import { type ModelGraph } from "../loader/model-graph.js"; import type { Violation } from "./types.js"; /** * Cross-node consistency (Proposal 016 T3). Every other check in this layer * asks "is this ONE node well-formed?"; these two ask "do the nodes agree with * each other?" — the blind spot that made both of the incidents below survive * human review at 60-node scale. * * Same cost budget as the rest of T0: pure functions of the already-loaded * graph. No file I/O, no AST, no network, no LLM. */ /** * Advisory: the same `path#symbol` anchor claimed by two or more nodes. * * An anchor on a loop or a flow is an OWNERSHIP claim — "this node is the * model's account of that code". Two nodes claiming one symbol means the same * behaviour got modeled twice, and conformance then grades it twice. Proposal * 016 D8: a parallel-modeling run filed one compaction behaviour as both L4 and * L10 (`agent-session.ts#_checkCompaction` appearing under each), `check` said * nothing, and a human found it with `uniq -c`. * * `Junction.evidence[].anchor` is deliberately OUT of scope. A junction cites * code as proof that a risk exists at a seam; the code it cites belongs to the * loops/flows on either side BY DESIGN, so overlap there is the intended shape, * not a duplicate claim. `Scenario.verified_by` is out for the same reason — * one test legitimately verifies several scenarios. * * WARNING, not error. Duplication is a modeling judgement: a shared entry point * genuinely claimed by two behaviours is rare but real, and the merge decision * (fold the nodes, or narrow each anchor) belongs to a human — Proposal 016's * 不做清单 rules out automatic merging precisely because this class of mistake * enters silently. An existing model must not turn red on upgrade over * something that has always been true of it. * * Matching is on the EXACT anchor string. Two spellings of one symbol * (`a.ts#foo` vs `a.ts#Klass.foo`) are not folded together: normalising would * mean guessing at symbol identity, and this check's whole value is that it * never guesses. * * TABLE-STYLE anchors (`sessions`, `jobs_table.payload` — the `#`-less form * anchor.ts allows) are skipped for the same reason junction evidence is. A * function is written once and belongs to one behaviour; a TABLE is read and * written by many, so two loops naming `sessions.status` is ordinary rather * than duplicate modeling. Only a `path#symbol` anchor carries the ownership * claim this check is about. */ export declare function checkAnchorDuplicate(graph: ModelGraph): Violation[]; /** * Advisory: an id-shaped token in prose that names no node in this model. * * Free text is the one place a cross-reference is written with no schema behind * it, so nothing catches it going stale. Proposal 016 D10: a loop's `notes` * said "见 L4 auto-retry-backoff" about behaviour that actually lived in L3. It * survived two rounds of review, and when an unrelated L4 was later added the * error got WORSE — from pointing at nothing to pointing at the wrong node. * (This check cannot catch that second stage, by construction: L4 exists. It * catches the window in which the reference is still dangling, which is when * the fix is cheap.) * * KNOWN FALSE POSITIVES, accepted deliberately. This is a text scan with no * notion of what a sentence is about: "C1" in prose may be a hardware pin, a * column name or a path fragment, and each of those reports. Telling them apart * needs an LLM, which the engine's zero-LLM/zero-network rule forbids — and a * check that stays silent on real stale references is worth less than one that * occasionally names an innocent token. Hence WARNING and never error: a false * positive costs a reader one glance, and nothing turns red. */ export declare function checkFreetextIdRef(graph: ModelGraph): Violation[]; //# sourceMappingURL=consistency.d.ts.map