Initial curated projectbrain source from 8a7b1e0651dbdab97d744cbd2e653ab3970ac6c5
This commit is contained in:
commit
5aa3e8d685
700 files changed
+132801
No files matched your search
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const root = process.cwd();
|
||||
const args = new Set(process.argv.slice(2));
|
||||
const asJson = args.has("--json");
|
||||
const read = (file) => fs.readFileSync(path.join(root, file), "utf8");
|
||||
const exists = (file) => fs.existsSync(path.join(root, file));
|
||||
const normalizePath = (file) => file.replaceAll(path.sep, "/");
|
||||
const walk = (dir, filter = () => true) => {
|
||||
const out = [];
|
||||
const base = path.join(root, dir);
|
||||
if (!fs.existsSync(base)) return out;
|
||||
const stack = [base];
|
||||
while (stack.length) {
|
||||
const current = stack.pop();
|
||||
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
||||
const full = path.join(current, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
if (!["node_modules", "dist", ".git", ".next", "coverage"].includes(entry.name)) stack.push(full);
|
||||
} else if (filter(full)) {
|
||||
out.push(normalizePath(path.relative(root, full)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return out.sort();
|
||||
};
|
||||
|
||||
const sourceFiles = walk("src", (file) => /\.(ts|tsx)$/.test(file));
|
||||
const backendFiles = walk("backend/src", (file) => /\.(ts|tsx)$/.test(file));
|
||||
const docs = walk("docs", (file) => file.endsWith(".md"));
|
||||
const routeText = exists("src/app/routes.tsx") ? read("src/app/routes.tsx") : "";
|
||||
const allTextFiles = [...sourceFiles, ...backendFiles].filter((file) => exists(file));
|
||||
const implementationFiles = allTextFiles.filter((file) => ![
|
||||
"src/shared/lib/mock-data.ts",
|
||||
"src/shared/lib/projectAudit.ts",
|
||||
].includes(file));
|
||||
const countPattern = (files, pattern) => files.reduce((count, file) => count + ((read(file).match(pattern) ?? []).length), 0);
|
||||
const filesWith = (files, pattern) => files.filter((file) => pattern.test(read(file)));
|
||||
const firstMatches = (files, pattern, limit = 20) => {
|
||||
const out = [];
|
||||
for (const file of files) {
|
||||
const lines = read(file).split(/\r?\n/);
|
||||
for (const [index, line] of lines.entries()) {
|
||||
if (pattern.test(line)) out.push({ file, line: index + 1, text: line.trim().slice(0, 180) });
|
||||
pattern.lastIndex = 0;
|
||||
if (out.length >= limit) return out;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
const rawConsoleMatches = firstMatches(implementationFiles, /console\./g, 50);
|
||||
const containedConsoleMatches = rawConsoleMatches.filter((match) => normalizePath(match.file) === "src/shared/lib/appLogger.ts");
|
||||
const uncontainedConsoleMatches = rawConsoleMatches.filter((match) => normalizePath(match.file) !== "src/shared/lib/appLogger.ts");
|
||||
const directMockDataFiles = filesWith(implementationFiles, /mockData/).filter((file) => file !== "src/shared/lib/projectbrainSelectors.ts");
|
||||
const anyCastMatches = firstMatches(implementationFiles, /\bas any\b/g, 50);
|
||||
const localhostMatches = firstMatches(implementationFiles, /localhost|127\.0\.0\.1/g, 50);
|
||||
const localStorageMatches = firstMatches(implementationFiles, /localStorage/g, 50);
|
||||
const auditCatalogText = exists("src/shared/lib/projectAudit.ts") ? read("src/shared/lib/projectAudit.ts") : "";
|
||||
const queuedAuditItems = (auditCatalogText.match(/queued_for_/g) ?? []).length;
|
||||
const v59AuditItems = (auditCatalogText.match(/implemented_in_v59/g) ?? []).length;
|
||||
|
||||
const report = {
|
||||
generatedAt: new Date().toISOString(),
|
||||
totals: {
|
||||
frontendFiles: sourceFiles.length,
|
||||
backendFiles: backendFiles.length,
|
||||
docs: docs.length,
|
||||
routes: (routeText.match(/<Route\s/g) ?? []).length,
|
||||
},
|
||||
signals: {
|
||||
todoFixme: countPattern(implementationFiles, /TODO|FIXME|HACK|XXX/g),
|
||||
directMockDataFiles: directMockDataFiles.length,
|
||||
consoleUsage: countPattern(implementationFiles, /console\./g),
|
||||
uncontainedConsoleUsage: uncontainedConsoleMatches.length,
|
||||
localStorageUsage: countPattern(implementationFiles, /localStorage/g),
|
||||
anyCasts: countPattern(implementationFiles, /\bas any\b/g),
|
||||
localhostReferences: countPattern(implementationFiles, /localhost|127\.0\.0\.1/g),
|
||||
queuedAuditItems,
|
||||
v59AuditItems,
|
||||
},
|
||||
details: {
|
||||
directMockDataFiles,
|
||||
uncontainedConsoleMatches,
|
||||
containedConsoleMatches,
|
||||
anyCastMatches,
|
||||
localStorageMatches,
|
||||
localhostMatches,
|
||||
},
|
||||
gates: {
|
||||
auditCenterRoute: routeText.includes("/audit"),
|
||||
auditCatalog: exists("src/shared/lib/projectAudit.ts"),
|
||||
auditDocs: exists("docs/PROJECTBRAIN_CSI_AUDIT_200_FINDINGS.md"),
|
||||
blueprintEngineRoute: routeText.includes("/blueprint"),
|
||||
v57Docs: exists("docs/STABILIZATION_PASS_V57_FULL_CSI_AUDIT.md"),
|
||||
v58Docs: exists("docs/STABILIZATION_PASS_V58_QUEUE_BURNDOWN.md"),
|
||||
v59Docs: exists("docs/STABILIZATION_PASS_V59_AUDIT_QUEUE_COMPLETION.md"),
|
||||
appLogger: exists("src/shared/lib/appLogger.ts"),
|
||||
},
|
||||
};
|
||||
|
||||
const pass =
|
||||
report.gates.auditCenterRoute &&
|
||||
report.gates.auditCatalog &&
|
||||
report.gates.auditDocs &&
|
||||
report.gates.appLogger &&
|
||||
report.totals.routes > 20 &&
|
||||
report.signals.uncontainedConsoleUsage === 0 &&
|
||||
report.signals.directMockDataFiles <= 1 &&
|
||||
report.signals.anyCasts <= 3 &&
|
||||
report.signals.localhostReferences === 0 &&
|
||||
report.signals.queuedAuditItems === 0 &&
|
||||
report.gates.v59Docs;
|
||||
|
||||
if (asJson) {
|
||||
console.log(JSON.stringify({ pass, ...report }, null, 2));
|
||||
} else {
|
||||
console.log(`ProjectBrain CSI audit: ${pass ? "PASS" : "WARN"}`);
|
||||
console.log(`Frontend files: ${report.totals.frontendFiles}`);
|
||||
console.log(`Backend files: ${report.totals.backendFiles}`);
|
||||
console.log(`Docs: ${report.totals.docs}`);
|
||||
console.log(`Routes: ${report.totals.routes}`);
|
||||
console.log(`TODO/FIXME/HACK/XXX markers: ${report.signals.todoFixme}`);
|
||||
console.log(`Implementation files with direct mockData usage: ${report.signals.directMockDataFiles}`);
|
||||
console.log(`console.* usages: ${report.signals.consoleUsage} (${report.signals.uncontainedConsoleUsage} uncontained)`);
|
||||
console.log(`localStorage usages: ${report.signals.localStorageUsage}`);
|
||||
console.log(`'as any' casts: ${report.signals.anyCasts}`);
|
||||
console.log(`localhost references: ${report.signals.localhostReferences}`);
|
||||
console.log(`queued audit items: ${report.signals.queuedAuditItems}`);
|
||||
console.log(`V59 audit completions: ${report.signals.v59AuditItems}`);
|
||||
console.log(`Audit Center route: ${report.gates.auditCenterRoute ? "yes" : "no"}`);
|
||||
console.log(`Audit catalog: ${report.gates.auditCatalog ? "yes" : "no"}`);
|
||||
console.log(`Audit docs: ${report.gates.auditDocs ? "yes" : "no"}`);
|
||||
console.log(`App logger: ${report.gates.appLogger ? "yes" : "no"}`);
|
||||
console.log(`V59 docs: ${report.gates.v59Docs ? "yes" : "no"}`);
|
||||
if (!pass) {
|
||||
if (directMockDataFiles.length) console.log(`Direct mockData files: ${directMockDataFiles.join(", ")}`);
|
||||
if (uncontainedConsoleMatches.length) console.log(`Uncontained console usage: ${uncontainedConsoleMatches.map((m) => `${m.file}:${m.line}`).join(", ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pass) process.exitCode = 1;
|
||||
Reference in new issue
Block a user