tools/core/entrypoints/corpus.entrypoint.ts
tools/core/entrypoints/corpus.entrypoint.ts is a file in Coordination Surface. 193 lines of code and 49 definitions.
import type { CorpusMove, CorpusRoot } from "../types/corpus.types.ts";
import type { Document, Finding } from "../types/segment.types.ts";
import { GENERATED_DIR, NO_FIX_FLAG } from "../constants/path.constants.ts";
import {
PREVIEW_ONLY,
appliedOutcome,
corpusHead,
corpusSummary,
noMovesList,
rewroteLine,
} from "../strings/corpus.strings.ts";
import { countBy, unresolvedFinding } from "../transformers/corpus.transformer.ts";
import { dirname, join, resolve } from "node:path";
import { hasFields, isCorpusMoveList } from "../predicates/schema.predicate.ts";
import { keyFromSymbol, nameParts, rawFacetOf, symbolOf } from "../resolvers/corpus.resolver.ts";
import { mkdirSync, renameSync, rmdirSync, writeFileSync } from "node:fs";
import { readSource, toPosix, walk } from "../iterators/file.iterator.ts";
import { renameMapOf, rewriteReferences } from "../transformers/reference.transformer.ts";
import { RMDIR_REFUSALS } from "../constants/file.constants.ts";
import { hasErrorCode } from "../predicates/file.predicate.ts";
import { parseJson } from "../readers/json.reader.ts";
import { projectRoot } from "../../../config/surface.config.ts";
import { readDocument } from "../readers/document.reader.ts";
import { taxonomy } from "../../../config/taxonomy.config.ts";
const REPO_ROOT = projectRoot();
const CORPUS_ROOTS: Readonly<Record<string, CorpusRoot>> = taxonomy.corpusRoots;
const REPORT_NAME = "corpus.report.generated.json";
const REPORT_PATH = join(REPO_ROOT, GENERATED_DIR, REPORT_NAME);
export const RESTATES: readonly string[] = [
"mutation_preview_first",
"healing_is_default_in_every_entrypoint",
"pattern_references_verified_after_rename",
"born_conformant",
];
interface Resolved {
readonly moves: readonly CorpusMove[];
readonly findings: readonly Finding[];
}
interface Placed {
readonly rootName: string;
readonly config: CorpusRoot;
readonly relPath: string;
readonly name: string;
readonly insideSubtree: boolean;
}
const NOTHING: Resolved = { findings: [], moves: [] };
const refused = function refused(finding: Finding): Resolved {
return { findings: [finding], moves: [] };
};
const rewriteRecorded = function rewriteRecorded(): void {
const prior = parseJson(readSource(REPORT_PATH), REPORT_PATH);
if (!hasFields(prior, ["moves"]) || !isCorpusMoveList(prior["moves"])) {
throw new Error(noMovesList(REPORT_PATH));
}
const { moves } = prior;
const rewritten = rewriteReferences(REPO_ROOT, renameMapOf(moves));
process.stdout.write(rewroteLine(rewritten, moves.length));
};
const keyOf = function keyOf(placed: Placed, document: Document): Finding | string {
if (placed.insideSubtree) {
const symbol = symbolOf(document);
return symbol === null
? unresolvedFinding(placed.relPath, "symbol", "absent", "declare the canonical symbol as a level-2 heading")
: keyFromSymbol(symbol);
}
const key = nameParts(placed.name)[0] ?? "";
return key.length === 0
? unresolvedFinding(placed.relPath, "key", placed.name, "name the file <key>.<facet>.md")
: key;
};
const destinationOf = function destinationOf(placed: Placed, move: Omit<CorpusMove, "from" | "to">): string {
const { config, insideSubtree, rootName } = placed;
const filename =
move.variant === null ? `${move.key}.${move.facet}.md` : `${move.key}.${move.variant}.${move.facet}.md`;
return insideSubtree ? `${rootName}/${config.filedUnder}/${move.facet}/${filename}` : `${rootName}/${filename}`;
};
const variantOf = function variantOf(placed: Placed): string | null {
const segments = nameParts(placed.name);
const carried = segments.length >= 4 ? (segments.at(-3) ?? null) : null;
const originDir = placed.relPath.slice(placed.rootName.length + 1, placed.relPath.lastIndexOf("/"));
return carried ?? placed.config.variantByOrigin[originDir] ?? null;
};
const resolveFile = function resolveFile(rootName: string, config: CorpusRoot, file: string): Resolved {
const relPath = toPosix(REPO_ROOT, file);
const document = readDocument(relPath, readSource(file));
const placed: Placed = {
config,
insideSubtree: relPath.startsWith(`${rootName}/${config.filedUnder}/`),
name: relPath.slice(relPath.lastIndexOf("/") + 1),
relPath,
rootName,
};
const rawFacet = rawFacetOf(document, config);
const facet = rawFacet === null ? undefined : config.facetByValue[rawFacet];
if (facet === undefined) {
const decide = `declare one of ${config.facetFields.join(", ")} carrying a value in the declared facet set`;
return refused(unresolvedFinding(relPath, "facet", rawFacet ?? "absent", decide));
}
const key = keyOf(placed, document);
if (typeof key !== "string") {
return refused(key);
}
const resolved = { facet, key, variant: variantOf(placed) };
const to = destinationOf(placed, resolved);
return to === relPath ? NOTHING : { findings: [], moves: [{ ...resolved, from: relPath, to }] };
};
const resolveRoots = function resolveRoots(): Resolved[] {
return Object.entries(CORPUS_ROOTS).flatMap(([rootName, config]) =>
walk({ extensions: [".md"], ignored: [], root: resolve(REPO_ROOT, rootName) }).map((file) =>
resolveFile(rootName, config, file),
),
);
};
const collisionFindings = function collisionFindings(moves: readonly CorpusMove[]): Finding[] {
return [...Map.groupBy(moves, (move) => move.to)]
.filter(([, sources]) => sources.length >= 2)
.map(([target, sources]) =>
unresolvedFinding(
sources.map((move) => move.from).join(" + "),
"collision",
target,
"two files resolve to one name — give one a variant so the keys stay distinct",
),
);
};
const removeEmptyOrigin = function removeEmptyOrigin(directory: string): void {
try {
rmdirSync(directory);
} catch (error) {
if (!hasErrorCode(error, RMDIR_REFUSALS)) {
throw error;
}
}
};
const performMoves = function performMoves(moves: readonly CorpusMove[]): number {
for (const move of moves) {
const toAbs = resolve(REPO_ROOT, move.to);
mkdirSync(dirname(toAbs), { recursive: true });
renameSync(resolve(REPO_ROOT, move.from), toAbs);
}
for (const [origin, config] of Object.entries(CORPUS_ROOTS)) {
const nested = Object.keys(config.variantByOrigin).toSorted((a, b) => b.length - a.length);
for (const dir of nested) {
removeEmptyOrigin(join(REPO_ROOT, origin, dir));
}
}
return rewriteReferences(REPO_ROOT, renameMapOf(moves));
};
const closingLines = function closingLines(apply: boolean, blocked: boolean): string {
if (blocked) {
return "blocked — resolve the findings before applying\n";
}
return apply ? "" : `rehearsal only — rerun without ${NO_FIX_FLAG} to perform the moves\n`;
};
const main = function main(): void {
if (process.argv.includes("--rewrite-refs")) {
rewriteRecorded();
return;
}
const apply = !process.argv.includes(NO_FIX_FLAG);
const resolved = resolveRoots();
const resolvedMoves = resolved.flatMap((entry) => entry.moves);
const findings = [...resolved.flatMap((entry) => entry.findings), ...collisionFindings(resolvedMoves)];
const blocked = findings.length > 0;
const applied = apply && !blocked;
const referencesRewritten = applied ? performMoves(resolvedMoves) : 0;
const report = {
applied,
byFacet: countBy(resolvedMoves, (move) => move.facet),
byVariant: countBy(resolvedMoves, (move) => move.variant ?? "(none)"),
findings,
moves: resolvedMoves,
referencesRewritten,
resolved: resolvedMoves.length,
tool: "corpus",
verdict: blocked ? "fail" : "pass",
};
mkdirSync(dirname(REPORT_PATH), { recursive: true });
writeFileSync(REPORT_PATH, `${JSON.stringify(report, null, 4)}\n`, "utf8");
const outcome = applied ? appliedOutcome(referencesRewritten) : PREVIEW_ONLY;
const head = corpusHead(report.verdict.toUpperCase(), report.resolved, findings.length, outcome);
process.stdout.write(
corpusSummary(
head,
JSON.stringify(report.byFacet),
JSON.stringify(report.byVariant),
`${GENERATED_DIR}/${REPORT_NAME}`,
closingLines(apply, blocked),
),
);
process.exit(blocked ? 1 : 0);
};
main();