Skip to content
Merged
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
15 changes: 14 additions & 1 deletion .github/workflows/stress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,20 @@ jobs:
count=$("$PYBIN" -c "import unittest; l=unittest.TestLoader(); s=l.discover('tests', top_level_dir='.'); assert not l.errors, l.errors; f=lambda x: sum(map(f,x)) if isinstance(x,unittest.TestSuite) else 1; print(f(s))")
echo "discovered $count tests"
# A mistyped module name would otherwise repeat nothing, silently.
test "$count" -ge 160 || { echo "discovery too low: $count"; exit 1; }
# The gate tracks the published suite size. A loose floor -- this read
# `-ge 160` against a 402-test suite -- passes a regression that
# silently drops more than half of discovery, which is precisely what
# this preflight exists to catch.
# Captured with `|| documented=""` because `set -e` plus `pipefail`
# would otherwise abort on a no-match grep, killing the job before the
# diagnostic below can say why. `sed -n 1p` rather than `head -1` so a
# second match cannot SIGPIPE the producer under pipefail.
documented=$(grep -oE '[0-9]{2,4} tests' docs/TESTING.md \
| sed -n 1p | cut -d' ' -f1) || documented=""
test -n "$documented" || { echo "docs/TESTING.md states no count"; exit 1; }
test "$count" -eq "$documented" || {
echo "discovery $count does not match the documented $documented"
exit 1; }
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Repeat the targeted race regressions
shell: bash
Expand Down
4 changes: 2 additions & 2 deletions AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ reported:
continuum: error: Expecting value: line 1 column 1 (char 0)
```

The raw environment and output are stored in
`artifacts/baseline/linux-x86_64-python3.12.13.txt`. The race was fixed by
The failure text above is the retained record; the raw baseline log was never
committed to this tree. The race was fixed by
fully writing and fsyncing a hidden same-directory file, then atomically
publishing it with a no-clobber hard link. The integration test passed five
consecutive runs after the fix.
Expand Down
4 changes: 2 additions & 2 deletions PORTABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ implementation and can still have platform-specific behavior.
| IR 0.4/runtime 0.2.0 | Native Linux x86_64 | Native Apple Silicon macOS arm64 | **verified**; Actions run 30592158078 at commit `21f7b2e`, carrying a class, an instance, a live handler, variadic bindings, and a shared closure cell |
| Release IR 0.4/runtime 0.3.0 | Native Linux x86_64 | Native Apple Silicon macOS arm64 | **verified**; Actions run 30596179154 at commit `023f74c` |
| Container format 0.2/IR 0.4/execution ABI 1.0/runtime 0.4.0a1 | Native Linux x86_64, **CPython 3.12.13** | Native Apple Silicon macOS arm64, **CPython 3.13.14** | **verified**; Actions run 30658976309 at commit `40cc9dd`, image SHA-256 `3b564d9d37a9353ebb22027a4b3597d30fc2eef1272c3a220fc7f65e3d939824` identical at capture, on arrival, and after restore; driven entirely through the public CLI; 4 live frames; 0 completed actions repeated |
| Container format 0.2/IR 0.4/execution ABI 1.0/runtime 0.5.0a1 | Native Linux x86_64, **CPython 3.12.13** | Native Apple Silicon macOS arm64, **CPython 3.13.14** | **verified**; Actions run 30682958873, evaluated on merge commit `d328397`, image SHA-256 `8e4f4314b57a8c91611bdbe69576d055c54374987fe58255b58ee8399066e3f3` identical at capture, on arrival, and after restore; 4 live frames; 0 completed actions repeated. This rerun is the first with the corrected replay oracle, which compares line multiplicities against the uninterrupted control instead of intersecting the two halves |
| Container format 0.2/IR 0.4/execution ABI 1.0/runtime 0.5.0a1 | Native Linux x86_64, **CPython 3.12.13** | Native Apple Silicon macOS arm64, **CPython 3.13.14** | **verified**; Actions run 30682958873, evaluated on GitHub's pull-request merge commit `d328397`, which is generated per run and is not reachable from any branch in this repository, image SHA-256 `8e4f4314b57a8c91611bdbe69576d055c54374987fe58255b58ee8399066e3f3` identical at capture, on arrival, and after restore; 4 live frames; 0 completed actions repeated. This rerun is the first with the corrected replay oracle, which compares line multiplicities against the uninterrupted control instead of intersecting the two halves |
| Any revision | Native Windows x86_64 | Any other platform | unverified; no workflow generates or resumes a cross-host Windows image |
| Container format 0.2 | Any CPython outside `abi.VERIFIED_PYTHON_VERSIONS` | Any | unverified and refused before execution; the allowlist is exact, so 3.13.0 and 3.12.14 are refused as firmly as 3.9 |
| Any revision | Any other platform | Native Windows x86_64 | unverified; no workflow generates or resumes a cross-host Windows image |
Expand Down Expand Up @@ -170,6 +170,6 @@ in this package.
| Revisions | Source | Target | Status |
| --- | --- | --- | --- |
| A -> B, plan format 1.0 | Native Linux x86_64, CPython 3.12.13 | Native Apple Silicon macOS arm64, CPython 3.13.14 | **verified**; Actions run 30668706966 at commit `03da288`, image SHA-256 `fb847f3b1e7fab9921f46d97b4f6b996716e89bad7880ce5231f45d9ac8c4d80` identical at capture, on arrival, and after migration; 4 active frames and 20 bindings mapped totally; 30 action nonces each exactly once; 0 repeated; old revision's future behavior not executed, new revision's executed; zero oracle failures |
| A -> B, plan format 1.0 | Native Linux x86_64, CPython 3.12.13 | Native Apple Silicon macOS arm64, CPython 3.13.14 | **verified**; Actions run 30682958879, evaluated on merge commit `d328397`, image SHA-256 `10597941c210190f27e3af1905d7a2e038f4ee013c4a5bbc2a7c34b20caddb4c` identical at capture, on arrival, and after migration; same 4 frames, 20 bindings, 1 class, 30 nonces, 0 repeated, zero oracle failures. Repeated after review, because the earlier run's harness wrote `final-report.json` before its last four checks were appended and recorded `exited_and_reaped_before_target` as a literal; both are now measured, so this is the first run whose archived evidence is a measurement throughout |
| A -> B, plan format 1.0 | Native Linux x86_64, CPython 3.12.13 | Native Apple Silicon macOS arm64, CPython 3.13.14 | **verified**; Actions run 30682958879, evaluated on GitHub's pull-request merge commit `d328397`, which is generated per run and is not reachable from any branch in this repository, image SHA-256 `10597941c210190f27e3af1905d7a2e038f4ee013c4a5bbc2a7c34b20caddb4c` identical at capture, on arrival, and after migration; same 4 frames, 20 bindings, 1 class, 30 nonces, 0 repeated, zero oracle failures. Repeated after review, because the earlier run's harness wrote `final-report.json` before its last four checks were appended and recorded `exited_and_reaped_before_target` as a literal; both are now measured, so this is the first run whose archived evidence is a measurement throughout |

Everything outside the accepted edit classes in COMPATIBILITY.md is refused.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ source host recorded it; `NEW` is resolved on the current host.
python3 -m unittest discover -s tests -v
```

The suite discovers 402 tests and is run natively on Linux x86_64, Apple
The suite discovers 408 tests and is run natively on Linux x86_64, Apple
Silicon macOS arm64, and Windows x86_64 by `runtime-bundles.yml`. Tests whose
mechanism does not exist on the current host skip explicitly: POSIX signal
notification and the shell installer skip on Windows, and the native Apple
Expand Down
4 changes: 2 additions & 2 deletions STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ has no Windows job.
resumed on a native Apple Silicon macOS arm64 runner under CPython 3.13.14.
Actions run
[30682958879](https://github.com/byte271/Continuum/actions/runs/30682958879),
evaluated on merge commit `d328397`. Four active frames and twenty bindings
evaluated on GitHub's pull-request merge commit `d328397`, which is generated per run and is not reachable from any branch in this repository. Four active frames and twenty bindings
mapped totally,
the original image byte-identical throughout, 30 action nonces each executed
exactly once, zero repeated, the old revision's future behavior absent and
Expand Down Expand Up @@ -112,7 +112,7 @@ has no Windows job.
all four gates for 35 programs (70.0%), up from 32 (64.0%) before default
arguments. That rate is a Linux x86_64 measurement; the suite exercises two
corpus programs through all four gates on every host.
- Current full suite: 402 tests discovered. Tests skip only where the host
- Current full suite: 408 tests discovered. Tests skip only where the host
lacks the mechanism under test: the native Apple Silicon test skips off
macOS arm64, and POSIX signal notification, the shell installer, and the
symlink launcher skip on Windows.
Expand Down
17 changes: 17 additions & 0 deletions continuum/abi.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,22 @@ def legacy_decision(
ABI-compatible, this keeps the original strict rule and reports refusals
with the format version named, so the message explains *why* the stricter
rule applied.

The runtime's own platform allowlist is applied first, before either exact
check. The runtime side of the platform decision does not depend on what an
image declares, so it cannot depend on the container format either: an
older format is a reason to be stricter, never a way to reach a pair this
runtime has not verified.
"""

if (host.operating_system, host.architecture) not in host.verified_platforms:
raise IncompatibleImage(
REASON_UNSUPPORTED_PLATFORM,
f"this runtime does not accept platform {host.operating_system} "
f"{host.architecture}; accepted pairs are "
f"{[f'{name} {machine}' for name, machine in host.verified_platforms]}",
)

image_python = compatibility.get("python_version")
if image_python != host.python_version:
raise IncompatibleImage(
Expand Down Expand Up @@ -571,6 +585,9 @@ def contract_summary(contract: Mapping[str, Any]) -> dict[str, Any]:
"MANDATORY_CAPABILITIES",
"PROVIDED_CAPABILITIES",
"SUPPORTED_PYTHON",
"TARGET_ARCHITECTURES",
"TARGET_OPERATING_SYSTEMS",
"TARGET_PLATFORMS",
"VERIFIED_PLATFORMS",
"VERIFIED_PYTHON_VERSIONS",
"build_contract",
Expand Down
23 changes: 16 additions & 7 deletions continuum/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
GRAPH_CODEC_VERSION,
LEGACY_CONTAINER_FORMAT_VERSION,
POLICY_EXECUTION_ABI,
TARGET_ARCHITECTURES,
TARGET_OPERATING_SYSTEMS,
VERIFIED_PLATFORMS,
VERIFIED_PYTHON_VERSIONS,
normalized_architecture,
)
Expand Down Expand Up @@ -293,11 +296,7 @@ def _sessions() -> int:
def _doctor(args: argparse.Namespace) -> int:
current_python = platform.python_version()
current_system = platform.system()
current_machine = {
"amd64": "x86_64",
"x64": "x86_64",
"aarch64": "arm64",
}.get(platform.machine().lower(), platform.machine().lower())
current_machine = normalized_architecture()
manifest_path = os.environ.get("CONTINUUM_BUNDLE_MANIFEST")
bundle_manifest = None
problems = []
Expand All @@ -307,10 +306,20 @@ def _doctor(args: argparse.Namespace) -> int:
f"Python {current_python} is not verified by this runtime; verified "
f"CPython versions are {list(VERIFIED_PYTHON_VERSIONS)}"
)
if current_system not in {"Linux", "Darwin", "Windows"}:
if current_system not in TARGET_OPERATING_SYSTEMS:
problems.append(f"unsupported operating system: {current_system}")
if current_machine not in {"x86_64", "arm64"}:
if current_machine not in TARGET_ARCHITECTURES:
problems.append(f"unsupported architecture: {current_machine}")
# The axis checks above accept the whole 3x2 product. Membership in both
# axes is not membership in the pair set: Windows arm64 satisfies each axis
# and is still refused at restore. `doctor` answers "will this host work?",
# so it has to ask the same question the runtime does.
if (current_system, current_machine) not in VERIFIED_PLATFORMS:
problems.append(
f"this runtime does not accept platform {current_system} "
f"{current_machine}; accepted pairs are "
f"{[f'{name} {machine}' for name, machine in VERIFIED_PLATFORMS]}"
)

if manifest_path:
path = Path(manifest_path)
Expand Down
15 changes: 13 additions & 2 deletions continuum/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import random
from typing import Any

# The graph codec version is declared once, in `abi`, because the execution
# contract advertises it as a capability. Restating it here let the bytes this
# module writes disagree with the capability the runtime claims.
from .abi import GRAPH_CODEC_VERSION
from .errors import ImageError, UnsupportedObjectError
from .resources import PortableFile
from .values import (
Expand Down Expand Up @@ -35,7 +39,11 @@ def __init__(self, max_objects: int = 2_000_000):

def encode(self, root: Any) -> dict[str, Any]:
encoded_root = self._value(root)
return {"codec_version": "0.1", "root": encoded_root, "objects": self.nodes}
return {
"codec_version": GRAPH_CODEC_VERSION,
"root": encoded_root,
"objects": self.nodes,
}

def _reference(self, value: Any, kind: str) -> tuple[dict[str, Any], dict[str, Any]] | None:
identity = id(value)
Expand Down Expand Up @@ -222,7 +230,10 @@ def __init__(
resources: dict[str, PortableFile] | None = None,
max_objects: int = 2_000_000,
):
if not isinstance(document, dict) or document.get("codec_version") != "0.1":
if (
not isinstance(document, dict)
or document.get("codec_version") != GRAPH_CODEC_VERSION
):
raise ImageError("unsupported heap codec version")
self.nodes = document.get("objects")
if not isinstance(self.nodes, list) or len(self.nodes) > max_objects:
Expand Down
32 changes: 32 additions & 0 deletions continuum/migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,31 @@
PLAN_FORMAT_VERSION = "1.0"
PLAN_ENTRIES = ("plan.json", "new_source.py", "new_ir.json", "checksums.json")

# Every field `plan.json` must carry. Checked when the plan is read, so a
# caller that only reads -- `inspect-upgrade` prints fifteen of these -- gets a
# refusal naming the missing field rather than a KeyError traceback from deep
# inside the printer. Verification re-derives the whole document and would
# catch the same absence, but reading is a public entry point on its own.
PLAN_FIELDS = (
"plan_format_version",
"semantic_model_version",
"execution_abi_version",
"original_image_sha256",
"old_source_sha256",
"old_ir_sha256",
"new_source_sha256",
"new_ir_sha256",
"entry_program",
"active_frames",
"frame_mappings",
"binding_mappings",
"control_region_mappings",
"class_mappings",
"accepted_edit_classes",
"assumptions",
"mapping_is_total",
)

# Refusal reason codes. Every one names a specific unmappable element.
REFUSE_ACTIVE_FUNCTION_MISSING = "active-function-missing"
REFUSE_ACTIVE_FUNCTION_AMBIGUOUS = "active-function-ambiguous"
Expand Down Expand Up @@ -805,6 +830,13 @@ def read_plan(path: str | os.PathLike[str]) -> tuple[dict[str, Any], str, dict[s
)

plan = _plan_json(raw["plan.json"], "plan.json")
missing = [field for field in PLAN_FIELDS if field not in plan]
if missing:
raise MigrationRefused(
REFUSE_MALFORMED_PLAN,
"plan.json",
f"plan omits required fields: {missing}",
)
if plan.get("plan_format_version") != PLAN_FORMAT_VERSION:
raise MigrationRefused(
REFUSE_UNKNOWN_PLAN_VERSION,
Expand Down
4 changes: 2 additions & 2 deletions docs/RELEASE_NOTES_0.5.0a1.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ the edit. Verified simultaneously across operating system, architecture, Python
version, and source revision.

[Actions run 30682958879](https://github.com/byte271/Continuum/actions/runs/30682958879),
evaluated on merge commit `d328397`:
evaluated on GitHub's pull-request merge commit `d328397`, which is generated per run and is not reachable from any branch in this repository:

| Property | Result |
| --- | --- |
Expand Down Expand Up @@ -91,7 +91,7 @@ them by a different rule.

**Accepted-migration correctness: 100%.**

402 tests green on CPython 3.12.13 and 3.13.14.
408 tests green on CPython 3.12.13 and 3.13.14.

## A bug the sweep found

Expand Down
13 changes: 9 additions & 4 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ $env:PYTHONPATH = "."; python benchmarks\measure.py `
--iterations 10000 --repetitions 5
```

The suite discovers 402 tests on every host. Skips are explicit and
The suite discovers 408 tests on every host. Skips are explicit and
mechanism-bound rather than platform exclusions:

| Host | Skipped |
Expand All @@ -67,9 +67,14 @@ mechanism-bound rather than platform exclusions:
| macOS arm64 | native Apple Silicon test, unless `CONTINUUM_LINUX_IMAGE` supplies a qualified Linux image |
| Windows x86_64 | native Apple Silicon test, two POSIX signal-notification tests, the POSIX shell-installer test, the POSIX symlink-launcher test |

Raw untouched-baseline and final proof logs are under `artifacts/`; corpus and
benchmark samples are under their respective `results/` directories. The
published corpus and benchmark numbers are Linux x86_64 measurements.
On every host the static undefined-name gate also skips unless `pylint` is
importable. It is not a runtime dependency; the stress workflow installs it, so
that job is the one where the gate actually runs.

Corpus and benchmark samples are under their respective `results/` directories.
The published corpus and benchmark numbers are Linux x86_64 measurements. Raw
untouched-baseline and final proof logs are attached to the Actions runs cited
in STATUS.md rather than committed to the tree.

## Real cross-platform protocol

Expand Down
31 changes: 31 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from continuum import IR_VERSION, SUPPORTED_PYTHON, __version__
from continuum.abi import (
CONTAINER_FORMAT_VERSION,
VERIFIED_PLATFORMS,
VERIFIED_PYTHON_VERSIONS,
build_contract,
)
Expand Down Expand Up @@ -132,6 +133,36 @@ def test_doctor_accepts_windows_x86_64(self):
" ".join(report["verified_cross_platform_paths"]),
)

def test_doctor_refuses_a_platform_pair_the_runtime_does_not_accept(self):
"""Membership in both axes is not membership in the pair set.

Windows is a supported operating system and arm64 is a supported
architecture, but the pair is not one this runtime accepts, and a
restore on it is refused. `doctor` answers "will this host work?", so
reporting no problem here would be reporting the opposite of the truth.
"""

self.assertNotIn(("Windows", "arm64"), VERIFIED_PLATFORMS)
output = io.StringIO()
with (
mock.patch.dict(os.environ, {"CONTINUUM_BUNDLE_MANIFEST": ""}),
mock.patch.object(platform, "system", return_value="Windows"),
mock.patch.object(platform, "machine", return_value="ARM64"),
redirect_stdout(output),
):
result = _doctor(argparse.Namespace(json=True))

report = json.loads(output.getvalue())
self.assertEqual(report["os"], "Windows")
self.assertEqual(report["architecture"], "arm64")
self.assertNotEqual(result, 0)
self.assertTrue(
any("Windows arm64" in problem for problem in report["problems"]),
report["problems"],
)
# The runtime is the authority; doctor must not invent its own list.
self.assertNotIn("Windows arm64", report["format_compatible_targets"])

def test_doctor_validates_self_contained_manifest(self):
with tempfile.TemporaryDirectory() as temporary:
manifest = Path(temporary) / "runtime-manifest.json"
Expand Down
Loading
Loading