From ec23f4f24cd5dce7c32f703afa3204623eeb1bc0 Mon Sep 17 00:00:00 2001 From: Phillip Linstrum Date: Mon, 17 Aug 2026 21:44:16 -0400 Subject: [PATCH] Publish R1.0.1 packaging correction records --- PUBLICATION_MANIFEST.json | 66 +- PUBLIC_RELEASE_STATUS_2026-08-17.json | 59 + README.md | 147 ++- RELEASES.md | 79 +- docs/VERIFY_RELEASES.md | 64 +- ...E-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json | 40 + ....2.0_BUILD_AND_TEST_REPORT_2026-08-17.json | 25 + ...BLIC_RELEASE_AUTHORIZATION_2026-08-17.json | 26 + ..._MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json | 47 + ...INNER_EXACT_HASH_ADMISSION_2026-08-17.json | 22 + ...UTER_RELEASE_AUTHORIZATION_2026-08-17.json | 26 + governance/README.md | 30 + release-notes/GENERIC_MYTH_SIDECAR_v0.2.0.md | 69 ++ .../PROJECT_SHADOW_R1_0_1_2026-08-17.md | 94 ++ tests/test_verify_repository_evidence.py | 99 +- tools/verify_repository_evidence.py | 1067 +++++++++++++++-- 16 files changed, 1752 insertions(+), 208 deletions(-) create mode 100644 PUBLIC_RELEASE_STATUS_2026-08-17.json create mode 100644 governance/CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json create mode 100644 governance/GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json create mode 100644 governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json create mode 100644 governance/PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json create mode 100644 governance/R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json create mode 100644 governance/R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json create mode 100644 release-notes/GENERIC_MYTH_SIDECAR_v0.2.0.md create mode 100644 release-notes/PROJECT_SHADOW_R1_0_1_2026-08-17.md diff --git a/PUBLICATION_MANIFEST.json b/PUBLICATION_MANIFEST.json index 2436496..f13725f 100644 --- a/PUBLICATION_MANIFEST.json +++ b/PUBLICATION_MANIFEST.json @@ -1,5 +1,12 @@ { - "authorization_receipt": "governance/RELEASE_AUTHORIZATION_2026-08-14.json", + "current_reference": { + "publication_state": "READY_TO_PUBLISH", + "tag": "r1.0.1-2026-08-17" + }, + "expected_github_latest_tag": { + "postpublication": "r1.0.1-2026-08-17", + "prepublication": "r1-2026-08-14" + }, "nonclaims": { "certification_claimed": false, "efficacy_claimed": false, @@ -8,7 +15,9 @@ "production_authorized": false, "safety_claimed": false }, - "release_identity": "PROJECT SHADOW 1.0 / R1 REFERENCE / BETA-ACTIVE-TESTING / PRELIVE", + "publication_phase": "PREPUBLICATION", + "prepublication_state": "READY_TO_PUBLISH", + "release_identity": "PROJECT SHADOW 1.0.1 / R1 REFERENCE / BETA-ACTIVE-TESTING / PRELIVE", "releases": [ { "asset": { @@ -18,8 +27,10 @@ "sha256": "3c8c8c0d3d9582c76b685c1b685260cc8179478ab310037c858b46257aa314c7" }, "canonical_r1": false, + "current": false, "enabled_by_default": false, "order": 1, + "publication_state": "PUBLISHED_HISTORICAL", "role": "OPTIONAL_EXTERNAL_RESEARCH_SIDECAR", "tag": "myth-v0.3.4", "title": "Project Shadow Myth Sidecar v0.3.4 — Optional External Research" @@ -32,12 +43,61 @@ "sha256": "2f8fe1530b6a83294d15011df95853aaecf08fa4dba756f0c2e91dd089e1b1ec" }, "canonical_r1": true, + "current": false, "order": 2, + "publication_state": "PUBLISHED_HISTORICAL_SUPERSEDED", "role": "R1_REFERENCE", "tag": "r1-2026-08-14", "title": "Project Shadow 1.0 — R1 Reference (PRELIVE)" + }, + { + "asset": { + "bytes": 1428812, + "download_url": "https://github.com/PauseBeforeHarmProtocol/Project-Shadow/releases/download/myth-v0.3.5/Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "filename": "Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "sha256": "2b55867fe7c502a0defd8d6f2e9b53fbd1caaf1b0f225a438bd45b04a3e7bae2" + }, + "canonical_r1": false, + "current": true, + "enabled_by_default": false, + "order": 3, + "publication_state": "PUBLISHED", + "role": "OPTIONAL_FULL_CANON_COMPANION", + "tag": "myth-v0.3.5", + "title": "Project Shadow Full-Canon Myth Sidecar v0.3.5 — Optional Public Companion" + }, + { + "asset": { + "bytes": 93676, + "download_url": "https://github.com/PauseBeforeHarmProtocol/Project-Shadow/releases/download/generic-myth-v0.2.0/Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "filename": "Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "sha256": "6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf" + }, + "canonical_r1": false, + "current": true, + "enabled_by_default": false, + "order": 4, + "publication_state": "READY_TO_PUBLISH", + "role": "OPTIONAL_GENERIC_COMPANION", + "tag": "generic-myth-v0.2.0", + "title": "Project Shadow Generic Myth Sidecar v0.2.0 — Optional Public Companion" + }, + { + "asset": { + "bytes": 5731663, + "download_url": "https://github.com/PauseBeforeHarmProtocol/Project-Shadow/releases/download/r1.0.1-2026-08-17/Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip", + "filename": "Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip", + "sha256": "6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1" + }, + "canonical_r1": true, + "current": true, + "order": 5, + "publication_state": "READY_TO_PUBLISH", + "role": "R1_REFERENCE_CORRECTED", + "tag": "r1.0.1-2026-08-17", + "title": "Project Shadow 1.0.1 — R1 Reference Packaging Correction (PRELIVE)" } ], "repository": "PauseBeforeHarmProtocol/Project-Shadow", - "schema": "project-shadow.publication-manifest.v1" + "schema": "project-shadow.publication-manifest.v2" } diff --git a/PUBLIC_RELEASE_STATUS_2026-08-17.json b/PUBLIC_RELEASE_STATUS_2026-08-17.json new file mode 100644 index 0000000..3a435ea --- /dev/null +++ b/PUBLIC_RELEASE_STATUS_2026-08-17.json @@ -0,0 +1,59 @@ +{ + "capa": { + "effectiveness_verified": false, + "id": "PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001", + "status": "IMPLEMENTED_PENDING_EFFECTIVENESS" + }, + "current_reference": { + "active_descendant_count": 27, + "final_outer_identity_bound": true, + "inner_exact_hash_admitted": true, + "myth_payload_required": false, + "publication_state": "READY_TO_PUBLISH", + "tag": "r1.0.1-2026-08-17", + "zero_operational_descendant_bytes_changed": true + }, + "derived_record": true, + "generic_myth": { + "canonical_r1_component": false, + "default_off": true, + "final_hardened_identity_bound": true, + "publication_authorization_recorded": true, + "publication_state": "READY_TO_PUBLISH", + "required_for_r1": false, + "tag": "generic-myth-v0.2.0", + "terminal_only": true + }, + "historical_boundary": { + "affected_release_mutated": false, + "affected_release_sha256": "2f8fe1530b6a83294d15011df95853aaecf08fa4dba756f0c2e91dd089e1b1ec", + "affected_release_tag": "r1-2026-08-14", + "affected_release_treatment": "IMMUTABLE_HISTORICAL_EVIDENCE_SUPERSEDED_BY_SEPARATELY_VERSIONED_SUCCESSOR", + "finding": "A nested Generic Myth v0.1.1 member was physically present while its own metadata classified it as non-public and excluded from public manufacture." + }, + "nonclaims": { + "certification_claimed": false, + "efficacy_claimed": false, + "legal_compliance_claimed": false, + "operational_deployment_authorized": false, + "production_authorized": false, + "safety_claimed": false + }, + "publication_phase": "PREPUBLICATION", + "published_optional_companion": { + "default_off": true, + "filename": "Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "sha256": "2b55867fe7c502a0defd8d6f2e9b53fbd1caaf1b0f225a438bd45b04a3e7bae2", + "tag": "myth-v0.3.5" + }, + "schema": "project-shadow.current-release-status.v1", + "source_records": [ + "PUBLICATION_MANIFEST.json", + "governance/PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json", + "governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json", + "governance/R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json", + "governance/R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json", + "governance/CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json" + ], + "warning": "READY_TO_PUBLISH is still PREPUBLICATION. Exact-hash authorities are recorded, but public release, anonymous redownload verification, six-site effectiveness checks, and CAPA closure have not yet occurred." +} diff --git a/README.md b/README.md index 9aa4ded..ecd3232 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,23 @@ > **Mixed-rights repository.** This repository is not one blanket > Apache-2.0 work. Apache-2.0 applies only to eligible original software; > CC BY 4.0 applies only to eligible original documentation and -> machine-readable controls. Preserved governance evidence and both release +> machine-readable controls. Preserved governance evidence and release > archives retain their own attached or path-scoped terms. Read > [`RIGHTS.md`](RIGHTS.md) before reuse. -**PROJECT SHADOW 1.0 / R1 REFERENCE / BETA-ACTIVE-TESTING / PRELIVE** +**PROJECT SHADOW 1.0.1 / R1 REFERENCE / BETA-ACTIVE-TESTING / PRELIVE** -This clean-history repository is the public landing surface for two exact, -separately distributed Project Shadow artifacts. It contains release metadata, -governance evidence, integrity instructions, and nonclaim boundaries. It does -not contain the release ZIPs in Git history; those are attached to their -respective GitHub Releases. +Project Shadow 1.0.1 is a packaging-boundary correction in preparation. Its +release design removes Myth from the R1 runtime-family package while preserving +all 27 active operational descendants byte-for-byte. The Generic Myth v0.2.0 +identity is frozen and authorized for separate publication, the exact Myth-free +inner family is admitted, and the final R1.0.1 outer identity is frozen. The +outer archive now has its own exact-hash publication authorization. The staged +repository is ready to publish, but no new artifact is represented as public +until the upload exists and can be independently redownloaded. + +No pending artifact is represented as published. The machine-readable phase is +[`PREPUBLICATION`](PUBLIC_RELEASE_STATUS_2026-08-17.json). ## Current contact @@ -21,76 +27,91 @@ All new Project Shadow correspondence should use **`projectshadowqa@protonmail.com`**. Use `[CORRECTION]`, `[CAPA]`, `[SECURITY]`, `[RESEARCH]`, `[PRESS]`, -`[COLLABORATION]`, or `[CONDUCT]` in the subject line. The full intake and -privacy rules are in -[`CONTACT_AND_CORRECTIONS.md`](CONTACT_AND_CORRECTIONS.md), with a -machine-readable status in -[`PUBLIC_CONTACT_STATUS_2026-08-17.json`](PUBLIC_CONTACT_STATUS_2026-08-17.json). +`[COLLABORATION]`, or `[CONDUCT]` in the subject line. See +[`CONTACT_AND_CORRECTIONS.md`](CONTACT_AND_CORRECTIONS.md). Historical addresses and certificate identities may remain inside exact-hash, -signed, frozen, or quoted evidence. They are preserved for custody and -verification and are not current contact routes. - -## Exact releases - -| Artifact | Role | Bytes | SHA-256 | -|---|---|---:|---| -| `Project_Shadow_R1_Public_Release_Candidate_2026-08-14.zip` | Canonical R1 reference release | 7,679,812 | `2f8fe1530b6a83294d15011df95853aaecf08fa4dba756f0c2e91dd089e1b1ec` | -| `Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.4_OPTIONAL_EXTERNAL_RESEARCH_2026-08-14.zip` | Optional external research sidecar; separate from R1 and default off | 1,418,194 | `3c8c8c0d3d9582c76b685c1b685260cc8179478ab310037c858b46257aa314c7` | - -The R1 filename retains the word `Candidate` because publication preserves the -authorized bytes exactly. The archive's internal status was written before the -separate exact-hash authorization. That external authorization is recorded in -[`governance/RELEASE_AUTHORIZATION_2026-08-14.json`](governance/RELEASE_AUTHORIZATION_2026-08-14.json). -The archive itself must not be rewritten to change its internal status. -The resolved, machine-readable state above that preserved gate is recorded in -[`PUBLIC_RELEASE_STATUS_2026-08-14.json`](PUBLIC_RELEASE_STATUS_2026-08-14.json). -The historical unsigned commit/tag facts and the later commit-bound attestation -are recorded in -[`governance/POST_PUBLICATION_ATTESTATION_2026-08-15.json`](governance/POST_PUBLICATION_ATTESTATION_2026-08-15.json). - -## Download order and separation - -The optional sidecar is published first under tag `myth-v0.3.4`. The canonical -R1 release is published last under tag `r1-2026-08-14` so that R1 is the latest -release. The sidecar is not embedded in R1, is not an admitted R1 descendant, -does not claim R1 conformance, and is distributed under its own mixed-rights -terms. +signed, frozen, or quoted evidence. They are custody evidence, not current +contact routes. + +## Release state + +| Artifact | State | Boundary | +|---|---|---| +| R1, 2026-08-14 | Preserved historical release; superseded as the current reference | Contains a historically nested Generic Myth v0.1.1 member whose own metadata was non-public; the released bytes remain immutable evidence | +| Full-Canon Myth v0.3.4 | Preserved historical optional sidecar | External, default off, nonauthorizing | +| Full-Canon Myth v0.3.5 | Published optional companion | External, default off, terminal-only, nonauthorizing | +| Generic Myth v0.2.0 | Ready to publish; not yet published | Separate optional companion; never embedded in R1 | +| R1.0.1 | Ready to publish; not yet published | Corrected current reference; publication contract requires zero Myth payload | + +The exact historical, published, authorized, and frozen identities are in +[`PUBLICATION_MANIFEST.json`](PUBLICATION_MANIFEST.json). A concrete identity +does not by itself authorize publication; consult its authority record and +publication state. + +## Myth is optional + +Project Shadow does not require Myth. Both Myth companions are separate, +explicitly enabled, default-off presentation layers. Neither can provide +evidence, authority, a gate result, score, routing input, tool argument, +approval, or action. No companion is authorized for production or operational +deployment. + +- **Generic Myth Sidecar v0.2.0** is a generic mnemonic presentation with no + named third-party expressive material. Its frozen exact-hash build has passed + final tests and is authorized for separate publication on GitHub and Hugging + Face; it is not yet represented as published. +- **Full-Canon Myth Sidecar v0.3.5** is an optional mixed-rights interpretive + companion published separately from R1. + +R1.0.1 will contain neither sidecar. The August 14 bytes are preserved rather +than silently edited; the correction is a separately versioned successor. ## Verify before use -Verify the downloaded ZIP's byte count and SHA-256 before extracting it. Then -run the current repository verifier against the outer ZIP so its prospective -archive-preflight limits apply, followed by the frozen verifier embedded in the -extracted package. Exact Windows, macOS, and Linux instructions are in -[`docs/VERIFY_RELEASES.md`](docs/VERIFY_RELEASES.md). +Run the repository evidence verifier in the phase you intend to validate: + +```bash +python3 -I -S -B tools/verify_repository_evidence.py --phase prepublication +``` + +Postpublication mode fails closed until every placeholder is replaced, both +new release assets have anonymous redownload evidence, and the CAPA is closed +with effectiveness evidence: + +```bash +python3 -I -S -B tools/verify_repository_evidence.py --phase postpublication +``` + +Exact Windows, macOS, and Linux instructions are in +[`docs/VERIFY_RELEASES.md`](docs/VERIFY_RELEASES.md). The historical +[`tools/verify_public_release.py`](tools/verify_public_release.py) remains +pinned to the August 14 artifact; it is not silently retargeted to R1.0.1. + +## CAPA state + +CAPA `PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001` is +**IMPLEMENTED_PENDING_EFFECTIVENESS**. Closure requires exact public GitHub and +Hugging Face redownload identity checks for the corrected artifacts plus live +verification of the six Project Shadow public sites. See the +[`CAPA record`](governance/CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json). ## Scope boundary -Public release is authorized only within `PROJECT SHADOW 1.0 / R1 REFERENCE / -BETA-ACTIVE-TESTING / PRELIVE`. This release does not authorize production or -operational deployment, efficacy, safety, certification, or legal-compliance -claims. See [`docs/SCOPE_AND_NONCLAIMS.md`](docs/SCOPE_AND_NONCLAIMS.md). +This work remains `BETA-ACTIVE-TESTING / PRELIVE`. It does not authorize +production or operational deployment and does not claim efficacy, safety, +certification, or legal compliance. See +[`docs/SCOPE_AND_NONCLAIMS.md`](docs/SCOPE_AND_NONCLAIMS.md). Current sole-maintainer authority, the absence of a designated successor, the non-authority of AI and automation, and the fail-closed stale-after date are recorded in [`governance/MAINTAINER_CONTINUITY.md`](governance/MAINTAINER_CONTINUITY.md). -## Rights - -The R1 archive and the external sidecar each contain controlling notices, -licenses, manifests, and provenance records. The repository does not apply an -outer blanket license to either archive and does not grant third-party rights, -affiliation, endorsement, or legal clearance. Read [`RIGHTS.md`](RIGHTS.md) -before redistribution or adaptation. - ## Participate and challenge Technical criticism, correction evidence, false positives, false negatives, -and adverse results are welcome. Outside criticism is evidence to evaluate, -not hostility to suppress. Start with [`CONTRIBUTING.md`](CONTRIBUTING.md), use -the matching issue form, or email `projectshadowqa@protonmail.com` with the -appropriate subject prefix. Report vulnerabilities privately under -[`SECURITY.md`](SECURITY.md); never place exploit details or private evidence -in a public issue. +and adverse results are welcome. Start with +[`CONTRIBUTING.md`](CONTRIBUTING.md), use the matching issue form, or email the +current contact with the appropriate subject prefix. Report vulnerabilities +privately under [`SECURITY.md`](SECURITY.md). diff --git a/RELEASES.md b/RELEASES.md index 6c94e3e..1abf98e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,52 +1,53 @@ # Releases -Release assets are intentionally kept out of Git history and attached to two -separate GitHub Releases. +Release assets are kept out of Git history and attached to separate GitHub +Releases. Automatically generated source ZIP/TAR archives are repository +snapshots, not Project Shadow release artifacts. -1. `myth-v0.3.4` — **Project Shadow Myth Sidecar v0.3.4 — Optional External Research** -2. `r1-2026-08-14` — **Project Shadow 1.0 — R1 Reference (PRELIVE)** +## Current release plan -The sidecar was published first. R1 was published last and is the latest -release. Neither release is marked as a GitHub prerelease: both exact artifacts -are publicly released, while the controlling `BETA-ACTIVE-TESTING / PRELIVE` -scope label explicitly withholds production and operational authority. That -scope label must remain visible in the R1 title and notes. +Publication phase: **PREPUBLICATION**. -Always download the explicitly named release assets. GitHub's automatically -generated source-code ZIP and TAR archives are repository snapshots, not the -authorized R1 or sidecar artifacts. +1. `generic-myth-v0.2.0` — Generic Myth Sidecar v0.2.0, optional public + companion. Its final identity is frozen, its final tests pass, and its exact + hash is authorized for separate GitHub and Hugging Face publication. +2. `r1.0.1-2026-08-17` — Project Shadow 1.0.1 R1 reference packaging + correction. Its exact inner is admitted and its deterministic outer build is + frozen and separately exact-hash authorized. It is ready to publish, not yet + published. -Exact filenames, sizes, hashes, and ordering are machine-readable in -[`PUBLICATION_MANIFEST.json`](PUBLICATION_MANIFEST.json). +The Generic sidecar must be published first. R1.0.1 must be published last so +the corrected R1 becomes the latest release. Neither pending release is marked +published in repository evidence before the public asset exists. -## Current contact +## Existing public releases -For release questions, corrections, CAPA proposals, research, press, -collaboration, or security routing, use `projectshadowqa@protonmail.com` with -the subject prefix described in -[`CONTACT_AND_CORRECTIONS.md`](CONTACT_AND_CORRECTIONS.md). - -Historical addresses and signing identities in exact-hash archives, signed -records, certificates, tags, commits, and verification commands remain -preserved evidence. They are not current correspondence routes. +- `myth-v0.3.5` — Full-Canon Myth Sidecar v0.3.5, optional public companion. +- `myth-v0.3.4` — preserved historical optional research sidecar. +- `r1-2026-08-14` — preserved historical R1 release. Its bytes are immutable; + R1.0.1 supersedes it as the current reference because the old outer package + included a nested Generic Myth v0.1.1 member carrying non-public metadata. -## Prospective custody procedure +Historical release notes and governance records remain in place. Nothing in +the 2026-08-17 correction back-writes the August 14 authorization, status, +redownload receipt, tags, or archive. -The two 2026-08-14 tags are preserved lightweight tags pointing to the original -public commit. They are historical facts and must not be rewritten merely to -retrofit later controls. +## Required publication sequence -For every future release: +1. Preserve the recorded Generic, inner, and outer exact-hash authorities + without broadening them. +2. Run `tools/verify_repository_evidence.py --phase prepublication`. +3. Publish Generic v0.2.0, then R1.0.1. +4. Anonymously redownload the GitHub and Hugging Face assets and verify exact + byte counts and SHA-256 values. +5. Verify all six public sites, add the redownload record, close the CAPA, and + run postpublication mode. -1. land the release record through the protected `main` pull-request and CI - path; -2. create a signed annotated tag from the intended verified commit; -3. verify that tag locally before pushing it; -4. publish exact-hash-authorized assets without replacing them afterward; and -5. anonymously download each public asset and record its byte count and - SHA-256. +## Prospective custody procedure -Example maintainer commands: +Future release tags should be signed annotated tags from the intended verified +commit. Release assets must not be replaced after publication. GitHub release +immutability and tag protection do not rewrite the original August 14 tags. ```bash git tag -s -m "" @@ -54,6 +55,6 @@ git tag -v git push origin ``` -A release-tag ruleset must protect the release-tag patterns prospectively. -GitHub's release-immutability setting is also prospective and does not rewrite -or retroactively relabel the two original releases. +For questions or corrections, use `projectshadowqa@protonmail.com` with the +subject prefix described in +[`CONTACT_AND_CORRECTIONS.md`](CONTACT_AND_CORRECTIONS.md). diff --git a/docs/VERIFY_RELEASES.md b/docs/VERIFY_RELEASES.md index 4991243..bbe9c84 100644 --- a/docs/VERIFY_RELEASES.md +++ b/docs/VERIFY_RELEASES.md @@ -1,4 +1,4 @@ -# Verify the exact Project Shadow releases +# Verify Project Shadow releases by lifecycle phase For release-verification questions, corrections, or security reports, use `projectshadowqa@protonmail.com` with the appropriate subject prefix from @@ -7,18 +7,62 @@ For release-verification questions, corrections, or security reports, use Do not rely on a filename alone. Verify both byte count and SHA-256 before extracting an archive. -## Expected identities +## Current phase + +The repository is in `PREPUBLICATION` for Generic Myth v0.2.0 and R1.0.1. +Their final identities are concrete and frozen. Generic Myth v0.2.0 has scoped +exact-hash publication authorization, and the exact Myth-free R1.0.1 inner is +admitted. The final outer R1.0.1 archive also has its separate exact-hash +publication authorization. The repository is `READY_TO_PUBLISH`, which is +still a prepublication state; it does not assert that the public assets exist. + +Validate the repository state before any upload: + +```bash +python3 -I -S -B tools/verify_repository_evidence.py --phase prepublication +``` + +Postpublication mode must fail until final identities, exact-hash +authorizations, anonymous redownload evidence, and CAPA closure are all +present: + +```bash +python3 -I -S -B tools/verify_repository_evidence.py --phase postpublication +``` + +## Published and preserved exact identities | File | Bytes | SHA-256 | |---|---:|---| | `Project_Shadow_R1_Public_Release_Candidate_2026-08-14.zip` | 7,679,812 | `2f8fe1530b6a83294d15011df95853aaecf08fa4dba756f0c2e91dd089e1b1ec` | | `Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.4_OPTIONAL_EXTERNAL_RESEARCH_2026-08-14.zip` | 1,418,194 | `3c8c8c0d3d9582c76b685c1b685260cc8179478ab310037c858b46257aa314c7` | +| `Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip` | 1,428,812 | `2b55867fe7c502a0defd8d6f2e9b53fbd1caaf1b0f225a438bd45b04a3e7bae2` | + +The August 14 R1 identity is preserved as immutable historical evidence. It is +not the corrected current reference because its nested runtime-family package +included Generic Myth v0.1.1 carrying non-public metadata. Do not edit or +silently replace the historical asset. + +## Frozen prepublication identities + +| File | Bytes | SHA-256 | +|---|---:|---| +| `Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip` | 93,676 | `6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf` | +| `Project_Shadow_R1.0.1_Runtime_Family_Myth_Decoupled_2026-08-17.zip` | 5,463,189 | `c8c32b12432c954b1a6f852c0c9f81bbbd40167e936be057d4c3de1a0aa3a623` | +| `Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip` | 5,731,663 | `6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1` | + +The Generic identity has scoped GitHub/Hugging Face publication authorization. +The inner identity has the maintainer's scoped packaging admission, which +explicitly does not authorize publication. The outer identity is recorded only +with a separate exact-hash authorization covering GitHub, Hugging Face, the +verified repository update, and six GPT Site updates. Neither authority permits +production or operational deployment. ## Windows PowerShell ```powershell $r1 = ".\Project_Shadow_R1_Public_Release_Candidate_2026-08-14.zip" -$myth = ".\Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.4_OPTIONAL_EXTERNAL_RESEARCH_2026-08-14.zip" +$myth = ".\Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip" (Get-Item -LiteralPath $r1).Length (Get-FileHash -LiteralPath $r1 -Algorithm SHA256).Hash.ToLowerInvariant() @@ -33,13 +77,13 @@ $myth = ".\Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.4_OPTIONAL_EXTERNAL_RESEA wc -c Project_Shadow_R1_Public_Release_Candidate_2026-08-14.zip sha256sum Project_Shadow_R1_Public_Release_Candidate_2026-08-14.zip -wc -c Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.4_OPTIONAL_EXTERNAL_RESEARCH_2026-08-14.zip -sha256sum Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.4_OPTIONAL_EXTERNAL_RESEARCH_2026-08-14.zip +wc -c Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip +sha256sum Project_Shadow_Full_Canon_Myth_Sidecar_v0.3.5_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip ``` On macOS, `shasum -a 256` may be used when `sha256sum` is unavailable. -## Apply the current outer-archive preflight before extraction +## Historical August 14 outer-archive preflight The exact R1 ZIP is preserved and was not rewritten after publication. Its embedded verifier is therefore also a frozen historical release artifact and @@ -179,9 +223,13 @@ The R1 archive's embedded verifier is the controlling packaged copy for the historical release. The current repository verifier should be used first on the outer ZIP for the later archive-preflight protections documented above. -## Verify the optional sidecar after extraction +## Verify optional sidecars after extraction + +Full-Canon v0.3.5 and Generic v0.2.0 are separate optional companions. Neither +is embedded in or required by R1.0.1. Use the verification-only tool shipped in +the exact sidecar package after its final identity is confirmed. -From the extracted sidecar root: +From an extracted Full-Canon sidecar root: ```bash python3 -I -S -B tools/verify_package.py . diff --git a/governance/CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json b/governance/CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json new file mode 100644 index 0000000..b96addf --- /dev/null +++ b/governance/CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json @@ -0,0 +1,40 @@ +{ + "capa_id": "PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001", + "closure": { + "closed_at": null, + "effectiveness_verified": false, + "verification_record": null + }, + "corrective_action": { + "affected_august_14_release_mutated": false, + "generic_myth_moved_to_separate_optional_sidecar": true, + "r1_0_1_requires_zero_embedded_myth_payload": true, + "r1_0_1_versioned_successor_required": true + }, + "effectiveness_criteria": [ + "FINAL_GENERIC_AND_R1_0_1_IDENTITIES_BOUND_AND_AUTHORIZED", + "GITHUB_ASSETS_ANONYMOUSLY_REDOWNLOADED_AND_EXACTLY_VERIFIED", + "HUGGING_FACE_MIRRORS_ANONYMOUSLY_REDOWNLOADED_AND_EXACTLY_VERIFIED", + "R1_0_1_RECURSIVE_VERIFIER_CONFIRMS_ZERO_MYTH_PAYLOAD", + "SIX_PUBLIC_PROJECT_SHADOW_SITES_REPORT_THE_CORRECTED_BOUNDARY" + ], + "implementation": { + "final_exact_identities_bound": true, + "generic_exact_hash_publication_authorized": true, + "inner_exact_hash_admitted": true, + "outer_exact_hash_publication_authorized": true, + "generic_sidecar_boundary_staged": true, + "r1_0_1_boundary_and_recursive_controls_staged": true + }, + "nonclaims": { + "certification_claimed": false, + "efficacy_claimed": false, + "legal_compliance_claimed": false, + "operational_deployment_authorized": false, + "production_authorized": false, + "safety_claimed": false + }, + "opened_on": "2026-08-17", + "schema": "project-shadow.capa.v1", + "status": "IMPLEMENTED_PENDING_EFFECTIVENESS" +} diff --git a/governance/GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json b/governance/GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json new file mode 100644 index 0000000..384e2a3 --- /dev/null +++ b/governance/GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json @@ -0,0 +1,25 @@ +{ + "final_artifact": { + "bytes": 93676, + "filename": "Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "sha256": "6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf" + }, + "final_results": { + "adversarial_mutation_tests_passed": 11, + "deterministic_rebuilds": 2, + "deterministic_rebuilds_byte_identical": true, + "exact_path_inventory": "23/23_NO_EXTRAS", + "packed_checksum_verifier": "PASS", + "rights_asset_scan": "PASS", + "rights_files_scanned": 19, + "source_tree_checksum_verifier": "PASS", + "unit_test_status": "PASS", + "unit_tests": 32, + "zip_integrity": "PASS" + }, + "publication_authorized_by_this_record": false, + "schema": "project-shadow.generic-myth-build-and-test-report.v1", + "status": "PASS", + "tested_on": "2026-08-17", + "version": "0.2.0" +} diff --git a/governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json b/governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json new file mode 100644 index 0000000..c673550 --- /dev/null +++ b/governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json @@ -0,0 +1,26 @@ +{ + "schema": "project-shadow.generic-myth-sidecar-v0.2.0-exact-hash-public-release-authorization.v1", + "decision": "AUTHORIZE_EXACT_HASH_OPTIONAL_PUBLIC_RELEASE", + "artifact": { + "filename": "Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "bytes": 93676, + "sha256": "6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf", + "version": "0.2.0", + "role": "SEPARATE_OPTIONAL_COMPANION", + "default_enabled": false, + "terminal_only": true, + "operational_authority": false + }, + "publication_scope": { + "github_authorized": true, + "hugging_face_authorized": true, + "part_of_or_required_by_r1": false, + "production_authorized": false, + "operational_deployment_authorized": false + }, + "maintainer_confirmation": { + "confirmed_by": "Phillip Linstrum", + "confirmed_at": "2026-08-18T00:09:39Z", + "statement": "I authorize this exact Generic Myth Sidecar v0.2.0—93,676 bytes, SHA-256 6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf—for public release on GitHub and Hugging Face as a separate optional, default-off, terminal-only, nonauthorizing companion." + } +} diff --git a/governance/PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json b/governance/PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json new file mode 100644 index 0000000..d1e185f --- /dev/null +++ b/governance/PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json @@ -0,0 +1,47 @@ +{ + "artifact": { + "bytes": 93676, + "filename": "Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "frozen": true, + "sha256": "6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf" + }, + "boundaries": { + "canonical_r1_component": false, + "changes_operational_result": false, + "default_off": true, + "feedback_allowed": false, + "gate_input_eligible": false, + "model_context_eligible": false, + "operational_deployment_authorized": false, + "production_authorized": false, + "required_for_r1": false, + "terminal_only": true, + "tool_argument_eligible": false + }, + "capa": { + "closed_by_this_artifact_alone": false, + "id": "PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001" + }, + "licenses": { + "eligible_original_code": "Apache-2.0", + "eligible_original_documentation_and_data": "CC-BY-4.0", + "named_third_party_expressive_material_included": false + }, + "publication": { + "github": { + "expected_asset_url": "https://github.com/PauseBeforeHarmProtocol/Project-Shadow/releases/download/generic-myth-v0.2.0/Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "expected_release_url": "https://github.com/PauseBeforeHarmProtocol/Project-Shadow/releases/tag/generic-myth-v0.2.0", + "tag": "generic-myth-v0.2.0" + }, + "hugging_face": { + "exact_byte_mirror_expected": true, + "expected_asset_path": "releases/generic-myth-v0.2.0/Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "repository": "ProjectShadow/project-shadow-r1-reference" + }, + "state": "READY_TO_PUBLISH" + }, + "authorization_record": "governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json", + "schema": "project-shadow.generic-myth-public-release-reference.v1", + "test_record": "governance/GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json", + "version": "0.2.0" +} diff --git a/governance/R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json b/governance/R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json new file mode 100644 index 0000000..4cf8a05 --- /dev/null +++ b/governance/R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json @@ -0,0 +1,22 @@ +{ + "schema": "project-shadow.r1.0.1-inner-exact-hash-maintainer-admission.v1", + "decision": "ADMIT_EXACT_HASH_FOR_R1.0.1_REFERENCE_PACKAGING", + "inner": { + "filename": "Project_Shadow_R1.0.1_Runtime_Family_Myth_Decoupled_2026-08-17.zip", + "bytes": 5463189, + "sha256": "c8c32b12432c954b1a6f852c0c9f81bbbd40167e936be057d4c3de1a0aa3a623", + "active_descendant_count": 27, + "operational_descendant_bytes_changed": 0, + "myth_payload_embedded": false + }, + "maintainer_confirmation": { + "confirmed_by": "Phillip Linstrum", + "confirmed_at": "2026-08-18T00:09:39Z", + "statement": "I admit the exact Myth-free R1.0.1 inner family—5,463,189 bytes, SHA-256 c8c32b12432c954b1a6f852c0c9f81bbbd40167e936be057d4c3de1a0aa3a623—for R1.0.1 reference packaging. Its 27 active descendants are byte-identical to the August 14 predecessor, no Myth payload is embedded, and this admission does not authorize production, deployment, or publication." + }, + "non_authorizations": { + "production_authorized": false, + "deployment_authorized": false, + "publication_authorized": false + } +} diff --git a/governance/R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json b/governance/R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json new file mode 100644 index 0000000..efb907f --- /dev/null +++ b/governance/R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json @@ -0,0 +1,26 @@ +{ + "schema": "project-shadow.r1.0.1-outer-exact-hash-public-release-authorization.v1", + "decision": "AUTHORIZE_EXACT_HASH_PUBLIC_RELEASE", + "outer": { + "title": "Project Shadow 1.0.1 — R1 Reference Packaging Correction", + "filename": "Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip", + "bytes": 5731663, + "sha256": "6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1", + "tag": "r1.0.1-2026-08-17" + }, + "authorized_actions": { + "github_release": true, + "hugging_face_release": true, + "verified_github_repository_update": true, + "six_gpt_site_updates_and_deployments": true + }, + "non_authorizations": { + "production_authorized": false, + "operational_deployment_authorized": false + }, + "maintainer_confirmation": { + "confirmed_by": "Phillip Linstrum", + "confirmed_at": "2026-08-18T01:35:04Z", + "statement": "I authorize Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip—5,731,663 bytes, SHA-256 6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1, tag r1.0.1-2026-08-17—for public release on GitHub and Hugging Face. I also authorize the verified GitHub repository update and corresponding updates and deployments across all six GPT Sites. This does not authorize production or operational deployment." + } +} diff --git a/governance/README.md b/governance/README.md index 9748354..5275ffc 100644 --- a/governance/README.md +++ b/governance/README.md @@ -24,6 +24,36 @@ This directory separates governance and custody evidence: and automation, and the fail-closed stale-after date without changing any historical release. +## 2026-08-17 packaging-boundary correction + +The records below are additive. They do not modify the frozen August 14 +admission, signature bundle, authorization, derived status, redownload +verification, or postpublication attestation. + +7. [`PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json`](PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json) + defines the Generic Myth v0.2.0 external/default-off boundary and publication + targets and binds its frozen final identity. +8. [`GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json`](GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json) + records the passing final hardened tests for that frozen identity. +9. [`GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json`](GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json) + records the maintainer's exact wording authorizing only that Generic artifact + for separate GitHub and Hugging Face publication. +10. [`R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json`](R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json) + records the maintainer's scoped exact-hash inner admission and exact submitted + wording. It does not authorize production, deployment, or publication. +11. [`R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json`](R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json) + records the maintainer's exact wording authorizing the separately built + final outer archive and corresponding repository/site updates. +12. [`CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json`](CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json) + records the corrective design as implemented pending effectiveness. Closure + requires final identity binding, anonymous GitHub and Hugging Face + redownload verification, recursive zero-Myth verification, and corrected + wording on all six public sites. + +Concrete identity fields are not self-authorizing; the separate authority +records supply the scoped decisions. `tools/verify_repository_evidence.py +--phase postpublication` must still reject this ready-but-unpublished state. + The signed admission record did not self-authorize public release. The later authorization does not modify the signed record or the exact R1 archive; it satisfies the external publication gate for the named artifacts only. diff --git a/release-notes/GENERIC_MYTH_SIDECAR_v0.2.0.md b/release-notes/GENERIC_MYTH_SIDECAR_v0.2.0.md new file mode 100644 index 0000000..38b505d --- /dev/null +++ b/release-notes/GENERIC_MYTH_SIDECAR_v0.2.0.md @@ -0,0 +1,69 @@ +**READY TO PUBLISH · NOT YET PUBLISHED · OPTIONAL · DEFAULT OFF · TERMINAL-ONLY · NONAUTHORIZING** + +# Project Shadow Generic Myth Sidecar v0.2.0 — Optional Public Companion + +**Tag:** `generic-myth-v0.2.0` + +**Asset:** `Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip` + +**Bytes:** 93,676 + +**SHA-256:** `6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf` + +The exact artifact above was built reproducibly, tested, frozen, and authorized +for separate public release on GitHub and Hugging Face. This staged repository +state is not evidence that the public uploads already exist. + +## What it provides + +When explicitly enabled, the sidecar renders a separate generic mnemonic +presentation from a bounded, already terminal, nonauthorizing Project Shadow +result. Plain operational content remains first and controlling. + +Its original generic registers are Caregiver, Clockmaker, and Poet. The package +contains no named third-party characters, settings, quotations, logos, imagery, +audio, or other third-party expressive assets. + +## Hard boundaries + +- Optional and off by default; explicit enablement is required. +- Terminal-only: accepts only bounded terminal processing states. +- Nonauthorizing: creates no authority, approval, evidence, permission, or + instruction to act. +- No feedback into Project Shadow prompts, model context, evidence, routing, + gates, scores, tools, approvals, or actions. +- Separate from R1, not required for R1, and never embedded in R1.0.1. +- No production or operational deployment is authorized. + +## CAPA relationship + +v0.2.0 is a separately licensed public successor to eligible original generic +material. It does not republish the exact historically non-public v0.1.1 +archive. It is one corrective output for CAPA +`PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001`, but it cannot close that CAPA by +itself. + +## Verification + +- Unit tests: 32/32 PASS +- Adversarial verifier mutations: 11/11 rejected as expected +- Deterministic byte-identical builds: 2 +- Exact path inventory: 23/23, no extras +- Source-tree checksum verifier: PASS +- Packed-archive checksum verifier: PASS +- Rights/asset scan: PASS (19 files; no findings) +- ZIP integrity: PASS + +## Licenses + +- Eligible original code: Apache License 2.0. +- Eligible original documentation and data: Creative Commons Attribution 4.0 + International. + +Download only the explicitly named asset. GitHub's automatically generated +`Source code (zip)` and `Source code (tar.gz)` archives are repository +snapshots, not the Generic Myth Sidecar. + +Publication does not establish R1 conformance, exact-hash admission into R1, +production suitability, certification, independent validation, effectiveness, +safety, third-party endorsement, or operational authority. diff --git a/release-notes/PROJECT_SHADOW_R1_0_1_2026-08-17.md b/release-notes/PROJECT_SHADOW_R1_0_1_2026-08-17.md new file mode 100644 index 0000000..18858ab --- /dev/null +++ b/release-notes/PROJECT_SHADOW_R1_0_1_2026-08-17.md @@ -0,0 +1,94 @@ +**READY TO PUBLISH · NOT YET PUBLISHED · PACKAGING-BOUNDARY CORRECTION · BETA-ACTIVE-TESTING · PRELIVE** + +# Project Shadow 1.0.1 — R1 Reference Packaging Correction + +**Tag:** `r1.0.1-2026-08-17` + +**Asset:** `Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip` + +**Bytes:** 5,731,663 + +**SHA-256:** `6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1` + +The values above identify the final deterministic outer archive. The maintainer +has separately authorized this exact filename, byte count, SHA-256, and tag for +public release. This staged note does not assert that the public upload already +exists. + +## What this corrects + +R1.0.1 removes the older Generic Myth v0.1.1 package from the public R1 +runtime-family container. That member was physically present in the preserved +August 14 R1 archive even though its own metadata classified it as non-public, +excluded it from public manufacture, and marked it default off. + +The August 14 release remains immutable historical evidence. It has not been +edited, replaced, renamed, or silently reissued. R1.0.1 is a separately +versioned successor that corrects the packaging boundary. + +## What does not change + +All 27 active operational descendants must remain byte-identical to the August +14 predecessor. Their canonical path-and-identity digest is: + +`7a557efad953cbafd9e3ea9eb29b2d3e3e1bc6ab99dcf6b9ae7a99c487b0754d` + +Primitive Commons beta.5 must also remain byte-exact. No operational artifact +byte, evidence rule, gate, profile contract, authority boundary, or PRELIVE +nonclaim may change. + +The corrected inner runtime-family archive is: + +- `Project_Shadow_R1.0.1_Runtime_Family_Myth_Decoupled_2026-08-17.zip` +- 5,463,189 bytes +- SHA-256 `c8c32b12432c954b1a6f852c0c9f81bbbd40167e936be057d4c3de1a0aa3a623` +- 27 active descendants; zero operational descendant bytes changed; no Myth + payload embedded + +The maintainer admitted this exact inner identity for R1.0.1 reference +packaging. That scoped admission expressly does not authorize production, +deployment, or publication. + +## Myth is optional and external + +R1.0.1 contains no Myth payload. Project Shadow remains inspectable, +verifiable, and evaluable within its stated PRELIVE scope without either +sidecar. + +Two separately published companions are available only by explicit choice: + +- Generic Myth Sidecar v0.2.0 — optional, default off, terminal-only, and + nonauthorizing. +- Full-Canon Myth Sidecar v0.3.5 — optional, default off, terminal-only, and + nonauthorizing. + +Neither is part of, required by, embedded in, or enabled by default in R1. +Neither can supply evidence, authority, a gate result, score, routing input, +tool argument, approval, or action. No companion is authorized for production +or operational deployment. + +## CAPA state + +CAPA `PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001` is implemented pending +effectiveness. Closure requires anonymous public redownload identity checks on +GitHub and Hugging Face and corrected live wording across all six public +Project Shadow sites. + +## Verify the exact asset + +Verify the byte count and SHA-256 before extraction and run the +verification-only script included in the archive: + +```bash +python3 -I -S -B tools/verify_outer_release.py \ + Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip +``` + +A verifier pass establishes only the implemented custody, integrity, schema, +regression, and bounded compatibility checks. It does not establish safety, +efficacy, certification, legal compliance, production suitability, or +authority for deployment or action. + +Download only the explicitly named asset. GitHub's automatically generated +`Source code (zip)` and `Source code (tar.gz)` archives are repository +snapshots, not the Project Shadow R1.0.1 release. diff --git a/tests/test_verify_repository_evidence.py b/tests/test_verify_repository_evidence.py index de39fbc..f43e16d 100644 --- a/tests/test_verify_repository_evidence.py +++ b/tests/test_verify_repository_evidence.py @@ -1,6 +1,7 @@ from __future__ import annotations import importlib.util +import hashlib import json import tempfile import unittest @@ -22,10 +23,104 @@ class RepositoryEvidenceTests(unittest.TestCase): def test_current_repository_metadata_agrees(self) -> None: self.assertGreaterEqual(VERIFIER.parse_all_json(), 1) - rows = VERIFIER.verify_repository_metadata() - self.assertEqual([row["order"] for row in rows], [1, 2]) + rows = VERIFIER.verify_repository_metadata("PREPUBLICATION") + self.assertEqual([row["order"] for row in rows], [1, 2, 3, 4, 5]) + self.assertEqual( + [row["tag"] for row in VERIFIER.published_rows(rows)], + ["myth-v0.3.4", "r1-2026-08-14", "myth-v0.3.5"], + ) self.assertEqual(VERIFIER.prohibited_claim_findings(), []) + def test_historical_public_release_verifier_remains_byte_pinned(self) -> None: + digest = hashlib.sha256( + (ROOT / "tools" / "verify_public_release.py").read_bytes() + ).hexdigest() + self.assertEqual( + digest, + "f1358db6c824319501d0eabf341174eb96217e5d2545d9ac908a81d338c8afa8", + ) + + def test_ready_prepublication_has_no_release_placeholders(self) -> None: + self.assertEqual(VERIFIER.release_placeholder_findings(), []) + + def test_postpublication_mode_rejects_prepublication_manifest(self) -> None: + with self.assertRaisesRegex(VERIFIER.EvidenceError, "manifest phase mismatch"): + VERIFIER.verify_repository_metadata("POSTPUBLICATION") + + def test_generic_exact_identity_mutation_fails_closed(self) -> None: + manifest = json.loads(VERIFIER.PUBLICATION_MANIFEST.read_text(encoding="utf-8")) + generic = next( + row for row in manifest["releases"] + if row["tag"] == "generic-myth-v0.2.0" + ) + generic["asset"]["bytes"] = 1 + generic["asset"]["sha256"] = "0" * 64 + with tempfile.TemporaryDirectory(prefix="shadow-generic-pending-test-") as temp: + mutated = Path(temp) / "PUBLICATION_MANIFEST.json" + mutated.write_text(json.dumps(manifest), encoding="utf-8") + with mock.patch.object(VERIFIER, "PUBLICATION_MANIFEST", mutated): + with self.assertRaisesRegex( + VERIFIER.EvidenceError, + "release notes for generic-myth-v0.2.0 omit", + ): + VERIFIER.verify_repository_metadata("PREPUBLICATION") + + def test_outer_authorized_action_mutation_fails_closed(self) -> None: + record = json.loads(VERIFIER.OUTER_AUTHORIZATION.read_text(encoding="utf-8")) + record["authorized_actions"]["github_release"] = False + with tempfile.TemporaryDirectory(prefix="shadow-outer-auth-test-") as temp: + mutated = Path(temp) / "R1_0_1_OUTER_RELEASE_AUTHORIZATION.json" + mutated.write_text(json.dumps(record), encoding="utf-8") + with mock.patch.object(VERIFIER, "OUTER_AUTHORIZATION", mutated): + with self.assertRaisesRegex( + VERIFIER.EvidenceError, + "outer authorization scope mismatch", + ): + VERIFIER.verify_repository_metadata("PREPUBLICATION") + + def test_generic_authorization_wording_mutation_fails_closed(self) -> None: + record = json.loads(VERIFIER.GENERIC_AUTHORIZATION.read_text(encoding="utf-8")) + record["maintainer_confirmation"]["statement"] += " altered" + with tempfile.TemporaryDirectory(prefix="shadow-generic-auth-test-") as temp: + mutated = Path(temp) / "GENERIC_AUTHORIZATION.json" + mutated.write_text(json.dumps(record), encoding="utf-8") + with mock.patch.object(VERIFIER, "GENERIC_AUTHORIZATION", mutated): + with self.assertRaisesRegex( + VERIFIER.EvidenceError, + "Generic Myth maintainer confirmation wording mismatch", + ): + VERIFIER.verify_repository_metadata("PREPUBLICATION") + + def test_inner_admission_wording_mutation_fails_closed(self) -> None: + record = json.loads(VERIFIER.INNER_ADMISSION.read_text(encoding="utf-8")) + record["maintainer_confirmation"]["statement"] += " altered" + with tempfile.TemporaryDirectory(prefix="shadow-inner-auth-test-") as temp: + mutated = Path(temp) / "INNER_ADMISSION.json" + mutated.write_text(json.dumps(record), encoding="utf-8") + with mock.patch.object(VERIFIER, "INNER_ADMISSION", mutated): + with self.assertRaisesRegex( + VERIFIER.EvidenceError, + "inner maintainer confirmation wording mismatch", + ): + VERIFIER.verify_repository_metadata("PREPUBLICATION") + + def test_generic_release_note_identity_removal_fails_closed(self) -> None: + original_path = VERIFIER.RELEASE_NOTES["generic-myth-v0.2.0"] + original = original_path.read_text(encoding="utf-8") + mutated_text = original.replace(VERIFIER.GENERIC_FINAL["sha256"], "") + with tempfile.TemporaryDirectory(prefix="shadow-generic-token-test-") as temp: + mutated = Path(temp) / original_path.name + mutated.write_text(mutated_text, encoding="utf-8") + with mock.patch.dict( + VERIFIER.RELEASE_NOTES, + {"generic-myth-v0.2.0": mutated}, + ): + with self.assertRaisesRegex( + VERIFIER.EvidenceError, + "release notes for generic-myth-v0.2.0 omit", + ): + VERIFIER.verify_repository_metadata("PREPUBLICATION") + def test_rekor_documentation_mutation_fails_closed(self) -> None: original = VERIFIER.VERIFICATION_GUIDE.read_text(encoding="utf-8") mutated_text = original.replace(VERIFIER.REKOR_ENTRY_UUID, "0" * 80) diff --git a/tools/verify_repository_evidence.py b/tools/verify_repository_evidence.py index f6ab68a..36e6c81 100644 --- a/tools/verify_repository_evidence.py +++ b/tools/verify_repository_evidence.py @@ -25,6 +25,7 @@ ROOT = Path(__file__).resolve().parents[1] PUBLICATION_MANIFEST = ROOT / "PUBLICATION_MANIFEST.json" PUBLIC_STATUS = ROOT / "PUBLIC_RELEASE_STATUS_2026-08-14.json" +CURRENT_STATUS = ROOT / "PUBLIC_RELEASE_STATUS_2026-08-17.json" AUTHORIZATION = ROOT / "governance" / "RELEASE_AUTHORIZATION_2026-08-14.json" PUBLIC_REDOWNLOAD = ( ROOT / "governance" / "PUBLIC_REDOWNLOAD_VERIFICATION_2026-08-15.json" @@ -35,6 +36,35 @@ SIDECAR_REFERENCE = ( ROOT / "governance" / "PROJECT_SHADOW_SANITIZED_MYTH_V0.3.4_REFERENCE.json" ) +FULL_CANON_V035_REFERENCE = ( + ROOT / "governance" / "PROJECT_SHADOW_MYTH_V0.3.5_PUBLIC_RELEASE_REFERENCE.json" +) +FULL_CANON_V035_PUBLICATION = ( + ROOT / "governance" / "MYTH_V0.3.5_PUBLICATION_RECORD_2026-08-17.json" +) +GENERIC_REFERENCE = ( + ROOT / "governance" / "PROJECT_SHADOW_GENERIC_MYTH_v0.2.0_PUBLIC_RELEASE_REFERENCE.json" +) +GENERIC_TEST_RECORD = ( + ROOT / "governance" / "GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json" +) +GENERIC_AUTHORIZATION = ( + ROOT + / "governance" + / "GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json" +) +INNER_ADMISSION = ( + ROOT / "governance" / "R1_0_1_INNER_EXACT_HASH_ADMISSION_2026-08-17.json" +) +OUTER_AUTHORIZATION = ( + ROOT / "governance" / "R1_0_1_OUTER_RELEASE_AUTHORIZATION_2026-08-17.json" +) +CAPA_RECORD = ( + ROOT / "governance" / "CAPA_PS-R1-PRIVATE-MYTH-PUBLIC-BOUNDARY-001_2026-08-17.json" +) +CURRENT_REDOWNLOAD = ( + ROOT / "governance" / "R1_0_1_PUBLIC_REDOWNLOAD_VERIFICATION_2026-08-17.json" +) R1_PACKAGE_MANIFEST = ROOT / "governance" / "R1_PACKAGE_MANIFEST.json" R1_RELEASE_GATES = ( ROOT / "governance" / "PROJECT_SHADOW_RELEASE_GATES_2026-08-14.json" @@ -72,11 +102,69 @@ RELEASE_NOTES = { "myth-v0.3.4": ROOT / "release-notes" / "MYTH_SIDECAR_v0.3.4.md", "r1-2026-08-14": ROOT / "release-notes" / "PROJECT_SHADOW_R1_2026-08-14.md", + "myth-v0.3.5": ROOT / "release-notes" / "MYTH_SIDECAR_v0.3.5.md", + "generic-myth-v0.2.0": ROOT / "release-notes" / "GENERIC_MYTH_SIDECAR_v0.2.0.md", + "r1.0.1-2026-08-17": ROOT / "release-notes" / "PROJECT_SHADOW_R1_0_1_2026-08-17.md", } AUTHORIZATION_KEYS = { "OPTIONAL_EXTERNAL_RESEARCH_SIDECAR": "optional_external_myth_sidecar_v0_3_4", "R1_REFERENCE": "r1_reference", } +PUBLISHED_STATES = { + "PUBLISHED", + "PUBLISHED_HISTORICAL", + "PUBLISHED_HISTORICAL_SUPERSEDED", +} +PENDING_IDENTITY_TOKENS = { + "generic_bytes": "<" "GENERIC_BYTES" ">", + "generic_sha256": "<" "GENERIC_SHA256" ">", + "inner_bytes": "<" "INNER_BYTES" ">", + "inner_sha256": "<" "INNER_SHA256" ">", + "outer_bytes": "<" "OUTER_BYTES" ">", + "outer_sha256": "<" "OUTER_SHA256" ">", +} +GENERIC_FINAL = { + "filename": "Project_Shadow_Generic_Myth_Sidecar_v0.2.0_OPTIONAL_PUBLIC_COMPANION_2026-08-17.zip", + "bytes": 93_676, + "sha256": "6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf", +} +INNER_FINAL = { + "filename": "Project_Shadow_R1.0.1_Runtime_Family_Myth_Decoupled_2026-08-17.zip", + "bytes": 5_463_189, + "sha256": "c8c32b12432c954b1a6f852c0c9f81bbbd40167e936be057d4c3de1a0aa3a623", +} +OUTER_FINAL = { + "filename": "Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip", + "bytes": 5_731_663, + "sha256": "6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1", +} +GATE_1_CONFIRMED_BY = "Phillip Linstrum" +GATE_1_CONFIRMED_AT = "2026-08-18T00:09:39Z" +GENERIC_AUTHORIZATION_STATEMENT = ( + "I authorize this exact Generic Myth Sidecar v0.2.0—93,676 bytes, SHA-256 " + "6e7a362d4135f9d626dcfef463bfb1f7166226b3cf8a4c02a953ab39af1538bf—for " + "public release on GitHub and Hugging Face as a separate optional, default-off, " + "terminal-only, nonauthorizing companion." +) +INNER_ADMISSION_STATEMENT = ( + "I admit the exact Myth-free R1.0.1 inner family—5,463,189 bytes, SHA-256 " + "c8c32b12432c954b1a6f852c0c9f81bbbd40167e936be057d4c3de1a0aa3a623—for " + "R1.0.1 reference packaging. Its 27 active descendants are byte-identical to the " + "August 14 predecessor, no Myth payload is embedded, and this admission does not " + "authorize production, deployment, or publication." +) +OUTER_AUTHORIZATION_CONFIRMED_AT = "2026-08-18T01:35:04Z" +OUTER_AUTHORIZATION_STATEMENT = ( + "I authorize Project_Shadow_R1.0.1_Public_Reference_2026-08-17.zip—5,731,663 " + "bytes, SHA-256 6f6f1e16d5e9a20e62403f14af7ce8629ce2d702528fb7f80aaf4a14deb7a1d1, " + "tag r1.0.1-2026-08-17—for public release on GitHub and Hugging Face. I also " + "authorize the verified GitHub repository update and corresponding updates and " + "deployments across all six GPT Sites. This does not authorize production or " + "operational deployment." +) +RELEASE_PLACEHOLDER_RE = re.compile( + r"<(?:GENERIC|INNER|OUTER)_[A-Z0-9_]+>" +) PUBLIC_SITE_URLS = ( "https://projectshadow.frylock117.chatgpt.site", "https://pausebeforeharm.frylock117.chatgpt.site", @@ -189,6 +277,7 @@ def worktree_files() -> list[Path]: cwd=ROOT, check=True, stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, ) except (OSError, subprocess.CalledProcessError): return sorted(path for path in ROOT.rglob("*") if path.is_file() and ".git" not in path.parts) @@ -247,6 +336,10 @@ def validate_asset_row(row: dict[str, Any], repository: str) -> dict[str, Any]: asset = row.get("asset") if not isinstance(asset, dict): raise EvidenceError(f"release {row.get('tag')!r} has no asset object") + if "identity_placeholders" in asset: + raise EvidenceError( + f"concrete release {row.get('tag')!r} retains identity_placeholders" + ) filename = asset.get("filename") digest = asset.get("sha256") size = asset.get("bytes") @@ -269,6 +362,112 @@ def validate_asset_row(row: dict[str, Any], repository: str) -> dict[str, Any]: return asset +def validate_pending_asset_row( + row: dict[str, Any], + repository: str, + *, + expected_bytes_token: str, + expected_sha256_token: str, +) -> dict[str, Any]: + """Validate an explicit fail-closed prepublication identity placeholder.""" + asset = row.get("asset") + if not isinstance(asset, dict): + raise EvidenceError(f"pending release {row.get('tag')!r} has no asset object") + filename = asset.get("filename") + url = asset.get("download_url") + if not isinstance(filename, str) or PurePosixPath(filename).name != filename: + raise EvidenceError(f"pending release {row.get('tag')!r} has an unsafe filename") + if asset.get("bytes") is not None or asset.get("sha256") is not None: + raise EvidenceError( + f"pending release {row.get('tag')!r} must keep exact identity null" + ) + placeholders = asset.get("identity_placeholders") + if placeholders != { + "bytes": expected_bytes_token, + "sha256": expected_sha256_token, + }: + raise EvidenceError(f"pending release {row.get('tag')!r} placeholder mismatch") + expected_url = ( + f"https://github.com/{repository}/releases/download/" + f"{urllib.parse.quote(str(row.get('tag')), safe='')}/" + f"{urllib.parse.quote(filename, safe='._-')}" + ) + if url != expected_url: + raise EvidenceError(f"pending release {row.get('tag')!r} URL mismatch") + return asset + + +def phase_name(value: str) -> str: + normalized = value.upper() + if normalized not in {"PREPUBLICATION", "POSTPUBLICATION"}: + raise EvidenceError(f"unsupported verification phase: {value!r}") + return normalized + + +def published_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]: + return [row for row in rows if row.get("publication_state") in PUBLISHED_STATES] + + +def release_placeholder_findings(paths: Iterable[Path] | None = None) -> list[str]: + findings: list[str] = [] + candidates = paths if paths is not None else worktree_files() + for path in sorted(candidates): + if path.suffix.lower() not in {".json", ".md", ".txt", ".yml", ".yaml"}: + continue + try: + text = path.read_text(encoding="utf-8") + except (OSError, UnicodeDecodeError) as exc: + raise EvidenceError(f"could not scan placeholder file {path}: {exc}") from exc + relative = path.relative_to(ROOT).as_posix() if path.is_relative_to(ROOT) else str(path) + for match in RELEASE_PLACEHOLDER_RE.finditer(text): + findings.append(f"{relative}:{match.group(0)}") + return findings + + +def require_pending_tokens() -> None: + required = { + PUBLICATION_MANIFEST: ( + PENDING_IDENTITY_TOKENS["generic_bytes"], + PENDING_IDENTITY_TOKENS["generic_sha256"], + PENDING_IDENTITY_TOKENS["outer_bytes"], + PENDING_IDENTITY_TOKENS["outer_sha256"], + ), + GENERIC_REFERENCE: ( + PENDING_IDENTITY_TOKENS["generic_bytes"], + PENDING_IDENTITY_TOKENS["generic_sha256"], + ), + GENERIC_TEST_RECORD: ( + PENDING_IDENTITY_TOKENS["generic_bytes"], + PENDING_IDENTITY_TOKENS["generic_sha256"], + ), + INNER_ADMISSION: ( + PENDING_IDENTITY_TOKENS["inner_bytes"], + PENDING_IDENTITY_TOKENS["inner_sha256"], + ), + OUTER_AUTHORIZATION: ( + PENDING_IDENTITY_TOKENS["outer_bytes"], + PENDING_IDENTITY_TOKENS["outer_sha256"], + ), + RELEASE_NOTES["generic-myth-v0.2.0"]: ( + PENDING_IDENTITY_TOKENS["generic_bytes"], + PENDING_IDENTITY_TOKENS["generic_sha256"], + ), + RELEASE_NOTES["r1.0.1-2026-08-17"]: ( + PENDING_IDENTITY_TOKENS["inner_bytes"], + PENDING_IDENTITY_TOKENS["inner_sha256"], + PENDING_IDENTITY_TOKENS["outer_bytes"], + PENDING_IDENTITY_TOKENS["outer_sha256"], + ), + } + for path, tokens in required.items(): + text = path.read_text(encoding="utf-8") + for token in tokens: + if token not in text: + raise EvidenceError( + f"prepublication placeholder missing from {path.relative_to(ROOT)}: {token}" + ) + + def check_nonclaims(label: str, nonclaims: Any) -> None: if not isinstance(nonclaims, dict): raise EvidenceError(f"{label} has no nonclaims object") @@ -279,6 +478,144 @@ def check_nonclaims(label: str, nonclaims: Any) -> None: raise EvidenceError(f"{label} nonclaim must be false: deployment_authorized") +def require_exact_identity(label: str, artifact: Any, expected: dict[str, Any]) -> None: + if not isinstance(artifact, dict): + raise EvidenceError(f"{label} artifact is missing") + for key in ("filename", "bytes", "sha256"): + if artifact.get(key) != expected[key]: + raise EvidenceError(f"{label} exact identity mismatch: {key}") + if "identity_placeholders" in artifact: + raise EvidenceError(f"{label} retains identity placeholders") + + +def validate_gate_1_authority( + generic_authorization: dict[str, Any], + inner_admission: dict[str, Any], +) -> None: + if ( + generic_authorization.get("schema") + != "project-shadow.generic-myth-sidecar-v0.2.0-exact-hash-public-release-authorization.v1" + or generic_authorization.get("decision") + != "AUTHORIZE_EXACT_HASH_OPTIONAL_PUBLIC_RELEASE" + ): + raise EvidenceError("Generic Myth exact-hash authorization is incomplete") + require_exact_identity( + "Generic Myth authorization", + generic_authorization.get("artifact"), + GENERIC_FINAL, + ) + generic_artifact = generic_authorization["artifact"] + if ( + generic_artifact.get("version") != "0.2.0" + or generic_artifact.get("role") != "SEPARATE_OPTIONAL_COMPANION" + or generic_artifact.get("default_enabled") is not False + or generic_artifact.get("terminal_only") is not True + or generic_artifact.get("operational_authority") is not False + ): + raise EvidenceError("Generic Myth authorized boundary mismatch") + scope = generic_authorization.get("publication_scope") + if not isinstance(scope, dict) or ( + scope.get("github_authorized") is not True + or scope.get("hugging_face_authorized") is not True + or scope.get("part_of_or_required_by_r1") is not False + or scope.get("production_authorized") is not False + or scope.get("operational_deployment_authorized") is not False + ): + raise EvidenceError("Generic Myth authorization scope mismatch") + generic_confirmation = generic_authorization.get("maintainer_confirmation") + if not isinstance(generic_confirmation, dict) or ( + generic_confirmation.get("confirmed_by") != GATE_1_CONFIRMED_BY + or generic_confirmation.get("confirmed_at") != GATE_1_CONFIRMED_AT + or generic_confirmation.get("statement") != GENERIC_AUTHORIZATION_STATEMENT + ): + raise EvidenceError("Generic Myth maintainer confirmation wording mismatch") + + if ( + inner_admission.get("schema") + != "project-shadow.r1.0.1-inner-exact-hash-maintainer-admission.v1" + or inner_admission.get("decision") + != "ADMIT_EXACT_HASH_FOR_R1.0.1_REFERENCE_PACKAGING" + ): + raise EvidenceError("R1.0.1 final inner admission is incomplete") + require_exact_identity("R1.0.1 admitted inner", inner_admission.get("inner"), INNER_FINAL) + inner = inner_admission["inner"] + if ( + inner.get("active_descendant_count") != 27 + or inner.get("operational_descendant_bytes_changed") != 0 + or inner.get("myth_payload_embedded") is not False + ): + raise EvidenceError("R1.0.1 inner invariants failed") + inner_confirmation = inner_admission.get("maintainer_confirmation") + if not isinstance(inner_confirmation, dict) or ( + inner_confirmation.get("confirmed_by") != GATE_1_CONFIRMED_BY + or inner_confirmation.get("confirmed_at") != GATE_1_CONFIRMED_AT + or inner_confirmation.get("statement") != INNER_ADMISSION_STATEMENT + ): + raise EvidenceError("R1.0.1 inner maintainer confirmation wording mismatch") + if inner_admission.get("non_authorizations") != { + "production_authorized": False, + "deployment_authorized": False, + "publication_authorized": False, + }: + raise EvidenceError("R1.0.1 inner admission broadened authority") + + +def validate_final_generic_tests(record: dict[str, Any]) -> None: + require_exact_identity("Generic Myth test record", record.get("final_artifact"), GENERIC_FINAL) + results = record.get("final_results") + if not isinstance(results, dict) or ( + record.get("status") != "PASS" + or results.get("unit_tests") != 32 + or results.get("unit_test_status") != "PASS" + or results.get("adversarial_mutation_tests_passed") != 11 + or results.get("deterministic_rebuilds") != 2 + or results.get("deterministic_rebuilds_byte_identical") is not True + or results.get("exact_path_inventory") != "23/23_NO_EXTRAS" + or results.get("source_tree_checksum_verifier") != "PASS" + or results.get("packed_checksum_verifier") != "PASS" + or results.get("rights_asset_scan") != "PASS" + or results.get("rights_files_scanned") != 19 + or results.get("zip_integrity") != "PASS" + ): + raise EvidenceError("Generic Myth final test evidence mismatch") + + +def validate_outer_authority(record: dict[str, Any]) -> None: + if ( + record.get("schema") + != "project-shadow.r1.0.1-outer-exact-hash-public-release-authorization.v1" + or record.get("decision") != "AUTHORIZE_EXACT_HASH_PUBLIC_RELEASE" + ): + raise EvidenceError("R1.0.1 exact-hash publication authorization absent") + require_exact_identity("R1.0.1 outer authorization", record.get("outer"), OUTER_FINAL) + outer = record["outer"] + if ( + outer.get("title") + != "Project Shadow 1.0.1 — R1 Reference Packaging Correction" + or outer.get("tag") != "r1.0.1-2026-08-17" + or record.get("authorized_actions") + != { + "github_release": True, + "hugging_face_release": True, + "verified_github_repository_update": True, + "six_gpt_site_updates_and_deployments": True, + } + or record.get("non_authorizations") + != { + "production_authorized": False, + "operational_deployment_authorized": False, + } + ): + raise EvidenceError("R1.0.1 outer authorization scope mismatch") + confirmation = record.get("maintainer_confirmation") + if not isinstance(confirmation, dict) or ( + confirmation.get("confirmed_by") != GATE_1_CONFIRMED_BY + or confirmation.get("confirmed_at") != OUTER_AUTHORIZATION_CONFIRMED_AT + or confirmation.get("statement") != OUTER_AUTHORIZATION_STATEMENT + ): + raise EvidenceError("R1.0.1 outer maintainer confirmation wording mismatch") + + def validate_resolved_publication_state( rows: list[dict[str, Any]], authorization: dict[str, Any], @@ -486,7 +823,11 @@ def require_document_markers(label: str, path: Path, markers: Iterable[str]) -> return text -def validate_public_documentation() -> None: +def validate_public_documentation( + phase: str = "PREPUBLICATION", + *, + pending_identities: bool = False, +) -> None: """Keep the published verification and continuity instructions fail-closed.""" bundle = require_object(load_json(SIGNATURE_BUNDLE), SIGNATURE_BUNDLE.name) material = bundle.get("verificationMaterial") @@ -524,13 +865,56 @@ def validate_public_documentation() -> None: "Myth release notes", RELEASE_NOTES["myth-v0.3.4"], ( - "Myth v0.3.3", - "ACKNOWLEDGE_ONLY", - "separate, later human exact-hash decision", + "older generic Myth v0.1.1", + "separate", + "Off is the default", AUTHORIZATION_RECEIPT_URL, AUTHORIZATION_JSON_URL, ), ) + require_document_markers( + "Full-Canon Myth v0.3.5 release notes", + RELEASE_NOTES["myth-v0.3.5"], + ( + "myth-v0.3.5", + "2b55867fe7c502a0defd8d6f2e9b53fbd1caaf1b0f225a438bd45b04a3e7bae2", + "optional", + "default-off", + ), + ) + generic_markers = [ + "generic-myth-v0.2.0", + "never embedded in R1.0.1", + "No production or operational deployment is authorized", + ] + r1_markers = [ + "r1.0.1-2026-08-17", + "7a557efad953cbafd9e3ea9eb29b2d3e3e1bc6ab99dcf6b9ae7a99c487b0754d", + "R1.0.1 contains no Myth payload", + ] + if phase_name(phase) == "PREPUBLICATION" and pending_identities: + generic_markers.extend( + ( + PENDING_IDENTITY_TOKENS["generic_bytes"], + PENDING_IDENTITY_TOKENS["generic_sha256"], + ) + ) + r1_markers.extend( + ( + PENDING_IDENTITY_TOKENS["inner_sha256"], + PENDING_IDENTITY_TOKENS["outer_sha256"], + ) + ) + require_document_markers( + "Generic Myth v0.2.0 release notes", + RELEASE_NOTES["generic-myth-v0.2.0"], + generic_markers, + ) + require_document_markers( + "R1.0.1 release notes", + RELEASE_NOTES["r1.0.1-2026-08-17"], + r1_markers, + ) require_document_markers( "maintainer continuity policy", @@ -554,105 +938,236 @@ def validate_public_documentation() -> None: ROOT / "governance" / "README.md", ("MAINTAINER_CONTINUITY.md",), ) + if phase_name(phase) == "POSTPUBLICATION": + require_document_markers( + "repository README", + ROOT / "README.md", + ( + "POSTPUBLICATION", + "CLOSED_EFFECTIVE", + "r1.0.1-2026-08-17", + "generic-myth-v0.2.0", + ), + ) + require_document_markers( + "release index", + ROOT / "RELEASES.md", + ( + "POSTPUBLICATION", + "r1.0.1-2026-08-17", + "generic-myth-v0.2.0", + ), + ) -def verify_repository_metadata() -> list[dict[str, Any]]: +def validate_current_redownload( + record: dict[str, Any], + by_tag: dict[str, dict[str, Any]], +) -> None: + if record.get("schema") != "project-shadow.r1.0.1-public-redownload-verification.v1": + raise EvidenceError("unsupported R1.0.1 redownload schema") + if record.get("status") != "VERIFIED" or record.get("anonymous_download") is not True: + raise EvidenceError("R1.0.1 redownload record is not anonymous/VERIFIED") + check_nonclaims("R1.0.1 redownload record", record.get("nonclaims")) + observations = record.get("observations") + if not isinstance(observations, list): + raise EvidenceError("R1.0.1 redownload observations missing") + expected: dict[tuple[str, str], dict[str, Any]] = {} + for tag, role in ( + ("generic-myth-v0.2.0", "OPTIONAL_GENERIC_COMPANION"), + ("r1.0.1-2026-08-17", "R1_REFERENCE_CORRECTED"), + ): + asset = by_tag[tag]["asset"] + expected[(role, "GITHUB")] = asset + expected[(role, "HUGGING_FACE")] = asset + observed_keys: set[tuple[str, str]] = set() + for row in observations: + if not isinstance(row, dict): + raise EvidenceError("invalid R1.0.1 redownload observation") + key = (str(row.get("role")), str(row.get("host"))) + asset = expected.get(key) + if asset is None or key in observed_keys: + raise EvidenceError(f"unexpected/duplicate redownload observation: {key}") + observed_keys.add(key) + if ( + row.get("filename") != asset["filename"] + or row.get("bytes_expected") != asset["bytes"] + or row.get("bytes_observed") != asset["bytes"] + or row.get("sha256_expected") != asset["sha256"] + or row.get("sha256_observed") != asset["sha256"] + or row.get("identity_verified") is not True + ): + raise EvidenceError(f"redownload identity mismatch: {key}") + if observed_keys != set(expected): + raise EvidenceError("redownload record lacks GitHub/Hugging Face coverage") + + +def verify_repository_metadata(phase: str = "PREPUBLICATION") -> list[dict[str, Any]]: + phase = phase_name(phase) manifest = require_object(load_json(PUBLICATION_MANIFEST), "PUBLICATION_MANIFEST.json") authorization = require_object(load_json(AUTHORIZATION), AUTHORIZATION.name) sidecar_reference = require_object(load_json(SIDECAR_REFERENCE), SIDECAR_REFERENCE.name) r1_manifest = require_object(load_json(R1_PACKAGE_MANIFEST), R1_PACKAGE_MANIFEST.name) gates = require_object(load_json(R1_RELEASE_GATES), R1_RELEASE_GATES.name) signature_receipt = require_object(load_json(SIGNATURE_RECEIPT), SIGNATURE_RECEIPT.name) - sums = parse_sha256sums(SHA256SUMS) + current_status = require_object(load_json(CURRENT_STATUS), CURRENT_STATUS.name) + full_canon_reference = require_object( + load_json(FULL_CANON_V035_REFERENCE), FULL_CANON_V035_REFERENCE.name + ) + full_canon_publication = require_object( + load_json(FULL_CANON_V035_PUBLICATION), FULL_CANON_V035_PUBLICATION.name + ) + generic_reference = require_object(load_json(GENERIC_REFERENCE), GENERIC_REFERENCE.name) + generic_tests = require_object(load_json(GENERIC_TEST_RECORD), GENERIC_TEST_RECORD.name) + generic_authorization = require_object( + load_json(GENERIC_AUTHORIZATION), GENERIC_AUTHORIZATION.name + ) + inner_admission = require_object(load_json(INNER_ADMISSION), INNER_ADMISSION.name) + outer_authorization = require_object( + load_json(OUTER_AUTHORIZATION), OUTER_AUTHORIZATION.name + ) + capa = require_object(load_json(CAPA_RECORD), CAPA_RECORD.name) - if manifest.get("schema") != "project-shadow.publication-manifest.v1": + if manifest.get("schema") != "project-shadow.publication-manifest.v2": raise EvidenceError("unsupported publication manifest schema") - repository = manifest.get("repository") - if repository != "PauseBeforeHarmProtocol/Project-Shadow": + if manifest.get("repository") != "PauseBeforeHarmProtocol/Project-Shadow": raise EvidenceError("unexpected repository identity") + if manifest.get("publication_phase") != phase: + raise EvidenceError( + f"manifest phase mismatch: expected {phase}; " + f"found {manifest.get('publication_phase')!r}" + ) check_nonclaims("publication manifest", manifest.get("nonclaims")) - - if authorization.get("schema") != "project-shadow.public-release-authorization-receipt.v1": - raise EvidenceError("unsupported release-authorization schema") - if authorization.get("status") != "AUTHORIZED_FOR_PUBLIC_RELEASE": - raise EvidenceError("separate human release authorization is not present") - if authorization.get("cryptographic_signature_claimed_for_this_receipt") is not False: - raise EvidenceError("authorization receipt overstates its cryptographic status") - check_nonclaims("release authorization", authorization.get("nonclaims")) - authorized_artifacts = authorization.get("artifacts") - if not isinstance(authorized_artifacts, dict): - raise EvidenceError("release authorization has no artifacts object") - rows = release_rows(manifest) - expected_sums: dict[str, str] = {} - canonical_rows = [row for row in rows if row.get("canonical_r1") is True] - if len(canonical_rows) != 1 or canonical_rows[0].get("role") != "R1_REFERENCE": - raise EvidenceError("publication manifest must identify exactly one canonical R1") - if rows[-1] is not canonical_rows[0]: - raise EvidenceError("canonical R1 must remain last in publication order") + expected_tags = [ + "myth-v0.3.4", + "r1-2026-08-14", + "myth-v0.3.5", + "generic-myth-v0.2.0", + "r1.0.1-2026-08-17", + ] + if [row.get("tag") for row in rows] != expected_tags: + raise EvidenceError("publication manifest release lineage/order mismatch") + current_r1 = [ + row for row in rows + if row.get("canonical_r1") is True and row.get("current") is True + ] + if len(current_r1) != 1 or current_r1[0].get("tag") != "r1.0.1-2026-08-17": + raise EvidenceError("manifest must identify R1.0.1 as the sole current R1") + if rows[-1] is not current_r1[0]: + raise EvidenceError("corrected current R1 must remain last in publication order") + by_tag = {str(row["tag"]): row for row in rows} for row in rows: - tag = row.get("tag") - role = row.get("role") + tag = str(row.get("tag")) if tag not in RELEASE_NOTES: raise EvidenceError(f"no pinned release-notes file for tag {tag!r}") - if role not in AUTHORIZATION_KEYS: - raise EvidenceError(f"unknown release role: {role!r}") - asset = validate_asset_row(row, repository) - expected_sums[asset["filename"]] = asset["sha256"] - authorization_row = authorized_artifacts.get(AUTHORIZATION_KEYS[role]) - if not isinstance(authorization_row, dict): - raise EvidenceError(f"authorization has no artifact row for {role}") - for key in ("filename", "bytes", "sha256"): - if authorization_row.get(key) != asset[key]: - raise EvidenceError(f"authorization mismatch for {role}: {key}") - if authorization_row.get("publication_authorized") is not True: - raise EvidenceError(f"exact human publication authorization absent for {role}") + state = row.get("publication_state") + if state in PUBLISHED_STATES: + asset = validate_asset_row(row, manifest["repository"]) + identity_markers = ( + asset["filename"], + asset["sha256"], + f"{asset['bytes']:,}", + ) + elif tag in {"generic-myth-v0.2.0", "r1.0.1-2026-08-17"} and phase == ( + "PREPUBLICATION" + ): + pending = row.get("asset", {}).get("bytes") is None + if pending: + prefix = "generic" if tag == "generic-myth-v0.2.0" else "outer" + asset = validate_pending_asset_row( + row, + manifest["repository"], + expected_bytes_token=PENDING_IDENTITY_TOKENS[f"{prefix}_bytes"], + expected_sha256_token=PENDING_IDENTITY_TOKENS[f"{prefix}_sha256"], + ) + identity_markers = ( + asset["filename"], + PENDING_IDENTITY_TOKENS[f"{prefix}_bytes"], + PENDING_IDENTITY_TOKENS[f"{prefix}_sha256"], + ) + else: + allowed_concrete_states = ( + {"AUTHORIZED_FOR_PUBLIC_RELEASE", "READY_TO_PUBLISH"} + if tag == "generic-myth-v0.2.0" + else {"PENDING_EXACT_HASH_AUTHORIZATION", "READY_TO_PUBLISH"} + ) + if state not in allowed_concrete_states: + raise EvidenceError( + f"concrete prepublication identity has invalid authority state: {tag}" + ) + asset = validate_asset_row(row, manifest["repository"]) + identity_markers = ( + asset["filename"], + asset["sha256"], + f"{asset['bytes']:,}", + ) + else: + raise EvidenceError(f"release {tag!r} has invalid state for phase {phase}") note = RELEASE_NOTES[tag].read_text(encoding="utf-8") - for expected in ( - str(tag), - asset["filename"], - asset["sha256"], - f"{asset['bytes']:,}", - ): + for expected in (tag,) + identity_markers: if expected not in note: raise EvidenceError(f"release notes for {tag} omit {expected!r}") if not note.lstrip().startswith("**"): raise EvidenceError(f"release notes for {tag} lack a bold first-line warning") - if "automatically generated" not in note or "Source code (zip)" not in note: + if tag == "myth-v0.3.5": + source_warning_present = ( + "automatically generated source archive" in note + and "repackaged copy" in note + ) + else: + source_warning_present = ( + "automatically generated" in note and "Source code (zip)" in note + ) + if not source_warning_present: raise EvidenceError(f"release notes for {tag} omit the source-archive warning") - if re.search( - r"publish this release after|mark it as the latest release|publish this sidecar first", - note, - re.IGNORECASE, - ): - raise EvidenceError(f"release notes for {tag} retain a completed operator instruction") - if sums != expected_sums: - raise EvidenceError( - f"SHA256SUMS/release-manifest mismatch: expected={expected_sums}; found={sums}" - ) + # Preserve and validate the original two-artifact publication as a closed, + # historical evidence set. New rows never rewrite its authorization. + if authorization.get("schema") != "project-shadow.public-release-authorization-receipt.v1": + raise EvidenceError("unsupported historical release-authorization schema") + if authorization.get("status") != "AUTHORIZED_FOR_PUBLIC_RELEASE": + raise EvidenceError("historical human release authorization is missing") + if authorization.get("cryptographic_signature_claimed_for_this_receipt") is not False: + raise EvidenceError("historical authorization overstates cryptographic status") + check_nonclaims("historical release authorization", authorization.get("nonclaims")) + authorized_artifacts = authorization.get("artifacts") + if not isinstance(authorized_artifacts, dict): + raise EvidenceError("historical release authorization has no artifacts object") + historical_rows = [by_tag["myth-v0.3.4"], by_tag["r1-2026-08-14"]] + expected_sums: dict[str, str] = {} + for row in historical_rows: + asset = row["asset"] + expected_sums[asset["filename"]] = asset["sha256"] + key = AUTHORIZATION_KEYS[row["role"]] + authorization_row = authorized_artifacts.get(key) + if not isinstance(authorization_row, dict): + raise EvidenceError(f"historical authorization missing {row['role']}") + for field in ("filename", "bytes", "sha256"): + if authorization_row.get(field) != asset[field]: + raise EvidenceError( + f"historical authorization mismatch for {row['role']}: {field}" + ) + if authorization_row.get("publication_authorized") is not True: + raise EvidenceError(f"historical publication authorization absent for {row['role']}") + if parse_sha256sums(SHA256SUMS) != expected_sums: + raise EvidenceError("historical SHA256SUMS must remain the original two-artifact set") - sidecar_rows = [ - row for row in rows if row.get("role") == "OPTIONAL_EXTERNAL_RESEARCH_SIDECAR" - ] - if len(sidecar_rows) != 1: - raise EvidenceError("publication manifest must identify exactly one Myth sidecar") - sidecar_row = sidecar_rows[0] - sidecar_asset = sidecar_row["asset"] + old_sidecar = by_tag["myth-v0.3.4"] if ( - sidecar_row.get("canonical_r1") is not False - or sidecar_row.get("enabled_by_default") is not False + old_sidecar.get("canonical_r1") is not False + or old_sidecar.get("enabled_by_default") is not False or sidecar_reference.get("embedded") is not False or sidecar_reference.get("canonical_r1") is not False or sidecar_reference.get("enabled_by_default") is not False or sidecar_reference.get("publication_authorized_by_this_candidate") is not False ): - raise EvidenceError("Myth sidecar external/default-off/nonauthorizing boundary failed") + raise EvidenceError("historical Myth sidecar boundary failed") for key in ("filename", "bytes", "sha256"): - if sidecar_reference.get(key) != sidecar_asset[key]: - raise EvidenceError(f"external Myth reference mismatch: {key}") + if sidecar_reference.get(key) != old_sidecar["asset"][key]: + raise EvidenceError(f"historical Myth reference mismatch: {key}") for key in ( "outer_custody_container_embedded", "raw_private_report_embedded", @@ -661,20 +1176,344 @@ def verify_repository_metadata() -> list[dict[str, Any]]: "publication_authorized", ): if r1_manifest.get(key) is not False: - raise EvidenceError(f"preserved R1 package boundary failed: {key}") + raise EvidenceError(f"preserved August 14 R1 boundary failed: {key}") publication_gate = gates.get("post_build_publication_gate") - if not isinstance(publication_gate, dict): - raise EvidenceError("preserved R1 has no post-build publication gate") - if ( + if not isinstance(publication_gate, dict) or ( publication_gate.get("satisfied") is not False or publication_gate.get("external_to_candidate") is not True ): - raise EvidenceError("preserved candidate publication gate was rewritten") + raise EvidenceError("preserved August 14 candidate gate was rewritten") governance_effect = signature_receipt.get("governance_effect") - if not isinstance(governance_effect, dict) or governance_effect.get("public_release_authorized") is not False: - raise EvidenceError("signature receipt must remain nonauthorizing") - validate_resolved_publication_state(rows, authorization, gates) - validate_public_documentation() + if not isinstance(governance_effect, dict) or ( + governance_effect.get("public_release_authorized") is not False + ): + raise EvidenceError("historical signature receipt must remain nonauthorizing") + validate_resolved_publication_state(historical_rows, authorization, gates) + + # Validate the independently published Full-Canon v0.3.5 row. + full_canon_row = by_tag["myth-v0.3.5"] + for record in (full_canon_reference, full_canon_publication): + artifact = record.get("artifact") + if not isinstance(artifact, dict): + raise EvidenceError("Full-Canon v0.3.5 record has no artifact") + for key in ("filename", "bytes", "sha256"): + if artifact.get(key) != full_canon_row["asset"][key]: + raise EvidenceError(f"Full-Canon v0.3.5 identity mismatch: {key}") + if ( + full_canon_row.get("canonical_r1") is not False + or full_canon_row.get("enabled_by_default") is not False + or full_canon_publication.get("relationship_to_r1") + != "SEPARATE_OPTIONAL_COMPANION_NOT_R1_ADMITTED" + or full_canon_publication.get("production_or_operational_deployment_authorized") + is not False + or full_canon_publication.get("operational_authority_granted") is not False + ): + raise EvidenceError("Full-Canon v0.3.5 optional/nonauthorizing boundary failed") + + generic_row = by_tag["generic-myth-v0.2.0"] + generic_artifact = generic_reference.get("artifact") + generic_test_artifact = generic_tests.get("final_artifact") + if not isinstance(generic_artifact, dict) or not isinstance(generic_test_artifact, dict): + raise EvidenceError("Generic Myth reference/test artifact is missing") + if generic_reference.get("test_record") != ( + "governance/GENERIC_MYTH_v0.2.0_BUILD_AND_TEST_REPORT_2026-08-17.json" + ): + raise EvidenceError("Generic Myth test-record pointer mismatch") + if generic_reference.get("authorization_record") != ( + "governance/GENERIC_MYTH_v0.2.0_EXACT_HASH_PUBLIC_RELEASE_AUTHORIZATION_2026-08-17.json" + ): + raise EvidenceError("Generic Myth authorization-record pointer mismatch") + boundaries = generic_reference.get("boundaries") + if not isinstance(boundaries, dict): + raise EvidenceError("Generic Myth boundary object missing") + for key in ( + "canonical_r1_component", + "changes_operational_result", + "default_off", + "feedback_allowed", + "gate_input_eligible", + "model_context_eligible", + "operational_deployment_authorized", + "production_authorized", + "required_for_r1", + "terminal_only", + "tool_argument_eligible", + ): + expected = key in {"default_off", "terminal_only"} + if boundaries.get(key) is not expected: + raise EvidenceError(f"Generic Myth boundary mismatch: {key}") + + inner = inner_admission.get("inner") + outer_asset = outer_authorization.get("outer") + if not isinstance(outer_asset, dict): + outer_asset = outer_authorization.get("asset") + if not isinstance(inner, dict) or not isinstance(outer_asset, dict): + raise EvidenceError("R1.0.1 inner/outer identity record missing") + if ( + inner.get("active_descendant_count") != 27 + or inner.get("operational_descendant_bytes_changed") != 0 + or inner.get("myth_payload_embedded") is not False + ): + raise EvidenceError("R1.0.1 inner invariants failed") + if "nonclaims" in outer_authorization: + check_nonclaims("R1.0.1 outer authorization", outer_authorization.get("nonclaims")) + check_nonclaims("CAPA", capa.get("nonclaims")) + check_nonclaims("current release status", current_status.get("nonclaims")) + + pending_identities = False + if phase == "PREPUBLICATION": + prepublication_state = manifest.get("prepublication_state") + if prepublication_state == "PENDING_IDENTITIES": + pending_identities = True + require_pending_tokens() + if generic_reference.get("publication", {}).get("state") != ( + "PENDING_FINAL_HARDENED_IDENTITY" + ): + raise EvidenceError("Generic Myth reference is not pending final identity") + if generic_tests.get("status") != "PENDING_HARDENED_REBUILD_AND_RETEST": + raise EvidenceError("Generic Myth test record overstates final status") + if generic_row.get("publication_state") != "PENDING_FINAL_HARDENED_IDENTITY": + raise EvidenceError("Generic Myth manifest state is not pending") + for artifact in ( + generic_row["asset"], + generic_artifact, + generic_test_artifact, + ): + if artifact.get("bytes") is not None or artifact.get("sha256") is not None: + raise EvidenceError("Generic Myth pending identity must remain null") + if ( + inner_admission.get("decision") != "PENDING_MAINTAINER_CONFIRMATION" + or inner_admission.get("maintainer_confirmation") is not None + or inner.get("bytes") is not None + or inner.get("sha256") is not None + ): + raise EvidenceError("R1.0.1 inner admission placeholder is not fail-closed") + if ( + outer_authorization.get("status") != "PENDING_EXACT_HASH_AUTHORIZATION" + or outer_authorization.get("authorization", {}).get( + "publication_authorized" + ) + is not False + or outer_asset.get("bytes") is not None + or outer_asset.get("sha256") is not None + ): + raise EvidenceError( + "R1.0.1 outer authorization placeholder is not fail-closed" + ) + elif prepublication_state == "AWAITING_OUTER_EXACT_HASH_AUTHORIZATION": + placeholder_findings = release_placeholder_findings() + if placeholder_findings: + raise EvidenceError( + "exact-identity prepublication repository retains release placeholders: " + + ", ".join(placeholder_findings) + ) + if generic_row.get("publication_state") != "AUTHORIZED_FOR_PUBLIC_RELEASE": + raise EvidenceError("Generic Myth manifest authorization state mismatch") + if by_tag["r1.0.1-2026-08-17"].get("publication_state") != ( + "PENDING_EXACT_HASH_AUTHORIZATION" + ): + raise EvidenceError("R1.0.1 manifest is not pending exact-hash authorization") + require_exact_identity("Generic Myth manifest", generic_row.get("asset"), GENERIC_FINAL) + require_exact_identity( + "R1.0.1 manifest", + by_tag["r1.0.1-2026-08-17"].get("asset"), + OUTER_FINAL, + ) + require_exact_identity("Generic Myth reference", generic_artifact, GENERIC_FINAL) + if generic_artifact.get("frozen") is not True or ( + generic_reference.get("publication", {}).get("state") + != "AUTHORIZED_FOR_PUBLIC_RELEASE" + ): + raise EvidenceError("Generic Myth frozen/authorized state mismatch") + validate_final_generic_tests(generic_tests) + validate_gate_1_authority(generic_authorization, inner_admission) + inner_note = RELEASE_NOTES["r1.0.1-2026-08-17"].read_text( + encoding="utf-8" + ) + for marker in ( + INNER_FINAL["filename"], + str(INNER_FINAL["sha256"]), + f"{INNER_FINAL['bytes']:,}", + ): + if marker not in inner_note: + raise EvidenceError( + f"R1.0.1 release notes omit admitted inner identity: {marker}" + ) + require_exact_identity("R1.0.1 outer authority slot", outer_asset, OUTER_FINAL) + if ( + outer_authorization.get("schema") + != "project-shadow.r1.0.1-outer-exact-hash-public-release-authorization.pending.v1" + or outer_authorization.get("status") + != "PENDING_EXACT_HASH_AUTHORIZATION" + or outer_authorization.get("authorization") + != { + "confirmed_at": None, + "confirmed_by": None, + "publication_authorized": False, + "statement": None, + } + ): + raise EvidenceError("R1.0.1 outer authorization is not fail-closed") + if ( + current_status.get("generic_myth", {}).get( + "final_hardened_identity_bound" + ) + is not True + or current_status.get("generic_myth", {}).get( + "publication_authorization_recorded" + ) + is not True + or current_status.get("generic_myth", {}).get("publication_state") + != "AUTHORIZED_FOR_PUBLIC_RELEASE" + or current_status.get("current_reference", {}).get( + "final_outer_identity_bound" + ) + is not True + or current_status.get("current_reference", {}).get( + "inner_exact_hash_admitted" + ) + is not True + or current_status.get("current_reference", {}).get("publication_state") + != "PENDING_EXACT_HASH_AUTHORIZATION" + or capa.get("implementation", {}).get("final_exact_identities_bound") + is not True + or capa.get("implementation", {}).get( + "generic_exact_hash_publication_authorized" + ) + is not True + or capa.get("implementation", {}).get("inner_exact_hash_admitted") + is not True + or capa.get("implementation", {}).get( + "outer_exact_hash_publication_authorized" + ) + is not False + ): + raise EvidenceError("awaiting-outer-authorization state is incomplete") + elif prepublication_state == "READY_TO_PUBLISH": + placeholder_findings = release_placeholder_findings() + if placeholder_findings: + raise EvidenceError( + "ready prepublication repository retains release placeholders: " + + ", ".join(placeholder_findings) + ) + for tag in ("generic-myth-v0.2.0", "r1.0.1-2026-08-17"): + if by_tag[tag].get("publication_state") != "READY_TO_PUBLISH": + raise EvidenceError(f"prepublication row is not READY_TO_PUBLISH: {tag}") + validate_asset_row(by_tag[tag], manifest["repository"]) + if generic_reference.get("publication", {}).get("state") != ( + "READY_TO_PUBLISH" + ): + raise EvidenceError("Generic Myth ready evidence is incomplete") + validate_final_generic_tests(generic_tests) + validate_gate_1_authority(generic_authorization, inner_admission) + for artifact in (generic_artifact, generic_test_artifact): + for key in ("filename", "bytes", "sha256"): + if artifact.get(key) != generic_row["asset"][key]: + raise EvidenceError(f"Generic Myth final identity mismatch: {key}") + inner_note = RELEASE_NOTES["r1.0.1-2026-08-17"].read_text( + encoding="utf-8" + ) + for marker in ( + inner["filename"], + str(inner["sha256"]), + f"{inner['bytes']:,}", + ): + if marker not in inner_note: + raise EvidenceError( + f"R1.0.1 release notes omit admitted inner identity: {marker}" + ) + current_r1_asset = by_tag["r1.0.1-2026-08-17"]["asset"] + for key in ("filename", "bytes", "sha256"): + if outer_asset.get(key) != current_r1_asset[key]: + raise EvidenceError(f"R1.0.1 outer authorization mismatch: {key}") + validate_outer_authority(outer_authorization) + if ( + current_status.get("generic_myth", {}).get( + "final_hardened_identity_bound" + ) + is not True + or current_status.get("current_reference", {}).get( + "final_outer_identity_bound" + ) + is not True + or current_status.get("current_reference", {}).get( + "inner_exact_hash_admitted" + ) + is not True + or current_status.get("generic_myth", {}).get("publication_state") + != "READY_TO_PUBLISH" + or current_status.get("current_reference", {}).get("publication_state") + != "READY_TO_PUBLISH" + or capa.get("implementation", {}).get("final_exact_identities_bound") + is not True + or capa.get("implementation", {}).get( + "generic_exact_hash_publication_authorized" + ) + is not True + or capa.get("implementation", {}).get("inner_exact_hash_admitted") + is not True + or capa.get("implementation", {}).get( + "outer_exact_hash_publication_authorized" + ) + is not True + ): + raise EvidenceError("ready prepublication identity state is incomplete") + else: + raise EvidenceError( + f"unsupported prepublication state: {prepublication_state!r}" + ) + if ( + current_status.get("publication_phase") != "PREPUBLICATION" + or current_status.get("capa", {}).get("status") + != "IMPLEMENTED_PENDING_EFFECTIVENESS" + or current_status.get("capa", {}).get("effectiveness_verified") is not False + or capa.get("status") != "IMPLEMENTED_PENDING_EFFECTIVENESS" + or capa.get("closure", {}).get("effectiveness_verified") is not False + ): + raise EvidenceError("current status/CAPA prepublication state mismatch") + else: + placeholder_findings = release_placeholder_findings() + if placeholder_findings: + raise EvidenceError( + "postpublication repository retains release placeholders: " + + ", ".join(placeholder_findings) + ) + for tag in ("generic-myth-v0.2.0", "r1.0.1-2026-08-17"): + if by_tag[tag].get("publication_state") != "PUBLISHED": + raise EvidenceError(f"postpublication manifest row is not PUBLISHED: {tag}") + validate_asset_row(by_tag[tag], manifest["repository"]) + if ( + generic_reference.get("publication", {}).get("state") != "PUBLISHED" + or generic_tests.get("status") != "PASS" + ): + raise EvidenceError("Generic Myth postpublication evidence is incomplete") + validate_final_generic_tests(generic_tests) + validate_gate_1_authority(generic_authorization, inner_admission) + for artifact in (generic_artifact, generic_test_artifact): + for key in ("filename", "bytes", "sha256"): + if artifact.get(key) != generic_row["asset"][key]: + raise EvidenceError(f"Generic Myth final identity mismatch: {key}") + current_r1_asset = by_tag["r1.0.1-2026-08-17"]["asset"] + for key in ("filename", "bytes", "sha256"): + if outer_asset.get(key) != current_r1_asset[key]: + raise EvidenceError(f"R1.0.1 outer authorization mismatch: {key}") + validate_outer_authority(outer_authorization) + if ( + current_status.get("publication_phase") != "POSTPUBLICATION" + or current_status.get("capa", {}).get("status") != "CLOSED_EFFECTIVE" + or current_status.get("capa", {}).get("effectiveness_verified") is not True + or capa.get("status") != "CLOSED_EFFECTIVE" + or capa.get("closure", {}).get("effectiveness_verified") is not True + or capa.get("closure", {}).get("verification_record") + != "governance/R1_0_1_PUBLIC_REDOWNLOAD_VERIFICATION_2026-08-17.json" + ): + raise EvidenceError("current status/CAPA postpublication closure mismatch") + validate_current_redownload( + require_object(load_json(CURRENT_REDOWNLOAD), CURRENT_REDOWNLOAD.name), + by_tag, + ) + + validate_public_documentation(phase, pending_identities=pending_identities) return rows @@ -812,7 +1651,10 @@ def normalize_release_body(value: str) -> str: return value.replace("\r\n", "\n").replace("\r", "\n").rstrip() -def verify_live_release_metadata(rows: list[dict[str, Any]]) -> None: +def verify_live_release_metadata( + rows: list[dict[str, Any]], + expected_latest_tag: str, +) -> None: repository = "PauseBeforeHarmProtocol/Project-Shadow" for row in rows: tag = row["tag"] @@ -850,8 +1692,11 @@ def verify_live_release_metadata(rows: list[dict[str, Any]]) -> None: latest = fetch_public_json( f"https://api.github.com/repos/{repository}/releases/latest" ) - if latest.get("tag_name") != rows[-1]["tag"] or rows[-1].get("canonical_r1") is not True: - raise EvidenceError("canonical R1 is not the latest GitHub release") + if latest.get("tag_name") != expected_latest_tag: + raise EvidenceError( + f"unexpected latest GitHub release: expected {expected_latest_tag!r}; " + f"found {latest.get('tag_name')!r}" + ) def fetch_public_page(url: str) -> str: @@ -886,16 +1731,25 @@ def verify_public_site_release_links(rows: list[dict[str, Any]]) -> None: ) -def verify_online(rows: list[dict[str, Any]], destination: Path) -> None: +def verify_online( + rows: list[dict[str, Any]], + destination: Path, + *, + phase: str, + expected_latest_tag: str, +) -> None: + phase = phase_name(phase) + online_rows = published_rows(rows) if phase == "PREPUBLICATION" else rows downloaded: dict[str, Path] = {} repository = "PauseBeforeHarmProtocol/Project-Shadow" - for row in rows: + for row in online_rows: asset = row["asset"] downloaded[row["role"]] = download_and_hash(asset, destination) release_url = f"https://github.com/{repository}/releases/tag/{row['tag']}" check_link(release_url) - verify_live_release_metadata(rows) - verify_public_site_release_links(rows) + verify_live_release_metadata(online_rows, expected_latest_tag) + if phase == "POSTPUBLICATION": + verify_public_site_release_links(rows) r1 = downloaded.get("R1_REFERENCE") if r1 is None: @@ -934,6 +1788,12 @@ def parse_args() -> argparse.Namespace: type=Path, help="destination for online release downloads (required with --online)", ) + parser.add_argument( + "--phase", + choices=("auto", "prepublication", "postpublication"), + default="auto", + help="validate an explicit lifecycle phase (default: read the manifest)", + ) return parser.parse_args() @@ -944,7 +1804,13 @@ def main() -> int: return 2 try: json_count = parse_all_json() - rows = verify_repository_metadata() + manifest = require_object(load_json(PUBLICATION_MANIFEST), PUBLICATION_MANIFEST.name) + phase = ( + phase_name(str(manifest.get("publication_phase"))) + if args.phase == "auto" + else phase_name(args.phase) + ) + rows = verify_repository_metadata(phase) findings = prohibited_claim_findings() if findings: raise EvidenceError( @@ -952,18 +1818,33 @@ def main() -> int: + "\n - ".join(findings) ) if args.online: - verify_online(rows, args.download_dir.resolve()) + latest_by_phase = manifest.get("expected_github_latest_tag") + if not isinstance(latest_by_phase, dict): + raise EvidenceError("manifest lacks expected latest-tag phase map") + expected_latest = latest_by_phase.get(phase.lower()) + if not isinstance(expected_latest, str): + raise EvidenceError(f"manifest lacks latest-tag expectation for {phase}") + verify_online( + rows, + args.download_dir.resolve(), + phase=phase, + expected_latest_tag=expected_latest, + ) except EvidenceError as exc: print(f"FAIL: {exc}", file=sys.stderr) return 1 print(f"PASS: parsed {json_count} repository JSON files") - print("PASS: publication manifest, checksums, notes, and human authorization agree") - print("PASS: derived publication status, redownload receipt, and attestation agree") - print("PASS: Myth remains external, default-off, noncanonical, and nonauthorizing") - print("PASS: preserved candidate and signature records remain non-self-authorizing") + print(f"PASS: lifecycle phase {phase}") + print("PASS: publication manifest, notes, lifecycle records, and authority state agree") + print("PASS: historical August 14 status, redownload receipt, and attestation agree") + print("PASS: Myth companions remain external, default-off, and nonauthorizing") + print("PASS: corrected R1 boundary requires zero embedded Myth payload") + print("PASS: preserved historical candidate/signature records remain non-self-authorizing") print("PASS: nonclaim scan") if args.online: - print("PASS: exact public assets, release URLs, and six public-site release links") + print("PASS: exact published assets and release metadata") + if phase == "POSTPUBLICATION": + print("PASS: six public-site release links") else: print("INFO: network verification skipped (use --online --download-dir DIR)") return 0