diff --git a/docs/assessment/31-hindrance-audit.md b/docs/assessment/31-hindrance-audit.md index d1b89816..584db68c 100644 --- a/docs/assessment/31-hindrance-audit.md +++ b/docs/assessment/31-hindrance-audit.md @@ -59,6 +59,15 @@ Ranked by leverage (cognitive/structural load removed ÷ effort), per the AGENTS **Why it hinders:** asymmetric rigor invites the assumption that the un-tabled boundary is the less important one; it is the opposite. **Better home:** an M2 trust-boundary table in `runtime_contracts.md`, formation-style; hardening PRs only where the table exposes real deltas. **Authority:** documentation first; evidence decides whether code follows. +**Status (2026-07-28): CLOSED — table written, and the measurement reframes the entry.** `docs/specs/runtime_contracts.md` §"M2 trust-boundary table" measures `ingest/gate.py` against all six of formation's declared boundaries at `edf6c2a4`. The result is not "five of six missing": + +| | | +|---|---| +| **Already met** | no floats in hashed payloads (`_stable_digest` hashes strings only); no pickle anywhere under `ingest/` | +| **Category differences — closed, not owed** | content-addressing, self-sealing, and the source allow-list all presuppose a *persisted artifact with citations*. Formation validates artifacts it will store; the gate transforms text it will not. Writing these as obligations would have manufactured three gaps and sent someone to close them | +| **REAL DELTA (one)** | **no audit record per rejection.** The gate refuses with typed exceptions and records nothing about what it refused | + +The surviving delta is **not a containment hole** — refusal is fail-closed and nothing unvalidated crosses. It costs forensics, and it is the *same failure class as H-11*: a guard that works correctly and leaves no trace of having worked. It also has a downstream consumer worth naming — a widening program (G-3) must be able to ask "what shapes is the boundary refusing, and how often?", which today it cannot. Hardening is a separate PR per this entry's own authority. ## H-8 · The record contradicts the code at three load-bearing points **Verdict:** `wrong-solution` as *record-keeping* — divergence that reasoners inherit · **Layers:** governance diff --git a/docs/assessment/50-execution-plan.md b/docs/assessment/50-execution-plan.md index 87a9dd37..516b5483 100644 --- a/docs/assessment/50-execution-plan.md +++ b/docs/assessment/50-execution-plan.md @@ -221,9 +221,11 @@ The assessment directory's own corrections (N-1…N-7 applied to `30-gap-registe **Landed, and the verification pass this item mandated is why the three came out differently.** (a) was the real gap and worse than the register stated: the only import ban covered a single physics module, while `generate/realize/recall.py` — the actual recall path — asserted the law in its docstring with nothing enforcing it. Now scanned across five roots for banned ANN libraries *and* hand-rolled `cosine*` definitions. (b) is now exact: no function may construct `TurnVerdicts` without invoking `safety_check.check`, and every call must pass `self.safety_pack` (substituting the pack is a bypass that skipping-detection would miss). (c) was already well pinned — its gap was **reach**: a fail-closed safety contract running in no curated suite, verified only after merge. Promoted onto the gate. **Four sabotages, each observed red**, each caught by its own pin. -### PR-7 · The M2 trust-boundary table · **M** · H-7 +### PR-7 · The M2 trust-boundary table · **M** · H-7 — **LANDED 2026-07-28** Formation's six-boundary standard written for `ingest/gate.py` in `runtime_contracts.md`. **Documentation first** — the table's job is to expose real deltas at the surface facing untrusted user text; hardening PRs follow only where deltas are real, and are separate PRs. +**Landed, and the table's value turned out to be as much in what it closes as in what it opens.** Measured at `edf6c2a4`: two boundaries **already met** (no floats in hashed payloads, no pickle), three are **category differences** (content-addressing, self-sealing, source allow-list all presuppose a persisted artifact with citations — formation validates what it stores, the gate transforms what it does not), and **one is a real delta**: no audit record per rejection. Recording the three as closed is the load-bearing half; as owed obligations they would have generated three fake hardening tasks. The surviving delta is forensic, not containment (refusal is fail-closed), and is the same failure class PR-9 just closed on the turn spine. + ### PR-8 · Materialise the typed refusal · **M** · H-3/G-20 — *needs a small ADR (the ADR-0024 chain reserved the seam)* `InnerLoopExhaustion`'s reason/region/rejected-attempt evidence reaches `ChatResponse.refusal_reason` and a minimal honest served surface, instead of `""`. **Verification:** a refusing turn serves a non-empty, typed, replayable refusal, and `trace_hash` behavior is unchanged for non-refusing turns. diff --git a/docs/specs/runtime_contracts.md b/docs/specs/runtime_contracts.md index 68a2fcdb..3487a712 100644 --- a/docs/specs/runtime_contracts.md +++ b/docs/specs/runtime_contracts.md @@ -1087,3 +1087,63 @@ under complete provenance: Enforcement pin: `tests/test_observed_he_morph_constraint_v0.py` (four-arm ablation). + +--- + +## M2 trust-boundary table — `ingest/gate.py` (PR-7, H-7) + +**Why this table exists.** `formation/` declares its trust boundary explicitly: +the Forge's five ordered validation rules (`formation/forge.py`) plus the +hashing contract (`formation/hashing.py` — content-addressed artifacts, no +floats in hashed payloads, no pickle, self-sealing SHAs). `ingest/gate.py` is +the *production* boundary — the only point where raw data enters the versor +manifold, facing untrusted user text on every turn — and it had no comparable +declared table. H-7's charge: asymmetric rigor invites the assumption that the +un-tabled boundary is the less important one, when it is the opposite. + +**Method: measured, not assumed.** Each row states what formation declares, +what the gate actually does at `edf6c2a4`, and a verdict. Three of the six +turn out **not to transfer at all**, and saying so is the point — formation +validates *artifacts it will persist*; the gate transforms *text it will not*. +Writing those three as owed obligations would have manufactured four gaps that +do not exist and sent someone to close them. + +| # | Formation's boundary | `ingest/gate.py` at `edf6c2a4` | Verdict | +|---|---|---|---| +| B1 | **Content-addressed artifacts** — canonical JSON + SHA over every artifact | Produces a `FieldState` in memory; persists no artifact | **Category difference** — nothing is stored, so there is nothing to address | +| B2 | **No floats in hashed payloads** (`canonical_json` rejects them; float repr is platform-dependent) | `_stable_digest` (`:135`) hashes `salt + "\0" + name`, both UTF-8 strings. No float reaches a digest | **Already met** | +| B3 | **No pickle anywhere** (code-execution surface; defeats replay determinism) | No `pickle` import anywhere under `ingest/` | **Already met** | +| B4 | **Self-sealing** — SHA computed over the payload with its own `sha` field blanked | No persisted artifact to seal | **Category difference** | +| B5 | **Source allow-list** (Forge R3 — every cited source SHA must be allow-listed) | Input is live user text, not mined corpus with citations | **Category difference** | +| B6 | **An audit record per rejection** — quarantine is recorded, not merely refused | Refuses with typed exceptions (`KeyError` `:235`/`:286`, `RuntimeError` `:318`/`:424`). `vocab.record_unknown_token` (`:331`) records OOV *observation*, which is not a rejection record | **REAL DELTA — the only one** | + +### The one real delta, stated precisely + +The production boundary facing untrusted text **refuses correctly and records +nothing about what it refused.** Formation quarantines with a record; the gate +raises and the fact is gone unless a caller happens to log it. Two consequences +worth separating: + +- **Not a safety hole.** The refusal is typed and fail-closed — nothing + unvalidated crosses into the manifold. B6's absence costs *forensics*, not + containment. +- **It is the same failure class as H-11**, which PR-9 closed on the turn + spine: a guard that works correctly and leaves no trace of having worked. + A boundary that cannot say what it rejected cannot answer "is this input + shape common enough to support?" — which is exactly the question a widening + program (G-3) has to ask of its own refusals. + +### What this table does not do + +Per H-7's authority — *"documentation first; evidence decides whether code +follows"* — this is the evidence, not the fix. B6 is a hardening candidate for +a separate PR, sized against whether anything actually consumes gate-rejection +telemetry today. B1/B4/B5 are **closed as category differences** and should not +be re-derived as gaps by a future reader; that is what this table is for. + +**AGENTS.md §"Security and trust boundaries" defaults**, checked against the +gate for completeness: explicit opt-in for arbitrary execution (n/a — the gate +executes nothing), reject unsafe paths before filesystem access (n/a — no +filesystem access), centralize safe display/log handling (met — the gate emits +no user-controlled text to logs), no hidden background execution (met), no +broad filesystem mutation (met — the gate mutates nothing).