feat: productionize the cross-Python Execution ABI (0.4.0a1) - #2
Conversation
The 0.1 container collapsed every compatibility question into two fields: the exact creator Python version and the exact creator Continuum version. Both are provenance. Neither determines whether a target can reconstruct serialized execution state, because Continuum's frames, operand stacks, lexical cells, and control blocks live in its own VM rather than in CPython frame objects. This introduces continuum/abi.py, which separates the axes that decision actually depends on: container format, graph codec, IR version, execution ABI, creator runtime and Python (provenance only), accepted target runtime implementations, explicitly verified target Python versions, and required named capabilities. A target may restore only when it implements the exact execution ABI and every required capability, and only when the running interpreter appears in both the image's allowlist and this runtime's independently verified list. An image cannot widen the verified set by asserting a version this runtime has never proven, and an unverified interpreter is refused rather than attempted. Refusals carry stable machine-readable reason codes, and the decision function takes an injectable Host, so every boundary is reachable in a test on a single interpreter instead of depending on which Python happens to be installed. Format 0.1's strict rule is preserved verbatim as the legacy policy, with refusal messages that name the format version and say how to obtain cross-Python restore. No behavior is wired into the image path yet; this is the contract alone.
Container format 0.2 manifests carry the execution contract from abi.py as the single authority on whether a target may restore. Creator identity moves inside it as provenance, and `validate_compatibility` now returns the accepted decision instead of only raising. Format 0.1 images keep their original rule verbatim, in a separate validator, because they carry no contract: nothing in a 0.1 image justifies a capability-based decision, so assuming ABI compatibility for them would be a guess. Their refusals now name the format version and say how to obtain cross-Python restore. The gate that actually blocked the public CLI was _require_runtime_version, which compared platform.python_version() against a single hard-coded string and so refused to run, verify, or resume on any other interpreter. That is why the earlier feasibility work needed a private reader. It is replaced by an exact allowlist of interpreters this runtime has verified end to end -- still exact, never a range, so an unproven interpreter is refused before any state is created or reconstructed. Contract metadata must also agree with runtime.json and the manifest source section, so rewriting creator provenance and recomputing every archive checksum is refused rather than accepted as well-formed. inspect, verify, resume, and doctor now report the contract axes, and resume names both interpreters so a cross-Python restore is visible to an operator. Adds validation/cross_python/cli_proof.py, which proves the capability using only continuum run, freeze, verify, and resume, with the source process exited and reaped before the target reads the image. Verified locally on native Linux x86_64: frozen under CPython 3.12.13 with four active frames, restored under CPython 3.13.14, image byte-identical, zero completed actions repeated, source-plus-target output identical to an uninterrupted control. Full suite passes on both interpreters (227 tests each).
…tects faults Runs every corpus program at safe points spread across its execution: freeze under one interpreter, deeply verify the image without executing it, restore under another, and compare against an independently run uninterrupted control. The comparison covers the dimensions that matter rather than just output. Both sides compute a canonical state fingerprint over the logical frame chain, resume positions and opcodes, locals, lexical cells, operand stacks, control blocks, pending finally state, module globals, module RNG state, Random instance state, file offsets, and instruction and safe-point counters. Object identity is captured by labelling each object on first visit and emitting a back-reference on revisit, so shared references and reference cycles are structural features of the compared value: a restore that duplicated a shared list or broke a cycle produces a different fingerprint even when every scalar matches. Checkpoints are chosen by execution position, and the workload is read from the corpus, so nothing in the harness recognizes any particular program. A suite reporting zero mismatches proves nothing unless it can detect one, so the accompanying tests corrupt each compared dimension in turn and assert the corruption is caught -- including a replayed completed action and a target that restarted from program entry. Cells are covered in both places they live: held by a still-live enclosing frame, and reachable through a returned function's closure. First full run, native Linux x86_64, CPython 3.12.13 -> 3.13.14: 204 cases over 50 programs, 189 accepted and correct, 0 silent mismatches, 0 infrastructure failures, live frame depth up to 16. The 15 remaining cases are 10 programs the language frontend does not compile; they are reported as frontend gaps and excluded from the correctness rate rather than hidden in it.
Every case builds a real image, tampers with exactly one thing, then recomputes every covered archive checksum so the tampering is internally consistent. Recomputing the hashes is the point: an attacker editing a manifest will also fix the integrity document, so checksums alone prove nothing about metadata that must agree with the rest of the image. Covers unknown execution ABI, IR, graph-codec and container-format versions; policy downgrade and unknown policy names; unverified and out-of-allowlist Python versions; malformed and empty allowlists; missing and omitted capabilities; required native payloads; rewritten creator provenance, including the case where the manifest, its source section, and runtime.json are all rewritten to agree with each other; tampered program text and IR; frame and heap count disagreements; a dropped security boundary; broken checksums; and duplicate archive entries. Format 0.1 is exercised end to end by synthesizing the manifest shape 0.3.1 wrote, confirming such an image still loads, is accepted on its exact creator host, refuses a different Python or runtime version, and cannot obtain the ABI policy by declaring 0.1 while carrying contract fields. Verification is asserted not to execute the frozen program: a checkpoint taken inside a printing loop produces no program output while being fully verified. The foreign Python version used by refusal cases is derived from the running interpreter rather than hard-coded. A literal silently became a no-op when the suite ran on that exact version, which turned four refusal tests into tests that asserted nothing; running the suite on both interpreters exposed it. 300 tests pass on CPython 3.12.13 and 3.13.14.
…e runners Three jobs. The source job runs the full suite and then freezes a live program on native Linux x86_64 under CPython 3.12.13 using only continuum run and an external continuum freeze. The target job runs on a separate native Apple Silicon macOS arm64 runner under CPython 3.13.14 and restores the unchanged image using only continuum verify and continuum resume. A third job runs the paired differential corpus across both interpreters and enforces the release gate on its result. Because the jobs are separate runners, the source machine is gone before the target starts; the source harness additionally waits on the process, so its exit status is recorded and the evidence states that it had terminated and been reaped before the image was read. The target asserts the properties that make this a continuation rather than a restart: the image byte-identical at capture, on arrival, and after restore; zero completed actions repeated; source-plus-target output identical to an independently run uninterrupted control, with the source output a genuine prefix of it; and four live logical frames. It also asserts the restore was decided by the execution ABI rather than by matching the creator interpreter, by requiring the execution-abi policy and both distinct Python versions in the verify and resume output. Rosetta translation is refused on the target, so this is a claim about native arm64 rather than about x86_64 emulation. Every assertion string was checked against real local output first.
Documentation now records evidence that exists. Actions run 30658976309 at commit 40cc9dd passed all three jobs: a program frozen on native Linux x86_64 under CPython 3.12.13 was verified and resumed on a native Apple Silicon macOS arm64 runner under CPython 3.13.14, using only the public CLI, after the source process had exited and been reaped. Version 0.3.1 -> 0.4.0a1. Container format 0.1 -> 0.2. requires-python widens to >=3.12.13,<3.14 so a verified target interpreter can install the package at all. The packaging equality check it replaces is not weakened but split into two stronger tests: the specifier must admit every verified version, and the runtime must refuse a version the specifier admits that CI never proved. An exact allowlist cannot be written as a PEP 440 specifier, so the halves are tested separately rather than pretending one field expresses both. No dependency was added to read it. PORTABILITY.md gains the new proof row with the image hash and keeps every historical row. COMPATIBILITY.md documents the contract axes, which of them gate a restore, the two independent interpreter gates, and the corpus result. README, STATUS, LIMITATIONS, FORMAT, and LANGUAGE_SUPPORT are updated to name both verified interpreters and to state that the allowlist is exact rather than a range. Release notes state plainly what is not claimed: arbitrary Python versions, arbitrary process migration, native CPython frame migration, arbitrary hot reload, thread/socket/subprocess/native-extension migration, any verified Windows cross-platform path, and cross-Python restore on any platform pair other than the one proven. 302 tests green on CPython 3.12.13 and 3.13.14.
📝 WalkthroughWalkthroughAdds an execution ABI for format 0.2 images, supports verified cross-Python restores, adds CLI proof and differential validation harnesses, and records native Linux-to-macOS compatibility evidence. ChangesCross-Python compatibility
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant SourceCLI
participant SourceImage
participant TargetCLI
participant DifferentialReport
SourceCLI->>SourceImage: freeze execution state and write image
SourceImage->>TargetCLI: transfer byte-identical image
TargetCLI->>SourceImage: verify contract and restore state
TargetCLI->>DifferentialReport: record resumed output and execution evidence
DifferentialReport-->>SourceCLI: compare accepted results and failures
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (12)
tests/test_image.py (1)
179-201: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRename the test to match what it now asserts.
The body tampers with
execution_contract.creator.python_versionand expects "creator Python provenance disagrees". The name still saysruntime_version. Rename it totest_rewritten_creator_python_provenance_is_rejected.🤖 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 `@tests/test_image.py` around lines 179 - 201, Rename the test method from test_incompatible_runtime_version_is_rejected to test_rewritten_creator_python_provenance_is_rejected so it accurately reflects the creator provenance validation exercised by its existing body.continuum/abi.py (2)
533-551: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSort
__all__to keep the Ruff gate green.Ruff reports RUF022:
HostandIncompatibleImageappear between SCREAMING_CASE entries. Move them after the constant block.♻️ Proposed ordering
__all__ = [ "CONTAINER_FORMAT_VERSION", "EXECUTION_ABI_VERSION", "GRAPH_CODEC_VERSION", - "Host", - "IncompatibleImage", "LEGACY_CONTAINER_FORMAT_VERSION", "MANDATORY_CAPABILITIES", "PROVIDED_CAPABILITIES", "SUPPORTED_PYTHON", "VERIFIED_PYTHON_VERSIONS", + "Host", + "IncompatibleImage", "build_contract",🤖 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 `@continuum/abi.py` around lines 533 - 551, Reorder the exports in __all__ so all SCREAMING_CASE constants appear first, followed by Host and IncompatibleImage, then the lowercase functions; preserve every existing export without adding or removing entries.Source: Linters/SAST tools
120-121: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRename
REASON_UNKNOWN_CAPABILITYbefore the codes become stable.
REASON_MISSING_CAPABILITYmeans the runtime does not implement a capability the image requires.REASON_UNKNOWN_CAPABILITYmeans the image omitted a mandatory capability. The second name does not describe that condition, and the two names read as near synonyms. These codes are documented as stable and asserted on by tests, so renaming is cheaper now than after 0.4.0a1 ships.♻️ Proposed rename
-REASON_UNKNOWN_CAPABILITY = "unknown-capability" +REASON_MANDATORY_CAPABILITY_OMITTED = "mandatory-capability-omitted"absent = sorted(MANDATORY_CAPABILITIES - required) if absent: raise IncompatibleImage( - REASON_UNKNOWN_CAPABILITY, + REASON_MANDATORY_CAPABILITY_OMITTED, f"image omits mandatory execution capabilities: {absent}", )Update
tests/test_execution_abi.pyline 145 andtests/test_image_refusals.pyline 318 accordingly.Also applies to: 427-432
🤖 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 `@continuum/abi.py` around lines 120 - 121, Rename REASON_UNKNOWN_CAPABILITY to the clearer mandatory-capability omission name throughout continuum/abi.py and all references, including the assertions in tests/test_execution_abi.py and tests/test_image_refusals.py. Preserve the existing reason code value and behavior; update every occurrence consistently so the stable code remains unchanged.COMPATIBILITY.md (1)
9-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd the platform axes to the table.
abi.decide_restoregatestarget.operating_systems,target.architectures, andtarget.platforms. The table omits all three, so it understates what the contract decides.📝 Proposed rows
| `target.python_versions` | interpreters the creator accepts | yes | +| `target.operating_systems` | operating systems the creator accepts | yes | +| `target.architectures` | instruction set architectures the creator accepts | yes | +| `target.platforms` | accepted operating system and architecture pairs | yes | | `target.required_capabilities` | named features the target must implement | yes |🤖 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 `@COMPATIBILITY.md` around lines 9 - 19, Update the compatibility axes table to include target.operating_systems, target.architectures, and target.platforms as restore-gating dimensions, each marked as gated by abi.decide_restore. Place them alongside the existing target.runtime_implementations and target.python_versions rows.continuum/image.py (1)
602-607: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDistinguish the three "runtime metadata is inconsistent" refusals.
Lines 602-603 and 604-607 raise the same text, and
_validate_legacy_compatibilityline 555 raises it a third time. An operator cannot tell which document disagreed. Name the disagreeing pair in each message.♻️ Proposed messages
if runtime.get("ir_version") != ir.get("ir_version"): - raise ImageError("runtime metadata is inconsistent") + raise ImageError( + "runtime metadata is inconsistent: IR version disagrees with code/ir.json" + ) if manifest.get("format_version") == CONTAINER_FORMAT_VERSION and runtime.get( "ir_version" ) != manifest["execution_contract"].get("ir_version"): - raise ImageError("runtime metadata is inconsistent") + raise ImageError( + "runtime metadata is inconsistent: IR version disagrees with the " + "execution contract" + )Both messages keep the existing prefix, so
tests/test_image_refusals.pyline 193 and line 619 continue to match.🤖 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 `@continuum/image.py` around lines 602 - 607, Update the runtime metadata validation errors in the surrounding validation flow and _validate_legacy_compatibility so each refusal identifies the disagreeing document pair, while preserving the existing “runtime metadata is inconsistent” prefix and distinct behavior for each check.continuum/cli.py (1)
974-985: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueBranch on
POLICY_EXACTexplicitly.The
elsebranch assumes any non-ABI decision is a legacy format 0.1 decision and indexesloaded.manifest["target_compatibility"]. If a future policy value appears, this path raisesKeyErrorinstead of a clear error. Compare againstPOLICY_EXACTand raiseContinuumErrorfor an unknown policy.♻️ Proposed refactor
- else: + elif decision.get("compatibility_policy") == POLICY_EXACT: compatibility = loaded.manifest["target_compatibility"] print( "Compatibility accepted: " f"container format {LEGACY_CONTAINER_FORMAT_VERSION} exact-version " f"policy, runtime {compatibility['runtime_version']}, " f"Python {compatibility['python_version']}, " f"{platform.system()} {current_architecture}, " "portable IR with no native payload.", file=sys.stderr, flush=True, ) + else: + raise ContinuumError( + "unknown compatibility policy " + f"{decision.get('compatibility_policy')!r}" + )
POLICY_EXACTmust be added to thecontinuum.abiimport at lines 17-25.🤖 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 `@continuum/cli.py` around lines 974 - 985, Update the policy decision branch in continuum/cli.py to handle POLICY_EXACT explicitly, adding the symbol to the existing continuum.abi imports. Keep the current compatibility output only for POLICY_EXACT, and raise ContinuumError with a clear message for any unrecognized policy instead of indexing target_compatibility.validation/cross_python/cli_proof.py (2)
105-116: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a timeout to the CLI subprocess calls.
run_controlcallssubprocess.runwithouttimeout. The same omission exists ininspect_image(lines 202-208),verify_image(lines 217-223), andresume_image(lines 230-236).freeze_sourcealready bounds its wait withcommunicate(timeout=180). If a restored program hangs, the proof job blocks until the workflow-level timeout instead of failing with a clear error.♻️ Proposed change for `run_control`; apply the same to the other three helpers
+CLI_TIMEOUT = 600 + + def run_control(python: str, program: Path, home: Path) -> dict[str, Any]: @@ completed = subprocess.run( [*cli(python), "run", str(program)], cwd=str(REPOSITORY), env=environment(home), capture_output=True, text=True, + timeout=CLI_TIMEOUT, )🤖 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 `@validation/cross_python/cli_proof.py` around lines 105 - 116, Bound the subprocess waits in run_control, inspect_image, verify_image, and resume_image by adding the same finite timeout used for CLI execution, matching freeze_source’s 180-second limit. Ensure timeout failures propagate clearly rather than allowing a hung restored program to block until the workflow-level timeout.
342-344: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueThe replay check counts identical output text, not completed actions.
repeatedis the set intersection of source lines and resumed lines. Any line whose text appears in both halves counts as a repeated action, even when the program legitimately prints the same text twice. The harness docstring states that nothing here recognizes a particular program, so this heuristic can produce a falsePROOF FAILUREfor a different workload. Consider comparing positional prefixes of the control output instead, or record the heuristic and its assumption in the report.🤖 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 `@validation/cross_python/cli_proof.py` around lines 342 - 344, The replay check around source_lines, resumed_lines, and repeated incorrectly treats matching output text as repeated actions. Replace the set-based intersection heuristic with a positional comparison of the resumed output against the control output prefix, or explicitly report the heuristic and its assumption so identical legitimate lines do not cause false proof failures.tests/test_documentation_consistency.py (1)
30-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
version_tuplefails withValueErroron a non-numeric release segment.
int(part)raisesValueErrorfor a wildcard or prerelease segment, for example3.12.*or3.14.0rc1. The clause parser at lines 44-49 already fails loudly with a message for an unsupported operator. Add the same clear failure for an unparsable version so a futurerequires-pythonedit reports the cause instead of a bareValueError.♻️ Proposed change
def version_tuple(value: str) -> tuple[int, ...]: + assert re.fullmatch(r"\d+(\.\d+)*", value), f"unsupported version {value!r}" return tuple(int(part) for part in value.split("."))🤖 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 `@tests/test_documentation_consistency.py` around lines 30 - 31, Update version_tuple to catch non-numeric version segments while converting value.split(".") and raise a clear, contextual failure identifying the unparsable requires-python version, matching the clause parser’s explicit error behavior. Preserve normal tuple conversion for fully numeric versions..github/workflows/cross-python-cli-proof.yml (1)
163-163: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winMove
needs.*.outputsexpansion out of the shell script body.Line 163 and line 208 each expand
${{ needs.linux-py312-source.outputs.* }}directly inside arun:bash block. GitHub Actions substitutes${{ }}expressions textually before the shell runs the script, so any future change that lets this output carry shell metacharacters becomes an injection point. Today's values are hex strings (git rev-parse HEAD,shasum -a 256), so the immediate risk is low, but the pattern itself is the actual concern flagged by static analysis.Pass the value through
env:and reference it as an environment variable instead.🔒 Proposed fix
- name: Verify a clean native Apple Silicon target shell: bash + env: + SOURCE_COMMIT: ${{ needs.linux-py312-source.outputs.source_commit }} run: | set -Eeuo pipefail test "$(git rev-parse HEAD)" = "$GITHUB_SHA" - test "$GITHUB_SHA" = "${{ needs.linux-py312-source.outputs.source_commit }}" + test "$GITHUB_SHA" = "$SOURCE_COMMIT"- name: Confirm the image arrived byte-identical shell: bash + env: + EXPECTED_IMAGE_SHA256: ${{ needs.linux-py312-source.outputs.image_sha256 }} run: | set -Eeuo pipefail source_dir="$RUNNER_TEMP/source-artifact" if [[ -d "$source_dir/cross-python-source" ]]; then source_dir="$source_dir/cross-python-source" fi echo "SOURCE_DIR=$source_dir" >> "$GITHUB_ENV" actual="$(shasum -a 256 "$source_dir/source.cont" | cut -d' ' -f1)" - expected="${{ needs.linux-py312-source.outputs.image_sha256 }}" + expected="$EXPECTED_IMAGE_SHA256"Also applies to: 208-208
🤖 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 @.github/workflows/cross-python-cli-proof.yml at line 163, Update the run steps around the SHA comparisons at lines 163 and 208 to pass each needs.*.outputs value through the step’s env configuration, then reference the environment variable inside the bash commands instead of embedding GitHub expressions directly in the script body. Preserve the existing equality checks and output values.Source: Linters/SAST tools
validation/cross_python/differential.py (2)
548-561: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDocstring overstates the endpoint guarantee for large runs.
The docstring for
safe_points_forstates it is "always including its first and last" safe point. This is only true whentotal <= count(thelist(range(1, total))branch). Fortotal > count, points are sampled atstride * (index + 1), which does not include1ortotal - 1in general. For example,safe_points_for(37, 6)yields{5, 11, 16, 21, 26, 32}, excluding both endpoints.No existing test enforces the literal endpoint-inclusion claim for
total > count;test_sampling_stays_inside_the_runonly checks that points stay within[1, total). Since this function determines which safe points the corpus actually exercises, the docstring's claim could mislead future maintainers about edge-case coverage (e.g., entry/exit safe points) for larger programs.Correct the docstring to describe the actual behavior, or extend the sampling to guarantee both endpoints when
count >= 2.📝 Proposed docstring fix
def safe_points_for(total: int, count: int) -> list[int]: - """Spread checkpoints across a run, always including its first and last. + """Spread checkpoints roughly evenly across a run. + + Every interior safe point is used only when `total <= count`. For larger + runs, samples are stride-spaced and do not necessarily include safe + point 1 or `total - 1`. Sampling by execution position rather than by program feature keeps the corpus free of workload-specific knowledge. """🤖 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 `@validation/cross_python/differential.py` around lines 548 - 561, Update the docstring for safe_points_for to accurately describe its behavior: checkpoints are interior positions, and when total exceeds count they are sampled across the run without guaranteeing the first or last safe point. Do not change the sampling logic unless necessary to make the documented behavior accurate.
539-543: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winReplay-detection heuristic ignores line order and multiplicity.
compare()flags "completed actions repeated" usingset(prefix_lines) & set(suffix_lines). This treats any literal output line shared betweensource["stdout"]andtarget["stdout"]as evidence of replayed work, regardless of position or how many times the line legitimately occurs. A program whose output contains the same literal line more than once for unrelated reasons (not a replay) would trigger a false "silent mismatch" on an otherwise correct restore, and the release gate in.github/workflows/cross-python-cli-proof.ymlrequiressilent_mismatches == 0.The current test (
test_detects_replayed_completed_work) only exercises true replay (the source's first action line prepended to target output) and does not probe this false-positive path. Consider anchoring the check to the actual replay pattern instead: a target run replays completed work only if its output does not properly continue where the source left off, e.g., check whethertarget["stdout"]begins by re-emitting any of the trailing lines already present insource["stdout"], rather than checking global set intersection.🤖 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 `@validation/cross_python/differential.py` around lines 539 - 543, The replay heuristic in compare() incorrectly uses global set intersection, causing false positives from legitimate repeated output lines. Replace the repeated check with an order-aware prefix check that only flags target stdout when it begins by re-emitting trailing lines from source stdout, while preserving the existing diagnostic format and true replay detection.
🤖 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 `@continuum/abi.py`:
- Around line 434-452: Add Host.verified_platforms with a default derived from
TARGET_PLATFORMS. In decide_restore, require the parsed image platform pair to
be present in both target["platforms"] and host.verified_platforms, preserving
the existing unsupported-platform rejection when either allowlist does not
contain the pair.
In `@FORMAT.md`:
- Around line 134-136: Update FORMAT.md’s compatibility documentation for format
0.2: change the title to identify Portable Process Image 0.2, include both
CPython 3.12.13 and 3.13.14 in the accepted versions, and replace references to
target_compatibility.platforms with execution_contract.target while preserving
the surrounding compatibility entries.
In `@README.md`:
- Around line 106-131: Update the final sentence of the README proof section to
explicitly identify the IR 0.2 cross-platform proof and reference commit
15bceef, rather than using ambiguous wording such as “That proof” and “the
commit above.”
---
Nitpick comments:
In @.github/workflows/cross-python-cli-proof.yml:
- Line 163: Update the run steps around the SHA comparisons at lines 163 and 208
to pass each needs.*.outputs value through the step’s env configuration, then
reference the environment variable inside the bash commands instead of embedding
GitHub expressions directly in the script body. Preserve the existing equality
checks and output values.
In `@COMPATIBILITY.md`:
- Around line 9-19: Update the compatibility axes table to include
target.operating_systems, target.architectures, and target.platforms as
restore-gating dimensions, each marked as gated by abi.decide_restore. Place
them alongside the existing target.runtime_implementations and
target.python_versions rows.
In `@continuum/abi.py`:
- Around line 533-551: Reorder the exports in __all__ so all SCREAMING_CASE
constants appear first, followed by Host and IncompatibleImage, then the
lowercase functions; preserve every existing export without adding or removing
entries.
- Around line 120-121: Rename REASON_UNKNOWN_CAPABILITY to the clearer
mandatory-capability omission name throughout continuum/abi.py and all
references, including the assertions in tests/test_execution_abi.py and
tests/test_image_refusals.py. Preserve the existing reason code value and
behavior; update every occurrence consistently so the stable code remains
unchanged.
In `@continuum/cli.py`:
- Around line 974-985: Update the policy decision branch in continuum/cli.py to
handle POLICY_EXACT explicitly, adding the symbol to the existing continuum.abi
imports. Keep the current compatibility output only for POLICY_EXACT, and raise
ContinuumError with a clear message for any unrecognized policy instead of
indexing target_compatibility.
In `@continuum/image.py`:
- Around line 602-607: Update the runtime metadata validation errors in the
surrounding validation flow and _validate_legacy_compatibility so each refusal
identifies the disagreeing document pair, while preserving the existing “runtime
metadata is inconsistent” prefix and distinct behavior for each check.
In `@tests/test_documentation_consistency.py`:
- Around line 30-31: Update version_tuple to catch non-numeric version segments
while converting value.split(".") and raise a clear, contextual failure
identifying the unparsable requires-python version, matching the clause parser’s
explicit error behavior. Preserve normal tuple conversion for fully numeric
versions.
In `@tests/test_image.py`:
- Around line 179-201: Rename the test method from
test_incompatible_runtime_version_is_rejected to
test_rewritten_creator_python_provenance_is_rejected so it accurately reflects
the creator provenance validation exercised by its existing body.
In `@validation/cross_python/cli_proof.py`:
- Around line 105-116: Bound the subprocess waits in run_control, inspect_image,
verify_image, and resume_image by adding the same finite timeout used for CLI
execution, matching freeze_source’s 180-second limit. Ensure timeout failures
propagate clearly rather than allowing a hung restored program to block until
the workflow-level timeout.
- Around line 342-344: The replay check around source_lines, resumed_lines, and
repeated incorrectly treats matching output text as repeated actions. Replace
the set-based intersection heuristic with a positional comparison of the resumed
output against the control output prefix, or explicitly report the heuristic and
its assumption so identical legitimate lines do not cause false proof failures.
In `@validation/cross_python/differential.py`:
- Around line 548-561: Update the docstring for safe_points_for to accurately
describe its behavior: checkpoints are interior positions, and when total
exceeds count they are sampled across the run without guaranteeing the first or
last safe point. Do not change the sampling logic unless necessary to make the
documented behavior accurate.
- Around line 539-543: The replay heuristic in compare() incorrectly uses global
set intersection, causing false positives from legitimate repeated output lines.
Replace the repeated check with an order-aware prefix check that only flags
target stdout when it begins by re-emitting trailing lines from source stdout,
while preserving the existing diagnostic format and true replay detection.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8d1d1167-da12-4394-9d7b-7a5ba0adfd21
📒 Files selected for processing (26)
.github/workflows/cross-python-cli-proof.ymlCOMPATIBILITY.mdFORMAT.mdLANGUAGE_SUPPORT.mdLIMITATIONS.mdPORTABILITY.mdREADME.mdROADMAP.mdSTATUS.mdcompatibility/results/cross-python-3.12.13-to-3.13.14-linux-x86_64-2026-07-31.jsoncontinuum/__init__.pycontinuum/abi.pycontinuum/cli.pycontinuum/image.pydocs/RELEASE_NOTES_0.4.0a1.mddocs/TESTING.mdpyproject.tomltests/test_cli.pytests/test_cross_python_differential.pytests/test_documentation_consistency.pytests/test_execution_abi.pytests/test_image.pytests/test_image_refusals.pyvalidation/cross_python/cli_proof.pyvalidation/cross_python/differential.pyvalidation/cross_python/programs/layered_accumulator.py
…lone Verified the review finding before fixing it. On the previous head an image that added Windows arm64 to its own operating_systems, architectures, and platforms lists was ACCEPTED on a Windows arm64 host, even though the runtime's own TARGET_PLATFORMS has never contained that pair. The platform decision was single-sided: the untrusted document decided its own admissibility. That was inconsistent with the Python-version decision, which has been two-sided since the contract was introduced. Adds abi.VERIFIED_PLATFORMS, derived from TARGET_PLATFORMS, and Host.verified_platforms defaulted from it. decide_restore now requires the running pair in both the image's platform list and the runtime's accepted list, keeping the existing unsupported-platform reason code so no test depends on new prose. The two halves report different messages so a refusal says which side rejected it. Six contract-level tests cover both halves, a runtime narrowed by hand, every accepted pair still being accepted, and Windows arm64 being absent from the runtime list. Five image-level adversarial tests take a real image, insert Windows arm64 into every platform list it carries, and recompute every covered archive checksum so the artifact is internally consistent. One test asserts that premise explicitly, so the case can never pass for the wrong reason. The refusal is required to be deterministic across repeated attempts, to hold on every verified interpreter, to leave legitimate platforms working, and to hold through the public verify_image path rather than only the decision function. Also closes the two documentation findings. FORMAT.md was titled "Portable Process Image 0.1", named only CPython 3.12.13, and pointed at target_compatibility.platforms, which format 0.2 replaced with execution_contract.target. PORTABILITY.md carried the same three staleness issues in its compatibility list. README.md said "That proof ... at the commit above", which after the cross-Python section was inserted resolved to 40cc9dd rather than to the IR 0.2 proof at 15bceef; both proofs are now named. 313 tests green on CPython 3.12.13 and 3.13.14.
What this proves
Continuum can freeze a supported program through the public CLI on native Linux x86_64 under CPython 3.12.13, terminate and reap the source process, transfer the image unchanged, and verify/resume the same computation on native Apple Silicon macOS arm64 under CPython 3.13.14.
Latest proof-bearing implementation commit:
af80b785dc4f566c8fbedbdc05f1c7d0eb62d3f8.Latest completed native proof: Actions run 30671869025, evaluated on GitHub's PR merge commit
a7beb9057964a4df232bd0549152879e71bf7c5f.run,freeze,inspect,verify,resumea608bddf3a97306ddfce7adfd64da43a84ceeaba9b0d3051a8de7c5fb17f5dd7f17fcb9409916f0d95d91076a7cd6549e3a8408dc1a187180b9f74d82adddf8b370db292fc16df2e739ae9ca0004545da97f5dae44e74f0aa1df7d7b38482a87Execution compatibility contract
Image format 0.2 separates nine compatibility axes:
Creator identity is provenance. Restore is gated by exact ABI/capability compatibility, an exact Python allowlist, and two-sided platform authorization: the platform pair must be accepted independently by both the image contract and the runtime-owned
VERIFIED_PLATFORMSset.The platform gate was added after review found a real single-sided trust bug. Five adversarial tests now insert Windows arm64 into every document-side platform list, recompute all archive checksums, and require deterministic
unsupported-platformrefusal while legitimate verified pairs remain accepted.Format 0.1 images remain readable under their original exact-Python and exact-runtime rule.
Differential evidence
Cross-Python corpus, CPython 3.12.13 → 3.13.14:
Correctness among accepted cases is 100%. The comparison covers frame chains, logical positions, locals, lexical cells, operand stacks, control blocks, pending-finally state, shared identity, supported cycles, RNG state, supported file offsets, output, final result, and completed-action evidence. Fault injection confirms the oracle detects corruption, replay, and restart-from-entry behavior.
313 tests pass under both CPython 3.12.13 and 3.13.14.
Relationship to PR #1
PR #1 remains preserved as the original feasibility experiment. This PR replaces its private proof reader with the core image and public CLI path, avoids post-write manifest rewriting, and makes compatibility decisions from separated, testable axes.
Strongest supported claim
Not claimed
Arbitrary Python versions, arbitrary Python programs, native CPython frame migration, arbitrary process migration, thread/socket/subprocess/native-extension-state migration, or any verified Windows cross-platform path.
Release gate
0.4.0a1is prepared but not published. Merge and publication remain blocked until every check on the current branch head is complete and green.Note: the current branch head contains two housekeeping commits after
af80b78; their combined tree diff againstaf80b78is empty. They do not change the implementation or evidence above.