docs(proposal): P-022 Rust core migration — bird's-eye architecture#166
Conversation
Design-only proposal for porting the Python core to a Rust workspace, keeping the Python repo as the differential oracle / golden test. Covers: crate topology as an enforced acyclic DAG (decoupled across the OwnIR seam), Rust idioms that remove the current accidental complexity (enum+match vs assert_never, newtype IDs vs id(sym), persistent state vs deep copy, Lattice/Analysis traits vs the interleaved _Analyzer), library candidates, prior art to study (rust-analyzer, ruff, rustc_mir_dataflow, Polonius, ...), Rust architecture-fitness tooling (crate-graph fitness test, cargo-modules/deny/machete/public-api), and the differential-oracle design that rides the already-frozen evidence/SARIF/JSON contracts. No Rust code yet; Python stays authoritative until parity holds.
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR adds two documentation files and updates the proposals index. It introduces a cross-stack strictness/fitness policy document (Rust, C#/.NET, Python tooling, ratchet doctrine) and a design proposal (P-022) for migrating the analysis core to Rust, including architecture, differential oracle, and migration strategy. ChangesDocumentation additions
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant CI
participant PythonCore
participant RustCore
participant Oracle
CI->>PythonCore: run on corpus input
CI->>RustCore: run on same corpus input
PythonCore-->>Oracle: exit status, SARIF/JSON, CFG export
RustCore-->>Oracle: exit status, SARIF/JSON
Oracle->>Oracle: compare normalized outputs exactly
Oracle-->>CI: pass/fail verdict
Related issues: None specified. Related PRs: None specified. Suggested labels: documentation, proposal Suggested reviewers: None specified. Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review This is an architecture brainstorm, not a gate —
Findings/suggestions welcome as inline comments on the doc. Thanks! Generated by Claude Code |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
gh pr view 166 --repo PhysShell/Own.NET --json files,title,body -q '.files[].path'
echo "---"
fd -i "P-022" .
echo "---"
fd -i "oracle_compare" .Length of output: 465 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== P-022 doc ==="
cat -n docs/proposals/P-022-rust-core-migration.md
echo "=== oracle_compare.py ==="
cat -n scripts/oracle_compare.py
echo "=== proposals README diff context ==="
sed -n '1,60p' docs/proposals/README.mdLength of output: 65507 🏁 Script executed: #!/bin/bash
set -euo pipefail
fd -i "evidence.py" .
echo "---"
sed -n '1,80p' ownlang/evidence.py 2>/dev/null || true
echo "---diagnostics.py head---"
sed -n '1,60p' ownlang/diagnostics.py 2>/dev/null || true
echo "---grep Evidence usage in analysis---"
rg -n "Evidence" ownlang/*.py | head -50Length of output: 8541 🏁 Script executed: #!/bin/bash
set -euo pipefail
fd -i "codegen" ownlang -t f
echo "---"
rg -n "^def emit|^def render|^import|^from" ownlang/codegen.py 2>/dev/null | head -30
echo "---cli---"
rg -n "emit\(|render\(|analyz" ownlang/cli.py 2>/dev/null | head -40Length of output: 832 🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n "^def emit" ownlang/codegen.py
sed -n '1,40p' ownlang/codegen.py | tail -20
echo "---find cli file---"
fd -i "cli" ownlang -t fLength of output: 471 🏁 Script executed: #!/bin/bash
set -euo pipefail
grep -n "^def \|^class " ownlang/codegen.py | head -30Length of output: 1113
1. Crate DAG / couplingThe But I think the diagram has one edge that doesn't match reality: 2. Dataflow state representationAgree persistent maps are the right default to reach for, but bench against arena+generational-index CoW before committing, because:
3. ParserHand-roll is the right call given the explicit goal is golden-parity of error messages, not just successful parses. 4. The oracleThis is where I'd push hardest. Blind spots the SARIF/JSON contract comparison structurally can't catch:
5. Prior artYour list is strong. One I'd add: 6. Repo layoutMonorepo is right for this phase — the oracle's whole value proposition is "one clone, one CI run, diff both binaries," and a sibling repo adds submodule/pinned-SHA ceremony that only pays off once the Rust core is independently versioned/released. Revisit the split once Rust is authoritative and Python becomes the legacy/reference-only artifact — at that point the coupling direction inverts and a monorepo's blast radius (Rust CI running on every Python-only doc change, etc.) becomes the annoyance instead of the benefit. ✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 220502241f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| shape `scripts/oracle_compare.py` already produces for the cross-tool (Infer#/ | ||
| CodeQL) diff. **The Rust core is just another SARIF producer that the existing | ||
| oracle diffs against Python.** |
There was a problem hiding this comment.
Replace the cross-tool oracle before using it for parity
scripts/oracle_compare.py is not an exact implementation-parity oracle: it parses SARIF down to (path, line, rule, message, cls), then compare() keeps only leak-class findings and matches by basename within a line tolerance. If the Rust port reuses it here, changes in evidence/codeFlows, subject/resource metadata, warning/advisory levels, non-leak diagnostics, full paths, ordering, or even exit status can still pass as “parity”. For the Rust migration, make this a new exact diff harness over canonical stdout/stderr/status/SARIF, or extend the script with an exact mode, instead of using the cross-tool oracle.
Useful? React with 👍 / 👎.
| │ └────────────────────────┐ | ||
| own-syntax ───┤ │ | ||
| (lexer/AST) ▼ │ | ||
| own-cfg ──▶ own-analysis ──▶ own-diagnostics ──▶ own-codegen |
There was a problem hiding this comment.
Route codegen around diagnostics
The diagram locks own-codegen behind own-diagnostics, but the crate notes say codegen emits from CFG + analysis results. With the allowed-edge test proposed below, codegen would have no legal access to solver result types unless own-diagnostics re-exports analysis internals or codegen re-runs/duplicates analysis, which breaks the stated “diagnostics knows nothing about solver internals” invariant. Model diagnostics and codegen as sibling consumers of own-cfg/own-analysis instead of chaining codegen through the verdict renderer.
Useful? React with 👍 / 👎.
| files, and OwnIR fact files. Plus generated inputs (see below). | ||
| - **Run both:** `python -m ownlang check --format sarif <f>` vs | ||
| `own-rs check --format sarif <f>` (identical CLI surface + SARIF ⇒ clean diff). | ||
| Likewise `cfg` (dump CFG as JSON), `report` (`.ownreport.json`), `emit` (C#). |
There was a problem hiding this comment.
Add a canonical CFG JSON seam before depending on it
This treats cfg JSON as an existing per-layer contract, but the Python CLI currently prints a human CFG with _print_cfg and has no --format json surface. If the Rust port starts diffing CFGs as written, there is no Python JSON oracle to compare against, and mirroring the text dump would bake in a non-contract debug format. Add and freeze a canonical Python CFG JSON export before the ratchet uses this seam.
Useful? React with 👍 / 👎.
Both reviewers converged; all corrections are factual/design refinements (no forks): - Crate DAG: own-codegen is a SIBLING of own-diagnostics (both consume own-cfg/own-analysis), not chained through it. Codegen is verdict-independent (AST/CFG-driven, matching Python codegen.generate), so the old own-diagnostics -> own-codegen edge would have forced diagnostics to re-export solver internals. Added a fitness function locking codegen !-> diagnostics (and !-> analysis for now). (Codex P2, CodeRabbit #1) - Oracle: do NOT reuse scripts/oracle_compare.py as the parity oracle — it is cross-tool fuzzy (leak-only, +-N line tolerance, coarse severity) and would mask off-by-one/label/subject/exit-status divergences. Spec a new exact harness over status+stdout+stderr+SARIF/JSON, with an exit/crash gate first, exact set-equality incl. evidence label text, and intra-tie ordering. (Codex P1, CodeRabbit #4) - CFG seam does not exist yet: python cfg prints human text, not JSON. Add+freeze a canonical cfg --format json before the ratchet uses that seam; added as migration step 0. (Codex P2) - State: arena+CoW likely wins this procedural workload; bench largest real function, wall-clock + RSS. Prior art: clippy lint-pass registry, prusti-viper encoding boundary. Repo-layout revisit trigger. (CodeRabbit #2/#3/#5/#6)
|
Thanks both — genuinely useful architecture pushback. Folded all of it into Codegen ⊥ diagnostics (Codex P2 @65 + CodeRabbit #1) — redrew the DAG: Oracle is not CFG-JSON seam doesn't exist yet (Codex P2 @185) — correct, Also folded (CodeRabbit): arena+CoW as the likely winner for this procedural workload (bench largest real function, wall-clock and RSS); prior art += clippy lint-pass registry + prusti-viper encoding boundary; parser combinator-rewrite deferred behind frozen error-parity; monorepo revisit-trigger noted. Still a draft / design doc — no code yet. Further pushback welcome. Generated by Claude Code |
Performance: frontend-specific levers in payoff order — intern everything (u32 symbols), bitset lattice (u8 bitflags for VarState + dense Vec<_> by RID, not HashSet) which also tips the persistent-vs-arena call toward arena+CoW, arenas + u32 indices, FxHashMap, rayon across independent per-function analyses, mimalloc/jemalloc. Micro-opt last, behind a flamegraph; perf locked by an iai-callgrind instruction-count ratchet in CI (deterministic). Added the matching library rows. Strictness: declarative [workspace.lints] block (Rust >= 1.74) — unsafe_code=forbid, unreachable_pub/rust_2018_idioms deny, clippy pedantic/nursery as warn with justified allows, unwrap/indexing/ arithmetic_side_effects/panic/dbg/print_stdout denied surgically. Added cargo-mutants (does the suite/oracle actually catch a broken transfer?), cargo-semver-checks, cargo-hack --feature-powerset, cargo-udeps, and the honest 'no NDepend-for-Rust' limit. Plus the ratchet doctrine: baseline current violations, hold new code to the full bar, tighten half a turn per iteration — same ratchet as the oracle (correctness) and iai-callgrind (perf), honouring 'a false positive is worse than a miss' at the tooling layer.
…pline) Cross-checked the performance section against the source article (troubles.md, 'Writing words and reading dwords'). Added the concrete frontend-relevant levers it teaches that were missing: - bump/typed arena for the build-once/read-many AST/CFG (bumpalo, typed-arena, rustc TypedArena) alongside u32 indices; - flat backing arrays, never Vec<Vec<_>> (a cache miss per row); - SmallVec for the many-small collections (evidence steps, loans, per-block diagnostics) — inline by the law of small numbers; - enums / impl Trait / &dyn over Box<dyn>; - the article's discipline framing we already run as doctrine: optimize by cumulative cost under perf (not by looks), skip one-time costs, keep the transfer function pure (registers + benchmarkability), algorithms first, #[inline] only on tiny cross-crate hot fns (never inline(always) by reflex), LTO + panic=abort, micro-opt last behind a flamegraph; - further-reading credits (the article, ripgrep post-mortem, Fastware).
Capture the tooling posture across all three stacks as a companion to P-022, centered on the ratchet doctrine (baseline current violations, hold new code to the full bar, tighten half a turn per iteration) — the same monotone gate we run for correctness (oracle) and perf (iai-callgrind), grounded in 'a false positive is worse than a miss'. Per stack: Rust (cargo-deny/udeps/semver-checks/hack/modules/mutants; [workspace.lints] lives in P-022; honest 'no NDepend-for-Rust' limit); C#/.NET WPF (csproj strictness + editorconfig; IDisposableAnalyzers, VSTHRD, Meziantou, ErrorProne, Sonar, BannedApiAnalyzers; NetArchTest/ ArchUnitNET + NDepend + Stryker.NET); Python ownlang (ruff ALL, xenon, vulture, import-linter, pyright, Hypothesis). Cross-stack: CodeQL + Semgrep. Notes the SOLID/SRP semantic limit (proxy metrics only; real detection = review, human or the CodeRabbit/Codex layer we already run) and a start order for ~80% of the value in a day. P-022 links to it.
|
@codex review Specifically: please pressure-test and extend the "Performance principles" section of Already covered (please add net-new, not repeats):
What am I missing? Candidates I'd love your take on: worklist scheduling / RPO ordering to cut fixpoint iterations; representing the worklist itself (bitset-of-blocks vs Generated by Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2fc4df260
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| under `perf`/a flamegraph, not by what "looks slow"; one-time costs (CLI/OwnIR parsing) | ||
| don't matter, the hot path (the transfer function in the worklist) does — so **keep |
There was a problem hiding this comment.
Keep OwnIR and SARIF I/O in the perf budget
For CLI/CI scans over large OwnIR dumps, serde_json parsing and SARIF/report rendering happen on every input and are O(input + findings), so after the transfer loop is optimized they can dominate wall time and allocations. This sentence tells implementers to exclude that path from profiling; add representative large OwnIR/SARIF benches (e.g. from_slice/to_writer with buffered output and borrowed/interned diagnostic strings) rather than only transfer-function microbenches.
Useful? React with 👍 / 👎.
| | `assert_never` dispatch updated by hand in cfg/analysis/codegen | `enum` + exhaustive `match` | a missed variant is a **compile error**, not a runtime assert | | ||
| | RID = `id(sym)`; handles keyed by object identity | newtype indices `Rid(u32)`, `BlockId(u32)`, `LoanId(u32)` + arena | deterministic, serializable, no identity hacks | | ||
| | AST/CFG as object graphs | **arena + indices** (`la-arena`/`id-arena`) | borrow-checker-friendly graphs, cheap clone, cache-friendly | | ||
| | `State.copy()` deep-copies dicts every merge | **persistent maps** (`imbl`/`rpds`) — structural sharing | join/clone at merges is O(log n) sharing, not a deep copy | |
There was a problem hiding this comment.
Avoid baking in persistent maps as the default state
This table presents imbl/rpds as the replacement for State.copy(), but the same proposal later argues dense bitset/Vec arena+CoW is likely better for this workload. If this row is followed during the port, the solver may get locked into tree-node allocation and O(log n) lookups before the corpus benchmark has compared it with state pooling/scratch-buffer CoW, so make persistent maps an explicit benchmark candidate rather than the default idiom.
Useful? React with 👍 / 👎.
| Direction of the analysis (forward worklist to fixpoint, union at merge, monotone | ||
| transfer over a finite lattice) ports directly — it is textbook `rustc_mir_dataflow` | ||
| shape. |
There was a problem hiding this comment.
Specify RPO-guided worklist scheduling
The solver shape is left as a generic forward worklist, but for monotone intraprocedural analyses with loops, block order determines how many times joins and transfers rerun. Without an RPO/postorder scheduling principle plus a cheap in_queue bitset (or dense bitset-of-blocks for small CFGs), an implementation can burn most of its time revisiting blocks and reallocating states even with the compact lattice described below.
Useful? React with 👍 / 👎.
| "no findings = parity". Diff `stderr` too (e.g. the P-014 OWN050 advisory notes | ||
| live there, not in SARIF). |
There was a problem hiding this comment.
Don't treat OWN050 as stderr-only
Current ownir SARIF output passes the shown findings into build_sarif (ownlang/__main__.py:320-325), and the test suite pins advisory OWN050 as a SARIF result with level: "note" (tests/test_ownir.py:2251-2263). Saying these notes live in stderr can make the exact oracle compare the wrong stream or double-count human summary text; stderr is only the machine-format summary/chatter, while the advisory finding remains semantic SARIF output.
Useful? React with 👍 / 👎.
…OWN050) Four P3 suggestions, all confirmed: - OWN050 is a real SARIF result (level: note, pinned in test_ownir.py), not stderr-only — corrected the oracle exit/crash-gate bullet so the exact harness compares it on the SARIF seam and doesn't diff the wrong stream / double-count the human summary. (Codex @325) - Solver scheduling: added RPO/reverse-postorder worklist ordering + an in_queue bitset (dense bitset-of-blocks for small CFGs) + scratch-state reuse as a first-class lever — block order dominates fixpoint iteration count even with the compact lattice. (Codex @123) - I/O in the perf budget: over large OwnIR dumps serde_json parse + SARIF render are O(input+findings) per invocation and can dominate once the transfer is tight; bench large-OwnIR from_slice / buffered to_writer with interned strings, not only transfer microbenches. Softened the 'one-time costs don't matter' claim. (Codex @191) - Dataflow-state table row: present persistent maps (imbl/rpds) as a benchmark *candidate*, with dense-bitset arena/scratch CoW as the leaning default — don't lock the port into tree-node alloc + O(log n) before the corpus bench. (Codex @116)
|
Thanks @codex — all four folded into
Still a draft design doc — no code yet. Generated by Claude Code |
|
Summary
Testing
Committed changes on the current branch:
Created PR:
|
Codex flagged (and fixed in its sandbox) that the Patterns/idioms table still presented persistent maps as THE State.copy() replacement, out of sync with the Libraries-row/perf-section fix. Apply the same wording here so the doc is internally consistent: dense bitset Vec + arena/scratch CoW is the leaning default; imbl/rpds a benchmark candidate. (Codex's own commit 3a38d70 never landed on the branch/GitHub — folded manually.)
|
@coderabbitai review Draft design doc — re-review requested after folding your earlier round + Codex's. Since your last pass, Generated by Claude Code |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
gh pr view 166 --repo PhysShell/Own.NET --json commits -q '.commits[].oid' | tail -20
echo "---"
fd -i "P-022" .
echo "---"
fd -i "strictness-and-fitness" .Length of output: 705 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== P-022 doc ==="
cat -n docs/proposals/P-022-rust-core-migration.md
echo "=== strictness-and-fitness ==="
cat -n docs/notes/strictness-and-fitness.mdLength of output: 39048
1. Crate diagram arrow direction contradicts the fitness functions you just added. Lines 65–66: By the convention you use everywhere else in this diagram (Lines 61–63:
And it contradicts the finding from the first review round that's still true here: (or however you want to render it — the point is the arrow needs to originate from own-diagnostics into own-analysis, and own-codegen's only upstream should be own-cfg.) 2. Line 278 sets Everything else — the exact oracle harness, OWN050-as-SARIF correction, RPO scheduling, I/O perf caveat, ratchet framing — reads internally consistent this round. ✅ Action performedReview finished.
|
Two internal inconsistencies CodeRabbit flagged this round:
- Crate-DAG arrows were drawn backward for the verdict layer. The solver
constructs Diagnostic/Evidence (types owned by own-diagnostics), so the
real Cargo edge is own-analysis -> own-diagnostics, NOT the reverse —
which is what the fitness function ('own-diagnostics must not depend on
own-analysis') and the migration order already imply. Redrew the diagram
(own-diagnostics upstream of own-analysis; own-codegen depends on
own-cfg only) and rewrote the prose + crate bullets to match.
- unsafe_code = 'forbid' (workspace-wide) contradicted the perf section
still listing 'unsafe get_unchecked' as a lever. Dropped it: bounds-check
elision is done the safe way (one early assert! + LLVM), and a profiled
hot path that genuinely needs raw indexing scopes that ONE crate from
forbid -> deny with a documented reviewed #[allow(unsafe_code)], never
the workspace.
|
Both fixed in
(Note: a re-review pass may still be mid-flight on the prior commit Generated by Claude Code |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with 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.
Inline comments:
In `@docs/proposals/P-022-rust-core-migration.md`:
- Around line 59-70: The crate-topology block is an unlabeled fenced code block,
which markdownlint flags; update the fence in the proposal doc to use a language
tag such as text so the block remains unchanged but lint-clean. Locate the
fenced topology diagram around the own-ir/own-cli/own-oracle section and adjust
only the opening/closing fence.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: e53541d5-5381-4a99-85f3-14ffeb76502a
📒 Files selected for processing (3)
docs/notes/strictness-and-fitness.mddocs/proposals/P-022-rust-core-migration.mddocs/proposals/README.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4d3a37c19f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| The non-obvious edge is **`own-analysis → own-diagnostics`**: the solver *constructs* | ||
| `Diagnostic`/`Evidence` values (in Python, `analysis.py` imports and builds them from | ||
| `diagnostics.py` using solver-internal state), and those types are *owned by* | ||
| `own-diagnostics` — so analysis depends on diagnostics, **not the reverse**. |
There was a problem hiding this comment.
Add the CFG-to-diagnostics edge
This only calls out own-analysis → own-diagnostics, but the current Python pipeline also treats CFG lowering diagnostics as first-class verdicts: check_module appends d1 from build_cfg before analysis (ownlang/__main__.py:67-70), and ownlang/cfg.py emits Diagnostic for undefined names/resources, duplicate definitions, missing returns, etc. If the Rust crate graph omits own-cfg → own-diagnostics, lowering cannot produce those stable OWN030/OWN031/OWN033 results without duplicating or rerouting diagnostic types, which breaks the exact parity contract. Add that edge or explicitly state where CFG diagnostics are converted.
Useful? React with 👍 / 👎.
|
|
||
| ### Compiler strictness — declarative `[workspace.lints]` (Rust ≥ 1.74) | ||
|
|
||
| Lint config lives once in the workspace `Cargo.toml` and every crate inherits it: |
There was a problem hiding this comment.
Opt each crate into workspace lints
Cargo does not apply [workspace.lints] to every member automatically; per the Cargo/RFC 3389 inheritance model, a member manifest must include [lints] workspace = true before those lint levels are inherited. If the migration follows this block verbatim, a new crate can silently skip all of the deny/forbid settings during cargo clippy --workspace, so the strictness ratchet will not protect new code. Include the per-crate stanza or add a metadata check that fails when it is absent.
Useful? React with 👍 / 👎.
Что и зачем
Design-only proposal (bird's-eye) по переезду Python-ядра на Rust-workspace, где Python-репо остаётся дифференциальным оракулом / golden-тестом. Кода на Rust пока нет — Python авторитетен, пока не сойдётся паритет. Документ отвечает на конкретные вопросы: крейт-топология (enforced acyclic DAG, decoupled по OwnIR-seam), Rust-идиомы против текущей accidental complexity, библиотеки-кандидаты, prior art, Rust architecture-fitness тулинг, и дизайн дифф-оракула поверх уже замороженных evidence/SARIF/JSON контрактов.
Это брейншторм-PR (draft): зову CodeRabbit и Codex специально ради архитектурного фидбека, а не как gate. Особенно интересуют:
own-analysisvsown-diagnostics/own-ir— не течёт ли связность;imbl/rpds) vs arena+CoW для dataflow — что бенчить;chumsky/winnowдля golden-parity;scripts/oracle_compare.py— дыры в подходе?rust/subtree) vs sibling-repo.Тип изменения
Как проверено
python tests/run_tests.pyruff check .иmypyСвязанные issue
Нет связанного issue. Follow-up к execution-surfaces ADR (#164, #165) — Rust-переезд как триггер из §8.
Чеклист
docs/proposals/README.mddocs:)🤖 Generated with Claude Code
Generated by Claude Code
Summary by CodeRabbit