118 lines
7.1 KiB
JavaScript
118 lines
7.1 KiB
JavaScript
#!/usr/bin/env node
|
|
import { existsSync, readFileSync } from "node:fs";
|
|
|
|
const requiredFiles = [
|
|
"src/shared/lib/buildLoop.ts",
|
|
"src/features/build-loop/pages/BuildLoopDashboard.tsx",
|
|
"src/app/routes.tsx",
|
|
"src/shared/lib/navigation.tsx",
|
|
"src/shared/components/ProjectFlowRail.tsx",
|
|
"src/features/projects/pages/Workspace.tsx",
|
|
"src/features/projects/pages/Projects.tsx",
|
|
"src/features/execution/pages/ExecutionCenter.tsx",
|
|
"src/features/repo-builder/pages/RepoBuilder.tsx",
|
|
"src/features/handoffs/pages/CodexHandoffs.tsx",
|
|
"src/features/execution-feedback/pages/ExecutionFeedback.tsx",
|
|
"src/features/audit/pages/ProjectAuditCenter.tsx",
|
|
"src/shared/lib/projectOperatingStep.ts",
|
|
"src/shared/lib/projectSearch.ts",
|
|
"src/shared/lib/routeRegistry.ts",
|
|
"package.json",
|
|
];
|
|
|
|
const failures = [];
|
|
for (const file of requiredFiles) {
|
|
if (!existsSync(file)) failures.push(`Missing required file: ${file}`);
|
|
}
|
|
|
|
const read = (file) => readFileSync(file, "utf8");
|
|
const text = Object.fromEntries(requiredFiles.filter(existsSync).map((file) => [file, read(file)]));
|
|
|
|
const helper = text["src/shared/lib/buildLoop.ts"] ?? "";
|
|
const page = text["src/features/build-loop/pages/BuildLoopDashboard.tsx"] ?? "";
|
|
const routes = text["src/app/routes.tsx"] ?? "";
|
|
const navigation = text["src/shared/lib/navigation.tsx"] ?? "";
|
|
const flowRail = text["src/shared/components/ProjectFlowRail.tsx"] ?? "";
|
|
const workspace = text["src/features/projects/pages/Workspace.tsx"] ?? "";
|
|
const projects = text["src/features/projects/pages/Projects.tsx"] ?? "";
|
|
const execution = text["src/features/execution/pages/ExecutionCenter.tsx"] ?? "";
|
|
const repoBuilder = text["src/features/repo-builder/pages/RepoBuilder.tsx"] ?? "";
|
|
const handoffs = text["src/features/handoffs/pages/CodexHandoffs.tsx"] ?? "";
|
|
const feedback = text["src/features/execution-feedback/pages/ExecutionFeedback.tsx"] ?? "";
|
|
const audit = text["src/features/audit/pages/ProjectAuditCenter.tsx"] ?? "";
|
|
const operatingStep = text["src/shared/lib/projectOperatingStep.ts"] ?? "";
|
|
const projectSearch = text["src/shared/lib/projectSearch.ts"] ?? "";
|
|
const routeRegistry = text["src/shared/lib/routeRegistry.ts"] ?? "";
|
|
const pkg = text["package.json"] ?? "";
|
|
|
|
const mustContain = [
|
|
[helper, "getBuildLoopStatus", "buildLoop helper must expose getBuildLoopStatus."],
|
|
[helper, "getCurrentBuildLoopPhase", "buildLoop helper must derive current phase."],
|
|
[helper, "getRecommendedBuildLoopAction", "buildLoop helper must recommend next action."],
|
|
[helper, "getBuildLoopRisks", "buildLoop helper must derive risks."],
|
|
[helper, "getBuildLoopValidationSummary", "buildLoop helper must summarize validation."],
|
|
[helper, "getBuildLoopSkillCoverage", "buildLoop helper must summarize skill coverage."],
|
|
[helper, "getBuildLoopProgress", "buildLoop helper must calculate progress."],
|
|
[helper, "formatBuildLoopMarkdown", "buildLoop helper must export markdown."],
|
|
[helper, "repositoryIntakes", "buildLoop helper must use repository intakes/gaps."],
|
|
[helper, "codexHandoffs", "buildLoop helper must use Codex handoffs."],
|
|
[helper, "handoffReviews", "buildLoop helper must use handoff reviews."],
|
|
[helper, "codexSessionPacks", "buildLoop helper must use session packs."],
|
|
[helper, "Create Codex session pack", "buildLoop helper must recommend creating session packs."],
|
|
[helper, "Run session and add feedback", "buildLoop helper must recommend feedback after session packs."],
|
|
[helper, "latestSessionPack", "buildLoop helper must expose latest session pack."],
|
|
[helper, "codexExecutionFeedback", "buildLoop helper must use execution feedback."],
|
|
[helper, "getActiveProjectSkills", "buildLoop helper must use Codex skills."],
|
|
[routes, "/projects/:projectId/build-loop", "Build Loop route missing."],
|
|
[routes, "BuildLoopDashboard", "Build Loop page must be imported in routes."],
|
|
[navigation, "getPrimaryPathNavigationItems", "Primary navigation must expose the workspace that owns the Build Loop entry."],
|
|
[routeRegistry, 'key: "workspace"', "Canonical route registry must expose the workspace that owns the Build Loop entry."],
|
|
[flowRail, 'id: "build-loop"', "Project Flow Rail must include Build Loop."],
|
|
[navigation, '`${base}/build-loop`', "Technical navigation must expose Build Loop."],
|
|
[workspace, "Technische details", "Workspace must progressively disclose technical execution."],
|
|
[page, "getBuildLoopStatus", "Technical Build Loop must use the shared helper."],
|
|
[projects, "resolveProjectListOperatingState", "Projects must combine daily guidance with live Auto state."],
|
|
[projects, "getProjectOperatingStep", "Projects cards must derive the central next safe action."],
|
|
[projects, "operatingState.label", "Projects must render the central operating-state label."],
|
|
[projects, "operatingState.description", "Projects must render the central operating-state explanation."],
|
|
[execution, "View build loop", "Execution Center must link to Build Loop."],
|
|
[execution, "getBuildLoopStatus", "Execution Center must use Build Loop recommended action."],
|
|
[repoBuilder, "Naar de buildloop", "Repo Builder must link back to the Build Loop from its task-first header."],
|
|
[handoffs, "View in Build Loop", "Codex Handoffs must link to Build Loop."],
|
|
[feedback, "Linked session pack", "Execution Feedback must link session packs."],
|
|
[feedback, "Return to Build Loop", "Execution Feedback must link back to Build Loop."],
|
|
[audit, "Build Loop cockpit", "Audit Center must show Build Loop coverage."],
|
|
[audit, "Codex session pack readiness", "Audit Center must show session pack coverage."],
|
|
[projectSearch, 'type: "buildLoop"', "Search index must include Build Loop result."],
|
|
[page, "Technische uitvoeringsstatus", "Build Loop page must show status summary."],
|
|
[page, "Interne fasen", "Build Loop page must show timeline."],
|
|
[page, "Geslaagde controles", "Build Loop page must show safety and validation."],
|
|
[page, "Repositorytoestand", "Build Loop page must show repo health."],
|
|
[page, "uitvoeringsprofielen", "Build Loop page must show skill coverage."],
|
|
[helper, "latestSessionPack", "Build Loop data must retain session pack readiness."],
|
|
[helper, "codexExecutionFeedback", "Build Loop data must retain execution feedback."],
|
|
[page, "Recente technische gebeurtenissen", "Build Loop page must show recent events."],
|
|
[helper, "formatBuildLoopMarkdown", "Build Loop must retain its export formatter."],
|
|
[pkg, "audit:build-loop", "package.json must expose audit:build-loop."],
|
|
[pkg, "check-build-loop-readiness.mjs", "package.json must wire Build Loop readiness script."],
|
|
];
|
|
|
|
for (const [haystack, needle, message] of mustContain) {
|
|
if (!haystack.includes(needle)) failures.push(message);
|
|
}
|
|
|
|
const scripts = JSON.parse(pkg || "{}").scripts ?? {};
|
|
const experienceAudit = scripts["audit:experience"] ?? "";
|
|
const allAudit = scripts["audit:all"] ?? "";
|
|
if (!experienceAudit.includes("audit:build-loop") || !allAudit.includes("audit:experience")) {
|
|
failures.push("audit:all must include the experience gate with Build Loop readiness.");
|
|
}
|
|
|
|
if (failures.length) {
|
|
console.error("ProjectBrain build loop readiness: FAIL");
|
|
for (const failure of failures) console.error(`- ${failure}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("ProjectBrain build loop readiness: PASS");
|