Files
projectbrain-Public/scripts/check-repository-intake-readiness.mjs

111 lines
7.3 KiB
JavaScript

#!/usr/bin/env node
import { existsSync, readFileSync } from "node:fs";
const requiredFiles = [
"src/shared/lib/model.ts",
"src/shared/lib/repositoryIntake.ts",
"src/shared/lib/safeData.ts",
"src/shared/lib/projectStartFlow.ts",
"src/shared/lib/projectWizard.ts",
"src/shared/contexts/ProjectContext.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/components/ProjectFlowRail.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/repositoryIntake.ts"] ?? "";
const safeData = text["src/shared/lib/safeData.ts"] ?? "";
const startFlow = text["src/shared/lib/projectStartFlow.ts"] ?? "";
const wizard = text["src/shared/lib/projectWizard.ts"] ?? "";
const context = text["src/shared/contexts/ProjectContext.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 flowRail = text["src/shared/components/ProjectFlowRail.tsx"] ?? "";
const pkg = text["package.json"] ?? "";
const mustContain = [
[model, "export interface RepositoryIntake", "RepositoryIntake model missing."],
[model, "export interface RepositoryTreeEntry", "RepositoryTreeEntry model missing."],
[model, "export interface RepositoryGap", "RepositoryGap model missing."],
[model, "RepositorySkillMapping", "RepositorySkillMapping model missing."],
[model, "RepositoryImportMode", "RepositoryImportMode model missing."],
[model, "repositoryIntakes?: RepositoryIntake[]", "Project model must persist repository intakes."],
[model, "linkedRepositoryIntakeIds?: ID[]", "Repo artifacts must preserve linked repository intake ids."],
[safeData, "repositoryIntakes: asArray(project.repositoryIntakes)", "Runtime normalization must preserve repository intakes."],
[helper, "parseRepositoryTreeInput", "Repository intake parser helper missing."],
[helper, "classifyRepositoryEntry", "Repository entry classifier missing."],
[helper, "detectRepositoryStack", "Repository stack detector missing."],
[helper, "detectPackageManagers", "Package manager detector missing."],
[helper, "detectFrameworks", "Framework detector missing."],
[helper, "mapRepositoryEntriesToSkills", "Repository-to-skill mapping helper missing."],
[helper, "deriveRepositoryGaps", "Repository gap derivation helper missing."],
[helper, "formatRepositoryIntakeMarkdown", "Repository intake export formatter missing."],
[helper, "recommendRepoBuilderActionsFromIntake", "Repository intake recommendation helper missing."],
[helper, "frontend-react-vite-build", "Skill mapping must cover React/Vite evidence."],
[helper, "docker-runtime-hardening", "Skill mapping must cover Docker evidence."],
[helper, "database-migration", "Skill mapping must cover database evidence."],
[helper, "documentation-system-build", "Skill mapping must cover documentation evidence."],
[helper, "qa-qc-review", "Skill mapping must cover test evidence."],
[helper, "Imported repository evidence is not live filesystem truth", "Intake export must label imported evidence as non-live truth."],
[repoBuilder, "Existing repository intake", "Repo Builder must expose Existing repository intake section."],
[repoBuilder, "Paste a file tree, package manifest, repo summary or current-state notes", "Repo Builder must explain repository intake source types."],
[repoBuilder, "will not treat it as live disk truth", "Repo Builder must communicate the intake trust boundary."],
[repoBuilder, "saveRepositoryIntake", "Repo Builder must save repository intakes."],
[repoBuilder, "archiveRepositoryIntake", "Repo Builder must archive repository intakes."],
[repoBuilder, "formatRepositoryIntakeMarkdown", "Repo Builder must copy/download intake markdown."],
[repoBuilder, "Create expansion brief", "Repository gaps must create expansion briefs."],
[repoBuilder, "Create delivery package", "Repository gaps must create delivery packages."],
[repoBuilder, "Create Codex handoff", "Repository gaps must create Codex handoffs."],
[context, "generateCodexHandoff", "ProjectContext must generate Codex handoffs from repository evidence."],
[context, "generateHandoffReview", "ProjectContext must generate impact reviews for handoffs from repository evidence."],
[context, "repositoryIntakeItems", "Project search index must include repository intakes."],
[context, "saveRepositoryIntake", "ProjectContext must expose saveRepositoryIntake."],
[context, "archiveRepositoryIntake", "ProjectContext must expose archiveRepositoryIntake."],
[context, "createRepoExpansionFromGap", "ProjectContext must create expansion briefs from repository gaps."],
[context, "createRepoDeliveryPackageFromGap", "ProjectContext must create delivery packages from repository gaps."],
[context, "deriveRepositoryGaps", "Repo state snapshots must derive repository gaps from intakes."],
[context, "imported files", "Repo state snapshots must include imported file evidence."],
[context, "not live disk truth", "Generated handoffs must keep imported evidence separate from live truth."],
[history, "repoIntakeEntries", "Project History must include repository intake records."],
[history, "Repo Builder / repository intake", "History entries must label repository intake source."],
[audit, "Repository intake coverage", "Audit Center must show repository intake coverage."],
[workspace, "repositoryIntakeCount", "Workspace must count repository intakes."],
[workspace, "repositoryGapCount", "Workspace must count repository gaps."],
[startFlow, "import-repository-state", "Unified start next-actions must include repository intake for existing repo projects."],
[startFlow, "Generate repo state snapshot", "Unified start next-actions must lead from intake to repo state snapshot."],
[wizard, "Import repository state in Repo Builder", "First-run wizard recommendations must mention repository intake for existing repos."],
[flowRail, "Import repo evidence, derive repo state, resolve gaps", "Flow rail must describe repository intake/state/gap/delivery flow."],
[pkg, "audit:repository-intake", "package.json must expose audit:repository-intake."],
[pkg, "check-repository-intake-readiness.mjs", "package.json must wire repository intake readiness script."],
];
for (const [haystack, needle, message] of mustContain) {
if (!haystack.includes(needle)) failures.push(message);
}
if (!pkg.includes("audit:repository-intake") || !pkg.includes("audit:all")) {
failures.push("audit:all must include the repository intake readiness check.");
}
if (failures.length) {
console.error("ProjectBrain repository intake readiness: FAIL");
for (const failure of failures) console.error(`- ${failure}`);
process.exit(1);
}
console.log("ProjectBrain repository intake readiness: PASS");