111 lines
7.3 KiB
JavaScript
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");
|