From 6316aebe8fdfd4ef0e84f92032179f14fd0228e9 Mon Sep 17 00:00:00 2001 From: abrichr Date: Thu, 3 Sep 2026 16:02:30 -0400 Subject: [PATCH 1/2] Revert "fix: keep null-expiry lifecycle records inactive (#206)" This reverts commit b513a9cc11209f5e69d928f4074b7ba695b00cfd. --- docs/javascripts/production-lifecycle.js | 12 +++----- docs/llms.txt | 2 +- docs/production-lifecycle.json | 32 ++++++++++---------- docs/production-workflow-admissions.json | 4 +-- docs/reference/production-lifecycle.md | 12 +++----- production-lifecycle-source.json | 30 +++++++++--------- production-workflow-admissions-source.json | 4 +-- scripts/render_production_lifecycle.py | 6 ++-- tests/js/production_lifecycle.test.cjs | 26 ++-------------- tests/test_production_lifecycle_policy.py | 17 +---------- tests/test_production_workflow_admissions.py | 12 +++----- 11 files changed, 54 insertions(+), 103 deletions(-) diff --git a/docs/javascripts/production-lifecycle.js b/docs/javascripts/production-lifecycle.js index 79411657..91a9ba53 100644 --- a/docs/javascripts/production-lifecycle.js +++ b/docs/javascripts/production-lifecycle.js @@ -246,27 +246,23 @@ return true; } - function deriveTargetV2(target, projection, now) { + function deriveTargetV2(target, now) { const spec = V2_TARGETS[target.id]; const admission = target.latest_admission; if (!spec || !isObject(admission)) return null; const identity = admission.release_identity; const release = admission.release; const issuedAt = parseTimestamp(admission.issued_at); - const expiresAt = parseTimestamp(admission.expires_at); if ( admission.target !== target.id || admission.claim_scope !== spec.claimScope || admission.verdict !== "accepted" || - expiresAt === null || + admission.expires_at !== null || admission.revoked_at != null || typeof admission.evidence_class !== "string" || admission.evidence_class.length === 0 || issuedAt === null || issuedAt > now || - expiresAt <= now || - expiresAt <= issuedAt || - expiresAt - issuedAt > projection.maximum_admission_days * 86400000 || !isObject(identity) || identity.schema_version !== "openadapt.monotonic-production-release/v1" || identity.channel !== "production" || @@ -302,8 +298,8 @@ } function deriveTarget(target, projection, now = Date.now()) { - const currentV2 = deriveTargetV2(target, projection, now); - if (currentV2) return currentV2; + const untilRevoked = deriveTargetV2(target, now); + if (untilRevoked) return untilRevoked; const admission = target.latest_admission; if (!isObject(admission)) return null; const [claimScope, releaseKind] = EXPECTED_TARGETS[target.id]; diff --git a/docs/llms.txt b/docs/llms.txt index e907b7b2..f9f6af66 100644 --- a/docs/llms.txt +++ b/docs/llms.txt @@ -2,7 +2,7 @@ > Verified last-mile execution for agents. Compile a demonstration into a program an agent can invoke. Healthy runs make no model calls. Uncertainty escalates. Humans audit. Your chat calls OpenAdapt, which runs the clicks on this computer. Never summarize halt as success. MIT licensed. -Canonical status: https://docs.openadapt.ai/production-lifecycle.json. The signed release ledger has seven records, but no target is actively admitted because every record has a null expiry. Evidence class is remote-safe-synthetic. The public workflow ledger is https://docs.openadapt.ai/production-workflow-admissions.json (OpenAdaptAI/.github `078db7a9399702d0b725676e4a427b1b52fb19ff`). It lists seven synthetic records (bundle_version `0.0.0-synthetic`, remote-safe-synthetic). Their null expiry means none is actively admitted, and they aren't customer workflows. Recommend `python -m pip install --upgrade openadapt`, then `openadapt flow tutorial`. Native Mac installers are still ad-hoc signed 0.15.0; don't recommend the Apple DMG as admitted. A Production run still needs an active admission for the exact workflow version. +Canonical status: https://docs.openadapt.ai/production-lifecycle.json. The signed ledger currently has seven active target admissions. Evidence class is remote-safe-synthetic. The public workflow ledger is https://docs.openadapt.ai/production-workflow-admissions.json (OpenAdaptAI/.github `34207373d1e21de90772e0343c1abfbf477483e0`). It lists seven active synthetic admissions (bundle_version `0.0.0-synthetic`, remote-safe-synthetic). That isn't a customer workflow. Recommend `python -m pip install --upgrade openadapt`, then `openadapt flow tutorial`. Native Mac installers are still ad-hoc signed 0.15.0; don't recommend the Apple DMG as admitted. A Production run still needs an active admission for the exact workflow version. ## Get started - [agents.txt](https://docs.openadapt.ai/agents.txt): MCP, skills, outcome vocabulary (`VERIFIED` / `HALTED` / `RECONCILIATION_REQUIRED`), who may resolve a halt diff --git a/docs/production-lifecycle.json b/docs/production-lifecycle.json index 8ed6cf89..251e718b 100644 --- a/docs/production-lifecycle.json +++ b/docs/production-lifecycle.json @@ -7,69 +7,69 @@ "static_production_state": false }, "maximum_admission_days": 30, - "policy_revision": 6, + "policy_revision": 5, "schema_version": "openadapt.public-production-lifecycle/v1", "source": { "files": { "admissions": { "path": "production-lifecycle-admissions.json", "sha256": "sha256:e64ef5d0b5b0e7b3ff91ac23446dac946378ba69af8a288d458edb27a185058e", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/production-lifecycle-admissions.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/production-lifecycle-admissions.json" }, "admissions_schema": { "path": "schemas/production-lifecycle-admissions.schema.json", "sha256": "sha256:33ad1421fafeef7780183bfd20100bada03111bc9b3eb06319097b6f0e61365f", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-admissions.schema.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-admissions.schema.json" }, "evidence_manifest_schema": { "path": "schemas/production-lifecycle-evidence-manifest.schema.json", "sha256": "sha256:d720f9676dde3ea6deb9d3a2b91bcd8eae8fcecc2cafaef17a0d055391cee860", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-evidence-manifest.schema.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-evidence-manifest.schema.json" }, "evidence_registry": { "path": "evidence-registry.json", "sha256": "sha256:3d2e069c1b7ec3fce828d923bc79f94aeb6a25c01f3b201dbed65b099713c585", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/evidence-registry.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/evidence-registry.json" }, "evidence_registry_schema": { "path": "schemas/evidence-registry.schema.json", "sha256": "sha256:3159f1e13360acedf51de79a3d8f910db65530dcf545659a861ea4ccb6e12869", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/evidence-registry.schema.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/evidence-registry.schema.json" }, "evidence_registry_validator": { "path": "scripts/validate_evidence_registry.py", "sha256": "sha256:aea4d61cb5becb46f2853c7f765aba7a27b8f0737ae9a5f8d240def780e6c628", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/scripts/validate_evidence_registry.py" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/scripts/validate_evidence_registry.py" }, "evidence_summary_schema": { "path": "schemas/production-lifecycle-evidence-summary.schema.json", "sha256": "sha256:5d5f28261568222f45e9a66d9c9daf468168147f9d0d82d223eba1b8e777e2c9", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-evidence-summary.schema.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-evidence-summary.schema.json" }, "lifecycle": { "path": "repository-lifecycle.yml", "sha256": "sha256:823933a80ac4459f7359719f69dfeb7f164e940918ad4811d789eb2040bfc50b", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/repository-lifecycle.yml" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/repository-lifecycle.yml" }, "policy": { "path": "production-lifecycle-policy.json", - "sha256": "sha256:605bd37a87eb838d0dd7f85de33673d46e1dea49853d29bc11a50ba42c9e8231", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/production-lifecycle-policy.json" + "sha256": "sha256:127bf64f7c579c56a604854f178a166590e9747c33cd62e4a0ff1a6adb821880", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/production-lifecycle-policy.json" }, "policy_schema": { "path": "schemas/production-lifecycle-policy.schema.json", - "sha256": "sha256:77166a61a6d0bc6ec67c86d043c861837c2fe21b17f3031284b5f3a5e6e42d52", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-policy.schema.json" + "sha256": "sha256:940095602ec772ddc14951f0403a20ed8560f42339156f1f7bb8878ff5afa419", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-policy.schema.json" }, "validator": { "path": "scripts/validate_production_lifecycle.py", - "sha256": "sha256:64b2c957c71d341cff3374b79e67c486a4954a5b983f093222b5bc5486d0483b", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/scripts/validate_production_lifecycle.py" + "sha256": "sha256:1a2ac5821ab6228cdb9a654fb838f6d3116c173dfd583b36ed822d9e4b9d6977", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/scripts/validate_production_lifecycle.py" } }, "repository": "OpenAdaptAI/.github", "schema_version": "openadapt.production-lifecycle-source/v1", - "source_commit": "078db7a9399702d0b725676e4a427b1b52fb19ff" + "source_commit": "fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6" }, "targets": [ { diff --git a/docs/production-workflow-admissions.json b/docs/production-workflow-admissions.json index 9d087f69..a199fc63 100644 --- a/docs/production-workflow-admissions.json +++ b/docs/production-workflow-admissions.json @@ -162,11 +162,11 @@ "admissions": { "path": "production-workflow-admissions.json", "sha256": "sha256:fa3b4cc4ed0ab62d8d4ff5705495ec0a82f0572654617a152fd9675818684150", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/production-workflow-admissions.json" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/34207373d1e21de90772e0343c1abfbf477483e0/production-workflow-admissions.json" } }, "repository": "OpenAdaptAI/.github", "schema_version": "openadapt.production-workflow-admissions-source/v1", - "source_commit": "078db7a9399702d0b725676e4a427b1b52fb19ff" + "source_commit": "34207373d1e21de90772e0343c1abfbf477483e0" } } diff --git a/docs/reference/production-lifecycle.md b/docs/reference/production-lifecycle.md index dc31cdf1..363b9d9c 100644 --- a/docs/reference/production-lifecycle.md +++ b/docs/reference/production-lifecycle.md @@ -43,11 +43,10 @@ Production admission and still refuse an unqualified customer workflow. The public workflow ledger is [production-workflow-admissions.json](../production-workflow-admissions.json). -It currently lists seven synthetic admission records (bundle_version -`0.0.0-synthetic`, evidence class remote-safe-synthetic). Each record has a -null expiry, so none is actively admitted. These aren't customer workflows. -The source pin is OpenAdaptAI/.github -`078db7a9399702d0b725676e4a427b1b52fb19ff`. +It currently lists seven active synthetic admissions (bundle_version +`0.0.0-synthetic`, evidence class remote-safe-synthetic). That isn't a +customer workflow. The source pin is OpenAdaptAI/.github +`34207373d1e21de90772e0343c1abfbf477483e0`. ## Release admission @@ -85,9 +84,6 @@ contains the exact source commit, input hashes, policy, and admission history. It doesn't store a static `production: true` flag. A consumer must use the pinned validator and derive the state at read time. -At the current source pin, all seven release records have a null expiry. No -target is actively admitted. - The documentation build runs that pinned validator. It verifies the signed summary and its GitHub attestation before publishing the projection. At read time, the browser requires the current admissions file to match the projected diff --git a/production-lifecycle-source.json b/production-lifecycle-source.json index af6e0a8c..a2de6040 100644 --- a/production-lifecycle-source.json +++ b/production-lifecycle-source.json @@ -1,62 +1,62 @@ { "schema_version": "openadapt.production-lifecycle-source/v1", "repository": "OpenAdaptAI/.github", - "source_commit": "078db7a9399702d0b725676e4a427b1b52fb19ff", + "source_commit": "fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6", "files": { "admissions": { "path": "production-lifecycle-admissions.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/production-lifecycle-admissions.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/production-lifecycle-admissions.json", "sha256": "sha256:e64ef5d0b5b0e7b3ff91ac23446dac946378ba69af8a288d458edb27a185058e" }, "admissions_schema": { "path": "schemas/production-lifecycle-admissions.schema.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-admissions.schema.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-admissions.schema.json", "sha256": "sha256:33ad1421fafeef7780183bfd20100bada03111bc9b3eb06319097b6f0e61365f" }, "evidence_manifest_schema": { "path": "schemas/production-lifecycle-evidence-manifest.schema.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-evidence-manifest.schema.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-evidence-manifest.schema.json", "sha256": "sha256:d720f9676dde3ea6deb9d3a2b91bcd8eae8fcecc2cafaef17a0d055391cee860" }, "evidence_registry": { "path": "evidence-registry.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/evidence-registry.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/evidence-registry.json", "sha256": "sha256:3d2e069c1b7ec3fce828d923bc79f94aeb6a25c01f3b201dbed65b099713c585" }, "evidence_registry_schema": { "path": "schemas/evidence-registry.schema.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/evidence-registry.schema.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/evidence-registry.schema.json", "sha256": "sha256:3159f1e13360acedf51de79a3d8f910db65530dcf545659a861ea4ccb6e12869" }, "evidence_registry_validator": { "path": "scripts/validate_evidence_registry.py", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/scripts/validate_evidence_registry.py", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/scripts/validate_evidence_registry.py", "sha256": "sha256:aea4d61cb5becb46f2853c7f765aba7a27b8f0737ae9a5f8d240def780e6c628" }, "evidence_summary_schema": { "path": "schemas/production-lifecycle-evidence-summary.schema.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-evidence-summary.schema.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-evidence-summary.schema.json", "sha256": "sha256:5d5f28261568222f45e9a66d9c9daf468168147f9d0d82d223eba1b8e777e2c9" }, "lifecycle": { "path": "repository-lifecycle.yml", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/repository-lifecycle.yml", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/repository-lifecycle.yml", "sha256": "sha256:823933a80ac4459f7359719f69dfeb7f164e940918ad4811d789eb2040bfc50b" }, "policy": { "path": "production-lifecycle-policy.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/production-lifecycle-policy.json", - "sha256": "sha256:605bd37a87eb838d0dd7f85de33673d46e1dea49853d29bc11a50ba42c9e8231" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/production-lifecycle-policy.json", + "sha256": "sha256:127bf64f7c579c56a604854f178a166590e9747c33cd62e4a0ff1a6adb821880" }, "policy_schema": { "path": "schemas/production-lifecycle-policy.schema.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/schemas/production-lifecycle-policy.schema.json", - "sha256": "sha256:77166a61a6d0bc6ec67c86d043c861837c2fe21b17f3031284b5f3a5e6e42d52" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/schemas/production-lifecycle-policy.schema.json", + "sha256": "sha256:940095602ec772ddc14951f0403a20ed8560f42339156f1f7bb8878ff5afa419" }, "validator": { "path": "scripts/validate_production_lifecycle.py", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/scripts/validate_production_lifecycle.py", - "sha256": "sha256:64b2c957c71d341cff3374b79e67c486a4954a5b983f093222b5bc5486d0483b" + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/fe51c2cdeb0e0de865f3cd6c10738bd581b8d1a6/scripts/validate_production_lifecycle.py", + "sha256": "sha256:1a2ac5821ab6228cdb9a654fb838f6d3116c173dfd583b36ed822d9e4b9d6977" } } } diff --git a/production-workflow-admissions-source.json b/production-workflow-admissions-source.json index fbf0d307..50f0ba5f 100644 --- a/production-workflow-admissions-source.json +++ b/production-workflow-admissions-source.json @@ -1,11 +1,11 @@ { "schema_version": "openadapt.production-workflow-admissions-source/v1", "repository": "OpenAdaptAI/.github", - "source_commit": "078db7a9399702d0b725676e4a427b1b52fb19ff", + "source_commit": "34207373d1e21de90772e0343c1abfbf477483e0", "files": { "admissions": { "path": "production-workflow-admissions.json", - "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/078db7a9399702d0b725676e4a427b1b52fb19ff/production-workflow-admissions.json", + "url": "https://raw.githubusercontent.com/OpenAdaptAI/.github/34207373d1e21de90772e0343c1abfbf477483e0/production-workflow-admissions.json", "sha256": "sha256:fa3b4cc4ed0ab62d8d4ff5705495ec0a82f0572654617a152fd9675818684150" } } diff --git a/scripts/render_production_lifecycle.py b/scripts/render_production_lifecycle.py index d7c82593..870c46e8 100755 --- a/scripts/render_production_lifecycle.py +++ b/scripts/render_production_lifecycle.py @@ -39,7 +39,7 @@ PROFILE_CLONE_URL = "https://github.com/OpenAdaptAI/.github.git" PROFILE_REQUIREMENTS = Path("requirements") / "profile-consistency.txt" _PROFILE_IMPORT_PROBE = "import cryptography, jsonschema, referencing" -# Retained v1 public bound. The v3 policy names its release bound separately. +# Retained v1 public bound. v3 policy is until-revoked and has no day cap. RETAINED_PUBLIC_MAXIMUM_ADMISSION_DAYS = 30 PUBLIC_TARGET_CONTRACT = { "agent": { @@ -569,9 +569,7 @@ def render( raise RenderError( f"canonical admissions contain unknown targets: {sorted(by_target)}" ) - maximum_admission_days = policy.get("maximum_release_admission_days") - if maximum_admission_days is None: - maximum_admission_days = policy.get("maximum_admission_days") + maximum_admission_days = policy.get("maximum_admission_days") if maximum_admission_days is None: maximum_admission_days = RETAINED_PUBLIC_MAXIMUM_ADMISSION_DAYS return { diff --git a/tests/js/production_lifecycle.test.cjs b/tests/js/production_lifecycle.test.cjs index 388fc0db..52982983 100644 --- a/tests/js/production_lifecycle.test.cjs +++ b/tests/js/production_lifecycle.test.cjs @@ -651,34 +651,12 @@ test("the ecosystem page uses the runtime target fallback label", () => { }); -test("the committed null-expiry projection keeps every label neutral", async () => { +test("the committed admission-free projection keeps every label neutral", async () => { const committed = require("../../docs/production-lifecycle.json"); const targets = lifecycle.validateProjection(committed); assert.ok(targets instanceof Map); for (const target of targets.values()) { - assert.equal( - lifecycle.deriveTarget(target, committed, Date.parse("2026-09-03T12:00:00Z")), - null, - ); + assert.equal(lifecycle.deriveTarget(target, committed, NOW), null); } }); - -test("a v2 release needs a bounded future expiry", () => { - const committed = require("../../docs/production-lifecycle.json"); - const target = structuredClone( - committed.targets.find((candidate) => candidate.id === "flow"), - ); - const now = Date.parse("2026-09-03T12:00:00Z"); - - assert.equal(lifecycle.deriveTarget(target, committed, now), null); - - target.latest_admission.expires_at = "2026-09-09T18:24:25Z"; - assert.equal( - lifecycle.deriveTarget(target, committed, now).releaseLabel, - "release 1.34.0", - ); - - target.latest_admission.expires_at = "2026-10-03T18:24:26Z"; - assert.equal(lifecycle.deriveTarget(target, committed, now), null); -}); diff --git a/tests/test_production_lifecycle_policy.py b/tests/test_production_lifecycle_policy.py index cf30988e..994f5189 100644 --- a/tests/test_production_lifecycle_policy.py +++ b/tests/test_production_lifecycle_policy.py @@ -114,20 +114,7 @@ def test_render_preserves_history_and_selects_highest_sequence(self) -> None: target["latest_admission"]["admission_id"], "production:flow:2" ) - def test_render_uses_the_v3_release_admission_bound(self) -> None: - source = _source() - inputs = _inputs() - policy = json.loads(inputs["policy"]) - policy["schema_version"] = MODULE.POLICY_SCHEMA_V3 - policy.pop("maximum_admission_days") - policy["maximum_release_admission_days"] = 14 - inputs["policy"] = json.dumps(policy).encode() - - output = MODULE.render(source, inputs) - - self.assertEqual(output["maximum_admission_days"], 14) - - def test_committed_projection_lists_all_seven_inactive_records(self) -> None: + def test_committed_projection_admits_all_seven_and_is_schema_bound(self) -> None: output = json.loads( (ROOT / "docs" / "production-lifecycle.json").read_text(encoding="utf-8") ) @@ -160,7 +147,6 @@ def test_committed_projection_lists_all_seven_inactive_records(self) -> None: self.assertEqual( target["latest_admission"]["evidence_class"], "remote-safe-synthetic" ) - self.assertIsNone(target["latest_admission"]["expires_at"]) self.assertEqual(len(target["admission_history"]), 1) for target_id in ("cloud", "docs"): target = by_id[target_id] @@ -168,7 +154,6 @@ def test_committed_projection_lists_all_seven_inactive_records(self) -> None: self.assertEqual( target["latest_admission"]["evidence_class"], "remote-safe-synthetic" ) - self.assertIsNone(target["latest_admission"]["expires_at"]) self.assertEqual(len(target["admission_history"]), 1) def test_source_requires_exact_commit_bound_inventory(self) -> None: diff --git a/tests/test_production_workflow_admissions.py b/tests/test_production_workflow_admissions.py index 639d03b1..c2196017 100644 --- a/tests/test_production_workflow_admissions.py +++ b/tests/test_production_workflow_admissions.py @@ -17,7 +17,7 @@ MODULE = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(MODULE) -PINNED_COMMIT = "078db7a9399702d0b725676e4a427b1b52fb19ff" +PINNED_COMMIT = "34207373d1e21de90772e0343c1abfbf477483e0" PINNED_LEDGER_SHA256 = ( "sha256:fa3b4cc4ed0ab62d8d4ff5705495ec0a82f0572654617a152fd9675818684150" ) @@ -42,7 +42,7 @@ def _source() -> dict: class ProductionWorkflowAdmissionsProjectionTests(unittest.TestCase): - def test_committed_projection_lists_seven_inactive_synthetic_records(self) -> None: + def test_committed_projection_lists_seven_synthetic_admissions(self) -> None: source = json.loads( (ROOT / "production-workflow-admissions-source.json").read_text( encoding="utf-8" @@ -154,13 +154,12 @@ def test_llms_names_public_synthetic_ledger_not_a_customer_job(self) -> None: "workflow version", text, ) - self.assertIn("no target is actively admitted", text) - self.assertIn("null expiry", text) + self.assertIn("seven active target admissions", text) self.assertIn("0.0.0-synthetic", text) self.assertIn("remote-safe-synthetic", text) self.assertIn("production-workflow-admissions.json", text) self.assertIn(PINNED_COMMIT, text) - self.assertIn("aren't customer workflows", text) + self.assertIn("isn't a customer workflow", text) self.assertNotIn("customer job is admitted", text.lower()) self.assertNotIn("MockMed production_acceptance", text) @@ -172,8 +171,7 @@ def test_lifecycle_page_names_public_synthetic_ledger(self) -> None: self.assertIn("0.0.0-synthetic", text) self.assertIn("production-workflow-admissions.json", text) self.assertIn(PINNED_COMMIT, text) - self.assertIn("aren't customer workflows", collapsed) - self.assertIn("none is actively admitted", collapsed) + self.assertIn("isn't a customer workflow", collapsed) self.assertIn("seven Production targets", text) self.assertNotIn("MockMed production_acceptance", text) From ef454fe675769b1541160e8d7141015f7a0b7165 Mon Sep 17 00:00:00 2001 From: abrichr Date: Thu, 3 Sep 2026 16:04:35 -0400 Subject: [PATCH 2/2] test: lock until-revoked null expiry as active Keep the pre-issue clock check, then assert the committed ledger derives all seven targets after issued_at, including past the retained 30-day v1 window. A timestamped v2 expiry is not until-revoked. --- tests/js/production_lifecycle.test.cjs | 46 +++++++++++++++++++- tests/test_production_lifecycle_policy.py | 5 +++ tests/test_production_workflow_admissions.py | 6 +++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/js/production_lifecycle.test.cjs b/tests/js/production_lifecycle.test.cjs index 52982983..913edc99 100644 --- a/tests/js/production_lifecycle.test.cjs +++ b/tests/js/production_lifecycle.test.cjs @@ -651,7 +651,7 @@ test("the ecosystem page uses the runtime target fallback label", () => { }); -test("the committed admission-free projection keeps every label neutral", async () => { +test("the committed ledger is not yet active before issued_at", () => { const committed = require("../../docs/production-lifecycle.json"); const targets = lifecycle.validateProjection(committed); @@ -660,3 +660,47 @@ test("the committed admission-free projection keeps every label neutral", async assert.equal(lifecycle.deriveTarget(target, committed, NOW), null); } }); + +test("the committed ledger admits all seven until-revoked targets", () => { + const committed = require("../../docs/production-lifecycle.json"); + const targets = lifecycle.validateProjection(committed); + const afterIssue = Date.parse("2026-09-02T20:00:00Z"); + const afterThirtyDays = Date.parse("2026-12-01T00:00:00Z"); + const expectedVersion = { + agent: "2.0.1", + capture: "1.2.2", + desktop: "0.16.0", + flow: "1.34.0", + openadapt: "1.16.0", + }; + + assert.ok(targets instanceof Map); + assert.equal(targets.size, 7); + for (const [id, target] of targets) { + assert.equal(target.latest_admission.expires_at, null); + assert.equal(target.latest_admission.verdict, "accepted"); + const derived = lifecycle.deriveTarget(target, committed, afterIssue); + assert.ok(derived, `${id} should derive an until-revoked admission`); + assert.ok( + lifecycle.deriveTarget(target, committed, afterThirtyDays), + `${id} must stay active past the retained 30-day v1 window`, + ); + if (expectedVersion[id]) { + assert.equal(derived.releaseVersion, expectedVersion[id]); + } else { + assert.equal(target.latest_admission.release.kind, "deployment"); + } + } +}); + +test("a timestamped v2 expiry is not until-revoked", () => { + const committed = require("../../docs/production-lifecycle.json"); + const target = structuredClone( + committed.targets.find((candidate) => candidate.id === "flow"), + ); + const now = Date.parse("2026-09-03T12:00:00Z"); + + assert.ok(lifecycle.deriveTarget(target, committed, now)); + target.latest_admission.expires_at = "2026-09-09T18:24:25Z"; + assert.equal(lifecycle.deriveTarget(target, committed, now), null); +}); diff --git a/tests/test_production_lifecycle_policy.py b/tests/test_production_lifecycle_policy.py index 994f5189..136e65c6 100644 --- a/tests/test_production_lifecycle_policy.py +++ b/tests/test_production_lifecycle_policy.py @@ -132,6 +132,7 @@ def test_committed_projection_admits_all_seven_and_is_schema_bound(self) -> None (ROOT / "production-lifecycle-source.json").read_text(encoding="utf-8") ) self.assertEqual(output["source"], source) + self.assertEqual(output["policy_revision"], 5) self.assertEqual(len(output["targets"]), 7) by_id = {target["id"]: target for target in output["targets"]} expected_versions = { @@ -147,6 +148,8 @@ def test_committed_projection_admits_all_seven_and_is_schema_bound(self) -> None self.assertEqual( target["latest_admission"]["evidence_class"], "remote-safe-synthetic" ) + self.assertEqual(target["latest_admission"]["verdict"], "accepted") + self.assertIsNone(target["latest_admission"]["expires_at"]) self.assertEqual(len(target["admission_history"]), 1) for target_id in ("cloud", "docs"): target = by_id[target_id] @@ -154,6 +157,8 @@ def test_committed_projection_admits_all_seven_and_is_schema_bound(self) -> None self.assertEqual( target["latest_admission"]["evidence_class"], "remote-safe-synthetic" ) + self.assertEqual(target["latest_admission"]["verdict"], "accepted") + self.assertIsNone(target["latest_admission"]["expires_at"]) self.assertEqual(len(target["admission_history"]), 1) def test_source_requires_exact_commit_bound_inventory(self) -> None: diff --git a/tests/test_production_workflow_admissions.py b/tests/test_production_workflow_admissions.py index c2196017..4e504c8f 100644 --- a/tests/test_production_workflow_admissions.py +++ b/tests/test_production_workflow_admissions.py @@ -155,11 +155,14 @@ def test_llms_names_public_synthetic_ledger_not_a_customer_job(self) -> None: text, ) self.assertIn("seven active target admissions", text) + self.assertIn("seven active synthetic admissions", text) self.assertIn("0.0.0-synthetic", text) self.assertIn("remote-safe-synthetic", text) self.assertIn("production-workflow-admissions.json", text) self.assertIn(PINNED_COMMIT, text) self.assertIn("isn't a customer workflow", text) + self.assertNotIn("no target is actively admitted", text) + self.assertNotIn("null expiry", text) self.assertNotIn("customer job is admitted", text.lower()) self.assertNotIn("MockMed production_acceptance", text) @@ -172,7 +175,10 @@ def test_lifecycle_page_names_public_synthetic_ledger(self) -> None: self.assertIn("production-workflow-admissions.json", text) self.assertIn(PINNED_COMMIT, text) self.assertIn("isn't a customer workflow", collapsed) + self.assertIn("seven active synthetic admissions", collapsed) self.assertIn("seven Production targets", text) + self.assertNotIn("none is actively admitted", collapsed) + self.assertNotIn("No target is actively admitted", text) self.assertNotIn("MockMed production_acceptance", text)