129 lines
8.1 KiB
JavaScript
129 lines
8.1 KiB
JavaScript
#!/usr/bin/env node
|
|
import { existsSync, readFileSync } from "node:fs";
|
|
|
|
const requiredFiles = [
|
|
"src/app/routes.tsx",
|
|
"src/shared/lib/navigation.tsx",
|
|
"src/shared/components/ProjectFlowRail.tsx",
|
|
"src/shared/lib/projectStartFlow.ts",
|
|
"src/features/projects/pages/Projects.tsx",
|
|
"src/features/projects/pages/Workspace.tsx",
|
|
"src/features/build-loop/pages/BuildLoopDashboard.tsx",
|
|
"src/features/repo-builder/pages/RepoBuilder.tsx",
|
|
"src/features/handoffs/pages/CodexHandoffs.tsx",
|
|
"src/features/session-packs/pages/SessionPacks.tsx",
|
|
"src/features/execution-feedback/pages/ExecutionFeedback.tsx",
|
|
"src/shared/lib/safeData.ts",
|
|
"src/shared/lib/codexSessionPackExport.ts",
|
|
"src/shared/lib/downloads.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 routes = text["src/app/routes.tsx"] ?? "";
|
|
const navigation = text["src/shared/lib/navigation.tsx"] ?? "";
|
|
const flowRail = text["src/shared/components/ProjectFlowRail.tsx"] ?? "";
|
|
const startFlow = text["src/shared/lib/projectStartFlow.ts"] ?? "";
|
|
const projects = text["src/features/projects/pages/Projects.tsx"] ?? "";
|
|
const workspace = text["src/features/projects/pages/Workspace.tsx"] ?? "";
|
|
const buildLoop = text["src/features/build-loop/pages/BuildLoopDashboard.tsx"] ?? "";
|
|
const repoBuilder = text["src/features/repo-builder/pages/RepoBuilder.tsx"] ?? "";
|
|
const handoffs = text["src/features/handoffs/pages/CodexHandoffs.tsx"] ?? "";
|
|
const sessionPacks = text["src/features/session-packs/pages/SessionPacks.tsx"] ?? "";
|
|
const feedback = text["src/features/execution-feedback/pages/ExecutionFeedback.tsx"] ?? "";
|
|
const safeData = text["src/shared/lib/safeData.ts"] ?? "";
|
|
const exportHelper = text["src/shared/lib/codexSessionPackExport.ts"] ?? "";
|
|
const downloads = text["src/shared/lib/downloads.ts"] ?? "";
|
|
const pkg = text["package.json"] ?? "";
|
|
|
|
const mustContain = [
|
|
[routes, "/start", "Unified Start route must be registered."],
|
|
[routes, "/projects/new", "Projects/new compatibility route must remain registered."],
|
|
[routes, "/projects/:projectId/workspace", "Workspace route missing."],
|
|
[routes, "/projects/:projectId/source-library", "Source Library route missing."],
|
|
[routes, "/projects/:projectId/skills", "Skill Library route missing."],
|
|
[routes, "/projects/:projectId/repo-builder", "Repo Builder route missing."],
|
|
[routes, "/projects/:projectId/handoffs", "Codex Handoffs route missing."],
|
|
[routes, "/projects/:projectId/session-packs", "Session Packs route missing."],
|
|
[routes, "/projects/:projectId/execution-feedback", "Execution Feedback route missing."],
|
|
[routes, "/projects/:projectId/build-loop", "Build Loop route missing."],
|
|
[routes, "/projects/:projectId/execution", "Execution Center route missing."],
|
|
[routes, "/projects/:projectId/history", "History route missing."],
|
|
[routes, "/projects/:projectId/audit", "Audit Center route missing."],
|
|
[routes, "/projects/:projectId/prompts", "Prompt Builder route missing."],
|
|
[navigation, "Build Loop", "Navigation must expose Build Loop."],
|
|
[navigation, "Repo Builder", "Navigation must expose Repo Builder."],
|
|
[navigation, "Codex Handoffs", "Navigation must expose Codex Handoffs."],
|
|
[navigation, "Session Packs", "Navigation must expose Session Packs."],
|
|
[navigation, "Execution Feedback", "Navigation must expose Execution Feedback."],
|
|
[flowRail, 'id: "source-library"', "Flow Rail must include Source Library."],
|
|
[flowRail, 'id: "skills"', "Flow Rail must include Skills."],
|
|
[flowRail, 'id: "repo-builder"', "Flow Rail must include Repo Builder."],
|
|
[flowRail, 'id: "handoffs"', "Flow Rail must include Handoffs."],
|
|
[flowRail, 'id: "session-packs"', "Flow Rail must include Session Packs."],
|
|
[flowRail, 'id: "execution-feedback"', "Flow Rail must include Execution Feedback."],
|
|
[flowRail, 'id: "build-loop"', "Flow Rail must include Build Loop."],
|
|
[startFlow, "/start?path=no-idea", "Start flow must support no-idea path."],
|
|
[startFlow, "/start?path=rough-idea", "Start flow must support rough-idea path."],
|
|
[startFlow, "/start?path=source-material", "Start flow must support source-material path."],
|
|
[startFlow, "/start?path=existing-repo", "Start flow must support existing-repo path."],
|
|
[startFlow, "/projects/new?source=unified-start", "Direct project setup must pass through unified project setup route."],
|
|
[projects, "/start", "Projects page must link into unified Start."],
|
|
[projects, "getProjectNextAction", "Projects page must use shared next-action helper."],
|
|
[workspace, "Build Loop", "Workspace must expose Build Loop."],
|
|
[workspace, "Session Packs", "Workspace must expose Session Packs."],
|
|
[buildLoop, "Open linked module", "Build Loop page must expose linked module navigation."],
|
|
[buildLoop, "Open Session Packs", "Build Loop page must link to Session Packs."],
|
|
[repoBuilder, "Imported repository evidence is not live filesystem truth", "Repo Builder must label imported evidence boundary."],
|
|
[handoffs, "ProjectBrain-derived impact simulation, not a live git diff", "Codex Handoffs must label simulated review boundary."],
|
|
[handoffs, "controlled input for a Codex build session", "Codex Handoffs must explain session pack boundary."],
|
|
[sessionPacks, "Download instructions/scripts ZIP", "Session Packs must expose clear instructions/scripts ZIP export."],
|
|
[sessionPacks, "Export session pack files", "Session Packs must keep individual-file export fallback."],
|
|
[sessionPacks, "ZIP export contains only", "Session Packs must explain ZIP contents."],
|
|
[feedback, "not live git truth or live filesystem truth", "Execution Feedback must label feedback truth boundary."],
|
|
[safeData, "repositoryIntakes: asArray(project.repositoryIntakes)", "safeData must normalize repository intakes."],
|
|
[safeData, "codexHandoffs: asArray(project.codexHandoffs)", "safeData must normalize Codex handoffs."],
|
|
[safeData, "handoffReviews: asArray(project.handoffReviews)", "safeData must normalize handoff reviews."],
|
|
[safeData, "codexExecutionFeedback: asArray(project.codexExecutionFeedback)", "safeData must normalize execution feedback."],
|
|
[safeData, "codexSessionPacks: asArray(project.codexSessionPacks)", "safeData must normalize session packs."],
|
|
[safeData, "repoStateSnapshots: asArray(project.repoStateSnapshots)", "safeData must normalize repo state snapshots."],
|
|
[safeData, "repoDeliveryPackages: asArray(project.repoDeliveryPackages)", "safeData must normalize delivery packages."],
|
|
[safeData, "repoWorkPlans: asArray(project.repoWorkPlans)", "safeData must normalize work plans."],
|
|
[safeData, "codexSkills: asArray(project.codexSkills)", "safeData must normalize project skill selections."],
|
|
[safeData, "hiddenHistoryEntryIds: asArray(project.hiddenHistoryEntryIds)", "safeData must normalize hidden history ids."],
|
|
[exportHelper, "zipExport: true", "Session pack manifest must state ZIP export availability."],
|
|
[exportHelper, "downloadCodexSessionPackZip", "Session pack helper must expose ZIP download."],
|
|
[exportHelper, "bundle-manifest.json", "Session pack bundle must include manifest."],
|
|
[downloads, "URL.revokeObjectURL", "Download helper must revoke Blob URLs."],
|
|
[pkg, "audit:release-consolidation", "package.json must expose release consolidation audit."],
|
|
[pkg, "check-build-loop-release-consolidation.mjs", "package.json must wire release consolidation audit."],
|
|
];
|
|
|
|
for (const [haystack, needle, message] of mustContain) {
|
|
if (!haystack.includes(needle)) failures.push(message);
|
|
}
|
|
|
|
if (sessionPacks.includes("Download Bundle / ZIP")) {
|
|
failures.push("Session Packs must not imply that a real ZIP is produced.");
|
|
}
|
|
|
|
const auditAll = JSON.parse(pkg || "{}")?.scripts?.["audit:all"] ?? "";
|
|
if (!auditAll.includes("audit:release-consolidation")) {
|
|
failures.push("audit:all must include the release consolidation audit.");
|
|
}
|
|
|
|
if (failures.length) {
|
|
console.error("ProjectBrain release consolidation readiness: FAIL");
|
|
for (const failure of failures) console.error(`- ${failure}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("ProjectBrain release consolidation readiness: PASS");
|