The Dialect Contract — how the map learns new languages

Move 0 of the fabric arc. Before the map learns to read shell scripts and, later, a practice's actual truth, this contract fixes the rules every new language must obey — so an edge is always real, a blind spot always confesses, and no dialect ever has to negotiate meaning with another. Five scouts surveyed the field first; an independent reviewer graded the result twice (7 → revise → 8.5/10, BUILD). Four calls are yours. Everything else is settled or fenced.

No third class. A wire is proven, or the blindness is named. Nothing in between — no "probably," ever.
Shared rules, private vocabularies. Dialects share what counts as proof and how things are named. They never share meanings — that's the mistake that killed every universal-graph project before us.
Receipts bind to bytes. Every proven wire carries evidence you can grep and a fingerprint a machine can check.
The kill-check came back clear. No existing standard does this whole job — we adopt the field's proven shapes and build the one piece nobody has.

The journey — follow one wire through the system

The concrete thing to hold: a line in our CI config that runs a test script. Today that wire is invisible to the map. Here is its whole life under the contract.

  1. Five scouts surveyed the field before a line was designed. The headline: nobody has our fence. The best supply-chain standards can say "this list may be incomplete" — a shrug. None can say "I can't see here, and here are the exact suspects, and here's how to check." The big code-analysis tools handle blindness by guessing generously and calling it sound — right for security scanners, poisonous for trust decisions. And the graveyard of "one graph of everything" projects all died the same death: making everyone agree on meanings cost more than it paid. The winners fixed one narrow boundary and let each side stay itself.
    ↘ go deeper — adopted, diverged, rejected, with evidence grades

    ADOPT (architecture): per-dialect extractors feeding one queryable substrate — CodeQL (extractor per language, per-language schemas into shared query machinery) and Meta's Glean. The field's at-scale practice is shared substrate + thin join — exactly our split. ADOPT (shapes): in-toto's digest-binding ("subjects matched purely by digest" — fetched verbatim); SCIP-over-LSIF's human-readable string keys (debuggability won); SPDX 3.0's completeness-as-first-class-metadata precedent.

    DIVERGE (justified): the field over-approximates unresolvables (Joern's external stubs with sound propagation; Bazel's select-union). We carry the same candidate set as fence doors, never as edges — our consumers make trust decisions; a laundered edge is our false green. The doors ARE the union, labeled.

    REJECT: universal semantic unification (OWL usability failure — fetched; scoped-protocol wins — SCIP half fetched, LSP half synthesis, the reject stands on fetched legs). The named anti-pattern, now cited from the source's own bytes: scip.proto's occurrence symbol field is literally annotated "(optional)" and the protocol has NO field for unresolved references — a failed resolution is an absent field, silently. That silence is what our fence replaces.

    KILL-CHECK: fires nothing. GUAC aggregates but its gaps are absence-of-data, not structured fences; CodeQL exposes extraction errors as diagnostics OUTSIDE the queryable database. No candidate covers per-edge receipts + first-class fences + pluggable dialects.

  2. A dialect joins by declaring its own blindness, in its own words. Each dialect (JS imports, C#, shell, someday practice truth) registers with a closed, frozen list of the ways it can be blind. The contract enforces the closedness mechanically — but never the vocabulary. Two dialects may even use the same short word for different blind spots; namespacing keeps them apart. The day dialects must agree on meanings is the day we've rebuilt the semantic web — so the literal form of cross-dialect coupling is rejected by a machine check at registration, and the subtle form (converging meanings under different names) is caught by a human question asked in writing, every registration. Honest strength claim: the machine catches the letter; the human catches the spirit.
    ↘ go deeper — axis discipline + the tripwire gates

    G-M0-1 [M]: a fence citing an axis outside its dialect's declared enum → registration throws. Deliberate-break fixture included.

    G-M0-2 [M]+[J]: axis ids are dialect-namespaced. Machine leg rejects (a) a fence whose namespace isn't its own dialect, (b) an enum containing another dialect's namespaced member. Bare homonyms allowed — the live example: "computed-path" exists today in two of our own modules meaning two things; forcing global uniqueness would be the ontology trap itself. Judgment leg: new-dialect registration includes the lead's one-page review with the negotiated-meaning question answered in writing.

    Generalizes the closed-enum throw discipline already live in the flow lens (frozen enum + membership validation that names the rejected family explicitly).

  3. It reads the repo at a pin — and every wire is proven, or the blindness is named. This is the floor everything rests on. Our CI line invokes a committed script by its literal path: that becomes a proven edge. Three lines down, a command builds its path from a variable at runtime: the dialect cannot prove where that goes — so it emits a fence: the blindness named, the exact spot marked, every candidate target it might reach listed as an unproven door, and the manual check prescribed. The doors are the field's "generous guess," carried honestly — same information the big tools emit, never laundered into real wires. A guess never travels as a wire.
    ↘ go deeper — the contract types + site-vs-scope fences
    DialectExtractor {
      id                                 // 'import-js' | 'scip' | 'shell' | 'neuron-projection'
      edges(pin)   -> ProvenEdge[]       // ONLY provably-real (never-lie floor; no heuristic class)
      fences(pin)  -> Fence[]            // named blindness, per-target where extractable
      blindAxes()  -> BlindAxis[]        // this dialect's OWN closed frozen enum
      fixtures: { mustFire, mustNotFire, deliberateBreak }  // gate-run at every merge
    }
    Fence {
      axisId                             // namespaced <dialectId>/<axis>
      at: {file,line} | {scope}          // SITE fence, or SCOPE fence for traversal-bound
                                         // blindness with no source location (e.g. a depth cap)
                                         // — a fence with no site NEVER invents one
      doors: [{to?, why}]                // the labeled over-approximation
      grepPattern                        // fences carry their handle
    }

    Dual face: the canonical face is "enumerate your edges and fences at this pin"; a dialect may compute lazily inside (our CI parser answers point questions today and keeps doing so — the retrofit wraps it in an enumerator; the existing gate consumer keeps its face through a shim, zero behavior change, proven the same two ways move 1 demands). A dialect that can't enumerate isn't a dialect yet — it ships fence-only.

    G-M0-4 [M]: every dialect's fixtures run at gate time; a dialect whose deliberate-break does NOT go red is vacuous and fails — both fence directions (missed real edge AND real consumer swept into blind) mandatory.

  4. Every proven wire carries its receipt — and receipts come in exactly two kinds. A wire read out of source carries the file, the line, the verbatim quote, and a fingerprint of the exact bytes it rests on — a human can grep it, a machine can verify it. A wire someone declared (the future workstream-state records) carries a pointer to its evidence — a PR, a commit, a transcript — and the date it was last verified. Two kinds, closed; no third. An edge without a complete receipt of its kind is rejected: no naked edges.
    ↘ go deeper — receipt shapes + the honest retrofit cost
    SourceReceipt   { file, line, quote, contentHash }        // parsed-source dialects
    DeclaredReceipt { pointer, pointerKind: 'pr'|'commit'|'test-run'|'transcript',
                      verifiedDate }                           // declared-record dialects

    Stated honestly (review catch): neither existing engine carries receipts today — import edges are bare from→to pairs; the C# engine discards occurrence positions and dedups references. Move 1 BUILDS receipt derivation for both, with deterministic licensing rules (import: first matching import line; C#: first occurrence in file-then-line order). Receipts are additive — excluded from the zero-behavior-change byte-diff. If any existing edge's receipt proves underivable, that is move 1's KILL clause (contract redesign) — never a silent edge-set shrink, never a fabricated receipt.

    G-M0-3 [M]: completeness is per receipt kind — all four source fields, or all three declared fields. A receipt matching neither kind fully is rejected.

  5. Dialects meet only at names — never at meanings. The one agreement dialects make with each other: how things are named. A file, a fact, a gate — each gets one canonical, repo-qualified name, because the fabric's whole point is edges that cross repos (a fact in the genome, the page it fills in a practice's site), and an unqualified path is ambiguous the moment two repos are on the table. A wrong identity join would be a confident-wrong edge at the identity layer — the exact class this engine exists to kill. Currency travels the same way: every answer names the exact version of every repo it read, per repo, never one blended stamp.
    ↘ go deeper — node identity + the alternative we weighed and rejected

    Node keys are repo-qualified: a registered repo short-name plus a per-class canonical key (repo-relative path for files; fact id for facts; leg id for gates). No dialect mints a new node class OR repo name without a registered one-page key scheme, lead-ratified. Key schemes name THINGS, never meanings — the only cross-dialect agreement the contract permits. The envelope carries a per-repo pin map, never a single pin.

    Weighed and rejected — the field's strongest alternative shape for epistemic labeling: Bazel/Buck2 expose separate query surfaces per resolution stage. Rejected: our dialects form no resolution pipeline — a pinned snapshot is already the single named state, so staged surfaces would multiply query APIs without adding states we possess. What we adopt is the principle: the resolution state is always NAMED, never implied — here, by the pin map on every envelope.

  6. A verdict must confess everything it cannot see. When the merged map answers "nothing consumes this" or "this holds," that is an absence claim — and asserting absence requires having seen everything. So every verdict is gated on a confession across five axes: source classes no dialect reads yet; each dialect's declared blind spots; files that wouldn't parse; repos answering from mismatched versions; and — for declared records — silence itself (a workstream with no record since a date is reported as exactly that, never as "no change"; the absence of a declaration is not a declaration of absence). Where completeness can't be proven, the answer is "cannot certify" — never a fake green.
    ↘ go deeper — the staleness gate for declared records

    G-M0-6 [M]: declared-record staleness fails closed — a claim whose verified-date predates newer evidence renders "[STALE — last verified date]"; the deliberate-break (serve it present-tense) must go RED. A record appended without an evidence pointer is rejected at write time. Arms at first declared-record dialect registration, not at move 1 — a gate demanding unbuilt machinery would force scope creep or a forbidden skip.

    G-M0-5 [J]: this spec's own bar — independent graded review ≥8/10 with an outward frame-fitness lens empowered to reject the intent itself. Two passes: 7/10 REVISE (nine findings, all verified against disk before folding) → 8.5/10 BUILD (conditions folded, independently re-verified).

  7. The board question rides along as a use case — deliberately not a build. The three-shards incident (three sessions, three confident silo answers, June truth served in a July voice) minted a requirement: the fabric must someday answer "what is the state of my world," with every claim dated and evidenced. This contract accommodates it for the cost of a paragraph — the declared-receipt kind above — and builds nothing on it. Your memory-testimony ruling governs the real decision (a new record type, or the reflex that no world-claim testifies without a currency check), and that ruling gets made when the fabric reaches the domain concretely, not tonight. A dormant accommodation is strikeable; a built dialect is a retrofit.
  8. What happens on your word. Move 1: retrofit the two engines we already trust (JS imports, C#) under this contract with zero behavior change, proven two ways — the full gate green at a pinned baseline, and byte-identical edge and fence sets on a fixed corpus. Then move 2: the shell dialect, lifted from the CI parser we already built — and our CI wire from the top of this journey finally becomes a proven, receipted edge on the map. The contract never gets its own celebration; it's right when nobody notices it.

What could go wrong — named, with mitigations

The contract quietly becomes an ontology. The failure signature: any field whose meaning two dialects must negotiate. Mechanical tripwire at registration for the literal form; the human question in writing for the subtle form; and honest labeling that the tipping-point theory is our own inference, flagged for falsification as dialects accumulate.
A dialect can't actually enumerate. Then it isn't a dialect yet — it ships fence-only until it can. Same rule move 2 already carries for precision failures.
The fence advance is a mirage. Maybe suspects-behind-doors doesn't scale. Mitigation: the door model is already LIVE in our flow lens on real code — we're generalizing a working mechanism, not an academic paper (the one paper proposing the same idea is unshipped; we cite it, we don't lean on it).

Your four calls

1 — Name the arc.

Working name: the Fabric Arc. Candidates if you want them: Fabric (what it is), Loom (what it does — weaves fact to surface). Or yours. One word settles it.

2 — Confirm practice truth as dialect #3.

Carried from the fabric plan, still formally open: after shell, the next language the map learns is a veterinary practice's actual truth — with the mechanical spine already ratified (a projection edge is real only when the build recorded "fact X filled slot Y"; agreement without that record is fenced, never proven).

3 — Ratify this contract.

The grade bar is met (8.5/10, BUILD, conditions folded and independently re-verified). On your word, move 1 starts: retrofit both engines, zero behavior change, twin proofs.

4 — The board question: confirm the holding position.

It stays a use-case the contract must not preclude — nothing built, sequencing deferred under your memory-testimony ruling until the fabric reaches that domain concretely. Your call here is narrow: confirm this holding position is right, or strike the board-question material from the contract entirely.

The one non-negotiable underneath all of it: a guess never travels as a wire. Proven, or fenced by name with its suspects listed — no third class, in any dialect, ever.

Reference strip

Decisions: proven-or-fenced · algebra-not-meanings · two receipt kinds · repo-qualified names
Gates: G-M0-1 axis membership · G-M0-2 anti-ontology · G-M0-3 no naked edges · G-M0-4 fixture vacuity · G-M0-5 this review · G-M0-6 declared staleness
Your calls: name · dialect #3 · ratify · board holding
Risks: ontology creep · can't enumerate · fence mirage

↘ follow-ups banked (not this move) + provenance

SCAI (in-toto's attribute predicate) — 15-minute read before move 1; fold or dismiss in writing. Sigstore graph tooling — same. GUAC's actual GraphQL schema — fetch before treating "no fence primitive" as discharged. The RDF-economics paper — re-fetch before that framing enters canon. The tipping-point boundary — falsify against real dialect accumulation at moves 2/4.

Canonical source: docs/ai/SPEC-move0-dialect-contract.md (Markdown wins on any disagreement). Provenance: five-leg frontier scan, lead-adjudicated, internal receipts grep-verified on disk; graded 7 → folds verified → 8.5 BUILD; board-question fold from the Robert-approved Neuron handoff; call #4 reframed under intent/ruling/memory-testimony (ratified in-chat 2026-07-05).