tools/rules/record.rule.ts

tools/rules/record.rule.ts is a file in Coordination Surface. 90 lines of code and 16 definitions.

import type { RuleContext, RuleDeclaration, RuleResult } from "../core/types/rule.types.ts";
import { checkSchema, checkTension, recordFinding as finding } from "../core/validators/record.validator.ts";
import { citedIds, readRecordDocument } from "../core/readers/record.reader.ts";
import type { Finding } from "../core/types/segment.types.ts";
import { INTEL_ROOT } from "../core/constants/template.constants.ts";

const CITATION_KEYS = ["conflicts", "with", "compatible", "incompatible", "see"] as const;

type RecordDocument = ReturnType<typeof readRecordDocument>;

type IntelRecord = RecordDocument["records"][number];

const citationFindings = function citationFindings(
    path: string,
    record: IntelRecord,
    known: ReadonlySet<string>,
): Finding[] {
    return CITATION_KEYS.flatMap((key) => {
        const value = record.keys[key];
        const cited = value === undefined ? [] : citedIds(value);
        return cited
            .filter((id) => !known.has(id))
            .map((id) =>
                finding(
                    "unresolvedCitation",
                    path,
                    record.line,
                    `${record.id} ${key}`,
                    `${id} does not resolve to a record`,
                    "correct the id or drop the citation — a citation that resolves to nothing errors nowhere and disconnects the graph silently",
                ),
            );
    });
};

const typedFindings = function typedFindings(path: string, record: IntelRecord, document: RecordDocument): Finding[] {
    if (document.shape !== "typed") {
        return [];
    }
    return [...checkSchema(path, record), ...(record.keys["type"] === "tension" ? checkTension(path, record) : [])];
};

const documentFindings = function documentFindings(
    path: string,
    document: RecordDocument,
    known: ReadonlySet<string>,
): Finding[] {
    return document.records.flatMap((record, index) => {
        const repeated = document.records.slice(0, index).some((earlier) => earlier.id === record.id);
        const duplicate = repeated
            ? [
                  finding(
                      "duplicateId",
                      path,
                      record.line,
                      record.id,
                      `${record.id} is declared more than once`,
                      "record ids are stable and unique; renumber the later one rather than reusing an id another record already answers to",
                  ),
              ]
            : [];
        return [...duplicate, ...citationFindings(path, record, known), ...typedFindings(path, record, document)];
    });
};

export const rule: RuleDeclaration = {
    check(context: RuleContext): RuleResult {
        const paths = context.paths.filter((path) => path.startsWith(INTEL_ROOT));
        const parsed = paths.map((path) => ({ document: readRecordDocument(context.read(path)), path }));
        const known = new Set(parsed.flatMap(({ document }) => document.records.map((record) => record.id)));
        const findings = parsed.flatMap(({ document, path }) => documentFindings(path, document, known));

        return {
            derivations: {
                reached: paths,
                recordsWalked: [...known].toSorted((left, right) => left.localeCompare(right, "en")),
                skippedAsOutsideRecordRoot: context.paths.filter((path) => !path.startsWith(INTEL_ROOT)),
            },
            findings,
            healed: [],
        };
    },
    extensions: [".md"],
    heals: false,
    invariant: "every typed intel record carries its required keys and every cited record id resolves",
    jurisdiction: "taxonomy",
    kinds: [
        "disputedNotSurfaced",
        "duplicateId",
        "kindContradiction",
        "missingKey",
        "missingTensionKey",
        "unknownDerivation",
        "unknownKind",
        "unknownTier",
    ],

    stage: "content",
};