#!/usr/bin/env node import { existsSync, readFileSync } from "node:fs"; const requiredFiles = [ "src/shared/lib/model.ts", "src/shared/lib/codexExecutionFeedback.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/execution-feedback/pages/ExecutionFeedback.tsx", "src/features/handoffs/pages/CodexHandoffs.tsx", "src/features/execution/pages/ExecutionCenter.tsx", "src/features/repo-builder/pages/RepoBuilder.tsx", "src/features/history/pages/ProjectHistory.tsx", "src/features/audit/pages/ProjectAuditCenter.tsx", "src/features/projects/pages/Workspace.tsx", "src/shared/lib/projectStartFlow.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 model = text["src/shared/lib/model.ts"] ?? ""; const helper = text["src/shared/lib/codexExecutionFeedback.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 page = text["src/features/execution-feedback/pages/ExecutionFeedback.tsx"] ?? ""; const handoffs = text["src/features/handoffs/pages/CodexHandoffs.tsx"] ?? ""; const execution = text["src/features/execution/pages/ExecutionCenter.tsx"] ?? ""; const repoBuilder = text["src/features/repo-builder/pages/RepoBuilder.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 startFlow = text["src/shared/lib/projectStartFlow.ts"] ?? ""; const pkg = text["package.json"] ?? ""; const mustContain = [ [model, "export interface CodexExecutionFeedback", "CodexExecutionFeedback type missing."], [model, "export interface CodexExecutionValidationResult", "CodexExecutionValidationResult type missing."], [model, "export interface CodexExecutionChangedFile", "CodexExecutionChangedFile type missing."], [model, "export type CodexExecutionOutcome", "CodexExecutionOutcome type missing."], [model, "export interface CodexExecutionFollowUp", "CodexExecutionFollowUp type missing."], [model, "export type CodexExecutionEvidenceStatus", "CodexExecutionEvidenceStatus type missing."], [model, "codexExecutionFeedback?: CodexExecutionFeedback[]", "Project model must persist execution feedback."], [safeData, "codexExecutionFeedback: asArray(project.codexExecutionFeedback)", "Runtime normalization must preserve execution feedback."], [helper, "parseCodexExecutionReport", "Feedback parser helper missing."], [helper, "extractChangedFilesFromReport", "Changed-file parser missing."], [helper, "extractValidationResultsFromReport", "Validation parser missing."], [helper, "compareFeedbackToHandoff", "Feedback-to-handoff comparison missing."], [helper, "deriveExecutionOutcome", "Outcome derivation missing."], [helper, "deriveResolvedGaps", "Resolved gap derivation missing."], [helper, "deriveNewGapCandidates", "New gap candidate derivation missing."], [helper, "deriveExecutionFollowUps", "Follow-up derivation missing."], [helper, "formatExecutionFeedbackMarkdown", "Feedback markdown formatter missing."], [helper, "scoreFeedbackCompleteness", "Feedback completeness scoring missing."], [helper, "not live git truth", "Helper must state feedback is not live git truth."], [realClient, "importCodexOutput", "Real client must expose backend Codex output import."], [hooks, "useProjectCodexTasksData", "Async hooks must expose backend Codex tasks for feedback import."], [hooks, "useProjectReviewQueueData", "Async hooks must expose Review Queue reload after feedback import."], [context, "saveCodexExecutionFeedback", "ProjectContext must save feedback."], [context, "updateCodexExecutionFeedbackStatus", "ProjectContext must update evidence status."], [context, "archiveCodexExecutionFeedback", "ProjectContext must archive feedback."], [context, "createFollowUpHandoffFromFeedback", "ProjectContext must create follow-up handoff from feedback."], [context, "executionFeedbackItems", "Project search must index execution feedback."], [routes, "/projects/:projectId/execution-feedback", "Execution Feedback route missing."], [navigation, "Execution Feedback", "Navigation must expose Execution Feedback."], [flowRail, 'id: "execution-feedback"', "Project Flow Rail must include feedback step."], [page, "Intake Codex report", "Execution Feedback page must show intake form."], [page, "Live backend Codex output import", "Execution Feedback page must expose the live backend Codex output import bridge."], [page, "Import to backend Review Queue", "Execution Feedback page must import backend Codex output into Review Queue."], [page, "useProjectCodexTasksData", "Execution Feedback page must read live backend Codex tasks."], [page, "realClient.runtimeV7.importCodexOutput", "Execution Feedback page must call the backend Codex output import endpoint."], [page, "Linked handoff", "Execution Feedback page must link handoffs."], [page, "Linked session pack", "Execution Feedback page must link session packs."], [page, "Session pack feedback boundary", "Execution Feedback page must show session pack feedback boundary."], [page, "Use this feedback template", "Execution Feedback page must insert session pack feedback template."], [page, "Download template", "Execution Feedback page must download session pack feedback template."], [page, "Paste Codex report generated from this session pack", "Execution Feedback page must label reports from session packs."], [page, "Parsed preview", "Execution Feedback page must show parsed preview."], [page, "Claimed changed files", "Execution Feedback page must show changed files."], [page, "Validation results", "Execution Feedback page must show validation results."], [page, "Accept evidence", "Execution Feedback page must accept evidence."], [page, "Create follow-up handoff", "Execution Feedback page must create follow-up handoffs."], [page, "not live git truth", "Execution Feedback page must show evidence boundary."], [page, "Return to Build Loop", "Execution Feedback page must link back to Build Loop."], [handoffs, "Add execution feedback", "Codex Handoffs page must link feedback intake."], [handoffs, "Create session pack", "Codex Handoffs page must create session packs."], [handoffs, "Feedback status", "Codex Handoffs page must show feedback status."], [execution, "Codex Execution Feedback", "Execution Center must show execution feedback."], [execution, "Codex Session Pack", "Execution Center must show session pack status."], [repoBuilder, "feedback records", "Repo Builder must show feedback status."], [history, 'kind: "executionFeedback"', "Project History must include feedback records."], [history, 'kind: "sessionPack"', "Project History must include session pack records."], [audit, "Execution feedback intake", "Audit Center must show feedback coverage."], [audit, "Codex session pack readiness", "Audit Center must show session pack coverage."], [workspace, "Execution Feedback", "Workspace must expose Execution Feedback."], [startFlow, "add-execution-feedback", "Next action must add execution feedback."], [startFlow, "review-execution-feedback", "Next action must review execution feedback."], [startFlow, "create-feedback-follow-up", "Next action must create feedback follow-up."], [pkg, "audit:execution-feedback", "package.json must expose audit:execution-feedback."], [pkg, "check-execution-feedback-readiness.mjs", "package.json must wire feedback readiness script."], ]; for (const [haystack, needle, message] of mustContain) { if (!haystack.includes(needle)) failures.push(message); } if (!pkg.includes("audit:execution-feedback") || !pkg.includes("audit:all")) { failures.push("audit:all must include the execution feedback readiness check."); } if (failures.length) { console.error("ProjectBrain execution feedback readiness: FAIL"); for (const failure of failures) console.error(`- ${failure}`); process.exit(1); } console.log("ProjectBrain execution feedback readiness: PASS");