Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/proposals/P-022-rust-core-migration.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,7 +53,7 @@ was #258 alone, which is satisfied. Per the checkpoints #259 itself defines:

| #259 checkpoint | Status | Evidence / what remains |
|---|---|---|
| 1 — typed OwnIR validation | **partial** | `OwnIr::from_json` + the #294 OD-2 fail-loud unknown-kind rule. Full validation acceptance/rejection parity (fixture layer 1) is out of the current slice |
| 1 — typed OwnIR validation | **acceptance surface closed except two named families — not yet complete** | Two censuses. The first froze 77 controls, closed twelve permissive documents and read 0/0/0 — then review found seven divergences the ledger could not express, because the same author wrote the ledger and the port and one gap in reading BR-D1 produced a matching gap in each (`_svc()` always supplied `lifetime`, so no control could omit it). The re-census is derived from `load()` and `obligations.py` line by line: **193 controls**, which opened a further **58** permissive documents and **9** category mismatches. Closing them was architectural — the strict door is now a sequential validator over the raw document (`own-ir/src/strict.rs`) reproducing BR-D1's interleaving of shape and semantics *per section, in declaration order*; `serde` is the typed constructor, and a document it rejects after validation is reported as a hole in the validator and asserted against. The obligation **acceptance grammar** is ported (`own-ir/src/protocol.rs`); protocol *analysis* is not, and is not part of what the door accepts. Taxonomy is now **seven** categories: `WellFormedness` was added for the two protocol rules whose values are all correctly typed and whose records still cannot mean anything — a category set frozen by the first census is a claim about that census, not about the contract. Matrix 31/162, 0/0/0; 31 mutations each caught, five only by the validator-hole guard and two changing nothing but a category. **Why this is not yet complete:** two Python-accept/Rust-reject families are measured and deliberately excluded from the ledger — source coordinates beyond Rust's integer range, and sufficiently deep protocol/flow nesting. 0/0/0 therefore means "over a set from which two known divergence families were removed", which is not the parity #259 asks for. Both close in one **Python-first** defensive-limit change (signed-64 coordinates; one measured domain nesting limit, at-limit accept and limit+1 reject, written into the OwnIR contract). That lands first; this checkpoint is then rebased, gains boundary controls for both families, and is re-measured before it may be called complete. #294 OD-2 remains a separate tolerant-door concern |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reconcile the reported matrix totals with the final results.

Line 56 reports 31/162 and 31 mutations, but the PR objectives report 29 agreed accepts, 162 agreed rejects, and 27 mutations. Update these values, or label the current values as pre-exclusion totals and explain the difference.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/proposals/P-022-rust-core-migration.md` at line 56, Reconcile the matrix
figures in the P-022 checkpoint with the PR objective totals: update “31/162”
and “31 mutations” to the agreed “29 accepts, 162 rejects, and 27 mutations,” or
explicitly label the existing figures as pre-exclusion totals and state how the
two excluded divergence families account for the difference.

| 2 — fact lowering | **complete** | `lower()` → `own_lowered`; **27/27** `rust_replay` cases in `tests/fixtures/lowered/manifest.json` byte-exact |
| 3 — interprocedural MOS | **complete for the stage-1 domain** | `dump_summaries()` byte-identical to `python -m ownlang summaries` across **35** `*.summaries.json` goldens. Container-valued metadata is **outside** the declared scalar-metadata parity domain — a separate #294-class door decision, not a silent gap |
| 4 — analysis wiring | **not started** | the crate states its own boundary: "no diagnostics, no analysis" |
Expand All@@ -72,7 +72,13 @@ was #258 alone, which is satisfied. Per the checkpoints #259 itself defines:
| 7b | Rust `own-cli`: command/output/exit-code parity | #261 | blocked — needs the production bridge and the output surfaces |
| 8 | Rust-default **cutover**, rollback gate, Python distribution removal | #262 | blocked by #260/#261 and final parity |

**Preferred queue:** #259 remaining (cp1 → cp4 → cp5) → #260/#269.
**Preferred queue:** Python-first defensive limits → finish cp1 → cp4 → cp5,
then #260/#269. The limits change is **not** a side quest: it closes the two measured
Python-accept/Rust-reject families (source-coordinate integers beyond signed 64
bits, and nesting depth), and until it lands cp1's 0/0/0 is a result over a set
with two known divergence families removed from it. Closing them by widening
Rust — arbitrary-precision integers, `unbounded_depth` — is refused: the limit
belongs in the contract, not in the representation.

### What #256 asked for that the tree does not have

Expand Down
2 changes: 1 addition & 1 deletion docs/proposals/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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) | 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 + MOS parity landed, analysis wiring open); Python authoritative until cutover |
| [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 re-censused at 193 controls after a first 0/0/0 proved to be the ledger agreeing with its own author, and awaiting a Python-first defensive-limit change before it can be called complete; analysis wiring open); 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) |
Expand Down
15 changes: 13 additions & 2 deletions rust/crates/own-bridge/tests/replay.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,9 +41,20 @@ fn read(name: &str) -> String {
}

/// facts text → the canonical Layer 2 bytes, through the Rust pipeline only.
///
/// Deserialized **without** `OwnIr::from_json`, on purpose. That is the strict
/// door (BR-D1), and this harness exercises the **tolerant** one — the path
/// `check_facts`/`to_module` take when an embedder hands over a dict directly,
/// never having called `load()`. Routing through the strict door would make
/// this suite test the wrong entry surface, and since #259 cp1 taught that door
/// to enforce IR4 it would also make `tolerant_unknown_kind` unreachable: the
/// strict door would reject the facts before the lowerer could demonstrate that
/// it rejects them too. The lowerer's own fail-loud check (#294 OD-2) exists
/// precisely because this path bypasses `load()`, so the test must bypass it as
/// well or it proves nothing.
fn lower_bytes(facts_text: &str, case: &str) -> String {
let facts = own_ir::OwnIr::from_json(facts_text)
.unwrap_or_else(|e| panic!("{case}: own-ir rejected the shared facts: {e}"));
let facts: own_ir::OwnIr = serde_json::from_str(facts_text)
.unwrap_or_else(|e| panic!("{case}: shared facts do not deserialize: {e}"));
let surface = match own_bridge::lower(&facts) {
Ok(doc) => Surface::Lowered(doc),
Err(e) => Surface::Rejected(Rejected {
Expand Down
Loading
Loading