many changes
Traceability Validation / Check Requirement Traces (push) Failing after 1m18s
🏗️ Build and Test JellyTau / Build APK and Run Tests (push) Has been cancelled

This commit is contained in:
2026-02-14 00:09:47 +01:00
parent 6d1c618a3a
commit e3797f32ca
74 changed files with 6718 additions and 771 deletions
+115 -88
View File
@@ -10,9 +10,7 @@
import * as fs from "fs";
import * as path from "path";
// Use built-in Bun.glob
const glob = (pattern: string) => new Bun.Glob(pattern);
import { execSync } from "child_process";
interface TraceEntry {
file: string;
@@ -46,21 +44,54 @@ function extractRequirementIds(tracesString: string): string[] {
return matches.map((m) => `${m[1]}-${m[2]}`);
}
function getContext(content: string, lineNum: number): string {
const lines = content.split("\n");
const contextStart = Math.max(0, lineNum - 3);
const contextEnd = Math.min(lines.length, lineNum + 1);
const contextLines = lines.slice(contextStart, contextEnd);
return contextLines.join("\n").trim();
function getAllSourceFiles(): string[] {
const baseDir = "/home/dtourolle/Development/JellyTau";
const patterns = ["src", "src-tauri/src"];
const files: string[] = [];
function walkDir(dir: string) {
try {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
const relativePath = path.relative(baseDir, fullPath);
// Skip node_modules, target, build
if (
relativePath.includes("node_modules") ||
relativePath.includes("target") ||
relativePath.includes("build") ||
relativePath.includes(".git")
) {
continue;
}
if (entry.isDirectory()) {
walkDir(fullPath);
} else if (
entry.name.endsWith(".ts") ||
entry.name.endsWith(".svelte") ||
entry.name.endsWith(".rs")
) {
files.push(fullPath);
}
}
} catch (error) {
// Skip directories we can't read
}
}
for (const pattern of patterns) {
const dir = path.join(baseDir, pattern);
if (fs.existsSync(dir)) {
walkDir(dir);
}
}
return files;
}
async function extractTraces(): Promise<TracesData> {
const patterns = [
"src/**/*.ts",
"src/**/*.svelte",
"src-tauri/src/**/*.rs",
];
function extractTraces(): TracesData {
const requirementMap: RequirementMapping = {};
const byType: Record<string, Set<string>> = {
UR: new Set(),
@@ -70,89 +101,82 @@ async function extractTraces(): Promise<TracesData> {
};
let totalTraces = 0;
const processedFiles = new Set<string>();
const baseDir = "/home/dtourolle/Development/JellyTau";
for (const pattern of patterns) {
const globber = glob(pattern);
const files = [];
for await (const file of globber.scan({
cwd: "/home/dtourolle/Development/JellyTau",
})) {
files.push(file);
}
const files = getAllSourceFiles();
for (const file of files) {
if (processedFiles.has(file)) continue;
processedFiles.add(file);
for (const fullPath of files) {
try {
const content = fs.readFileSync(fullPath, "utf-8");
const lines = content.split("\n");
const relativePath = path.relative(baseDir, fullPath);
try {
const fullPath = `/home/dtourolle/Development/JellyTau/${file}`;
const content = fs.readFileSync(fullPath, "utf-8");
const lines = content.split("\n");
let match;
TRACES_PATTERN.lastIndex = 0;
let match;
TRACES_PATTERN.lastIndex = 0;
while ((match = TRACES_PATTERN.exec(content)) !== null) {
const tracesStr = match[1];
const reqIds = extractRequirementIds(tracesStr);
while ((match = TRACES_PATTERN.exec(content)) !== null) {
const tracesStr = match[1];
const reqIds = extractRequirementIds(tracesStr);
if (reqIds.length === 0) continue;
if (reqIds.length === 0) continue;
// Find line number
const beforeMatch = content.substring(0, match.index);
const lineNum = beforeMatch.split("\n").length - 1;
// Find line number
const beforeMatch = content.substring(0, match.index);
const lineNum = beforeMatch.split("\n").length - 1;
// Get context (function/class name if available)
let context = "Unknown";
for (let i = lineNum; i >= Math.max(0, lineNum - 10); i--) {
const line = lines[i];
if (
line.includes("function ") ||
line.includes("export const ") ||
line.includes("pub fn ") ||
line.includes("pub enum ") ||
line.includes("pub struct ") ||
line.includes("impl ") ||
line.includes("async function ") ||
line.includes("class ")
) {
context = line.trim();
break;
}
// Get context (function/class name if available)
let context = "Unknown";
for (let i = lineNum; i >= Math.max(0, lineNum - 10); i--) {
const line = lines[i];
if (
line.includes("function ") ||
line.includes("export const ") ||
line.includes("pub fn ") ||
line.includes("pub enum ") ||
line.includes("pub struct ") ||
line.includes("impl ") ||
line.includes("async function ") ||
line.includes("class ") ||
line.includes("export type ")
) {
context = line
.trim()
.replace(/^\s*\/\/\s*/, "")
.replace(/^\s*\/\*\*\s*/, "");
break;
}
const entry: TraceEntry = {
file: file.replace(/^\//, ""),
line: lineNum + 1,
context,
requirements: reqIds,
};
for (const reqId of reqIds) {
if (!requirementMap[reqId]) {
requirementMap[reqId] = [];
}
requirementMap[reqId].push(entry);
// Track by type
const type = reqId.substring(0, 2);
if (byType[type]) {
byType[type].add(reqId);
}
}
totalTraces++;
}
} catch (error) {
console.error(`Error processing ${file}:`, error);
const entry: TraceEntry = {
file: relativePath,
line: lineNum + 1,
context,
requirements: reqIds,
};
for (const reqId of reqIds) {
if (!requirementMap[reqId]) {
requirementMap[reqId] = [];
}
requirementMap[reqId].push(entry);
// Track by type
const type = reqId.substring(0, 2);
if (byType[type]) {
byType[type].add(reqId);
}
}
totalTraces++;
}
} catch (error) {
// Skip files we can't read
}
}
return {
timestamp: new Date().toISOString(),
totalFiles: processedFiles.size,
totalFiles: files.length,
totalTraces,
requirements: requirementMap,
byType: {
@@ -224,7 +248,8 @@ ${data.byType.JA.join(", ")}
for (const entry of entries) {
md += `- **File:** [\`${entry.file}\`](${entry.file}#L${entry.line})\n`;
md += ` - **Line:** ${entry.line}\n`;
md += ` - **Context:** \`${entry.context.substring(0, 80)}...\`\n`;
const contextPreview = entry.context.substring(0, 70);
md += ` - **Context:** \`${contextPreview}${entry.context.length > 70 ? "..." : ""}\`\n`;
}
md += "\n";
}
@@ -242,8 +267,8 @@ const format = args.includes("--format")
? args[args.indexOf("--format") + 1]
: "markdown";
console.error("Extracting TRACES from codebase...");
const data = await extractTraces();
console.error("🔍 Extracting TRACES from codebase...");
const data = extractTraces();
if (format === "json") {
console.log(generateJson(data));
@@ -251,4 +276,6 @@ if (format === "json") {
console.log(generateMarkdown(data));
}
console.error(`\n✅ Complete! Found ${data.totalTraces} TRACES across ${data.totalFiles} files`);
console.error(
`\n✅ Complete! Found ${data.totalTraces} TRACES across ${data.totalFiles} files`
);