#!/usr/bin/env node import { existsSync, readFileSync } from "node:fs"; const requiredFiles = [ "src/shared/lib/buildLoopWalkthrough.ts", "src/shared/lib/buildLoop.ts", "src/features/build-loop/pages/BuildLoopDashboard.tsx", "src/features/projects/pages/Projects.tsx", "src/features/projects/pages/Workspace.tsx", "src/features/repo-builder/pages/RepoBuilder.tsx", "src/features/handoffs/pages/CodexHandoffs.tsx", "src/features/execution-feedback/pages/ExecutionFeedback.tsx", "src/features/skills/pages/SkillLibrary.tsx", "src/features/source-library/pages/SourceLibrary.tsx", "src/features/operations/pages/ReviewQueue.tsx", "src/features/execution/pages/ExecutionCenter.tsx", "src/features/history/pages/ProjectHistory.tsx", "src/features/audit/pages/ProjectAuditCenter.tsx", "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/buildLoopWalkthrough.ts"] ?? ""; const buildLoop = text["src/features/build-loop/pages/BuildLoopDashboard.tsx"] ?? ""; const projects = text["src/features/projects/pages/Projects.tsx"] ?? ""; const workspace = text["src/features/projects/pages/Workspace.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 skills = text["src/features/skills/pages/SkillLibrary.tsx"] ?? ""; const sourceLibrary = text["src/features/source-library/pages/SourceLibrary.tsx"] ?? ""; const reviewQueue = text["src/features/operations/pages/ReviewQueue.tsx"] ?? ""; const execution = text["src/features/execution/pages/ExecutionCenter.tsx"] ?? ""; const history = text["src/features/history/pages/ProjectHistory.tsx"] ?? ""; const audit = text["src/features/audit/pages/ProjectAuditCenter.tsx"] ?? ""; const pkg = text["package.json"] ?? ""; const requiredSteps = [ "start-project", "add-sources-or-repo-intake", "review-context", "configure-skills", "shape-repo", "create-delivery-package", "create-codex-handoff", "review-impact", "create-session-pack", "execute-in-codex", "add-execution-feedback", "continue-next-loop", ]; const mustContain = [ [helper, "getFirstTimeBuildLoopSteps", "Walkthrough helper must expose getFirstTimeBuildLoopSteps."], [helper, "getBuildLoopEmptyState", "Walkthrough helper must expose getBuildLoopEmptyState."], [helper, "getBuildLoopModuleExplanation", "Walkthrough helper must expose module explanations."], [helper, "getBuildLoopStepStatus", "Walkthrough helper must expose step status."], [helper, "getNextBeginnerAction", "Walkthrough helper must expose next beginner action."], [helper, "formatBuildLoopWalkthroughMarkdown", "Walkthrough helper must export markdown."], [buildLoop, "Guided walkthrough", "Build Loop page must show guided walkthrough."], [buildLoop, "Copy walkthrough", "Build Loop page must support walkthrough export."], [buildLoop, "getFirstTimeBuildLoopSteps", "Build Loop page must use the walkthrough helper."], [buildLoop, "Use this when:", "Build Loop page must explain the active module."], [workspace, "getNextBeginnerAction", "Workspace must use beginner next action."], [projects, "Existing project memories", "Projects page must put existing project memories first."], [projects, "Start another project through one flow", "Projects page must still route to unified Start for new projects."], [projects, "Continue build loop", "Project cards must use harmonized build-loop CTA."], [repoBuilder, "Repository intake", "Repo Builder must show repository intake subflow."], [repoBuilder, "Create delivery package", "Repo Builder must show delivery-package step."], [repoBuilder, "Continue build loop", "Repo Builder must link back to the loop."], [handoffs, "Create handoff", "Handoffs must show create/review/run/feedback mini-flow."], [handoffs, "Create session pack", "Handoffs must include create-session-pack action."], [handoffs, "Run in Codex", "Handoffs must include run-in-Codex stage."], [handoffs, "Stage:", "Handoff cards must show stage."], [feedback, "user-provided execution evidence", "Execution Feedback must clarify evidence boundary."], [feedback, "Linked session pack", "Execution Feedback must link session packs."], [feedback, "Use this feedback template", "Execution Feedback must use session pack feedback templates."], [feedback, "Create follow-up handoff", "Execution Feedback must keep follow-up handoff CTA."], [skills, "No active skills yet", "Skill Library must explain empty active skills state."], [sourceLibrary, "Use this when:", "Source Library must have module explanation."], [reviewQueue, "Use this when:", "Review Queue must have module explanation."], [execution, "Use this when:", "Execution Center must have module explanation."], [history, "Use this when:", "History must have module explanation."], [audit, "Use this when:", "Audit Center must have module explanation."], [audit, "Codex session pack readiness", "Audit Center must show session pack readiness."], [pkg, "audit:build-loop-walkthrough", "package.json must expose audit:build-loop-walkthrough."], [pkg, "check-build-loop-walkthrough-readiness.mjs", "package.json must wire the walkthrough readiness script."], ]; for (const step of requiredSteps) { if (!helper.includes(step)) failures.push(`Walkthrough helper missing step: ${step}`); } for (const [haystack, needle, message] of mustContain) { if (!haystack.includes(needle)) failures.push(message); } if (!pkg.includes("audit:build-loop-walkthrough") || !pkg.includes("audit:all")) { failures.push("audit:all must include the build-loop walkthrough readiness check."); } if (failures.length) { console.error("ProjectBrain build loop walkthrough readiness: FAIL"); for (const failure of failures) console.error(`- ${failure}`); process.exit(1); } console.log("ProjectBrain build loop walkthrough readiness: PASS");