You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement rust/crates/own-bridge as the production OwnIR-to-core boundary, following the normative contract from #258 and preserving Python behavior exactly.
The bridge consumes OwnIR facts, validates and lowers them into the Rust core, performs interprocedural MOS inference, drives own-analysis, and maps correct analysis results into the common diagnostic model.
It must not create cycles or move presentation/analysis logic into the bridge.
Checkpoint status
Per the status-drift rule in #250, this body is a status surface and moves together with docs/proposals/P-022-rust-core-migration.md and the proposals index. The list below gained a 4b at the cp4 review: none of cp1–cp5 named the obligation-protocol analysis, while final acceptance requires it. Reconciled at 21fb0c3 (PR #341 merge) — final acceptance reached; closed by hand at that merge.
State of this issue, for the record. It was closed by automation when PR #339 merged: GitHub's keyword parser read that PR's own sentence "does not close #259" as close #259 — negation is not parsed — linked the PR in the Development panel, and closed the issue on merge while its final acceptance was still open. It was reopened, and it is now closed by hand, at the #341 merge, because final acceptance is reached. A checkpoint PR references an issue with Refs #N and never places a closing keyword before the number, negated or not — an issue's open/closed bit is a status surface too.
checkpoint
status
1 — typed OwnIR validation
complete — no known strict-door divergence (PR #325); a fourth census at final acceptance (PR #341)
complete — Layer 3 parity over the measured set, protocol family included (PR #340)
5 — full fact-to-verdict parity
complete at the cp5 surface — every Finding member, every refusal in full, the rendered surfaces byte for byte (PR #339)
final acceptance
reached (PR #341) — the coordinate-domain contract landed Python-first and mirrored in the port; the exclusion ledger names only the two OD-1 door controls (#294)
The wording this issue has earned, and no more:#259 final acceptance reached: Layer 3 parity over the full#258 family inventory at the full Finding and the rendered surfaces; declared boundary: the two OD-1 door controls (#294), measured, not open work. Not "shadow mode" (that is #260's acceptance, blocked on its own two decisions), not "P-022 done", not "Rust is the default" (#262's cutover). Counts live only in docs/generated/; the record is docs/notes/p022-bridge-verdict-final-acceptance.md.
Checkpoint 1: typed OwnIR validation
Implement:
serde types for the current schema;
version checks;
additive optional-field handling;
unknown vocabulary failure rules;
reference/location validation;
deterministic loading;
safe errors for untrusted input.
Acceptance
all valid Python fixtures accepted;
all invalid controls rejected with matching error class/category;
no panic on malformed JSON/OwnIR;
limits or defensive parsing documented for externally supplied inputs.
Status: complete via PR #325 — 216 controls, nothing excluded, no known strict-door divergence. The detail worth keeping (three censuses; a ledger that agreed with its own author; a taxonomy taken from where the reference raises rather than from the mechanism violated) is recorded in #250 and in P-022. A fourth census landed with final acceptance (PR #341): the coordinate domain flipped the ledger's accept-twins at the signed-64 edges and at a negative line into Location rejections, with the old why quoted beside the new one, and added a domain control per line-bearing field at every nesting shape. The count is generated, never typed: p022-cp1-census.md. The ledger compares accept/reject and, on rejection, the category — never the message text; that is deliberate on both sides (tests/test_ownir_validation_fixtures.py, own-ir/tests/validation_replay.rs) and final acceptance did not move it.
Checkpoint 2: fact lowering
Implement:
OwnIR functions/types/resources;
handle/RID minting;
facts → AST/CFG;
local map and kill-on-rebind;
branches, loops and merge preparation;
source-location preservation;
normalized lowered representation for differential testing.
ordering and ID permutations that are non-semantic do not alter output;
no analysis algorithm appears in the bridge.
Status: complete — the rust_replay cases are byte-exact. Since PR #341 the Layer 3 replay additionally asserts the §4.2 coordinate domain at Layer 2 over every replayed case.
every mapped Python MOS test family has a frozen differential control;
generated call-graph controls cover cycles, overloads and fallback;
unknown behavior remains conservative;
output is deterministic.
Status: complete for the stage-1 scalar-metadata domain — the *.summaries.json goldens are byte-identical. Container-valued metadata is declared outside that domain (a separate #294-class door decision), not a silent gap.
Checkpoint 4: analysis wiring
Feed real bridge facts into:
ownership;
lifetime;
buffer policy;
effect;
DI.
The bridge must preserve analysis-selected primary anchors. It must not duplicate effect or DI graph algorithms.
Required controls
EFF001 through real OwnIR facts;
DI001–DI005 through real OwnIR facts;
DI004 call-site anchor;
DI005 cache-site anchor;
duplicate-site last-wins;
multi-file ordering;
ownership/lifetime cases already pinned by .own parity where representable through OwnIR.
Status: complete at the checkpoint-4 surface — via PR #336. Deliberately not "verdict parity complete": the claim was parity at the cp4 surface, over a measured set whose complement was named.
own_bridge::check_facts runs real OwnIR facts through the ported analyses (check_module: ownership, lifetime, buffer policy; the DI and effect finders from own-analysis) and maps ERROR-tier verdicts back onto fact handles through the verdict's subject, keeping the reference's map-or-raise refusal and the analysis-selected anchors (BR-V1/V2/V3/V5, BR-P1/P2, the OWN050/051/052 side paths, tiering and suppression BR-V6, dedup and the stable sort BR-V7/V8). Landing it needed one core change: own-analysis now stamps subject exactly where analysis.py/lifetimes.py do.
The comparison surface at cp4 was identity, anchor, kind and tiering — over the frozen Layer 3 ledger (tests/fixtures/verdicts/); cp5 widened it to every member (below). The differential over the replayed set is asserted, not restated here: the Rust replay compares every replayed case against its golden, collects every divergence without fail-fast, and fails the build if one exists — so a green replay is the claim. What sat outside that set was a named exclusion ledger the replay executes, not a silent gap, and two of its three families have since been promoted:
One declared comparison boundary on refusals at cp4: the map-or-raise text was compared up to its message= member, because the core's messages were still titles. Removed at cp5.2 — refusals now compare in full.
The measured census is not typed on any status surface — it is generated from the ledger by scripts/render_checkpoint_status.py and held in sync by the Python test gate: docs/generated/p022-cp4-census.md, with the recorded mutation campaign in docs/generated/p022-cp4-mutations.md.
Steady-state command (zero Python): cd rust && cargo test -p own-bridge --test verdicts.
Checkpoint 4b: protocol analysis (OBL001–005)
Port ownlang/obligations.py — the obligation-protocol analysis — and admit the protocol-bearing documents into the measured set.
This checkpoint did not exist in the original list, and its absence was the gap: none of cp1–cp5 names the protocol analysis, while Final acceptance below requires the full #258 family inventory, which includes the protocol rows (BR-P3). obligations.py is a path-sensitive analysis in its own right — lattice, walker, matching — so it is a checkpoint of its own rather than a fourth job for cp5, whose scope is messages, evidence and rendering. Folding a whole analysis family into the last checkpoint would have made that checkpoint a bag.
Acceptance
OBL001–005 produced from real OwnIR facts through the bridge;
the protocol-bearing documents move out of the exclusion ledger into the replayed set;
no protocol algorithm is duplicated in the bridge.
Status: complete via PR #340 — Layer 3 parity over the measured set, protocol family included.
OBL001–005 come from real OwnIR facts through the bridge. The analysis is own-analysis/src/obligation.rs (BR-B1 — the analysis owns its verdict): the {OPEN, CLOSED} set lattice with min-line provenance, the opens → closes → barriers leaf order with allow beating barrier, the never-invent asymmetry of an opaque write, exits anchored at the acquire, the loop's silent fixpoint and single emitting pass, the close-line evidence and the four-part sort key. The bridge maps BR-P3 in its BR-V1 place (after effects, before OWN050): the (kind, definite) table, the four deliberately line-free wordings, the identity derivations, the anchorless advisory OBL005 and the opened → barrier (→ late close) slice. refuse_protocols is gone.
Both protocol-bearing reference documents are promoted out of rust_replay_excluded into the replayed set, and neither golden was regenerated to get there.
No protocol algorithm lives in the bridge, and there is one grammar.own-ir/src/protocol.rs grew from validate-only to validate-and-construct, so the strict door and the analysis consume the same typed Protocol/MethodEvents values and cannot drift into two readings of one grammar; no strict-door error text or category moved (the cp1 ledger's protocol controls stayed green). Since PR feat(ownir): bound source coordinates to int32 and mirror it in the bridge (#259 final acceptance) #341 the grammar takes a Door: type and representability stay grammar and still skip a malformed entry whole; only the coordinate domain follows the door.
Oracle. A third analysis-level fact-parity family beside DI and effects: tests/test_obligation_fact_parity.py runs the reference's own check_protocols/unmatched_scopes and freezes every violation whole into tests/fixtures/obligation_fact_parity.json; own-analysis/tests/obligation_parity.rs replays the same raw documents with zero Python, so each side builds the values with its own half of the grammar. Synthetic Layer 3 and rendered controls close every row the corpus could not reach — the corpus had reached exactly one shape — insertion-stable.
Measured and recorded rather than claimed (note §6.7). BR-V5's "a slice shorter than two steps is dropped" is not applied on the protocol path: a leak off the end of a method carries a one-step slice; the port reproduces the reference, and whether the spec sentence or the code moves is a Python-first decision still owed (it does not block this issue). The family's append position is unobservable end to end, because the BR-V8 sort key's code component decides first. The tolerant door's protocol rules (skip a malformed protocol, skip a malformed method entry, first-wins on a duplicate name) are reachable end to end and pinned by replay — unlike the OD-1 effect-entry case cp4 recorded.
path
line
code
severity
message
subject
resource_kind
ordered Evidence
After #256, also compare canonical report JSON and SARIF.
Status: complete at the cp5 surface via PR #339 — Layer 3 parity over the measured set at the full Finding and the rendered surfaces. No pre-existing golden was regenerated or edited.
5.0 — inventory.tests/verdict_surface_inventory.py: one ledger row per BR-V4 wording branch with who owns the string, per BR-V5 evidence family and degradation rule, per BR-V9 rule, each matched against the committed goldens so coverage is computed from the tree. A row at zero over the replayed set is a branch that must get a control, not one that may be declared. Generated: p022-cp5-inventory.md.
5.1 — the full Finding.own_bridge::Finding carries message, related, flow; the BR-V4 matrix and the BR-V5 slice builders are ported; the replay compares every member against the goldens as committed. Branches no facts document can reach are pinned by controls whose expected text is read from tests/fixtures/unreachable_branches.json — the reference's own output, recorded by tests/test_unreachable_branch_probe.py (re-runnable; one source of truth, so the two sides cannot drift into agreeing with each other instead of with Python).
5.2 — the refusal text.own_cfg::Diag carries the resolver's message the BR-V3 map-or-raise line interpolates; the message= cut is gone and refusals compare in full. Removing the cut exposed a port defect it had been hiding — py_repr quoting unconditionally with ' where CPython switches to " — fixed in Rust and pinned against CPython's own output. The unported remainder is an Option: a code whose text is missing renders as its title, and the first golden refusing on it goes red demanding the message.
5.3 — the rendered surfaces (BR-V9).ownlang/renders.py (an observer beside verdicts.py), tests/fixtures/verdict_renders/ under its own frozen ledger, and a Rust replay comparing the bytes — SARIF key order is part of the surface, so the port emits through typed structs. codeFlows reuses own_diagnostics::code_flow; relatedLocations deliberately does not (the core's builder drops an empty-file step, the reference's inline comprehension does not — a golden pins the difference).
5.4 — surfaces and campaigns. Re-run on a clean tree: p022-cp5-mutations.md. The cp4 campaign re-run against the cp5 tree turned its BR-V7 dedup-key mutations from caught to survived — putting message in the key made several members unobservable at the output — so those controls now drive dedup directly. Worth keeping: a comparison surface that gains a member can lose controls for the members it subsumes.
What cp5 did not claim, and what has happened to each since: the protocol family (landed at 4b), the u32 coordinate boundary (decided and landed at final acceptance, PR #341), the OD-1 door controls (a declared boundary, unchanged). own-shadow was not extended to Layer 3 — its verdict capture declares full, and the reducer still refuses the layer.
Final acceptance: the coordinate-domain contract (PR #341)
The last item final acceptance owed was a contract decision, not one more port: §4.2 bounded a source coordinate at signed 64 bits while the core holds a line as u32, and four verdict_boundary_* controls sat in the exclusion ledger because of the gap. The decision was the owner's and it landed Python-first, the way #326 did:
D1 — the domain. Every line is an integer in [0, 2147483647]; 0 is legal and means "unknown / file-level", because it is the reference's own default for an absent line and the corpus carries it everywhere; a negative line is rejected (no producer emits one); every column is in [1, 2147483647] or absent. The bound is int32 because int32 is the line type of every consumer this project feeds (Roslyn, LSP, .NET diagnostics) — never "Rust holds u32, so the reference is wrong".
D2 — where. The strict door (load()) rejects an out-of-domain coordinate as Location, for every line-bearing field — including the two §4.2 had recorded as validated nowhere (components[].subscriptions[].line, the flow-op line at every nesting shape), which now get type validation too. The representable-form rule (signed 64 bits, Shape) is unchanged and checked first; keeping the two axes apart is what stops a domain violation being filed as a shape one.
D3 — the tolerant door.check_facts() degrades an out-of-domain line to 0 and a column to absent — degrade, never clamp — exactly the §4.1 column precedent. The Rust side mirrors it: own-ir at the strict door and in the protocol grammar (a Door parameter, not a second parser), own-bridge in its lowering and readers. The four boundary controls left rust_replay_excluded with goldens regenerated by Python; the ledger now names only the two OD-1 door controls.
Measured rather than claimed (note §5–§6): the Rust column path had no u32 boundary to find; ast::core_line's degrade is unreachable end to end because the lowering degrades one layer earlier, so its control is a direct one that says so; a tolerant column reader on the Rust side had no upper bound and gained one so the two doors cannot disagree; the cp1 ledger compares category, never message text, and that surface did not move. Evidence, generated never typed: p022-cp1-census.md, p022-coord-census.md, p022-coord-mutations.md, with every earlier campaign re-run against the new tree.
Three tails from the final-acceptance review are carried to #260, not left here: own-bridge has two identical private tolerant line readers (lower.rs, verdict.rs) that should be one; the final-acceptance note's §3.2 diff stat predates its docs commit; and a campaign's expected_catchers can rot silently between runs (shadow-cp4's M61 did, after 4b), which --validate does not detect.
Fixture layers
validation acceptance/rejection;
normalized lowered representation;
MOS summaries;
final diagnostics;
report/SARIF where available.
All fixtures are Python-authored. Rust steady-state tests invoke zero Python.
Guardrails
No schema redesign.
No new diagnostic behavior.
No bridge-side repair of wrong analysis locations/codes.
No duplication of ownership/lifetime/effect/DI algorithms.
No CLI cutover.
No performance pass before parity and profiling.
Python remains authoritative.
PR/checkpoint packet
Each checkpoint reports:
Python-only:
Rust-only:
Changed:
Ordering-only:
Unexplained:
Fixture changed:
Acceptance changed:
Production DAG changed:
Unexplained must be zero before proceeding.
Final acceptance
own-bridge exists in the workspace with the allowed DAG.
Validation, lowering, MOS, analysis wiring and final verdict parity are green — each at its declared surface: cp1 with no known strict-door divergence (four censuses); cp2 byte-exact; cp3 over the stage-1 scalar-metadata domain; cp4 + cp5 as Layer 3 parity at the full Finding and the rendered surfaces.
#259 final acceptance reached: Layer 3 parity over the full #258 family inventory at the full Finding and the rendered surfaces; declared boundary: the two OD-1 door controls (#294), measured, not open work.
Parent: #250
Recommended tier: strong
Blocked by: #258
Preferably after: #255 and #256
Goal
Implement
rust/crates/own-bridgeas the production OwnIR-to-core boundary, following the normative contract from #258 and preserving Python behavior exactly.The bridge consumes OwnIR facts, validates and lowers them into the Rust core, performs interprocedural MOS inference, drives
own-analysis, and maps correct analysis results into the common diagnostic model.Production dependencies
The crate may depend on:
It must not create cycles or move presentation/analysis logic into the bridge.
Checkpoint status
Per the status-drift rule in #250, this body is a status surface and moves together with
docs/proposals/P-022-rust-core-migration.mdand the proposals index. The list below gained a 4b at the cp4 review: none of cp1–cp5 named the obligation-protocol analysis, while final acceptance requires it. Reconciled at21fb0c3(PR #341 merge) — final acceptance reached; closed by hand at that merge.Findingmember, every refusal in full, the rendered surfaces byte for byte (PR #339)The wording this issue has earned, and no more: #259 final acceptance reached: Layer 3 parity over the full #258 family inventory at the full
Findingand the rendered surfaces; declared boundary: the two OD-1 door controls (#294), measured, not open work. Not "shadow mode" (that is #260's acceptance, blocked on its own two decisions), not "P-022 done", not "Rust is the default" (#262's cutover). Counts live only indocs/generated/; the record isdocs/notes/p022-bridge-verdict-final-acceptance.md.Checkpoint 1: typed OwnIR validation
Implement:
Acceptance
Status: complete via PR #325 — 216 controls, nothing excluded, no known strict-door divergence. The detail worth keeping (three censuses; a ledger that agreed with its own author; a taxonomy taken from where the reference raises rather than from the mechanism violated) is recorded in #250 and in P-022. A fourth census landed with final acceptance (PR #341): the coordinate domain flipped the ledger's accept-twins at the signed-64 edges and at a negative line into
Locationrejections, with the oldwhyquoted beside the new one, and added a domain control per line-bearing field at every nesting shape. The count is generated, never typed:p022-cp1-census.md. The ledger compares accept/reject and, on rejection, the category — never the message text; that is deliberate on both sides (tests/test_ownir_validation_fixtures.py,own-ir/tests/validation_replay.rs) and final acceptance did not move it.Checkpoint 2: fact lowering
Implement:
Acceptance
Status: complete — the
rust_replaycases are byte-exact. Since PR #341 the Layer 3 replay additionally asserts the §4.2 coordinate domain at Layer 2 over every replayed case.Checkpoint 3: interprocedural MOS
Implement the #258 contract for:
sigresolution and fallback;Acceptance
Status: complete for the stage-1 scalar-metadata domain — the
*.summaries.jsongoldens are byte-identical. Container-valued metadata is declared outside that domain (a separate #294-class door decision), not a silent gap.Checkpoint 4: analysis wiring
Feed real bridge facts into:
The bridge must preserve analysis-selected primary anchors. It must not duplicate effect or DI graph algorithms.
Required controls
.ownparity where representable through OwnIR.Status: complete at the checkpoint-4 surface — via PR #336. Deliberately not "verdict parity complete": the claim was parity at the cp4 surface, over a measured set whose complement was named.
own_bridge::check_factsruns real OwnIR facts through the ported analyses (check_module: ownership, lifetime, buffer policy; the DI and effect finders fromown-analysis) and maps ERROR-tier verdicts back onto fact handles through the verdict'ssubject, keeping the reference's map-or-raise refusal and the analysis-selected anchors (BR-V1/V2/V3/V5, BR-P1/P2, the OWN050/051/052 side paths, tiering and suppression BR-V6, dedup and the stable sort BR-V7/V8). Landing it needed one core change:own-analysisnow stampssubjectexactly whereanalysis.py/lifetimes.pydo.The comparison surface at cp4 was identity, anchor, kind and tiering — over the frozen Layer 3 ledger (
tests/fixtures/verdicts/); cp5 widened it to every member (below). The differential over the replayed set is asserted, not restated here: the Rust replay compares every replayed case against its golden, collects every divergence without fail-fast, and fails the build if one exists — so a green replay is the claim. What sat outside that set was a named exclusion ledger the replay executes, not a silent gap, and two of its three families have since been promoted:u32line-domain representability boundary — refused, never clamped, until the coordinate-domain contract landed; promoted at final acceptance (PR feat(ownir): bound source coordinates to int32 and mirror it in the bridge (#259 final acceptance) #341): the domain is now the reference's, and both doors degrade an out-of-domain coordinate the same way;One declared comparison boundary on refusals at cp4: the map-or-raise text was compared up to its
message=member, because the core's messages were still titles. Removed at cp5.2 — refusals now compare in full.The measured census is not typed on any status surface — it is generated from the ledger by
scripts/render_checkpoint_status.pyand held in sync by the Python test gate:docs/generated/p022-cp4-census.md, with the recorded mutation campaign indocs/generated/p022-cp4-mutations.md.Steady-state command (zero Python):
cd rust && cargo test -p own-bridge --test verdicts.Checkpoint 4b: protocol analysis (OBL001–005)
Port
ownlang/obligations.py— the obligation-protocol analysis — and admit the protocol-bearing documents into the measured set.This checkpoint did not exist in the original list, and its absence was the gap: none of cp1–cp5 names the protocol analysis, while Final acceptance below requires the full #258 family inventory, which includes the protocol rows (BR-P3).
obligations.pyis a path-sensitive analysis in its own right — lattice, walker, matching — so it is a checkpoint of its own rather than a fourth job for cp5, whose scope is messages, evidence and rendering. Folding a whole analysis family into the last checkpoint would have made that checkpoint a bag.Acceptance
Status: complete via PR #340 — Layer 3 parity over the measured set, protocol family included.
own-analysis/src/obligation.rs(BR-B1 — the analysis owns its verdict): the{OPEN, CLOSED}set lattice with min-line provenance, the opens → closes → barriers leaf order with allow beating barrier, the never-invent asymmetry of an opaque write, exits anchored at the acquire, the loop's silent fixpoint and single emitting pass, the close-line evidence and the four-part sort key. The bridge maps BR-P3 in its BR-V1 place (after effects, before OWN050): the(kind, definite)table, the four deliberately line-free wordings, the identity derivations, the anchorless advisory OBL005 and the opened → barrier (→ late close) slice.refuse_protocolsis gone.rust_replay_excludedinto the replayed set, and neither golden was regenerated to get there.own-ir/src/protocol.rsgrew from validate-only to validate-and-construct, so the strict door and the analysis consume the same typedProtocol/MethodEventsvalues and cannot drift into two readings of one grammar; no strict-door error text or category moved (the cp1 ledger's protocol controls stayed green). Since PR feat(ownir): bound source coordinates to int32 and mirror it in the bridge (#259 final acceptance) #341 the grammar takes aDoor: type and representability stay grammar and still skip a malformed entry whole; only the coordinate domain follows the door.tests/test_obligation_fact_parity.pyruns the reference's owncheck_protocols/unmatched_scopesand freezes every violation whole intotests/fixtures/obligation_fact_parity.json;own-analysis/tests/obligation_parity.rsreplays the same raw documents with zero Python, so each side builds the values with its own half of the grammar. Synthetic Layer 3 and rendered controls close every row the corpus could not reach — the corpus had reached exactly one shape — insertion-stable.verdictslayer moves fromrefusedtoproduced— the same shape of change feat(bridge): #259 cp5 — the full Finding, the refusal text and the rendered surfaces, proven #339 recorded forpartial→full. Theown-shadowreducer still refuses Layer 3: P-022 step 7a: add dual-engine shadow mode and zero-diff reproduction artifacts #260's boundary, unmoved.p022-cp4-census.md,p022-cp5-inventory.md,p022-cp4b-mutations.md; the checkpoint note.Checkpoint 5: full fact-to-verdict parity
Compare normalized:
After #256, also compare canonical report JSON and SARIF.
Status: complete at the cp5 surface via PR #339 — Layer 3 parity over the measured set at the full
Findingand the rendered surfaces. No pre-existing golden was regenerated or edited.tests/verdict_surface_inventory.py: one ledger row per BR-V4 wording branch with who owns the string, per BR-V5 evidence family and degradation rule, per BR-V9 rule, each matched against the committed goldens so coverage is computed from the tree. A row at zero over the replayed set is a branch that must get a control, not one that may be declared. Generated:p022-cp5-inventory.md.Finding.own_bridge::Findingcarriesmessage,related,flow; the BR-V4 matrix and the BR-V5 slice builders are ported; the replay compares every member against the goldens as committed. Branches no facts document can reach are pinned by controls whose expected text is read fromtests/fixtures/unreachable_branches.json— the reference's own output, recorded bytests/test_unreachable_branch_probe.py(re-runnable; one source of truth, so the two sides cannot drift into agreeing with each other instead of with Python).own_cfg::Diagcarries the resolver's message the BR-V3 map-or-raise line interpolates; themessage=cut is gone and refusals compare in full. Removing the cut exposed a port defect it had been hiding —py_reprquoting unconditionally with'where CPython switches to"— fixed in Rust and pinned against CPython's own output. The unported remainder is anOption: a code whose text is missing renders as its title, and the first golden refusing on it goes red demanding the message.ownlang/renders.py(an observer besideverdicts.py),tests/fixtures/verdict_renders/under its own frozen ledger, and a Rust replay comparing the bytes — SARIF key order is part of the surface, so the port emits through typed structs.codeFlowsreusesown_diagnostics::code_flow;relatedLocationsdeliberately does not (the core's builder drops an empty-file step, the reference's inline comprehension does not — a golden pins the difference).p022-cp5-mutations.md. The cp4 campaign re-run against the cp5 tree turned its BR-V7 dedup-key mutations from caught to survived — puttingmessagein the key made several members unobservable at the output — so those controls now drivededupdirectly. Worth keeping: a comparison surface that gains a member can lose controls for the members it subsumes.What cp5 did not claim, and what has happened to each since: the protocol family (landed at 4b), the
u32coordinate boundary (decided and landed at final acceptance, PR #341), the OD-1 door controls (a declared boundary, unchanged).own-shadowwas not extended to Layer 3 — its verdict capture declaresfull, and the reducer still refuses the layer.Final acceptance: the coordinate-domain contract (PR #341)
The last item final acceptance owed was a contract decision, not one more port: §4.2 bounded a source coordinate at signed 64 bits while the core holds a line as
u32, and fourverdict_boundary_*controls sat in the exclusion ledger because of the gap. The decision was the owner's and it landed Python-first, the way #326 did:lineis an integer in[0, 2147483647];0is legal and means "unknown / file-level", because it is the reference's own default for an absent line and the corpus carries it everywhere; a negative line is rejected (no producer emits one); everycolumnis in[1, 2147483647]or absent. The bound is int32 because int32 is the line type of every consumer this project feeds (Roslyn, LSP, .NET diagnostics) — never "Rust holdsu32, so the reference is wrong".load()) rejects an out-of-domain coordinate as Location, for every line-bearing field — including the two §4.2 had recorded as validated nowhere (components[].subscriptions[].line, the flow-oplineat every nesting shape), which now get type validation too. The representable-form rule (signed 64 bits, Shape) is unchanged and checked first; keeping the two axes apart is what stops a domain violation being filed as a shape one.check_facts()degrades an out-of-domain line to0and a column to absent — degrade, never clamp — exactly the §4.1 column precedent. The Rust side mirrors it:own-irat the strict door and in the protocol grammar (aDoorparameter, not a second parser),own-bridgein its lowering and readers. The four boundary controls leftrust_replay_excludedwith goldens regenerated by Python; the ledger now names only the two OD-1 door controls.Measured rather than claimed (note §5–§6): the Rust column path had no
u32boundary to find;ast::core_line's degrade is unreachable end to end because the lowering degrades one layer earlier, so its control is a direct one that says so; a tolerant column reader on the Rust side had no upper bound and gained one so the two doors cannot disagree; the cp1 ledger compares category, never message text, and that surface did not move. Evidence, generated never typed:p022-cp1-census.md,p022-coord-census.md,p022-coord-mutations.md, with every earlier campaign re-run against the new tree.Three tails from the final-acceptance review are carried to #260, not left here:
own-bridgehas two identical private tolerant line readers (lower.rs,verdict.rs) that should be one; the final-acceptance note's §3.2 diff stat predates its docs commit; and a campaign'sexpected_catcherscan rot silently between runs (shadow-cp4's M61 did, after 4b), which--validatedoes not detect.Fixture layers
All fixtures are Python-authored. Rust steady-state tests invoke zero Python.
Guardrails
PR/checkpoint packet
Each checkpoint reports:
Unexplainedmust be zero before proceeding.Final acceptance
own-bridgeexists in the workspace with the allowed DAG.Findingand the rendered surfaces.own-shadowreducer still refuses the verdict layer by P-022 step 7a: add dual-engine shadow mode and zero-diff reproduction artifacts #260's own boundary.#259 final acceptance reached: Layer 3 parity over the full #258 family inventory at the full
Findingand the rendered surfaces; declared boundary: the two OD-1 door controls (#294), measured, not open work.