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 4b7e5686..e4a288f0 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_prep.py @@ -90,6 +90,7 @@ "package_registry_assembly_activation_prep": "docs/validation/milestone-e-package-publication-registry-assembly-activation-prep-validation-2026-06-21.md", "package_real_version_selection_prep": "docs/validation/milestone-e-package-publication-real-version-selection-prep-validation-2026-06-21.md", "package_tag_creation_prep": "docs/validation/milestone-e-package-publication-tag-creation-prep-validation-2026-06-21.md", + "package_decision_bundle_validation": "docs/validation/milestone-e-package-publication-decision-bundle-validation-2026-06-21.md", } EXPECTED_PUBLICATION_DECISION_INPUTS = { "decision_status": "not_approved_pending_exact_decision", @@ -212,6 +213,65 @@ "package publication remains blocked", ], } +EXPECTED_PACKAGE_PUBLICATION_APPROVAL_REQUEST_PACKET = { + "packet_state": "approval_request_packet_recorded_publication_blocked", + "candidate_crates": [ + "ethos-doc-core mapped from crates/ethos-core; package-name migration remains pending", + "ethos-verify mapped from crates/ethos-verify; dependency manifest activation remains pending", + "ethos-pdf mapped from crates/ethos-pdf; dependency manifest activation and PDFium boundary confirmation must remain current", + ], + "package_version_map": [ + "ethos-doc-core has no selected package publication version", + "ethos-verify has no selected package publication version", + "ethos-pdf has no selected package publication version", + ], + "package_tag_name": "not selected; package tag creation remains blocked", + "package_tag_source_commit": "not selected; package tag binding remains blocked", + "package_tag_source_tree": "not selected; package source tree binding remains blocked", + "manifest_activation_diff": "not prepared; current Cargo manifests remain unchanged", + "registry_assembly_evidence": "not activated; registry-backed dependent package assembly remains blocked", + "public_installation_wording": "No public installation wording is approved; public installation remains blocked.", + "explicit_exclusions": [ + "wheels", + "npm packages", + "binaries", + "hosted surfaces", + "production positioning", + "public benchmark reports", + "public benchmark claims", + "release artifacts", + "project-maintained PDFium builds", + ], + "required_before_approval": [ + "exact package publication approval decision record", + "exact candidate crate list", + "exact SemVer package version or per-crate version map", + "exact package tag name and package_tag_source_commit", + "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", + "posture and claims gates after exact public installation wording changes", + ], + "non_approvals": [ + "this packet does not select a package publication version", + "this packet does not create a package tag", + "this packet does not change Cargo manifests", + "this packet does not activate package dependency manifests", + "this packet does not create a registry", + "this packet does not activate registry-backed dependent package assembly", + "this packet does not invite public installation", + "this packet 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", + "real-version cargo publish remains blocked", + ], +} FORBIDDEN_PREP_WORDING = [ "public beta is approved", @@ -541,6 +601,48 @@ def test_combined_package_publication_decision_prep_bundle_blocks_all_actions(se self.assertIn('name = "ethos-pdf"', pdf_manifest) self.assertIn('version = "0.1.0"', cargo) + def test_package_publication_approval_request_packet_keeps_all_actions_blocked(self) -> None: + packet = load_json(PREP)["package_publication_approval_request_packet"] + 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_APPROVAL_REQUEST_PACKET, packet) + self.assertEqual("approval_request_packet_recorded_publication_blocked", packet["packet_state"]) + self.assertEqual(3, len(packet["candidate_crates"])) + self.assertIn("ethos-doc-core has no selected package publication version", packet["package_version_map"]) + self.assertEqual( + "not selected; package tag creation remains blocked", + packet["package_tag_name"], + ) + self.assertEqual( + "not selected; package tag binding remains blocked", + packet["package_tag_source_commit"], + ) + self.assertEqual( + "not prepared; current Cargo manifests remain unchanged", + packet["manifest_activation_diff"], + ) + self.assertIn("public installation remains blocked", packet["public_installation_wording"]) + self.assertIn("release artifacts", packet["explicit_exclusions"]) + self.assertIn("project-maintained PDFium builds", packet["explicit_exclusions"]) + self.assertIn("exact package tag name and package_tag_source_commit", packet["required_before_approval"]) + self.assertIn("posture and claims gates after exact public installation wording changes", packet["required_before_approval"]) + self.assertIn("this packet does not change Cargo manifests", packet["non_approvals"]) + self.assertIn("this packet does not invite public installation", packet["non_approvals"]) + self.assertIn("this packet does not approve package publication", packet["non_approvals"]) + self.assertIn("real-version cargo publish remains blocked", packet["retained_blockers"]) + self.assertIn('"crates/ethos-core"', cargo) + self.assertIn('"crates/ethos-verify"', cargo) + self.assertIn('"crates/ethos-pdf"', cargo) + 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) + 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"]) @@ -602,6 +704,10 @@ def test_schema_validation_covers_package_publication_prep(self) -> None: False, schema["$defs"]["package_publication_decision_prep_bundle"]["additionalProperties"], ) + self.assertEqual( + False, + schema["$defs"]["package_publication_approval_request_packet"]["additionalProperties"], + ) self.assertEqual(9, schema["properties"]["required_evidence"]["minItems"]) self.assertEqual(13, schema["properties"]["explicit_blockers"]["minItems"]) self.assertEqual( @@ -628,6 +734,18 @@ def test_schema_validation_covers_package_publication_prep(self) -> None: "required_decision_inputs" ]["minItems"], ) + self.assertEqual( + 8, + schema["$defs"]["package_publication_approval_request_packet"]["properties"][ + "required_before_approval" + ]["minItems"], + ) + self.assertEqual( + 9, + schema["$defs"]["package_publication_approval_request_packet"]["properties"][ + "explicit_exclusions" + ]["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/.github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py b/.github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py new file mode 100644 index 00000000..e3e34f81 --- /dev/null +++ b/.github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +# +# Copyright 2026 The Ethos maintainers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from __future__ import annotations + +import json +import re +import unittest +from pathlib import Path + +from makefile_guard import target_block + + +ROOT = Path(__file__).resolve().parents[2] +PREP = ROOT / "docs/milestone-e-package-publication-approval-prep.json" +RECORD = ( + ROOT + / "docs/validation/" + "milestone-e-package-publication-decision-bundle-validation-2026-06-21.md" +) +VALIDATION_README = ROOT / "docs/validation/README.md" +CI_WORKFLOW = ROOT / ".github/workflows/ci.yml" + +FORBIDDEN_SCOPE_EXPANSION = [ + "public reports are approved", + "public result wording approved", + "release-ready", + "release artifact approved", + "package-ready", + "package publication is approved", + "package publication approved", + "packages are published", + "published packages", + "production-ready", + "production positioning approved", + "benchmark-validated", + "public benchmark pass", + "speed validated", + "fastest", + "launch-ready", + "hosted surface approved", + "hosted demo approved", + "demo-ready", + "performance validated", + "quality validated", + "footprint validated", + "table-quality validated", + "parser-quality validated", +] + + +def read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def normalized(path: Path) -> str: + return re.sub(r"\s+", " ", read(path)) + + +def load_json(path: Path) -> dict: + return json.loads(path.read_text(encoding="utf-8")) + + +class MilestoneEPackagePublicationDecisionBundleValidationRecordTests(unittest.TestCase): + def test_decision_bundle_record_is_indexed(self) -> None: + readme = read(VALIDATION_README) + normalized_readme = re.sub(r"\s+", " ", readme) + + self.assertIn(RECORD.name, readme) + self.assertIn( + "package publication decision-bundle validation for the combined decision inputs", + normalized_readme, + ) + + def test_record_names_validation_commands(self) -> None: + text = read(RECORD) + + self.assertIn("Validated source HEAD before this record: `63d8647`", text) + self.assertIn( + "python3 .github/scripts/test_milestone_e_package_publication_approval_prep.py", + text, + ) + self.assertIn( + "python3 .github/scripts/" + "test_milestone_e_package_publication_decision_bundle_validation_record.py", + text, + ) + self.assertIn("python3 .github/scripts/test_public_surface_posture.py", text) + self.assertIn("python3 .github/scripts/claims_gate.py", text) + self.assertIn("cargo build --locked -p ethos-cli", text) + self.assertIn("make milestone-e-prep PYTHON=/bin/python", text) + self.assertIn("git diff --check", text) + + def test_record_matches_combined_decision_bundle_scope(self) -> None: + prep = load_json(PREP) + bundle = prep["package_publication_decision_prep_bundle"] + record = normalized(RECORD) + + self.assertEqual("combined_decision_inputs_recorded_actions_blocked", bundle["decision_state"]) + for boundary in bundle["review_boundary"]: + self.assertIn(boundary, record) + for decision_input in bundle["required_decision_inputs"]: + self.assertIn(decision_input, record) + for non_approval in bundle["non_approvals"]: + self.assertIn(non_approval, record) + for blocker in bundle["retained_blockers"]: + self.assertIn(blocker, record) + self.assertIn("Ethos remains source-only pre-alpha", record) + self.assertIn("Package publication remains blocked", record) + self.assertIn("Public installation remains blocked", record) + + def test_record_matches_non_activating_approval_request_packet(self) -> None: + prep = load_json(PREP) + packet = prep["package_publication_approval_request_packet"] + record = normalized(RECORD) + + self.assertEqual("approval_request_packet_recorded_publication_blocked", packet["packet_state"]) + self.assertIn(packet["packet_state"], record) + for candidate in packet["candidate_crates"]: + self.assertIn(candidate, record) + for version in packet["package_version_map"]: + self.assertIn(version, record) + self.assertIn(packet["package_tag_name"], record) + self.assertIn(packet["package_tag_source_commit"], record) + self.assertIn(packet["package_tag_source_tree"], record) + self.assertIn(packet["manifest_activation_diff"], record) + self.assertIn(packet["registry_assembly_evidence"], record) + self.assertIn(packet["public_installation_wording"], record) + for exclusion in packet["explicit_exclusions"]: + self.assertIn(exclusion, record) + for required in packet["required_before_approval"]: + self.assertIn(required, record) + for non_approval in packet["non_approvals"]: + self.assertIn(non_approval, record) + for blocker in packet["retained_blockers"]: + self.assertIn(blocker, record) + + def test_record_keeps_public_boundaries_explicit(self) -> None: + record = normalized(RECORD) + + self.assertIn("Public reports remain blocked", record) + self.assertIn("Public result wording remains blocked", record) + self.assertIn("Release artifacts remain blocked", record) + self.assertIn("Binaries remain blocked", record) + self.assertIn("Wheels remain blocked", record) + self.assertIn("Npm packages remain blocked", record) + self.assertIn("Hosted surfaces remain blocked", record) + self.assertIn("Production positioning remains blocked", record) + self.assertIn("Public benchmark reports remain blocked", record) + self.assertIn("Public benchmark claims remain blocked", record) + self.assertIn("Project-maintained PDFium builds remain blocked", record) + + def test_make_and_ci_run_record_guard_after_combined_prep(self) -> None: + make_block = target_block("milestone-e-prep") + ci = read(CI_WORKFLOW) + registry_activation_guard = ( + "test_milestone_e_package_publication_registry_assembly_activation_prep.py" + ) + record_guard = "test_milestone_e_package_publication_decision_bundle_validation_record.py" + command_guard = "test_milestone_e_validation_command_index.py" + + for text, prefix in ((make_block, "$(PYTHON) .github/scripts/"), (ci, "python3 .github/scripts/")): + self.assertIn(prefix + record_guard, text) + self.assertEqual(1, text.count(prefix + record_guard)) + self.assertLess(text.index(prefix + registry_activation_guard), text.index(prefix + record_guard)) + self.assertLess(text.index(prefix + record_guard), text.index(prefix + command_guard)) + + def test_record_avoids_scope_expansion_language_or_private_paths(self) -> None: + lower = normalized(RECORD).lower() + raw = read(RECORD) + + for phrase in FORBIDDEN_SCOPE_EXPANSION: + self.assertNotIn(phrase, lower) + self.assertNotIn("/Users/", raw) + self.assertNotIn("/private/tmp", raw) + self.assertNotIn("/private/var", raw) + self.assertNotIn("/var/folders", raw) + self.assertNotIn("saumildiwaker", raw) + self.assertNotIn("Desktop/Stuff", raw) + self.assertNotIn("project/repo/ethos", raw) + self.assertNotIn("docs/.roadmap.md.swp", raw) + self.assertNotIn("web/", raw) + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/scripts/test_milestone_e_prep_guard_sequence_index.py b/.github/scripts/test_milestone_e_prep_guard_sequence_index.py index 0cc2cd65..cb510cae 100644 --- a/.github/scripts/test_milestone_e_prep_guard_sequence_index.py +++ b/.github/scripts/test_milestone_e_prep_guard_sequence_index.py @@ -104,6 +104,7 @@ "$(PYTHON) .github/scripts/test_milestone_e_package_publication_tag_creation_prep.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py", + "$(PYTHON) .github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py", "$(PYTHON) .github/scripts/test_milestone_e_validation_command_index.py", "$(PYTHON) .github/scripts/test_milestone_e_validation_command_index_validation_record.py", "$(PYTHON) .github/scripts/test_milestone_e_validation_record_index.py", diff --git a/.github/scripts/test_milestone_e_prep_scope.py b/.github/scripts/test_milestone_e_prep_scope.py index 4d87c6b9..12281cc9 100644 --- a/.github/scripts/test_milestone_e_prep_scope.py +++ b/.github/scripts/test_milestone_e_prep_scope.py @@ -403,6 +403,7 @@ def test_make_target_is_narrow_and_guarded(self) -> None: "$(PYTHON) .github/scripts/test_milestone_e_package_publication_tag_creation_prep.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py", + "$(PYTHON) .github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py", "$(PYTHON) .github/scripts/test_milestone_e_validation_command_index.py", "$(PYTHON) .github/scripts/test_milestone_e_validation_command_index_validation_record.py", "$(PYTHON) .github/scripts/test_milestone_e_validation_record_index.py", diff --git a/.github/scripts/test_milestone_e_validation_record_index.py b/.github/scripts/test_milestone_e_validation_record_index.py index add039a8..58aae6fd 100644 --- a/.github/scripts/test_milestone_e_validation_record_index.py +++ b/.github/scripts/test_milestone_e_validation_record_index.py @@ -250,6 +250,10 @@ class RecordCoverage: "milestone-e-package-publication-registry-assembly-activation-prep-validation-2026-06-21.md", "test_milestone_e_package_publication_registry_assembly_activation_prep.py", ), + RecordCoverage( + "milestone-e-package-publication-decision-bundle-validation-2026-06-21.md", + "test_milestone_e_package_publication_decision_bundle_validation_record.py", + ), RecordCoverage( "milestone-e-validation-command-index-validation-2026-06-20.md", "test_milestone_e_validation_command_index_validation_record.py", @@ -345,6 +349,9 @@ def test_index_guards_run_after_row_and_schema_records(self) -> None: package_registry_activation_guard = ( "test_milestone_e_package_publication_registry_assembly_activation_prep.py" ) + package_decision_bundle_guard = ( + "test_milestone_e_package_publication_decision_bundle_validation_record.py" + ) command_guard = "test_milestone_e_validation_command_index_validation_record.py" index_guard = "test_milestone_e_validation_record_index.py" index_record_guard = "test_milestone_e_validation_record_index_validation_record.py" @@ -393,8 +400,12 @@ def test_index_guards_run_after_row_and_schema_records(self) -> None: text.index(prefix + package_manifest_activation_guard), text.index(prefix + package_registry_activation_guard), ) - self.assertLess(text.index(prefix + package_registry_activation_guard), text.index(prefix + command_guard)) - self.assertLess(text.index(prefix + package_registry_activation_guard), text.index(prefix + index_guard)) + self.assertLess( + text.index(prefix + package_registry_activation_guard), + text.index(prefix + package_decision_bundle_guard), + ) + self.assertLess(text.index(prefix + package_decision_bundle_guard), text.index(prefix + command_guard)) + self.assertLess(text.index(prefix + package_decision_bundle_guard), text.index(prefix + index_guard)) self.assertLess(text.index(prefix + package_manifest_activation_guard), text.index(prefix + command_guard)) self.assertLess(text.index(prefix + package_manifest_activation_guard), text.index(prefix + index_guard)) self.assertLess(text.index(prefix + package_tag_guard), text.index(prefix + command_guard)) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d741377..a59dadb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -222,6 +222,8 @@ jobs: run: python3 .github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py - name: Milestone E package publication registry-assembly activation prep tests run: python3 .github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py + - name: Milestone E package publication decision-bundle validation record tests + run: python3 .github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py - name: Milestone E validation-command index tests run: python3 .github/scripts/test_milestone_e_validation_command_index.py - name: Milestone E validation-command index validation record tests diff --git a/Makefile b/Makefile index 4206a020..5ef8211e 100644 --- a/Makefile +++ b/Makefile @@ -218,6 +218,7 @@ milestone-e-prep: $(PYTHON) .github/scripts/test_milestone_e_package_publication_tag_creation_prep.py $(PYTHON) .github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py $(PYTHON) .github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py + $(PYTHON) .github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py $(PYTHON) .github/scripts/test_milestone_e_validation_command_index.py $(PYTHON) .github/scripts/test_milestone_e_validation_command_index_validation_record.py $(PYTHON) .github/scripts/test_milestone_e_validation_record_index.py diff --git a/docs/milestone-e-package-publication-approval-prep.json b/docs/milestone-e-package-publication-approval-prep.json index 2006b798..6709ed67 100644 --- a/docs/milestone-e-package-publication-approval-prep.json +++ b/docs/milestone-e-package-publication-approval-prep.json @@ -77,7 +77,8 @@ "package_registry_assembly_prep": "docs/validation/milestone-e-package-publication-registry-assembly-prep-validation-2026-06-21.md", "package_registry_assembly_activation_prep": "docs/validation/milestone-e-package-publication-registry-assembly-activation-prep-validation-2026-06-21.md", "package_real_version_selection_prep": "docs/validation/milestone-e-package-publication-real-version-selection-prep-validation-2026-06-21.md", - "package_tag_creation_prep": "docs/validation/milestone-e-package-publication-tag-creation-prep-validation-2026-06-21.md" + "package_tag_creation_prep": "docs/validation/milestone-e-package-publication-tag-creation-prep-validation-2026-06-21.md", + "package_decision_bundle_validation": "docs/validation/milestone-e-package-publication-decision-bundle-validation-2026-06-21.md" }, "publication_approval_decision_inputs": { "decision_status": "not_approved_pending_exact_decision", @@ -200,6 +201,65 @@ "package publication remains blocked" ] }, + "package_publication_approval_request_packet": { + "packet_state": "approval_request_packet_recorded_publication_blocked", + "candidate_crates": [ + "ethos-doc-core mapped from crates/ethos-core; package-name migration remains pending", + "ethos-verify mapped from crates/ethos-verify; dependency manifest activation remains pending", + "ethos-pdf mapped from crates/ethos-pdf; dependency manifest activation and PDFium boundary confirmation must remain current" + ], + "package_version_map": [ + "ethos-doc-core has no selected package publication version", + "ethos-verify has no selected package publication version", + "ethos-pdf has no selected package publication version" + ], + "package_tag_name": "not selected; package tag creation remains blocked", + "package_tag_source_commit": "not selected; package tag binding remains blocked", + "package_tag_source_tree": "not selected; package source tree binding remains blocked", + "manifest_activation_diff": "not prepared; current Cargo manifests remain unchanged", + "registry_assembly_evidence": "not activated; registry-backed dependent package assembly remains blocked", + "public_installation_wording": "No public installation wording is approved; public installation remains blocked.", + "explicit_exclusions": [ + "wheels", + "npm packages", + "binaries", + "hosted surfaces", + "production positioning", + "public benchmark reports", + "public benchmark claims", + "release artifacts", + "project-maintained PDFium builds" + ], + "required_before_approval": [ + "exact package publication approval decision record", + "exact candidate crate list", + "exact SemVer package version or per-crate version map", + "exact package tag name and package_tag_source_commit", + "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", + "posture and claims gates after exact public installation wording changes" + ], + "non_approvals": [ + "this packet does not select a package publication version", + "this packet does not create a package tag", + "this packet does not change Cargo manifests", + "this packet does not activate package dependency manifests", + "this packet does not create a registry", + "this packet does not activate registry-backed dependent package assembly", + "this packet does not invite public installation", + "this packet 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", + "real-version cargo publish remains blocked" + ] + }, "public_boundary": [ "public reports remain blocked", "release artifacts remain blocked", diff --git a/docs/validation/README.md b/docs/validation/README.md index 2480b57b..b9baddd9 100644 --- a/docs/validation/README.md +++ b/docs/validation/README.md @@ -314,6 +314,11 @@ inventory, metadata/readiness, dry-run planning, version/tag policy, and PDFium - `milestone-e-package-publication-tag-creation-prep-validation-2026-06-21.md` - package publication tag-creation prep validation for future package tag review; the record keeps package publication and public installation blocked while recording that no package tag is created. +- `milestone-e-package-publication-decision-bundle-validation-2026-06-21.md` - package + publication decision-bundle validation for the combined decision inputs; the record keeps + package publication and public installation blocked while recording that no package publication + version is selected, no package tag is created, no Cargo manifest is changed, no registry is + created, no registry-backed assembly is activated, and no public installation is invited. - `milestone-e-validation-command-index-validation-2026-06-20.md` - internal Milestone E validation-command index validation passed through command-alignment checks, schema enum checks, row-record checks, public-surface posture checks, `make milestone-e-prep`, and diff hygiene; the diff --git a/docs/validation/milestone-e-package-publication-decision-bundle-validation-2026-06-21.md b/docs/validation/milestone-e-package-publication-decision-bundle-validation-2026-06-21.md new file mode 100644 index 00000000..a47a6e6d --- /dev/null +++ b/docs/validation/milestone-e-package-publication-decision-bundle-validation-2026-06-21.md @@ -0,0 +1,149 @@ +# Milestone E Package Publication Decision-Bundle Validation - 2026-06-21 + +## Purpose + +Record validation for the combined package publication decision-prep bundle without approving +package publication. + +This record validates that the combined decision inputs are recorded before any later dedicated +package publication approval. It does not select a package publication version, create a package +tag, change Cargo manifests, activate package dependency manifests, create a registry, activate +registry-backed dependent package assembly, approve public installation, approve package +publication, publish binaries, publish wheels, publish npm packages, approve hosted surfaces, +approve production positioning, approve public benchmark reports, approve public benchmark claims, +or approve public result wording. It does not resolve or soften blockers outside this +decision-prep bundle. + +## Status + +Status: **pass for package publication decision-bundle validation with publication blocked**. + +Ethos remains source-only pre-alpha outside the approved source-only public beta surface and +internal package publication prep boundary. + +Package publication remains blocked. + +Public installation remains blocked. + +## Subject + +- Repository: `docushell/ethos` +- Validated source HEAD before this record: `63d8647` +- Lane: package publication decision-prep bundle +- Evidence area: combined package tag, manifest activation, registry assembly, and public + installation decision inputs with retained blocked actions + +## Evidence Review + +- 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 retained for later dedicated approval: + +- 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 + +## Approval Request Packet + +The non-activating package publication approval request packet is recorded with: + +- packet state: `approval_request_packet_recorded_publication_blocked` +- candidate crates: + - ethos-doc-core mapped from crates/ethos-core; package-name migration remains pending + - ethos-verify mapped from crates/ethos-verify; dependency manifest activation remains pending + - ethos-pdf mapped from crates/ethos-pdf; dependency manifest activation and PDFium boundary + confirmation must remain current +- package version map: + - ethos-doc-core has no selected package publication version + - ethos-verify has no selected package publication version + - ethos-pdf has no selected package publication version +- package tag name: not selected; package tag creation remains blocked +- package tag source commit: not selected; package tag binding remains blocked +- package tag source tree: not selected; package source tree binding remains blocked +- manifest activation diff: not prepared; current Cargo manifests remain unchanged +- registry assembly evidence: not activated; registry-backed dependent package assembly remains + blocked +- public installation wording: No public installation wording is approved; public installation + remains blocked. +- explicit exclusions: wheels, npm packages, binaries, hosted surfaces, production positioning, + public benchmark reports, public benchmark claims, release artifacts, and project-maintained + PDFium builds +- required before approval: exact package publication approval decision record, exact candidate + crate list, exact SemVer package version or per-crate version map, exact package tag name and + package_tag_source_commit, 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, and posture and claims gates after exact public installation wording changes + +Non-approvals retained: + +- 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 +- this packet does not select a package publication version +- this packet does not create a package tag +- this packet does not change Cargo manifests +- this packet does not activate package dependency manifests +- this packet does not create a registry +- this packet does not activate registry-backed dependent package assembly +- this packet does not invite public installation +- this packet does not approve package publication + +## Blockers Retained + +- 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 +- real-version cargo publish remains blocked +- `ethos-doc` and `ethos-rag` remain reserved placeholders until package owners, manifests, README + files, metadata, and support expectations are prepared. +- Project-maintained PDFium builds remain blocked. + +## Commands + +```sh +python3 .github/scripts/test_milestone_e_package_publication_approval_prep.py +python3 .github/scripts/test_milestone_e_package_publication_decision_bundle_validation_record.py +python3 .github/scripts/test_public_surface_posture.py +python3 .github/scripts/claims_gate.py +cargo build --locked -p ethos-cli +make milestone-e-prep PYTHON=/bin/python +git diff --check +``` + +## Explicit Boundaries + +- Public reports remain blocked. +- Public result wording remains blocked. +- Package publication remains blocked. +- Public installation remains blocked. +- real-version cargo publish remains blocked +- Release artifacts remain blocked. +- Binaries remain blocked. +- Wheels remain blocked. +- Npm packages remain blocked. +- Hosted surfaces remain blocked. +- Production positioning remains blocked. +- Public benchmark reports remain blocked. +- Public benchmark claims remain blocked. +- Project-maintained PDFium builds 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 72cceb2a..1db1fed4 100644 --- a/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json +++ b/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json @@ -24,6 +24,7 @@ "candidate_crate_surface_review", "semver_package_version_decision_prep", "package_publication_decision_prep_bundle", + "package_publication_approval_request_packet", "public_boundary", "approval_scope", "required_evidence", @@ -68,6 +69,9 @@ "package_publication_decision_prep_bundle": { "$ref": "#/$defs/package_publication_decision_prep_bundle" }, + "package_publication_approval_request_packet": { + "$ref": "#/$defs/package_publication_approval_request_packet" + }, "public_boundary": { "type": "array", "minItems": 10, @@ -273,7 +277,8 @@ "package_registry_assembly_prep", "package_registry_assembly_activation_prep", "package_real_version_selection_prep", - "package_tag_creation_prep" + "package_tag_creation_prep", + "package_decision_bundle_validation" ], "additionalProperties": false, "properties": { @@ -309,6 +314,9 @@ }, "package_tag_creation_prep": { "const": "docs/validation/milestone-e-package-publication-tag-creation-prep-validation-2026-06-21.md" + }, + "package_decision_bundle_validation": { + "const": "docs/validation/milestone-e-package-publication-decision-bundle-validation-2026-06-21.md" } } }, @@ -474,6 +482,84 @@ } } }, + "package_publication_approval_request_packet": { + "type": "object", + "required": [ + "packet_state", + "candidate_crates", + "package_version_map", + "package_tag_name", + "package_tag_source_commit", + "package_tag_source_tree", + "manifest_activation_diff", + "registry_assembly_evidence", + "public_installation_wording", + "explicit_exclusions", + "required_before_approval", + "non_approvals", + "retained_blockers" + ], + "additionalProperties": false, + "properties": { + "packet_state": { "const": "approval_request_packet_recorded_publication_blocked" }, + "candidate_crates": { + "type": "array", + "minItems": 3, + "maxItems": 3, + "items": { "$ref": "#/$defs/packet_candidate_crate" }, + "uniqueItems": true + }, + "package_version_map": { + "type": "array", + "minItems": 3, + "maxItems": 3, + "items": { "$ref": "#/$defs/packet_package_version" }, + "uniqueItems": true + }, + "package_tag_name": { "const": "not selected; package tag creation remains blocked" }, + "package_tag_source_commit": { "const": "not selected; package tag binding remains blocked" }, + "package_tag_source_tree": { + "const": "not selected; package source tree binding remains blocked" + }, + "manifest_activation_diff": { + "const": "not prepared; current Cargo manifests remain unchanged" + }, + "registry_assembly_evidence": { + "const": "not activated; registry-backed dependent package assembly remains blocked" + }, + "public_installation_wording": { + "const": "No public installation wording is approved; public installation remains blocked." + }, + "explicit_exclusions": { + "type": "array", + "minItems": 9, + "maxItems": 9, + "items": { "$ref": "#/$defs/packet_explicit_exclusion" }, + "uniqueItems": true + }, + "required_before_approval": { + "type": "array", + "minItems": 8, + "maxItems": 8, + "items": { "$ref": "#/$defs/packet_required_before_approval" }, + "uniqueItems": true + }, + "non_approvals": { + "type": "array", + "minItems": 8, + "maxItems": 8, + "items": { "$ref": "#/$defs/packet_non_approval" }, + "uniqueItems": true + }, + "retained_blockers": { + "type": "array", + "minItems": 7, + "maxItems": 7, + "items": { "$ref": "#/$defs/packet_retained_blocker" }, + "uniqueItems": true + } + } + }, "reserved_identifier": { "enum": [ "ethos-doc-core", @@ -622,6 +708,68 @@ "package publication remains blocked" ] }, + "packet_candidate_crate": { + "enum": [ + "ethos-doc-core mapped from crates/ethos-core; package-name migration remains pending", + "ethos-verify mapped from crates/ethos-verify; dependency manifest activation remains pending", + "ethos-pdf mapped from crates/ethos-pdf; dependency manifest activation and PDFium boundary confirmation must remain current" + ] + }, + "packet_package_version": { + "enum": [ + "ethos-doc-core has no selected package publication version", + "ethos-verify has no selected package publication version", + "ethos-pdf has no selected package publication version" + ] + }, + "packet_explicit_exclusion": { + "enum": [ + "wheels", + "npm packages", + "binaries", + "hosted surfaces", + "production positioning", + "public benchmark reports", + "public benchmark claims", + "release artifacts", + "project-maintained PDFium builds" + ] + }, + "packet_required_before_approval": { + "enum": [ + "exact package publication approval decision record", + "exact candidate crate list", + "exact SemVer package version or per-crate version map", + "exact package tag name and package_tag_source_commit", + "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", + "posture and claims gates after exact public installation wording changes" + ] + }, + "packet_non_approval": { + "enum": [ + "this packet does not select a package publication version", + "this packet does not create a package tag", + "this packet does not change Cargo manifests", + "this packet does not activate package dependency manifests", + "this packet does not create a registry", + "this packet does not activate registry-backed dependent package assembly", + "this packet does not invite public installation", + "this packet does not approve package publication" + ] + }, + "packet_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", + "real-version cargo publish remains blocked" + ] + }, "in_tree_reconciliation": { "enum": [ "ethos-doc-core maps to the in-tree ethos-core crate before any future publish prep can advance",