# runtime/entrypoints/coverage.entrypoint.ts

> 106 lines of code and 16 definitions.

Tree: Bane's Lab Content
Language: typescript
Layer: runtime
Canonical: https://banes-lab.com/anatomy/content#file-content-runtime-entrypoints-coverage-entrypoint-ts
Source text: https://banes-lab.com/source/content/runtime/entrypoints/coverage.entrypoint.ts.txt

Listed in [runtime/entrypoints](https://banes-lab.com/api/source/content/runtime/entrypoints.md), after [runtime/entrypoints/coordination.entrypoint.ts](https://banes-lab.com/source/content/runtime/entrypoints/coordination.entrypoint.ts.md) and before [runtime/entrypoints/inventory.entrypoint.ts](https://banes-lab.com/source/content/runtime/entrypoints/inventory.entrypoint.ts.md).

## Definitions

- `asFinding` (lexical_declaration, line 60)
- `inventory` (lexical_declaration, line 46)
- `seeds` (lexical_declaration, line 50)
- `graphs` (lexical_declaration, line 55)
- `known` (lexical_declaration, line 64)
- `payloadSections` (lexical_declaration, line 65)
- `findings` (lexical_declaration, line 66)
- `payload` (lexical_declaration, line 68)
- `context` (lexical_declaration, line 75)
- `graphFindings` (lexical_declaration, line 76)
- `reported` (lexical_declaration, line 81)
- `key` (lexical_declaration, line 83)
- `grounding` (lexical_declaration, line 90)
- `panels` (lexical_declaration, line 96)
- `sections` (lexical_declaration, line 98)
- `untaught` (lexical_declaration, line 104)

## Contained in

- [runtime/entrypoints](https://banes-lab.com/anatomy/content/folder-content-runtime-entrypoints.md)

## Uses

- [core/converters/section.converter.ts](https://banes-lab.com/source/content/core/converters/section.converter.ts.md)

## Enforces

- [Directed Acyclic Graph](https://banes-lab.com/records/architecture/directed-acyclic-graph.md)
- [Single Source of Truth](https://banes-lab.com/records/architecture/single-source-of-truth.md)

## Linked from

- [core/converters](https://banes-lab.com/anatomy/content/folder-content-core-converters.md)

## Source

```typescript
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);
```
