diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 0129902..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: ci -on: - push: - pull_request: - -jobs: - local-gate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - run: python -m compileall -q reference tools tests - - run: python tools/run_local_gate.py - - run: python -m pip install -r requirements-ci.txt - - run: python -m pytest -q diff --git a/.github/workflows/seed-stutter-assurance.yml b/.github/workflows/seed-stutter-assurance.yml deleted file mode 100644 index 93f7789..0000000 --- a/.github/workflows/seed-stutter-assurance.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Seed stutter assurance - -on: - pull_request: - push: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - -jobs: - seed-stutter-assurance: - runs-on: ubuntu-24.04 - steps: - - name: Checkout Worker Extension - uses: actions/checkout@v4 - - - name: Checkout pinned public ASET assurance - uses: actions/checkout@v4 - with: - repository: attractor-set/ASET - ref: e89d984203a126f8bc62467224cdf6c5374dada7 - path: .upstream/ASET - persist-credentials: false - - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - run: python -m pip install -r requirements-ci.txt - - run: python .upstream/ASET/tools/build_seed_recognition_boundary_assurance.py --check - - name: Check Worker -> Seed stutter -> public-v60 assurance - run: >- - python tools/check_seed_stutter_assurance.py - --seed-root .upstream/ASET - --output dist/worker-seed-stutter-assurance.json - - run: python -m pytest -q tests/test_seed_stutter_assurance.py - - - uses: actions/upload-artifact@v4 - if: always() - with: - name: worker-seed-stutter-assurance - if-no-files-found: warn - path: dist/worker-seed-stutter-assurance.json diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..64ca70c --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,109 @@ +name: verify + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - run: python -m pip install -r requirements-ci.txt + + - name: Materialize exact ASET Seed 0.4alpha base + shell: bash + run: | + set -euo pipefail + seed_tag="seed-0.4alpha-3way" + seed_commit="0028f1d25a4f1d052a9b998baf402898446ac599" + seed_root="$RUNNER_TEMP/aset-seed-alpha4" + seed_release_zip="$RUNNER_TEMP/ASET-Seed-0.4alpha.zip" + seed_profiles_zip="$RUNNER_TEMP/ASET-Seed-0.4alpha-profiles.zip" + seed_release_unpack="$RUNNER_TEMP/aset-seed-release" + seed_profiles_unpack="$RUNNER_TEMP/aset-seed-profiles" + + git clone --depth 1 --branch "$seed_tag" \ + https://github.com/attractor-set/aset-seed.git "$seed_root" + test "$(git -C "$seed_root" rev-parse HEAD)" = "$seed_commit" + + curl --fail --location --retry 3 \ + --output "$seed_release_zip" \ + "https://github.com/attractor-set/aset-seed/releases/download/$seed_tag/ASET-Seed-0.4alpha.zip" + curl --fail --location --retry 3 \ + --output "$seed_profiles_zip" \ + "https://github.com/attractor-set/aset-seed/releases/download/$seed_tag/ASET-Seed-0.4alpha-profiles.zip" + + echo "4170d9111c353c3607cf9ada3398c15007acfed7b2d486f5376c72d3f13ed331 $seed_release_zip" \ + | sha256sum --check + echo "790588c145a390da6d47ac08901945253904aa053d170bfd35f6fb20dd1ae5a1 $seed_profiles_zip" \ + | sha256sum --check + + mkdir -p "$seed_release_unpack" "$seed_profiles_unpack" + unzip -q "$seed_release_zip" -d "$seed_release_unpack" + unzip -q "$seed_profiles_zip" -d "$seed_profiles_unpack" + + seed_release_root="$seed_release_unpack/ASET-Seed-0.4alpha" + seed_profiles_root="$seed_profiles_unpack/ASET-Seed-0.4alpha-profiles" + test -f "$seed_release_root/RELEASE_MANIFEST.json" + test -f "$seed_profiles_root/RELEASE_PROFILE_MANIFEST.json" + + echo "SEED_ALPHA4_ROOT=$seed_root" >> "$GITHUB_ENV" + echo "SEED_RELEASE_ROOT=$seed_release_root" >> "$GITHUB_ENV" + echo "SEED_PROFILES_ROOT=$seed_profiles_root" >> "$GITHUB_ENV" + + - name: Download pinned TLAPM + shell: bash + run: | + set -euo pipefail + archive="$RUNNER_TEMP/tlapm-1.6.0-pre-x86_64-linux-gnu.tar.gz" + unpack="$RUNNER_TEMP/tlapm-unpacked" + curl --fail --location --retry 3 \ + --output "$archive" \ + https://github.com/tlaplus/tlapm/releases/download/1.6.0-pre/tlapm-1.6.0-pre-x86_64-linux-gnu.tar.gz + echo "bfa5e5350ac1ec7202feecad0a4a71a5bb58c16a49660448b35b6f371ba9e2f5 $archive" \ + | sha256sum --check + mkdir -p "$unpack" + tar -xzf "$archive" -C "$unpack" + tlapm_bin="$(find "$unpack" -type f -path '*/bin/tlapm' -print -quit)" + test -n "$tlapm_bin" + test -x "$tlapm_bin" + test "$("$tlapm_bin" --version)" = "4600b24" + echo "TLAPM_BIN=$tlapm_bin" >> "$GITHUB_ENV" + + - name: Verify and materialize Runtime Alpha4 release + run: | + python -m tools.alpha4_runtime_release_gate \ + --seed-root "$SEED_ALPHA4_ROOT" \ + --seed-release-root "$SEED_RELEASE_ROOT" \ + --seed-profiles-root "$SEED_PROFILES_ROOT" \ + --tlapm "$TLAPM_BIN" + + - name: Verify exact committed tree + shell: bash + run: | + set -euo pipefail + git diff --exit-code -- . + git diff --cached --exit-code -- . + test -z "$(git status --porcelain --untracked-files=all)" + + - name: Upload Runtime Alpha4 release assurance + uses: actions/upload-artifact@v4 + with: + name: aset-runtime-alpha4-release-${{ github.sha }} + if-no-files-found: error + path: | + dist/ASET-Runtime-0.1.0-alpha.4.zip + dist/ASET-Runtime-0.1.0-alpha.4-profiles.zip + dist/runtime-release-assembled-tlaps-evidence.json + dist/runtime-python-airgap-evidence.json + dist/runtime-release-admission-certificate.json + dist/runtime-public-release-audit.json diff --git a/.gitignore b/.gitignore index 05cbaf7..52ce2e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,13 @@ -# Python __pycache__/ *.py[cod] .pytest_cache/ -.coverage -htmlcov/ - -# Virtual environments +.ruff_cache/ .venv/ venv/ - -# TLA+ / TLAPS local caches .tlacache/ - -# Local formal execution workspace -dist/formal-candidate/ - -# Editors / OS +dist/ +.upstream/ .vscode/ .idea/ *~ .DS_Store - -# Reproducible local formal release execution output -dist/formal-release-gate.json - -# Pinned public assurance checkout -.upstream/ - -# Local Seed stutter assurance evidence -dist/worker-seed-stutter-assurance.json diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..85db2bc --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,12 @@ +cff-version: 1.2.0 +message: "If you use ASET Runtime, cite the exact verified release." +title: "ASET Runtime" +type: software +abstract: "ASET Runtime is the bounded execution lifecycle extension for ASET Seed 0.4alpha." +authors: + - family-names: "Prychyna" + given-names: "Dzmitry" + alias: "Attractor Set" +version: "0.1.0-alpha.4" +license: Apache-2.0 +repository-code: "https://github.com/attractor-set/aset-runtime" diff --git a/NOTICE b/NOTICE index 2ef3cee..51c8117 100644 --- a/NOTICE +++ b/NOTICE @@ -1,2 +1,5 @@ -ASET Worker Extension -Copyright 2026 ASET contributors +ASET Runtime +Copyright 2026 Dzmitry Prychyna, publicly known as Attractor Set. +Original author and copyright holder: Dzmitry Prychyna. + +Licensed under the Apache License, Version 2.0. diff --git a/README.md b/README.md index aa3f2ff..099d248 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,67 @@ -# ASET Worker Extension +# ASET Runtime -`aset-worker-extension` is the minimal productive-attempt boundary of ASET. +ASET Runtime 0.1.0-alpha.4 is the current public representation of the bounded +execution lifecycle extension for ASET Seed 0.4alpha. -The normative bootstrap surface recognizes one work identity through only two operations: +**Execution may produce material. Recognition remains local to Seed.** -```text -UNREGISTERED - | - | START_WORK - v - RUNNING - / \ - / \ -END END - | | -RESULT NO_RESULT - \ / - \_XOR/ -``` - -The canonical state is append-only: a work identity first gains one exact immutable started-work binding and may later gain one exact immutable terminal record. `RUNNING`, `RESULT`, and `NO_RESULT` are projections of those facts. +Runtime owns exact execution-attempt records and lifecycle transitions only. It +does not own Seed recognition, Authority, or external effect permission. Every +Runtime-only transition preserves the exact bound Seed state. -`NO_RESULT` is a first-class terminal assertion. It is **not** the absence of a record and it is not equivalent to `RUNNING` without a terminal record. +Terminal statements distinguish `RESULT` from `NO_RESULT`; neither term is a quality +judgment and neither grants recognition. -`RESULT` does not mean success, and `NO_RESULT` does not mean failure. Worker standardizes only whether one exact productive attempt terminally produced result material. +## Active structure -Assignment, acceptance, queueing, scheduling, retry provenance, descriptor internals, verification policy and result quality are deliberately outside the Worker canon. Profiles may define them without changing the base lifecycle. +- `runtime/alpha4/operational/` — independently authored restricted-Forth + operational representation. +- `runtime/alpha4/formal/` — relational representation, formal reflection, and + mechanical proof surface. +- `runtime/alpha4/causal/` — independently authored causal representation. +- `runtime/alpha4/RUNTIME.aset` — non-semantic composition and identity + manifest. +- `upstream/ASET_SEED_ALPHA4_BINDING.aset` — content-addressed binding to the + exact ASET Seed 0.4alpha subject and release companions. +- `tools/alpha4_runtime_gate.py` — complete source-assurance gate. +- `tools/alpha4_runtime_release_gate.py` — deterministic release, post-build + proof, companion, admission, and public-audit gate. +- `history/REFERENCES.aset` — immutable reference to the superseded public + predecessor; history is not active semantics. -Worker output, evidence and execution do not create ASET Seed Authority, do not create a Seed Resolution, and do not grant external effect permission by implication. +The 0.1.0-alpha.4 representation claims no compatibility with the predecessor +bootstrap. -## Bootstrap status +## Assurance boundary -This semantic revision is `0.1.0-alpha.1` / `ASET-WORKER-CANON-0.1-ALPHA2` and is not release-ready. Because the lifecycle was minimized after the previous proof materialization, formal assurance is intentionally reset to `OPEN`; the new generated projection, lifecycle safety proof candidate and Seed-stuttering proof candidate must be mechanically closed again before release. +The operational, relational, and causal representations are independently +authored and mechanically cross-checked with semantic precedence `NONE`. +Runtime extends Seed only through the exact Seed preservation boundary and does +not copy, redefine, or replace Seed recognition semantics. -## Local gate +Source TLAPS proves the Runtime operational/relational pairing and the Seed +preservation boundary. The deterministic release builder then materializes +`formal/AssembledRuntime.tla`; a separate post-build TLAPS verifier proves the +assembled Runtime release against the exact bound Seed preservation relations. +Verification runs outside the release tree and checks exact release identities. -```bash -python tools/run_local_gate.py -``` +English and Python are downstream release companion extensions, not additional +assurance representations. Both are bound to the exact released Seed companion +base. The Python companion is admitted through an independent air-gap verifier +and Runtime-only transitions leave the Seed state observationally unchanged. -Optional pytest suite: +Verify the source surface with: -```bash -python -m pytest -q +```text +python -m tools.alpha4_runtime_gate ``` -The local gate uses only the Python standard library. - -## Public v60 Seed-stutter assurance +The complete release gate requires the exact Seed source, Seed release tree, +Seed companion tree, and TLAPM and is implemented by +`tools.alpha4_runtime_release_gate.py`. -`ASET-WORKER-SEED-STUTTER-ASSURANCE-V1` is a separate non-normative assurance -perimeter. When the materialized Worker-to-Seed stuttering evidence is -`MECHANICALLY_PROVED` (as in the current proof artifact), the checker composes -that evidence with the public ASET v60 recognition-boundary assurance only when -both bind the exact same frozen `SeedResolution.tla` subject. +SHA-256 identifies exact release bytes; semantic integrity is established by +declared relations and proof obligations. Generated evidence has semantic +precedence `NONE`. -This does not create a new composed TLAPS theorem and does not change Worker -semantics: productive work remains non-authoritative and grants no Seed -recognition or external effect permission by implication. +Copyright and attribution are in `NOTICE`. Licensing terms are in `LICENSE`. diff --git a/README.ru.md b/README.ru.md deleted file mode 100644 index c1f8b2f..0000000 --- a/README.ru.md +++ /dev/null @@ -1,33 +0,0 @@ -# ASET Worker Extension - -Это минимальная semantic boundary продуктивной попытки ASET. - -Базовый Worker теперь знает только два перехода: - -```text -UNREGISTERED --START_WORK--> RUNNING --END_WORK(RESULT|NO_RESULT)--> terminal -``` - -Каноническое состояние append-only: сначала появляется exact immutable started-work binding, затем при завершении — один exact immutable terminal record. `RUNNING`, `RESULT` и `NO_RESULT` являются проекциями этих фактов. - -`NO_RESULT` — явно зафиксированный терминальный исход, а не отсутствие записи. `RESULT` не означает успех, а `NO_RESULT` не означает провал. - -Assignment, acceptance, очередь, scheduling, retry provenance, внутреннее устройство work descriptor, verification policy и качество результата находятся вне Worker canon и могут определяться профилями. - -Worker, его способность, исполнение, результат и evidence сами по себе не создают Authority, Seed Resolution, признанное изменение Context или разрешение на внешний эффект. - -Текущая semantic revision: `0.1.0-alpha.1` / `ASET-WORKER-CANON-0.1-ALPHA2`. После минимизации предыдущие materialized proofs намеренно не переносятся: formal closure должен быть выполнен заново для новой модели. - -Локальная bootstrap-проверка: - -```bash -python tools/run_local_gate.py -``` - -## Public v60 assurance Seed-stutter - -Ненормативный профиль `ASET-WORKER-SEED-STUTTER-ASSURANCE-V1` связывает -материализованное доказательство Worker -> Seed stuttering с публичной -assurance-базой ASET v60 только через точный общий `SeedResolution.tla`. -Это не новый составной TLAPS theorem и не изменение Worker semantics: Worker -не создаёт Seed recognition и не получает право внешнего эффекта по факту работы. diff --git a/assurance/seed-stutter/ASSURANCE_PROFILE.json b/assurance/seed-stutter/ASSURANCE_PROFILE.json deleted file mode 100644 index 90dcfd3..0000000 --- a/assurance/seed-stutter/ASSURANCE_PROFILE.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "assurance_id": "ASET-WORKER-SEED-STUTTER-ASSURANCE-V1", - "document_type": "aset-worker-seed-stutter-assurance-profile", - "schema_version": 1, - "normative": false, - "normative_precedence": "NONE", - "relation_type": "EVIDENCE_COMPOSITION_OVER_SHARED_SEED_SUBJECT", - "worker_subject": { - "canon_id": "ASET-WORKER-CANON-0.1-ALPHA2", - "extension_version": "0.1.0-alpha.1", - "seed_refinement_scope": "WORKER_ONLY_OPERATIONS_AS_PINNED_SEED_STUTTER", - "seed_refinement_obligations": 19, - "model_sha256": "sha256:e7769e1ea41fce4ebf05f66adb03f6c048f3040ec215011c8d070b62a32b8ff0", - "seed_stuttering_sha256": "sha256:a0b91fb37442b031ab31960f72b072644116f31f9d8797b756c5c183d72f2b5e", - "seed_stuttering_proof_sha256": "sha256:8f5f8a5c3ba55436511ea792e69ec6fbd2131e1a767c31339c253f6751aab19f", - "seed_refinement_evidence_sha256": "sha256:9f2ee796783bbd7476234e41acf16b2a8ae588a30f226d7ebf13df7058e81e2f" - }, - "shared_seed_subject": { - "canon_id": "ASET-SEED-RESOLUTION-CANON-0.3-ALPHA1", - "canon_version": "0.3.0-alpha.1", - "seed_resolution_sha256": "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926" - }, - "public_v60_subject": { - "repository": "https://github.com/attractor-set/ASET", - "commit": "e89d984203a126f8bc62467224cdf6c5374dada7", - "assurance_id": "ASET-SEED-RECOGNITION-BOUNDARY-ASSURANCE-V60", - "package_file_sha256": "sha256:1b1efd4c75e253c78080423275963629c014085a73f27a2259c08de1c624bbd8", - "package_digest": "sha256:d537ad0555a0746e297f309e841aaccc8f059a44177400fd155253037a31747c", - "expected_tlaps_obligations": 2257, - "required_proof_relations": [ - { - "id": "CANONICAL_PHASE_TO_SEED", - "final_theorem": "CanonicalPhaseSeedRefinesSeedResolution", - "expected_obligations": 299 - }, - { - "id": "SEED_TO_CANONICAL_PHASE", - "final_theorem": "SeedResolutionRefinesCanonicalPhaseSeed", - "expected_obligations": 370 - } - ] - }, - "projection_contract": { - "worker_operations": "SEED_STUTTER", - "worker_owned_seed_state": false, - "worker_creates_seed_resolution": false, - "worker_grants_external_effect_permission": false - }, - "claim_boundary": { - "included": [ - "exact identity composition of the mechanically materialized Worker-to-Seed stuttering proof with public v60 over the same SeedResolution source", - "Worker lifecycle transitions preserve Seed-owned state", - "Worker result material does not create Seed recognition or effect permission" - ], - "excluded": [ - "a new mechanically composed Worker-to-v60 TLAPS theorem", - "normative modification of ASET Seed or ASET Worker Extension", - "implementation conformance", - "worker result quality, verification policy, liveness, cryptographic correctness, scheduling or execution technology" - ] - } -} diff --git a/assurance/seed-stutter/README.md b/assurance/seed-stutter/README.md deleted file mode 100644 index 9e399ae..0000000 --- a/assurance/seed-stutter/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Seed stutter assurance - -`ASET-WORKER-SEED-STUTTER-ASSURANCE-V1` is a non-normative evidence-composition -perimeter for the Worker Extension. - -```text -Worker lifecycle transitions - | - | mechanically materialized Worker -> Seed stuttering proof - v -exact SeedResolution.tla (unchanged projection) - | - | public ASET v60 recognition-boundary assurance - v -canonical recognition boundary -``` - -The checker requires the materialized Worker Seed-refinement evidence and the -public v60 package to bind the exact same `SeedResolution.tla` SHA-256. It fails -closed on any mismatch. - -This is not a new mechanically composed theorem and it does not modify Worker or -Seed normative semantics. Worker productive state remains non-authoritative: -Worker transitions create no Seed Resolution, own no Seed state and grant no -external effect permission by implication. - -Run against the pinned public ASET assurance checkout: - -```bash -python tools/check_seed_stutter_assurance.py \ - --seed-root ~/ASET-public-assurance-e89d9842 \ - --output dist/worker-seed-stutter-assurance.json -``` diff --git a/docs/architecture/GENERATIVE_VERIFICATION_LOOP.md b/docs/architecture/GENERATIVE_VERIFICATION_LOOP.md deleted file mode 100644 index afb1dd5..0000000 --- a/docs/architecture/GENERATIVE_VERIFICATION_LOOP.md +++ /dev/null @@ -1,31 +0,0 @@ -# Generative-verification interpretation - -This document is explanatory and non-normative. - -A useful intuition is a generator evaluated by a mathematical teacher: - -```text -Worker - | - v -candidate/result material - | - v -evidence / verification material - | - v -target-local Context machine -``` - -The analogy is deliberately limited. This is **not GAN semantics**. The pinned Seed semantics are not a learned discriminator and are not co-optimized against the Worker. A Worker may adapt to the constraints of recognized Context evolution; those constraints do not adapt merely because the Worker repeatedly fails to satisfy them. - -A closer technical analogy is candidate generation or synthesis under an external verifier. Even that analogy is only explanatory: the Worker extension itself does not define a verifier or a learning algorithm. - -Two distinct questions must remain separate: - -```text -optimization: which produced material appears better? -admissibility: which consequential change may be recognized? -``` - -Worker standardizes the productive side of the boundary, not the normative decision. diff --git a/docs/architecture/STATE_MACHINE.md b/docs/architecture/STATE_MACHINE.md deleted file mode 100644 index 85819b8..0000000 --- a/docs/architecture/STATE_MACHINE.md +++ /dev/null @@ -1,23 +0,0 @@ -# Work lifecycle state machine - -For each `work_id`, absence from Worker state is the implicit `UNREGISTERED` condition. - -The only normative Worker operations are: - -```text -UNREGISTERED --START_WORK----------------------> RUNNING -RUNNING --END_WORK(kind=RESULT)-----------> RESULT -RUNNING --END_WORK(kind=NO_RESULT)--------> NO_RESULT -``` - -The implementation may expose `RESULT` and `NO_RESULT` as derived states; canonically they are the mutually exclusive kinds of one immutable terminal record. - -`START_WORK` establishes the exact immutable binding of one productive attempt. The work descriptor is opaque to the Worker canon. Its internal structure belongs to a profile or implementation. - -`END_WORK` terminates exact running work. `NO_RESULT` is explicit and never inferred from missing output or missing terminal state. - -There is no `ACCEPTED`, `FAILED`, `SUCCESS`, `TIMEOUT`, `CANCELLED`, `PARTIAL`, or `ABORTED` state in the base lifecycle. Assignment, acceptance, queueing and such classifications may exist in profiles or orchestration. - -Terminal work is never reopened. Any later productive attempt uses a fresh `work_id`. Whether that later attempt is a retry, successor, alternative or unrelated work is provenance outside the Worker lifecycle canon. - -No liveness claim is made. A work identity may remain `RUNNING` indefinitely unless a stricter profile adds independently stated liveness conditions. diff --git a/docs/architecture/WORKER_ROLE.md b/docs/architecture/WORKER_ROLE.md deleted file mode 100644 index 18e41cd..0000000 --- a/docs/architecture/WORKER_ROLE.md +++ /dev/null @@ -1,37 +0,0 @@ -# Worker role - -## Productive boundary - -A Worker is an implementation-neutral source of productive work. It may be a human, an AI model, a deterministic program, a solver, a compiler, a tool, a remote service, a physical actuator, or another implementation. - -The Worker extension does not standardize how work is assigned, described internally or performed. It standardizes only one exact productive attempt: - -```text -exact START_WORK binding - | - v - RUNNING - / \ - / \ - RESULT NO_RESULT -``` - -`RESULT` means that exact result material was terminally produced. `NO_RESULT` means that the exact attempt terminally produced no result material. Neither state evaluates quality, correctness, usefulness, policy compliance or acceptability. - -## Descriptor opacity - -`START_WORK` binds an opaque exact `work_descriptor_binding`. Profiles may put repository coordinates, prompts, skills, MCP tools, models, input artifacts, constraints or other information behind that binding. None of those structures belong to the Worker canon. - -## Productive power is not normative power - -```text -productive power != normative power -``` - -Worker execution, terminal result material and evidence do not create Resolution Authority and do not become recognized Context state by implication. - -Worker transitions are Seed-stuttering extension transitions: Worker state may change while the pinned Seed projection remains unchanged. Consequential recognition of Worker material, when required, occurs through a separate target-local Context/Seed path. - -## Non-goals - -The Worker extension does not define task discovery, task decomposition, eligibility, assignment, acceptance, queueing, scheduling, ranking, planning, retry provenance, learning, memory, verification policy, result quality, external effect authorization or Worker implementation technology. diff --git a/docs/assurance/FORMALIZATION_PLAN.md b/docs/assurance/FORMALIZATION_PLAN.md deleted file mode 100644 index 9ef0589..0000000 --- a/docs/assurance/FORMALIZATION_PLAN.md +++ /dev/null @@ -1,44 +0,0 @@ -# Formalization plan - -The minimized Worker semantic bootstrap separates four assurance stages: - -1. executable/conformance checking of the machine-readable canon; -2. a handwritten append-only Worker lifecycle model and unbounded TLAPS safety proof; -3. a standalone deterministic canon projection with TLAPS behavioral-equivalence proof; -4. a separate stuttering refinement proof against the exact pinned Seed formal model. - -The machine-readable canon remains normative. Formal artifacts and proof evidence are assurance surfaces and do not gain normative implementation precedence. - -Because `0.1.0-alpha.1` removes `ACCEPTED/ACCEPT_WORK` and unifies terminal completion under `END_WORK`, proof evidence from the previous semantic revision is intentionally invalidated and removed. New proof evidence must bind the exact current hashes. - -## Candidate proof run - -```text -python tools/run_formal_candidate_gate.py \ - --tlapm "$HOME/ASET/.tooling/tlapm/bin/tlapm" \ - --seed-root "$HOME/ASET-seed-0.3.0-alpha.3" -``` - -A passing candidate gate writes machine-readable run reports under `dist/formal-candidate/`. Those reports are local evidence and are not part of the canon package. - -## Evidence materialization - -After a reviewed passing proof run: - -```text -python tools/materialize_formal_evidence.py -``` - -The materializer accepts only a `PASS` candidate-gate report whose exact proof artifacts, TLAPM identity, Seed release commit and pinned `SeedResolution.tla` digest match the current repository. - -## Reproducible formal release gate - -```text -python tools/run_formal_release_gate.py \ - --tlapm "$HOME/ASET/.tooling/tlapm/bin/tlapm" \ - --seed-root "$HOME/ASET-seed-0.3.0-alpha.3" -``` - -## Claim boundary - -Mechanical proof closure is limited to the abstract minimized lifecycle and Seed-stuttering relation. It does not establish arbitrary runtime implementation refinement, descriptor correctness, liveness, result correctness, cryptographic correctness, worker eligibility, external-effect safety, or concrete Authority establishment. diff --git a/extension/canonical/CANON_PACKAGE.json b/extension/canonical/CANON_PACKAGE.json deleted file mode 100644 index 7d36429..0000000 --- a/extension/canonical/CANON_PACKAGE.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "canon_id": "ASET-WORKER-CANON-0.1-ALPHA2", - "document_type": "aset-worker-canon-package", - "files": [ - { - "path": "assurance/canon-refinement-proof.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:6be043713c5b8eeac9567ee65e8f050ba912c98d748d74d401a95890736cc8e0" - }, - { - "path": "assurance/canon-tla-refinement.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:7951ca0cc5275d3d658d3cf61dee3f83b5d76814f66a4068ce89bcb981b6847b" - }, - { - "path": "assurance/lifecycle-proof-candidate.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:2a5251550e9f661d6660c2b906c5f25408ee4ceb9e019b759c2c71d86f456c60" - }, - { - "path": "assurance/lifecycle-proof.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:cc9adc07d083f86a82eea302937debe66ced06d7bb61cc268b010237e19f9324" - }, - { - "path": "assurance/seed-refinement-proof.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:9f2ee796783bbd7476234e41acf16b2a8ae588a30f226d7ebf13df7058e81e2f" - }, - { - "path": "assurance/seed-refinement.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:7afcc9bcf1309de0146bb7d14232e342f35fd5d7fd662fe273379266def58aec" - }, - { - "path": "assurance/verification-registry.json", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:8a29d3c29cd31ef68d52b9fa7db8617896a21fdbe706960f85a79f8a899a75c5" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-001.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:7d65abb6fab6f80ead9f6ab6192f1a7a21f457f96d8f331e01eb963cfb3db667" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-002.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:43f3592d4a968fe19b304719e42d8bab5b1e4ab82259b39b6637684ad51ddb75" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-003.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:8cdd1c7d4c460297cb4e50995c96e57fe982155f1e5c80c7082a8fd15a11e791" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-004.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:3941cbc719ffb1ab5e4cf291e97dbcdf156be1ce6faca9c31678c60e576fa159" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-005.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:95c8fd2daf01dfd61cb7c7d314141aea4dfb6fbb0c0e508ba92110259c75a304" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-006.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:67c458e78766eebb87dcb3069d140d4d867bad092946e0f77b51c1c9e53b754d" - }, - { - "path": "conformance/cases/negative/WORKER-NEG-007.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:f18376a70b372ffdb16b02f6269a83e0d56099c60d2329ca3fed80d45c792f9b" - }, - { - "path": "conformance/cases/positive/WORKER-POS-001.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:ddee666f8f26c9772c651d273192cb4e69713cd37f8a49f1ca36c05e53a9fe22" - }, - { - "path": "conformance/cases/positive/WORKER-POS-002.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:3581b9fb2457c02b7d9f816a945302de307e2852ba7d82dcdb7c9a5e1ffa074e" - }, - { - "path": "conformance/cases/positive/WORKER-POS-003.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:31b5ffd1a7e15753d697f2817c4a26e146d390b4d93bdce110641a7b0ac61acc" - }, - { - "path": "conformance/cases/positive/WORKER-POS-004.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:cd989ef7de9df3a934cfb233c325367511909c18fcd0ba7a0b4139bb4e9113ee" - }, - { - "path": "conformance/cases/positive/WORKER-POS-005.json", - "role": "NORMATIVE_CONFORMANCE_CASE", - "sha256": "sha256:b80226677e992b12fc339a1058c9490741df03698bfe1974e49b72c18cf00d97" - }, - { - "path": "conformance/conformance-profile.json", - "role": "NORMATIVE_CONFORMANCE_PROFILE", - "sha256": "sha256:86015ac7ad9a16eb07072fd312776cc02dee6195ae05bc639bb9c64968b1a20c" - }, - { - "path": "formal/README.md", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:2936ff340ba4aa6dc36e9c328b2b18a49d1a24c11d91dfdf37fe2846cd1dc93b" - }, - { - "path": "formal/WorkerCanonProjection.tla", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:6d8eec29e99704fbc9504ed32a59ea6201dfdf6c3bb22c4e6ba4159e12efba4c" - }, - { - "path": "formal/WorkerCanonRefinementProofs.tla", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:1bdca0038df67975409ba61235010843c695f691cd09606bd6b7b74d98b77c81" - }, - { - "path": "formal/WorkerLifecycle.cfg", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:311debf59d32a7e6a1896413616307744c00cbf44ca303e3c87d03cb5cb734c9" - }, - { - "path": "formal/WorkerLifecycle.tla", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:989b37e70587c00005a48b64642841f99ffc411221942480edf5359299616105" - }, - { - "path": "formal/WorkerLifecycleProofs.tla", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:8c0d2cb241f1f4f3eec826319dd63e73a3296cfce4bd27b231c17a9d81ee8005" - }, - { - "path": "formal/WorkerSeedStuttering.tla", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:a0b91fb37442b031ab31960f72b072644116f31f9d8797b756c5c183d72f2b5e" - }, - { - "path": "formal/WorkerSeedStutteringProofs.tla", - "role": "NON_NORMATIVE_ASSURANCE_ARTIFACT", - "sha256": "sha256:8f5f8a5c3ba55436511ea792e69ec6fbd2131e1a767c31339c253f6751aab19f" - }, - { - "path": "protocol/protocol-profile.json", - "role": "NORMATIVE_PROTOCOL_PROFILE", - "sha256": "sha256:9cf31c652b2c4110aa0c7f6a59e96a5619843479e704d46e0af3688d4c5c3db0" - }, - { - "path": "protocol/schemas/conformance-case.schema.json", - "role": "NORMATIVE_CONFORMANCE_SCHEMA", - "sha256": "sha256:d40fd358fada82bbdd03175ec8cd26ba3e84cb60320d643d13fb1a6ff25136c0" - }, - { - "path": "protocol/schemas/end-work.schema.json", - "role": "NORMATIVE_WIRE_SCHEMA", - "sha256": "sha256:aa7a466101cecfea324cb82501c3bb329f214561a05cdf1777106556a220d204" - }, - { - "path": "protocol/schemas/start-work.schema.json", - "role": "NORMATIVE_WIRE_SCHEMA", - "sha256": "sha256:35dfce3a882f5b3d6b465274c92ded56a1a693b6d9b0a10d26b93746b20261b2" - }, - { - "path": "protocol/schemas/worker-model.schema.json", - "role": "NORMATIVE_CANON_SCHEMA", - "sha256": "sha256:806ffa1fe3c2f4ee3d1038a9b25b339b543700b681a025d6b9e02109aa9cca3b" - }, - { - "path": "source/worker-model.json", - "role": "NORMATIVE_MACHINE_CANON", - "sha256": "sha256:e7769e1ea41fce4ebf05f66adb03f6c048f3040ec215011c8d070b62a32b8ff0" - } - ], - "schema_version": 1, - "version": "0.1.0-alpha.1" -} diff --git a/extension/canonical/assurance/canon-refinement-proof.json b/extension/canonical/assurance/canon-refinement-proof.json deleted file mode 100644 index 90532b4..0000000 --- a/extension/canonical/assurance/canon-refinement-proof.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "artifacts": { - "generated_projection": { - "module": "WorkerCanonProjection", - "path": "extension/canonical/formal/WorkerCanonProjection.tla", - "sha256": "sha256:6d8eec29e99704fbc9504ed32a59ea6201dfdf6c3bb22c4e6ba4159e12efba4c" - }, - "proof": { - "module": "WorkerCanonRefinementProofs", - "path": "extension/canonical/formal/WorkerCanonRefinementProofs.tla", - "sha256": "sha256:1bdca0038df67975409ba61235010843c695f691cd09606bd6b7b74d98b77c81" - }, - "source_model": { - "path": "extension/canonical/source/worker-model.json", - "sha256": "sha256:e7769e1ea41fce4ebf05f66adb03f6c048f3040ec215011c8d070b62a32b8ff0" - }, - "target_model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": "sha256:989b37e70587c00005a48b64642841f99ffc411221942480edf5359299616105" - } - }, - "claim_boundary": [ - "The proof establishes behavioral equivalence only for the declared standalone generated lifecycle-safety projection and the exact handwritten WorkerLifecycle.tla artifact recorded here.", - "It does not establish correctness of the projection generator, natural-language or wire-schema equivalence, digest construction correctness, runtime execution correctness, liveness, result correctness, or implementation refinement." - ], - "document_type": "aset-worker-canon-refinement-proof-evidence", - "normative_precedence": "MACHINE_READABLE_CANON", - "profile": "ASET-WORKER-CANON-TLA-PROJECTION-V2", - "proof_gate": { - "final_theorems": [ - "WorkerSafetyEquivalentToCanonProjection", - "WorkerLifecycleBehaviorallyEquivalentToCanonProjection" - ], - "obligation_count_semantics": "RECORDED_EVIDENCE_NOT_FIXED_SEMANTIC_CONTRACT", - "obligations_proved": 2, - "runner": "tools/run_formal_candidate_gate.py", - "verdict": "PASS" - }, - "schema_version": 1, - "scope": "EXACT_CANON_PROJECTION_TO_HANDWRITTEN_LIFECYCLE_EQUIVALENCE", - "status": "MECHANICALLY_PROVED", - "tlapm": { - "commit": "4600b24c6d95a25ff081ad37b63b2a01c29d43a5", - "version": "4600b24" - } -} diff --git a/extension/canonical/assurance/canon-tla-refinement.json b/extension/canonical/assurance/canon-tla-refinement.json deleted file mode 100644 index 926332f..0000000 --- a/extension/canonical/assurance/canon-tla-refinement.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "document_type": "aset-worker-canon-tla-relation", - "excluded_claims": [ - "work-descriptor interpretation", - "wire-schema equivalence", - "digest construction correctness", - "runtime execution correctness", - "liveness", - "result correctness", - "implementation refinement" - ], - "generated_projection": { - "generator": "tools/generate_canon_tla_projection.py", - "generator_sha256": "sha256:e7e5fa45b5a5bb7b6dfdcfe19c709386fed3eb26c1132bec81bae449638d98f3", - "module": "WorkerCanonProjection", - "path": "extension/canonical/formal/WorkerCanonProjection.tla", - "sha256": "sha256:6d8eec29e99704fbc9504ed32a59ea6201dfdf6c3bb22c4e6ba4159e12efba4c" - }, - "normative_precedence": "MACHINE_READABLE_CANON", - "profile": "ASET-WORKER-CANON-TLA-PROJECTION-V2", - "proof_candidate": { - "final_theorems": [ - "WorkerSafetyEquivalentToCanonProjection", - "WorkerLifecycleBehaviorallyEquivalentToCanonProjection" - ], - "module": "WorkerCanonRefinementProofs", - "path": "extension/canonical/formal/WorkerCanonRefinementProofs.tla", - "sha256": "sha256:1bdca0038df67975409ba61235010843c695f691cd09606bd6b7b74d98b77c81" - }, - "proof_evidence": { - "obligations_proved": 2, - "path": "extension/canonical/assurance/canon-refinement-proof.json", - "status": "MECHANICALLY_PROVED" - }, - "relation_type": "STANDALONE_GENERATED_PROJECTION_WITH_BEHAVIORAL_EQUIVALENCE_PROOF", - "schema_version": 1, - "scope": "MINIMIZED_PRODUCTIVE_ATTEMPT_LIFECYCLE_SAFETY_PROJECTION", - "source_model": { - "path": "extension/canonical/source/worker-model.json", - "sha256": "sha256:e7769e1ea41fce4ebf05f66adb03f6c048f3040ec215011c8d070b62a32b8ff0" - }, - "status": "MECHANICALLY_PROVED", - "target_model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": "sha256:989b37e70587c00005a48b64642841f99ffc411221942480edf5359299616105" - } -} diff --git a/extension/canonical/assurance/lifecycle-proof-candidate.json b/extension/canonical/assurance/lifecycle-proof-candidate.json deleted file mode 100644 index 23b16ef..0000000 --- a/extension/canonical/assurance/lifecycle-proof-candidate.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "document_type": "aset-worker-lifecycle-proof-candidate", - "excluded_claims": [ - "work-descriptor interpretation", - "wire metadata correctness", - "digest correctness", - "liveness", - "result correctness", - "implementation refinement" - ], - "model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": "sha256:989b37e70587c00005a48b64642841f99ffc411221942480edf5359299616105" - }, - "proof": { - "final_theorems": [ - "SpecImpliesAlwaysWorkerSafety", - "SpecImpliesStartedAppendOnly", - "SpecImpliesTerminalAppendOnly", - "SpecImpliesWorkerStateChangesOnlyByRecognizedTransition" - ], - "module": "WorkerLifecycleProofs", - "path": "extension/canonical/formal/WorkerLifecycleProofs.tla", - "sha256": "sha256:8c0d2cb241f1f4f3eec826319dd63e73a3296cfce4bd27b231c17a9d81ee8005" - }, - "schema_version": 1, - "status": "PROOF_CANDIDATE_MATERIALIZED" -} diff --git a/extension/canonical/assurance/lifecycle-proof.json b/extension/canonical/assurance/lifecycle-proof.json deleted file mode 100644 index 57c9c25..0000000 --- a/extension/canonical/assurance/lifecycle-proof.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "artifacts": { - "model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": "sha256:989b37e70587c00005a48b64642841f99ffc411221942480edf5359299616105" - }, - "proof": { - "module": "WorkerLifecycleProofs", - "path": "extension/canonical/formal/WorkerLifecycleProofs.tla", - "sha256": "sha256:8c0d2cb241f1f4f3eec826319dd63e73a3296cfce4bd27b231c17a9d81ee8005" - } - }, - "claim_boundary": [ - "The proof establishes the declared safety properties of the exact WorkerLifecycle.tla and WorkerLifecycleProofs.tla artifacts recorded here.", - "It does not establish liveness, result correctness, wire metadata correctness, digest correctness, or implementation refinement." - ], - "document_type": "aset-worker-lifecycle-proof-evidence", - "normative_precedence": "MACHINE_READABLE_CANON", - "proof_gate": { - "final_theorems": [ - "SpecImpliesAlwaysWorkerSafety", - "SpecImpliesStartedAppendOnly", - "SpecImpliesTerminalAppendOnly", - "SpecImpliesWorkerStateChangesOnlyByRecognizedTransition" - ], - "obligation_count_semantics": "RECORDED_EVIDENCE_NOT_FIXED_SEMANTIC_CONTRACT", - "obligations_proved": 52, - "runner": "tools/run_formal_candidate_gate.py", - "verdict": "PASS" - }, - "schema_version": 1, - "scope": "UNBOUNDED_TLAPS_WORKER_LIFECYCLE_SAFETY", - "status": "MECHANICALLY_PROVED", - "tlapm": { - "commit": "4600b24c6d95a25ff081ad37b63b2a01c29d43a5", - "version": "4600b24" - } -} diff --git a/extension/canonical/assurance/seed-refinement-proof.json b/extension/canonical/assurance/seed-refinement-proof.json deleted file mode 100644 index 5aaafa4..0000000 --- a/extension/canonical/assurance/seed-refinement-proof.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "artifacts": { - "mapping": { - "module": "WorkerSeedStuttering", - "path": "extension/canonical/formal/WorkerSeedStuttering.tla", - "sha256": "sha256:a0b91fb37442b031ab31960f72b072644116f31f9d8797b756c5c183d72f2b5e" - }, - "proof": { - "module": "WorkerSeedStutteringProofs", - "path": "extension/canonical/formal/WorkerSeedStutteringProofs.tla", - "sha256": "sha256:8f5f8a5c3ba55436511ea792e69ec6fbd2131e1a767c31339c253f6751aab19f" - } - }, - "claim_boundary": [ - "The proof applies to the declared Worker-to-Seed stuttering mapping and the exact pinned SeedResolution.tla artifact recorded here.", - "It proves Worker-only lifecycle operations preserve the Seed projection and does not make Worker output a Seed request, Resolution, Authority, effect permission, or implementation refinement proof." - ], - "document_type": "aset-worker-seed-refinement-proof-evidence", - "normative_precedence": "MACHINE_READABLE_CANON", - "proof_gate": { - "final_theorems": [ - "WorkerOperationsPreserveSeedProjection", - "WorkerOperationsPreserveSeedOwnedState", - "WorkerCompositionRefinesSeedResolutionByStuttering" - ], - "obligation_count_semantics": "RECORDED_EVIDENCE_NOT_FIXED_SEMANTIC_CONTRACT", - "obligations_proved": 19, - "runner": "tools/run_formal_candidate_gate.py", - "verdict": "PASS" - }, - "schema_version": 1, - "scope": "WORKER_ONLY_OPERATIONS_AS_PINNED_SEED_STUTTER", - "status": "MECHANICALLY_PROVED", - "tlapm": { - "commit": "4600b24c6d95a25ff081ad37b63b2a01c29d43a5", - "version": "4600b24" - }, - "upstream_seed": { - "compatibility_standard": "ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3", - "materialization": "EXTERNAL_PINNED_SEED_SOURCE_NOT_VENDORED", - "module": "SeedResolution", - "path": "seed/canonical/formal/SeedResolution.tla", - "release_commit": "633c130187b2a2bb42f24cfd66662d475de385d2", - "release_tag": "seed-0.3.0-alpha.3", - "sha256": "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926" - } -} diff --git a/extension/canonical/assurance/seed-refinement.json b/extension/canonical/assurance/seed-refinement.json deleted file mode 100644 index 0bae8e6..0000000 --- a/extension/canonical/assurance/seed-refinement.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "claim_boundary": "START_WORK and END_WORK alter only Worker extension state and are stuttering steps with respect to the exact pinned Seed projection.", - "document_type": "aset-worker-seed-refinement-relation", - "excluded_claims": [ - "Worker output is a Seed request", - "Worker output is a Seed resolution", - "Worker evidence creates Authority", - "Worker execution grants effect permission", - "implementation refinement", - "liveness" - ], - "mapping_candidate": { - "module": "WorkerSeedStuttering", - "path": "extension/canonical/formal/WorkerSeedStuttering.tla", - "sha256": "sha256:a0b91fb37442b031ab31960f72b072644116f31f9d8797b756c5c183d72f2b5e", - "worker_operations": "SEED_STUTTER" - }, - "proof_candidate": { - "final_theorems": [ - "WorkerOperationsPreserveSeedProjection", - "WorkerOperationsPreserveSeedOwnedState", - "WorkerCompositionRefinesSeedResolutionByStuttering" - ], - "module": "WorkerSeedStutteringProofs", - "path": "extension/canonical/formal/WorkerSeedStutteringProofs.tla", - "sha256": "sha256:8f5f8a5c3ba55436511ea792e69ec6fbd2131e1a767c31339c253f6751aab19f" - }, - "proof_evidence": { - "obligations_proved": 19, - "path": "extension/canonical/assurance/seed-refinement-proof.json", - "status": "MECHANICALLY_PROVED" - }, - "relation_type": "WORKER_ONLY_OPERATIONS_AS_SEED_STUTTER_PROOF", - "schema_version": 1, - "status": "MECHANICALLY_PROVED", - "upstream_seed": { - "canon_id": "ASET-SEED-RESOLUTION-CANON-0.3-ALPHA1", - "canon_package_digest": "sha256:c5d48a418466ea7a60fccb7161adbd5ad568174bbc9a28fc03fd7e6e77955d31", - "canon_version": "0.3.0-alpha.1", - "compatibility_standard": "ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3", - "materialization": "EXTERNAL_PINNED_SEED_SOURCE_NOT_VENDORED", - "module": "SeedResolution", - "path": "seed/canonical/formal/SeedResolution.tla", - "release_commit": "633c130187b2a2bb42f24cfd66662d475de385d2", - "release_tag": "seed-0.3.0-alpha.3", - "sha256": "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926" - } -} diff --git a/extension/canonical/assurance/verification-registry.json b/extension/canonical/assurance/verification-registry.json deleted file mode 100644 index c29422e..0000000 --- a/extension/canonical/assurance/verification-registry.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "claim_boundary": "Mechanical proof evidence covers the abstract formal surfaces listed above. It does not establish arbitrary Worker runtime implementation refinement, liveness, result correctness, cryptographic correctness, or external-effect safety.", - "document_type": "aset-worker-formal-verification-registry", - "normative_precedence": "MACHINE_READABLE_CANON", - "proofs": [ - { - "evidence": "extension/canonical/assurance/lifecycle-proof.json", - "id": "WORKER_TLAPS_SAFETY", - "obligations_proved": 52, - "status": "MECHANICALLY_PROVED" - }, - { - "evidence": "extension/canonical/assurance/canon-refinement-proof.json", - "id": "WORKER_CANON_TO_TLA", - "obligations_proved": 2, - "status": "MECHANICALLY_PROVED" - }, - { - "evidence": "extension/canonical/assurance/seed-refinement-proof.json", - "id": "WORKER_SEED_REFINEMENT", - "obligations_proved": 19, - "status": "MECHANICALLY_PROVED" - } - ], - "schema_version": 1, - "status": "MECHANICALLY_PROVED", - "toolchain": { - "tlapm_commit": "4600b24c6d95a25ff081ad37b63b2a01c29d43a5", - "tlapm_version": "4600b24" - } -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-001.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-001.json deleted file mode 100644 index a977906..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-001.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "case_id": "WORKER-NEG-001", - "expected": { - "authority_created": false, - "code": "WORK_NOT_STARTED", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "UNREGISTERED" - }, - "polarity": "negative", - "steps": [ - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:8888888888888888888888888888888888888888888888888888888888888888", - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-002.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-002.json deleted file mode 100644 index c8de503..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-002.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "case_id": "WORKER-NEG-002", - "expected": { - "authority_created": false, - "code": "WORK_BINDING_REQUIRED", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "UNREGISTERED" - }, - "polarity": "negative", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-003.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-003.json deleted file mode 100644 index adb9b10..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-003.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "case_id": "WORKER-NEG-003", - "expected": { - "authority_created": false, - "code": "WORK_IDENTITY_CONFLICT", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RUNNING" - }, - "polarity": "negative", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:4444444444444444444444444444444444444444444444444444444444444444", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-004.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-004.json deleted file mode 100644 index 63f8684..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-004.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "case_id": "WORKER-NEG-004", - "expected": { - "authority_created": false, - "code": "WORK_BINDING_MISMATCH", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RUNNING" - }, - "polarity": "negative", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:8888888888888888888888888888888888888888888888888888888888888888", - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-005.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-005.json deleted file mode 100644 index bbada43..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-005.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "case_id": "WORKER-NEG-005", - "expected": { - "authority_created": false, - "code": "TERMINAL_BINDING_REQUIRED", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RUNNING" - }, - "polarity": "negative", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "END_WORK", - "payload": { - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-006.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-006.json deleted file mode 100644 index aaa3b8b..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-006.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "case_id": "WORKER-NEG-006", - "expected": { - "authority_created": false, - "code": "TERMINAL_WORK_IMMUTABLE", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RESULT" - }, - "polarity": "negative", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:8888888888888888888888888888888888888888888888888888888888888888", - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - "terminal_kind": "NO_RESULT", - "terminal_record_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/negative/WORKER-NEG-007.json b/extension/canonical/conformance/cases/negative/WORKER-NEG-007.json deleted file mode 100644 index acc417c..0000000 --- a/extension/canonical/conformance/cases/negative/WORKER-NEG-007.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "case_id": "WORKER-NEG-007", - "expected": { - "authority_created": false, - "code": "WORKER_AUTHORITY_FORBIDDEN", - "effect_permitted": false, - "recognized": false, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RUNNING" - }, - "polarity": "negative", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "ASSERT_WORKER_AUTHORITY", - "payload": { - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/positive/WORKER-POS-001.json b/extension/canonical/conformance/cases/positive/WORKER-POS-001.json deleted file mode 100644 index 10c2a29..0000000 --- a/extension/canonical/conformance/cases/positive/WORKER-POS-001.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "case_id": "WORKER-POS-001", - "expected": { - "authority_created": false, - "code": "WORK_STARTED", - "effect_permitted": false, - "recognized": true, - "seed_resolution_created": false, - "state_changed": true, - "work_state": "RUNNING" - }, - "polarity": "positive", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/positive/WORKER-POS-002.json b/extension/canonical/conformance/cases/positive/WORKER-POS-002.json deleted file mode 100644 index 7010df6..0000000 --- a/extension/canonical/conformance/cases/positive/WORKER-POS-002.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "case_id": "WORKER-POS-002", - "expected": { - "authority_created": false, - "code": "WORK_ENDED_WITH_RESULT", - "effect_permitted": false, - "recognized": true, - "seed_resolution_created": false, - "state_changed": true, - "work_state": "RESULT" - }, - "polarity": "positive", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:8888888888888888888888888888888888888888888888888888888888888888", - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/positive/WORKER-POS-003.json b/extension/canonical/conformance/cases/positive/WORKER-POS-003.json deleted file mode 100644 index ac95dbe..0000000 --- a/extension/canonical/conformance/cases/positive/WORKER-POS-003.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "case_id": "WORKER-POS-003", - "expected": { - "authority_created": false, - "code": "WORK_ENDED_WITH_NO_RESULT", - "effect_permitted": false, - "recognized": true, - "seed_resolution_created": false, - "state_changed": true, - "work_state": "NO_RESULT" - }, - "polarity": "positive", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - "terminal_kind": "NO_RESULT", - "terminal_record_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/positive/WORKER-POS-004.json b/extension/canonical/conformance/cases/positive/WORKER-POS-004.json deleted file mode 100644 index a5d9432..0000000 --- a/extension/canonical/conformance/cases/positive/WORKER-POS-004.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "case_id": "WORKER-POS-004", - "expected": { - "authority_created": false, - "code": "IDEMPOTENT_REPLAY", - "effect_permitted": false, - "recognized": true, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RUNNING" - }, - "polarity": "positive", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - } - ] -} diff --git a/extension/canonical/conformance/cases/positive/WORKER-POS-005.json b/extension/canonical/conformance/cases/positive/WORKER-POS-005.json deleted file mode 100644 index 84b08d4..0000000 --- a/extension/canonical/conformance/cases/positive/WORKER-POS-005.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "case_id": "WORKER-POS-005", - "expected": { - "authority_created": false, - "code": "IDEMPOTENT_REPLAY", - "effect_permitted": false, - "recognized": true, - "seed_resolution_created": false, - "state_changed": false, - "work_state": "RESULT" - }, - "polarity": "positive", - "steps": [ - { - "kind": "START_WORK", - "payload": { - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_descriptor_binding": "sha256:3333333333333333333333333333333333333333333333333333333333333333", - "work_id": "work:1", - "worker_binding": "sha256:2222222222222222222222222222222222222222222222222222222222222222" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:8888888888888888888888888888888888888888888888888888888888888888", - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - }, - { - "kind": "END_WORK", - "payload": { - "evidence_bindings": [ - "sha256:9999999999999999999999999999999999999999999999999999999999999999" - ], - "terminal_binding": "sha256:8888888888888888888888888888888888888888888888888888888888888888", - "terminal_kind": "RESULT", - "terminal_record_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", - "work_binding_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", - "work_id": "work:1" - } - } - ] -} diff --git a/extension/canonical/conformance/conformance-profile.json b/extension/canonical/conformance/conformance-profile.json deleted file mode 100644 index aca11e9..0000000 --- a/extension/canonical/conformance/conformance-profile.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "case_count": 12, - "document_type": "aset-worker-conformance-profile", - "negative_cases": 7, - "oracle": "reference/oracle.py", - "positive_cases": 5, - "profile_id": "ASET-WORKER-CONFORMANCE-V2", - "schema_version": 1, - "status": "BOOTSTRAP" -} diff --git a/extension/canonical/formal/README.md b/extension/canonical/formal/README.md deleted file mode 100644 index 73093cd..0000000 --- a/extension/canonical/formal/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Worker formal assurance - -The minimized lifecycle projected here is: - -```text -UNREGISTERED -> RUNNING -> (RESULT XOR NO_RESULT) -``` - -with the two normative operations `START_WORK` and `END_WORK`. The TLA+ state is intentionally smaller than the wire/profile surface: it tracks only append-only started and terminal-kind facts. - -The machine-readable canon remains normative. `WorkerCanonProjection.tla` is deterministically generated from it; `WorkerLifecycle.tla` is the handwritten assurance model; `WorkerCanonRefinementProofs.tla` is the behavioral-equivalence proof candidate. - -`WorkerSeedStuttering.tla` composes the Worker-only lifecycle with the exact externally pinned Seed model and treats every Worker operation as a Seed stutter. - -Formal assurance for this semantic revision is OPEN until the exact new proof artifacts are run and materialized. Previous proof evidence for the pre-minimization `ACCEPTED` lifecycle must not be reused. diff --git a/extension/canonical/formal/WorkerCanonProjection.tla b/extension/canonical/formal/WorkerCanonProjection.tla deleted file mode 100644 index 78d8fe4..0000000 --- a/extension/canonical/formal/WorkerCanonProjection.tla +++ /dev/null @@ -1,76 +0,0 @@ ----------------------- MODULE WorkerCanonProjection ---------------------- -EXTENDS FiniteSets - -(*************************************************************************** -GENERATED FILE. DO NOT EDIT. -Source: extension/canonical/source/worker-model.json -Source SHA-256: e7769e1ea41fce4ebf05f66adb03f6c048f3040ec215011c8d070b62a32b8ff0 -Projection profile: ASET-WORKER-CANON-TLA-PROJECTION-V2 - -This standalone safety projection captures only the minimized append-only -productive-attempt lifecycle declared by the machine-readable Worker canon. -It does not interpret the opaque work descriptor, terminal payload, wire-level -digests, runtime execution, liveness, result correctness or implementation -refinement. -***************************************************************************) - -CONSTANT WorkIds - -VARIABLES started, resultWorks, noResultWorks - -CanonVars == <> - -CanonInit == - /\ started = {} - /\ resultWorks = {} - /\ noResultWorks = {} - -CanonTerminal == resultWorks \cup noResultWorks - -CanonStartWork(w) == - /\ w \in WorkIds - /\ w \notin started - /\ started' = started \cup {w} - /\ UNCHANGED <> - -CanonEndWorkWithResult(w) == - /\ w \in started - /\ w \notin CanonTerminal - /\ resultWorks' = resultWorks \cup {w} - /\ UNCHANGED <> - -CanonEndWorkWithNoResult(w) == - /\ w \in started - /\ w \notin CanonTerminal - /\ noResultWorks' = noResultWorks \cup {w} - /\ UNCHANGED <> - -CanonEndWork(w, terminalKind) == - \/ /\ terminalKind = "RESULT" - /\ CanonEndWorkWithResult(w) - \/ /\ terminalKind = "NO_RESULT" - /\ CanonEndWorkWithNoResult(w) - -CanonRecognizedWorkerTransition == - \/ \E w \in WorkIds : CanonStartWork(w) - \/ \E w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : CanonEndWork(w, terminalKind) - -CanonNext == CanonRecognizedWorkerTransition -CanonSpec == CanonInit /\ [][CanonNext]_CanonVars - -CanonTypeOK == - /\ started \subseteq WorkIds - /\ resultWorks \subseteq WorkIds - /\ noResultWorks \subseteq WorkIds - -CanonResultImpliesStarted == resultWorks \subseteq started -CanonNoResultImpliesStarted == noResultWorks \subseteq started -CanonResultXorNoResult == resultWorks \cap noResultWorks = {} - -CanonWorkerSafety == - /\ CanonTypeOK - /\ CanonResultImpliesStarted - /\ CanonNoResultImpliesStarted - /\ CanonResultXorNoResult - -============================================================================= diff --git a/extension/canonical/formal/WorkerCanonRefinementProofs.tla b/extension/canonical/formal/WorkerCanonRefinementProofs.tla deleted file mode 100644 index cd95d0b..0000000 --- a/extension/canonical/formal/WorkerCanonRefinementProofs.tla +++ /dev/null @@ -1,54 +0,0 @@ -------------------- MODULE WorkerCanonRefinementProofs ------------------- -EXTENDS WorkerLifecycle, TLAPS - -(*************************************************************************** -Behavioral-equivalence proof candidate between the handwritten minimized -WorkerLifecycle model and the standalone deterministic projection generated -from the exact machine-readable Worker canon. -***************************************************************************) - -Canon == INSTANCE WorkerCanonProjection - WITH WorkIds <- WorkIds, - started <- started, - resultWorks <- resultWorks, - noResultWorks <- noResultWorks - -THEOREM WorkerSafetyEquivalentToCanonProjection == - WorkerSafety <=> Canon!CanonWorkerSafety -PROOF - BY DEF WorkerSafety, - TypeOK, - ResultImpliesStarted, - NoResultImpliesStarted, - ResultXorNoResult, - Canon!CanonWorkerSafety, - Canon!CanonTypeOK, - Canon!CanonResultImpliesStarted, - Canon!CanonNoResultImpliesStarted, - Canon!CanonResultXorNoResult - -THEOREM WorkerLifecycleBehaviorallyEquivalentToCanonProjection == - Spec <=> Canon!CanonSpec -PROOF - BY DEF Spec, - Init, - Next, - RecognizedWorkerTransition, - StartWork, - EndWork, - EndWorkWithResult, - EndWorkWithNoResult, - Terminal, - vars, - Canon!CanonSpec, - Canon!CanonInit, - Canon!CanonNext, - Canon!CanonRecognizedWorkerTransition, - Canon!CanonStartWork, - Canon!CanonEndWork, - Canon!CanonEndWorkWithResult, - Canon!CanonEndWorkWithNoResult, - Canon!CanonTerminal, - Canon!CanonVars - -============================================================================= diff --git a/extension/canonical/formal/WorkerLifecycle.cfg b/extension/canonical/formal/WorkerLifecycle.cfg deleted file mode 100644 index ba56136..0000000 --- a/extension/canonical/formal/WorkerLifecycle.cfg +++ /dev/null @@ -1,8 +0,0 @@ -SPECIFICATION Spec - -CONSTANT WorkIds = {w1, w2} - -INVARIANT TypeOK -INVARIANT ResultImpliesStarted -INVARIANT NoResultImpliesStarted -INVARIANT ResultXorNoResult diff --git a/extension/canonical/formal/WorkerLifecycle.tla b/extension/canonical/formal/WorkerLifecycle.tla deleted file mode 100644 index 5a60355..0000000 --- a/extension/canonical/formal/WorkerLifecycle.tla +++ /dev/null @@ -1,78 +0,0 @@ ------------------------------ MODULE WorkerLifecycle ----------------------------- -EXTENDS FiniteSets - -CONSTANT WorkIds - -VARIABLES started, resultWorks, noResultWorks - -vars == <> - -Init == - /\ started = {} - /\ resultWorks = {} - /\ noResultWorks = {} - -Terminal == resultWorks \cup noResultWorks - -StartWork(w) == - /\ w \in WorkIds - /\ w \notin started - /\ started' = started \cup {w} - /\ UNCHANGED <> - -EndWorkWithResult(w) == - /\ w \in started - /\ w \notin Terminal - /\ resultWorks' = resultWorks \cup {w} - /\ UNCHANGED <> - -EndWorkWithNoResult(w) == - /\ w \in started - /\ w \notin Terminal - /\ noResultWorks' = noResultWorks \cup {w} - /\ UNCHANGED <> - -EndWork(w, terminalKind) == - \/ /\ terminalKind = "RESULT" - /\ EndWorkWithResult(w) - \/ /\ terminalKind = "NO_RESULT" - /\ EndWorkWithNoResult(w) - -RecognizedWorkerTransition == - \/ \E w \in WorkIds : StartWork(w) - \/ \E w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : EndWork(w, terminalKind) - -Next == RecognizedWorkerTransition - -Spec == Init /\ [][Next]_vars - -TypeOK == - /\ started \subseteq WorkIds - /\ resultWorks \subseteq WorkIds - /\ noResultWorks \subseteq WorkIds - -ResultImpliesStarted == resultWorks \subseteq started -NoResultImpliesStarted == noResultWorks \subseteq started -ResultXorNoResult == resultWorks \cap noResultWorks = {} - -WorkerSafety == - /\ TypeOK - /\ ResultImpliesStarted - /\ NoResultImpliesStarted - /\ ResultXorNoResult - -StartedAppendOnlyStep == started \subseteq started' -StartedAppendOnly == [][StartedAppendOnlyStep]_vars - -TerminalAppendOnlyStep == - /\ resultWorks \subseteq resultWorks' - /\ noResultWorks \subseteq noResultWorks' -TerminalAppendOnly == [][TerminalAppendOnlyStep]_vars - -WorkerStateChangesOnlyByRecognizedTransitionStep == - vars' # vars => RecognizedWorkerTransition - -WorkerStateChangesOnlyByRecognizedTransition == - [][WorkerStateChangesOnlyByRecognizedTransitionStep]_vars - -============================================================================= diff --git a/extension/canonical/formal/WorkerLifecycleProofs.tla b/extension/canonical/formal/WorkerLifecycleProofs.tla deleted file mode 100644 index 5b59e65..0000000 --- a/extension/canonical/formal/WorkerLifecycleProofs.tla +++ /dev/null @@ -1,209 +0,0 @@ ------------------------- MODULE WorkerLifecycleProofs ------------------------ -EXTENDS WorkerLifecycle, TLAPS - -(*************************************************************************** -Unbounded safety proof candidate for the minimized Worker lifecycle projection. - -The proof covers only the abstract append-only productive-attempt state in -WorkerLifecycle.tla. Exact wire metadata, digest construction, descriptor -contents, runtime execution, liveness, result correctness and implementation -refinement remain outside this proof boundary. -***************************************************************************) - -THEOREM InitImpliesWorkerSafety == - Init => WorkerSafety -PROOF - BY DEF Init, - WorkerSafety, - TypeOK, - ResultImpliesStarted, - NoResultImpliesStarted, - ResultXorNoResult - -THEOREM StartWorkPreservesWorkerSafety == - \A w \in WorkIds : - WorkerSafety /\ StartWork(w) => WorkerSafety' -PROOF - BY DEF WorkerSafety, - TypeOK, - ResultImpliesStarted, - NoResultImpliesStarted, - ResultXorNoResult, - StartWork, - Terminal - -THEOREM EndWorkWithResultPreservesWorkerSafety == - \A w \in WorkIds : - WorkerSafety /\ EndWorkWithResult(w) => WorkerSafety' -PROOF - BY DEF WorkerSafety, - TypeOK, - ResultImpliesStarted, - NoResultImpliesStarted, - ResultXorNoResult, - EndWorkWithResult, - Terminal - -THEOREM EndWorkWithNoResultPreservesWorkerSafety == - \A w \in WorkIds : - WorkerSafety /\ EndWorkWithNoResult(w) => WorkerSafety' -PROOF - BY DEF WorkerSafety, - TypeOK, - ResultImpliesStarted, - NoResultImpliesStarted, - ResultXorNoResult, - EndWorkWithNoResult, - Terminal - -THEOREM EndWorkPreservesWorkerSafety == - \A w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : - WorkerSafety /\ EndWork(w, terminalKind) => WorkerSafety' -PROOF - BY EndWorkWithResultPreservesWorkerSafety, - EndWorkWithNoResultPreservesWorkerSafety - DEF EndWork - -THEOREM RecognizedWorkerTransitionPreservesWorkerSafety == - WorkerSafety /\ RecognizedWorkerTransition => WorkerSafety' -PROOF - BY StartWorkPreservesWorkerSafety, - EndWorkPreservesWorkerSafety - DEF RecognizedWorkerTransition - -THEOREM StateStutterPreservesWorkerSafety == - WorkerSafety /\ UNCHANGED vars => WorkerSafety' -PROOF - BY DEF vars, - WorkerSafety, - TypeOK, - ResultImpliesStarted, - NoResultImpliesStarted, - ResultXorNoResult - -THEOREM BoxNextPreservesWorkerSafety == - WorkerSafety /\ [Next]_vars => WorkerSafety' -PROOF - BY RecognizedWorkerTransitionPreservesWorkerSafety, - StateStutterPreservesWorkerSafety - DEF Next - -THEOREM SpecImpliesAlwaysWorkerSafety == - Spec => []WorkerSafety -PROOF - BY PTL, - InitImpliesWorkerSafety, - BoxNextPreservesWorkerSafety - DEF Spec - -THEOREM StartWorkSatisfiesStartedAppendOnlyStep == - \A w \in WorkIds : - StartWork(w) => StartedAppendOnlyStep -PROOF - BY DEF StartWork, StartedAppendOnlyStep - -THEOREM EndWorkWithResultSatisfiesStartedAppendOnlyStep == - \A w \in WorkIds : - EndWorkWithResult(w) => StartedAppendOnlyStep -PROOF - BY DEF EndWorkWithResult, StartedAppendOnlyStep - -THEOREM EndWorkWithNoResultSatisfiesStartedAppendOnlyStep == - \A w \in WorkIds : - EndWorkWithNoResult(w) => StartedAppendOnlyStep -PROOF - BY DEF EndWorkWithNoResult, StartedAppendOnlyStep - -THEOREM EndWorkSatisfiesStartedAppendOnlyStep == - \A w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : - EndWork(w, terminalKind) => StartedAppendOnlyStep -PROOF - BY EndWorkWithResultSatisfiesStartedAppendOnlyStep, - EndWorkWithNoResultSatisfiesStartedAppendOnlyStep - DEF EndWork - -THEOREM NextSatisfiesStartedAppendOnlyStep == - Next => StartedAppendOnlyStep -PROOF - BY StartWorkSatisfiesStartedAppendOnlyStep, - EndWorkSatisfiesStartedAppendOnlyStep - DEF Next, RecognizedWorkerTransition - -THEOREM BoxNextSatisfiesBoxStartedAppendOnlyStep == - [Next]_vars => [StartedAppendOnlyStep]_vars -PROOF - BY NextSatisfiesStartedAppendOnlyStep - DEF vars, StartedAppendOnlyStep - -THEOREM SpecImpliesStartedAppendOnly == - Spec => StartedAppendOnly -PROOF - BY PTL, - BoxNextSatisfiesBoxStartedAppendOnlyStep - DEF Spec, StartedAppendOnly - -THEOREM StartWorkSatisfiesTerminalAppendOnlyStep == - \A w \in WorkIds : - StartWork(w) => TerminalAppendOnlyStep -PROOF - BY DEF StartWork, TerminalAppendOnlyStep - -THEOREM EndWorkWithResultSatisfiesTerminalAppendOnlyStep == - \A w \in WorkIds : - EndWorkWithResult(w) => TerminalAppendOnlyStep -PROOF - BY DEF EndWorkWithResult, TerminalAppendOnlyStep - -THEOREM EndWorkWithNoResultSatisfiesTerminalAppendOnlyStep == - \A w \in WorkIds : - EndWorkWithNoResult(w) => TerminalAppendOnlyStep -PROOF - BY DEF EndWorkWithNoResult, TerminalAppendOnlyStep - -THEOREM EndWorkSatisfiesTerminalAppendOnlyStep == - \A w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : - EndWork(w, terminalKind) => TerminalAppendOnlyStep -PROOF - BY EndWorkWithResultSatisfiesTerminalAppendOnlyStep, - EndWorkWithNoResultSatisfiesTerminalAppendOnlyStep - DEF EndWork - -THEOREM NextSatisfiesTerminalAppendOnlyStep == - Next => TerminalAppendOnlyStep -PROOF - BY StartWorkSatisfiesTerminalAppendOnlyStep, - EndWorkSatisfiesTerminalAppendOnlyStep - DEF Next, RecognizedWorkerTransition - -THEOREM BoxNextSatisfiesBoxTerminalAppendOnlyStep == - [Next]_vars => [TerminalAppendOnlyStep]_vars -PROOF - BY NextSatisfiesTerminalAppendOnlyStep - DEF vars, TerminalAppendOnlyStep - -THEOREM SpecImpliesTerminalAppendOnly == - Spec => TerminalAppendOnly -PROOF - BY PTL, - BoxNextSatisfiesBoxTerminalAppendOnlyStep - DEF Spec, TerminalAppendOnly - -THEOREM RecognizedWorkerTransitionSatisfiesStateChangeBoundary == - RecognizedWorkerTransition => WorkerStateChangesOnlyByRecognizedTransitionStep -PROOF - BY DEF WorkerStateChangesOnlyByRecognizedTransitionStep - -THEOREM BoxNextSatisfiesBoxStateChangeBoundary == - [Next]_vars => [WorkerStateChangesOnlyByRecognizedTransitionStep]_vars -PROOF - BY RecognizedWorkerTransitionSatisfiesStateChangeBoundary - DEF Next, vars, WorkerStateChangesOnlyByRecognizedTransitionStep - -THEOREM SpecImpliesWorkerStateChangesOnlyByRecognizedTransition == - Spec => WorkerStateChangesOnlyByRecognizedTransition -PROOF - BY PTL, - BoxNextSatisfiesBoxStateChangeBoundary - DEF Spec, WorkerStateChangesOnlyByRecognizedTransition - -============================================================================= diff --git a/extension/canonical/formal/WorkerSeedStuttering.tla b/extension/canonical/formal/WorkerSeedStuttering.tla deleted file mode 100644 index b8c6915..0000000 --- a/extension/canonical/formal/WorkerSeedStuttering.tla +++ /dev/null @@ -1,62 +0,0 @@ ------------------------- MODULE WorkerSeedStuttering ------------------------ -EXTENDS WorkerLifecycle - -(*************************************************************************** -Worker -> Seed stuttering bridge. - -SeedResolution.tla is supplied externally from the exact pinned Seed release. -Every minimized Worker lifecycle operation is a stuttering step with respect -to the entire Seed projection. Worker output is not a Seed request, a Seed -resolution, Authority, or external effect permission. -***************************************************************************) - -CONSTANTS ResolutionIds, Bindings, Authorities, TerminalCommitments, - RecognizedTerminalCommitments, NoCommitment, - RecognizedAuthorityBindings - -VARIABLES requestMeta, terminalMeta, conflicts - -Seed == INSTANCE SeedResolution - WITH ResolutionIds <- ResolutionIds, - Bindings <- Bindings, - Authorities <- Authorities, - TerminalCommitments <- TerminalCommitments, - RecognizedTerminalCommitments <- RecognizedTerminalCommitments, - NoCommitment <- NoCommitment, - RecognizedAuthorityBindings <- RecognizedAuthorityBindings, - requestMeta <- requestMeta, - terminalMeta <- terminalMeta, - conflicts <- conflicts - -projectedSeedVars == <> -projectedSeedOwnedVars == <> -compositionVars == - <> - -WorkerStartWork(w) == - /\ StartWork(w) - /\ UNCHANGED projectedSeedVars - -WorkerEndWork(w, terminalKind) == - /\ EndWork(w, terminalKind) - /\ UNCHANGED projectedSeedVars - -WorkerOnlyAction == - \/ \E w \in WorkIds : WorkerStartWork(w) - \/ \E w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : WorkerEndWork(w, terminalKind) - -CompositionInit == - /\ Init - /\ Seed!Init - -CompositionSpec == - CompositionInit /\ [][WorkerOnlyAction]_compositionVars - -WorkerOperationsPreserveSeedProjectionStep == - WorkerOnlyAction => UNCHANGED projectedSeedVars - -WorkerOperationsPreserveSeedOwnedStateStep == - WorkerOnlyAction => UNCHANGED projectedSeedOwnedVars - -============================================================================= diff --git a/extension/canonical/formal/WorkerSeedStutteringProofs.tla b/extension/canonical/formal/WorkerSeedStutteringProofs.tla deleted file mode 100644 index 000f70c..0000000 --- a/extension/canonical/formal/WorkerSeedStutteringProofs.tla +++ /dev/null @@ -1,71 +0,0 @@ -------------------- MODULE WorkerSeedStutteringProofs ------------------- -EXTENDS WorkerSeedStuttering, TLAPS - -(*************************************************************************** -Mechanical proof candidate for the minimized Worker -> Seed stuttering -relation. The exact pinned SeedResolution.tla is loaded externally by the -runner. -***************************************************************************) - -THEOREM ProjectionTupleMatchesSeedVars == - projectedSeedVars = Seed!vars -PROOF - BY DEF projectedSeedVars, Seed!vars - -THEOREM ProjectionOwnedTupleMatchesSeedOwnedVars == - projectedSeedOwnedVars = Seed!seedVars -PROOF - BY DEF projectedSeedOwnedVars, Seed!seedVars - -THEOREM WorkerStartWorkPreservesSeedProjection == - \A w \in WorkIds : - WorkerStartWork(w) => UNCHANGED projectedSeedVars -PROOF - BY DEF WorkerStartWork - -THEOREM WorkerEndWorkPreservesSeedProjection == - \A w \in WorkIds, terminalKind \in {"RESULT", "NO_RESULT"} : - WorkerEndWork(w, terminalKind) => UNCHANGED projectedSeedVars -PROOF - BY DEF WorkerEndWork - -THEOREM WorkerOperationsPreserveSeedProjection == - WorkerOnlyAction => UNCHANGED projectedSeedVars -PROOF - BY WorkerStartWorkPreservesSeedProjection, - WorkerEndWorkPreservesSeedProjection - DEF WorkerOnlyAction - -THEOREM WorkerOperationsPreserveSeedOwnedState == - WorkerOnlyAction => UNCHANGED projectedSeedOwnedVars -PROOF - BY WorkerOperationsPreserveSeedProjection - DEF projectedSeedVars, projectedSeedOwnedVars - -THEOREM CompositionStateStutterPreservesSeedProjection == - UNCHANGED compositionVars => UNCHANGED projectedSeedVars -PROOF - BY DEF compositionVars, projectedSeedVars - -THEOREM WorkerBoxStepIsProjectedSeedBoxStep == - [WorkerOnlyAction]_compositionVars => [Seed!Next]_projectedSeedVars -PROOF - BY WorkerOperationsPreserveSeedProjection, - CompositionStateStutterPreservesSeedProjection - DEF compositionVars, projectedSeedVars - -THEOREM WorkerBoxStepIsSeedBoxStep == - [WorkerOnlyAction]_compositionVars => [Seed!Next]_Seed!vars -PROOF - BY WorkerBoxStepIsProjectedSeedBoxStep - DEF Seed!vars, projectedSeedVars - -THEOREM WorkerCompositionRefinesSeedResolutionByStuttering == - CompositionSpec => Seed!Spec -PROOF - BY PTL, - WorkerBoxStepIsSeedBoxStep, - ProjectionTupleMatchesSeedVars - DEF CompositionSpec, CompositionInit, Seed!Spec - -============================================================================= diff --git a/extension/canonical/protocol/protocol-profile.json b/extension/canonical/protocol/protocol-profile.json deleted file mode 100644 index a341cff..0000000 --- a/extension/canonical/protocol/protocol-profile.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "document_type": "aset-worker-protocol-profile", - "operations": { - "END_WORK": "schemas/end-work.schema.json", - "START_WORK": "schemas/start-work.schema.json" - }, - "profile_id": "ASET-WORKER-PROTOCOL-V2", - "schema_version": 1, - "status": "BOOTSTRAP" -} diff --git a/extension/canonical/protocol/schemas/conformance-case.schema.json b/extension/canonical/protocol/schemas/conformance-case.schema.json deleted file mode 100644 index 57930ca..0000000 --- a/extension/canonical/protocol/schemas/conformance-case.schema.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "case_id": { - "minLength": 1, - "type": "string" - }, - "expected": { - "additionalProperties": false, - "properties": { - "authority_created": { - "type": "boolean" - }, - "code": { - "type": "string" - }, - "effect_permitted": { - "type": "boolean" - }, - "recognized": { - "type": "boolean" - }, - "seed_resolution_created": { - "type": "boolean" - }, - "state_changed": { - "type": "boolean" - }, - "work_state": { - "enum": [ - "UNREGISTERED", - "RUNNING", - "RESULT", - "NO_RESULT" - ] - } - }, - "required": [ - "recognized", - "code", - "state_changed", - "work_state", - "authority_created", - "effect_permitted", - "seed_resolution_created" - ], - "type": "object" - }, - "polarity": { - "enum": [ - "positive", - "negative" - ] - }, - "steps": { - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "type": "string" - }, - "payload": { - "type": "object" - } - }, - "required": [ - "kind", - "payload" - ], - "type": "object" - }, - "minItems": 1, - "type": "array" - } - }, - "required": [ - "case_id", - "polarity", - "steps", - "expected" - ], - "type": "object" -} diff --git a/extension/canonical/protocol/schemas/end-work.schema.json b/extension/canonical/protocol/schemas/end-work.schema.json deleted file mode 100644 index 098a7c0..0000000 --- a/extension/canonical/protocol/schemas/end-work.schema.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "evidence_bindings": { - "items": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "type": "array", - "uniqueItems": true - }, - "terminal_binding": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "terminal_kind": { - "enum": [ - "RESULT", - "NO_RESULT" - ] - }, - "terminal_record_digest": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "work_binding_digest": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "work_id": { - "minLength": 1, - "type": "string" - } - }, - "required": [ - "work_id", - "work_binding_digest", - "terminal_kind", - "terminal_record_digest", - "terminal_binding" - ], - "type": "object" -} diff --git a/extension/canonical/protocol/schemas/start-work.schema.json b/extension/canonical/protocol/schemas/start-work.schema.json deleted file mode 100644 index 35219c1..0000000 --- a/extension/canonical/protocol/schemas/start-work.schema.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "work_binding_digest": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "work_descriptor_binding": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "work_id": { - "minLength": 1, - "type": "string" - }, - "worker_binding": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - } - }, - "required": [ - "work_id", - "work_binding_digest", - "worker_binding", - "work_descriptor_binding" - ], - "type": "object" -} diff --git a/extension/canonical/protocol/schemas/worker-model.schema.json b/extension/canonical/protocol/schemas/worker-model.schema.json deleted file mode 100644 index c9c71b2..0000000 --- a/extension/canonical/protocol/schemas/worker-model.schema.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": true, - "properties": { - "canon_id": { - "const": "ASET-WORKER-CANON-0.1-ALPHA2" - }, - "document_type": { - "const": "aset-worker-extension-model" - }, - "extension_id": { - "const": "ASET-WORKER-EXTENSION" - }, - "invariants": { - "maxItems": 9, - "minItems": 9, - "type": "array" - }, - "operations": { - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - "requirements": { - "maxItems": 9, - "minItems": 9, - "type": "array" - }, - "status": { - "const": "SEMANTIC_BOOTSTRAP" - }, - "version": { - "const": "0.1.0-alpha.1" - } - }, - "required": [ - "document_type", - "schema_version", - "extension_id", - "canon_id", - "version", - "status", - "state_machine", - "requirements", - "invariants", - "operations", - "formal_assurance" - ], - "type": "object" -} diff --git a/extension/canonical/source/worker-model.json b/extension/canonical/source/worker-model.json deleted file mode 100644 index 03770c2..0000000 --- a/extension/canonical/source/worker-model.json +++ /dev/null @@ -1,202 +0,0 @@ -{ - "canon_id": "ASET-WORKER-CANON-0.1-ALPHA2", - "canonicality": { - "conformance_cases": "NORMATIVE_BLACK_BOX_EXPECTATIONS_FOR_BOOTSTRAP_SURFACE", - "formal_projection": "ASSURANCE_PROJECTION_DRAFT_NOT_MECHANICALLY_CLOSED", - "implementation_precedence": "NONE", - "machine_readable_model": "NORMATIVE_CANON", - "protocol_schemas": "NORMATIVE_WIRE_PROFILE", - "reference_oracle": "NON_NORMATIVE_EXECUTABLE_AID" - }, - "compatibility_standard": { - "profile_id": "ASET-WORKER-COMPATIBILITY-STANDARD-V1", - "release_claim_status": "NOT_PUBLISHED", - "series_id": "ASET-WORKER-COMPATIBILITY-STANDARD" - }, - "composition": { - "conflicts": [], - "provides": [ - "EXACT_PRODUCTIVE_ATTEMPT", - "EXPLICIT_NO_RESULT_TERMINAL", - "NON_AUTHORITATIVE_PRODUCTIVE_WORK" - ], - "requires": [ - "ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3" - ] - }, - "derived_semantics": { - "NO_RESULT": "started work with one exact terminal record whose kind is NO_RESULT", - "NO_RESULT_NOT_ABSENCE": "NO_RESULT is an explicit terminal assertion and is distinct from a missing terminal record", - "NO_RESULT_NOT_FAILURE": "NO_RESULT records terminal absence of result material and does not by itself classify failure cause", - "RESULT": "started work with one exact terminal record whose kind is RESULT", - "RESULT_NOT_SUCCESS": "RESULT records produced result material and does not imply correctness, acceptance or success", - "RUNNING": "started work with no terminal record", - "UNREGISTERED": "absence of a started-work binding for the work identity" - }, - "document_type": "aset-worker-extension-model", - "extension_id": "ASET-WORKER-EXTENSION", - "formal_assurance": { - "canon_to_tla_equivalence": "OPEN", - "python_finite_model": "tools/check_finite_model.py", - "release_gate": "BLOCKED_UNTIL_FORMAL_CLOSURE", - "seed_refinement": "OPEN", - "tla_projection": "extension/canonical/formal/WorkerLifecycle.tla", - "tlaps_safety_proof": "OPEN", - "tlc_config": "extension/canonical/formal/WorkerLifecycle.cfg" - }, - "invariants": [ - { - "id": "WORKER-INV-001", - "text": "Every RESULT work identity is already started." - }, - { - "id": "WORKER-INV-002", - "text": "Every NO_RESULT work identity is already started." - }, - { - "id": "WORKER-INV-003", - "text": "No work identity is both RESULT and NO_RESULT." - }, - { - "id": "WORKER-INV-004", - "text": "The exact started-work binding for one work identity is immutable after first start." - }, - { - "id": "WORKER-INV-005", - "text": "Terminal work metadata is unique and immutable." - }, - { - "id": "WORKER-INV-006", - "text": "Absence of a terminal record never implies NO_RESULT." - }, - { - "id": "WORKER-INV-007", - "text": "Terminal work cannot be started again, ended again with conflicting metadata, or reopened; a subsequent attempt uses a fresh work identity." - }, - { - "id": "WORKER-INV-008", - "text": "Worker state transitions create no Authority or effect permission and do not themselves create a Seed Resolution." - }, - { - "id": "WORKER-INV-009", - "text": "Worker lifecycle transitions are required to preserve the pinned Seed projection; mechanical Seed refinement remains an open assurance gate for this semantic revision." - } - ], - "normative_precedence": "MACHINE_READABLE_CANON", - "normative_scope": { - "defines": [ - "exact started-work binding", - "RUNNING productive-attempt state", - "one immutable terminal record of kind RESULT or NO_RESULT", - "explicit first-class NO_RESULT terminal assertion", - "fresh identity for a subsequent productive attempt", - "non-authority boundary for productive work" - ], - "does_not_define": [ - "task discovery or decomposition", - "eligibility, assignment or acceptance", - "planning, queueing or scheduling", - "worker ranking or optimization", - "profile-specific work descriptor structure", - "retry or predecessor provenance relationships", - "worker implementation technology", - "result quality or correctness", - "verification policy", - "learning or memory", - "external effect authorization", - "liveness" - ] - }, - "operations": [ - { - "id": "WORKER-OP-001", - "kind": "START_WORK", - "role": "STATE_TRANSITION" - }, - { - "id": "WORKER-OP-002", - "kind": "END_WORK", - "role": "STATE_TRANSITION" - } - ], - "requirements": [ - { - "id": "WORKER-REQ-001", - "text": "Implementations MUST recognize only the lifecycle UNREGISTERED -> RUNNING -> TERMINAL, where the exact terminal kind is RESULT XOR NO_RESULT for one work identity." - }, - { - "id": "WORKER-REQ-002", - "text": "START_WORK MUST bind a fresh work identity to one exact immutable Worker binding and one exact opaque work-descriptor binding; descriptor internals are profile or implementation concerns." - }, - { - "id": "WORKER-REQ-003", - "text": "The exact started-work binding MUST be immutable after first start; exact replay MAY be idempotent and conflicting reuse of the work identity MUST be rejected." - }, - { - "id": "WORKER-REQ-004", - "text": "END_WORK MUST apply only to exact RUNNING work and MUST bind the exact started-work digest." - }, - { - "id": "WORKER-REQ-005", - "text": "END_WORK MUST create exactly one immutable terminal record whose kind is RESULT or NO_RESULT and whose exact terminal binding is bound to that kind." - }, - { - "id": "WORKER-REQ-006", - "text": "NO_RESULT MUST be represented by an explicit exact terminal record and MUST NOT be inferred from absence of a terminal or result record." - }, - { - "id": "WORKER-REQ-007", - "text": "Terminal work MUST NOT return to RUNNING; any subsequent productive attempt MUST use a fresh work identity. Retry or predecessor relationships, if any, are outside the Worker lifecycle canon." - }, - { - "id": "WORKER-REQ-008", - "text": "Worker capability, execution, result and evidence MUST NOT create Authority, Seed Resolution, recognized Context mutation or external effect permission by implication." - }, - { - "id": "WORKER-REQ-009", - "text": "No human, AI model, runtime, tool, solver, robot, provider or other Worker implementation has normative precedence." - } - ], - "schema_version": 1, - "semantic_objects": { - "terminal_record": "Exact immutable terminal record of kind RESULT or NO_RESULT, bound to the exact started work.", - "work_binding": "Exact immutable binding established by START_WORK for one work identity.", - "work_descriptor_binding": "Opaque exact binding to profile- or implementation-defined work description. The Worker canon does not interpret its internal structure.", - "worker_binding": "Opaque exact identity of the productive source. Worker type and implementation are non-normative." - }, - "state_machine": { - "implicit_absence_state": "UNREGISTERED", - "stored_or_derived_states": [ - "RUNNING", - "RESULT", - "NO_RESULT" - ], - "terminal_relation": "XOR", - "terminal_states": [ - "RESULT", - "NO_RESULT" - ], - "transitions": [ - { - "from": "UNREGISTERED", - "operation": "START_WORK", - "to": "RUNNING" - }, - { - "from": "RUNNING", - "operation": "END_WORK", - "terminal_kind": "RESULT", - "to": "RESULT" - }, - { - "from": "RUNNING", - "operation": "END_WORK", - "terminal_kind": "NO_RESULT", - "to": "NO_RESULT" - } - ] - }, - "status": "SEMANTIC_BOOTSTRAP", - "upstream_binding_ref": "upstream/ASET_SEED_BINDING.json", - "version": "0.1.0-alpha.1" -} diff --git a/history/REFERENCES.aset b/history/REFERENCES.aset new file mode 100644 index 0000000..b268d71 --- /dev/null +++ b/history/REFERENCES.aset @@ -0,0 +1,7 @@ +ASET-HISTORY 1 + +STATE ASET-WORKER-CANON-0.1-ALPHA2 HISTORICAL +STATUS SUPERSEDED +ACTIVE-SEMANTICS FALSE +EXECUTABLE-SURFACE NONE +NOTE Superseded public Runtime bootstrap representation; retained in Git history only. diff --git a/pyproject.toml b/pyproject.toml index f4e46b1..0ad1362 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,9 @@ -[build-system] -requires = ["setuptools>=68"] -build-backend = "setuptools.build_meta" - -[project] -name = "aset-worker-extension-bootstrap" -version = "0.1.0a1" -description = "Minimal productive-attempt semantic bootstrap for ASET Worker Extension" -requires-python = ">=3.11" -license = {text = "Apache-2.0"} +[tool.pytest.ini_options] +testpaths = ["tests"] -[project.optional-dependencies] -dev = ["pytest>=8,<9", "jsonschema>=4.20,<5"] +[tool.ruff] +line-length = 100 +target-version = "py312" -[tool.pytest.ini_options] -addopts = "-q" -pythonpath = ["."] +[tool.ruff.lint] +select = ["E", "F", "I", "UP", "B"] diff --git a/reference/__init__.py b/reference/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/reference/oracle.py b/reference/oracle.py deleted file mode 100644 index e0797f9..0000000 --- a/reference/oracle.py +++ /dev/null @@ -1,124 +0,0 @@ -from __future__ import annotations -from copy import deepcopy - -BASE = { - "recognized": False, - "code": "UNSET", - "state_changed": False, - "work_state": "UNREGISTERED", - "authority_created": False, - "effect_permitted": False, - "seed_resolution_created": False, -} - - -def _result(**changes): - out = dict(BASE) - out.update(changes) - return out - - -def state_of(work_id, started, terminal): - t = terminal.get(work_id) - if t is not None: - return t["terminal_kind"] - if work_id in started: - return "RUNNING" - return "UNREGISTERED" - - -def run_case(case): - started = {} - terminal = {} - last = None - - for step in case["steps"]: - kind = step["kind"] - p = step["payload"] - wid = p.get("work_id", "") - - if kind == "START_WORK": - required = [ - p.get("work_id"), - p.get("work_binding_digest"), - p.get("worker_binding"), - p.get("work_descriptor_binding"), - ] - if not all(required): - last = _result(code="WORK_BINDING_REQUIRED") - continue - previous = started.get(wid) - if previous is None: - started[wid] = deepcopy(p) - last = _result( - recognized=True, - code="WORK_STARTED", - state_changed=True, - work_state="RUNNING", - ) - elif previous == p: - last = _result( - recognized=True, - code="IDEMPOTENT_REPLAY", - work_state=state_of(wid, started, terminal), - ) - else: - last = _result( - code="WORK_IDENTITY_CONFLICT", - work_state=state_of(wid, started, terminal), - ) - - elif kind == "END_WORK": - work = started.get(wid) - if work is None: - last = _result(code="WORK_NOT_STARTED") - continue - if p.get("work_binding_digest") != work.get("work_binding_digest"): - last = _result(code="WORK_BINDING_MISMATCH", work_state=state_of(wid, started, terminal)) - continue - terminal_kind = p.get("terminal_kind") - if terminal_kind not in {"RESULT", "NO_RESULT"}: - last = _result(code="TERMINAL_KIND_REQUIRED", work_state="RUNNING") - continue - if not p.get("terminal_record_digest") or not p.get("terminal_binding"): - last = _result(code="TERMINAL_BINDING_REQUIRED", work_state="RUNNING") - continue - previous = terminal.get(wid) - if previous is not None: - if previous == p: - last = _result( - recognized=True, - code="IDEMPOTENT_REPLAY", - work_state=previous["terminal_kind"], - ) - else: - last = _result( - code="TERMINAL_WORK_IMMUTABLE", - work_state=previous["terminal_kind"], - ) - continue - terminal[wid] = deepcopy(p) - code = ( - "WORK_ENDED_WITH_RESULT" - if terminal_kind == "RESULT" - else "WORK_ENDED_WITH_NO_RESULT" - ) - last = _result( - recognized=True, - code=code, - state_changed=True, - work_state=terminal_kind, - ) - - elif kind == "ASSERT_WORKER_AUTHORITY": - last = _result( - code="WORKER_AUTHORITY_FORBIDDEN", - work_state=state_of(wid, started, terminal), - ) - else: - last = _result( - code="UNKNOWN_OPERATION", - work_state=state_of(wid, started, terminal), - ) - - return deepcopy(last) diff --git a/requirements-ci.txt b/requirements-ci.txt index 3c593e6..3089c39 100644 --- a/requirements-ci.txt +++ b/requirements-ci.txt @@ -1,2 +1,2 @@ -pytest>=8,<9 -jsonschema>=4.20,<5 +pytest==9.1.1 +ruff==0.15.22 diff --git a/runtime/alpha4/RUNTIME.aset b/runtime/alpha4/RUNTIME.aset new file mode 100644 index 0000000..2c4cb02 --- /dev/null +++ b/runtime/alpha4/RUNTIME.aset @@ -0,0 +1,56 @@ +ASET-RUNTIME 1 ASET-RUNTIME-ALPHA4 0.1.0-alpha.4 +SEMANTIC-PRECEDENCE NONE +PREDECESSOR-COMPATIBILITY NONE + +UPSTREAM-SUBJECT ASET-SEED-0.4-ALPHA +UPSTREAM-BINDING upstream/ASET_SEED_ALPHA4_BINDING.aset + +SEED-EXTENSION-BIND OPERATIONAL PRESERVE-UNKNOWN,PRESERVE-ALLOW,PRESERVE-BLOCK ALL-RUNTIME-TRANSITIONS +SEED-EXTENSION-BIND RELATIONAL PreserveUnknown,PreserveAllow,PreserveBlock ALL-RUNTIME-TRANSITIONS +SEED-EXTENSION-BIND CAUSAL PRESERVE-UNKNOWN,PRESERVE-ALLOW,PRESERVE-BLOCK ALL-RUNTIME-TRANSITIONS + +STATE STARTS,TERMINALS EXACT-APPEND-ONLY-ATTEMPT-RECORDS +TRANSITION START-ATTEMPT +TRANSITION END-ATTEMPT + +OPERATIONAL runtime/alpha4/operational/components.forth +RELATIONAL runtime/alpha4/formal/RuntimeRelations.tla +FORMAL-REFLECTION runtime/alpha4/formal/RestrictedOperationalSemantics.tla +CAUSAL-MODEL runtime/alpha4/causal/components.petri + +PAIR ASET-RUNTIME-COMPONENT-START-FRESH START-ATTEMPT StartFresh OperationalStartFresh StartFreshPairing +PAIR ASET-RUNTIME-COMPONENT-START-REPLAY START-ATTEMPT StartReplay OperationalStartReplay StartReplayPairing +PAIR ASET-RUNTIME-COMPONENT-REJECT-START-CONFLICT START-ATTEMPT RejectStartConflict OperationalRejectStartConflict RejectStartConflictPairing +PAIR ASET-RUNTIME-COMPONENT-END-RESULT END-ATTEMPT EndResult OperationalEndResult EndResultPairing +PAIR ASET-RUNTIME-COMPONENT-END-NO-RESULT END-ATTEMPT EndNoResult OperationalEndNoResult EndNoResultPairing +PAIR ASET-RUNTIME-COMPONENT-END-REPLAY END-ATTEMPT EndReplay OperationalEndReplay EndReplayPairing +PAIR ASET-RUNTIME-COMPONENT-REJECT-END-CONFLICT END-ATTEMPT RejectEndConflict OperationalRejectEndConflict RejectEndConflictPairing +PAIR ASET-RUNTIME-COMPONENT-REJECT-END-NOT-RUNNING END-ATTEMPT RejectEndNotRunning OperationalRejectEndNotRunning RejectEndNotRunningPairing + +CAUSAL-BIND ASET-RUNTIME-COMPONENT-START-FRESH START-FRESH +CAUSAL-BIND ASET-RUNTIME-COMPONENT-START-REPLAY START-REPLAY +CAUSAL-BIND ASET-RUNTIME-COMPONENT-REJECT-START-CONFLICT REJECT-START-CONFLICT +CAUSAL-BIND ASET-RUNTIME-COMPONENT-END-RESULT END-RESULT +CAUSAL-BIND ASET-RUNTIME-COMPONENT-END-NO-RESULT END-NO-RESULT +CAUSAL-BIND ASET-RUNTIME-COMPONENT-END-REPLAY END-REPLAY +CAUSAL-BIND ASET-RUNTIME-COMPONENT-REJECT-END-CONFLICT REJECT-END-CONFLICT +CAUSAL-BIND ASET-RUNTIME-COMPONENT-REJECT-END-NOT-RUNNING REJECT-END-NOT-RUNNING + +SEED-PROJECTION ALL-RUNTIME-TRANSITIONS PRESERVE-SEED-STATE +SEED-RECOGNITION-OWNER SEED-ONLY +EFFECT-PERMITTED-BY-RUNTIME NEVER + +PROOF OPERATIONAL_RELATIONAL_PAIRING runtime/alpha4/formal/OperationalRelationalPairingProofs.tla OperationalRelationalPairing +PROOF SEED_BOUNDARY runtime/alpha4/formal/SeedBoundaryProofs.tla RuntimePreservesSeedBoundary + +CHECK BINDING tools/validate_alpha4_runtime.py +CHECK OPERATIONAL_RELATIONAL tools/alpha4_runtime_paired_expression.py +CHECK ASSURANCE tools/alpha4_runtime_assurance.py +CHECK TRIANGULATED_EXPRESSION tools/alpha4_runtime_triangulated_expression.py + +RELATION OPERATIONAL_RELATIONAL BOUNDED_OPERATIONAL_RELATIONAL_CONGRUENCE +RELATION OPERATIONAL_CAUSAL BOUNDED_OPERATIONAL_CAUSAL_CONGRUENCE +RELATION RELATIONAL_CAUSAL BOUNDED_RELATIONAL_CAUSAL_CONGRUENCE +RELATION TRIANGULATED THREE_WAY_BOUNDED_OBSERVATIONAL_CONGRUENCE + +GATE tools/alpha4_runtime_gate.py diff --git a/runtime/alpha4/causal/components.petri b/runtime/alpha4/causal/components.petri new file mode 100644 index 0000000..46f33cb --- /dev/null +++ b/runtime/alpha4/causal/components.petri @@ -0,0 +1,96 @@ +ASET-CAUSAL-NET 1 ASET-RUNTIME-ALPHA4-CAUSAL +SEMANTIC-PRECEDENCE NONE +MODE STATE-TRANSITION + +TRANSITION START-FRESH ASET-RUNTIME-COMPONENT-START-FRESH +REQUIRE EXACT_START +REQUIRE FRESH_ID +EFFECT ADD_START +OUTPUT ACCEPTED TRUE +OUTPUT CODE ATTEMPT_STARTED +OUTPUT STATE_CHANGED TRUE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION START-REPLAY ASET-RUNTIME-COMPONENT-START-REPLAY +REQUIRE EXACT_START +REQUIRE EXACT_START_REPLAY +EFFECT PRESERVE_STATE +OUTPUT ACCEPTED TRUE +OUTPUT CODE IDEMPOTENT_REPLAY +OUTPUT STATE_CHANGED FALSE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION REJECT-START-CONFLICT ASET-RUNTIME-COMPONENT-REJECT-START-CONFLICT +REQUIRE EXACT_START +REQUIRE START_CONFLICT +EFFECT PRESERVE_STATE +OUTPUT ACCEPTED FALSE +OUTPUT CODE ATTEMPT_IDENTITY_CONFLICT +OUTPUT STATE_CHANGED FALSE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION END-RESULT ASET-RUNTIME-COMPONENT-END-RESULT +REQUIRE EXACT_TERMINAL +REQUIRE EXACT_RUNNING +REQUIRE FRESH_TERMINAL +REQUIRE KIND_RESULT +EFFECT ADD_TERMINAL +OUTPUT ACCEPTED TRUE +OUTPUT CODE ATTEMPT_ENDED_WITH_RESULT +OUTPUT STATE_CHANGED TRUE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION END-NO-RESULT ASET-RUNTIME-COMPONENT-END-NO-RESULT +REQUIRE EXACT_TERMINAL +REQUIRE EXACT_RUNNING +REQUIRE FRESH_TERMINAL +REQUIRE KIND_NO_RESULT +EFFECT ADD_TERMINAL +OUTPUT ACCEPTED TRUE +OUTPUT CODE ATTEMPT_ENDED_WITH_NO_RESULT +OUTPUT STATE_CHANGED TRUE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION END-REPLAY ASET-RUNTIME-COMPONENT-END-REPLAY +REQUIRE EXACT_TERMINAL +REQUIRE EXACT_TERMINAL_REPLAY +EFFECT PRESERVE_STATE +OUTPUT ACCEPTED TRUE +OUTPUT CODE IDEMPOTENT_REPLAY +OUTPUT STATE_CHANGED FALSE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION REJECT-END-CONFLICT ASET-RUNTIME-COMPONENT-REJECT-END-CONFLICT +REQUIRE EXACT_TERMINAL +REQUIRE TERMINAL_CONFLICT +EFFECT PRESERVE_STATE +OUTPUT ACCEPTED FALSE +OUTPUT CODE TERMINAL_ATTEMPT_IMMUTABLE +OUTPUT STATE_CHANGED FALSE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END + +TRANSITION REJECT-END-NOT-RUNNING ASET-RUNTIME-COMPONENT-REJECT-END-NOT-RUNNING +REQUIRE EXACT_TERMINAL +REQUIRE NO_TERMINAL_FOR_ID +REQUIRE NOT_EXACT_RUNNING +EFFECT PRESERVE_STATE +OUTPUT ACCEPTED FALSE +OUTPUT CODE ATTEMPT_NOT_RUNNING +OUTPUT STATE_CHANGED FALSE +OUTPUT SEED_ACTION STUTTER +OUTPUT SEED_EFFECT FALSE +END diff --git a/runtime/alpha4/formal/OperationalRelationalPairingProofs.tla b/runtime/alpha4/formal/OperationalRelationalPairingProofs.tla new file mode 100644 index 0000000..fc792f2 --- /dev/null +++ b/runtime/alpha4/formal/OperationalRelationalPairingProofs.tla @@ -0,0 +1,72 @@ +-------------- MODULE OperationalRelationalPairingProofs -------------- +EXTENDS RestrictedOperationalSemantics, TLAPS + +THEOREM StartFreshPairing == + \A s, t, start, result : + OperationalStartFresh(s, t, start, result) <=> StartFresh(s, t, start, result) +PROOF + BY DEF OperationalStartFresh, StartFresh + +THEOREM StartReplayPairing == + \A s, t, start, result : + OperationalStartReplay(s, t, start, result) <=> StartReplay(s, t, start, result) +PROOF + BY DEF OperationalStartReplay, StartReplay + +THEOREM RejectStartConflictPairing == + \A s, t, start, result : + OperationalRejectStartConflict(s, t, start, result) <=> RejectStartConflict(s, t, start, result) +PROOF + BY DEF OperationalRejectStartConflict, RejectStartConflict + +THEOREM EndResultPairing == + \A s, t, terminal, result : + OperationalEndResult(s, t, terminal, result) <=> EndResult(s, t, terminal, result) +PROOF + BY DEF OperationalEndResult, EndResult + +THEOREM EndNoResultPairing == + \A s, t, terminal, result : + OperationalEndNoResult(s, t, terminal, result) <=> EndNoResult(s, t, terminal, result) +PROOF + BY DEF OperationalEndNoResult, EndNoResult + +THEOREM EndReplayPairing == + \A s, t, terminal, result : + OperationalEndReplay(s, t, terminal, result) <=> EndReplay(s, t, terminal, result) +PROOF + BY DEF OperationalEndReplay, EndReplay + +THEOREM RejectEndConflictPairing == + \A s, t, terminal, result : + OperationalRejectEndConflict(s, t, terminal, result) <=> RejectEndConflict(s, t, terminal, result) +PROOF + BY DEF OperationalRejectEndConflict, RejectEndConflict + +THEOREM RejectEndNotRunningPairing == + \A s, t, terminal, result : + OperationalRejectEndNotRunning(s, t, terminal, result) + <=> RejectEndNotRunning(s, t, terminal, result) +PROOF + BY DEF OperationalRejectEndNotRunning, RejectEndNotRunning + +THEOREM OperationalRelationalPairing == + /\ StartFreshPairing + /\ StartReplayPairing + /\ RejectStartConflictPairing + /\ EndResultPairing + /\ EndNoResultPairing + /\ EndReplayPairing + /\ RejectEndConflictPairing + /\ RejectEndNotRunningPairing +PROOF + BY StartFreshPairing, + StartReplayPairing, + RejectStartConflictPairing, + EndResultPairing, + EndNoResultPairing, + EndReplayPairing, + RejectEndConflictPairing, + RejectEndNotRunningPairing + +============================================================================= diff --git a/runtime/alpha4/formal/RestrictedOperationalSemantics.tla b/runtime/alpha4/formal/RestrictedOperationalSemantics.tla new file mode 100644 index 0000000..75045b7 --- /dev/null +++ b/runtime/alpha4/formal/RestrictedOperationalSemantics.tla @@ -0,0 +1,63 @@ +-------------------- MODULE RestrictedOperationalSemantics -------------------- +EXTENDS RuntimeRelations + +OperationalStartFresh(s, t, start, result) == + /\ RuntimeInvariant(s) + /\ start \in StartUniverse + /\ FreshStartIdentifier(s, start) + /\ t = [s EXCEPT !.starts = @ \cup {start}] + /\ result = "ATTEMPT_STARTED" + +OperationalStartReplay(s, t, start, result) == + /\ RuntimeInvariant(s) + /\ start \in StartUniverse + /\ ExactStartReplay(s, start) + /\ t = s + /\ result = "IDEMPOTENT_REPLAY" + +OperationalRejectStartConflict(s, t, start, result) == + /\ RuntimeInvariant(s) + /\ start \in StartUniverse + /\ StartConflict(s, start) + /\ t = s + /\ result = "ATTEMPT_IDENTITY_CONFLICT" + +OperationalEndResult(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ terminal.terminal_kind = "RESULT" + /\ ExactRunning(s, terminal) + /\ t = [s EXCEPT !.terminals = @ \cup {terminal}] + /\ result = "ATTEMPT_ENDED_WITH_RESULT" + +OperationalEndNoResult(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ terminal.terminal_kind = "NO_RESULT" + /\ ExactRunning(s, terminal) + /\ t = [s EXCEPT !.terminals = @ \cup {terminal}] + /\ result = "ATTEMPT_ENDED_WITH_NO_RESULT" + +OperationalEndReplay(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ ExactTerminalReplay(s, terminal) + /\ t = s + /\ result = "IDEMPOTENT_REPLAY" + +OperationalRejectEndConflict(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ TerminalConflict(s, terminal) + /\ t = s + /\ result = "TERMINAL_ATTEMPT_IMMUTABLE" + +OperationalRejectEndNotRunning(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ FreshTerminalIdentifier(s, terminal) + /\ ~MatchingStart(s, terminal) + /\ t = s + /\ result = "ATTEMPT_NOT_RUNNING" + +============================================================================= diff --git a/runtime/alpha4/formal/RuntimeRelations.tla b/runtime/alpha4/formal/RuntimeRelations.tla new file mode 100644 index 0000000..7c74492 --- /dev/null +++ b/runtime/alpha4/formal/RuntimeRelations.tla @@ -0,0 +1,164 @@ +--------------------------- MODULE RuntimeRelations --------------------------- +EXTENDS FiniteSets + +CONSTANTS AttemptIds, AttemptDigests, RuntimeBindings, DescriptorBindings, + TerminalDigests, TerminalBindings, EvidenceBindings + +TerminalKinds == {"RESULT", "NO_RESULT"} + +StartUniverse == + [attempt_id : AttemptIds, + attempt_digest : AttemptDigests, + runtime_binding : RuntimeBindings, + descriptor_binding : DescriptorBindings] + +TerminalUniverse == + [attempt_id : AttemptIds, + attempt_digest : AttemptDigests, + terminal_kind : TerminalKinds, + terminal_digest : TerminalDigests, + terminal_binding : TerminalBindings, + evidence_bindings : SUBSET EvidenceBindings] + +StateType == [starts : SUBSET StartUniverse, terminals : SUBSET TerminalUniverse] + +SameStartIdentifier(a, b) == a.attempt_id = b.attempt_id +SameTerminalIdentifier(a, b) == a.attempt_id = b.attempt_id + +StartIdentifierExists(s, start) == + \E current \in s.starts : SameStartIdentifier(current, start) + +TerminalIdentifierExists(s, terminal) == + \E current \in s.terminals : SameTerminalIdentifier(current, terminal) + +FreshStartIdentifier(s, start) == ~StartIdentifierExists(s, start) +ExactStartReplay(s, start) == start \in s.starts +StartConflict(s, start) == + /\ StartIdentifierExists(s, start) + /\ ~ExactStartReplay(s, start) + +FreshTerminalIdentifier(s, terminal) == ~TerminalIdentifierExists(s, terminal) +ExactTerminalReplay(s, terminal) == terminal \in s.terminals +TerminalConflict(s, terminal) == + /\ TerminalIdentifierExists(s, terminal) + /\ ~ExactTerminalReplay(s, terminal) + +MatchingStart(s, terminal) == + \E start \in s.starts : + /\ start.attempt_id = terminal.attempt_id + /\ start.attempt_digest = terminal.attempt_digest + +ExactRunning(s, terminal) == + /\ MatchingStart(s, terminal) + /\ FreshTerminalIdentifier(s, terminal) + +StartIdentifiersUnique(s) == + \A a, b \in s.starts : SameStartIdentifier(a, b) => a = b + +TerminalIdentifiersUnique(s) == + \A a, b \in s.terminals : SameTerminalIdentifier(a, b) => a = b + +TerminalsBoundToStarts(s) == + \A terminal \in s.terminals : MatchingStart(s, terminal) + +RuntimeInvariant(s) == + /\ s \in StateType + /\ StartIdentifiersUnique(s) + /\ TerminalIdentifiersUnique(s) + /\ TerminalsBoundToStarts(s) + +ResultCodes == + {"ATTEMPT_STARTED", + "IDEMPOTENT_REPLAY", + "ATTEMPT_IDENTITY_CONFLICT", + "ATTEMPT_ENDED_WITH_RESULT", + "ATTEMPT_ENDED_WITH_NO_RESULT", + "TERMINAL_ATTEMPT_IMMUTABLE", + "ATTEMPT_NOT_RUNNING"} + +AcceptedResult(result) == + result \in + {"ATTEMPT_STARTED", + "IDEMPOTENT_REPLAY", + "ATTEMPT_ENDED_WITH_RESULT", + "ATTEMPT_ENDED_WITH_NO_RESULT"} + +SeedProjectionAction(result) == "STUTTER" +SeedProjectionEffectPermitted(result) == FALSE + +StartFresh(s, t, start, result) == + /\ RuntimeInvariant(s) + /\ start \in StartUniverse + /\ FreshStartIdentifier(s, start) + /\ t = [s EXCEPT !.starts = @ \cup {start}] + /\ result = "ATTEMPT_STARTED" + +StartReplay(s, t, start, result) == + /\ RuntimeInvariant(s) + /\ start \in StartUniverse + /\ ExactStartReplay(s, start) + /\ t = s + /\ result = "IDEMPOTENT_REPLAY" + +RejectStartConflict(s, t, start, result) == + /\ RuntimeInvariant(s) + /\ start \in StartUniverse + /\ StartConflict(s, start) + /\ t = s + /\ result = "ATTEMPT_IDENTITY_CONFLICT" + +StartAttempt(s, t, start, result) == + \/ StartFresh(s, t, start, result) + \/ StartReplay(s, t, start, result) + \/ RejectStartConflict(s, t, start, result) + +EndResult(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ terminal.terminal_kind = "RESULT" + /\ ExactRunning(s, terminal) + /\ t = [s EXCEPT !.terminals = @ \cup {terminal}] + /\ result = "ATTEMPT_ENDED_WITH_RESULT" + +EndNoResult(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ terminal.terminal_kind = "NO_RESULT" + /\ ExactRunning(s, terminal) + /\ t = [s EXCEPT !.terminals = @ \cup {terminal}] + /\ result = "ATTEMPT_ENDED_WITH_NO_RESULT" + +EndReplay(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ ExactTerminalReplay(s, terminal) + /\ t = s + /\ result = "IDEMPOTENT_REPLAY" + +RejectEndConflict(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ TerminalConflict(s, terminal) + /\ t = s + /\ result = "TERMINAL_ATTEMPT_IMMUTABLE" + +RejectEndNotRunning(s, t, terminal, result) == + /\ RuntimeInvariant(s) + /\ terminal \in TerminalUniverse + /\ FreshTerminalIdentifier(s, terminal) + /\ ~MatchingStart(s, terminal) + /\ t = s + /\ result = "ATTEMPT_NOT_RUNNING" + +EndAttempt(s, t, terminal, result) == + \/ EndResult(s, t, terminal, result) + \/ EndNoResult(s, t, terminal, result) + \/ EndReplay(s, t, terminal, result) + \/ RejectEndConflict(s, t, terminal, result) + \/ RejectEndNotRunning(s, t, terminal, result) + +Next(s, t) == + \/ \E start \in StartUniverse, result \in ResultCodes : StartAttempt(s, t, start, result) + \/ \E terminal \in TerminalUniverse, result \in ResultCodes : EndAttempt(s, t, terminal, result) + +============================================================================= diff --git a/runtime/alpha4/formal/SeedBoundaryProofs.tla b/runtime/alpha4/formal/SeedBoundaryProofs.tla new file mode 100644 index 0000000..2aef48a --- /dev/null +++ b/runtime/alpha4/formal/SeedBoundaryProofs.tla @@ -0,0 +1,20 @@ +---------------------- MODULE SeedBoundaryProofs ---------------------- +EXTENDS RuntimeRelations, TLAPS + +THEOREM RuntimeProjectsOnlyToSeedStutter == + \A result \in ResultCodes : SeedProjectionAction(result) = "STUTTER" +PROOF + BY DEF SeedProjectionAction + +THEOREM RuntimeNeverPermitsSeedEffect == + \A result \in ResultCodes : SeedProjectionEffectPermitted(result) = FALSE +PROOF + BY DEF SeedProjectionEffectPermitted + +THEOREM RuntimePreservesSeedBoundary == + /\ RuntimeProjectsOnlyToSeedStutter + /\ RuntimeNeverPermitsSeedEffect +PROOF + BY RuntimeProjectsOnlyToSeedStutter, RuntimeNeverPermitsSeedEffect + +============================================================================= diff --git a/runtime/alpha4/operational/components.forth b/runtime/alpha4/operational/components.forth new file mode 100644 index 0000000..989d4f4 --- /dev/null +++ b/runtime/alpha4/operational/components.forth @@ -0,0 +1,8 @@ +: START-FRESH ( state start -- state result ) EXACT-START? FRESH-ID? ADD-START ATTEMPT-STARTED ; +: START-REPLAY ( state start -- state result ) EXACT-START? EXACT-START-REPLAY? KEEP-STATE IDEMPOTENT-REPLAY ; +: REJECT-START-CONFLICT ( state start -- state result ) EXACT-START? START-CONFLICT? KEEP-STATE ATTEMPT-IDENTITY-CONFLICT ; +: END-RESULT ( state terminal -- state result ) EXACT-TERMINAL? EXACT-RUNNING? FRESH-TERMINAL? KIND-RESULT? ADD-TERMINAL ATTEMPT-ENDED-WITH-RESULT ; +: END-NO-RESULT ( state terminal -- state result ) EXACT-TERMINAL? EXACT-RUNNING? FRESH-TERMINAL? KIND-NO-RESULT? ADD-TERMINAL ATTEMPT-ENDED-WITH-NO-RESULT ; +: END-REPLAY ( state terminal -- state result ) EXACT-TERMINAL? EXACT-TERMINAL-REPLAY? KEEP-STATE IDEMPOTENT-REPLAY ; +: REJECT-END-CONFLICT ( state terminal -- state result ) EXACT-TERMINAL? TERMINAL-CONFLICT? KEEP-STATE TERMINAL-ATTEMPT-IMMUTABLE ; +: REJECT-END-NOT-RUNNING ( state terminal -- state result ) EXACT-TERMINAL? NO-TERMINAL-FOR-ID? NOT-EXACT-RUNNING? KEEP-STATE ATTEMPT-NOT-RUNNING ; diff --git a/standards/worker-compatibility/compatibility-standard-profile-v1.json b/standards/worker-compatibility/compatibility-standard-profile-v1.json deleted file mode 100644 index bf7fe9b..0000000 --- a/standards/worker-compatibility/compatibility-standard-profile-v1.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "document_type": "aset-worker-compatibility-standard-profile", - "formal_release_gate": "REQUIRES_REPRODUCIBLE_FORMAL_RELEASE_GATE", - "implementation_precedence": "NONE", - "profile_id": "ASET-WORKER-COMPATIBILITY-STANDARD-V1", - "required_conformance_profile": "ASET-WORKER-CONFORMANCE-V2", - "requires_seed": "ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3", - "schema_version": 1, - "series_id": "ASET-WORKER-COMPATIBILITY-STANDARD", - "status": "FORMAL_ASSURANCE_MATERIALIZED_NOT_RELEASED", - "worker_canon": "ASET-WORKER-CANON-0.1-ALPHA2" -} diff --git a/tests/test_alpha4_runtime.py b/tests/test_alpha4_runtime.py new file mode 100644 index 0000000..b8a4596 --- /dev/null +++ b/tests/test_alpha4_runtime.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +from tools.alpha4_runtime_paired_expression import ( + bounded_pairing_check, + bounded_safety_check, + operational_end, + operational_start, + parse_operational_words, +) +from tools.validate_alpha4_runtime import main as validate_runtime + + +def test_runtime_alpha4_validation() -> None: + assert validate_runtime() == 0 + + +def test_operational_surface_is_exactly_eight_components() -> None: + assert len(parse_operational_words()) == 8 + + +def test_bounded_operational_relational_pairing() -> None: + evidence = bounded_pairing_check() + assert evidence == {"start": 484, "end": 1936, "total": 2420} + + +def test_bounded_runtime_safety_and_append_only_boundaries() -> None: + evidence = bounded_safety_check() + assert evidence == {"start": 484, "end": 1936, "total": 2420} + + +def test_result_and_no_result_are_distinct_exact_terminals() -> None: + start = { + "attempt_id": "a0", + "attempt_digest": "d0", + "runtime_binding": "runtime:0", + "descriptor_binding": "descriptor:0", + } + empty = {"starts": [], "terminals": []} + running, started = operational_start(empty, start) + assert started["code"] == "ATTEMPT_STARTED" + result_terminal = { + "attempt_id": "a0", + "attempt_digest": "d0", + "terminal_kind": "RESULT", + "terminal_digest": "t0", + "terminal_binding": "tb0", + "evidence_bindings": ["e0"], + } + no_result_terminal = {**result_terminal, "terminal_kind": "NO_RESULT", "terminal_digest": "t1"} + result_state, result = operational_end(running, result_terminal) + no_result_state, no_result = operational_end(running, no_result_terminal) + assert result["code"] == "ATTEMPT_ENDED_WITH_RESULT" + assert no_result["code"] == "ATTEMPT_ENDED_WITH_NO_RESULT" + assert result_state != no_result_state + assert ( + result["seed_projection"] + == no_result["seed_projection"] + == { + "action": "STUTTER", + "effect_permitted": False, + } + ) + + +def test_start_identity_conflict_covers_non_digest_bindings() -> None: + start = { + "attempt_id": "a0", + "attempt_digest": "d0", + "runtime_binding": "runtime:0", + "descriptor_binding": "descriptor:0", + } + running, _ = operational_start({"starts": [], "terminals": []}, start) + conflicting = {**start, "runtime_binding": "runtime:1"} + next_state, result = operational_start(running, conflicting) + assert next_state == running + assert result["code"] == "ATTEMPT_IDENTITY_CONFLICT" + assert result["accepted"] is False + + +def test_terminal_identity_conflict_covers_terminal_binding() -> None: + start = { + "attempt_id": "a0", + "attempt_digest": "d0", + "runtime_binding": "runtime:0", + "descriptor_binding": "descriptor:0", + } + running, _ = operational_start({"starts": [], "terminals": []}, start) + terminal = { + "attempt_id": "a0", + "attempt_digest": "d0", + "terminal_kind": "RESULT", + "terminal_digest": "t0", + "terminal_binding": "terminal-binding:0", + "evidence_bindings": ["e0"], + } + ended, _ = operational_end(running, terminal) + conflicting = {**terminal, "terminal_binding": "terminal-binding:1"} + next_state, result = operational_end(ended, conflicting) + assert next_state == ended + assert result["code"] == "TERMINAL_ATTEMPT_IMMUTABLE" + assert result["accepted"] is False diff --git a/tests/test_alpha4_runtime_release_architecture.py b/tests/test_alpha4_runtime_release_architecture.py new file mode 100644 index 0000000..6c8e2eb --- /dev/null +++ b/tests/test_alpha4_runtime_release_architecture.py @@ -0,0 +1,84 @@ +from __future__ import annotations + +import hashlib +from pathlib import Path + +from tools.alpha4_runtime_public_release_audit import check_public_root +from tools.alpha4_runtime_release_profiles import ( + manifest_records, + parse_english, + write_english, + write_python, +) +from tools.build_alpha4_runtime_release import write_assembled_runtime +from tools.run_alpha4_runtime_release_tlaps import FINAL_THEOREM, verifier_source + + +def test_generated_english_round_trip(tmp_path: Path) -> None: + target = tmp_path / "Runtime.md" + records = manifest_records() + write_english(target, "sha256:" + "0" * 64, records) + assert parse_english(target) == records + + +def test_generated_python_uses_exact_seed_base_and_stutters_seed(tmp_path: Path) -> None: + profiles = tmp_path / "profiles" + base = profiles / "base/seed/python/aset_seed_alpha4.py" + runtime = profiles / "python/aset_runtime_alpha4.py" + base.parent.mkdir(parents=True) + runtime.parent.mkdir(parents=True) + base.write_text( + "def state(subject, authority, recognition='UNKNOWN', evidence=()):\n" + " return {'subject': subject, 'authority': authority, " + "'recognition': recognition, 'evidence': tuple(evidence)}\n\n" + "def apply_component(current, component_id, **kwargs):\n" + " return dict(current)\n", + encoding="utf-8", + ) + digest = "sha256:" + hashlib.sha256(base.read_bytes()).hexdigest() + write_python(runtime, digest, manifest_records()) + namespace = {"__file__": str(runtime), "__name__": "runtime_test_subject"} + exec(compile(runtime.read_text(encoding="utf-8"), str(runtime), "exec"), namespace) + current = namespace["state"]() + seed = {"subject": "s", "authority": "a", "recognition": "ALLOW", "evidence": ("e",)} + start = { + "attempt_id": "x", + "attempt_digest": "d", + "runtime_binding": "r", + "descriptor_binding": "q", + } + next_runtime, next_seed, result = namespace["start_attempt"](current, start, seed) + assert next_runtime["starts"] == [start] + assert next_seed == seed + assert result["seed_projection"] == {"action": "STUTTER", "effect_permitted": False} + + +def test_assembled_runtime_is_a_nonsemantic_composition_alias(tmp_path: Path) -> None: + target = tmp_path / "AssembledRuntime.tla" + write_assembled_runtime(target) + text = target.read_text(encoding="utf-8") + assert "EXTENDS RuntimeRelations" in text + assert "AssembledStep(s, t, result) ==" in text + assert "AssembledNext(s, t) == Next(s, t)" in text + + +def test_post_build_verifier_binds_all_exact_seed_preservation_operators() -> None: + source = verifier_source() + assert FINAL_THEOREM == "AssembledRuntimePreservesExactSeedBoundary" + assert "Seed!PreserveUnknown" in source + assert "Seed!PreserveAllow" in source + assert "Seed!PreserveBlock" in source + assert "AssembledStep(rs, rt, result)" in source + assert 'SeedProjectionAction(result) = "STUTTER"' in source + assert "SeedProjectionEffectPermitted(result) = FALSE" in source + assert "ExactSeedPreservation(s, t, e)" in source + assert "t = s" in source + assert "t.recognition = s.recognition" in source + + +def test_public_root_matches_runtime_identity() -> None: + identity = check_public_root() + assert identity["project"] == "ASET Runtime" + assert identity["representation_id"] == "0.1.0-alpha.4" + assert identity["subject_id"] == "ASET-RUNTIME-ALPHA4" + assert identity["repository"] == "https://github.com/attractor-set/aset-runtime" diff --git a/tests/test_alpha4_runtime_three_way_assurance.py b/tests/test_alpha4_runtime_three_way_assurance.py new file mode 100644 index 0000000..94e80aa --- /dev/null +++ b/tests/test_alpha4_runtime_three_way_assurance.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from tools.alpha4_runtime_causal_expression import check_causal_bindings +from tools.alpha4_runtime_triangulated_expression import ( + check_representation_source_independence, + check_triangulated_assurance, +) + + +def test_causal_surface_binds_all_runtime_components() -> None: + net = check_causal_bindings() + assert len(net.transitions) == 8 + assert all(item.output_map()["SEED_ACTION"] == "STUTTER" for item in net.transitions) + assert all(item.output_map()["SEED_EFFECT"] == "FALSE" for item in net.transitions) + + +def test_three_assurance_representations_use_distinct_source_paths() -> None: + sources = check_representation_source_independence() + assert set(sources) == {"OPERATIONAL", "RELATIONAL", "CAUSAL-MODEL"} + assert len(set(sources.values())) == 3 + + +def test_three_way_assurance_covers_complete_bounded_domain() -> None: + evidence = check_triangulated_assurance() + assert evidence["start_checks"] == 484 + assert evidence["end_checks"] == 1936 + assert evidence["total_checks"] == 2420 + assert evidence["pairwise_relations"] == { + "operational_relational": "PASS", + "operational_causal": "PASS", + "relational_causal": "PASS", + } + assert evidence["representation_source_independence"] == "PASS" + assert evidence["seed_action"] == "STUTTER" + assert evidence["status"] == "PASS" diff --git a/tests/test_repository_minimal.py b/tests/test_repository_minimal.py new file mode 100644 index 0000000..984c375 --- /dev/null +++ b/tests/test_repository_minimal.py @@ -0,0 +1,5 @@ +from tools.validate_repository_minimal import main + + +def test_repository_surface_is_minimal() -> None: + assert main() == 0 diff --git a/tests/test_seed_stutter_assurance.py b/tests/test_seed_stutter_assurance.py deleted file mode 100644 index f68413e..0000000 --- a/tests/test_seed_stutter_assurance.py +++ /dev/null @@ -1,48 +0,0 @@ -from __future__ import annotations - -import json -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] - - -def profile() -> dict: - return json.loads( - (ROOT / "assurance/seed-stutter/ASSURANCE_PROFILE.json").read_text( - encoding="utf-8" - ) - ) - - -def test_profile_is_non_normative_evidence_composition() -> None: - value = profile() - assert value["normative"] is False - assert value["normative_precedence"] == "NONE" - assert value["relation_type"] == "EVIDENCE_COMPOSITION_OVER_SHARED_SEED_SUBJECT" - - -def test_profile_pins_public_v60_and_exact_seed_subject() -> None: - value = profile() - assert ( - value["public_v60_subject"]["commit"] - == "e89d984203a126f8bc62467224cdf6c5374dada7" - ) - assert value["public_v60_subject"]["expected_tlaps_obligations"] == 2257 - assert value["shared_seed_subject"]["seed_resolution_sha256"] == ( - "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926" - ) - - -def test_profile_does_not_claim_new_composed_theorem() -> None: - assert ( - "a new mechanically composed Worker-to-v60 TLAPS theorem" - in profile()["claim_boundary"]["excluded"] - ) - - -def test_worker_projection_contract_remains_non_authoritative() -> None: - contract = profile()["projection_contract"] - assert contract["worker_operations"] == "SEED_STUTTER" - assert contract["worker_owned_seed_state"] is False - assert contract["worker_creates_seed_resolution"] is False - assert contract["worker_grants_external_effect_permission"] is False diff --git a/tests/test_worker_semantics.py b/tests/test_worker_semantics.py deleted file mode 100644 index 6d28e88..0000000 --- a/tests/test_worker_semantics.py +++ /dev/null @@ -1,43 +0,0 @@ -import json -from pathlib import Path -from reference.oracle import run_case - -ROOT = Path(__file__).resolve().parents[1] - - -def test_all_conformance_cases(): - for p in sorted((ROOT / "extension/canonical/conformance/cases").rglob("*.json")): - case = json.loads(p.read_text()) - assert run_case(case) == case["expected"] - - -def test_terminal_pair_is_xor_in_canon(): - model = json.loads((ROOT / "extension/canonical/source/worker-model.json").read_text()) - assert model["state_machine"]["terminal_states"] == ["RESULT", "NO_RESULT"] - assert model["state_machine"]["terminal_relation"] == "XOR" - - -def test_no_result_is_explicit_not_absence(): - model = json.loads((ROOT / "extension/canonical/source/worker-model.json").read_text()) - assert "explicit terminal assertion" in model["derived_semantics"]["NO_RESULT_NOT_ABSENCE"] - - -def test_worker_does_not_claim_authority(): - model = json.loads((ROOT / "extension/canonical/source/worker-model.json").read_text()) - texts = " ".join(x["text"] for x in model["requirements"] + model["invariants"]) - assert "Authority" in texts - assert "Seed Resolution" in texts - - -def test_acceptance_is_not_in_worker_lifecycle(): - model = json.loads((ROOT / "extension/canonical/source/worker-model.json").read_text()) - assert [x["kind"] for x in model["operations"]] == ["START_WORK", "END_WORK"] - assert "ACCEPTED" not in model["state_machine"]["stored_or_derived_states"] - assert "eligibility, assignment or acceptance" in model["normative_scope"]["does_not_define"] - - -def test_work_descriptor_is_opaque_to_worker(): - model = json.loads((ROOT / "extension/canonical/source/worker-model.json").read_text()) - text = model["semantic_objects"]["work_descriptor_binding"] - assert "Opaque" in text - assert "does not interpret" in text diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 0000000..42682d3 --- /dev/null +++ b/tools/__init__.py @@ -0,0 +1 @@ +"""ASET Runtime verification tooling.""" diff --git a/tools/alpha4_runtime_assurance.py b/tools/alpha4_runtime_assurance.py new file mode 100644 index 0000000..f184980 --- /dev/null +++ b/tools/alpha4_runtime_assurance.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +from tools.alpha4_runtime_causal_expression import check_causal_bindings +from tools.alpha4_runtime_triangulated_expression import ( + check_triangulated_assurance, + print_evidence, +) + + +def main() -> int: + check_causal_bindings() + evidence = check_triangulated_assurance() + print_evidence(evidence) + print("ALPHA4_RUNTIME_ASSURANCE_SEMANTIC_DELTA=NONE") + print("ALPHA4_RUNTIME_ASSURANCE=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_causal_expression.py b/tools/alpha4_runtime_causal_expression.py new file mode 100644 index 0000000..e682466 --- /dev/null +++ b/tools/alpha4_runtime_causal_expression.py @@ -0,0 +1,243 @@ +from __future__ import annotations + +from copy import deepcopy +from dataclasses import dataclass +from pathlib import Path +from typing import Any + +from tools.alpha4_runtime_paired_expression import exact_start, exact_terminal + +ROOT = Path(__file__).resolve().parents[1] +CAUSAL = ROOT / "runtime/alpha4/causal/components.petri" +MANIFEST = ROOT / "runtime/alpha4/RUNTIME.aset" + + +class CausalExpressionError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise CausalExpressionError(message) + + +@dataclass(frozen=True) +class CausalTransition: + symbol: str + component_id: str + requirements: tuple[str, ...] + effects: tuple[str, ...] + outputs: tuple[tuple[str, str], ...] + + def output_map(self) -> dict[str, str]: + return dict(self.outputs) + + +@dataclass(frozen=True) +class CausalNet: + schema_version: int + subject_id: str + semantic_precedence: str + mode: str + transitions: tuple[CausalTransition, ...] + + +def _lines(path: Path) -> list[str]: + return [line.strip() for line in path.read_text(encoding="utf-8").splitlines() if line.strip()] + + +def parse_causal_net(path: Path = CAUSAL) -> CausalNet: + lines = _lines(path) + require(lines, "causal source is empty") + head = lines[0].split() + require( + head == ["ASET-CAUSAL-NET", "1", "ASET-RUNTIME-ALPHA4-CAUSAL"], + "causal header mismatch", + ) + semantic_precedence = "" + mode = "" + transitions: list[CausalTransition] = [] + index = 1 + while index < len(lines): + tokens = lines[index].split() + if tokens[0] == "SEMANTIC-PRECEDENCE": + require(tokens == ["SEMANTIC-PRECEDENCE", "NONE"], "causal precedence drift") + semantic_precedence = "NONE" + index += 1 + continue + if tokens[0] == "MODE": + require(tokens == ["MODE", "STATE-TRANSITION"], "causal mode drift") + mode = "STATE-TRANSITION" + index += 1 + continue + require( + tokens[0] == "TRANSITION" and len(tokens) == 3, + f"invalid causal statement: {lines[index]}", + ) + symbol, component_id = tokens[1], tokens[2] + requirements: list[str] = [] + effects: list[str] = [] + outputs: list[tuple[str, str]] = [] + index += 1 + while index < len(lines) and lines[index] != "END": + body = lines[index].split() + if body[0] == "REQUIRE": + require(len(body) == 2, f"{symbol}: invalid REQUIRE") + requirements.append(body[1]) + elif body[0] == "EFFECT": + require(len(body) == 2, f"{symbol}: invalid EFFECT") + effects.append(body[1]) + elif body[0] == "OUTPUT": + require(len(body) == 3, f"{symbol}: invalid OUTPUT") + outputs.append((body[1], body[2])) + else: + raise CausalExpressionError(f"{symbol}: unsupported statement {body[0]}") + index += 1 + require(index < len(lines) and lines[index] == "END", f"{symbol}: END missing") + transitions.append( + CausalTransition( + symbol=symbol, + component_id=component_id, + requirements=tuple(requirements), + effects=tuple(effects), + outputs=tuple(outputs), + ) + ) + index += 1 + require(semantic_precedence == "NONE", "causal semantic precedence missing") + require(mode == "STATE-TRANSITION", "causal mode missing") + require(len(transitions) == 8, "Runtime causal surface must contain exactly eight transitions") + require(len({item.symbol for item in transitions}) == 8, "duplicate causal transition") + require(len({item.component_id for item in transitions}) == 8, "duplicate causal component") + return CausalNet(1, "ASET-RUNTIME-ALPHA4-CAUSAL", semantic_precedence, mode, tuple(transitions)) + + +def manifest_bindings() -> dict[str, str]: + result: dict[str, str] = {} + for line in _lines(MANIFEST): + parts = line.split() + if parts[0] == "CAUSAL-BIND": + require(len(parts) == 3, f"invalid CAUSAL-BIND: {line}") + result[parts[1]] = parts[2] + require(len(result) == 8, "Runtime causal manifest bindings must contain eight entries") + return result + + +def check_causal_bindings() -> CausalNet: + net = parse_causal_net() + actual = {item.component_id: item.symbol for item in net.transitions} + require(actual == manifest_bindings(), "causal component binding mismatch") + for transition in net.transitions: + outputs = transition.output_map() + require(outputs.get("SEED_ACTION") == "STUTTER", f"{transition.symbol}: Seed action drift") + require(outputs.get("SEED_EFFECT") == "FALSE", f"{transition.symbol}: Seed effect drift") + return net + + +def _bool(value: str) -> bool: + require(value in {"TRUE", "FALSE"}, f"invalid causal boolean: {value}") + return value == "TRUE" + + +def _copy_state(state: dict[str, list[dict[str, Any]]]) -> dict[str, list[dict[str, Any]]]: + return {"starts": deepcopy(state["starts"]), "terminals": deepcopy(state["terminals"])} + + +def _result(transition: CausalTransition) -> dict[str, Any]: + outputs = transition.output_map() + return { + "accepted": _bool(outputs["ACCEPTED"]), + "code": outputs["CODE"], + "state_changed": _bool(outputs["STATE_CHANGED"]), + "seed_projection": { + "action": outputs["SEED_ACTION"], + "effect_permitted": _bool(outputs["SEED_EFFECT"]), + }, + } + + +def causal_start( + state: dict[str, list[dict[str, Any]]], start: dict[str, Any], net: CausalNet +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + if not exact_start(start): + raise ValueError("exact start record required") + current = _copy_state(state) + same_id = [item for item in current["starts"] if item["attempt_id"] == start["attempt_id"]] + facts = {"EXACT_START"} + if not same_id: + facts.add("FRESH_ID") + elif start in same_id: + facts.add("EXACT_START_REPLAY") + else: + facts.add("START_CONFLICT") + candidates = [ + item + for item in net.transitions + if item.symbol in {"START-FRESH", "START-REPLAY", "REJECT-START-CONFLICT"} + and set(item.requirements) <= facts + ] + require(len(candidates) == 1, f"start causal classification not singular: {facts!r}") + transition = candidates[0] + if "ADD_START" in transition.effects: + current["starts"].append(deepcopy(start)) + else: + require("PRESERVE_STATE" in transition.effects, f"{transition.symbol}: unsupported effect") + return current, _result(transition) + + +def causal_end( + state: dict[str, list[dict[str, Any]]], terminal: dict[str, Any], net: CausalNet +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + if not exact_terminal(terminal): + raise ValueError("exact terminal record required") + current = _copy_state(state) + same_terminal_id = [ + item for item in current["terminals"] if item["attempt_id"] == terminal["attempt_id"] + ] + matching_start = any( + item["attempt_id"] == terminal["attempt_id"] + and item["attempt_digest"] == terminal["attempt_digest"] + for item in current["starts"] + ) + facts = {"EXACT_TERMINAL"} + if terminal in same_terminal_id: + facts.add("EXACT_TERMINAL_REPLAY") + elif same_terminal_id: + facts.add("TERMINAL_CONFLICT") + elif matching_start: + facts.update({"EXACT_RUNNING", "FRESH_TERMINAL"}) + facts.add("KIND_RESULT" if terminal["terminal_kind"] == "RESULT" else "KIND_NO_RESULT") + else: + facts.update({"NO_TERMINAL_FOR_ID", "NOT_EXACT_RUNNING"}) + end_symbols = { + "END-RESULT", + "END-NO-RESULT", + "END-REPLAY", + "REJECT-END-CONFLICT", + "REJECT-END-NOT-RUNNING", + } + candidates = [ + item + for item in net.transitions + if item.symbol in end_symbols and set(item.requirements) <= facts + ] + require(len(candidates) == 1, f"end causal classification not singular: {facts!r}") + transition = candidates[0] + if "ADD_TERMINAL" in transition.effects: + current["terminals"].append(deepcopy(terminal)) + else: + require("PRESERVE_STATE" in transition.effects, f"{transition.symbol}: unsupported effect") + return current, _result(transition) + + +def main() -> int: + check_causal_bindings() + print("ALPHA4_RUNTIME_CAUSAL_COMPONENTS=8/8 PASS") + print("ALPHA4_RUNTIME_CAUSAL_SEMANTIC_PRECEDENCE=NONE") + print("ALPHA4_RUNTIME_CAUSAL_SEED_ACTION=STUTTER") + print("ALPHA4_RUNTIME_CAUSAL_EXPRESSION=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_expression_airgap.py b/tools/alpha4_runtime_expression_airgap.py new file mode 100644 index 0000000..ba2085c --- /dev/null +++ b/tools/alpha4_runtime_expression_airgap.py @@ -0,0 +1,249 @@ +from __future__ import annotations + +import argparse +import itertools +import json +from copy import deepcopy +from pathlib import Path +from typing import Any + +from tools.alpha4_runtime_seed_extension import parse_seed_binding, sha256, tree_digest + +ROOT = Path(__file__).resolve().parents[1] + + +class AirgapError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise AirgapError(message) + + +def _load_expression(path: Path) -> dict[str, Any]: + namespace: dict[str, Any] = { + "__file__": str(path), + "__name__": "aset_runtime_alpha4_airgap_subject", + } + source = path.read_text(encoding="utf-8") + exec(compile(source, str(path), "exec"), namespace) + return namespace + + +def _starts() -> list[dict[str, Any]]: + return [ + { + "attempt_id": attempt_id, + "attempt_digest": attempt_digest, + "runtime_binding": "runtime:0", + "descriptor_binding": "descriptor:0", + } + for attempt_id in ("a0", "a1") + for attempt_digest in ("d0", "d1") + ] + + +def _terminals() -> list[dict[str, Any]]: + return [ + { + "attempt_id": attempt_id, + "attempt_digest": attempt_digest, + "terminal_kind": terminal_kind, + "terminal_digest": terminal_digest, + "terminal_binding": "terminal-binding:0", + "evidence_bindings": ["e0"], + } + for attempt_id in ("a0", "a1") + for attempt_digest in ("d0", "d1") + for terminal_kind in ("RESULT", "NO_RESULT") + for terminal_digest in ("t0", "t1") + ] + + +def _states() -> list[dict[str, list[dict[str, Any]]]]: + starts = _starts() + terminals = _terminals() + starts_by_id = { + attempt_id: [item for item in starts if item["attempt_id"] == attempt_id] + for attempt_id in ("a0", "a1") + } + states: list[dict[str, list[dict[str, Any]]]] = [] + start_choices = [[None, *starts_by_id[attempt_id]] for attempt_id in ("a0", "a1")] + for selected in itertools.product(*start_choices): + selected_starts = [deepcopy(item) for item in selected if item is not None] + if not selected_starts: + states.append({"starts": [], "terminals": []}) + continue + terminal_choices: list[list[dict[str, Any] | None]] = [] + for start in selected_starts: + matching = [ + item + for item in terminals + if item["attempt_id"] == start["attempt_id"] + and item["attempt_digest"] == start["attempt_digest"] + ] + terminal_choices.append([None, *matching]) + for chosen_terminals in itertools.product(*terminal_choices): + states.append( + { + "starts": deepcopy(selected_starts), + "terminals": [deepcopy(item) for item in chosen_terminals if item is not None], + } + ) + return states + + +def _result(accepted: bool, code: str, changed: bool) -> dict[str, Any]: + return { + "accepted": accepted, + "code": code, + "state_changed": changed, + "seed_projection": {"action": "STUTTER", "effect_permitted": False}, + } + + +def _expected_start( + state: dict[str, list[dict[str, Any]]], start: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + next_state = deepcopy(state) + same_id = [item for item in next_state["starts"] if item["attempt_id"] == start["attempt_id"]] + if start in same_id: + return next_state, _result(True, "IDEMPOTENT_REPLAY", False) + if same_id: + return next_state, _result(False, "ATTEMPT_IDENTITY_CONFLICT", False) + next_state["starts"].append(deepcopy(start)) + return next_state, _result(True, "ATTEMPT_STARTED", True) + + +def _expected_end( + state: dict[str, list[dict[str, Any]]], terminal: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + next_state = deepcopy(state) + same_id = [ + item for item in next_state["terminals"] if item["attempt_id"] == terminal["attempt_id"] + ] + if terminal in same_id: + return next_state, _result(True, "IDEMPOTENT_REPLAY", False) + if same_id: + return next_state, _result(False, "TERMINAL_ATTEMPT_IMMUTABLE", False) + matching = any( + item["attempt_id"] == terminal["attempt_id"] + and item["attempt_digest"] == terminal["attempt_digest"] + for item in next_state["starts"] + ) + if not matching: + return next_state, _result(False, "ATTEMPT_NOT_RUNNING", False) + next_state["terminals"].append(deepcopy(terminal)) + code = ( + "ATTEMPT_ENDED_WITH_RESULT" + if terminal["terminal_kind"] == "RESULT" + else "ATTEMPT_ENDED_WITH_NO_RESULT" + ) + return next_state, _result(True, code, True) + + +def check_expression_airgap(profiles_root: Path) -> dict[str, Any]: + profiles_root = profiles_root.resolve() + binding = parse_seed_binding() + expression = profiles_root / "python/aset_runtime_alpha4.py" + seed_base = profiles_root / "base/seed/python/aset_seed_alpha4.py" + require(expression.is_file(), "Runtime Python companion missing") + require(seed_base.is_file(), "exact Seed Python base missing") + require( + sha256(seed_base) == binding.companions["PYTHON"][1], + "Seed Python base byte identity mismatch", + ) + tree_before = tree_digest(profiles_root) + namespace = _load_expression(expression) + require(callable(namespace.get("start_attempt")), "generated Runtime start entry point missing") + require(callable(namespace.get("end_attempt")), "generated Runtime end entry point missing") + require( + len(namespace.get("COMPONENT_BINDINGS", [])) == 8, + "generated Runtime component binding surface drift", + ) + seed_states = [ + {"subject": "s0", "authority": "a0", "recognition": recognition, "evidence": ("e0",)} + for recognition in ("UNKNOWN", "ALLOW", "BLOCK") + ] + starts = _starts() + terminals = _terminals() + states = _states() + start_checks = 0 + end_checks = 0 + for seed_state in seed_states: + for state in states: + for start in starts: + expected_state, expected_result = _expected_start(state, start) + actual_state, actual_seed, actual_result = namespace["start_attempt"]( + deepcopy(state), deepcopy(start), deepcopy(seed_state) + ) + require(actual_state == expected_state, "generated Runtime start state mismatch") + require(actual_result == expected_result, "generated Runtime start result mismatch") + require(actual_seed == seed_state, "Runtime start changed exact Seed state") + start_checks += 1 + for terminal in terminals: + expected_state, expected_result = _expected_end(state, terminal) + actual_state, actual_seed, actual_result = namespace["end_attempt"]( + deepcopy(state), deepcopy(terminal), deepcopy(seed_state) + ) + require(actual_state == expected_state, "generated Runtime end state mismatch") + require(actual_result == expected_result, "generated Runtime end result mismatch") + require(actual_seed == seed_state, "Runtime end changed exact Seed state") + end_checks += 1 + require( + tree_digest(profiles_root) == tree_before, + "Runtime profile tree changed during air-gap verification", + ) + return { + "document_type": "aset-runtime-python-airgap-evidence", + "schema_version": 1, + "semantic_precedence": "NONE", + "semantic_source_runtime_dependency": "NONE", + "generator_runtime_dependency": "NONE", + "seed_base": {"sha256": sha256(seed_base), "status": "EXACT"}, + "profile_tree_digest": tree_before, + "cases": { + "start": start_checks, + "end": end_checks, + "total": start_checks + end_checks, + }, + "seed_states_checked": ["UNKNOWN", "ALLOW", "BLOCK"], + "seed_projection": "STUTTER", + "status": "PASS", + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--profiles-root", type=Path, required=True) + parser.add_argument( + "--output", + type=Path, + default=ROOT / "dist/runtime-python-airgap-evidence.json", + ) + args = parser.parse_args() + try: + evidence = check_expression_airgap(args.profiles_root) + output = args.output if args.output.is_absolute() else ROOT / args.output + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(evidence, indent=2, sort_keys=True) + "\n", encoding="utf-8") + cases = evidence["cases"] + print(f"ALPHA4_RUNTIME_PYTHON_AIRGAP_START={cases['start']}/{cases['start']} PASS") + print(f"ALPHA4_RUNTIME_PYTHON_AIRGAP_END={cases['end']}/{cases['end']} PASS") + print(f"ALPHA4_RUNTIME_PYTHON_AIRGAP_TOTAL={cases['total']}/{cases['total']} PASS") + print("ALPHA4_RUNTIME_PYTHON_SEED_BASE=EXACT") + print("ALPHA4_RUNTIME_PYTHON_SEED_PROJECTION=STUTTER") + print("ALPHA4_RUNTIME_PYTHON_SEMANTIC_SOURCE_DEPENDENCY=NONE") + print("ALPHA4_RUNTIME_PYTHON_GENERATOR_DEPENDENCY=NONE") + print("ALPHA4_RUNTIME_PYTHON_PROFILE_TREE_UNCHANGED=PASS") + print("ALPHA4_RUNTIME_PYTHON_AIRGAP=PASS") + return 0 + except (OSError, ValueError, AirgapError) as error: + print(f"ALPHA4_RUNTIME_PYTHON_AIRGAP_ERROR={error}") + print("ALPHA4_RUNTIME_PYTHON_AIRGAP=FAIL") + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_gate.py b/tools/alpha4_runtime_gate.py new file mode 100644 index 0000000..d094b37 --- /dev/null +++ b/tools/alpha4_runtime_gate.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +COMMANDS = [ + [sys.executable, "-m", "tools.validate_repository_minimal"], + [sys.executable, "-m", "tools.validate_alpha4_runtime"], + [sys.executable, "-m", "tools.alpha4_runtime_paired_expression"], + [sys.executable, "-m", "tools.alpha4_runtime_assurance"], +] + + +def main() -> int: + for command in COMMANDS: + result = subprocess.run(command, cwd=ROOT, check=False) + if result.returncode: + print("ALPHA4_RUNTIME_GATE=FAIL") + return result.returncode + print("ALPHA4_RUNTIME_GATE=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_paired_expression.py b/tools/alpha4_runtime_paired_expression.py new file mode 100644 index 0000000..74ea445 --- /dev/null +++ b/tools/alpha4_runtime_paired_expression.py @@ -0,0 +1,352 @@ +from __future__ import annotations + +import itertools +import re +from copy import deepcopy +from pathlib import Path +from typing import Any + +ROOT = Path(__file__).resolve().parents[1] +FORTH = ROOT / "runtime/alpha4/operational/components.forth" + +EXPECTED_WORDS = { + "START-FRESH": ("EXACT-START?", "FRESH-ID?", "ADD-START", "ATTEMPT-STARTED"), + "START-REPLAY": ( + "EXACT-START?", + "EXACT-START-REPLAY?", + "KEEP-STATE", + "IDEMPOTENT-REPLAY", + ), + "REJECT-START-CONFLICT": ( + "EXACT-START?", + "START-CONFLICT?", + "KEEP-STATE", + "ATTEMPT-IDENTITY-CONFLICT", + ), + "END-RESULT": ( + "EXACT-TERMINAL?", + "EXACT-RUNNING?", + "FRESH-TERMINAL?", + "KIND-RESULT?", + "ADD-TERMINAL", + "ATTEMPT-ENDED-WITH-RESULT", + ), + "END-NO-RESULT": ( + "EXACT-TERMINAL?", + "EXACT-RUNNING?", + "FRESH-TERMINAL?", + "KIND-NO-RESULT?", + "ADD-TERMINAL", + "ATTEMPT-ENDED-WITH-NO-RESULT", + ), + "END-REPLAY": ( + "EXACT-TERMINAL?", + "EXACT-TERMINAL-REPLAY?", + "KEEP-STATE", + "IDEMPOTENT-REPLAY", + ), + "REJECT-END-CONFLICT": ( + "EXACT-TERMINAL?", + "TERMINAL-CONFLICT?", + "KEEP-STATE", + "TERMINAL-ATTEMPT-IMMUTABLE", + ), + "REJECT-END-NOT-RUNNING": ( + "EXACT-TERMINAL?", + "NO-TERMINAL-FOR-ID?", + "NOT-EXACT-RUNNING?", + "KEEP-STATE", + "ATTEMPT-NOT-RUNNING", + ), +} + +START_FIELDS = {"attempt_id", "attempt_digest", "runtime_binding", "descriptor_binding"} +TERMINAL_FIELDS = { + "attempt_id", + "attempt_digest", + "terminal_kind", + "terminal_digest", + "terminal_binding", + "evidence_bindings", +} +TERMINAL_KINDS = {"RESULT", "NO_RESULT"} + + +def parse_operational_words() -> dict[str, tuple[str, ...]]: + text = FORTH.read_text(encoding="utf-8") + pattern = re.compile(r":\s+(?P[A-Z0-9-]+)\s+\([^)]*--[^)]*\)\s+(?P.*?)\s*;") + words = { + match.group("word"): tuple(match.group("body").split()) for match in pattern.finditer(text) + } + if words != EXPECTED_WORDS: + raise RuntimeError(f"restricted operational vocabulary mismatch: {words!r}") + return words + + +def exact_start(value: dict[str, Any]) -> bool: + return set(value) == START_FIELDS and all( + isinstance(value[field], str) and value[field] for field in START_FIELDS + ) + + +def exact_terminal(value: dict[str, Any]) -> bool: + if set(value) != TERMINAL_FIELDS: + return False + if value["terminal_kind"] not in TERMINAL_KINDS: + return False + for field in TERMINAL_FIELDS - {"terminal_kind", "evidence_bindings"}: + if not isinstance(value[field], str) or not value[field]: + return False + evidence = value["evidence_bindings"] + return isinstance(evidence, list) and all(isinstance(item, str) and item for item in evidence) + + +def _result(accepted: bool, code: str, changed: bool) -> dict[str, Any]: + return { + "accepted": accepted, + "code": code, + "state_changed": changed, + "seed_projection": {"action": "STUTTER", "effect_permitted": False}, + } + + +def _copy_state(state: dict[str, list[dict[str, Any]]]) -> dict[str, list[dict[str, Any]]]: + return {"starts": deepcopy(state["starts"]), "terminals": deepcopy(state["terminals"])} + + +def _matching_start(state: dict[str, Any], terminal: dict[str, Any]) -> bool: + return any( + item["attempt_id"] == terminal["attempt_id"] + and item["attempt_digest"] == terminal["attempt_digest"] + for item in state["starts"] + ) + + +def operational_start( + state: dict[str, list[dict[str, Any]]], start: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + parse_operational_words() + if not exact_start(start): + raise ValueError("exact start record required") + current = _copy_state(state) + same_id = [item for item in current["starts"] if item["attempt_id"] == start["attempt_id"]] + if not same_id: + current["starts"].append(deepcopy(start)) + return current, _result(True, "ATTEMPT_STARTED", True) + if start in same_id: + return current, _result(True, "IDEMPOTENT_REPLAY", False) + return current, _result(False, "ATTEMPT_IDENTITY_CONFLICT", False) + + +def relational_start( + state: dict[str, list[dict[str, Any]]], start: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + if not exact_start(start): + raise ValueError("exact start record required") + current = _copy_state(state) + identical = start in current["starts"] + identifier_exists = any(item["attempt_id"] == start["attempt_id"] for item in current["starts"]) + if identical: + return current, _result(True, "IDEMPOTENT_REPLAY", False) + if identifier_exists: + return current, _result(False, "ATTEMPT_IDENTITY_CONFLICT", False) + current["starts"].append(deepcopy(start)) + return current, _result(True, "ATTEMPT_STARTED", True) + + +def operational_end( + state: dict[str, list[dict[str, Any]]], terminal: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + parse_operational_words() + if not exact_terminal(terminal): + raise ValueError("exact terminal record required") + current = _copy_state(state) + same_terminal_id = [ + item for item in current["terminals"] if item["attempt_id"] == terminal["attempt_id"] + ] + if terminal in same_terminal_id: + return current, _result(True, "IDEMPOTENT_REPLAY", False) + if same_terminal_id: + return current, _result(False, "TERMINAL_ATTEMPT_IMMUTABLE", False) + if not _matching_start(current, terminal): + return current, _result(False, "ATTEMPT_NOT_RUNNING", False) + current["terminals"].append(deepcopy(terminal)) + if terminal["terminal_kind"] == "RESULT": + return current, _result(True, "ATTEMPT_ENDED_WITH_RESULT", True) + return current, _result(True, "ATTEMPT_ENDED_WITH_NO_RESULT", True) + + +def relational_end( + state: dict[str, list[dict[str, Any]]], terminal: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any]]: + if not exact_terminal(terminal): + raise ValueError("exact terminal record required") + current = _copy_state(state) + identical = terminal in current["terminals"] + identifier_exists = any( + item["attempt_id"] == terminal["attempt_id"] for item in current["terminals"] + ) + if identical: + return current, _result(True, "IDEMPOTENT_REPLAY", False) + if identifier_exists: + return current, _result(False, "TERMINAL_ATTEMPT_IMMUTABLE", False) + matching = _matching_start(current, terminal) + if not matching: + return current, _result(False, "ATTEMPT_NOT_RUNNING", False) + current["terminals"].append(deepcopy(terminal)) + code = ( + "ATTEMPT_ENDED_WITH_RESULT" + if terminal["terminal_kind"] == "RESULT" + else "ATTEMPT_ENDED_WITH_NO_RESULT" + ) + return current, _result(True, code, True) + + +def bounded_domain() -> tuple[ + list[dict[str, Any]], + list[dict[str, Any]], + list[dict[str, list[dict[str, Any]]]], +]: + starts = [ + { + "attempt_id": attempt_id, + "attempt_digest": attempt_digest, + "runtime_binding": "runtime:0", + "descriptor_binding": "descriptor:0", + } + for attempt_id, attempt_digest in itertools.product(("a0", "a1"), ("d0", "d1")) + ] + terminals = [ + { + "attempt_id": attempt_id, + "attempt_digest": attempt_digest, + "terminal_kind": terminal_kind, + "terminal_digest": terminal_digest, + "terminal_binding": "terminal-binding:0", + "evidence_bindings": ["e0"], + } + for attempt_id, attempt_digest, terminal_kind, terminal_digest in itertools.product( + ("a0", "a1"), ("d0", "d1"), ("RESULT", "NO_RESULT"), ("t0", "t1") + ) + ] + starts_by_id = { + attempt_id: [item for item in starts if item["attempt_id"] == attempt_id] + for attempt_id in ("a0", "a1") + } + states: list[dict[str, list[dict[str, Any]]]] = [] + start_choices = [[None, *starts_by_id[attempt_id]] for attempt_id in ("a0", "a1")] + for selected in itertools.product(*start_choices): + selected_starts = [deepcopy(item) for item in selected if item is not None] + if not selected_starts: + states.append({"starts": [], "terminals": []}) + continue + terminal_choices: list[list[dict[str, Any] | None]] = [] + for start in selected_starts: + matching = [ + item + for item in terminals + if item["attempt_id"] == start["attempt_id"] + and item["attempt_digest"] == start["attempt_digest"] + ] + terminal_choices.append([None, *matching]) + for chosen_terminals in itertools.product(*terminal_choices): + states.append( + { + "starts": deepcopy(selected_starts), + "terminals": [deepcopy(item) for item in chosen_terminals if item is not None], + } + ) + return starts, terminals, states + + +def bounded_pairing_check() -> dict[str, int]: + starts, terminals, states = bounded_domain() + start_checks = 0 + end_checks = 0 + for state in states: + for start in starts: + op_state, op_result = operational_start(state, start) + rel_state, rel_result = relational_start(state, start) + if op_state != rel_state or op_result != rel_result: + raise RuntimeError(f"start pairing mismatch: state={state!r} start={start!r}") + start_checks += 1 + for terminal in terminals: + op_state, op_result = operational_end(state, terminal) + rel_state, rel_result = relational_end(state, terminal) + if op_state != rel_state or op_result != rel_result: + raise RuntimeError(f"end pairing mismatch: state={state!r} terminal={terminal!r}") + end_checks += 1 + return {"start": start_checks, "end": end_checks, "total": start_checks + end_checks} + + +def runtime_invariant(state: dict[str, list[dict[str, Any]]]) -> bool: + starts = state.get("starts") + terminals = state.get("terminals") + if not isinstance(starts, list) or not isinstance(terminals, list): + return False + if not all(exact_start(item) for item in starts): + return False + if not all(exact_terminal(item) for item in terminals): + return False + start_ids = [item["attempt_id"] for item in starts] + terminal_ids = [item["attempt_id"] for item in terminals] + if len(start_ids) != len(set(start_ids)): + return False + if len(terminal_ids) != len(set(terminal_ids)): + return False + return all(_matching_start(state, terminal) for terminal in terminals) + + +def _append_only(before: list[dict[str, Any]], after: list[dict[str, Any]]) -> bool: + return all(item in after for item in before) + + +def bounded_safety_check() -> dict[str, int]: + starts, terminals, states = bounded_domain() + start_checks = 0 + end_checks = 0 + for state in states: + if not runtime_invariant(state): + raise RuntimeError(f"bounded source state violates Runtime invariant: {state!r}") + for start in starts: + next_state, _ = relational_start(state, start) + if not runtime_invariant(next_state): + raise RuntimeError( + f"start transition violates Runtime invariant: state={state!r} start={start!r}" + ) + if not _append_only(state["starts"], next_state["starts"]): + raise RuntimeError("start transition violated starts append-only boundary") + if not _append_only(state["terminals"], next_state["terminals"]): + raise RuntimeError("start transition violated terminals append-only boundary") + start_checks += 1 + for terminal in terminals: + next_state, _ = relational_end(state, terminal) + if not runtime_invariant(next_state): + raise RuntimeError( + "end transition violates Runtime invariant: " + f"state={state!r} terminal={terminal!r}" + ) + if not _append_only(state["starts"], next_state["starts"]): + raise RuntimeError("end transition violated starts append-only boundary") + if not _append_only(state["terminals"], next_state["terminals"]): + raise RuntimeError("end transition violated terminals append-only boundary") + end_checks += 1 + return {"start": start_checks, "end": end_checks, "total": start_checks + end_checks} + + +def main() -> int: + parse_operational_words() + counts = bounded_pairing_check() + safety = bounded_safety_check() + print("ALPHA4_RUNTIME_OPERATIONAL_WORDS=8/8 PASS") + print(f"ALPHA4_RUNTIME_START_PAIRED_CASES={counts['start']}/{counts['start']} PASS") + print(f"ALPHA4_RUNTIME_END_PAIRED_CASES={counts['end']}/{counts['end']} PASS") + print(f"ALPHA4_RUNTIME_PAIRED_CASES={counts['total']}/{counts['total']} PASS") + print(f"ALPHA4_RUNTIME_BOUNDED_SAFETY={safety['total']}/{safety['total']} PASS") + print("ALPHA4_RUNTIME_APPEND_ONLY_BOUNDARY=PASS") + print("ALPHA4_RUNTIME_PAIRED_EXPRESSION=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_public_release_audit.py b/tools/alpha4_runtime_public_release_audit.py new file mode 100644 index 0000000..05528dd --- /dev/null +++ b/tools/alpha4_runtime_public_release_audit.py @@ -0,0 +1,240 @@ +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path +from typing import Any + +ROOT = Path(__file__).resolve().parents[1] +PROJECT = "ASET Runtime" +REPRESENTATION_ID = "0.1.0-alpha.4" +SUBJECT_ID = "ASET-RUNTIME-ALPHA4" +REPOSITORY = "https://github.com/attractor-set/aset-runtime" +FINAL_THEOREM = "AssembledRuntimePreservesExactSeedBoundary" +LICENSE_SHA256 = "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30" + + +class PublicReleaseAuditError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise PublicReleaseAuditError(message) + + +def load_json(path: Path) -> dict[str, Any]: + value = json.loads(path.read_text(encoding="utf-8")) + require(isinstance(value, dict), f"expected JSON object: {path}") + return value + + +def check_public_root(root: Path = ROOT) -> dict[str, str]: + readme = (root / "README.md").read_text(encoding="utf-8") + notice = (root / "NOTICE").read_text(encoding="utf-8") + citation = (root / "CITATION.cff").read_text(encoding="utf-8") + license_bytes = (root / "LICENSE").read_bytes() + + require(readme.startswith("# ASET Runtime\n"), "README project identity mismatch") + normalized_readme = " ".join(readme.split()) + require( + "bounded execution lifecycle extension for ASET Seed 0.4alpha" in normalized_readme, + "README Runtime role mismatch", + ) + require( + "Execution may produce material. Recognition remains local to Seed." in readme, + "README recognition boundary missing", + ) + require( + "operational, relational, and causal" in readme, + "README assurance representation set missing", + ) + require("semantic precedence `NONE`" in readme, "README semantic precedence missing") + + require(notice.startswith("ASET Runtime\n"), "NOTICE project identity mismatch") + require("Copyright 2026 Dzmitry Prychyna" in notice, "NOTICE copyright holder missing") + require("publicly known as Attractor Set" in notice, "NOTICE public author identity missing") + require( + "Original author and copyright holder: Dzmitry Prychyna." in notice, + "NOTICE original authorship missing", + ) + require( + "Licensed under the Apache License, Version 2.0." in notice, + "NOTICE license declaration missing", + ) + + for expected in ( + 'title: "ASET Runtime"', + 'version: "0.1.0-alpha.4"', + 'family-names: "Prychyna"', + 'given-names: "Dzmitry"', + 'alias: "Attractor Set"', + f'repository-code: "{REPOSITORY}"', + "license: Apache-2.0", + ): + require(expected in citation, f"CITATION identity drift: {expected}") + require( + hashlib.sha256(license_bytes).hexdigest() == LICENSE_SHA256, + "Apache-2.0 LICENSE byte identity drift", + ) + + return { + "project": PROJECT, + "representation_id": REPRESENTATION_ID, + "subject_id": SUBJECT_ID, + "repository": REPOSITORY, + } + + +def check_public_release( + root: Path, + release_root: Path, + profiles_root: Path, + certificate_path: Path, +) -> dict[str, object]: + check_public_root(root) + + require( + (release_root / "NOTICE").read_bytes() == (root / "NOTICE").read_bytes(), + "release NOTICE is not exact repository NOTICE", + ) + require( + (release_root / "LICENSE").read_bytes() == (root / "LICENSE").read_bytes(), + "release LICENSE is not exact repository LICENSE", + ) + + release = load_json(release_root / "RELEASE_MANIFEST.json") + profiles = load_json(profiles_root / "RELEASE_PROFILE_MANIFEST.json") + certificate = load_json(certificate_path) + + require(release.get("subject_id") == SUBJECT_ID, "release subject identity mismatch") + require(release.get("version") == REPRESENTATION_ID, "release version mismatch") + require(release.get("semantic_precedence") == "NONE", "release semantic precedence drift") + architecture = release.get("architecture") + require(isinstance(architecture, dict), "release architecture missing") + require( + architecture.get("representations") == ["OPERATIONAL", "RELATIONAL", "CAUSAL"], + "release assurance representation set mismatch", + ) + seed_base = release.get("seed_base") + require(isinstance(seed_base, dict), "release Seed base metadata missing") + require(seed_base.get("semantic_redefinition") == "ABSENT", "release redefines Seed") + require(seed_base.get("projection") == "PRESERVE-SEED-STATE", "release Seed projection drift") + triangulated = release.get("triangulated_assurance") + require(isinstance(triangulated, dict), "release triangulated assurance missing") + require(triangulated.get("status") == "PASS", "release triangulated assurance not PASS") + require(triangulated.get("semantic_delta") == "NONE", "release assurance semantic delta drift") + + require(profiles.get("subject_id") == SUBJECT_ID, "profile subject identity mismatch") + require(profiles.get("version") == REPRESENTATION_ID, "profile version mismatch") + require(profiles.get("semantic_precedence") == "NONE", "profile semantic precedence drift") + require( + profiles.get("seed_extension") == "PRESERVE-SEED-STATE", + "profile Seed extension boundary drift", + ) + companions = profiles.get("companions") + require(isinstance(companions, dict), "profile companion set missing") + require( + companions.get("controlled_english") == "en/Runtime.md" + and companions.get("python") == "python/aset_runtime_alpha4.py", + "profile companion identity mismatch", + ) + + require(certificate.get("subject_id") == SUBJECT_ID, "certificate subject identity mismatch") + require(certificate.get("version") == REPRESENTATION_ID, "certificate version mismatch") + require(certificate.get("status") == "PASS", "release admission is not PASS") + require(certificate.get("semantic_precedence") == "NONE", "certificate precedence drift") + require(certificate.get("seed_redefinition") == "ABSENT", "certificate Seed redefinition drift") + require(certificate.get("seed_projection") == "STUTTER", "certificate Seed projection drift") + seed_bindings = certificate.get("seed_bindings") + require( + isinstance(seed_bindings, dict) + and seed_bindings == {"operational": "PASS", "relational": "PASS", "causal": "PASS"}, + "certificate Seed binding set mismatch", + ) + post_build = certificate.get("post_build_tlaps") + require(isinstance(post_build, dict), "certificate post-build TLAPS missing") + require(post_build.get("status") == "PASS", "certificate post-build TLAPS not PASS") + require(post_build.get("final_theorem") == FINAL_THEOREM, "certificate final theorem drift") + require( + isinstance(post_build.get("obligations_proved"), int) + and post_build["obligations_proved"] > 0, + "certificate post-build obligation count invalid", + ) + require(certificate.get("english_seed_base") == "EXACT", "English Seed base not exact") + require(certificate.get("python_seed_base") == "EXACT", "Python Seed base not exact") + python_airgap = certificate.get("python_airgap") + require( + isinstance(python_airgap, dict) + and python_airgap.get("status") == "PASS" + and isinstance(python_airgap.get("cases"), int) + and python_airgap["cases"] > 0, + "Python air-gap public evidence invalid", + ) + require(certificate.get("archive_binding") == "EXACT", "archive binding is not exact") + + return { + "document_type": "aset-runtime-public-release-audit", + "schema_version": 1, + "project": PROJECT, + "representation_id": REPRESENTATION_ID, + "subject_id": SUBJECT_ID, + "repository": REPOSITORY, + "assurance_representations": ["OPERATIONAL", "RELATIONAL", "CAUSAL"], + "semantic_precedence": "NONE", + "seed_redefinition": "ABSENT", + "seed_projection": "STUTTER", + "post_build_formal_assurance": "PASS", + "release_admission": "PASS", + "status": "PASS", + } + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser() + parser.add_argument( + "--release-root", + type=Path, + default=ROOT / "dist/ASET-Runtime-0.1.0-alpha.4", + ) + parser.add_argument( + "--profiles-root", + type=Path, + default=ROOT / "dist/ASET-Runtime-0.1.0-alpha.4-profiles", + ) + parser.add_argument( + "--certificate", + type=Path, + default=ROOT / "dist/runtime-release-admission-certificate.json", + ) + parser.add_argument( + "--output", + type=Path, + default=ROOT / "dist/runtime-public-release-audit.json", + ) + args = parser.parse_args(argv) + + try: + evidence = check_public_release( + ROOT, args.release_root, args.profiles_root, args.certificate + ) + output = args.output if args.output.is_absolute() else ROOT / args.output + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(evidence, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("ALPHA4_RUNTIME_PUBLIC_IDENTITY=ASET_RUNTIME") + print("ALPHA4_RUNTIME_PUBLIC_REPRESENTATION=0.1.0-alpha.4") + print("ALPHA4_RUNTIME_PUBLIC_ASSURANCE_REPRESENTATIONS=OPERATIONAL,RELATIONAL,CAUSAL") + print("ALPHA4_RUNTIME_PUBLIC_SEED_REDEFINITION=ABSENT") + print("ALPHA4_RUNTIME_PUBLIC_SEED_PROJECTION=STUTTER") + print("ALPHA4_RUNTIME_PUBLIC_POST_BUILD_FORMAL_ASSURANCE=PASS") + print("ALPHA4_RUNTIME_PUBLIC_RELEASE_AUDIT=PASS") + return 0 + except (OSError, ValueError, json.JSONDecodeError, PublicReleaseAuditError) as error: + print(f"ALPHA4_RUNTIME_PUBLIC_RELEASE_AUDIT_ERROR={error}") + print("ALPHA4_RUNTIME_PUBLIC_RELEASE_AUDIT=FAIL") + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_release_admission.py b/tools/alpha4_runtime_release_admission.py new file mode 100644 index 0000000..1a96ed4 --- /dev/null +++ b/tools/alpha4_runtime_release_admission.py @@ -0,0 +1,226 @@ +from __future__ import annotations + +import argparse +import json +import tempfile +import zipfile +from pathlib import Path +from typing import Any + +from tools.alpha4_runtime_release_profiles import manifest_records, parse_english +from tools.alpha4_runtime_seed_extension import ( + check_seed_companion_bases, + check_seed_extension, + parse_seed_binding, + sha256, + tree_digest, +) + +ROOT = Path(__file__).resolve().parents[1] + + +class AdmissionError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise AdmissionError(message) + + +def archive_tree_digest(archive: Path) -> str: + with tempfile.TemporaryDirectory(prefix="aset-runtime-archive-") as temp_dir: + root = Path(temp_dir) + with zipfile.ZipFile(archive) as value: + value.extractall(root) + children = [path for path in root.iterdir() if path.is_dir()] + require(len(children) == 1, f"archive root surface drift: {archive.name}") + return tree_digest(children[0]) + + +def load_json(path: Path, document_type: str) -> dict[str, Any]: + require(path.is_file(), f"required evidence missing: {path.name}") + value = json.loads(path.read_text(encoding="utf-8")) + require(value.get("document_type") == document_type, f"unexpected evidence type: {path.name}") + require(value.get("status") == "PASS", f"evidence not PASS: {path.name}") + return value + + +def check_release_admission( + *, + seed_root: Path, + seed_release_root: Path, + seed_profiles_root: Path, + release_root: Path, + profiles_root: Path, + release_archive: Path, + profiles_archive: Path, + tlaps_evidence_path: Path, + airgap_evidence_path: Path, +) -> dict[str, Any]: + binding = parse_seed_binding() + extension = check_seed_extension(seed_root) + companions = check_seed_companion_bases(seed_profiles_root) + require(extension["status"] == "PASS", "Runtime Seed extension assurance failed") + require(companions["status"] == "PASS", "Runtime Seed companion base assurance failed") + require( + tree_digest(seed_release_root) == binding.release_tree, + "exact Seed release tree mismatch", + ) + + release_manifest = json.loads( + (release_root / "RELEASE_MANIFEST.json").read_text(encoding="utf-8") + ) + profile_manifest = json.loads( + (profiles_root / "RELEASE_PROFILE_MANIFEST.json").read_text(encoding="utf-8") + ) + require( + release_manifest.get("document_type") == "aset-runtime-alpha4-release-materialization", + "Runtime release manifest drift", + ) + require( + profile_manifest.get("document_type") + == "aset-runtime-alpha4-release-companion-materialization", + "Runtime profile manifest drift", + ) + release_tree = tree_digest(release_root) + profile_tree = tree_digest(profiles_root) + + tlaps = load_json(tlaps_evidence_path, "aset-runtime-release-assembled-tlaps-evidence") + airgap = load_json(airgap_evidence_path, "aset-runtime-python-airgap-evidence") + require( + tlaps["release_binding"]["tree_digest"] == release_tree, + "post-build TLAPS not bound to exact Runtime release tree", + ) + require( + tlaps["seed_binding"]["release_tree_digest"] == binding.release_tree, + "post-build TLAPS not bound to exact Seed release tree", + ) + require( + airgap["profile_tree_digest"] == profile_tree, + "Python air-gap not bound to exact Runtime profile tree", + ) + require(airgap["seed_base"]["status"] == "EXACT", "Python air-gap Seed base not exact") + require(airgap["seed_projection"] == "STUTTER", "Python air-gap Seed projection drift") + + seed_english = profiles_root / "base/seed/en/Seed.md" + seed_python = profiles_root / "base/seed/python/aset_seed_alpha4.py" + require( + sha256(seed_english) == binding.companions["ENGLISH"][1], + "Runtime English Seed base drift", + ) + require( + sha256(seed_python) == binding.companions["PYTHON"][1], + "Runtime Python Seed base drift", + ) + require( + parse_english(profiles_root / "en/Runtime.md") == manifest_records(ROOT), + "Runtime English companion projection drift", + ) + + require( + archive_tree_digest(release_archive) == release_tree, + "Runtime release archive binding mismatch", + ) + require( + archive_tree_digest(profiles_archive) == profile_tree, + "Runtime profile archive binding mismatch", + ) + + return { + "document_type": "aset-runtime-release-admission-certificate", + "schema_version": 1, + "subject_id": "ASET-RUNTIME-ALPHA4", + "version": "0.1.0-alpha.4", + "semantic_precedence": "NONE", + "assurance_representations": ["OPERATIONAL", "RELATIONAL", "CAUSAL"], + "seed_bindings": {"operational": "PASS", "relational": "PASS", "causal": "PASS"}, + "seed_redefinition": "ABSENT", + "seed_projection": "STUTTER", + "post_build_tlaps": { + "status": "PASS", + "final_theorem": tlaps["proof"]["final_theorem"], + "obligations_proved": tlaps["proof"]["obligations_proved"], + }, + "english_seed_base": "EXACT", + "python_seed_base": "EXACT", + "python_airgap": { + "status": "PASS", + "cases": airgap["cases"]["total"], + }, + "release": { + "tree_digest": release_tree, + "archive_sha256": sha256(release_archive), + }, + "profiles": { + "tree_digest": profile_tree, + "archive_sha256": sha256(profiles_archive), + }, + "archive_binding": "EXACT", + "status": "PASS", + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--seed-root", type=Path, required=True) + parser.add_argument("--seed-release-root", type=Path, required=True) + parser.add_argument("--seed-profiles-root", type=Path, required=True) + parser.add_argument("--release-root", type=Path, required=True) + parser.add_argument("--profiles-root", type=Path, required=True) + parser.add_argument("--release-archive", type=Path, required=True) + parser.add_argument("--profiles-archive", type=Path, required=True) + parser.add_argument( + "--tlaps-evidence", + type=Path, + default=ROOT / "dist/runtime-release-assembled-tlaps-evidence.json", + ) + parser.add_argument( + "--airgap-evidence", + type=Path, + default=ROOT / "dist/runtime-python-airgap-evidence.json", + ) + parser.add_argument( + "--output", + type=Path, + default=ROOT / "dist/runtime-release-admission-certificate.json", + ) + args = parser.parse_args() + try: + certificate = check_release_admission( + seed_root=args.seed_root, + seed_release_root=args.seed_release_root, + seed_profiles_root=args.seed_profiles_root, + release_root=args.release_root, + profiles_root=args.profiles_root, + release_archive=args.release_archive, + profiles_archive=args.profiles_archive, + tlaps_evidence_path=args.tlaps_evidence, + airgap_evidence_path=args.airgap_evidence, + ) + output = args.output if args.output.is_absolute() else ROOT / args.output + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text( + json.dumps(certificate, indent=2, sort_keys=True) + "\n", encoding="utf-8" + ) + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_SEED_BINDINGS=3/3 PASS") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_SEED_REDEFINITION=ABSENT") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_SEED_PROJECTION=STUTTER") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_POST_BUILD_TLAPS=PASS") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_ENGLISH_SEED_BASE=EXACT") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_PYTHON_SEED_BASE=EXACT") + cases = certificate["python_airgap"]["cases"] + print(f"ALPHA4_RUNTIME_RELEASE_ADMISSION_PYTHON_AIRGAP={cases}/{cases} PASS") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_ARCHIVE_BINDING=EXACT") + print("ALPHA4_RUNTIME_PUBLIC_ASSURANCE_REPRESENTATIONS=OPERATIONAL,RELATIONAL,CAUSAL") + print("ALPHA4_RUNTIME_PUBLIC_POST_BUILD_FORMAL_ASSURANCE=PASS") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_CERTIFICATE=PASS") + return 0 + except (OSError, ValueError, json.JSONDecodeError, zipfile.BadZipFile, AdmissionError) as error: + print(f"ALPHA4_RUNTIME_RELEASE_ADMISSION_ERROR={error}") + print("ALPHA4_RUNTIME_RELEASE_ADMISSION_CERTIFICATE=FAIL") + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_release_gate.py b/tools/alpha4_runtime_release_gate.py new file mode 100644 index 0000000..e151e6c --- /dev/null +++ b/tools/alpha4_runtime_release_gate.py @@ -0,0 +1,133 @@ +from __future__ import annotations + +import argparse +import shutil +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +RELEASE_NAME = "ASET-Runtime-0.1.0-alpha.4" + + +def run(command: list[str]) -> int: + result = subprocess.run(command, cwd=ROOT, check=False) + return result.returncode + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--seed-root", type=Path, required=True) + parser.add_argument("--seed-release-root", type=Path, required=True) + parser.add_argument("--seed-profiles-root", type=Path, required=True) + parser.add_argument("--tlapm", required=True) + args = parser.parse_args() + python = sys.executable + + stages = [ + [python, "-m", "tools.alpha4_runtime_gate"], + [ + python, + "-m", + "tools.alpha4_runtime_seed_extension", + "--seed-root", + str(args.seed_root), + "--seed-profiles-root", + str(args.seed_profiles_root), + ], + [python, "-m", "tools.run_alpha4_runtime_tlaps", "--tlapm", args.tlapm], + [python, "-m", "pytest", "-q"], + ] + ruff = shutil.which("ruff") + if ruff is not None: + stages += [[ruff, "format", "--check", "."], [ruff, "check", "."]] + for command in stages: + if run(command): + print("ALPHA4_RUNTIME_RELEASE_GATE=FAIL") + return 1 + + build = [ + python, + "-m", + "tools.build_alpha4_runtime_release", + "--seed-profiles-root", + str(args.seed_profiles_root), + "--verify-determinism", + ] + if run(build): + print("ALPHA4_RUNTIME_RELEASE_GATE=FAIL") + return 1 + + release_root = ROOT / "dist" / RELEASE_NAME + profiles_root = ROOT / "dist" / f"{RELEASE_NAME}-profiles" + release_archive = ROOT / "dist" / f"{RELEASE_NAME}.zip" + profiles_archive = ROOT / "dist" / f"{RELEASE_NAME}-profiles.zip" + + post_build = [ + python, + "-m", + "tools.run_alpha4_runtime_release_tlaps", + "--release-root", + str(release_root), + "--seed-release-root", + str(args.seed_release_root), + "--tlapm", + args.tlapm, + ] + if run(post_build): + print("ALPHA4_RUNTIME_RELEASE_GATE=FAIL") + return 1 + + airgap = [ + python, + "-m", + "tools.alpha4_runtime_expression_airgap", + "--profiles-root", + str(profiles_root), + ] + if run(airgap): + print("ALPHA4_RUNTIME_RELEASE_GATE=FAIL") + return 1 + + admission = [ + python, + "-m", + "tools.alpha4_runtime_release_admission", + "--seed-root", + str(args.seed_root), + "--seed-release-root", + str(args.seed_release_root), + "--seed-profiles-root", + str(args.seed_profiles_root), + "--release-root", + str(release_root), + "--profiles-root", + str(profiles_root), + "--release-archive", + str(release_archive), + "--profiles-archive", + str(profiles_archive), + ] + if run(admission): + print("ALPHA4_RUNTIME_RELEASE_GATE=FAIL") + return 1 + + public_audit = [ + python, + "-m", + "tools.alpha4_runtime_public_release_audit", + "--release-root", + str(release_root), + "--profiles-root", + str(profiles_root), + ] + if run(public_audit): + print("ALPHA4_RUNTIME_RELEASE_GATE=FAIL") + return 1 + + print("ALPHA4_RUNTIME_RELEASE_GATE=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_release_profiles.py b/tools/alpha4_runtime_release_profiles.py new file mode 100644 index 0000000..8bf324b --- /dev/null +++ b/tools/alpha4_runtime_release_profiles.py @@ -0,0 +1,319 @@ +from __future__ import annotations + +import json +import shutil +from pathlib import Path + +from tools.alpha4_runtime_seed_extension import ( + check_seed_companion_bases, + parse_seed_binding, + sha256, +) + +ROOT = Path(__file__).resolve().parents[1] +MANIFEST = ROOT / "runtime/alpha4/RUNTIME.aset" + + +class ReleaseProfileError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise ReleaseProfileError(message) + + +def _lines(path: Path) -> list[str]: + return [line.strip() for line in path.read_text(encoding="utf-8").splitlines() if line.strip()] + + +def manifest_records(root: Path = ROOT) -> list[dict[str, str]]: + lines = _lines(root / "runtime/alpha4/RUNTIME.aset") + causal: dict[str, str] = {} + for line in lines: + if line.startswith("CAUSAL-BIND "): + _, component_id, causal_transition = line.split() + causal[component_id] = causal_transition + operational_map = { + "ASET-RUNTIME-COMPONENT-START-FRESH": "START-FRESH", + "ASET-RUNTIME-COMPONENT-START-REPLAY": "START-REPLAY", + "ASET-RUNTIME-COMPONENT-REJECT-START-CONFLICT": "REJECT-START-CONFLICT", + "ASET-RUNTIME-COMPONENT-END-RESULT": "END-RESULT", + "ASET-RUNTIME-COMPONENT-END-NO-RESULT": "END-NO-RESULT", + "ASET-RUNTIME-COMPONENT-END-REPLAY": "END-REPLAY", + "ASET-RUNTIME-COMPONENT-REJECT-END-CONFLICT": "REJECT-END-CONFLICT", + "ASET-RUNTIME-COMPONENT-REJECT-END-NOT-RUNNING": "REJECT-END-NOT-RUNNING", + } + records: list[dict[str, str]] = [] + for line in lines: + if not line.startswith("PAIR "): + continue + parts = line.split() + require(len(parts) == 6, f"bad PAIR declaration: {line}") + _, component_id, transition_binding, relational, _reflection, pairing = parts + require(component_id in causal, f"causal binding missing for {component_id}") + records.append( + { + "component_id": component_id, + "transition_binding": transition_binding, + "operational": operational_map[component_id], + "relational": relational, + "causal": causal[component_id], + "pairing": pairing, + "seed_extension": "PRESERVE-SEED-STATE", + } + ) + require(len(records) == 8, "Runtime release companion requires eight component records") + return records + + +def write_english(target: Path, seed_english_sha256: str, records: list[dict[str, str]]) -> None: + lines = [ + "# ASET Runtime 0.1.0-alpha.4 — generated release companion extension", + "", + "Generated by release CI. Semantic precedence: none.", + f"Exact Seed English base SHA-256: `{seed_english_sha256}`", + "", + "This document adds only Runtime-owned lifecycle expression content; " + "the Seed companion remains the exact base expression.", + "Every Runtime-only transition preserves the Seed state.", + "", + ] + for item in records: + lines += [ + f"### {item['component_id']}", + f"Transition: `{item['transition_binding']}`", + f"Operational: `{item['operational']}`", + f"Relational: `{item['relational']}`", + f"Causal: `{item['causal']}`", + f"Pairing: `{item['pairing']}`", + f"Seed extension: `{item['seed_extension']}`", + "", + ] + target.write_text("\n".join(lines), encoding="utf-8") + + +def parse_english(path: Path) -> list[dict[str, str]]: + text = path.read_text(encoding="utf-8") + records: list[dict[str, str]] = [] + for section in text.split("\n### ")[1:]: + lines = [line.strip() for line in section.splitlines() if line.strip()] + component_id = lines[0] + fields: dict[str, str] = {} + for line in lines[1:]: + if ": `" in line and line.endswith("`"): + key, value = line.split(": `", 1) + fields[key] = value[:-1] + records.append( + { + "component_id": component_id, + "transition_binding": fields["Transition"], + "operational": fields["Operational"], + "relational": fields["Relational"], + "causal": fields["Causal"], + "pairing": fields["Pairing"], + "seed_extension": fields["Seed extension"], + } + ) + return records + + +def write_python(target: Path, seed_python_sha256: str, records: list[dict[str, str]]) -> None: + metadata = json.dumps(records, indent=2, sort_keys=True) + text = f'''"""Generated ASET Runtime 0.1.0-alpha.4 Python companion extension. + +The exact ASET Seed Python companion is the base expression. Semantic precedence: none. +""" + +from __future__ import annotations + +import hashlib +from copy import deepcopy +from pathlib import Path +BASE_SEED_EXPRESSION_SHA256 = {seed_python_sha256!r} +BASE_SEED_EXPRESSION_PATH = ( + Path(__file__).resolve().parents[1] + / "base" + / "seed" + / "python" + / "aset_seed_alpha4.py" +) +COMPONENT_BINDINGS = {metadata} +START_FIELDS = {{"attempt_id", "attempt_digest", "runtime_binding", "descriptor_binding"}} +TERMINAL_FIELDS = {{ + "attempt_id", + "attempt_digest", + "terminal_kind", + "terminal_digest", + "terminal_binding", + "evidence_bindings", +}} +TERMINAL_KINDS = {{"RESULT", "NO_RESULT"}} + + +def _sha256(path: Path) -> str: + return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest() + + +def _load_seed_base() -> dict[str, Any]: + if _sha256(BASE_SEED_EXPRESSION_PATH) != BASE_SEED_EXPRESSION_SHA256: + raise RuntimeError("exact Seed Python companion byte identity mismatch") + namespace: dict[str, Any] = {{}} + source = BASE_SEED_EXPRESSION_PATH.read_text(encoding="utf-8") + exec(compile(source, str(BASE_SEED_EXPRESSION_PATH), "exec"), namespace) + if not callable(namespace.get("state")) or not callable(namespace.get("apply_component")): + raise RuntimeError("exact Seed Python companion entry points missing") + return namespace + + +_seed = _load_seed_base() + + +def state( + starts: list[dict[str, Any]] | None = None, + terminals: list[dict[str, Any]] | None = None, +) -> dict[str, list[dict[str, Any]]]: + return {{ + "starts": deepcopy(starts or []), + "terminals": deepcopy(terminals or []), + }} + + +def _exact_start(value: dict[str, Any]) -> bool: + return set(value) == START_FIELDS and all( + isinstance(value[field], str) and value[field] for field in START_FIELDS + ) + + +def _exact_terminal(value: dict[str, Any]) -> bool: + if set(value) != TERMINAL_FIELDS or value["terminal_kind"] not in TERMINAL_KINDS: + return False + for field in TERMINAL_FIELDS - {{"terminal_kind", "evidence_bindings"}}: + if not isinstance(value[field], str) or not value[field]: + return False + evidence = value["evidence_bindings"] + return isinstance(evidence, list) and all(isinstance(item, str) and item for item in evidence) + + +def _runtime_result(accepted: bool, code: str, changed: bool) -> dict[str, Any]: + return {{ + "accepted": accepted, + "code": code, + "state_changed": changed, + "seed_projection": {{"action": "STUTTER", "effect_permitted": False}}, + }} + + +def start_attempt( + current: dict[str, list[dict[str, Any]]], + start: dict[str, Any], + seed_state: dict[str, Any], +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any], dict[str, Any]]: + if not _exact_start(start): + raise ValueError("exact start record required") + next_runtime = state(current["starts"], current["terminals"]) + next_seed = deepcopy(seed_state) + same_id = [item for item in next_runtime["starts"] if item["attempt_id"] == start["attempt_id"]] + if not same_id: + next_runtime["starts"].append(deepcopy(start)) + return next_runtime, next_seed, _runtime_result(True, "ATTEMPT_STARTED", True) + if start in same_id: + return next_runtime, next_seed, _runtime_result(True, "IDEMPOTENT_REPLAY", False) + return next_runtime, next_seed, _runtime_result(False, "ATTEMPT_IDENTITY_CONFLICT", False) + + +def end_attempt( + current: dict[str, list[dict[str, Any]]], + terminal: dict[str, Any], + seed_state: dict[str, Any], +) -> tuple[dict[str, list[dict[str, Any]]], dict[str, Any], dict[str, Any]]: + if not _exact_terminal(terminal): + raise ValueError("exact terminal record required") + next_runtime = state(current["starts"], current["terminals"]) + next_seed = deepcopy(seed_state) + same_id = [ + item for item in next_runtime["terminals"] if item["attempt_id"] == terminal["attempt_id"] + ] + if terminal in same_id: + return next_runtime, next_seed, _runtime_result(True, "IDEMPOTENT_REPLAY", False) + if same_id: + return next_runtime, next_seed, _runtime_result(False, "TERMINAL_ATTEMPT_IMMUTABLE", False) + matching_start = any( + item["attempt_id"] == terminal["attempt_id"] + and item["attempt_digest"] == terminal["attempt_digest"] + for item in next_runtime["starts"] + ) + if not matching_start: + return next_runtime, next_seed, _runtime_result(False, "ATTEMPT_NOT_RUNNING", False) + next_runtime["terminals"].append(deepcopy(terminal)) + code = ( + "ATTEMPT_ENDED_WITH_RESULT" + if terminal["terminal_kind"] == "RESULT" + else "ATTEMPT_ENDED_WITH_NO_RESULT" + ) + return next_runtime, next_seed, _runtime_result(True, code, True) +''' + target.write_text(text, encoding="utf-8") + + +def build_release_profiles(seed_profiles_root: Path, output: Path) -> dict[str, object]: + seed_profiles_root = seed_profiles_root.resolve() + evidence = check_seed_companion_bases(seed_profiles_root) + binding = parse_seed_binding() + records = manifest_records(ROOT) + if output.exists(): + shutil.rmtree(output) + (output / "base/seed/en").mkdir(parents=True) + (output / "base/seed/python").mkdir(parents=True) + (output / "en").mkdir(parents=True) + (output / "python").mkdir(parents=True) + seed_english_rel, seed_english_sha = binding.companions["ENGLISH"] + seed_python_rel, seed_python_sha = binding.companions["PYTHON"] + seed_english_target = output / "base/seed/en/Seed.md" + seed_python_target = output / "base/seed/python/aset_seed_alpha4.py" + shutil.copy2(seed_profiles_root / seed_english_rel, seed_english_target) + shutil.copy2(seed_profiles_root / seed_python_rel, seed_python_target) + require(sha256(seed_english_target) == seed_english_sha, "copied Seed English base drift") + require(sha256(seed_python_target) == seed_python_sha, "copied Seed Python base drift") + write_english(output / "en/Runtime.md", seed_english_sha, records) + write_python(output / "python/aset_runtime_alpha4.py", seed_python_sha, records) + manifest: dict[str, object] = { + "document_type": "aset-runtime-alpha4-release-companion-materialization", + "schema_version": 1, + "subject_id": "ASET-RUNTIME-ALPHA4", + "version": "0.1.0-alpha.4", + "semantic_precedence": "NONE", + "seed_base": { + "profile_tree_digest": evidence["profile_tree_digest"], + "english": {"path": "base/seed/en/Seed.md", "sha256": seed_english_sha}, + "python": {"path": "base/seed/python/aset_seed_alpha4.py", "sha256": seed_python_sha}, + }, + "companions": { + "controlled_english": "en/Runtime.md", + "python": "python/aset_runtime_alpha4.py", + }, + "seed_extension": "PRESERVE-SEED-STATE", + "records": records, + } + (output / "RELEASE_PROFILE_MANIFEST.json").write_text( + json.dumps(manifest, indent=2, sort_keys=True) + "\n", encoding="utf-8" + ) + return manifest + + +def main() -> int: + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--seed-profiles-root", type=Path, required=True) + parser.add_argument("--output", type=Path, required=True) + args = parser.parse_args() + build_release_profiles(args.seed_profiles_root, args.output) + print("ALPHA4_RUNTIME_RELEASE_ENGLISH_EXTENSION=PASS") + print("ALPHA4_RUNTIME_RELEASE_PYTHON_EXTENSION=EXACT_SEED_BASE") + print("ALPHA4_RUNTIME_RELEASE_PROFILES=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_seed_extension.py b/tools/alpha4_runtime_seed_extension.py new file mode 100644 index 0000000..790b55c --- /dev/null +++ b/tools/alpha4_runtime_seed_extension.py @@ -0,0 +1,253 @@ +from __future__ import annotations + +import argparse +import hashlib +import re +from dataclasses import dataclass +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +BINDING = ROOT / "upstream/ASET_SEED_ALPHA4_BINDING.aset" +RUNTIME = ROOT / "runtime/alpha4/RUNTIME.aset" + + +class SeedExtensionError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise SeedExtensionError(message) + + +def sha256(path: Path) -> str: + return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest() + + +def tree_digest(root: Path) -> str: + digest = hashlib.sha256() + for path in sorted(root.rglob("*")): + if path.is_file(): + relative = path.relative_to(root).as_posix() + digest.update(relative.encode("utf-8")) + digest.update(b"\0") + digest.update(path.read_bytes()) + digest.update(b"\0") + return "sha256:" + digest.hexdigest() + + +@dataclass(frozen=True) +class SeedBinding: + release_tag: str + release_tree: str + release_archive: str + profile_tree: str + profile_archive: str + sources: dict[str, str] + assurance_bases: dict[str, tuple[str, tuple[str, ...]]] + companions: dict[str, tuple[str, str]] + + +def _lines(path: Path) -> list[str]: + return [line.strip() for line in path.read_text(encoding="utf-8").splitlines() if line.strip()] + + +def parse_seed_binding(path: Path = BINDING) -> SeedBinding: + lines = _lines(path) + require( + lines[0] == "ASET-SEED-BINDING 1 ASET-SEED-0.4-ALPHA CONTENT-ADDRESSED", + "Seed binding header mismatch", + ) + scalar: dict[str, str] = {} + sources: dict[str, str] = {} + bases: dict[str, tuple[str, tuple[str, ...]]] = {} + companions: dict[str, tuple[str, str]] = {} + for line in lines[1:]: + parts = line.split() + if not parts: + continue + if parts[0] in { + "RELEASE-TAG", + "RELEASE-TREE", + "RELEASE-ARCHIVE", + "PROFILE-TREE", + "PROFILE-ARCHIVE", + }: + require(len(parts) == 2, f"bad binding scalar: {line}") + scalar[parts[0]] = parts[1] + elif parts[0] == "SOURCE": + require(len(parts) == 3, f"bad bound source: {line}") + sources[parts[1]] = parts[2] + elif parts[0] == "ASSURANCE-BASE": + require(len(parts) == 4, f"bad assurance base: {line}") + bases[parts[1]] = (parts[2], tuple(parts[3].split(","))) + elif parts[0] == "COMPANION": + require(len(parts) == 4, f"bad companion binding: {line}") + companions[parts[1]] = (parts[2], parts[3]) + for key in ( + "RELEASE-TAG", + "RELEASE-TREE", + "RELEASE-ARCHIVE", + "PROFILE-TREE", + "PROFILE-ARCHIVE", + ): + require(key in scalar, f"Seed binding scalar missing: {key}") + require( + set(bases) == {"OPERATIONAL", "RELATIONAL", "CAUSAL"}, + "Seed assurance base surface mismatch", + ) + require(set(companions) == {"ENGLISH", "PYTHON"}, "Seed companion surface mismatch") + return SeedBinding( + release_tag=scalar["RELEASE-TAG"], + release_tree=scalar["RELEASE-TREE"], + release_archive=scalar["RELEASE-ARCHIVE"], + profile_tree=scalar["PROFILE-TREE"], + profile_archive=scalar["PROFILE-ARCHIVE"], + sources=sources, + assurance_bases=bases, + companions=companions, + ) + + +def _transition_block(text: str, name: str) -> str: + match = re.search(rf"(?ms)^TRANSITION {re.escape(name)}\b.*?^END$", text) + require(match is not None, f"causal transition missing: {name}") + return match.group(0) + + +def check_seed_extension(seed_root: Path) -> dict[str, object]: + binding = parse_seed_binding() + seed_root = seed_root.resolve() + for relative, expected in binding.sources.items(): + path = seed_root / relative + require(path.is_file(), f"bound Seed source missing: {relative}") + require(sha256(path) == expected, f"bound Seed source digest mismatch: {relative}") + + operational_path, operational_words = binding.assurance_bases["OPERATIONAL"] + relational_path, relational_operators = binding.assurance_bases["RELATIONAL"] + causal_path, causal_transitions = binding.assurance_bases["CAUSAL"] + + seed_forth = (seed_root / operational_path).read_text(encoding="utf-8") + for word in operational_words: + require( + re.search(rf"(?m)^:\s+{re.escape(word)}\b.*?NOP\s*;\s*$", seed_forth) is not None, + f"exact Seed operational preservation boundary unavailable: {word}", + ) + + seed_relational = (seed_root / relational_path).read_text(encoding="utf-8") + for operator in relational_operators: + require( + re.search(rf"(?m)^{re.escape(operator)}\(s, t, e\)\s*==", seed_relational) is not None, + f"exact Seed relational preservation operator unavailable: {operator}", + ) + + seed_causal = (seed_root / causal_path).read_text(encoding="utf-8") + expected_places = { + "PRESERVE-UNKNOWN": ("U", "U"), + "PRESERVE-ALLOW": ("A", "A"), + "PRESERVE-BLOCK": ("B", "B"), + } + for transition in causal_transitions: + block = _transition_block(seed_causal, transition) + before, after = expected_places[transition] + require( + f"FROM {before}" in block and f"TO {after}" in block, + f"{transition}: Seed causal preservation drift", + ) + require( + "EFFECT PRESERVE_STATE" in block, + f"{transition}: Seed causal preserve effect missing", + ) + + runtime_forth = (ROOT / "runtime/alpha4/operational/components.forth").read_text( + encoding="utf-8" + ) + require( + "LOCAL-ALLOW!" not in runtime_forth and "LOCAL-BLOCK!" not in runtime_forth, + "Runtime acquired Seed recognition operation", + ) + runtime_relational = (ROOT / "runtime/alpha4/formal/RuntimeRelations.tla").read_text( + encoding="utf-8" + ) + require( + 'SeedProjectionAction(result) == "STUTTER"' in runtime_relational, + "Runtime Seed stutter projection drift", + ) + require( + "SeedProjectionEffectPermitted(result) == FALSE" in runtime_relational, + "Runtime Seed effect boundary drift", + ) + + manifest = set(_lines(RUNTIME)) + required = { + ( + "SEED-EXTENSION-BIND OPERATIONAL " + "PRESERVE-UNKNOWN,PRESERVE-ALLOW,PRESERVE-BLOCK ALL-RUNTIME-TRANSITIONS" + ), + ( + "SEED-EXTENSION-BIND RELATIONAL " + "PreserveUnknown,PreserveAllow,PreserveBlock ALL-RUNTIME-TRANSITIONS" + ), + ( + "SEED-EXTENSION-BIND CAUSAL " + "PRESERVE-UNKNOWN,PRESERVE-ALLOW,PRESERVE-BLOCK ALL-RUNTIME-TRANSITIONS" + ), + "SEED-PROJECTION ALL-RUNTIME-TRANSITIONS PRESERVE-SEED-STATE", + "SEED-RECOGNITION-OWNER SEED-ONLY", + "EFFECT-PERMITTED-BY-RUNTIME NEVER", + } + require(required <= manifest, "Runtime exact Seed extension bindings missing") + return { + "document_type": "aset-runtime-seed-extension-assurance", + "seed_release_tag": binding.release_tag, + "semantic_precedence": "NONE", + "bindings": {"operational": "PASS", "relational": "PASS", "causal": "PASS"}, + "seed_projection": "STUTTER", + "seed_redefinition": "ABSENT", + "status": "PASS", + } + + +def check_seed_companion_bases(seed_profiles_root: Path) -> dict[str, object]: + binding = parse_seed_binding() + seed_profiles_root = seed_profiles_root.resolve() + require(seed_profiles_root.is_dir(), "Seed profile tree missing") + actual_tree = tree_digest(seed_profiles_root) + require(actual_tree == binding.profile_tree, "Seed profile tree digest mismatch") + result: dict[str, object] = {"profile_tree_digest": actual_tree} + for kind, (relative, expected) in binding.companions.items(): + path = seed_profiles_root / relative + require(path.is_file(), f"Seed {kind.lower()} companion missing") + require(sha256(path) == expected, f"Seed {kind.lower()} companion byte identity mismatch") + result[kind.lower()] = {"path": relative, "sha256": expected} + result["status"] = "PASS" + return result + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--seed-root", type=Path, required=True) + parser.add_argument("--seed-profiles-root", type=Path) + args = parser.parse_args() + try: + evidence = check_seed_extension(args.seed_root) + print("ALPHA4_RUNTIME_SEED_OPERATIONAL_EXTENSION=PASS") + print("ALPHA4_RUNTIME_SEED_RELATIONAL_EXTENSION=PASS") + print("ALPHA4_RUNTIME_SEED_CAUSAL_EXTENSION=PASS") + print("ALPHA4_RUNTIME_SEED_EXTENSION_BINDINGS=3/3 PASS") + print(f"ALPHA4_RUNTIME_SEED_REDEFINITION={evidence['seed_redefinition']}") + print("ALPHA4_RUNTIME_SEED_PROJECTION=STUTTER") + if args.seed_profiles_root is not None: + check_seed_companion_bases(args.seed_profiles_root) + print("ALPHA4_RUNTIME_SEED_ENGLISH_COMPANION_BASE=EXACT") + print("ALPHA4_RUNTIME_SEED_PYTHON_COMPANION_BASE=EXACT") + print("ALPHA4_RUNTIME_SEED_EXTENSION_ASSURANCE=PASS") + return 0 + except (OSError, UnicodeError, ValueError, SeedExtensionError) as error: + print(f"ALPHA4_RUNTIME_SEED_EXTENSION_ERROR={error}") + print("ALPHA4_RUNTIME_SEED_EXTENSION_ASSURANCE=FAIL") + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/alpha4_runtime_triangulated_expression.py b/tools/alpha4_runtime_triangulated_expression.py new file mode 100644 index 0000000..0caa125 --- /dev/null +++ b/tools/alpha4_runtime_triangulated_expression.py @@ -0,0 +1,135 @@ +from __future__ import annotations + +from pathlib import Path + +from tools.alpha4_runtime_causal_expression import ( + causal_end, + causal_start, + check_causal_bindings, +) +from tools.alpha4_runtime_paired_expression import ( + bounded_domain, + operational_end, + operational_start, + relational_end, + relational_start, +) + +ROOT = Path(__file__).resolve().parents[1] +MANIFEST = ROOT / "runtime/alpha4/RUNTIME.aset" + + +def _manifest_lines() -> list[str]: + return [ + line.strip() for line in MANIFEST.read_text(encoding="utf-8").splitlines() if line.strip() + ] + + +def check_representation_source_independence() -> dict[str, str]: + lines = _manifest_lines() + if "SEMANTIC-PRECEDENCE NONE" not in lines: + raise RuntimeError("Runtime semantic precedence drift") + sources: dict[str, str] = {} + for line in lines: + tokens = line.split() + if tokens[0] in {"OPERATIONAL", "RELATIONAL", "CAUSAL-MODEL"}: + sources[tokens[0]] = tokens[1] + expected = {"OPERATIONAL", "RELATIONAL", "CAUSAL-MODEL"} + if set(sources) != expected: + raise RuntimeError(f"three-way Runtime source binding incomplete: {sources!r}") + if len(set(sources.values())) != 3: + raise RuntimeError(f"Runtime assurance representations share a source path: {sources!r}") + for source in sources.values(): + if not (ROOT / source).is_file(): + raise RuntimeError(f"bound Runtime assurance source missing: {source}") + return sources + + +def check_triangulated_assurance() -> dict[str, object]: + sources = check_representation_source_independence() + net = check_causal_bindings() + starts, terminals, states = bounded_domain() + start_checks = 0 + end_checks = 0 + for state in states: + for start in starts: + operational = operational_start(state, start) + relational = relational_start(state, start) + causal = causal_start(state, start, net) + if operational != relational: + raise RuntimeError( + f"operational/relational start mismatch: state={state!r} start={start!r}" + ) + if operational != causal: + raise RuntimeError( + f"operational/causal start mismatch: state={state!r} start={start!r}" + ) + if relational != causal: + raise RuntimeError( + f"relational/causal start mismatch: state={state!r} start={start!r}" + ) + start_checks += 1 + for terminal in terminals: + operational = operational_end(state, terminal) + relational = relational_end(state, terminal) + causal = causal_end(state, terminal, net) + if operational != relational: + raise RuntimeError( + f"operational/relational end mismatch: state={state!r} terminal={terminal!r}" + ) + if operational != causal: + raise RuntimeError( + f"operational/causal end mismatch: state={state!r} terminal={terminal!r}" + ) + if relational != causal: + raise RuntimeError( + f"relational/causal end mismatch: state={state!r} terminal={terminal!r}" + ) + end_checks += 1 + total_checks = start_checks + end_checks + return { + "document_type": "aset-runtime-three-way-assurance-evidence", + "schema_version": 1, + "representations": ("OPERATIONAL", "RELATIONAL", "CAUSAL"), + "representation_sources": sources, + "representation_source_independence": "PASS", + "pairwise_relations": { + "operational_relational": "PASS", + "operational_causal": "PASS", + "relational_causal": "PASS", + }, + "start_checks": start_checks, + "end_checks": end_checks, + "total_checks": total_checks, + "semantic_delta": "NONE", + "semantic_precedence": "NONE", + "seed_action": "STUTTER", + "status": "PASS", + } + + +def print_evidence(evidence: dict[str, object]) -> None: + start = int(evidence["start_checks"]) + end = int(evidence["end_checks"]) + total = int(evidence["total_checks"]) + print("ALPHA4_RUNTIME_ASSURANCE_REPRESENTATIONS=OPERATIONAL,RELATIONAL,CAUSAL") + print("ALPHA4_RUNTIME_ASSURANCE_SEMANTIC_PRECEDENCE=NONE") + print(f"ALPHA4_RUNTIME_OPERATIONAL_RELATIONAL_CONGRUENCE={total}/{total} PASS") + print(f"ALPHA4_RUNTIME_OPERATIONAL_CAUSAL_CONGRUENCE={total}/{total} PASS") + print(f"ALPHA4_RUNTIME_RELATIONAL_CAUSAL_CONGRUENCE={total}/{total} PASS") + print(f"ALPHA4_RUNTIME_TRIANGULATED_START={start}/{start} PASS") + print(f"ALPHA4_RUNTIME_TRIANGULATED_END={end}/{end} PASS") + print(f"ALPHA4_RUNTIME_TRIANGULATED_TOTAL={total}/{total} PASS") + print("ALPHA4_RUNTIME_REPRESENTATION_SOURCE_INDEPENDENCE=PASS") + print("ALPHA4_RUNTIME_TRIANGULATED_SEED_ACTION=STUTTER") + print("ALPHA4_RUNTIME_TRIANGULATED_EXPRESSION=PASS") + + +def main() -> int: + evidence = check_triangulated_assurance() + print_evidence(evidence) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/build_alpha4_runtime_release.py b/tools/build_alpha4_runtime_release.py new file mode 100644 index 0000000..e392bc0 --- /dev/null +++ b/tools/build_alpha4_runtime_release.py @@ -0,0 +1,194 @@ +from __future__ import annotations + +import argparse +import hashlib +import json +import shutil +import stat +import tempfile +import zipfile +from pathlib import Path + +from tools.alpha4_runtime_release_profiles import build_release_profiles +from tools.alpha4_runtime_seed_extension import parse_seed_binding, sha256, tree_digest +from tools.alpha4_runtime_triangulated_expression import check_triangulated_assurance + +ROOT = Path(__file__).resolve().parents[1] +DIST = ROOT / "dist" +RELEASE_NAME = "ASET-Runtime-0.1.0-alpha.4" +FIXED_ZIP_TIME = (1980, 1, 1, 0, 0, 0) + + +def write_assembled_runtime(target: Path) -> None: + target.write_text( + "\n".join( + [ + "------------------------- MODULE AssembledRuntime -------------------------", + "EXTENDS RuntimeRelations", + "", + "AssembledStart(s, t, start, result) == StartAttempt(s, t, start, result)", + "AssembledEnd(s, t, terminal, result) == EndAttempt(s, t, terminal, result)", + "AssembledStep(s, t, result) ==", + " \\/ \\E start \\in StartUniverse : AssembledStart(s, t, start, result)", + " \\/ \\E terminal \\in TerminalUniverse : AssembledEnd(s, t, terminal, result)", + "AssembledNext(s, t) == Next(s, t)", + "", + "=============================================================================", + "", + ] + ), + encoding="utf-8", + ) + + +def zip_tree(root: Path, output: Path, archive_root_name: str) -> None: + output.parent.mkdir(parents=True, exist_ok=True) + if output.exists(): + output.unlink() + with zipfile.ZipFile(output, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as archive: + for path in sorted(root.rglob("*")): + if not path.is_file(): + continue + relative = f"{archive_root_name}/{path.relative_to(root).as_posix()}" + info = zipfile.ZipInfo(relative, FIXED_ZIP_TIME) + info.compress_type = zipfile.ZIP_DEFLATED + info.external_attr = (stat.S_IFREG | 0o644) << 16 + archive.writestr(info, path.read_bytes()) + + +def source_digest(paths: list[str]) -> str: + digest = hashlib.sha256() + for relative in sorted(paths): + digest.update(relative.encode("utf-8")) + digest.update(b"\0") + digest.update((ROOT / relative).read_bytes()) + digest.update(b"\0") + return "sha256:" + digest.hexdigest() + + +def build_tree(output: Path) -> dict[str, object]: + if output.exists(): + shutil.rmtree(output) + for relative in ("source", "operational", "causal", "formal", "upstream"): + (output / relative).mkdir(parents=True, exist_ok=True) + shutil.copy2(ROOT / "LICENSE", output / "LICENSE") + shutil.copy2(ROOT / "NOTICE", output / "NOTICE") + shutil.copy2(ROOT / "runtime/alpha4/RUNTIME.aset", output / "source/RUNTIME.aset") + shutil.copy2( + ROOT / "runtime/alpha4/operational/components.forth", + output / "operational/components.forth", + ) + shutil.copy2( + ROOT / "runtime/alpha4/causal/components.petri", + output / "causal/components.petri", + ) + formal_sources = [ + "runtime/alpha4/formal/RuntimeRelations.tla", + "runtime/alpha4/formal/RestrictedOperationalSemantics.tla", + "runtime/alpha4/formal/OperationalRelationalPairingProofs.tla", + "runtime/alpha4/formal/SeedBoundaryProofs.tla", + ] + for relative in formal_sources: + shutil.copy2(ROOT / relative, output / "formal" / Path(relative).name) + write_assembled_runtime(output / "formal/AssembledRuntime.tla") + shutil.copy2( + ROOT / "upstream/ASET_SEED_ALPHA4_BINDING.aset", + output / "upstream/ASET_SEED_ALPHA4_BINDING.aset", + ) + assurance = check_triangulated_assurance() + (output / "TRIANGULATED_ASSURANCE.json").write_text( + json.dumps(assurance, indent=2, sort_keys=True) + "\n", encoding="utf-8" + ) + binding = parse_seed_binding() + sources = [ + "runtime/alpha4/RUNTIME.aset", + "runtime/alpha4/operational/components.forth", + "runtime/alpha4/causal/components.petri", + *formal_sources, + "upstream/ASET_SEED_ALPHA4_BINDING.aset", + ] + manifest: dict[str, object] = { + "document_type": "aset-runtime-alpha4-release-materialization", + "schema_version": 1, + "subject_id": "ASET-RUNTIME-ALPHA4", + "version": "0.1.0-alpha.4", + "semantic_precedence": "NONE", + "source_byte_identity_digest": source_digest(sources), + "seed_base": { + "release_tag": binding.release_tag, + "tree_digest": binding.release_tree, + "projection": "PRESERVE-SEED-STATE", + "semantic_redefinition": "ABSENT", + }, + "architecture": { + "operational": "operational/components.forth", + "relational": "formal/RuntimeRelations.tla", + "causal": "causal/components.petri", + "assembled_formal": "formal/AssembledRuntime.tla", + "representations": ["OPERATIONAL", "RELATIONAL", "CAUSAL"], + }, + "triangulated_assurance": assurance, + "post_build_assurance": { + "required": True, + "final_theorem": "AssembledRuntimePreservesExactSeedBoundary", + "seed_relations": ["PreserveUnknown", "PreserveAllow", "PreserveBlock"], + }, + } + (output / "RELEASE_MANIFEST.json").write_text( + json.dumps(manifest, indent=2, sort_keys=True) + "\n", encoding="utf-8" + ) + return manifest + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--seed-profiles-root", type=Path, required=True) + parser.add_argument("--verify-determinism", action="store_true") + args = parser.parse_args(argv) + + DIST.mkdir(parents=True, exist_ok=True) + release_dir = DIST / RELEASE_NAME + profiles_dir = DIST / f"{RELEASE_NAME}-profiles" + build_tree(release_dir) + release_digest = tree_digest(release_dir) + build_release_profiles(args.seed_profiles_root, profiles_dir) + profile_digest = tree_digest(profiles_dir) + + if args.verify_determinism: + with tempfile.TemporaryDirectory(prefix="aset-runtime-alpha4-") as tmp: + tmp_root = Path(tmp) + first = tmp_root / "first" + second = tmp_root / "second" + first_profiles = tmp_root / "first-profiles" + second_profiles = tmp_root / "second-profiles" + build_tree(first) + build_tree(second) + if tree_digest(first) != tree_digest(second): + print("ALPHA4_RUNTIME_RELEASE_DETERMINISM=FAIL") + return 1 + build_release_profiles(args.seed_profiles_root, first_profiles) + build_release_profiles(args.seed_profiles_root, second_profiles) + if tree_digest(first_profiles) != tree_digest(second_profiles): + print("ALPHA4_RUNTIME_RELEASE_PROFILE_DETERMINISM=FAIL") + return 1 + print("ALPHA4_RUNTIME_RELEASE_DETERMINISM=PASS") + print("ALPHA4_RUNTIME_RELEASE_PROFILE_DETERMINISM=PASS") + + archive = DIST / f"{RELEASE_NAME}.zip" + profiles_archive = DIST / f"{RELEASE_NAME}-profiles.zip" + zip_tree(release_dir, archive, RELEASE_NAME) + zip_tree(profiles_dir, profiles_archive, f"{RELEASE_NAME}-profiles") + print(f"ALPHA4_RUNTIME_RELEASE_TREE_DIGEST={release_digest}") + print(f"ALPHA4_RUNTIME_RELEASE_ARCHIVE={archive.relative_to(ROOT)}") + print(f"ALPHA4_RUNTIME_RELEASE_ARCHIVE_SHA256={sha256(archive)}") + print(f"ALPHA4_RUNTIME_RELEASE_PROFILE_TREE_DIGEST={profile_digest}") + print(f"ALPHA4_RUNTIME_RELEASE_PROFILE_ARCHIVE={profiles_archive.relative_to(ROOT)}") + print(f"ALPHA4_RUNTIME_RELEASE_PROFILE_ARCHIVE_SHA256={sha256(profiles_archive)}") + print("ALPHA4_RUNTIME_RELEASE_ENGLISH_EXTENSION=PASS") + print("ALPHA4_RUNTIME_RELEASE_PYTHON_EXTENSION=EXACT_SEED_BASE") + print("ALPHA4_RUNTIME_RELEASE_BUILD=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/build_canon_package.py b/tools/build_canon_package.py deleted file mode 100755 index 3e5517f..0000000 --- a/tools/build_canon_package.py +++ /dev/null @@ -1,63 +0,0 @@ -from __future__ import annotations -import hashlib, json -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -CANON = ROOT / 'extension/canonical' -PACKAGE = CANON / 'CANON_PACKAGE.json' - -ROLES = { - 'source/worker-model.json':'NORMATIVE_MACHINE_CANON', - 'protocol/protocol-profile.json':'NORMATIVE_PROTOCOL_PROFILE', - 'protocol/schemas/start-work.schema.json':'NORMATIVE_WIRE_SCHEMA', - 'protocol/schemas/end-work.schema.json':'NORMATIVE_WIRE_SCHEMA', - 'protocol/schemas/conformance-case.schema.json':'NORMATIVE_CONFORMANCE_SCHEMA', - 'protocol/schemas/worker-model.schema.json':'NORMATIVE_CANON_SCHEMA', - 'conformance/conformance-profile.json':'NORMATIVE_CONFORMANCE_PROFILE', -} -for p in sorted((CANON/'conformance/cases').rglob('*.json')): - ROLES[p.relative_to(CANON).as_posix()] = 'NORMATIVE_CONFORMANCE_CASE' -for rel in [ - 'formal/WorkerLifecycle.tla', - 'formal/WorkerLifecycle.cfg', - 'formal/WorkerLifecycleProofs.tla', - 'formal/WorkerCanonProjection.tla', - 'formal/WorkerCanonRefinementProofs.tla', - 'formal/WorkerSeedStuttering.tla', - 'formal/WorkerSeedStutteringProofs.tla', - 'formal/README.md', - 'assurance/canon-tla-refinement.json', - 'assurance/seed-refinement.json', - 'assurance/lifecycle-proof-candidate.json', -]: - ROLES[rel] = 'NON_NORMATIVE_ASSURANCE_ARTIFACT' -for rel in [ - 'assurance/lifecycle-proof.json', - 'assurance/canon-refinement-proof.json', - 'assurance/seed-refinement-proof.json', - 'assurance/verification-registry.json', -]: - if (CANON / rel).is_file(): - ROLES[rel] = 'NON_NORMATIVE_ASSURANCE_ARTIFACT' - - -def digest(p): - return 'sha256:' + hashlib.sha256(p.read_bytes()).hexdigest() - - -def main(): - files=[] - for rel, role in sorted(ROLES.items()): - p=CANON/rel - files.append({'path':rel,'role':role,'sha256':digest(p)}) - payload={ - 'document_type':'aset-worker-canon-package','schema_version':1, - 'canon_id':'ASET-WORKER-CANON-0.1-ALPHA2','version':'0.1.0-alpha.1','files':files - } - PACKAGE.write_text(json.dumps(payload, indent=2, sort_keys=True)+'\n') - print(f"CANON_PACKAGE_FILES={len(files)}") - print("CANON_PACKAGE_BUILD=PASS") - - -if __name__ == '__main__': - main() diff --git a/tools/build_formal_relations.py b/tools/build_formal_relations.py deleted file mode 100755 index 0833e72..0000000 --- a/tools/build_formal_relations.py +++ /dev/null @@ -1,176 +0,0 @@ -from __future__ import annotations - -import hashlib -import json -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -CANON = ROOT / "extension/canonical" -FORMAL = CANON / "formal" -ASSURANCE = CANON / "assurance" -MODEL = CANON / "source/worker-model.json" -BINDING = ROOT / "upstream/ASET_SEED_BINDING.json" - - -def sha(path: Path) -> str: - return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest() - - -def write(path: Path, payload: dict) -> None: - path.parent.mkdir(parents=True, exist_ok=True) - path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8") - - -def load_proof_evidence(name: str) -> dict | None: - path = ASSURANCE / name - if not path.is_file(): - return None - payload = json.loads(path.read_text(encoding="utf-8")) - if payload.get("status") != "MECHANICALLY_PROVED": - return None - return payload - - -def main() -> int: - binding = json.loads(BINDING.read_text(encoding="utf-8")) - canon_relation = { - "document_type": "aset-worker-canon-tla-relation", - "schema_version": 1, - "status": "PROOF_CANDIDATE_MATERIALIZED", - "normative_precedence": "MACHINE_READABLE_CANON", - "relation_type": "STANDALONE_GENERATED_PROJECTION_WITH_BEHAVIORAL_EQUIVALENCE_PROOF_CANDIDATE", - "profile": "ASET-WORKER-CANON-TLA-PROJECTION-V2", - "source_model": {"path": "extension/canonical/source/worker-model.json", "sha256": sha(MODEL)}, - "generated_projection": { - "module": "WorkerCanonProjection", - "path": "extension/canonical/formal/WorkerCanonProjection.tla", - "sha256": sha(FORMAL / "WorkerCanonProjection.tla"), - "generator": "tools/generate_canon_tla_projection.py", - "generator_sha256": sha(ROOT / "tools/generate_canon_tla_projection.py"), - }, - "target_model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": sha(FORMAL / "WorkerLifecycle.tla"), - }, - "proof_candidate": { - "module": "WorkerCanonRefinementProofs", - "path": "extension/canonical/formal/WorkerCanonRefinementProofs.tla", - "sha256": sha(FORMAL / "WorkerCanonRefinementProofs.tla"), - "final_theorems": [ - "WorkerSafetyEquivalentToCanonProjection", - "WorkerLifecycleBehaviorallyEquivalentToCanonProjection", - ], - }, - "scope": "MINIMIZED_PRODUCTIVE_ATTEMPT_LIFECYCLE_SAFETY_PROJECTION", - "excluded_claims": [ - "work-descriptor interpretation", - "wire-schema equivalence", - "digest construction correctness", - "runtime execution correctness", - "liveness", - "result correctness", - "implementation refinement", - ], - } - seed_relation = { - "document_type": "aset-worker-seed-refinement-relation", - "schema_version": 1, - "status": "PROOF_CANDIDATE_MATERIALIZED", - "relation_type": "WORKER_ONLY_OPERATIONS_AS_SEED_STUTTER_PROOF_CANDIDATE", - "upstream_seed": { - "compatibility_standard": binding["compatibility_standard"], - "release_tag": binding["seed_release_tag"], - "release_commit": binding["seed_release_commit"], - "canon_id": binding["canon_id"], - "canon_version": binding["canon_version"], - "canon_package_digest": binding["canon_package_digest"], - "module": "SeedResolution", - "path": "seed/canonical/formal/SeedResolution.tla", - "sha256": "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926", - "materialization": "EXTERNAL_PINNED_SEED_SOURCE_NOT_VENDORED", - }, - "mapping_candidate": { - "module": "WorkerSeedStuttering", - "path": "extension/canonical/formal/WorkerSeedStuttering.tla", - "sha256": sha(FORMAL / "WorkerSeedStuttering.tla"), - "worker_operations": "SEED_STUTTER", - }, - "proof_candidate": { - "module": "WorkerSeedStutteringProofs", - "path": "extension/canonical/formal/WorkerSeedStutteringProofs.tla", - "sha256": sha(FORMAL / "WorkerSeedStutteringProofs.tla"), - "final_theorems": [ - "WorkerOperationsPreserveSeedProjection", - "WorkerOperationsPreserveSeedOwnedState", - "WorkerCompositionRefinesSeedResolutionByStuttering", - ], - }, - "claim_boundary": "START_WORK and END_WORK alter only Worker extension state and are stuttering steps with respect to the exact pinned Seed projection.", - "excluded_claims": [ - "Worker output is a Seed request", - "Worker output is a Seed resolution", - "Worker evidence creates Authority", - "Worker execution grants effect permission", - "implementation refinement", - "liveness", - ], - } - lifecycle_proof = { - "document_type": "aset-worker-lifecycle-proof-candidate", - "schema_version": 1, - "status": "PROOF_CANDIDATE_MATERIALIZED", - "model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": sha(FORMAL / "WorkerLifecycle.tla"), - }, - "proof": { - "module": "WorkerLifecycleProofs", - "path": "extension/canonical/formal/WorkerLifecycleProofs.tla", - "sha256": sha(FORMAL / "WorkerLifecycleProofs.tla"), - "final_theorems": [ - "SpecImpliesAlwaysWorkerSafety", - "SpecImpliesStartedAppendOnly", - "SpecImpliesTerminalAppendOnly", - "SpecImpliesWorkerStateChangesOnlyByRecognizedTransition", - ], - }, - "excluded_claims": [ - "work-descriptor interpretation", - "wire metadata correctness", - "digest correctness", - "liveness", - "result correctness", - "implementation refinement", - ], - } - canon_evidence = load_proof_evidence("canon-refinement-proof.json") - if canon_evidence is not None: - canon_relation["status"] = "MECHANICALLY_PROVED" - canon_relation["relation_type"] = "STANDALONE_GENERATED_PROJECTION_WITH_BEHAVIORAL_EQUIVALENCE_PROOF" - canon_relation["proof_evidence"] = { - "path": "extension/canonical/assurance/canon-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": canon_evidence["proof_gate"]["obligations_proved"], - } - - seed_evidence = load_proof_evidence("seed-refinement-proof.json") - if seed_evidence is not None: - seed_relation["status"] = "MECHANICALLY_PROVED" - seed_relation["relation_type"] = "WORKER_ONLY_OPERATIONS_AS_SEED_STUTTER_PROOF" - seed_relation["proof_evidence"] = { - "path": "extension/canonical/assurance/seed-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": seed_evidence["proof_gate"]["obligations_proved"], - } - - write(ASSURANCE / "canon-tla-refinement.json", canon_relation) - write(ASSURANCE / "seed-refinement.json", seed_relation) - write(ASSURANCE / "lifecycle-proof-candidate.json", lifecycle_proof) - print("WORKER_FORMAL_RELATIONS_BUILD=PASS") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/check_finite_model.py b/tools/check_finite_model.py deleted file mode 100644 index 2a9d3a7..0000000 --- a/tools/check_finite_model.py +++ /dev/null @@ -1,72 +0,0 @@ -from __future__ import annotations -from collections import deque -from dataclasses import dataclass - -WORKS = ("w1", "w2") - - -@dataclass(frozen=True) -class State: - started: frozenset[str] - result: frozenset[str] - no_result: frozenset[str] - - -INIT = State(frozenset(), frozenset(), frozenset()) - - -def invariant(s: State) -> None: - universe = frozenset(WORKS) - assert s.started <= universe - assert s.result <= s.started - assert s.no_result <= s.started - assert not (s.result & s.no_result) - - -def successors(s: State): - terminal = s.result | s.no_result - for w in WORKS: - if w not in s.started: - yield ("START_WORK", w), State(s.started | {w}, s.result, s.no_result) - if w in s.started and w not in terminal: - yield ("END_WORK:RESULT", w), State(s.started, s.result | {w}, s.no_result) - yield ("END_WORK:NO_RESULT", w), State(s.started, s.result, s.no_result | {w}) - - -def state_of(s: State, w: str) -> str: - if w in s.result: - return "RESULT" - if w in s.no_result: - return "NO_RESULT" - if w in s.started: - return "RUNNING" - return "UNREGISTERED" - - -def main(): - q = deque([INIT]) - seen = {INIT} - edges = 0 - observed_states = set() - while q: - s = q.popleft() - invariant(s) - for w in WORKS: - observed_states.add(state_of(s, w)) - for _, nxt in successors(s): - invariant(nxt) - edges += 1 - if nxt not in seen: - seen.add(nxt) - q.append(nxt) - expected = {"UNREGISTERED", "RUNNING", "RESULT", "NO_RESULT"} - assert observed_states == expected, (observed_states, expected) - print(f"FINITE_MODEL_REACHABLE_STATES={len(seen)}") - print(f"FINITE_MODEL_EDGES={edges}") - print("FINITE_MODEL_LIFECYCLE_STATES=" + ",".join(sorted(observed_states))) - print("FINITE_MODEL_RESULT_XOR_NO_RESULT=PASS") - print("FINITE_MODEL_GATE=PASS") - - -if __name__ == "__main__": - main() diff --git a/tools/check_seed_stutter_assurance.py b/tools/check_seed_stutter_assurance.py deleted file mode 100755 index 5457c7b..0000000 --- a/tools/check_seed_stutter_assurance.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations - -import argparse -import hashlib -import json -import subprocess -from pathlib import Path -from typing import Any - -ROOT = Path(__file__).resolve().parents[1] -PROFILE_PATH = Path("assurance/seed-stutter/ASSURANCE_PROFILE.json") -CANON_PATH = Path("extension/canonical/CANON_PACKAGE.json") -MODEL_PATH = Path("extension/canonical/source/worker-model.json") -SEED_STUTTER_PATH = Path("extension/canonical/formal/WorkerSeedStuttering.tla") -SEED_PROOFS_PATH = Path("extension/canonical/formal/WorkerSeedStutteringProofs.tla") -SEED_EVIDENCE_PATH = Path("extension/canonical/assurance/seed-refinement-proof.json") -V60_PACKAGE_PATH = Path("assurance/seed-recognition-boundary/ASSURANCE_PACKAGE.json") -SEED_RESOLUTION_PATH = Path("seed/canonical/formal/SeedResolution.tla") - - -def load(path: Path) -> dict[str, Any]: - value = json.loads(path.read_text(encoding="utf-8")) - if not isinstance(value, dict): - raise ValueError(f"{path} must contain a JSON object") - return value - - -def sha256(path: Path) -> str: - return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest() - - -def require(condition: bool, message: str) -> None: - if not condition: - raise ValueError(message) - - -def proof_relation(v60: dict[str, Any], relation_id: str) -> dict[str, Any] | None: - for relation in v60.get("proof_chain", []): - if relation.get("id") == relation_id: - return relation - return None - - -def git_head(root: Path) -> str | None: - if not (root / ".git").exists(): - return None - result = subprocess.run( - ["git", "-C", str(root), "rev-parse", "HEAD"], - text=True, - capture_output=True, - check=False, - ) - return result.stdout.strip() if result.returncode == 0 else None - - -def check(worker_root: Path, seed_root: Path) -> dict[str, Any]: - profile = load(worker_root / PROFILE_PATH) - canon = load(worker_root / CANON_PATH) - model = load(worker_root / MODEL_PATH) - evidence = load(worker_root / SEED_EVIDENCE_PATH) - v60_path = seed_root / V60_PACKAGE_PATH - v60 = load(v60_path) - - worker = profile["worker_subject"] - seed = profile["shared_seed_subject"] - public = profile["public_v60_subject"] - - require( - profile.get("normative") is False, - "assurance profile must remain non-normative", - ) - require( - profile.get("normative_precedence") == "NONE", - "assurance profile gained precedence", - ) - require(canon.get("canon_id") == worker["canon_id"], "Worker canon id changed") - require( - model.get("canon_id") == worker["canon_id"], "Worker model canon id changed" - ) - require( - model.get("version") == worker["extension_version"], "Worker version changed" - ) - - identities = { - MODEL_PATH: "model_sha256", - SEED_STUTTER_PATH: "seed_stuttering_sha256", - SEED_PROOFS_PATH: "seed_stuttering_proof_sha256", - SEED_EVIDENCE_PATH: "seed_refinement_evidence_sha256", - } - for path, key in identities.items(): - require( - sha256(worker_root / path) == worker[key], - f"artifact identity changed: {path}", - ) - - gate = evidence.get("proof_gate", {}) - require( - evidence.get("status") == "MECHANICALLY_PROVED", - "Worker Seed refinement is not mechanically proved", - ) - require( - evidence.get("scope") == worker["seed_refinement_scope"], - "Worker Seed refinement scope changed", - ) - require( - gate.get("obligations_proved") == worker["seed_refinement_obligations"], - "Worker Seed proof-obligation evidence changed", - ) - require( - set(gate.get("final_theorems", [])) - == { - "WorkerOperationsPreserveSeedProjection", - "WorkerOperationsPreserveSeedOwnedState", - "WorkerCompositionRefinesSeedResolutionByStuttering", - }, - "Worker Seed theorem set changed", - ) - upstream_sha = evidence.get("upstream_seed", {}).get("sha256") - require( - upstream_sha == seed["seed_resolution_sha256"], - "Worker proof points at a different SeedResolution", - ) - - require( - sha256(v60_path) == public["package_file_sha256"], - "public v60 package file identity changed", - ) - require( - v60.get("assurance_id") == public["assurance_id"], - "public v60 assurance id changed", - ) - require( - v60.get("package_digest") == public["package_digest"], - "public v60 package digest changed", - ) - require( - v60.get("expected_tlaps_obligations") == public["expected_tlaps_obligations"], - "public v60 obligation evidence changed", - ) - require( - v60.get("subject", {}).get("canon_id") == seed["canon_id"], - "public v60 Seed canon id changed", - ) - require( - v60.get("subject", {}).get("canon_version") == seed["canon_version"], - "public v60 Seed canon version changed", - ) - require( - v60.get("subject", {}).get("seed_resolution_sha256") == upstream_sha, - "public v60 and Worker proof do not share the exact Seed subject", - ) - require( - sha256(seed_root / SEED_RESOLUTION_PATH) == upstream_sha, - "local SeedResolution bytes differ from the shared subject", - ) - - actual_head = git_head(seed_root) - if actual_head is not None: - require( - actual_head == public["commit"], - "public assurance checkout is not at the pinned commit", - ) - - for expected in public["required_proof_relations"]: - actual = proof_relation(v60, expected["id"]) - require(actual is not None, f"public v60 relation missing: {expected['id']}") - require( - actual.get("final_theorem") == expected["final_theorem"], - f"public v60 theorem changed: {expected['id']}", - ) - require( - actual.get("expected_obligations") == expected["expected_obligations"], - f"public v60 obligation evidence changed: {expected['id']}", - ) - - require( - "external effect authorization" - in model.get("normative_scope", {}).get("does_not_define", []), - "Worker canon now owns external effect authorization", - ) - require( - model.get("composition", {}).get("requires") - == ["ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3"], - "Worker direct Seed compatibility binding changed", - ) - - return { - "assurance_id": profile["assurance_id"], - "worker_canon_id": worker["canon_id"], - "worker_seed_refinement": "MECHANICALLY_PROVED", - "worker_seed_refinement_obligations": gate["obligations_proved"], - "public_v60_assurance_id": v60["assurance_id"], - "public_v60_expected_tlaps_obligations": v60["expected_tlaps_obligations"], - "shared_seed_resolution_sha256": upstream_sha, - "composition_type": "EVIDENCE_COMPOSITION_NOT_NEW_TLAPS_THEOREM", - "verdict": "PASS", - } - - -def main() -> int: - parser = argparse.ArgumentParser() - parser.add_argument("--worker-root", type=Path, default=ROOT) - parser.add_argument("--seed-root", type=Path, required=True) - parser.add_argument("--output", type=Path) - args = parser.parse_args() - try: - report = check(args.worker_root.resolve(), args.seed_root.resolve()) - except (OSError, KeyError, TypeError, ValueError, json.JSONDecodeError) as exc: - print(f"WORKER_SEED_STUTTER_ASSURANCE=FAIL:{exc}") - return 1 - print("WORKER_SEED_STUTTER_ASSURANCE_SUBJECT_BINDING=PASS") - print("WORKER_SEED_REFINEMENT_EVIDENCE=19/19") - print("WORKER_PUBLIC_V60_EVIDENCE=2257/2257") - print("WORKER_SEED_STUTTER_ASSURANCE=PASS") - if args.output: - output = args.output if args.output.is_absolute() else ROOT / args.output - output.parent.mkdir(parents=True, exist_ok=True) - output.write_text( - json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8" - ) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/generate_canon_tla_projection.py b/tools/generate_canon_tla_projection.py deleted file mode 100755 index 3b033ac..0000000 --- a/tools/generate_canon_tla_projection.py +++ /dev/null @@ -1,164 +0,0 @@ -from __future__ import annotations - -import argparse -import hashlib -import json -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -MODEL = ROOT / "extension/canonical/source/worker-model.json" -OUTPUT = ROOT / "extension/canonical/formal/WorkerCanonProjection.tla" -PROFILE = "ASET-WORKER-CANON-TLA-PROJECTION-V2" - -EXPECTED_TRANSITIONS = [ - ("UNREGISTERED", "START_WORK", None, "RUNNING"), - ("RUNNING", "END_WORK", "RESULT", "RESULT"), - ("RUNNING", "END_WORK", "NO_RESULT", "NO_RESULT"), -] -EXPECTED_OPERATIONS = ["START_WORK", "END_WORK"] - - -def sha256_bytes(data: bytes) -> str: - return hashlib.sha256(data).hexdigest() - - -def validate(model: dict) -> None: - errors: list[str] = [] - if model.get("canon_id") != "ASET-WORKER-CANON-0.1-ALPHA2": - errors.append("unexpected canon_id") - if model.get("version") != "0.1.0-alpha.1": - errors.append("unexpected version") - if model.get("state_machine", {}).get("terminal_states") != ["RESULT", "NO_RESULT"]: - errors.append("terminal states mismatch") - if model.get("state_machine", {}).get("terminal_relation") != "XOR": - errors.append("terminal relation is not XOR") - transitions = [ - (x.get("from"), x.get("operation"), x.get("terminal_kind"), x.get("to")) - for x in model.get("state_machine", {}).get("transitions", []) - ] - if transitions != EXPECTED_TRANSITIONS: - errors.append("state-machine transition set mismatch") - operations = [x.get("kind") for x in model.get("operations", [])] - if operations != EXPECTED_OPERATIONS: - errors.append("operation catalogue mismatch") - if len(model.get("requirements", [])) != 9: - errors.append("requirement count mismatch") - if len(model.get("invariants", [])) != 9: - errors.append("invariant count mismatch") - if errors: - raise ValueError("; ".join(errors)) - - -def render(model: dict) -> str: - source_sha = sha256_bytes(MODEL.read_bytes()) - return f'''---------------------- MODULE WorkerCanonProjection ---------------------- -EXTENDS FiniteSets - -(*************************************************************************** -GENERATED FILE. DO NOT EDIT. -Source: extension/canonical/source/worker-model.json -Source SHA-256: {source_sha} -Projection profile: {PROFILE} - -This standalone safety projection captures only the minimized append-only -productive-attempt lifecycle declared by the machine-readable Worker canon. -It does not interpret the opaque work descriptor, terminal payload, wire-level -digests, runtime execution, liveness, result correctness or implementation -refinement. -***************************************************************************) - -CONSTANT WorkIds - -VARIABLES started, resultWorks, noResultWorks - -CanonVars == <> - -CanonInit == - /\\ started = {{}} - /\\ resultWorks = {{}} - /\\ noResultWorks = {{}} - -CanonTerminal == resultWorks \\cup noResultWorks - -CanonStartWork(w) == - /\\ w \\in WorkIds - /\\ w \\notin started - /\\ started' = started \\cup {{w}} - /\\ UNCHANGED <> - -CanonEndWorkWithResult(w) == - /\\ w \\in started - /\\ w \\notin CanonTerminal - /\\ resultWorks' = resultWorks \\cup {{w}} - /\\ UNCHANGED <> - -CanonEndWorkWithNoResult(w) == - /\\ w \\in started - /\\ w \\notin CanonTerminal - /\\ noResultWorks' = noResultWorks \\cup {{w}} - /\\ UNCHANGED <> - -CanonEndWork(w, terminalKind) == - \\/ /\\ terminalKind = "RESULT" - /\\ CanonEndWorkWithResult(w) - \\/ /\\ terminalKind = "NO_RESULT" - /\\ CanonEndWorkWithNoResult(w) - -CanonRecognizedWorkerTransition == - \\/ \\E w \\in WorkIds : CanonStartWork(w) - \\/ \\E w \\in WorkIds, terminalKind \\in {{"RESULT", "NO_RESULT"}} : CanonEndWork(w, terminalKind) - -CanonNext == CanonRecognizedWorkerTransition -CanonSpec == CanonInit /\\ [][CanonNext]_CanonVars - -CanonTypeOK == - /\\ started \\subseteq WorkIds - /\\ resultWorks \\subseteq WorkIds - /\\ noResultWorks \\subseteq WorkIds - -CanonResultImpliesStarted == resultWorks \\subseteq started -CanonNoResultImpliesStarted == noResultWorks \\subseteq started -CanonResultXorNoResult == resultWorks \\cap noResultWorks = {{}} - -CanonWorkerSafety == - /\\ CanonTypeOK - /\\ CanonResultImpliesStarted - /\\ CanonNoResultImpliesStarted - /\\ CanonResultXorNoResult - -============================================================================= -''' - - -def main() -> int: - parser = argparse.ArgumentParser() - parser.add_argument("--check", action="store_true") - args = parser.parse_args() - model = json.loads(MODEL.read_text(encoding="utf-8")) - validate(model) - rendered = render(model).encode("utf-8") - if args.check: - if not OUTPUT.is_file(): - print("WORKER_CANON_PROJECTION_CHECK=FAIL") - print(f"WORKER_CANON_PROJECTION_ERROR=missing {OUTPUT.relative_to(ROOT)}") - return 1 - actual = OUTPUT.read_bytes() - if actual != rendered: - print("WORKER_CANON_PROJECTION_CHECK=FAIL") - print("WORKER_CANON_PROJECTION_ERROR=committed projection is stale") - print(f"WORKER_CANON_PROJECTION_EXPECTED_SHA256={sha256_bytes(rendered)}") - print(f"WORKER_CANON_PROJECTION_ACTUAL_SHA256={sha256_bytes(actual)}") - return 1 - print(f"WORKER_CANON_PROJECTION={OUTPUT.relative_to(ROOT)}") - print(f"WORKER_CANON_PROJECTION_SHA256=sha256:{sha256_bytes(actual)}") - print("WORKER_CANON_PROJECTION_CHECK=PASS") - return 0 - OUTPUT.write_bytes(rendered) - print(f"WORKER_CANON_PROJECTION={OUTPUT.relative_to(ROOT)}") - print(f"WORKER_CANON_PROJECTION_SHA256=sha256:{sha256_bytes(rendered)}") - print("WORKER_CANON_PROJECTION_BUILD=PASS") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/materialize_formal_evidence.py b/tools/materialize_formal_evidence.py deleted file mode 100755 index 2b54ef0..0000000 --- a/tools/materialize_formal_evidence.py +++ /dev/null @@ -1,407 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations - -import argparse -import hashlib -import json -import subprocess -import sys -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -CANON = ROOT / "extension/canonical" -FORMAL = CANON / "formal" -ASSURANCE = CANON / "assurance" -DIST = ROOT / "dist/formal-candidate" -BINDING = ROOT / "upstream/ASET_SEED_BINDING.json" -COMPATIBILITY_PROFILE = ROOT / "standards/worker-compatibility/compatibility-standard-profile-v1.json" - -EXPECTED_TLAPM_COMMIT = "4600b24c6d95a25ff081ad37b63b2a01c29d43a5" -EXPECTED_TLAPM_VERSION = "4600b24" -EXPECTED_SEED_RELEASE_COMMIT = "633c130187b2a2bb42f24cfd66662d475de385d2" -EXPECTED_SEED_RESOLUTION_SHA256 = "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926" - -PROOFS = { - "WORKER_TLAPS_SAFETY": { - "report": DIST / "worker_tlaps_safety.json", - "proof": FORMAL / "WorkerLifecycleProofs.tla", - "final_theorems": [ - "SpecImpliesAlwaysWorkerSafety", - "SpecImpliesStartedAppendOnly", - "SpecImpliesTerminalAppendOnly", - "SpecImpliesWorkerStateChangesOnlyByRecognizedTransition", - ], - }, - "WORKER_CANON_TO_TLA": { - "report": DIST / "worker_canon_to_tla.json", - "proof": FORMAL / "WorkerCanonRefinementProofs.tla", - "final_theorems": [ - "WorkerSafetyEquivalentToCanonProjection", - "WorkerLifecycleBehaviorallyEquivalentToCanonProjection", - ], - }, - "WORKER_SEED_REFINEMENT": { - "report": DIST / "worker_seed_refinement.json", - "proof": FORMAL / "WorkerSeedStutteringProofs.tla", - "final_theorems": [ - "WorkerOperationsPreserveSeedProjection", - "WorkerOperationsPreserveSeedOwnedState", - "WorkerCompositionRefinesSeedResolutionByStuttering", - ], - }, -} - - -def sha(path: Path) -> str: - return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest() - - -def canonical_bytes(value: object) -> bytes: - return (json.dumps(value, indent=2, sort_keys=True) + "\n").encode("utf-8") - - -def read_json(path: Path) -> dict: - return json.loads(path.read_text(encoding="utf-8")) - - -def validate_report(proof_id: str, spec: dict) -> tuple[dict, list[str]]: - errors: list[str] = [] - report_path: Path = spec["report"] - proof_path: Path = spec["proof"] - if not report_path.is_file(): - return {}, [f"missing proof report: {report_path.relative_to(ROOT)}"] - report = read_json(report_path) - expected_sha = sha(proof_path) - checks = { - "proof_id": proof_id, - "verdict": "PASS", - "proof_sha256": expected_sha, - "tlapm_commit": EXPECTED_TLAPM_COMMIT, - "tlapm_version": EXPECTED_TLAPM_VERSION, - } - for field, expected in checks.items(): - if report.get(field) != expected: - errors.append( - f"{proof_id} {field} mismatch: expected {expected!r}, got {report.get(field)!r}" - ) - if report.get("final_theorems") != spec["final_theorems"]: - errors.append(f"{proof_id} final theorem set mismatch") - obligations = report.get("obligations_proved") - if not isinstance(obligations, int) or obligations <= 0: - errors.append(f"{proof_id} obligations_proved is not a positive integer") - if report.get("returncode") != 0: - errors.append(f"{proof_id} report returncode is not zero") - if report.get("timed_out") is not False: - errors.append(f"{proof_id} report timed_out is not false") - if report.get("errors") != []: - errors.append(f"{proof_id} report contains errors") - return report, errors - - -def load_verified_runs() -> tuple[dict[str, dict], dict, list[str]]: - errors: list[str] = [] - gate_path = DIST / "formal-candidate-gate.json" - if not gate_path.is_file(): - return {}, {}, [f"missing gate report: {gate_path.relative_to(ROOT)}"] - gate = read_json(gate_path) - if gate.get("verdict") != "PASS": - errors.append("formal candidate gate report is not PASS") - if gate.get("tlapm_commit") != EXPECTED_TLAPM_COMMIT: - errors.append("formal candidate gate TLAPM commit mismatch") - if gate.get("tlapm_version") != EXPECTED_TLAPM_VERSION: - errors.append("formal candidate gate TLAPM version mismatch") - if gate.get("seed_release_commit") != EXPECTED_SEED_RELEASE_COMMIT: - errors.append("formal candidate gate Seed release commit mismatch") - if gate.get("seed_resolution_sha256") != EXPECTED_SEED_RESOLUTION_SHA256: - errors.append("formal candidate gate SeedResolution digest mismatch") - - reports: dict[str, dict] = {} - for proof_id, spec in PROOFS.items(): - report, report_errors = validate_report(proof_id, spec) - reports[proof_id] = report - errors.extend(report_errors) - - gate_proofs = {p.get("proof_id"): p for p in gate.get("proofs", []) if isinstance(p, dict)} - for proof_id, report in reports.items(): - gp = gate_proofs.get(proof_id) - if gp is None: - errors.append(f"formal candidate gate report is missing {proof_id}") - continue - for field in ("verdict", "obligations_proved", "proof_sha256"): - if gp.get(field) != report.get(field): - errors.append(f"formal candidate gate {proof_id} {field} mismatch") - return reports, gate, errors - - -def build_evidence(reports: dict[str, dict]) -> dict[str, dict]: - binding = read_json(BINDING) - safety = reports["WORKER_TLAPS_SAFETY"] - canon = reports["WORKER_CANON_TO_TLA"] - seed = reports["WORKER_SEED_REFINEMENT"] - - lifecycle = { - "document_type": "aset-worker-lifecycle-proof-evidence", - "schema_version": 1, - "status": "MECHANICALLY_PROVED", - "scope": "UNBOUNDED_TLAPS_WORKER_LIFECYCLE_SAFETY", - "normative_precedence": "MACHINE_READABLE_CANON", - "artifacts": { - "model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": sha(FORMAL / "WorkerLifecycle.tla"), - }, - "proof": { - "module": "WorkerLifecycleProofs", - "path": "extension/canonical/formal/WorkerLifecycleProofs.tla", - "sha256": sha(FORMAL / "WorkerLifecycleProofs.tla"), - }, - }, - "proof_gate": { - "runner": "tools/run_formal_candidate_gate.py", - "final_theorems": PROOFS["WORKER_TLAPS_SAFETY"]["final_theorems"], - "obligation_count_semantics": "RECORDED_EVIDENCE_NOT_FIXED_SEMANTIC_CONTRACT", - "obligations_proved": safety["obligations_proved"], - "verdict": "PASS", - }, - "tlapm": {"commit": EXPECTED_TLAPM_COMMIT, "version": EXPECTED_TLAPM_VERSION}, - "claim_boundary": [ - "The proof establishes the declared safety properties of the exact WorkerLifecycle.tla and WorkerLifecycleProofs.tla artifacts recorded here.", - "It does not establish liveness, result correctness, wire metadata correctness, digest correctness, or implementation refinement.", - ], - } - - canon_evidence = { - "document_type": "aset-worker-canon-refinement-proof-evidence", - "schema_version": 1, - "status": "MECHANICALLY_PROVED", - "scope": "EXACT_CANON_PROJECTION_TO_HANDWRITTEN_LIFECYCLE_EQUIVALENCE", - "normative_precedence": "MACHINE_READABLE_CANON", - "profile": "ASET-WORKER-CANON-TLA-PROJECTION-V2", - "artifacts": { - "source_model": { - "path": "extension/canonical/source/worker-model.json", - "sha256": sha(CANON / "source/worker-model.json"), - }, - "generated_projection": { - "module": "WorkerCanonProjection", - "path": "extension/canonical/formal/WorkerCanonProjection.tla", - "sha256": sha(FORMAL / "WorkerCanonProjection.tla"), - }, - "target_model": { - "module": "WorkerLifecycle", - "path": "extension/canonical/formal/WorkerLifecycle.tla", - "sha256": sha(FORMAL / "WorkerLifecycle.tla"), - }, - "proof": { - "module": "WorkerCanonRefinementProofs", - "path": "extension/canonical/formal/WorkerCanonRefinementProofs.tla", - "sha256": sha(FORMAL / "WorkerCanonRefinementProofs.tla"), - }, - }, - "proof_gate": { - "runner": "tools/run_formal_candidate_gate.py", - "final_theorems": PROOFS["WORKER_CANON_TO_TLA"]["final_theorems"], - "obligation_count_semantics": "RECORDED_EVIDENCE_NOT_FIXED_SEMANTIC_CONTRACT", - "obligations_proved": canon["obligations_proved"], - "verdict": "PASS", - }, - "tlapm": {"commit": EXPECTED_TLAPM_COMMIT, "version": EXPECTED_TLAPM_VERSION}, - "claim_boundary": [ - "The proof establishes behavioral equivalence only for the declared standalone generated lifecycle-safety projection and the exact handwritten WorkerLifecycle.tla artifact recorded here.", - "It does not establish correctness of the projection generator, natural-language or wire-schema equivalence, digest construction correctness, runtime execution correctness, liveness, result correctness, or implementation refinement.", - ], - } - - seed_evidence = { - "document_type": "aset-worker-seed-refinement-proof-evidence", - "schema_version": 1, - "status": "MECHANICALLY_PROVED", - "scope": "WORKER_ONLY_OPERATIONS_AS_PINNED_SEED_STUTTER", - "normative_precedence": "MACHINE_READABLE_CANON", - "artifacts": { - "mapping": { - "module": "WorkerSeedStuttering", - "path": "extension/canonical/formal/WorkerSeedStuttering.tla", - "sha256": sha(FORMAL / "WorkerSeedStuttering.tla"), - }, - "proof": { - "module": "WorkerSeedStutteringProofs", - "path": "extension/canonical/formal/WorkerSeedStutteringProofs.tla", - "sha256": sha(FORMAL / "WorkerSeedStutteringProofs.tla"), - }, - }, - "upstream_seed": { - "compatibility_standard": binding["compatibility_standard"], - "release_tag": binding["seed_release_tag"], - "release_commit": binding["seed_release_commit"], - "module": "SeedResolution", - "path": "seed/canonical/formal/SeedResolution.tla", - "sha256": EXPECTED_SEED_RESOLUTION_SHA256, - "materialization": "EXTERNAL_PINNED_SEED_SOURCE_NOT_VENDORED", - }, - "proof_gate": { - "runner": "tools/run_formal_candidate_gate.py", - "final_theorems": PROOFS["WORKER_SEED_REFINEMENT"]["final_theorems"], - "obligation_count_semantics": "RECORDED_EVIDENCE_NOT_FIXED_SEMANTIC_CONTRACT", - "obligations_proved": seed["obligations_proved"], - "verdict": "PASS", - }, - "tlapm": {"commit": EXPECTED_TLAPM_COMMIT, "version": EXPECTED_TLAPM_VERSION}, - "claim_boundary": [ - "The proof applies to the declared Worker-to-Seed stuttering mapping and the exact pinned SeedResolution.tla artifact recorded here.", - "It proves Worker-only lifecycle operations preserve the Seed projection and does not make Worker output a Seed request, Resolution, Authority, effect permission, or implementation refinement proof.", - ], - } - - registry = { - "document_type": "aset-worker-formal-verification-registry", - "schema_version": 1, - "status": "MECHANICALLY_PROVED", - "normative_precedence": "MACHINE_READABLE_CANON", - "toolchain": {"tlapm_commit": EXPECTED_TLAPM_COMMIT, "tlapm_version": EXPECTED_TLAPM_VERSION}, - "proofs": [ - { - "id": "WORKER_TLAPS_SAFETY", - "evidence": "extension/canonical/assurance/lifecycle-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": safety["obligations_proved"], - }, - { - "id": "WORKER_CANON_TO_TLA", - "evidence": "extension/canonical/assurance/canon-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": canon["obligations_proved"], - }, - { - "id": "WORKER_SEED_REFINEMENT", - "evidence": "extension/canonical/assurance/seed-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": seed["obligations_proved"], - }, - ], - "claim_boundary": "Mechanical proof evidence covers the abstract formal surfaces listed above. It does not establish arbitrary Worker runtime implementation refinement, liveness, result correctness, cryptographic correctness, or external-effect safety.", - } - return { - "lifecycle-proof.json": lifecycle, - "canon-refinement-proof.json": canon_evidence, - "seed-refinement-proof.json": seed_evidence, - "verification-registry.json": registry, - } - - -def update_relation_metadata(evidence: dict[str, dict]) -> None: - canon_relation = read_json(ASSURANCE / "canon-tla-refinement.json") - canon_relation["status"] = "MECHANICALLY_PROVED" - canon_relation["relation_type"] = "STANDALONE_GENERATED_PROJECTION_WITH_BEHAVIORAL_EQUIVALENCE_PROOF" - canon_relation["proof_evidence"] = { - "path": "extension/canonical/assurance/canon-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": evidence["canon-refinement-proof.json"]["proof_gate"]["obligations_proved"], - } - (ASSURANCE / "canon-tla-refinement.json").write_bytes(canonical_bytes(canon_relation)) - - seed_relation = read_json(ASSURANCE / "seed-refinement.json") - seed_relation["status"] = "MECHANICALLY_PROVED" - seed_relation["relation_type"] = "WORKER_ONLY_OPERATIONS_AS_SEED_STUTTER_PROOF" - seed_relation["proof_evidence"] = { - "path": "extension/canonical/assurance/seed-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": evidence["seed-refinement-proof.json"]["proof_gate"]["obligations_proved"], - } - (ASSURANCE / "seed-refinement.json").write_bytes(canonical_bytes(seed_relation)) - - -def expected_relation_metadata(evidence: dict[str, dict]) -> dict[str, dict]: - # Build expected closed relations in memory without mutating the tree. - canon_relation = read_json(ASSURANCE / "canon-tla-refinement.json") - canon_relation["status"] = "MECHANICALLY_PROVED" - canon_relation["relation_type"] = "STANDALONE_GENERATED_PROJECTION_WITH_BEHAVIORAL_EQUIVALENCE_PROOF" - canon_relation["proof_evidence"] = { - "path": "extension/canonical/assurance/canon-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": evidence["canon-refinement-proof.json"]["proof_gate"]["obligations_proved"], - } - seed_relation = read_json(ASSURANCE / "seed-refinement.json") - seed_relation["status"] = "MECHANICALLY_PROVED" - seed_relation["relation_type"] = "WORKER_ONLY_OPERATIONS_AS_SEED_STUTTER_PROOF" - seed_relation["proof_evidence"] = { - "path": "extension/canonical/assurance/seed-refinement-proof.json", - "status": "MECHANICALLY_PROVED", - "obligations_proved": evidence["seed-refinement-proof.json"]["proof_gate"]["obligations_proved"], - } - return { - "canon-tla-refinement.json": canon_relation, - "seed-refinement.json": seed_relation, - } - - -def build_repository_status_metadata() -> dict[str, dict]: - profile = read_json(COMPATIBILITY_PROFILE) - profile["formal_release_gate"] = "REQUIRES_REPRODUCIBLE_FORMAL_RELEASE_GATE" - profile["status"] = "FORMAL_ASSURANCE_MATERIALIZED_NOT_RELEASED" - return { - "standards/worker-compatibility/compatibility-standard-profile-v1.json": profile, - } - - -def run_builder(script: str) -> None: - result = subprocess.run([sys.executable, str(ROOT / script)], cwd=ROOT, text=True, check=False) - if result.returncode != 0: - raise RuntimeError(f"builder failed: {script} -> {result.returncode}") - - -def main() -> int: - parser = argparse.ArgumentParser() - parser.add_argument("--check", action="store_true") - args = parser.parse_args() - - reports, _gate, errors = load_verified_runs() - if errors: - print("WORKER_FORMAL_EVIDENCE_INPUT=FAIL") - for error in errors: - print(f"WORKER_FORMAL_EVIDENCE_ERROR={error}") - return 1 - - evidence = build_evidence(reports) - if args.check: - mismatches: list[str] = [] - for name, payload in evidence.items(): - path = ASSURANCE / name - if not path.is_file() or path.read_bytes() != canonical_bytes(payload): - mismatches.append(f"stale or missing assurance evidence: {path.relative_to(ROOT)}") - expected_relations = expected_relation_metadata(evidence) - for name, payload in expected_relations.items(): - path = ASSURANCE / name - if path.read_bytes() != canonical_bytes(payload): - mismatches.append(f"stale assurance relation: {path.relative_to(ROOT)}") - for rel, payload in build_repository_status_metadata().items(): - path = ROOT / rel - if not path.is_file() or path.read_bytes() != canonical_bytes(payload): - mismatches.append(f"stale repository status metadata: {rel}") - if mismatches: - print("WORKER_FORMAL_EVIDENCE_CHECK=FAIL") - for mismatch in mismatches: - print(f"WORKER_FORMAL_EVIDENCE_ERROR={mismatch}") - return 1 - print("WORKER_FORMAL_EVIDENCE_CHECK=PASS") - for proof_id, report in reports.items(): - print(f"{proof_id}_MATERIALIZED_OBLIGATIONS={report['obligations_proved']}") - return 0 - - for name, payload in evidence.items(): - (ASSURANCE / name).write_bytes(canonical_bytes(payload)) - update_relation_metadata(evidence) - for rel, payload in build_repository_status_metadata().items(): - (ROOT / rel).write_bytes(canonical_bytes(payload)) - run_builder("tools/build_formal_relations.py") - run_builder("tools/build_canon_package.py") - print("WORKER_FORMAL_EVIDENCE_MATERIALIZATION=PASS") - for proof_id, report in reports.items(): - print(f"{proof_id}_MATERIALIZED_OBLIGATIONS={report['obligations_proved']}") - print("NEXT=python tools/run_formal_release_gate.py --tlapm --seed-root ") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/run_alpha4_runtime_release_tlaps.py b/tools/run_alpha4_runtime_release_tlaps.py new file mode 100644 index 0000000..510cb4f --- /dev/null +++ b/tools/run_alpha4_runtime_release_tlaps.py @@ -0,0 +1,248 @@ +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import re +import subprocess +import sys +import tempfile +from pathlib import Path +from typing import Any + +from tools.alpha4_runtime_seed_extension import parse_seed_binding, sha256, tree_digest + +ROOT = Path(__file__).resolve().parents[1] +VERIFIER_MODULE = "AssembledRuntimeReleaseProofs" +FINAL_THEOREM = "AssembledRuntimePreservesExactSeedBoundary" + + +class RuntimeReleaseTLAPSError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise RuntimeReleaseTLAPSError(message) + + +def default_tlapm() -> str: + env = os.environ.get("TLAPM_BIN") + if env: + return env + return "tlapm" + + +def parse_obligation_count(text: str) -> int | None: + matches = re.findall(r"All ([0-9]+) obligations? proved\.", text) + return int(matches[-1]) if matches else None + + +def verifier_source() -> str: + return "\n".join( + [ + "---------------- MODULE AssembledRuntimeReleaseProofs ----------------", + "EXTENDS AssembledRuntime, TLAPS", + "", + "CONSTANTS SeedSubjects, SeedAuthorities, SeedEvidenceItems, SeedAuthorityRecognition", + "", + "Seed == INSTANCE ComponentRelations", + " WITH Subjects <- SeedSubjects,", + " Authorities <- SeedAuthorities,", + " EvidenceItems <- SeedEvidenceItems,", + " AuthorityRecognition <- SeedAuthorityRecognition", + "", + "ExactSeedPreservation(s, t, e) ==", + " \\/ Seed!PreserveUnknown(s, t, e)", + " \\/ Seed!PreserveAllow(s, t, e)", + " \\/ Seed!PreserveBlock(s, t, e)", + "", + "THEOREM RuntimeStepCompatibleWithExactSeedPreservation ==", + " \\A rs, rt, result, s, t, e :", + " /\\ AssembledStep(rs, rt, result)", + " /\\ ExactSeedPreservation(s, t, e)", + ' => /\\ SeedProjectionAction(result) = "STUTTER"', + " /\\ SeedProjectionEffectPermitted(result) = FALSE", + " /\\ t = s", + " /\\ t.subject = s.subject", + " /\\ t.authority = s.authority", + " /\\ t.evidence = s.evidence", + " /\\ t.recognition = s.recognition", + "PROOF", + " BY DEF ExactSeedPreservation,", + " Seed!PreserveUnknown,", + " Seed!PreserveAllow,", + " Seed!PreserveBlock,", + " SeedProjectionAction,", + " SeedProjectionEffectPermitted", + "", + f"THEOREM {FINAL_THEOREM} ==", + " RuntimeStepCompatibleWithExactSeedPreservation", + "PROOF", + " BY RuntimeStepCompatibleWithExactSeedPreservation", + "", + "=============================================================================", + "", + ] + ) + + +def load_release_manifest(release_root: Path) -> dict[str, Any]: + path = release_root / "RELEASE_MANIFEST.json" + require(path.is_file(), "Runtime release manifest missing") + value = json.loads(path.read_text(encoding="utf-8")) + require( + value.get("document_type") == "aset-runtime-alpha4-release-materialization", + "unexpected Runtime release manifest type", + ) + seed_base = value.get("seed_base") + require(isinstance(seed_base, dict), "Runtime release Seed base binding missing") + require(seed_base.get("projection") == "PRESERVE-SEED-STATE", "Runtime Seed projection drift") + return value + + +def check_release_tlaps(release_root: Path, seed_release_root: Path, tlapm: str) -> dict[str, Any]: + binding = parse_seed_binding() + release_root = release_root.resolve() + seed_release_root = seed_release_root.resolve() + assembled = release_root / "formal/AssembledRuntime.tla" + runtime_formal = release_root / "formal" + seed_formal = seed_release_root / "formal" + require(assembled.is_file(), "materialized AssembledRuntime.tla missing") + require(seed_formal.is_dir(), "exact Seed release formal tree missing") + require( + tree_digest(seed_release_root) == binding.release_tree, + "post-build proof Seed release tree mismatch", + ) + component_relations = seed_formal / "ComponentRelations.tla" + require(component_relations.is_file(), "exact Seed ComponentRelations.tla missing") + require( + sha256(component_relations) == binding.sources["seed/alpha4/formal/ComponentRelations.tla"], + "post-build proof Seed relational bytes mismatch", + ) + manifest = load_release_manifest(release_root) + require( + manifest["seed_base"]["tree_digest"] == binding.release_tree, + "Runtime release was assembled against another Seed tree", + ) + + release_tree_before = tree_digest(release_root) + seed_tree_before = tree_digest(seed_release_root) + source = verifier_source() + with tempfile.TemporaryDirectory(prefix="aset-runtime-release-tlaps-") as temp_dir: + verification_root = Path(temp_dir) + verifier = verification_root / f"{VERIFIER_MODULE}.tla" + verifier.write_text(source, encoding="utf-8") + command = [ + tlapm, + "-I", + str(runtime_formal), + "-I", + str(seed_formal), + str(verifier), + ] + try: + result = subprocess.run( + command, + cwd=verification_root, + check=False, + capture_output=True, + text=True, + ) + except OSError as error: + raise RuntimeReleaseTLAPSError(f"TLAPM invocation failed: {error}") from error + if result.stdout: + sys.stdout.write(result.stdout) + if result.stderr: + sys.stderr.write(result.stderr) + combined = result.stdout + "\n" + result.stderr + obligations = parse_obligation_count(combined) + require(result.returncode == 0, f"TLAPM returned {result.returncode}") + require(obligations is not None and obligations > 0, "proved obligation count missing") + require( + tree_digest(release_root) == release_tree_before, + "Runtime release tree changed during TLAPS verification", + ) + require( + tree_digest(seed_release_root) == seed_tree_before, + "Seed release tree changed during Runtime TLAPS verification", + ) + + return { + "document_type": "aset-runtime-release-assembled-tlaps-evidence", + "schema_version": 1, + "scope": "POST_BUILD_DEDUCTIVE_EXTENSION_ASSURANCE", + "semantic_delta": "NONE", + "semantic_precedence": "NONE", + "semantic_source_runtime_dependency": "NONE", + "release_binding": { + "tree_digest": release_tree_before, + "assembled_formal": { + "path": "formal/AssembledRuntime.tla", + "sha256": sha256(assembled), + }, + }, + "seed_binding": { + "release_tree_digest": seed_tree_before, + "component_relations": { + "path": "formal/ComponentRelations.tla", + "sha256": sha256(component_relations), + }, + "operators": ["PreserveUnknown", "PreserveAllow", "PreserveBlock"], + "relation": "PRESERVE_SEED_STATE", + }, + "proof": { + "module": VERIFIER_MODULE, + "module_materialization": "EPHEMERAL_VERIFIER_ONLY", + "module_sha256": "sha256:" + hashlib.sha256(source.encode("utf-8")).hexdigest(), + "final_theorem": FINAL_THEOREM, + "obligations_proved": obligations, + }, + "status": "PASS", + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--release-root", type=Path, required=True) + parser.add_argument("--seed-release-root", type=Path, required=True) + parser.add_argument("--tlapm", default=default_tlapm()) + parser.add_argument( + "--output", + type=Path, + default=ROOT / "dist/runtime-release-assembled-tlaps-evidence.json", + ) + args = parser.parse_args() + try: + evidence = check_release_tlaps(args.release_root, args.seed_release_root, args.tlapm) + output = args.output if args.output.is_absolute() else ROOT / args.output + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(evidence, indent=2, sort_keys=True) + "\n", encoding="utf-8") + proof = evidence["proof"] + print("ALPHA4_RUNTIME_RELEASE_TLAPS_SCOPE=POST_BUILD_DEDUCTIVE_EXTENSION_ASSURANCE") + print(f"ALPHA4_RUNTIME_RELEASE_TLAPS_FINAL_THEOREM={proof['final_theorem']}") + print(f"ALPHA4_RUNTIME_RELEASE_TLAPS_OBLIGATIONS={proof['obligations_proved']} PASS") + print( + f"ALPHA4_RUNTIME_RELEASE_TLAPS_TREE_DIGEST={evidence['release_binding']['tree_digest']}" + ) + print( + "ALPHA4_RUNTIME_RELEASE_TLAPS_SEED_TREE_DIGEST=" + f"{evidence['seed_binding']['release_tree_digest']}" + ) + print( + "ALPHA4_RUNTIME_RELEASE_TLAPS_SEED_OPERATORS=" + "PreserveUnknown,PreserveAllow,PreserveBlock" + ) + print("ALPHA4_RUNTIME_RELEASE_TLAPS_SEMANTIC_DELTA=NONE") + print("ALPHA4_RUNTIME_RELEASE_TLAPS_SEMANTIC_SOURCE_DEPENDENCY=NONE") + print("ALPHA4_RUNTIME_RELEASE_TLAPS=PASS") + return 0 + except (json.JSONDecodeError, OSError, ValueError, RuntimeReleaseTLAPSError) as error: + print(f"ALPHA4_RUNTIME_RELEASE_TLAPS_ERROR={error}") + print("ALPHA4_RUNTIME_RELEASE_TLAPS=FAIL") + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/run_alpha4_runtime_tlaps.py b/tools/run_alpha4_runtime_tlaps.py new file mode 100644 index 0000000..7ae5771 --- /dev/null +++ b/tools/run_alpha4_runtime_tlaps.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +import argparse +import re +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +FORMAL = ROOT / "runtime/alpha4/formal" +MODULES = [ + FORMAL / "OperationalRelationalPairingProofs.tla", + FORMAL / "SeedBoundaryProofs.tla", +] + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--tlapm", required=True) + args = parser.parse_args() + total = 0 + for module in MODULES: + result = subprocess.run( + [args.tlapm, "-I", str(FORMAL), str(module)], + cwd=ROOT, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=False, + ) + print(result.stdout, end="") + if result.returncode: + print(f"ALPHA4_RUNTIME_TLAPS_MODULE={module.name} FAIL") + return result.returncode + matches = re.findall(r"All ([0-9]+) obligations? proved\.", result.stdout) + if not matches: + print(f"ALPHA4_RUNTIME_TLAPS_MODULE={module.name} SUMMARY_MISSING") + return 1 + count = int(matches[-1]) + total += count + print(f"ALPHA4_RUNTIME_TLAPS_MODULE={module.name} OBLIGATIONS={count} PASS") + print(f"ALPHA4_RUNTIME_TLAPS_OBLIGATIONS={total} PASS") + print("ALPHA4_RUNTIME_TLAPS=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/run_conformance.py b/tools/run_conformance.py deleted file mode 100644 index 878a962..0000000 --- a/tools/run_conformance.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import annotations -import json -from pathlib import Path -import sys - -ROOT = Path(__file__).resolve().parents[1] -sys.path.insert(0, str(ROOT)) -from reference.oracle import run_case - - -def main(): - cases = sorted((ROOT / 'extension/canonical/conformance/cases').rglob('*.json')) - passed = 0 - for path in cases: - case = json.loads(path.read_text()) - actual = run_case(case) - assert actual == case['expected'], f"{case['case_id']}: expected {case['expected']}, got {actual}" - passed += 1 - print(f"CASE={case['case_id']} PASS") - print(f"CONFORMANCE={passed}/{len(cases)} PASS") - -if __name__ == '__main__': - main() diff --git a/tools/run_formal_candidate_gate.py b/tools/run_formal_candidate_gate.py deleted file mode 100755 index e0ee72f..0000000 --- a/tools/run_formal_candidate_gate.py +++ /dev/null @@ -1,323 +0,0 @@ -from __future__ import annotations - -import argparse -import hashlib -import json -import os -import re -import shutil -import subprocess -import sys -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -FORMAL = ROOT / "extension/canonical/formal" -DIST = ROOT / "dist/formal-candidate" -BINDING = ROOT / "upstream/ASET_SEED_BINDING.json" - -EXPECTED_TLAPM_VERSION = "4600b24" -EXPECTED_TLAPM_COMMIT = "4600b24c6d95a25ff081ad37b63b2a01c29d43a5" -EXPECTED_SEED_RELEASE_COMMIT = "633c130187b2a2bb42f24cfd66662d475de385d2" -EXPECTED_SEED_RESOLUTION_SHA256 = "1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926" - -PROOFS = [ - { - "id": "WORKER_TLAPS_SAFETY", - "path": FORMAL / "WorkerLifecycleProofs.tla", - "final_theorems": [ - "SpecImpliesAlwaysWorkerSafety", - "SpecImpliesStartedAppendOnly", - "SpecImpliesTerminalAppendOnly", - "SpecImpliesWorkerStateChangesOnlyByRecognizedTransition", - ], - "needs_seed": False, - }, - { - "id": "WORKER_CANON_TO_TLA", - "path": FORMAL / "WorkerCanonRefinementProofs.tla", - "final_theorems": [ - "WorkerSafetyEquivalentToCanonProjection", - "WorkerLifecycleBehaviorallyEquivalentToCanonProjection", - ], - "needs_seed": False, - }, - { - "id": "WORKER_SEED_REFINEMENT", - "path": FORMAL / "WorkerSeedStutteringProofs.tla", - "final_theorems": [ - "WorkerOperationsPreserveSeedProjection", - "WorkerOperationsPreserveSeedOwnedState", - "WorkerCompositionRefinesSeedResolutionByStuttering", - ], - "needs_seed": True, - }, -] - - -def sha_bytes(data: bytes) -> str: - return hashlib.sha256(data).hexdigest() - - -def sha_file(path: Path) -> str: - return sha_bytes(path.read_bytes()) - - -def run_checked(command: list[str], cwd: Path, timeout: int = 30) -> subprocess.CompletedProcess[str]: - return subprocess.run( - command, - cwd=cwd, - text=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - timeout=timeout, - check=False, - ) - - -def write_report(name: str, payload: dict) -> None: - DIST.mkdir(parents=True, exist_ok=True) - (DIST / f"{name}.json").write_text( - json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8" - ) - - -def materialize_pinned_seed(seed_root: Path) -> tuple[Path | None, list[str]]: - errors: list[str] = [] - if not (seed_root / ".git").exists(): - return None, [f"Seed checkout is not a git repository: {seed_root}"] - commit_check = run_checked( - ["git", "cat-file", "-e", f"{EXPECTED_SEED_RELEASE_COMMIT}^{{commit}}"], - seed_root, - ) - if commit_check.returncode != 0: - errors.append("pinned Seed release commit is absent from local object database") - return None, errors - show = run_checked( - [ - "git", - "show", - f"{EXPECTED_SEED_RELEASE_COMMIT}:seed/canonical/formal/SeedResolution.tla", - ], - seed_root, - ) - if show.returncode != 0: - errors.append("cannot materialize SeedResolution.tla from pinned Seed commit") - return None, errors - data = show.stdout.encode("utf-8") - actual = sha_bytes(data) - if actual != EXPECTED_SEED_RESOLUTION_SHA256: - errors.append( - "pinned SeedResolution.tla digest mismatch: " - f"expected {EXPECTED_SEED_RESOLUTION_SHA256}, got {actual}" - ) - return None, errors - pinned = DIST / "pinned-seed-formal" - pinned.mkdir(parents=True, exist_ok=True) - target = pinned / "SeedResolution.tla" - target.write_bytes(data) - return pinned, errors - - -def theorem_presence(path: Path, names: list[str]) -> list[str]: - errors: list[str] = [] - text = path.read_text(encoding="utf-8") - for theorem in names: - if re.search(rf"^THEOREM {re.escape(theorem)} ==\s*$", text, re.MULTILINE) is None: - errors.append(f"missing final theorem {theorem} in {path.name}") - return errors - - -def run_proof( - proof_id: str, - path: Path, - final_theorems: list[str], - tlapm: Path, - seed_include: Path | None, - timeout_seconds: int, -) -> dict: - errors = theorem_presence(path, final_theorems) - include_args = ["-I", str(FORMAL)] - if seed_include is not None: - include_args += ["-I", str(seed_include)] - shutil.rmtree(ROOT / ".tlacache", ignore_errors=True) - command = [str(tlapm), *include_args, str(path)] - output = "" - returncode: int | None = None - timed_out = False - if not errors: - try: - result = run_checked(command, ROOT, timeout_seconds) - output = result.stdout - returncode = result.returncode - except subprocess.TimeoutExpired as exc: - timed_out = True - captured = exc.stdout or "" - if isinstance(captured, bytes): - captured = captured.decode("utf-8", errors="replace") - output = captured - errors.append("TLAPS proof timed out") - if output: - print(output, end="" if output.endswith("\n") else "\n") - matches = re.findall(r"All ([0-9]+) obligations? proved\.", output) - obligations = int(matches[-1]) if matches else None - forbidden = ( - "obligations failed", - "unproved obligations", - "backend errors", - "Zenon error", - "Proof.Parser", - "[ERROR]", - ) - if returncode != 0: - errors.append(f"TLAPM returned {returncode}") - if obligations is None: - errors.append("TLAPM success summary was not found") - for marker in forbidden: - if marker in output: - errors.append(f"TLAPM output contains {marker!r}") - verdict = "PASS" if not errors else "FAIL" - report = { - "document_type": "aset-worker-formal-candidate-proof-run", - "schema_version": 1, - "proof_id": proof_id, - "proof_path": path.relative_to(ROOT).as_posix(), - "proof_sha256": "sha256:" + sha_file(path), - "final_theorems": final_theorems, - "command": command, - "tlapm_commit": EXPECTED_TLAPM_COMMIT, - "tlapm_version": EXPECTED_TLAPM_VERSION, - "obligations_proved": obligations, - "returncode": returncode, - "timed_out": timed_out, - "errors": errors, - "verdict": verdict, - } - write_report(proof_id.lower(), report) - if obligations is not None: - print(f"{proof_id}_OBLIGATIONS={obligations}") - print(f"{proof_id}_VERDICT={verdict}") - for error in errors: - print(f"{proof_id}_ERROR={error}") - return report - - -def main() -> int: - parser = argparse.ArgumentParser() - parser.add_argument( - "--tlapm", - type=Path, - default=Path.home() / "ASET/.tooling/tlapm/bin/tlapm", - ) - parser.add_argument("--seed-root", type=Path, default=Path.home() / "ASET") - parser.add_argument("--timeout-seconds", type=int, default=900) - args = parser.parse_args() - - tlapm = args.tlapm.expanduser().resolve() - seed_root = args.seed_root.expanduser().resolve() - DIST.mkdir(parents=True, exist_ok=True) - - print("=== ASET WORKER FORMAL CANDIDATE GATE ===") - errors: list[str] = [] - - projection = run_checked( - [sys.executable, str(ROOT / "tools/generate_canon_tla_projection.py"), "--check"], - ROOT, - ) - print(projection.stdout, end="" if projection.stdout.endswith("\n") else "\n") - if projection.returncode != 0: - errors.append("canon projection freshness check failed") - - candidate = run_checked( - [sys.executable, str(ROOT / "tools/verify_formal_candidate.py")], ROOT - ) - print(candidate.stdout, end="" if candidate.stdout.endswith("\n") else "\n") - if candidate.returncode != 0: - errors.append("formal candidate identity check failed") - - binding = json.loads(BINDING.read_text(encoding="utf-8")) - if binding.get("seed_release_commit") != EXPECTED_SEED_RELEASE_COMMIT: - errors.append("upstream Seed binding commit mismatch") - - if not tlapm.is_file(): - errors.append(f"missing TLAPM executable: {tlapm}") - elif not os.access(tlapm, os.X_OK): - errors.append(f"TLAPM is not executable: {tlapm}") - - version_output = "" - if tlapm.is_file() and os.access(tlapm, os.X_OK): - version = run_checked([str(tlapm), "--version"], ROOT) - version_output = version.stdout.strip() - if version.returncode != 0: - errors.append(f"tlapm --version returned {version.returncode}") - if version_output != EXPECTED_TLAPM_VERSION: - errors.append(f"unexpected TLAPM version: {version_output!r}") - - seed_include, seed_errors = materialize_pinned_seed(seed_root) - errors.extend(seed_errors) - - print(f"TLAPM_COMMIT={EXPECTED_TLAPM_COMMIT}") - print(f"TLAPM_VERSION={version_output}") - print(f"SEED_RELEASE_COMMIT={EXPECTED_SEED_RELEASE_COMMIT}") - if seed_include is not None: - seed_file = seed_include / "SeedResolution.tla" - print(f"PINNED_SEED_RESOLUTION={seed_file}") - print(f"PINNED_SEED_RESOLUTION_SHA256=sha256:{sha_file(seed_file)}") - - if errors: - print("FORMAL_CANDIDATE_GATE=FAIL") - for error in errors: - print(f"FORMAL_CANDIDATE_ERROR={error}") - write_report( - "formal-candidate-gate", - { - "document_type": "aset-worker-formal-candidate-gate", - "schema_version": 1, - "verdict": "FAIL", - "errors": errors, - }, - ) - return 1 - - reports = [] - for spec in PROOFS: - print(f"{spec['id']}=START") - for theorem in spec["final_theorems"]: - print(f"{spec['id']}_FINAL_THEOREM={theorem}") - reports.append( - run_proof( - spec["id"], - spec["path"], - spec["final_theorems"], - tlapm, - seed_include if spec["needs_seed"] else None, - args.timeout_seconds, - ) - ) - - verdict = "PASS" if all(r["verdict"] == "PASS" for r in reports) else "FAIL" - gate_report = { - "document_type": "aset-worker-formal-candidate-gate", - "schema_version": 1, - "tlapm_commit": EXPECTED_TLAPM_COMMIT, - "tlapm_version": version_output, - "seed_release_commit": EXPECTED_SEED_RELEASE_COMMIT, - "seed_resolution_sha256": "sha256:" + EXPECTED_SEED_RESOLUTION_SHA256, - "proofs": [ - { - "proof_id": r["proof_id"], - "verdict": r["verdict"], - "obligations_proved": r["obligations_proved"], - "proof_sha256": r["proof_sha256"], - } - for r in reports - ], - "verdict": verdict, - } - write_report("formal-candidate-gate", gate_report) - print(f"FORMAL_CANDIDATE_GATE={verdict}") - print("FORMAL_RELEASE_GATE=BLOCKED_PENDING_EVIDENCE_MATERIALIZATION") - return 0 if verdict == "PASS" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/run_formal_release_gate.py b/tools/run_formal_release_gate.py deleted file mode 100755 index 867d1d6..0000000 --- a/tools/run_formal_release_gate.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations - -import argparse -import json -import subprocess -import sys -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -DEFAULT_REPORT = ROOT / "dist/formal-release-gate.json" - - -def write_report(path: Path, report: dict[str, object]) -> None: - path.parent.mkdir(parents=True, exist_ok=True) - path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") - - -def run_stage(name: str, command: list[str]) -> dict[str, object]: - print(f"FORMAL_RELEASE_STAGE={name}:START") - result = subprocess.run(command, cwd=ROOT, check=False) - verdict = "PASS" if result.returncode == 0 else "FAIL" - print(f"FORMAL_RELEASE_STAGE={name}:{verdict}") - return {"name": name, "command": command, "returncode": result.returncode, "verdict": verdict} - - -def main() -> int: - parser = argparse.ArgumentParser() - parser.add_argument("--tlapm", type=Path, required=True) - parser.add_argument("--seed-root", type=Path, default=Path.home() / "ASET") - parser.add_argument("--timeout-seconds", type=int, default=900) - parser.add_argument("--output", type=Path, default=DEFAULT_REPORT) - args = parser.parse_args() - - output = args.output.expanduser() - if not output.is_absolute(): - output = ROOT / output - tlapm = args.tlapm.expanduser().resolve() - seed_root = args.seed_root.expanduser().resolve() - python = sys.executable - - stages = [ - ("CANON_PROJECTION_CHECK", [python, "tools/generate_canon_tla_projection.py", "--check"]), - ("LOCAL_GATE", [python, "tools/run_local_gate.py"]), - ( - "FORMAL_CANDIDATE_GATE", - [ - python, - "tools/run_formal_candidate_gate.py", - "--tlapm", - str(tlapm), - "--seed-root", - str(seed_root), - "--timeout-seconds", - str(args.timeout_seconds), - ], - ), - ("FORMAL_EVIDENCE_CHECK", [python, "tools/materialize_formal_evidence.py", "--check"]), - ("CANON_PACKAGE_VERIFY", [python, "tools/verify_canon_package.py"]), - ("TESTS", [python, "-m", "pytest", "-q"]), - ] - - results: list[dict[str, object]] = [] - for name, command in stages: - result = run_stage(name, command) - results.append(result) - if result["verdict"] != "PASS": - write_report( - output, - { - "document_type": "aset-worker-formal-release-gate-report", - "schema_version": 1, - "verdict": "FAIL", - "failed_stage": name, - "stages": results, - }, - ) - print("FORMAL_RELEASE_GATE=FAIL") - print(f"FORMAL_RELEASE_GATE_FAILED_STAGE={name}") - return 1 - - registry = json.loads( - (ROOT / "extension/canonical/assurance/verification-registry.json").read_text(encoding="utf-8") - ) - package = json.loads( - (ROOT / "extension/canonical/CANON_PACKAGE.json").read_text(encoding="utf-8") - ) - report = { - "document_type": "aset-worker-formal-release-gate-report", - "schema_version": 1, - "verdict": "PASS", - "canon_id": package["canon_id"], - "canon_version": package["version"], - "formal_verification_status": registry["status"], - "proofs": registry["proofs"], - "tlapm_commit": registry["toolchain"]["tlapm_commit"], - "tlapm_version": registry["toolchain"]["tlapm_version"], - "stages": results, - } - write_report(output, report) - for proof in registry["proofs"]: - print(f"FORMAL_RELEASE_{proof['id']}_STATUS={proof['status']}") - print(f"FORMAL_RELEASE_{proof['id']}_OBLIGATIONS={proof['obligations_proved']}") - print("FORMAL_RELEASE_GATE=PASS") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/run_local_gate.py b/tools/run_local_gate.py deleted file mode 100755 index 96999ce..0000000 --- a/tools/run_local_gate.py +++ /dev/null @@ -1,66 +0,0 @@ -from __future__ import annotations -import json -import subprocess -import sys -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] - - -def run(rel): - p = subprocess.run([sys.executable, str(ROOT / rel)], cwd=ROOT, text=True) - if p.returncode != 0: - raise RuntimeError(f"gate failed: {rel} -> {p.returncode}") - - -def structural_checks(): - model = json.loads((ROOT/'extension/canonical/source/worker-model.json').read_text()) - binding = json.loads((ROOT/'upstream/ASET_SEED_BINDING.json').read_text()) - assert model['canon_id'] == 'ASET-WORKER-CANON-0.1-ALPHA2' - assert model['version'] == '0.1.0-alpha.1' - assert model['state_machine']['terminal_states'] == ['RESULT','NO_RESULT'] - assert model['state_machine']['terminal_relation'] == 'XOR' - assert model['state_machine']['stored_or_derived_states'] == ['RUNNING','RESULT','NO_RESULT'] - assert [x['kind'] for x in model['operations']] == ['START_WORK','END_WORK'] - assert len(model['requirements']) == 9 - assert len(model['invariants']) == 9 - assert binding['compatibility_standard'] == 'ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3' - assert binding['seed_release_commit'] == '633c130187b2a2bb42f24cfd66662d475de385d2' - assert model['formal_assurance']['canon_to_tla_equivalence'] == 'OPEN' - assert model['formal_assurance']['seed_refinement'] == 'OPEN' - text = (ROOT/'README.md').read_text() - assert 'NO_RESULT' in text and 'RESULT' in text and 'XOR' in text - assert 'ACCEPT_WORK' not in text and 'ACCEPTED' not in text - print('STRUCTURAL_CANON_CHECKS=PASS') - print('UPSTREAM_SEED_BINDING=PASS') - print('FORMAL_CLAIM_BOUNDARY=PASS') - - -def main(): - print('=== ASET WORKER LOCAL GATE ===') - structural_checks() - run('tools/verify_formal_candidate.py') - run('tools/verify_canon_package.py') - run('tools/run_conformance.py') - run('tools/check_finite_model.py') - registry_path = ROOT/'extension/canonical/assurance/verification-registry.json' - if registry_path.is_file(): - registry = json.loads(registry_path.read_text()) - if registry.get('status') == 'MECHANICALLY_PROVED': - proofs = {p['id']:p for p in registry.get('proofs', [])} - print(f"MATERIALIZED_TLAPS_SAFETY={proofs.get('WORKER_TLAPS_SAFETY',{}).get('status','UNKNOWN')}") - print(f"MATERIALIZED_CANON_TO_TLA={proofs.get('WORKER_CANON_TO_TLA',{}).get('status','UNKNOWN')}") - print(f"MATERIALIZED_SEED_REFINEMENT={proofs.get('WORKER_SEED_REFINEMENT',{}).get('status','UNKNOWN')}") - print('FORMAL_RELEASE_GATE=REQUIRES_REPRODUCIBLE_FORMAL_RELEASE_GATE') - else: - print('FORMAL_RELEASE_GATE=BLOCKED') - else: - print('CANON_TO_TLA=OPEN') - print('TLAPS_SAFETY=OPEN') - print('SEED_REFINEMENT=OPEN') - print('FORMAL_RELEASE_GATE=BLOCKED') - print('ASET_WORKER_LOCAL_GATE=PASS') - - -if __name__=='__main__': - main() diff --git a/tools/validate_alpha4_runtime.py b/tools/validate_alpha4_runtime.py new file mode 100644 index 0000000..d84d796 --- /dev/null +++ b/tools/validate_alpha4_runtime.py @@ -0,0 +1,96 @@ +from __future__ import annotations + +from pathlib import Path + +from tools.alpha4_runtime_causal_expression import check_causal_bindings +from tools.alpha4_runtime_paired_expression import EXPECTED_WORDS, parse_operational_words + +ROOT = Path(__file__).resolve().parents[1] +MANIFEST = ROOT / "runtime/alpha4/RUNTIME.aset" + + +class ValidationError(RuntimeError): + pass + + +def require(condition: bool, message: str) -> None: + if not condition: + raise ValidationError(message) + + +def lines(path: Path) -> list[str]: + return [line.strip() for line in path.read_text(encoding="utf-8").splitlines() if line.strip()] + + +def main() -> int: + values = lines(MANIFEST) + require( + values[0] == "ASET-RUNTIME 1 ASET-RUNTIME-ALPHA4 0.1.0-alpha.4", + "Runtime subject header drift", + ) + require("SEMANTIC-PRECEDENCE NONE" in values, "Runtime semantic precedence drift") + require( + "PREDECESSOR-COMPATIBILITY NONE" in values, + "Runtime predecessor compatibility boundary drift", + ) + require( + "UPSTREAM-SUBJECT ASET-SEED-0.4-ALPHA" in values, + "Runtime Seed subject binding missing", + ) + require( + "UPSTREAM-BINDING upstream/ASET_SEED_ALPHA4_BINDING.aset" in values, + "Runtime Seed binding path drift", + ) + pairs = [line for line in values if line.startswith("PAIR ")] + causal = [line for line in values if line.startswith("CAUSAL-BIND ")] + require(len(pairs) == 8, f"Runtime pair surface must be 8, got {len(pairs)}") + require(len(causal) == 8, f"Runtime causal binding surface must be 8, got {len(causal)}") + component_ids = {line.split()[1] for line in pairs} + require( + component_ids == {line.split()[1] for line in causal}, + "Runtime pair/causal component identity drift", + ) + for relative in ( + "runtime/alpha4/operational/components.forth", + "runtime/alpha4/formal/RuntimeRelations.tla", + "runtime/alpha4/formal/RestrictedOperationalSemantics.tla", + "runtime/alpha4/formal/OperationalRelationalPairingProofs.tla", + "runtime/alpha4/formal/SeedBoundaryProofs.tla", + "runtime/alpha4/causal/components.petri", + "upstream/ASET_SEED_ALPHA4_BINDING.aset", + ): + require((ROOT / relative).is_file(), f"Runtime active source missing: {relative}") + require( + set(parse_operational_words()) == set(EXPECTED_WORDS), + "Runtime operational surface drift", + ) + check_causal_bindings() + relational = (ROOT / "runtime/alpha4/formal/RuntimeRelations.tla").read_text(encoding="utf-8") + for marker in ( + "RuntimeInvariant(s) ==", + "StartAttempt(s, t, start, result) ==", + "EndAttempt(s, t, terminal, result) ==", + 'SeedProjectionAction(result) == "STUTTER"', + "SeedProjectionEffectPermitted(result) == FALSE", + ): + require(marker in relational, f"Runtime relational marker missing: {marker}") + readme = (ROOT / "README.md").read_text(encoding="utf-8") + require( + "RESULT" in readme and "NO_RESULT" in readme, + "Runtime terminal semantics documentation drift", + ) + require( + "Recognition remains local to Seed" in readme, + "Runtime Seed authority boundary documentation missing", + ) + print("ALPHA4_RUNTIME_SUBJECT=PASS") + print("ALPHA4_RUNTIME_COMPONENT_PAIRS=8/8 PASS") + print("ALPHA4_RUNTIME_CAUSAL_BINDINGS=8/8 PASS") + print("ALPHA4_RUNTIME_SEMANTIC_PRECEDENCE=NONE") + print("ALPHA4_RUNTIME_PREDECESSOR_COMPATIBILITY=NONE") + print("ALPHA4_RUNTIME_VALIDATION=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/validate_repository_minimal.py b/tools/validate_repository_minimal.py new file mode 100644 index 0000000..1d7b800 --- /dev/null +++ b/tools/validate_repository_minimal.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +import hashlib +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +ALLOWED_ROOT_FILES = { + ".editorconfig", + ".gitattributes", + ".gitignore", + "CITATION.cff", + "LICENSE", + "NOTICE", + "README.md", + "pyproject.toml", + "requirements-ci.txt", +} +ALLOWED_ROOT_DIRS = {".github", "history", "runtime", "tests", "tools", "upstream"} +ALLOWED_ACTIVE_PATHS = { + ".editorconfig", + ".gitattributes", + ".github/workflows/verify.yml", + ".gitignore", + "CITATION.cff", + "LICENSE", + "NOTICE", + "README.md", + "history/REFERENCES.aset", + "pyproject.toml", + "requirements-ci.txt", + "runtime/alpha4/RUNTIME.aset", + "runtime/alpha4/causal/components.petri", + "runtime/alpha4/formal/OperationalRelationalPairingProofs.tla", + "runtime/alpha4/formal/RestrictedOperationalSemantics.tla", + "runtime/alpha4/formal/RuntimeRelations.tla", + "runtime/alpha4/formal/SeedBoundaryProofs.tla", + "runtime/alpha4/operational/components.forth", + "tests/test_alpha4_runtime.py", + "tests/test_alpha4_runtime_release_architecture.py", + "tests/test_alpha4_runtime_three_way_assurance.py", + "tests/test_repository_minimal.py", + "tools/__init__.py", + "tools/alpha4_runtime_assurance.py", + "tools/alpha4_runtime_causal_expression.py", + "tools/alpha4_runtime_expression_airgap.py", + "tools/alpha4_runtime_gate.py", + "tools/alpha4_runtime_paired_expression.py", + "tools/alpha4_runtime_public_release_audit.py", + "tools/alpha4_runtime_release_admission.py", + "tools/alpha4_runtime_release_gate.py", + "tools/alpha4_runtime_release_profiles.py", + "tools/alpha4_runtime_seed_extension.py", + "tools/alpha4_runtime_triangulated_expression.py", + "tools/build_alpha4_runtime_release.py", + "tools/run_alpha4_runtime_release_tlaps.py", + "tools/run_alpha4_runtime_tlaps.py", + "tools/validate_alpha4_runtime.py", + "tools/validate_repository_minimal.py", + "upstream/ASET_SEED_ALPHA4_BINDING.aset", +} + + +def require(condition: bool, message: str) -> None: + if not condition: + raise RuntimeError(message) + + +def git_paths(*args: str) -> set[str]: + result = subprocess.run( + ["git", *args, "-z"], + cwd=ROOT, + check=False, + capture_output=True, + ) + require(result.returncode == 0, f"git surface query failed: {' '.join(args)}") + return {item.decode("utf-8") for item in result.stdout.split(b"\0") if item} + + +def repository_paths() -> set[str]: + paths = git_paths("ls-files", "--cached", "--others", "--exclude-standard") + deleted = git_paths("diff", "--name-only", "--diff-filter=D") + deleted |= git_paths("diff", "--cached", "--name-only", "--diff-filter=D") + return paths - deleted + + +def relative_files(path: Path) -> set[str]: + prefix = path.relative_to(ROOT).as_posix().rstrip("/") + "/" + return {item for item in repository_paths() if item.startswith(prefix)} + + +def validate_root_surface() -> None: + paths = repository_paths() + files = {path for path in paths if "/" not in path} + dirs = {path.split("/", 1)[0] for path in paths if "/" in path} + require( + files == ALLOWED_ROOT_FILES, + f"root file surface drift: {sorted(files ^ ALLOWED_ROOT_FILES)}", + ) + require( + dirs == ALLOWED_ROOT_DIRS, + f"root directory surface drift: {sorted(dirs ^ ALLOWED_ROOT_DIRS)}", + ) + require( + paths == ALLOWED_ACTIVE_PATHS, + f"active repository surface drift: {sorted(paths ^ ALLOWED_ACTIVE_PATHS)}", + ) + + +def validate_single_readme() -> None: + readmes = sorted( + path for path in repository_paths() if Path(path).name.lower().startswith("readme") + ) + require(readmes == ["README.md"], f"README surface must be singular: {readmes}") + + +def validate_active_runtime_line() -> None: + children = {path.split("/", 2)[1] for path in repository_paths() if path.startswith("runtime/")} + require(children == {"alpha4"}, "Runtime must contain exactly one active Alpha4 line") + subject = (ROOT / "runtime/alpha4/RUNTIME.aset").read_text(encoding="utf-8") + require( + "PREDECESSOR-COMPATIBILITY NONE" in subject, + "Runtime predecessor compatibility boundary drift", + ) + require("SEMANTIC-PRECEDENCE NONE" in subject, "Runtime semantic precedence drift") + + +def validate_history_surface() -> None: + history = (ROOT / "history/REFERENCES.aset").read_text(encoding="utf-8") + require("ASET-HISTORY 1" in history, "history header missing") + state_lines = [line for line in history.splitlines() if line.startswith("STATE ")] + require( + len(state_lines) == 1 and state_lines[0].endswith(" HISTORICAL"), + "predecessor history reference missing", + ) + require("ACTIVE-SEMANTICS FALSE" in history, "history active-semantics boundary missing") + paths = repository_paths() + for prefix in ("extension/", "assurance/", "docs/", "reference/", "standards/"): + require( + not any(path.startswith(prefix) for path in paths), + f"legacy active surface present: {prefix}", + ) + + +def validate_upstream_surface() -> None: + files = relative_files(ROOT / "upstream") + require( + files == {"upstream/ASET_SEED_ALPHA4_BINDING.aset"}, + f"upstream surface drift: {sorted(files)}", + ) + + +def validate_verification_surface() -> None: + workflows = relative_files(ROOT / ".github/workflows") + require( + workflows == {".github/workflows/verify.yml"}, + f"workflow surface drift: {sorted(workflows)}", + ) + + +def validate_attribution() -> None: + readme = (ROOT / "README.md").read_text(encoding="utf-8") + require(readme.startswith("# ASET Runtime\n"), "README Runtime identity drift") + normalized_readme = " ".join(readme.split()) + require( + "bounded execution lifecycle extension for ASET Seed 0.4alpha" in normalized_readme, + "README Runtime role drift", + ) + require( + "Execution may produce material. Recognition remains local to Seed." in readme, + "README recognition boundary drift", + ) + + notice = (ROOT / "NOTICE").read_text(encoding="utf-8") + require(notice.startswith("ASET Runtime\n"), "NOTICE Runtime identity drift") + require("Copyright 2026 Dzmitry Prychyna" in notice, "copyright notice drift") + require("Attractor Set" in notice, "public author identity missing") + require( + "Original author and copyright holder: Dzmitry Prychyna." in notice, + "original authorship notice missing", + ) + require( + "Licensed under the Apache License, Version 2.0." in notice, + "NOTICE license declaration missing", + ) + + citation = (ROOT / "CITATION.cff").read_text(encoding="utf-8") + for required in ( + 'title: "ASET Runtime"', + 'version: "0.1.0-alpha.4"', + 'family-names: "Prychyna"', + 'given-names: "Dzmitry"', + 'alias: "Attractor Set"', + 'repository-code: "https://github.com/attractor-set/aset-runtime"', + "license: Apache-2.0", + ): + require(required in citation, f"citation attribution drift: {required}") + + license_bytes = (ROOT / "LICENSE").read_bytes() + license_sha256 = hashlib.sha256(license_bytes).hexdigest() + require( + license_sha256 == "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30", + "Apache-2.0 license byte identity drift", + ) + + +def main() -> int: + validate_root_surface() + validate_single_readme() + validate_active_runtime_line() + validate_history_surface() + validate_upstream_surface() + validate_verification_surface() + validate_attribution() + print("REPOSITORY_ACTIVE_SURFACE=MINIMAL") + print("REPOSITORY_LEGACY_SEMANTIC_SURFACE=ABSENT") + print("REPOSITORY_HISTORICAL_EXECUTABLE_SURFACE=ABSENT") + print("REPOSITORY_HISTORY_REFERENCES=PASS") + print("REPOSITORY_COPYRIGHT_NOTICE=PASS") + print("REPOSITORY_SINGLE_README=PASS") + print("REPOSITORY_SINGLE_ACTIVE_RUNTIME_LINE=ALPHA4") + print("REPOSITORY_SINGLE_VERIFICATION_WORKFLOW=PASS") + print("ASET_RUNTIME_REPOSITORY_MINIMAL=PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/verify_canon_package.py b/tools/verify_canon_package.py deleted file mode 100644 index c803e63..0000000 --- a/tools/verify_canon_package.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import annotations -import hashlib, json -from pathlib import Path -ROOT=Path(__file__).resolve().parents[1] -CANON=ROOT/'extension/canonical' - -def main(): - pkg=json.loads((CANON/'CANON_PACKAGE.json').read_text()) - for entry in pkg['files']: - p=CANON/entry['path'] - assert p.is_file(), entry['path'] - actual='sha256:'+hashlib.sha256(p.read_bytes()).hexdigest() - assert actual==entry['sha256'], (entry['path'], actual, entry['sha256']) - print(f"CANON_PACKAGE_VERIFY={len(pkg['files'])}/{len(pkg['files'])} PASS") -if __name__=='__main__': main() diff --git a/tools/verify_formal_candidate.py b/tools/verify_formal_candidate.py deleted file mode 100755 index e4ffc93..0000000 --- a/tools/verify_formal_candidate.py +++ /dev/null @@ -1,118 +0,0 @@ -from __future__ import annotations - -import hashlib -import json -import re -import subprocess -import sys -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -FORMAL = ROOT / "extension/canonical/formal" -ASSURANCE = ROOT / "extension/canonical/assurance" -MODEL = ROOT / "extension/canonical/source/worker-model.json" -BINDING = ROOT / "upstream/ASET_SEED_BINDING.json" - - -def sha(path: Path) -> str: - return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest() - - -def theorem_present(path: Path, name: str) -> bool: - text = path.read_text(encoding="utf-8") - return re.search(rf"^THEOREM {re.escape(name)} ==\s*$", text, re.MULTILINE) is not None - - -def main() -> int: - errors: list[str] = [] - result = subprocess.run( - [sys.executable, str(ROOT / "tools/generate_canon_tla_projection.py"), "--check"], - cwd=ROOT, - text=True, - check=False, - ) - if result.returncode != 0: - errors.append("generated canon projection is stale") - - binding = json.loads(BINDING.read_text(encoding="utf-8")) - if binding.get("seed_release_commit") != "633c130187b2a2bb42f24cfd66662d475de385d2": - errors.append("pinned Seed release commit mismatch") - - relations = [ - ASSURANCE / "canon-tla-refinement.json", - ASSURANCE / "seed-refinement.json", - ASSURANCE / "lifecycle-proof-candidate.json", - ] - for path in relations: - if not path.is_file(): - errors.append(f"missing relation: {path.relative_to(ROOT)}") - - if not errors: - canon = json.loads((ASSURANCE / "canon-tla-refinement.json").read_text(encoding="utf-8")) - seed = json.loads((ASSURANCE / "seed-refinement.json").read_text(encoding="utf-8")) - life = json.loads((ASSURANCE / "lifecycle-proof-candidate.json").read_text(encoding="utf-8")) - - if canon.get("status") not in {"PROOF_CANDIDATE_MATERIALIZED", "MECHANICALLY_PROVED"}: - errors.append("canon relation status mismatch") - if canon.get("status") == "MECHANICALLY_PROVED": - evidence = canon.get("proof_evidence", {}) - evidence_path = ROOT / evidence.get("path", "") - if evidence.get("status") != "MECHANICALLY_PROVED" or not evidence_path.is_file(): - errors.append("canon mechanically-proved evidence binding mismatch") - if canon.get("source_model", {}).get("sha256") != sha(MODEL): - errors.append("canon relation source digest mismatch") - for entry, path in [ - (canon.get("generated_projection", {}), FORMAL / "WorkerCanonProjection.tla"), - (canon.get("target_model", {}), FORMAL / "WorkerLifecycle.tla"), - (canon.get("proof_candidate", {}), FORMAL / "WorkerCanonRefinementProofs.tla"), - ]: - if entry.get("sha256") != sha(path): - errors.append(f"canon relation digest mismatch: {path.name}") - - if seed.get("status") not in {"PROOF_CANDIDATE_MATERIALIZED", "MECHANICALLY_PROVED"}: - errors.append("seed relation status mismatch") - if seed.get("status") == "MECHANICALLY_PROVED": - evidence = seed.get("proof_evidence", {}) - evidence_path = ROOT / evidence.get("path", "") - if evidence.get("status") != "MECHANICALLY_PROVED" or not evidence_path.is_file(): - errors.append("seed mechanically-proved evidence binding mismatch") - - if seed.get("upstream_seed", {}).get("sha256") != "sha256:1c0ebb27ed52da289f0981dcb11b61b6a7fc5c4a030ba434ae0b1d53b286b926": - errors.append("SeedResolution digest binding mismatch") - for entry, path in [ - (seed.get("mapping_candidate", {}), FORMAL / "WorkerSeedStuttering.tla"), - (seed.get("proof_candidate", {}), FORMAL / "WorkerSeedStutteringProofs.tla"), - ]: - if entry.get("sha256") != sha(path): - errors.append(f"seed relation digest mismatch: {path.name}") - - if life.get("model", {}).get("sha256") != sha(FORMAL / "WorkerLifecycle.tla"): - errors.append("lifecycle model digest mismatch") - if life.get("proof", {}).get("sha256") != sha(FORMAL / "WorkerLifecycleProofs.tla"): - errors.append("lifecycle proof digest mismatch") - - theorem_sets = [ - (FORMAL / "WorkerLifecycleProofs.tla", life.get("proof", {}).get("final_theorems", [])), - (FORMAL / "WorkerCanonRefinementProofs.tla", canon.get("proof_candidate", {}).get("final_theorems", [])), - (FORMAL / "WorkerSeedStutteringProofs.tla", seed.get("proof_candidate", {}).get("final_theorems", [])), - ] - for path, names in theorem_sets: - for name in names: - if not theorem_present(path, name): - errors.append(f"missing theorem {name} in {path.name}") - - if errors: - print("WORKER_FORMAL_CANDIDATE_VERIFY=FAIL") - for error in errors: - print(f"WORKER_FORMAL_CANDIDATE_ERROR={error}") - return 1 - print("WORKER_FORMAL_CANDIDATE_IDENTITY=PASS") - print("WORKER_CANON_TO_TLA_CANDIDATE=READY") - print("WORKER_TLAPS_SAFETY_CANDIDATE=READY") - print("WORKER_SEED_REFINEMENT_CANDIDATE=READY") - print("WORKER_FORMAL_CANDIDATE_VERIFY=PASS") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/upstream/ASET_SEED_ALPHA4_BINDING.aset b/upstream/ASET_SEED_ALPHA4_BINDING.aset new file mode 100644 index 0000000..5d5da4d --- /dev/null +++ b/upstream/ASET_SEED_ALPHA4_BINDING.aset @@ -0,0 +1,27 @@ +ASET-SEED-BINDING 1 ASET-SEED-0.4-ALPHA CONTENT-ADDRESSED +REPOSITORY https://github.com/attractor-set/aset-seed +RELEASE-TAG seed-0.4alpha-3way +COMPATIBILITY 0.3 NONE +SEMANTIC-PRECEDENCE NONE + +RELEASE-TREE sha256:136e174a987ee961877472eecac3903e4f1e54a68059815e9b84e8fb966e00cc +RELEASE-ARCHIVE sha256:4170d9111c353c3607cf9ada3398c15007acfed7b2d486f5376c72d3f13ed331 +PROFILE-TREE sha256:fb75339485027ad1529714e1793669c4850390fe54a586864772a13ab90c094e +PROFILE-ARCHIVE sha256:790588c145a390da6d47ac08901945253904aa053d170bfd35f6fb20dd1ae5a1 +COMPANION ENGLISH en/Seed.md sha256:8d44ddd7d244b385de5e37bd9429f9509680775593330a258f97ff178c5fb7b9 +COMPANION PYTHON python/aset_seed_alpha4.py sha256:fb71c154b8e6ee05986b6d203852ea1a964176ecb4e9753a51119dcbb9332071 + +ASSURANCE-BASE OPERATIONAL seed/alpha4/operational/components.forth PRESERVE-UNKNOWN,PRESERVE-ALLOW,PRESERVE-BLOCK +ASSURANCE-BASE RELATIONAL seed/alpha4/formal/ComponentRelations.tla PreserveUnknown,PreserveAllow,PreserveBlock +ASSURANCE-BASE CAUSAL seed/alpha4/causal/components.petri PRESERVE-UNKNOWN,PRESERVE-ALLOW,PRESERVE-BLOCK + +SOURCE seed/alpha4/SEED.aset sha256:ba837740d053affbf5cd28defeb5cfaa5c9dea6a0879ddd3e41287404e514854 +SOURCE seed/alpha4/operational/components.forth sha256:669174b785d97e7391dc25383f93db3574e4bf680ae9fcd8617d567eb08979da +SOURCE seed/alpha4/formal/RestrictedOperationalSemantics.tla sha256:5d2e104351a4a3f3ff3cd9dc509c020eabb78baf94878e1c12f58faa34a2b080 +SOURCE seed/alpha4/formal/ComponentRelations.tla sha256:3980d68ef27a505fd116c3bf374f20b9bdd49572352f0d50746374930893b3cb +SOURCE seed/alpha4/formal/OperationalRelationalPairingProofs.tla sha256:c164b8ee47f7fe6278f3bfe7e72c96d3e5d2ad9ad5ae15f4fcd0af36d9c6802c +SOURCE seed/alpha4/formal/ComponentCompositionProofs.tla sha256:7578230f18748c5a14e5aa6037ae2eb1ac2e6cd10a917ecf0a745b5071f1db2b +SOURCE seed/alpha4/causal/components.petri sha256:b29fc759a9344100f34dec44e9d06113d346030ffcdafab78a70ca682f309037 +SOURCE theory/local-recognition/formal/LocalRecognitionAlgebra.tla sha256:f953519975c394e05ed3e6ecce0f7727005284ea61aadf757a2f1c5d1b6ec837 + +RUNTIME-PROJECTION ALL-RUNTIME-TRANSITIONS PRESERVE-SEED-STATE diff --git a/upstream/ASET_SEED_BINDING.json b/upstream/ASET_SEED_BINDING.json deleted file mode 100644 index 3968d66..0000000 --- a/upstream/ASET_SEED_BINDING.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "binding_mode": "PINNED_COMPATIBILITY_STANDARD", - "canon_id": "ASET-SEED-RESOLUTION-CANON-0.3-ALPHA1", - "canon_package_digest": "sha256:c5d48a418466ea7a60fccb7161adbd5ad568174bbc9a28fc03fd7e6e77955d31", - "canon_version": "0.3.0-alpha.1", - "compatibility": "STRICT_EXTENSION_NO_WEAKENING", - "compatibility_standard": "ASET-SEED-COMPATIBILITY-STANDARD@seed-0.3.0-alpha.3", - "compatibility_standard_profile": "ASET-SEED-COMPATIBILITY-STANDARD-V1", - "document_type": "aset-seed-upstream-binding", - "implementation_precedence": "NONE", - "schema_version": 2, - "seed_conformance_kit_sha256": "sha256:5ecf9b93377a062b8772b4b4b44b4d76a0997d8ba98e8711e717456abbe583db", - "seed_release_commit": "633c130187b2a2bb42f24cfd66662d475de385d2", - "seed_release_tag": "seed-0.3.0-alpha.3", - "upstream_repository": "https://github.com/attractor-set/ASET" -}