What the port matched
- Python TestRejectMalformed
- Rust rejects_malformed never written
Topic · Cross-language port
Gist
You cannot guarantee identical bytes from a rename. Proof fails the merge with proof audit --check mirror_complete when a ledger cell on the old language has no counterpart on the new one. Names can change. The cell cannot vanish.
proof audit --check mirror_complete
Keep the transpiler. Keep golden-master dumps. They do not ask whether malformed:negative still exists after Python became Rust.
01 · The renamed suite
The port looks done. Every new test has a new name. The old malformed-input guard never made the jump.
The rewrite that already has a ledger, in one language or two, lives on characterization testing and mirrors. Two live services and a traffic split live on migrating a critical service. This page is the language pair: Python to Rust, Java to Kotlin, Go to something else. The test identifiers will not match. The cell key has to.
A Mirror is a contract that the target file-set reproduces the verification ledger of the source, for every requirement in scope. Cells are keyed by
(requirement, dimension, discriminant),
never by test name. A Python
TestRejectMalformed
and a Rust
rejects_malformed
are the same cell if they witness
malformed:negative.
Matching names is the hole the port opens.
// source, Python
// SYS-REQ-ocr:malformed:nominal
// SYS-REQ-ocr:malformed:negative // TestRejectMalformed
// target, Rust
// SYS-REQ-ocr:malformed:nominal // accepts_ok_payload
// malformed:negative // absent
// cargo test: green
Declare both trees at
proof/mirrors/MIR-*.yaml
with
source.name
and
target.name
set (Python / Rust). Those names are labels. The parity check does not read them.
proof audit --check mirror_complete
fails when the negative exists on the source and not on the target, once the mirror status is
complete.
02 · The exhibit
The Rust suite is green under new identifiers. The catalog still owes a negative. Click the tabs.
What the port matched
The shall
When the payload is malformed, the decoder shall reject it and leave the store unchanged.
No negative on RustThe names
Still different identifiers. Still not the key. A complete mirror does not read them.
Rename keptProof
Two names, or one cell. Click the tabs.
| Side | Python | Rust |
|---|---|---|
| Test name | TestRejectMalformed |
not written |
| Cell | ocr:malformed:negative |
absent |
| MC/DC row | same FRETish truth-table row | missing that row is a gap |
| Suite | pytest green | cargo test green |
| Move | What it buys | What it loses |
|---|---|---|
| Transpile / Babel | A syntax rewrite. Useful when the languages are close. | transpile is that SERP. It does not re-read the shall. Keep the compiler. It is not this bar. |
| Golden master | Observed bytes from the old process, including bugs you meant to drop. | A dump that records a wrong answer fails the port that finally corrects it. That job lives on characterization. |
| Canary / strangler | Traffic on the new binary, or a facade that peels routes. | Routing is not a cell key. The cutover H1 lives on migrating a critical service. |
| Proof | Each source cell has a target counterpart, or a complete mirror stays red. Names are labels. | Presence, not I/O. Jama still authors. Two shims are a different check. |
The check reads the Mirror object, then the cells on each side. Test identifiers are not an input. MC/DC row parity is the in-between signal: witness rows come from the language-independent FRETish truth table, so requiring the same rows means both decision logics were exercised at the same condition combinations.
proof mirror add --id MIR-001 \
--source "litellm/ocr/**,tests/**/ocr/**" \
--target "litellm-rust/crates/providers/src/mistral/ocr/**" \
--status in_progress
proof mirror status MIR-001
proof audit --check mirror_complete --verbose
// SYS-REQ-ocr:malformed:nominal
// SYS-REQ-ocr:malformed:negative
proof audit --check differential_conformance
mirror_complete proves the evidence cell
exists
on the target. It does not re-run the test. A mirrored test that fails is
tests_pass,
not a parity gap.
in_progress
gaps stay warnings. A
complete
mirror that later grows a source-only cell re-opens at error.
differential_conformance is the I/O check: one language-neutral input, two shims, compare envelopes. A transform with fewer than two complete shims is skipped as information. The
differential
dimension on the Mirror object itself is deferred. Never describe a completed mirror as “the Rust crate matches the Python package.” We have not run this gate against a frozen corpus of language ports next to a transpiler. The loss is named, not scored.
A GIL-specific race on Python can be an exemption with a reason and a reviewer, not a silent skip. Rust then owes its own
Send
/
Sync
coverage. That waiver is visible. It is not “the languages are different, so parity does not apply.”
03 · The honest loss
If nobody declared a Mirror, mirror_complete is a no-op. The transpiler still has to exist.
Proof does not translate source. Babel still does, when the languages are close. Proof does not pin observed bytes. A golden master still does. Proof does not split traffic. A canary still does.
mirror_complete
does not prove the two implementations agree on an input. That is
differential_conformance
on a declared transform, with two complete shims. A Python-only or Rust-only shim is skipped as information.
Proof does not invent the shall. Jama still authors the programme. 100% MC/DC on the written decision still misses a partition that was never a condition. A completed mirror is not a finished port.
The rewrite H1 lives on characterization testing and mirrors. The cutover H1 lives on migrating a critical service. The empty-start H1 lives on replace a component with no specs. The schema H1 lives on database or API migration.
04 · Nearby questions
How do I rewrite a legacy system without introducing regressions? The campaign on a tree that already has a ledger, language-agnostic. Characterization.
We're migrating a critical service. How do I prove the new one matches the old one? Two live services, a traffic split. Service cutover.
How do I safely replace a legacy component that has no specs and no tests? The empty start. Replace with no specs.
Is there a way to check behavioral equivalence between old and new implementations? Presence is
mirror_complete.
Agreement on an input is
differential_conformance.
Both are named on this page. The cutover write-up lives on
migrating a critical service.
What's the safest way to modernize legacy software that nobody fully understands? Do not invent the spec from the unread tree. Unknown-system modernize.