Skip to content

P-022 step 8: Rust-default cutover, rollback gate, and Python distribution removal #262

Description

@PhysShell

Parent: #250
Recommended tier: strong + owner decision
CLI prerequisite satisfied — #261 / 261.B: the production Rust OwnIR executable landed via PR #347 (merged as 206e9c7) and #261 is closed completed; it was the sole CLI prerequisite of this cutover by owner decision C-5 (ratified 2026-09-08). #260 is reached. Not blocked by #345, the residual .own/dev CLI split out of #261.
Evidence prerequisite for the cutover decision, not a normative blocker: #263's baselines — the performance gates below cannot be judged without them.
Also depends on: #256 and #259 (both reached)

Goal

Make an explicit, evidence-backed decision to switch Owen's default engine from Python to Rust, preserve a tested rollback path, and only later remove Python as a distribution dependency.

This is not an implementation catch-all. It is a cutover gate with measurable correctness, reliability, distribution and performance requirements.

Staged rollout

Stage 1: opt-in Rust

Stage 2: repository CI/dogfood Rust default

  • Rust is default in Own.NET's own CI and internal dogfood.
  • Python remains an explicit fallback/reference mode.
  • All compare gates continue to run.

Stage 3: public Rust default

  • Owen public package/Action uses Rust by default.
  • A documented escape hatch can select Python during the observation window.
  • No silent fallback from Rust failure to Python success.

Stage 4: remove Python distribution dependency

Separate PR after an observation period:

  • remove vendored Python core from the package;
  • remove runtime Python discovery/download/cache requirements;
  • deprecate/remove OWEN_PYTHON and legacy OWN_PYTHON according to a documented compatibility plan;
  • retain Python reference code and oracle fixtures in the repository while they remain valuable for differential testing.

Launcher rulings (ratified 2026-09-08 with #261's decision packet)

  • The Rust executable behind the launcher is own-cli ownir (P-022 step 7b: the production Rust OwnIR executable (own-cli ownir) — command, output and exit-code parity behind the existing launcher #261) — one engine. Engine selection, the staging above and the escape hatch are the launcher's, explicit and documented; no silent fallback from a Rust failure to a Python success at any stage.
  • An unexpected Rust child exit code outside the legal set maps to the public internal-error path (exit 5), and the raw child status is retained in the evidence/report. A catchable panic in the child is one actionable stderr diagnostic and exit 70 (mapped onto the internal-error path as today); an uncatchable death is a visible hard failure, never findings and never a clean exit, with no particular OS exit number contracted.
  • SIGINT/cancellation: the Windows and Linux reference behaviour is measured first; 130 is not invented as a universal contract.
  • stdin is not part of the production OwnIR contract.

Known differences recorded ahead of the packet (2026-09-08, from #261's 261.B measurement)

Named here so they enter the decision packet's Known differences: line as recorded facts rather than being discovered at cutover:

  • Windows console/pipe encoding — a deliberate behavior change at cutover, not a regression. On a piped Windows stdout the Python reference encodes with cp1252, translates line endings to CRLF, and dies with UnicodeEncodeError on non-ASCII output that the Linux reference renders. The Rust executable emits canonical UTF-8 on both platforms. So a Windows user's bytes change at cutover — cp1252 / CRLF (and the occasional UnicodeEncodeError) today, canonical UTF-8 tomorrow. Three claims, kept apart:
    • A — canonical reference parity: claimed. Rust reproduces the Linux/UTF-8 reference byte for byte.
    • B — Rust portability: claimed. Rust on Linux and Rust on Windows emit identical bytes.
    • C — native-Windows Python parity: NOT claimed. It does not exist today, because the Windows reference is not byte-portable; "better" here still means "different", so it is a behavior change, not folded into a parity claim.
  • Invalid UTF-8 input. The Python reference exits 70 on a UnicodeDecodeError (its load() catches OSError/JSONDecodeError only, so a decode failure escapes to the exit-70 catch-all). A Python-first hygiene fix is owed before public cutover — UnicodeDecodeErrorOwnIRError → rc 2. P-022 step 8: Rust-default cutover, rollback gate, and Python distribution removal #262 is the tracker of record for this cutover prerequisite; Roadmap: ship Owen Alpha and complete the Rust production vertical after #214 #250 mirrors this tail in its Still missing list. Until it lands the Rust executable reproduces the code and shape but claims no byte contract for it (a CPython exception's wording is deliberately not a cross-language contract).

Parser-domain rulings V1–V4 (owner-ratified 2026-09-08, surfaced by #261's Version census)

The ownir_version gate exposes classes where CPython's permissive json and serde_json decode the same source differently — V1–V3, acceptance / kind / sub-branch divergences, not message wording — plus one representation-only boundary, V4, where the two sides' Unicode tables are independently versioned. They are ruled here:

Correctness gates

Reliability gates

  • malformed OwnIR and malformed source inputs do not panic;
  • Rust crashes are visible and produce reproduction artifacts;
  • cancellation/interruption behavior is tested against the measured reference (the SIGINT ruling above);
  • deterministic reruns produce identical normalized output;
  • memory/resource limits for hostile or very large inputs are documented;
  • Windows and Linux clean-machine paths are covered.

Distribution gates

  • Rust binary is packaged for all supported platforms;
  • public Owen.Cli install and Action use work without undeclared runtimes;
  • package upgrade/uninstall/reinstall tested;
  • rollback engine selection is documented and tested during the observation stage;
  • release workflow tests the actual packed artifact, not a project build.

Performance gates

Establish and publish baselines for:

  • process startup;
  • OwnIR parse;
  • bridge/lowering;
  • analysis;
  • CLI/SARIF rendering;
  • end-to-end C# project/solution run;
  • peak RSS/allocations where practical.

#263 produces these baselines; without them this section cannot be judged, which is why #263 is the evidence prerequisite of the cutover decision. Do not require a theatrical multiplier. Rust must meet an explicit budget and must not materially regress the user-visible path. Profile before optimizing; JSON and rendering may dominate once analysis becomes cheap.

Cutover decision packet

The PR/ADR must include:

Observation window:
Fast compare result:
Five-repo compare result:
Large-solution result:
Windows packaging result:
Linux packaging result:
Startup delta:
End-to-end delta:
Peak memory delta:
Known differences:
Rollback command/config:
Python-removal timing:

The Known differences: line begins from the section recorded above (the Windows A/B/C behavior change, the invalid-UTF-8 tail, and the parser-domain rulings V1–V4), plus anything the observation window adds.

Rollback

  • Rollback must be a documented engine selection or package patch, not a hidden automatic fallback.
  • A Rust failure must remain observable.
  • Immutable release tags are never moved.
  • A broken release is corrected by a new patch release.

Guardrails

  • No new diagnostics.
  • No semantic cleanup mixed into cutover.
  • No removal of Python reference/oracle tests merely because distribution no longer needs Python.
  • No public Rust default before the evidence packet is approved.
  • No Python dependency removal in the same PR that first changes the default.
  • No engine selection inside the Rust executable, and no fallback anywhere (C-4).

Acceptance

  • Explicit owner-approved cutover decision exists.
  • Rust is public default only after all gates pass.
  • Rollback path is tested and documented.
  • Observation-period results are recorded.
  • Python distribution removal occurs in a later, separately reviewable PR.
  • Public Owen install/Action behavior remains correct on supported platforms.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions