diff --git a/.github/scripts/test_milestone_e_package_publication_approval_prep.py b/.github/scripts/test_milestone_e_package_publication_approval_prep.py index c7699148..4b7e5686 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_prep.py @@ -175,6 +175,43 @@ "package publication remains blocked", ], } +EXPECTED_PACKAGE_PUBLICATION_DECISION_PREP_BUNDLE = { + "decision_state": "combined_decision_inputs_recorded_actions_blocked", + "review_boundary": [ + "package tag and source-commit decision inputs are recorded while creating no package tag", + "package dependency manifest activation inputs are recorded while changing no Cargo manifest", + "registry-backed dependent package assembly inputs are recorded while creating no registry and activating no assembly", + "public installation wording and exclusion inputs are recorded while inviting no public installation", + ], + "required_decision_inputs": [ + "exact package tag name", + "exact source commit for package tag binding", + "exact package-name migration diff for ethos-doc-core", + "exact dependency manifest activation diff for ethos-verify and ethos-pdf", + "exact registry-backed dependent package assembly evidence for ethos-doc-core before ethos-verify and ethos-pdf", + "exact public installation wording limited to a later approved package surface", + "exact exclusion list for wheels, npm packages, binaries, hosted surfaces, production positioning, public benchmark reports, public benchmark claims, and project-maintained PDFium builds", + "posture and claims gates after exact public installation wording changes", + ], + "non_approvals": [ + "this bundle does not select a package publication version", + "this bundle does not create a package tag", + "this bundle does not change Cargo manifests", + "this bundle does not activate package dependency manifests", + "this bundle does not create a registry", + "this bundle does not activate registry-backed dependent package assembly", + "this bundle does not invite public installation", + "this bundle does not approve package publication", + ], + "retained_blockers": [ + "no package publication version is selected", + "no package tag is created", + "no package dependency manifest activation is approved", + "no registry-backed dependent package assembly activation is approved", + "public installation remains blocked", + "package publication remains blocked", + ], +} FORBIDDEN_PREP_WORDING = [ "public beta is approved", @@ -465,6 +502,45 @@ def test_semver_package_version_decision_prep_keeps_version_unselected(self) -> self.assertIn("public installation remains blocked", review["retained_blockers"]) self.assertIn("package publication remains blocked", review["retained_blockers"]) + def test_combined_package_publication_decision_prep_bundle_blocks_all_actions(self) -> None: + bundle = load_json(PREP)["package_publication_decision_prep_bundle"] + cargo = read(ROOT / "Cargo.toml") + core_manifest = read(ROOT / "crates/ethos-core/Cargo.toml") + verify_manifest = read(ROOT / "crates/ethos-verify/Cargo.toml") + pdf_manifest = read(ROOT / "crates/ethos-pdf/Cargo.toml") + + self.assertEqual(EXPECTED_PACKAGE_PUBLICATION_DECISION_PREP_BUNDLE, bundle) + self.assertEqual("combined_decision_inputs_recorded_actions_blocked", bundle["decision_state"]) + self.assertIn("exact package tag name", bundle["required_decision_inputs"]) + self.assertIn("exact source commit for package tag binding", bundle["required_decision_inputs"]) + self.assertIn( + "exact dependency manifest activation diff for ethos-verify and ethos-pdf", + bundle["required_decision_inputs"], + ) + self.assertIn( + "exact registry-backed dependent package assembly evidence for ethos-doc-core before ethos-verify and ethos-pdf", + bundle["required_decision_inputs"], + ) + self.assertIn( + "posture and claims gates after exact public installation wording changes", + bundle["required_decision_inputs"], + ) + self.assertIn("this bundle does not create a package tag", bundle["non_approvals"]) + self.assertIn("this bundle does not change Cargo manifests", bundle["non_approvals"]) + self.assertIn("this bundle does not create a registry", bundle["non_approvals"]) + self.assertIn("this bundle does not invite public installation", bundle["non_approvals"]) + self.assertIn("this bundle does not approve package publication", bundle["non_approvals"]) + self.assertIn("no package tag is created", bundle["retained_blockers"]) + self.assertIn("public installation remains blocked", bundle["retained_blockers"]) + self.assertIn("package publication remains blocked", bundle["retained_blockers"]) + self.assertIn("publish = false", core_manifest) + self.assertIn("publish = false", verify_manifest) + self.assertIn("publish = false", pdf_manifest) + self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-verify"', verify_manifest) + self.assertIn('name = "ethos-pdf"', pdf_manifest) + self.assertIn('version = "0.1.0"', cargo) + def test_pdfium_boundary_keeps_ethos_pdf_held_until_confirmed(self) -> None: approved = load_json(PREP)["approved_package_publication_prep"] pdfium_boundary = " ".join(approved["pdfium_boundary"]) @@ -522,6 +598,10 @@ def test_schema_validation_covers_package_publication_prep(self) -> None: False, schema["$defs"]["semver_package_version_decision_prep"]["additionalProperties"], ) + self.assertEqual( + False, + schema["$defs"]["package_publication_decision_prep_bundle"]["additionalProperties"], + ) self.assertEqual(9, schema["properties"]["required_evidence"]["minItems"]) self.assertEqual(13, schema["properties"]["explicit_blockers"]["minItems"]) self.assertEqual( @@ -542,6 +622,12 @@ def test_schema_validation_covers_package_publication_prep(self) -> None: "required_exact_decision_fields" ]["minItems"], ) + self.assertEqual( + 8, + schema["$defs"]["package_publication_decision_prep_bundle"]["properties"][ + "required_decision_inputs" + ]["minItems"], + ) self.assertIn("ethos-milestone-e-package-publication-approval-prep.schema.json", validate_examples) self.assertIn("docs\" / \"milestone-e-package-publication-approval-prep.json", validate_examples) self.assertIn("ethos-milestone-e-package-publication-approval-prep.schema.json", schemas_readme) diff --git a/docs/milestone-e-package-publication-approval-prep.json b/docs/milestone-e-package-publication-approval-prep.json index 5b09efae..2006b798 100644 --- a/docs/milestone-e-package-publication-approval-prep.json +++ b/docs/milestone-e-package-publication-approval-prep.json @@ -163,6 +163,43 @@ "package publication remains blocked" ] }, + "package_publication_decision_prep_bundle": { + "decision_state": "combined_decision_inputs_recorded_actions_blocked", + "review_boundary": [ + "package tag and source-commit decision inputs are recorded while creating no package tag", + "package dependency manifest activation inputs are recorded while changing no Cargo manifest", + "registry-backed dependent package assembly inputs are recorded while creating no registry and activating no assembly", + "public installation wording and exclusion inputs are recorded while inviting no public installation" + ], + "required_decision_inputs": [ + "exact package tag name", + "exact source commit for package tag binding", + "exact package-name migration diff for ethos-doc-core", + "exact dependency manifest activation diff for ethos-verify and ethos-pdf", + "exact registry-backed dependent package assembly evidence for ethos-doc-core before ethos-verify and ethos-pdf", + "exact public installation wording limited to a later approved package surface", + "exact exclusion list for wheels, npm packages, binaries, hosted surfaces, production positioning, public benchmark reports, public benchmark claims, and project-maintained PDFium builds", + "posture and claims gates after exact public installation wording changes" + ], + "non_approvals": [ + "this bundle does not select a package publication version", + "this bundle does not create a package tag", + "this bundle does not change Cargo manifests", + "this bundle does not activate package dependency manifests", + "this bundle does not create a registry", + "this bundle does not activate registry-backed dependent package assembly", + "this bundle does not invite public installation", + "this bundle does not approve package publication" + ], + "retained_blockers": [ + "no package publication version is selected", + "no package tag is created", + "no package dependency manifest activation is approved", + "no registry-backed dependent package assembly activation is approved", + "public installation remains blocked", + "package publication remains blocked" + ] + }, "public_boundary": [ "public reports remain blocked", "release artifacts remain blocked", diff --git a/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json b/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json index 574d8db5..72cceb2a 100644 --- a/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json +++ b/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json @@ -23,6 +23,7 @@ "publication_approval_decision_inputs", "candidate_crate_surface_review", "semver_package_version_decision_prep", + "package_publication_decision_prep_bundle", "public_boundary", "approval_scope", "required_evidence", @@ -64,6 +65,9 @@ "semver_package_version_decision_prep": { "$ref": "#/$defs/semver_package_version_decision_prep" }, + "package_publication_decision_prep_bundle": { + "$ref": "#/$defs/package_publication_decision_prep_bundle" + }, "public_boundary": { "type": "array", "minItems": 10, @@ -428,6 +432,48 @@ } } }, + "package_publication_decision_prep_bundle": { + "type": "object", + "required": [ + "decision_state", + "review_boundary", + "required_decision_inputs", + "non_approvals", + "retained_blockers" + ], + "additionalProperties": false, + "properties": { + "decision_state": { "const": "combined_decision_inputs_recorded_actions_blocked" }, + "review_boundary": { + "type": "array", + "minItems": 4, + "maxItems": 4, + "items": { "$ref": "#/$defs/bundle_review_boundary" }, + "uniqueItems": true + }, + "required_decision_inputs": { + "type": "array", + "minItems": 8, + "maxItems": 8, + "items": { "$ref": "#/$defs/bundle_required_decision_input" }, + "uniqueItems": true + }, + "non_approvals": { + "type": "array", + "minItems": 8, + "maxItems": 8, + "items": { "$ref": "#/$defs/bundle_non_approval" }, + "uniqueItems": true + }, + "retained_blockers": { + "type": "array", + "minItems": 6, + "maxItems": 6, + "items": { "$ref": "#/$defs/bundle_retained_blocker" }, + "uniqueItems": true + } + } + }, "reserved_identifier": { "enum": [ "ethos-doc-core", @@ -534,6 +580,48 @@ "package publication remains blocked" ] }, + "bundle_review_boundary": { + "enum": [ + "package tag and source-commit decision inputs are recorded while creating no package tag", + "package dependency manifest activation inputs are recorded while changing no Cargo manifest", + "registry-backed dependent package assembly inputs are recorded while creating no registry and activating no assembly", + "public installation wording and exclusion inputs are recorded while inviting no public installation" + ] + }, + "bundle_required_decision_input": { + "enum": [ + "exact package tag name", + "exact source commit for package tag binding", + "exact package-name migration diff for ethos-doc-core", + "exact dependency manifest activation diff for ethos-verify and ethos-pdf", + "exact registry-backed dependent package assembly evidence for ethos-doc-core before ethos-verify and ethos-pdf", + "exact public installation wording limited to a later approved package surface", + "exact exclusion list for wheels, npm packages, binaries, hosted surfaces, production positioning, public benchmark reports, public benchmark claims, and project-maintained PDFium builds", + "posture and claims gates after exact public installation wording changes" + ] + }, + "bundle_non_approval": { + "enum": [ + "this bundle does not select a package publication version", + "this bundle does not create a package tag", + "this bundle does not change Cargo manifests", + "this bundle does not activate package dependency manifests", + "this bundle does not create a registry", + "this bundle does not activate registry-backed dependent package assembly", + "this bundle does not invite public installation", + "this bundle does not approve package publication" + ] + }, + "bundle_retained_blocker": { + "enum": [ + "no package publication version is selected", + "no package tag is created", + "no package dependency manifest activation is approved", + "no registry-backed dependent package assembly activation is approved", + "public installation remains blocked", + "package publication remains blocked" + ] + }, "in_tree_reconciliation": { "enum": [ "ethos-doc-core maps to the in-tree ethos-core crate before any future publish prep can advance",