#!/usr/bin/env node import { existsSync, readFileSync } from "node:fs"; const requiredFiles = [ "src/shared/lib/model.ts", "src/shared/lib/codexHandoff.ts", "src/shared/lib/codexSessionPack.ts", "src/shared/lib/safeData.ts", "src/shared/api/realClient.ts", "src/shared/hooks/useProjectData.ts", "src/shared/contexts/ProjectContext.tsx", "src/app/routes.tsx", "src/shared/lib/navigation.tsx", "src/shared/components/ProjectFlowRail.tsx", "src/features/handoffs/pages/CodexHandoffs.tsx", "src/features/execution-feedback/pages/ExecutionFeedback.tsx", "src/features/repo-builder/pages/RepoBuilder.tsx", "src/features/execution/pages/ExecutionCenter.tsx", "src/features/prompts/pages/PromptGenerator.tsx", "src/features/history/pages/ProjectHistory.tsx", "src/features/audit/pages/ProjectAuditCenter.tsx", "src/features/projects/pages/Workspace.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 model = text["src/shared/lib/model.ts"] ?? ""; const helper = text["src/shared/lib/codexHandoff.ts"] ?? ""; const sessionPackHelper = text["src/shared/lib/codexSessionPack.ts"] ?? ""; const safeData = text["src/shared/lib/safeData.ts"] ?? ""; const realClient = text["src/shared/api/realClient.ts"] ?? ""; const hooks = text["src/shared/hooks/useProjectData.ts"] ?? ""; const context = text["src/shared/contexts/ProjectContext.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 handoffPage = text["src/features/handoffs/pages/CodexHandoffs.tsx"] ?? ""; const feedbackPage = text["src/features/execution-feedback/pages/ExecutionFeedback.tsx"] ?? ""; const repoBuilder = text["src/features/repo-builder/pages/RepoBuilder.tsx"] ?? ""; const execution = text["src/features/execution/pages/ExecutionCenter.tsx"] ?? ""; const promptBuilder = text["src/features/prompts/pages/PromptGenerator.tsx"] ?? ""; const history = text["src/features/history/pages/ProjectHistory.tsx"] ?? ""; const audit = text["src/features/audit/pages/ProjectAuditCenter.tsx"] ?? ""; const workspace = text["src/features/projects/pages/Workspace.tsx"] ?? ""; const pkg = text["package.json"] ?? ""; const mustContain = [ [model, "export interface CodexHandoff", "CodexHandoff model missing."], [model, "export interface CodexHandoffValidationItem", "CodexHandoffValidationItem model missing."], [model, "export interface CodexHandoffRisk", "CodexHandoffRisk model missing."], [model, "export interface CodexHandoffScope", "CodexHandoffScope model missing."], [model, "export interface CodexHandoffQualityScore", "CodexHandoffQualityScore model missing."], [model, "codexHandoffs?: CodexHandoff[]", "Project model must persist Codex handoffs."], [model, "codexSessionPacks?: CodexSessionPack[]", "Project model must persist Codex session packs."], [safeData, "codexHandoffs: asArray(project.codexHandoffs)", "Runtime normalization must preserve Codex handoffs."], [realClient, "createHandoffBundle", "Real client must expose backend handoff bundle creation."], [realClient, "createCodexTaskFromHandoff", "Real client must expose backend Codex task creation from handoff bundles."], [hooks, "useProjectHandoffBundlesData", "Async hooks must expose backend handoff bundles."], [hooks, "useProjectCodexTasksData", "Async hooks must expose backend Codex tasks."], [helper, "generateCodexHandoffFromDeliveryPackage", "Handoff helper must generate from delivery packages."], [helper, "generateCodexHandoffFromRepoGap", "Handoff helper must generate from repository gaps."], [helper, "generateCodexHandoffFromWorkPlan", "Handoff helper must generate from work plans."], [helper, "generateCodexHandoffFromRepoState", "Handoff helper must generate from repo state snapshots."], [helper, "buildAllowedFiles", "Handoff helper must build allowed files."], [helper, "buildForbiddenChanges", "Handoff helper must build forbidden changes."], [helper, "buildValidationMatrix", "Handoff helper must build validation matrix."], [helper, "buildRollbackPlan", "Handoff helper must build rollback plan."], [helper, "buildDoneCriteria", "Handoff helper must build done criteria."], [helper, "formatCodexHandoffMarkdown", "Handoff helper must format markdown."], [helper, "scoreCodexHandoffQuality", "Handoff helper must score quality."], [helper, "getHandoffWarnings", "Handoff helper must produce warnings."], [helper, "promptInstructions", "Skill prompt instructions must be included."], [helper, "validationCommands", "Skill validation commands must be included."], [helper, "qualityChecklist", "Skill quality checklist must be included."], [helper, "riskNotes", "Skill risk notes must be included."], [helper, "This is derived from imported repository evidence, not live filesystem truth", "Repo-gap handoffs must label imported evidence boundary."], [sessionPackHelper, "generateCodexSessionPack", "Session pack helper must generate packs from handoffs."], [routes, "/projects/:projectId/handoffs", "Codex Handoffs route missing."], [routes, "CodexHandoffs", "Codex Handoffs page must be imported in routes."], [navigation, "Codex Handoffs", "Navigation must expose Codex Handoffs."], [flowRail, 'id: "handoffs"', "Project Flow Rail must include Handoffs."], [handoffPage, "Codex Handoffs", "Handoff page must exist."], [handoffPage, "Live backend handoff path", "Handoff page must expose the live backend handoff bridge."], [handoffPage, "Create live handoff", "Handoff page must support creating backend-persisted handoff bundles."], [handoffPage, "Create Codex task", "Handoff page must support creating backend-persisted Codex tasks from handoff bundles."], [handoffPage, "useProjectHandoffBundlesData", "Handoff page must read backend handoff bundles in real mode."], [handoffPage, "quality", "Handoff page must show quality score."], [handoffPage, "Allowed files", "Handoff page must show allowed files."], [handoffPage, "Forbidden changes", "Handoff page must show forbidden changes."], [handoffPage, "Validation matrix", "Handoff page must show validation matrix."], [handoffPage, "Rollback", "Handoff page must show rollback."], [handoffPage, "Generated prompt", "Handoff page must show generated prompt."], [handoffPage, "Copy next Codex prompt", "Handoff page must support copying prompts."], [handoffPage, "Generate impact review", "Handoff page must support impact review generation."], [handoffPage, "ProjectBrain-derived impact simulation, not a live git diff", "Handoff page must distinguish simulated review from live git diff."], [handoffPage, "Add execution feedback", "Handoff page must link to execution feedback intake."], [handoffPage, "Create session pack", "Handoff page must create session packs."], [handoffPage, "Open session pack", "Handoff page must open session packs."], [handoffPage, "Copy session pack", "Handoff page must copy session packs."], [handoffPage, "Download session pack", "Handoff page must download session packs."], [handoffPage, "Download ZIP", "Handoff page must download session pack ZIP."], [handoffPage, "Export session pack files", "Handoff page must export session pack files."], [handoffPage, "controlled input for a Codex build session", "Handoff page must explain session pack purpose."], [handoffPage, "View in Build Loop", "Handoff page must link to Build Loop."], [feedbackPage, "Execution Feedback", "Execution feedback page must exist for post-handoff evidence intake."], [repoBuilder, "Create Codex handoff", "Repo Builder must generate handoffs."], [repoBuilder, "Create handoff from work plan", "Repo Builder must generate handoffs from work plans."], [repoBuilder, "Create handoff from repo state", "Repo Builder must generate handoffs from repo state."], [execution, "Codex Handoff Quality Engine", "Execution Center must show handoff engine."], [execution, "Copy next Codex prompt", "Execution Center must copy next prompt."], [execution, "Open Codex Handoff", "Execution Center must link to Handoffs."], [promptBuilder, "Codex Handoff source", "Prompt Builder must expose handoff source."], [promptBuilder, "Use handoff promptText", "Prompt Builder must use handoff promptText."], [context, "generateCodexHandoff", "ProjectContext must expose generateCodexHandoff."], [context, "generateCodexSessionPack", "ProjectContext must expose generateCodexSessionPack."], [context, "archiveCodexHandoff", "ProjectContext must expose archiveCodexHandoff."], [context, "codexHandoffItems", "Project search must index Codex handoffs."], [history, 'kind: "handoff"', "Project History must include handoff records."], [audit, "Codex handoff quality", "Audit Center must show handoff quality."], [workspace, "codexHandoffCount", "Workspace must count Codex handoffs."], [workspace, "Codex Handoffs", "Workspace must expose Codex Handoffs."], [pkg, "audit:handoffs", "package.json must expose audit:handoffs."], [pkg, "check-codex-handoff-readiness.mjs", "package.json must wire handoff readiness script."], ]; for (const [haystack, needle, message] of mustContain) { if (!haystack.includes(needle)) failures.push(message); } if (!pkg.includes("audit:handoffs") || !pkg.includes("audit:all")) { failures.push("audit:all must include the Codex handoff readiness check."); } if (failures.length) { console.error("ProjectBrain Codex handoff readiness: FAIL"); for (const failure of failures) console.error(`- ${failure}`); process.exit(1); } console.log("ProjectBrain Codex handoff readiness: PASS");