runtime/entrypoints/coverage.entrypoint.ts
runtime/entrypoints/coverage.entrypoint.ts is a file in Bane's Lab Content. 106 lines of code and 16 definitions.
import {
CLEAN_GRAPH,
FINDING_INDENT,
NO_GRAPHS,
NO_INVENTORY,
NO_SEEDS,
UNTAUGHT_HEAD,
} from "#configuration/strings/derivation.strings";
import {
GRAPHS_VALIDATED,
GROUNDING_SUMMARY,
PAGES_SUFFIX,
PAYLOAD_MISSING,
} from "#configuration/strings/coverage.strings";
import type { GraphContext, GraphFinding } from "#types/coverage.types";
import { citeFindings, groundingOf } from "#core/validators/evidence.validator";
import {
conceptsTaughtAcross,
taughtAcross,
untaughtOf,
validateGraph,
validateUnion,
} from "#core/validators/coverage.validator";
import { conclude, refuse, say } from "#core/reporters/derivation.reporter";
import { inventoryTarget, readInventory } from "#core/loaders/inventory.loader";
import { panelCount, validatePanels } from "#core/validators/panel.validator";
import { readSeeds, seedsTarget } from "#core/loaders/seed.loader";
import { COVERAGE_COMMAND } from "#configuration/constants/contract.constants";
import { COVERAGE_SUMMARY } from "#configuration/strings/contract.strings";
import { EVIDENCE } from "@banes-lab/web/configuration/constants/evidence.source.constants.ts";
import { EVIDENCE_ABSENT } from "#configuration/constants/evidence.constants";
import type { Finding } from "#types/derivation.types";
import { PANELS_VALIDATED } from "#configuration/strings/panel.strings";
import { defineCheck } from "@govlab/context/check";
import { loadContentGraphs } from "#core/loaders/coverage.loader";
import { locateNode } from "@banes-lab/web/core/loaders/definition.loader.ts";
import { nodeOf } from "#core/converters/section.converter";
import { readPagePayload } from "#core/loaders/payload.loader";
import { readPanelSections } from "#core/loaders/panel.loader";
import { resolveArgv } from "@govlab/argv";
defineCheck({ detects: [], enforces: ["architecture:directed-acyclic-graph", "architecture:single-source-of-truth"] });
resolveArgv({ command: COVERAGE_COMMAND, flags: [], summary: COVERAGE_SUMMARY });
const inventory = readInventory();
if (inventory === null) {
refuse(`${NO_INVENTORY}${inventoryTarget()}`);
}
const seeds = readSeeds();
if (seeds === null) {
refuse(`${NO_SEEDS}${seedsTarget()}`);
}
const graphs = await loadContentGraphs();
if (graphs.length === 0) {
say(NO_GRAPHS);
}
const asFinding = function asFinding(held: GraphFinding): Finding {
return { file: nodeOf(held.page, held.section), message: held.message };
};
const known = new Set([...inventory.records.map((record) => record.slug), ...seeds.seeds.map((seed) => seed.id)]);
const payloadSections = new Map<string, readonly string[]>();
const findings: Finding[] = [];
for (const graph of graphs) {
const payload = readPagePayload(graph.page);
if (payload === null) {
findings.push({ file: graph.page, message: `${PAYLOAD_MISSING}${graph.page}` });
continue;
}
payloadSections.set(graph.page, payload.sections);
}
const context: GraphContext = { known, payloadSections, taught: taughtAcross(graphs) };
const graphFindings: GraphFinding[] = [
...graphs.flatMap((graph) => validateGraph(graph, context)),
...validateUnion(graphs),
...conceptsTaughtAcross(graphs),
];
const reported = new Set<string>();
for (const held of graphFindings) {
const key = nodeOf(held.page, held.section) + held.message;
if (!reported.has(key)) {
reported.add(key);
findings.push(asFinding(held));
}
}
const grounding = groundingOf(graphs, EVIDENCE, EVIDENCE_ABSENT);
findings.push(...grounding.findings.map(asFinding), ...citeFindings(EVIDENCE, locateNode).map(asFinding));
say(
`${GROUNDING_SUMMARY}${String(grounding.grounded.length)}, ${String(grounding.absent.length)}, ${String(grounding.unassessed.length)}`,
);
let panels = 0;
for (const graph of graphs) {
const sections = readPanelSections(graph.page) ?? [];
panels += panelCount(sections);
findings.push(...validatePanels(graph.page, sections).map(asFinding));
}
say(`${String(panels)}${PANELS_VALIDATED}${String(graphs.length)}${PAGES_SUFFIX}`);
const untaught = untaughtOf(
graphs,
inventory.records.map((record) => record.slug),
);
if (untaught.length > 0) {
say(UNTAUGHT_HEAD);
for (const slug of untaught) {
say(`${FINDING_INDENT}${slug}`);
}
}
say(`${String(graphs.length)}${GRAPHS_VALIDATED}${String(payloadSections.size)}${PAGES_SUFFIX}`);
conclude(COVERAGE_COMMAND, findings, CLEAN_GRAPH);