From 69156e620aff78457d6208abb2f03b26fbcf2c91 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 17:18:00 +0000 Subject: [PATCH 1/2] =?UTF-8?q?docs(P-022):=20#251=20=E2=80=94=20reconcile?= =?UTF-8?q?=20the=20roadmap=20and=20crate=20status=20after=20#214/#249?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The proposal still opened with "draft / exploratory — no Rust code committed yet" while rust/ has five implemented, parity-gated workspace crates. Docs only, per the #251 brief; the historical design rationale is untouched — status is reconciled with markers and a status block, not rewrites: * top-level status -> "in execution" + an implementation-status block: own-ir, own-syntax, own-cfg (incl. the canonical CFG-JSON seam + cfg_parity fixtures the strategy text said "still needs building"), own-diagnostics (data-only layer), own-analysis (solver + ownership/ lifetime/buffer/effect/DI — the #214/#249 analysis-heart milestone); * every remaining production step points to exactly one #250 child issue: 5a #255, 5b #256, 5c #257, 6a #258 (delivered: spec/Bridge.md + BridgeBehaviorMatrix.md, review via PR #297), 6b #259, 7a #260 (+#269 AnalysisTrace support), 7b #261, 8 cutover #262; Datalog/Ascent stays post-cutover with no issue, deliberately; * migration-strategy steps 0-4 marked done in place; the per-layer-seams paragraph and the Placement footer get status notes instead of rewrites; * proposals/README.md index row updated to match. Python stays authoritative until #262's cutover gate; the verdict-changing inference feature-freeze stands. No code or fixture files changed. Closes #251. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MdYFKUaygHz1T9H1qJ7BqK --- docs/proposals/P-022-rust-core-migration.md | 99 ++++++++++++++++----- docs/proposals/README.md | 2 +- 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/docs/proposals/P-022-rust-core-migration.md b/docs/proposals/P-022-rust-core-migration.md index 6ac90829..9b9726e5 100644 --- a/docs/proposals/P-022-rust-core-migration.md +++ b/docs/proposals/P-022-rust-core-migration.md @@ -1,10 +1,47 @@ # P-022 — Rust core migration: bird's-eye architecture -Status: **draft / exploratory** (design only — no Rust code committed yet; the -Python core stays the reference implementation and the oracle until parity holds). -Revised per the post-merge review in +Status: **in execution** (strangler-fig underway; the Python core stays the +reference implementation and the oracle until the explicit cutover). The design +rationale below is historical and unchanged; the live sequencing is the #250 +child-issue DAG. Revised per the post-merge review in [`docs/notes/p022-review-notes.md`](../notes/p022-review-notes.md). +### Implementation status (reconciled after #214/#249 — see #250/#251) + +**Implemented** (workspace members in `rust/Cargo.toml`, parity-gated by +`scripts/oracle_exact.py` and the shared fixtures in `tests/fixtures/`): + +- `own-ir` — OwnIR serde + schema round-trip (step 1); +- `own-syntax` — parser, error-text parity (step 2); +- `own-cfg` — lowering + the canonical CFG-JSON seam, replaying + `tests/fixtures/cfg_parity.json` (steps 0/3; the seam the strategy below + said "still needs building" **is built** — `python -m ownlang cfg --format + json` + the `--write`-regenerated parity fixtures); +- `own-diagnostics` — the data-only diagnostics layer; +- `own-analysis` — the worklist solver + ownership/lifetime/buffer/effect/DI + analyses (step 4; the **analysis-heart milestone**, completed in #214 / + PR #249, replaying `diag_parity.json` and the DI/effect fact-parity + fixtures). + +**Next steps — each owned by exactly one child issue under #250:** + +| Step | Deliverable | Issue | +|---|---|---| +| 5a | diagnostic messages + ordered Evidence parity | #255 | +| 5b | `.ownreport.json` + SARIF projection, canonical parity | #256 | +| 5c | `own-codegen` (analysis-independent sibling) | #257 | +| 6a | OwnIR **bridge semantics formalized** before the port | #258 (delivered: `spec/Bridge.md` + `spec/BridgeBehaviorMatrix.md`, review via PR #297) | +| 6b | Rust `own-bridge`, layered OwnIR parity | #259 | +| 7a | dual-engine shadow mode + zero-diff reproduction artifacts | #260 (supported by #269 — normalized `AnalysisTrace` + first-divergence minimizer) | +| 7b | Rust `own-cli`: command/output/exit-code parity | #261 | +| 8 | Rust-default **cutover**, rollback gate, Python distribution removal | #262 | + +The Datalog/Ascent rule layer stays strictly **post-cutover** (strategy step 8 +below) and deliberately has no issue yet. Throughout: Python remains +authoritative until #262's cutover gate passes; a feature-freeze on +verdict-changing inference holds until then +([`interprocedural-roadmap.md`](../notes/interprocedural-roadmap.md)). + ## Why The primary trigger is the **IDE extension** — Gate B of @@ -477,37 +514,48 @@ SARIF/JSON shapes. So: misses. **Per-layer seams.** SARIF is the verdict-layer seam and already exists. A **CFG-layer -seam does not** — today `python -m ownlang cfg` prints a *human* dump (`_print_cfg`), -not a contract. So a prerequisite of diffing CFGs is to first **add and freeze a -canonical `cfg --format json` export on the Python side**; mirroring the debug text -dump would bake a non-contract format into the ratchet. Treat "CFG JSON seam" as work -to build, not an existing contract. With SARIF (verdict) present and CFG-JSON added, -a divergence can be bisected to the crate that introduced it. +seam did not** (at writing) — `python -m ownlang cfg` printed a *human* dump +(`_print_cfg`), not a contract. So a prerequisite of diffing CFGs was to first **add +and freeze a canonical `cfg --format json` export on the Python side**; mirroring the +debug text dump would bake a non-contract format into the ratchet. With SARIF (verdict) +present and CFG-JSON added, a divergence can be bisected to the crate that introduced +it. *(Status per #251: built and frozen — `cfg --format json` + +`tests/fixtures/cfg_parity.json`, replayed by `own-cfg`'s parity tests.)* Because the oracle compares *contracts we froze and tested*, the recent evidence/SARIF -hardening is what makes the verdict seam cheap — the CFG seam still needs building. +hardening is what made the verdict seam cheap — and the CFG seam has since been built +(step 0 ✅ above). ## Migration strategy (strangler-fig, bottom-up, oracle-gated) -0. **Add the missing Python seams first**: a canonical `cfg --format json` export - (and the exact diff harness). Without these the ratchet has nothing to compare the - CFG layer against. -1. **Stand up the workspace + `own-ir`** (serde round-trips the existing OwnIR +*(Status markers reconciled per #251; the plan text is otherwise as designed.)* + +0. ✅ **Add the missing Python seams first**: a canonical `cfg --format json` export + (and the exact diff harness, `scripts/oracle_exact.py`). Without these the ratchet + has nothing to compare the CFG layer against. +1. ✅ **Stand up the workspace + `own-ir`** (serde round-trips the existing OwnIR fixtures — first parity check, at the seam). -2. **`own-syntax`**: port the parser; diff the AST/`cfg` dump against Python. -3. **`own-cfg`**: port lowering; diff the frozen CFG JSON (from step 0). -4. **`own-analysis`**: port the worklist + ownership first, then lifetime/effect/DI; +2. ✅ **`own-syntax`**: port the parser; diff the AST/`cfg` dump against Python. +3. ✅ **`own-cfg`**: port lowering; diff the frozen CFG JSON (from step 0). +4. ✅ **`own-analysis`**: port the worklist + ownership first, then lifetime/effect/DI; diff diagnostics (no evidence) → then evidence → then SARIF, layer by layer. -5. **`own-diagnostics` + `own-codegen`**: SARIF/report/text and C# `emit`; diff each. + (#214 / PR #249 — the analysis heart; `own-diagnostics` shipped as its + data-only layer.) +5. **`own-diagnostics` (messages/Evidence — #255), report/SARIF (#256) + + `own-codegen` (#257)**: SARIF/report/text and C# `emit`; diff each. 6. **`own-bridge`**: port the OwnIR bridge — facts→core lowering, the MOS interprocedural inference, verdict mapping. **Prerequisite:** the normative write-up of the inference semantics (consume/borrow/fresh/alias/overwrite rules) from the tech-debt register, so the port has a spec and not just - `test_ownir.py` examples. Diff on the OwnIR fixtures + `ownir --format sarif`. -7. **`own-cli`**: cut over once corpus parity is ~100%. Keep Python frozen as the + `test_ownir.py` examples — delivered as `spec/Bridge.md` + + `spec/BridgeBehaviorMatrix.md` (#258, composing `spec/Inference.md`); + implementation is #259. Diff on the OwnIR fixtures + `ownir --format sarif`. +7. **`own-cli`**: cut over once corpus parity is ~100% (shadow mode #260 with + #269's AnalysisTrace, then the CLI #261). Keep Python frozen as the oracle/spec. 8. **Only then** revisit the rule layer as Datalog/Ascent (ADR §8: "core moves to - Rust" trigger now satisfied) — natively, not as a Python detour. + Rust" trigger now satisfied) — natively, not as a Python detour. The formal + cutover + rollback gate + Python-distribution removal is #262. Throughout, Python stays authoritative; the Rust crates light up behind the ratchet. @@ -541,6 +589,9 @@ Throughout, Python stays authoritative; the Rust crates light up behind the ratc ## Placement -This document lives in `PhysShell/Own.NET/docs/proposals/`. It is design-only; the -first code deliverable is the workspace skeleton + `own-ir` round-trip + the oracle -harness, on its own branch, gated by the differential ratchet from commit one. +This document lives in `PhysShell/Own.NET/docs/proposals/`. The document is +design + status; the first code deliverable it called for — the workspace +skeleton + `own-ir` round-trip + the oracle harness, gated by the differential +ratchet from commit one — has shipped (`rust/`, `scripts/oracle_exact.py`; see +the implementation-status block at the top). The monorepo layout it recommends +is the one in effect. diff --git a/docs/proposals/README.md b/docs/proposals/README.md index 1a15d9d2..e936b801 100644 --- a/docs/proposals/README.md +++ b/docs/proposals/README.md @@ -41,7 +41,7 @@ proposal is marked `done` with a pointer. | [P-017](P-017-multi-stack-frontends.md) | Multi-stack frontends (OwnTS / OwnJVM: OwnJava + OwnKotlin) | draft | | [P-020](P-020-ownts-react-effects.md) | OwnTS React effects profile (`Own.React`) — the effect-storm angle | draft | | [P-021](P-021-async-audit-pack.md) | Async audit pack (`Own.Async`) | draft | -| [P-022](P-022-rust-core-migration.md) | Rust core migration: crate DAG, patterns, prior art, differential oracle (Python = golden) | draft / exploratory | +| [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 (`own-ir`/`own-syntax`/`own-cfg`/`own-diagnostics`/`own-analysis`, #214/#249); remaining steps = the #250 child-issue DAG (#255–#262); Python authoritative until cutover | | [P-023](P-023-architecture-guard.md) | Architecture guard (`Own.Arch`): rules.yaml intent model + dependency-graph gate + baseline ratchet | draft | | [P-024](P-024-security-audit-profile.md) | Security audit profile (external tools + SARIF adapters; rejects own scanner engine) | draft | | [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) | From 3909f98f7461d4a6dddec6db0bfdbc4570efeb7b Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 17:21:45 +0000 Subject: [PATCH 2/2] =?UTF-8?q?docs(P-022):=20#251=20review=20fix=20?= =?UTF-8?q?=E2=80=94=20bridge=20spec=20lands=20with=20PR=20#297,=20not=20o?= =?UTF-8?q?n=20main=20yet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex review on #298 correctly flagged that spec/Bridge.md and spec/BridgeBehaviorMatrix.md are referenced as delivered but do not exist in this checkout — they live on PR #297 (the #258 deliverable, in independent review). Reworded the 6a status in both places to say the specs land with PR #297 and #259 starts only after that review gate, so the checklist stays truthful regardless of which PR merges first. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MdYFKUaygHz1T9H1qJ7BqK --- docs/proposals/P-022-rust-core-migration.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/proposals/P-022-rust-core-migration.md b/docs/proposals/P-022-rust-core-migration.md index 9b9726e5..837666a1 100644 --- a/docs/proposals/P-022-rust-core-migration.md +++ b/docs/proposals/P-022-rust-core-migration.md @@ -30,7 +30,7 @@ child-issue DAG. Revised per the post-merge review in | 5a | diagnostic messages + ordered Evidence parity | #255 | | 5b | `.ownreport.json` + SARIF projection, canonical parity | #256 | | 5c | `own-codegen` (analysis-independent sibling) | #257 | -| 6a | OwnIR **bridge semantics formalized** before the port | #258 (delivered: `spec/Bridge.md` + `spec/BridgeBehaviorMatrix.md`, review via PR #297) | +| 6a | OwnIR **bridge semantics formalized** before the port | #258 (deliverable written — `spec/Bridge.md` + `spec/BridgeBehaviorMatrix.md` **land with PR #297**, in independent review; not on `main` yet) | | 6b | Rust `own-bridge`, layered OwnIR parity | #259 | | 7a | dual-engine shadow mode + zero-diff reproduction artifacts | #260 (supported by #269 — normalized `AnalysisTrace` + first-divergence minimizer) | | 7b | Rust `own-cli`: command/output/exit-code parity | #261 | @@ -547,9 +547,11 @@ hardening is what made the verdict seam cheap — and the CFG seam has since bee interprocedural inference, verdict mapping. **Prerequisite:** the normative write-up of the inference semantics (consume/borrow/fresh/alias/overwrite rules) from the tech-debt register, so the port has a spec and not just - `test_ownir.py` examples — delivered as `spec/Bridge.md` + - `spec/BridgeBehaviorMatrix.md` (#258, composing `spec/Inference.md`); - implementation is #259. Diff on the OwnIR fixtures + `ownir --format sarif`. + `test_ownir.py` examples — written as `spec/Bridge.md` + + `spec/BridgeBehaviorMatrix.md` (#258, composing `spec/Inference.md`), + landing with PR #297 after independent review; implementation is #259 and + starts only after that review gate. Diff on the OwnIR fixtures + + `ownir --format sarif`. 7. **`own-cli`**: cut over once corpus parity is ~100% (shadow mode #260 with #269's AnalysisTrace, then the CLI #261). Keep Python frozen as the oracle/spec.