import { AGENT_FIELDS, AGENT_INDEX, BOARD_PATH, COMMS_TEMPLATE, GATE_FIELDS, PROJECTION_HOST, STALE_MARKERS, } from "../core/constants/board.constants.ts"; import { BLOCKING_SUFFIX, VENUE_ARCHIVE } from "../core/constants/blocking.constants.ts"; import type { BoardRecord, Delimiter } from "../core/analyzers/board.analyzer.ts"; import type { RuleContext, RuleDeclaration, RuleResult } from "../core/types/rule.types.ts"; import { boardFinding, checkAddressees, checkRecord, checkStateDrift, healStateDrift, peerSet, stateDrift, } from "../core/validators/board.validator.ts"; import { boardRecords, delimitersIn } from "../core/analyzers/board.analyzer.ts"; import { checkIndex, checkItemAddressing, checkItemFences, checkItemLetters, checkReadable, checkTemplateDrift, letterOfLabel, } from "../core/inspectors/board.inspector.ts"; import type { Finding } from "../core/types/segment.types.ts"; import type { StateDrift } from "../core/validators/board.validator.ts"; import { carriesMarker } from "../core/analyzers/marker.analyzer.ts"; import { checkGateState } from "../core/inspectors/report.inspector.ts"; import { checkProjection } from "../core/inspectors/projection.inspector.ts"; import { writeBoardIfUnmoved } from "../core/generators/board.generator.ts"; const NO_DRIFT = "none — no record's marker disagrees with its binding"; const DRIFT_HEALED = "HEALED IN THIS RUN — the markers below are what the walk MEASURED before it wrote, retained because " + "the heal is a comparison and the earlier state is its operand. They are not a live disagreement, " + "and reading them as current state is the reading a derivation invites, which is why the " + "disposition sits beside them rather than being inferred from an empty findings list"; const DRIFT_STANDING = "STANDING — the markers below disagree with their bindings and this run did not write, so each is " + "reported as a finding"; const PROJECTION_ABSENT = "ABSENT — no governance document is declared, so the branch that checks the projection does not run"; interface Fence { readonly open: number; readonly close: number; } interface DriftOutcome { readonly disposition: string; readonly drifts: readonly StateDrift[]; readonly findings: readonly Finding[]; readonly healed: readonly string[]; } const indexOf = function indexOf(context: RuleContext): string { return context.exists(AGENT_INDEX) ? context.read(AGENT_INDEX) : ""; }; const fieldCounts = function fieldCounts(lines: readonly string[], required: readonly string[]): Map { const seen = new Map(); for (const line of lines) { const field = required.find((each) => line.startsWith(` ${each}:`)); if (field !== undefined) { seen.set(field, (seen.get(field) ?? 0) + 1); } } return seen; }; const checkDuplicateFields = function checkDuplicateFields(source: string, records: readonly BoardRecord[]): Finding[] { const lines = source.split("\n"); return records.flatMap((record, index) => { const required = record.kind === "agent" ? AGENT_FIELDS : GATE_FIELDS; const end = records[index + 1]?.line ?? lines.length + 1; return [...fieldCounts(lines.slice(record.line, end - 1), required)] .filter(([, count]) => count > 1) .map(([field, count]) => boardFinding( "duplicateField", record.line, record.label, `${record.label} declares ${field} ${String(count)} times`, `${record.label} declares ${field} once`, "a record carries exactly its fixed schema, and a field parsed into a map collapses its duplicates into one entry — so a second declaration of the same field is invisible to every check that reads the parsed record, while a reader sees two fields disagreeing about one thing", ), ); }); }; const leadingValue = function leadingValue(line: string): string { const colon = line.indexOf(":"); const value = colon === -1 ? line.trim() : line.slice(colon + 1).trim(); return value.split(" ")[0] ?? ""; }; const checkMarkers = function checkMarkers(source: string): Finding[] { return source.split("\n").flatMap((line, index) => { const first = leadingValue(line); return STALE_MARKERS.filter((marker) => first === marker && carriesMarker(line, marker)).map((marker) => boardFinding( "staleMarker", index + 1, marker, `the board carries the marker ${marker}`, "current truth only", "the board is overwritten in place; a resolved flag or completed unit is deleted outright, because a stale record manufactures a false belief in every agent that reads it", ), ); }); }; const fenceOf = function fenceOf(markers: readonly Delimiter[], agent: string, line: number): Fence | null { const opens = markers.filter((mark) => mark.open && mark.agent === agent); const closes = markers.filter((mark) => !mark.open && mark.agent === agent); const [open] = opens; const [close] = closes; if (opens.length !== 1 || closes.length !== 1 || open === undefined || close === undefined) { return null; } return open.line < line && close.line > line ? { close: close.line, open: open.line } : null; }; const intruderIn = function intruderIn( markers: readonly Delimiter[], agent: string, fence: Fence, ): Delimiter | undefined { const foreign = markers.filter((mark) => mark.agent !== agent && !mark.agent.startsWith(`${agent}-`)); return foreign.find((mark) => mark.line > fence.open && mark.line < fence.close); }; const delimiterFindings = function delimiterFindings(record: BoardRecord, markers: readonly Delimiter[]): Finding[] { const agent = letterOfLabel(record.label); const fence = fenceOf(markers, agent, record.line); if (fence === null) { return [ boardFinding( "undelimitedRecord", record.line, record.label, `${record.label} is not enclosed by a matched delimiter pair`, `┌─── AGENT ${agent} above the record and └─── END AGENT ${agent} below it`, "an undelimited record has no anchor unique to its own writer, so a neighbor revising their block has nothing to edit against and reaches for a whole-file write instead — which succeeds, reports success to the one who overwrote, and says nothing to the one overwritten", ), ]; } const intruder = intruderIn(markers, agent, fence); return intruder === undefined ? [] : [ boardFinding( "interleavedRecord", intruder.line, record.label, `a delimiter for ${intruder.agent} falls inside the fence of ${record.label}`, `every marker between lines ${String(fence.open)} and ${String(fence.close)} belongs to ${agent}`, "a fence that encloses another agent's fence passes the pair check while defeating its purpose: an edit anchored on the outer fence spans the inner agent's content, which is exactly the destruction the fence exists to prevent, and both records read as correctly delimited while one sits inside the other", ), ]; }; const checkDelimiters = function checkDelimiters(source: string, records: readonly BoardRecord[]): Finding[] { const markers = delimitersIn(source); return records.filter((record) => record.kind === "agent").flatMap((record) => delimiterFindings(record, markers)); }; const driftOutcome = function driftOutcome( context: RuleContext, fix: boolean, source: string, records: readonly BoardRecord[], ): DriftOutcome { const drifts = stateDrift(records, indexOf(context)); if (drifts.length === 0) { return { disposition: NO_DRIFT, drifts, findings: [], healed: [] }; } const applied = fix && writeBoardIfUnmoved(context.repoRoot, source, healStateDrift(source, drifts)); if (applied) { return { disposition: DRIFT_HEALED, drifts, findings: [], healed: [BOARD_PATH] }; } return { disposition: DRIFT_STANDING, drifts, findings: checkStateDrift(drifts), healed: [] }; }; const projectionFindings = function projectionFindings( context: RuleContext, venues: readonly string[], ): Finding[] | null { const host = PROJECTION_HOST; return host === null || !context.exists(host) ? null : checkProjection(context.read(host), venues); }; const recordFindings = function recordFindings( context: RuleContext, source: string, records: readonly BoardRecord[], ): Finding[] { const index = indexOf(context); const peers = peerSet(records, index); return [ ...records.flatMap((record) => checkRecord(record, peers)), ...checkAddressees(source, index), ...checkGateState(source, context.repoRoot), ]; }; const surfaceFindings = function surfaceFindings( context: RuleContext, source: string, records: readonly BoardRecord[], ): Finding[] { return [ ...checkDelimiters(source, records), ...checkMarkers(source), ...checkReadable(source), ...checkDuplicateFields(source, records), ...checkItemFences(source), ...checkItemLetters(source), ...checkItemAddressing(source), ...(context.exists(AGENT_INDEX) ? checkIndex(records, context.read(AGENT_INDEX)) : []), ...(context.exists(COMMS_TEMPLATE) ? checkTemplateDrift(context.read(COMMS_TEMPLATE)) : []), ]; }; export const rule: RuleDeclaration = { check(context: RuleContext, fix: boolean): RuleResult { if (!context.paths.includes(BOARD_PATH)) { return { derivations: { board: "absent from this run's path set", skippedAsOutOfScope: [BOARD_PATH] }, findings: [], healed: [], }; } const source = context.read(BOARD_PATH); const records = boardRecords(source); const drift = driftOutcome(context, fix, source, records); const venues = context.paths .filter((path) => path.endsWith(BLOCKING_SUFFIX)) .filter((path) => !path.startsWith(VENUE_ARCHIVE)); const projection = projectionFindings(context, venues); return { derivations: { board: "present", projection: projection === null ? PROJECTION_ABSENT : "checked", recordsWalked: records.map((record) => record.label), stateDrift: drift.drifts.map((each) => `${each.letter}: ${each.marker} here, ${each.bound} bound`), stateDriftDisposition: drift.disposition, venuesSeen: venues, }, findings: [ ...drift.findings, ...(projection ?? []), ...recordFindings(context, source, records), ...surfaceFindings(context, source, records), ], healed: [...drift.healed], }; }, extensions: [], heals: true, invariant: "the coordination board carries current truth in exactly its declared schema", jurisdiction: "all", kinds: [ "badState", "danglingAddressee", "danglingAnswer", "derivedStateDrift", "duplicateField", "duplicateIndexBinding", "extraField", "foreignItemLetter", "interleavedRecord", "malformedItemFence", "missingField", "oversizedProjection", "phantomProjection", "repeatedClaim", "selfAnswer", "staleGateState", "staleMarker", "templateDrift", "undelimitedRecord", "unindexedAgent", "unreadableField", "unresolvedAddressing", "unstampedItem", ], reads: PROJECTION_HOST === null ? [BOARD_PATH, AGENT_INDEX, COMMS_TEMPLATE] : [BOARD_PATH, PROJECTION_HOST, AGENT_INDEX, COMMS_TEMPLATE], stage: "content", };