Skip to content

Commit d419fa4

Browse files
committed
docs(p022): bring the status surfaces level with what 4b proves (#259 cp4b.3)
The obligation family is ported, replayed and promoted, so every surface that still said otherwise is corrected — and none of them gains a number: * **P-022** row 4b goes from "not started" to complete, with the wording this checkpoint earns and links to the generated fragments; the preferred queue drops 4b and now reads coordinate-domain decision → #259 final acceptance → #260 acceptance / #261. Two stale claims elsewhere in the table go with it: cp5's "what remains is row 4b and the coordinate decision", and step 7a's typed shadow counts — which 4b changed, which is exactly why that row now points at the census instead of restating it. * **`spec/Bridge.md` §6** no longer lists a protocol-bearing document among the declared boundaries; it records that it did until 4b and that a re-declared exclusion is a red build, not a note. * **`spec/BridgeBehaviorMatrix.md`** gains two rows — the analysis (core suite, with its own fact-parity family) and the verdict mapping (L3 ✅) — and the paragraph in (e) is rewritten: one row family is outside the replayed set now, not two. * **cp4 and cp5 notes** carry a "read as history" banner where they describe the refusal, so a reader cannot mistake a checkpoint record for current state. * **The proposals index** records row 4b and carries no measured count at all. * **Both campaigns are registered** in `render_checkpoint_status.py` (a new `p022-cp4b-mutations.md` fragment) and in `test_checkpoint_status.DEFINITIONS`, so they are rendered from evidence and re-anchored by the gate like every other campaign in the tree. * Two remaining live claims are fixed rather than left to rot: the verdict fixture harness's docstring and the repro manifest's pin for the protocol artifact. The checkpoint note gains its results package: what landed, the frozen fixtures and their regeneration commands, the one production dependency change, the zero-on-every-axis differential, what both campaigns found before they were green, and the two things measured rather than claimed — that the protocol path does not apply BR-V5's short-slice rule, and that the family's append position is unobservable end to end. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WbgYFv2UW3iRJ3L33naVC3
1 parent 0761864 commit d419fa4

12 files changed

Lines changed: 370 additions & 64 deletions

‎docs/generated/p022-cp4b-mutations.md‎

Lines changed: 110 additions & 0 deletions
Large diffs are not rendered by default.

‎docs/notes/p022-bridge-verdict-checkpoint4.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ without regenerating a golden.
7878
7979
### The unmeasured set is named, not hidden
8080

81+
> **Read the protocol paragraphs below as history.** #259 checkpoint 4b
82+
> ([note](p022-bridge-verdict-checkpoint4b.md)) ported the obligation
83+
> analysis, wired it through the bridge and **promoted both protocol
84+
> documents out of `rust_replay_excluded`**. Where this note says the OBL
85+
> analysis is not ported, or that a protocol-bearing document is refused,
86+
> it describes the state at the time it was written.
87+
8188
Each exclusion is an entry in `rust_replay_excluded` with a reason and an
8289
expectation the replay executes (`rust_refusal: bridge` + an error substring,
8390
or `door`); the set is also pinned by name, and an exclusion that stops

‎docs/notes/p022-bridge-verdict-checkpoint4b.md‎

Lines changed: 174 additions & 32 deletions
Large diffs are not rendered by default.

‎docs/notes/p022-bridge-verdict-checkpoint5.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
> [`p022-cp5-mutations.md`](../generated/p022-cp5-mutations.md); nothing is
1010
> typed here.
1111
12+
> **Read the protocol paragraphs below as history.** #259 checkpoint 4b
13+
> ([note](p022-bridge-verdict-checkpoint4b.md)) ported the obligation
14+
> analysis, wired it through the bridge and **promoted both protocol
15+
> documents out of `rust_replay_excluded`**. Where this note says the OBL
16+
> analysis is not ported, or that a protocol-bearing document is refused,
17+
> it describes the state at the time it was written.
18+
1219
Checkpoint 4 ([note](p022-bridge-verdict-checkpoint4.md)) proved identity,
1320
anchor, kind and tiering over the replayed set, and left three members of
1421
`ownir.Finding` carried by the goldens but not compared: `message`, `related`

‎docs/proposals/P-022-rust-core-migration.md‎

Lines changed: 8 additions & 8 deletions
Large diffs are not rendered by default.

‎docs/proposals/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ proposal is marked `done` with a pointer.
4141
| [P-017](P-017-multi-stack-frontends.md) | Multi-stack frontends (OwnTS / OwnJVM: OwnJava + OwnKotlin) | draft |
4242
| [P-020](P-020-ownts-react-effects.md) | OwnTS React effects profile (`Own.React`) — the effect-storm angle | draft |
4343
| [P-021](P-021-async-audit-pack.md) | Async audit pack (`Own.Async`) | draft |
44-
| [P-022](P-022-rust-core-migration.md) | Rust core migration: crate DAG, patterns, prior art, differential oracle (Python = golden) | in execution — steps 0–4 built (#214/#249); step 5a done (full diagnostic contract, #255 via #319/#320/#321); step 5b SARIF done (#256; `.ownreport.json` struck — a buffer report needing the AST, not a diagnostics surface); step 6a done (`spec/Bridge.md`, #258); step 6b underway (`own-lowered`/`own-bridge`, #259: lowering and MOS parity landed; strict-door validation complete at 216 controls with no known divergence — the first 0/0/0 proved to be the ledger agreeing with its own author, and the second omitted two families that a Python-first defensive-limit change (#326) had to close before the third could measure them; analysis wiring complete at the checkpoint-4 surface — `check_facts` through the real analyses, Layer 3 goldens built, with an executable exclusion ledger naming the protocol boundary, the `u32` coordinate boundary and the OD-1 door controls; **cp5 complete at its surface** — the replay now compares EVERY `Finding` member (the BR-V4 wording matrix and the BR-V5 evidence slices included) and every refusal in full, and a second fixture family freezes the BR-V9 rendered surfaces byte for byte, all against goldens none of which was regenerated; what remains for #259's final acceptance is row 4b (the obligation-protocol analysis) and the coordinate-domain decision. Every count is generated: `docs/generated/p022-cp4-census.md` and `docs/generated/p022-cp5-inventory.md`); step 7a shadow-mode INFRASTRUCTURE **complete for everything the row listed as sliceable now** — checkpoints 1–4 (`ownlang/repro.py` + `own-shadow`: canonical same-input `OwnIR` identity, the reproduction-artifact format, the engine protocol, the `AnalysisTrace` (#269) with stable-ID normalization, and first-divergence reduction over the lowered/MOS layers); the corpus digest-pinned and re-hashed with zero Python, its artifacts, traces and reductions reproduced byte-for-byte, every campaign fully caught, and the computed divergence classification zero on every axis over the lowered+MOS scope, with the declared-boundary status observations named — all of it counted in `docs/generated/p022-shadow-census.md` and `docs/generated/p022-shadow-mutations.md`, never here; the findings are recorded and closed as contract decisions. NOT shadow mode and not parity: the reducer REFUSES the verdict layer and records the refusal, since acceptance compares end diagnostics and stays blocked by #259, and #260's raw-byte same-input invariant is not proved either — cp1 establishes shared CANONICAL document identity, which is the weaker claim; three departures from the slice's brief (checkpoint grouping, the `-0` domain narrowing, `sha2`) are ratified in [the owner-decision ledger](../notes/p022-shadow-infra-owner-decisions.md); Python authoritative until cutover |
44+
| [P-022](P-022-rust-core-migration.md) | Rust core migration: crate DAG, patterns, prior art, differential oracle (Python = golden) | in execution — steps 0–4 built (#214/#249); step 5a done (full diagnostic contract, #255 via #319/#320/#321); step 5b SARIF done (#256; `.ownreport.json` struck — a buffer report needing the AST, not a diagnostics surface); step 6a done (`spec/Bridge.md`, #258); step 6b underway (`own-lowered`/`own-bridge`, #259: lowering and MOS parity landed; strict-door validation complete with no known divergence — the first 0/0/0 proved to be the ledger agreeing with its own author, and the second omitted two families that a Python-first defensive-limit change (#326) had to close before the third could measure them; analysis wiring complete at the checkpoint-4 surface — `check_facts` through the real analyses, Layer 3 goldens built, with an executable exclusion ledger naming each declared boundary; **cp5 complete at its surface** — the replay compares EVERY `Finding` member (the BR-V4 wording matrix and the BR-V5 evidence slices included) and every refusal in full, and a second fixture family freezes the BR-V9 rendered surfaces byte for byte, all against goldens none of which was regenerated; **row 4b complete** — the obligation-protocol analysis (OBL001–005) is ported into `own-analysis`, its typed values come from the ONE grammar in `own-ir` that the strict door already delegated to, an analysis-level fact-parity family freezes every violation member with zero Python, the bridge maps BR-P3 in its BR-V1 place, and both protocol documents are promoted out of the exclusion ledger without regenerating either golden; what remains for #259's final acceptance is the coordinate-domain decision. Every count is generated: `docs/generated/p022-cp4-census.md`, `docs/generated/p022-cp5-inventory.md` and `docs/generated/p022-cp4b-mutations.md`); step 7a shadow-mode INFRASTRUCTURE **complete for everything the row listed as sliceable now** — checkpoints 1–4 (`ownlang/repro.py` + `own-shadow`: canonical same-input `OwnIR` identity, the reproduction-artifact format, the engine protocol, the `AnalysisTrace` (#269) with stable-ID normalization, and first-divergence reduction over the lowered/MOS layers); the corpus digest-pinned and re-hashed with zero Python, its artifacts, traces and reductions reproduced byte-for-byte, every campaign fully caught, and the computed divergence classification zero on every axis over the lowered+MOS scope, with the declared-boundary status observations named — all of it counted in `docs/generated/p022-shadow-census.md` and `docs/generated/p022-shadow-mutations.md`, never here; the findings are recorded and closed as contract decisions. NOT shadow mode and not parity: the reducer REFUSES the verdict layer and records the refusal, since acceptance compares end diagnostics and stays blocked by #259, and #260's raw-byte same-input invariant is not proved either — cp1 establishes shared CANONICAL document identity, which is the weaker claim; three departures from the slice's brief (checkpoint grouping, the `-0` domain narrowing, `sha2`) are ratified in [the owner-decision ledger](../notes/p022-shadow-infra-owner-decisions.md); Python authoritative until cutover |
4545
| [P-023](P-023-architecture-guard.md) | Architecture guard (`Own.Arch`): rules.yaml intent model + dependency-graph gate + baseline ratchet | draft |
4646
| [P-024](P-024-security-audit-profile.md) | Security audit profile (external tools + SARIF adapters; rejects own scanner engine) | draft |
4747
| [P-025](P-025-obligation-protocols.md) | Obligation protocols (`Own.Protocols`): barrier-sensitive project invariants (OBL001–005) | first slice built (core + bridge + fixtures; extractor pending) |

‎scripts/render_checkpoint_status.py‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* `docs/generated/p022-cp5-mutations.md` — checkpoint 5's recorded mutation
2525
campaigns, one section per sub-checkpoint, through the same
2626
`summarize()` as every other campaign in the tree.
27+
* `docs/generated/p022-cp4b-mutations.md` — checkpoint 4b's two campaigns (the
28+
obligation ANALYSIS and its BRIDGE half), rendered the same way.
2729
* `docs/generated/p022-shadow-census.md` — the step-7a (#260/#269)
2830
shadow-mode INFRASTRUCTURE census, from
2931
`tests/shadow_census.compute_shadow_census()` over the committed
@@ -88,6 +90,7 @@
8890
CENSUS_MD = "p022-cp4-census.md"
8991
INVENTORY_MD = "p022-cp5-inventory.md"
9092
CP5_MUTATIONS_MD = "p022-cp5-mutations.md"
93+
CP4B_MUTATIONS_MD = "p022-cp4b-mutations.md"
9194
MUTATIONS_MD = "p022-cp4-mutations.md"
9295
SHADOW_CENSUS_MD = "p022-shadow-census.md"
9396
SHADOW_MUTATIONS_MD = "p022-shadow-mutations.md"
@@ -109,6 +112,14 @@
109112
("checkpoint 5.2 — the refusal text and the core message it quotes", "p022-cp5-2"),
110113
("checkpoint 5.3 — the rendered surfaces", "p022-cp5-3"),
111114
)
115+
# Checkpoint 4b, on the same one-campaign-per-sub-checkpoint rule: the analysis
116+
# and the bridge are measured separately because they fail separately — a walk
117+
# that decides wrongly and a wording that phrases wrongly are different defects
118+
# with different catchers.
119+
CP4B_CAMPAIGNS = (
120+
("checkpoint 4b.1 — the obligation analysis", "p022-cp4b-1"),
121+
("checkpoint 4b.2 — the bridge mapping (BR-P3)", "p022-cp4b-2"),
122+
)
112123
SELF = "scripts/render_checkpoint_status.py"
113124

114125

@@ -637,6 +648,19 @@ def fragments() -> tuple[dict[str, str], list[str]]:
637648
CP5_CAMPAIGNS)
638649
out[CP5_MUTATIONS_MD] = cp5
639650
problems.extend(f"mutation campaign {p}" for p in cp5_problems)
651+
cp4b, cp4b_problems = render_campaign_set(
652+
"# P-022 checkpoint 4b — mutation campaigns",
653+
"The obligation-protocol family, measured in two halves: the ANALYSIS "
654+
"(`own-analysis/src/obligation.rs` plus the half of the shared grammar it "
655+
"reads) and the BRIDGE mapping (BR-P3 — codes, wordings, identity "
656+
"derivations, the evidence slice and the tolerant-door rules). Every "
657+
"mutation edits a **production** surface (P-022 discipline 2) and every "
658+
"workspace member runs for every mutation (discipline 3: no fail-fast); the "
659+
"counts are derived from the recorded runs by "
660+
"`scripts/mutate_campaign.summarize()`, never typed.",
661+
CP4B_CAMPAIGNS)
662+
out[CP4B_MUTATIONS_MD] = cp4b
663+
problems.extend(f"mutation campaign {p}" for p in cp4b_problems)
640664
return out, problems
641665

642666

‎spec/Bridge.md‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,8 @@ committed regeneration path and a zero-Python steady state:
367367
shared cases — its `Rejected` golden pins the identical error text on both
368368
sides — so there are **no `rust_replay: false` snapshots left**. Layer 1
369369
landed in `own-ir` (#259 cp1: 216 controls, 0/0/0); Layer 3 is built and fully
370-
compared (below); #259 as a whole remains open on **row 4b** (the
371-
obligation-protocol analysis) and the coordinate-domain decision.
370+
compared (below); #259 as a whole remains open on the coordinate-domain
371+
decision alone, row 4b (the obligation-protocol analysis) having landed.
372372
- **Layer 3 — final normalized diagnostics.** The findings list per facts
373373
fixture, and its SARIF/github/msbuild renderings — the outer contract, in
374374
**two families**. Built at #259 cp4, fully compared at cp5:
@@ -399,11 +399,14 @@ committed regeneration path and a zero-Python steady state:
399399
SARIF key order is part of this surface.
400400

401401
The manifest's `rust_replay_excluded` ledger names the documents the Rust
402-
core **refuses by a declared boundary** — a protocol-bearing document (OBL
403-
analysis not ported), a coordinate outside the core's `u32` line domain, a
404-
shape the typed Rust door rejects before the bridge runs (OD-1) — each with
405-
its reason and an expectation the replay executes, so an exclusion cannot
406-
rot. The `summaries` dump (INF-R1) covers the MOS sub-surface. Which BR-V4
402+
core **refuses by a declared boundary** — a coordinate outside the core's
403+
`u32` line domain, a shape the typed Rust door rejects before the bridge runs
404+
(OD-1) — each with its reason and an expectation the replay executes, so an
405+
exclusion cannot rot. It listed a third boundary until #259 checkpoint 4b:
406+
a protocol-bearing document, which the bridge refused rather than answer for
407+
with the OBL analysis unported. Both such documents are now **promoted** —
408+
the family is ported (BR-P3), and a re-declared exclusion is a red build
409+
rather than a note, because the replay runs every entry it names. The `summaries` dump (INF-R1) covers the MOS sub-surface. Which BR-V4
407410
wording, BR-V5 slice family and BR-V9 rule the corpus reaches — and the
408411
recorded disposition of every one it does not — is the generated ledger
409412
[`p022-cp5-inventory.md`](../docs/generated/p022-cp5-inventory.md).
@@ -452,7 +455,8 @@ Five points belong to this spec rather than to those notes.
452455
separately; this composition does not.
453456

454457
Nothing there is shadow mode: comparing end diagnostics as an acceptance
455-
surface is #260's acceptance and is blocked on #259 (cp5 and 4b).
458+
surface is #260's acceptance and is blocked on #259 — on its final acceptance,
459+
now that cp5 and 4b have both landed.
456460

457461
Regeneration: each layer gets a `--write` mode mirroring
458462
`tests/test_cfg_fixtures.py`; a stale committed fixture is a red build; the

‎spec/BridgeBehaviorMatrix.md‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
> diagnostics, S = the `summaries` dump) the Rust port must replay it at. A
1111
> layer marked **L3 ✅** is one whose substance the Rust replay now compares in
1212
> full rather than carries — the BR-V4 wording matrix and the BR-V9 renderings,
13-
> which #259 cp4 left deferred and cp5 proved.
13+
> which #259 cp4 left deferred and cp5 proved, and the BR-P3 protocol rows,
14+
> which cp4b ported and promoted out of the exclusion ledger.
1415
> **No family may be silently omitted here**; a new `test_ownir.py` family
1516
> without a row (or vice-versa) is a red build in spirit — reviewers enforce
1617
> it until a generated cross-check exists (see OD-7).
@@ -76,7 +77,9 @@
7677
|---|---|---|---|---|
7778
| DI graph finders' verdict sets + messages + anchor metadata (DI001/002/003/004/005 unit layer) | `ownlang/di.py` (not the bridge) | BR-B1, BR-P1 | L805–L1048 (18) | (core suite) |
7879
| advisory codes OWN051/OWN052 registered in `TITLES` (spec↔code drift guard) | `diagnostics.TITLES` | INF-P2/P3 | L1937 | — |
79-
| effects re-validation skip-not-coerce; protocol first-wins on tolerant door | `_effect_findings`, `_protocol_findings` | BR-D2, BR-P2/P3 | (pinned in `test_effects.py` / `test_obligations.py`) | L3 |
80+
| effects re-validation skip-not-coerce; protocol first-wins on tolerant door | `_effect_findings`, `_protocol_findings` | BR-D2, BR-P2/P3 | (pinned in `test_effects.py` / `test_obligations.py`) | L3 ✅ |
81+
| obligation protocols: the lattice, the leaf order, the exits, the loop's single emission, the evidence and the sort key | `ownlang/obligations.py` (not the bridge) | BR-B1, BR-P3 | `test_obligations.py` §1 + `tests/test_obligation_fact_parity.py` | (core suite) |
82+
| protocol verdict mapping: `(kind, definite)` → OBL001–004, the four line-free wordings, component/handler, the opened→barrier(→late-close) slice, the anchorless OBL005 | `_protocol_findings`, `_protocol_message` | BR-P3, BR-V4/V5/V6 | `test_obligations.py` §3 + the `verdict_protocol_*` Layer 3 cases | L3 ✅ |
8083

8184
## (e) Verdict mapping
8285

@@ -141,9 +144,14 @@ and the BR-V5 `related`/`flow` slices — and every refusal in full; and
141144
directly-pinned end-to-end surface, and no row's substance is carried without
142145
being compared. Which wording, slice family and rendering rule the corpus
143146
reaches — and the recorded disposition of each one it cannot — is the generated
144-
ledger [`p022-cp5-inventory.md`](../docs/generated/p022-cp5-inventory.md). Two
145-
row families are outside the replayed set by declaration, recorded in the
146-
manifest's `rust_replay_excluded` ledger with an executable expectation: the
147-
protocol rows (§4 BR-P3 — the OBL analysis is not ported, and the bridge
148-
refuses a protocol-bearing document rather than return an incomplete list) and
149-
the tolerant-door coercions the typed Rust constructor cannot reach (OD-1).
147+
ledger [`p022-cp5-inventory.md`](../docs/generated/p022-cp5-inventory.md).
148+
The **protocol rows** (§4 BR-P3) were the first of two row families outside the
149+
replayed set: the OBL analysis had no port, so the bridge refused a
150+
protocol-bearing document rather than return an incomplete list. #259
151+
checkpoint 4b closed that — the analysis is `own-analysis`'s, the typed values
152+
come from the one grammar in `own-ir`, the bridge maps them, and both reference
153+
documents are promoted out of `rust_replay_excluded` and replayed against the
154+
goldens exactly as they were committed. What is still outside the replayed set,
155+
recorded in that ledger with an executable expectation, is the coordinate
156+
boundary (a decision #259 owes) and the tolerant-door coercions the typed Rust
157+
constructor cannot reach (OD-1).

‎tests/fixtures/repro/manifest.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
"name": "protocol_isloaded_violation",
126126
"corpus": "ownir",
127127
"pins": [
128-
"a document the Rust bridge refuses by a declared #259 boundary (the obligation-protocol analysis is not ported) but the reference captures in full — the artifact records one engine's capture and takes no side on the other's"
128+
"a document declaring an obligation protocol: the Rust bridge REFUSED it by a declared #259 boundary until checkpoint 4b ported the OBL analysis, and now produces the verdict layer like the reference. The artifact records each engine's own capture and takes no side on the other's, so what the promotion changed here is one engine's status, not a comparison"
129129
]
130130
},
131131
{

0 commit comments

Comments
 (0)