From 9c6dfd229c4373489fb86178cd4b94dface1cf51 Mon Sep 17 00:00:00 2001 From: docushell-admin Date: Mon, 22 Jun 2026 10:13:15 +0530 Subject: [PATCH] Apply package manifest activation for review Signed-off-by: docushell-admin --- ...ackage_publication_candidate_activation.py | 67 ++++-- .github/scripts/test_determinism_workflow.py | 2 +- .../test_milestone_d_crop_element_contract.py | 2 +- ...t_milestone_d_grounding_source_contract.py | 2 +- .../test_milestone_d_internal_contracts.py | 4 +- ...ge_publication_approval_decision_record.py | 2 +- ...e_publication_approval_decision_refresh.py | 2 +- ..._publication_approval_decision_template.py | 2 +- ...one_e_package_publication_approval_prep.py | 59 ++--- ...e_publication_approval_readiness_review.py | 28 ++- ...ge_publication_approval_resolution_plan.py | 42 +++- ...blication_candidate_activation_evidence.py | 2 +- ...ation_decision_bundle_validation_record.py | 42 +++- ...ckage_publication_decision_input_packet.py | 43 +++- ...package_publication_dependency_ordering.py | 4 +- ...one_e_package_publication_dry_run_smoke.py | 10 +- ...publication_manifest_activation_applied.py | 202 ++++++++++++++++++ ...ication_manifest_activation_diff_review.py | 10 +- ...ge_publication_manifest_activation_prep.py | 8 +- ...age_publication_manifest_migration_prep.py | 10 +- ..._package_publication_metadata_readiness.py | 4 +- ...age_publication_pre_approval_gap_ledger.py | 35 ++- ...tion_public_installation_wording_review.py | 2 +- ...ation_registry_assembly_activation_prep.py | 8 +- ...ation_registry_assembly_evidence_review.py | 6 +- ...kage_publication_registry_assembly_prep.py | 8 +- ...t_milestone_e_prep_guard_sequence_index.py | 1 + .../scripts/test_milestone_e_prep_scope.py | 1 + ...est_milestone_e_validation_record_index.py | 4 + .github/workflows/ci.yml | 6 +- .github/workflows/determinism.yml | 2 +- Cargo.lock | 14 +- Cargo.toml | 2 +- Makefile | 9 +- crates/ethos-core/Cargo.toml | 5 +- crates/ethos-core/README.md | 10 +- docs/architecture.md | 9 +- docs/execution-status.md | 2 + docs/milestone-d-crop-element-contract.md | 2 +- ...e-e-package-publication-approval-prep.json | 61 +++--- docs/milestone-e-prep-scope.md | 8 + ...tone-e-public-facing-readiness-ledger.json | 4 +- docs/roadmap.md | 5 + docs/validation/README.md | 4 + ...ctivation-applied-validation-2026-06-22.md | 102 +++++++++ ...kage-publication-approval-prep.schema.json | 58 ++--- ...public-facing-readiness-ledger.schema.json | 4 +- 47 files changed, 722 insertions(+), 197 deletions(-) create mode 100644 .github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py create mode 100644 docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md diff --git a/.github/scripts/package_publication_candidate_activation.py b/.github/scripts/package_publication_candidate_activation.py index 112803f4..89b3b8a7 100644 --- a/.github/scripts/package_publication_candidate_activation.py +++ b/.github/scripts/package_publication_candidate_activation.py @@ -114,38 +114,47 @@ def record_command(command: str, commands: list[dict[str, object]], stdout: str ) -def replace_once(path: Path, old: str, new: str) -> None: +def replace_once_if_needed(path: Path, old: str, new: str) -> None: text = path.read_text(encoding="utf-8") - if old not in text: - raise RuntimeError(f"expected text not found in {path}: {old}") - path.write_text(text.replace(old, new, 1), encoding="utf-8") + if old in text: + path.write_text(text.replace(old, new, 1), encoding="utf-8") + return + if new in text: + return + raise RuntimeError(f"expected source or activated text not found in {path}: {old}") def rewrite_candidate_lockfile(workspace: Path) -> None: lockfile = workspace / "Cargo.lock" text = lockfile.read_text(encoding="utf-8") - if 'name = "ethos-core"' not in text: - raise RuntimeError("expected ethos-core package entry in candidate Cargo.lock") - lockfile.write_text(text.replace("ethos-core", CORE_PACKAGE), encoding="utf-8") + if 'name = "ethos-core"' in text: + lockfile.write_text(text.replace("ethos-core", CORE_PACKAGE), encoding="utf-8") + return + if 'name = "ethos-doc-core"' in text: + return + raise RuntimeError("expected core package entry in candidate Cargo.lock") def materialize_candidate_workspace(workspace: Path) -> None: shutil.copytree(ROOT, workspace, ignore=should_ignore) - replace_once( + replace_once_if_needed( workspace / "Cargo.toml", 'ethos-core = { path = "crates/ethos-core", version = "0.1.0", default-features = false }', 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.0", default-features = false }', ) - with (workspace / "Cargo.toml").open("a", encoding="utf-8") as handle: - handle.write( - '\n[patch.crates-io]\n' - 'ethos-doc-core = { path = "crates/ethos-core" }\n' - ) + root_manifest = workspace / "Cargo.toml" + root_text = root_manifest.read_text(encoding="utf-8") + if 'ethos-doc-core = { path = "crates/ethos-core" }' not in root_text: + with root_manifest.open("a", encoding="utf-8") as handle: + handle.write( + '\n[patch.crates-io]\n' + 'ethos-doc-core = { path = "crates/ethos-core" }\n' + ) core_manifest = workspace / "crates/ethos-core/Cargo.toml" - replace_once(core_manifest, 'name = "ethos-core"', 'name = "ethos-doc-core"') - replace_once( + replace_once_if_needed(core_manifest, 'name = "ethos-core"', 'name = "ethos-doc-core"') + replace_once_if_needed( core_manifest, "authors.workspace = true\n\n[package.metadata.ethos_publication]", 'authors.workspace = true\n\n[lib]\nname = "ethos_core"\n\n[package.metadata.ethos_publication]', @@ -529,18 +538,39 @@ def validate_packaged_manifests(artifacts: list[dict[str, str]]) -> dict[str, ob return checks +def source_manifests_have_activation_shape() -> bool: + workspace = (ROOT / "Cargo.toml").read_text(encoding="utf-8") + core = (ROOT / "crates/ethos-core/Cargo.toml").read_text(encoding="utf-8") + verify = (ROOT / "crates/ethos-verify/Cargo.toml").read_text(encoding="utf-8") + pdf = (ROOT / "crates/ethos-pdf/Cargo.toml").read_text(encoding="utf-8") + lockfile = (ROOT / "Cargo.lock").read_text(encoding="utf-8") + return all( + [ + 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.0", default-features = false }' + in workspace, + 'name = "ethos-doc-core"' in core, + '[lib]\nname = "ethos_core"' in core, + 'ethos-core = { workspace = true, features = ["grounding", "verify-types"] }' in verify, + 'ethos-core = { workspace = true, features = ["full"] }' in pdf, + 'name = "ethos-doc-core"' in lockfile, + 'name = "ethos-core"' not in lockfile, + ] + ) + + def source_manifests_are_still_blocked() -> bool: core = (ROOT / "crates/ethos-core/Cargo.toml").read_text(encoding="utf-8") verify = (ROOT / "crates/ethos-verify/Cargo.toml").read_text(encoding="utf-8") pdf = (ROOT / "crates/ethos-pdf/Cargo.toml").read_text(encoding="utf-8") return all( [ - 'name = "ethos-core"' in core, + source_manifests_have_activation_shape(), "publish = false" in core, "publish = false" in verify, "publish = false" in pdf, - 'package = "ethos-doc-core"' not in verify, - 'package = "ethos-doc-core"' not in pdf, + 'publication_status = "blocked"' in core, + 'publication_status = "blocked"' in verify, + 'publication_status = "blocked"' in pdf, not (ROOT / ".cargo/config.toml").exists(), not (ROOT / "target/package-registry").exists(), ] @@ -584,6 +614,7 @@ def run_candidate_activation(workspace: Path) -> dict[str, object]: for artifact in artifacts ], "registry_equivalent_consumer_check": "pass", + "source_manifest_activation_applied": source_manifests_have_activation_shape(), "source_manifests_remain_blocked": source_manifests_are_still_blocked(), "package_publication_approved": False, "public_installation_approved": False, diff --git a/.github/scripts/test_determinism_workflow.py b/.github/scripts/test_determinism_workflow.py index 5d2b2a5a..9223b97a 100644 --- a/.github/scripts/test_determinism_workflow.py +++ b/.github/scripts/test_determinism_workflow.py @@ -53,7 +53,7 @@ def test_contract_vectors_run_on_every_matrix_os(self) -> None: text = workflow_text() self.assertIn("runs-on: ${{ matrix.os }}", text) - self.assertIn("cargo test --locked -p ethos-core --all-features", text) + self.assertIn("cargo test --locked -p ethos-doc-core --all-features", text) def test_pdfium_corpus_step_remains_explicitly_configured(self) -> None: text = workflow_text() diff --git a/.github/scripts/test_milestone_d_crop_element_contract.py b/.github/scripts/test_milestone_d_crop_element_contract.py index be4c1b79..d48fc31d 100644 --- a/.github/scripts/test_milestone_d_crop_element_contract.py +++ b/.github/scripts/test_milestone_d_crop_element_contract.py @@ -529,7 +529,7 @@ def test_target_composes_contract_gates(self) -> None: block = target_block("milestone-d-crop-element-contract") required = [ - "cargo test --locked -p ethos-core crop_element", + "cargo test --locked -p ethos-doc-core crop_element", "cargo test --locked -p ethos-cli --test verify " "native_verify_crop_dir_writes_deterministic_crop_descriptors", "cargo test --locked -p ethos-cli --test verify crop_element_cli", diff --git a/.github/scripts/test_milestone_d_grounding_source_contract.py b/.github/scripts/test_milestone_d_grounding_source_contract.py index af824ec3..57d34e9d 100644 --- a/.github/scripts/test_milestone_d_grounding_source_contract.py +++ b/.github/scripts/test_milestone_d_grounding_source_contract.py @@ -117,7 +117,7 @@ def test_target_composes_contract_gates(self) -> None: block = target_block("milestone-d-grounding-source-contract") required = [ - "cargo test --locked -p ethos-core grounding", + "cargo test --locked -p ethos-doc-core grounding", "cargo test --locked -p ethos-cli --test verify native_ethos_verify_produces_non_empty_checks", "cargo test --locked -p ethos-cli --test verify opendataloader_verify_adapter_produces_capability_aware_report", "$(PYTHON) schemas/validate_examples.py", diff --git a/.github/scripts/test_milestone_d_internal_contracts.py b/.github/scripts/test_milestone_d_internal_contracts.py index 69f7c6f6..7341ca9f 100644 --- a/.github/scripts/test_milestone_d_internal_contracts.py +++ b/.github/scripts/test_milestone_d_internal_contracts.py @@ -114,7 +114,7 @@ "inventory": "examples/verify/grounding_source_v1_contract.json", "schema": "schemas/ethos-grounding-source-contract.schema.json", "commands": [ - "cargo test --locked -p ethos-core grounding", + "cargo test --locked -p ethos-doc-core grounding", "cargo test --locked -p ethos-cli --test verify native_ethos_verify_produces_non_empty_checks", "cargo test --locked -p ethos-cli --test verify opendataloader_verify_adapter_produces_capability_aware_report", ] @@ -166,7 +166,7 @@ "inventory": "examples/crop/crop_element_v1_contract.json", "schema": "schemas/ethos-crop-element-contract.schema.json", "commands": [ - "cargo test --locked -p ethos-core crop_element", + "cargo test --locked -p ethos-doc-core crop_element", "cargo test --locked -p ethos-cli --test verify native_verify_crop_dir_writes_deterministic_crop_descriptors", "cargo test --locked -p ethos-cli --test verify crop_element_cli", ] diff --git a/.github/scripts/test_milestone_e_package_publication_approval_decision_record.py b/.github/scripts/test_milestone_e_package_publication_approval_decision_record.py index 740c7a0a..37404041 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_decision_record.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_decision_record.py @@ -155,7 +155,7 @@ def test_current_manifests_tags_and_registry_state_stay_unactivated(self) -> Non for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn("publish = false", verify_manifest) self.assertIn("publish = false", pdf_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py b/.github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py index 117d06c1..51f3ebc3 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py @@ -168,7 +168,7 @@ def test_current_manifests_tags_and_registry_state_stay_unactivated(self) -> Non for value in prep["package_publication_decision_input_packet"]["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn("publish = false", verify_manifest) self.assertIn("publish = false", pdf_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_approval_decision_template.py b/.github/scripts/test_milestone_e_package_publication_approval_decision_template.py index c538ae08..587cfe28 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_decision_template.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_decision_template.py @@ -150,7 +150,7 @@ def test_current_manifests_tags_and_registry_state_stay_unactivated(self) -> Non for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn("publish = false", verify_manifest) self.assertIn("publish = false", pdf_manifest) 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 9e820d7f..e4985817 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_prep.py @@ -101,6 +101,7 @@ "package_approval_decision_record": "docs/validation/milestone-e-package-publication-approval-decision-validation-2026-06-21.md", "package_candidate_activation_evidence": "docs/validation/milestone-e-package-publication-candidate-activation-evidence-validation-2026-06-22.md", "package_approval_decision_refresh": "docs/validation/milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md", + "package_manifest_activation_applied": "docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md", } EXPECTED_PUBLICATION_DECISION_INPUTS = { "decision_status": "not_approved_pending_exact_decision", @@ -137,9 +138,9 @@ EXPECTED_CANDIDATE_CRATE_SURFACE_REVIEW = { "review_state": "candidate_surface_review_recorded_publication_blocked", "included_candidate_crates": [ - "ethos-doc-core from crates/ethos-core; current manifest name ethos-core; publish=false; package-name migration remains pending", - "ethos-verify from crates/ethos-verify; current manifest name ethos-verify; publish=false; dependency manifest activation remains pending", - "ethos-pdf from crates/ethos-pdf; current manifest name ethos-pdf; publish=false; dependency manifest activation and PDFium boundary confirmation must remain current", + "ethos-doc-core from crates/ethos-core; source manifest name ethos-doc-core; lib.name ethos_core; publish=false", + "ethos-verify from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core; publish=false", + "ethos-pdf from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core; PDFium boundary remains current; publish=false", ], "excluded_reserved_crates": [ "ethos-doc remains excluded because no in-tree workspace member or package manifest exists", @@ -157,7 +158,7 @@ "candidate surface review does not approve package publication", "candidate surface review does not select a package publication version", "candidate surface review does not create a package tag", - "candidate surface review does not change Cargo manifests", + "candidate surface review does not approve removing publish=false", "candidate surface review does not approve public installation", "candidate surface review does not approve registry-backed dependent package assembly activation", ], @@ -190,7 +191,7 @@ "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", + "package dependency manifest activation inputs are recorded and source activation is applied for review while publish flags remain false", "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", ], @@ -207,8 +208,8 @@ "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 remove publish=false", + "this bundle does not approve package dependency manifest activation for publication", "this bundle does not create a registry", "this bundle does not activate registry-backed dependent package assembly", "this bundle does not invite public installation", @@ -226,9 +227,9 @@ 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", + "ethos-doc-core mapped from crates/ethos-core; source package-name activation is applied for review while publish=false remains", + "ethos-verify mapped from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core while publish=false remains", + "ethos-pdf mapped from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core, PDFium boundary remains current, and publish=false remains", ], "package_version_map": [ "ethos-doc-core has no selected package publication version", @@ -238,7 +239,7 @@ "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", + "manifest_activation_diff": "applied for source review only; Cargo manifests keep publish=false and package publication remains blocked", "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": [ @@ -265,8 +266,8 @@ "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 remove publish=false", + "this packet does not approve package dependency manifest activation for publication", "this packet does not create a registry", "this packet does not activate registry-backed dependent package assembly", "this packet does not invite public installation", @@ -288,7 +289,7 @@ "version map gap: no package publication version is selected; requires exact SemVer package version or per-crate version map", "tag name gap: no package tag is created; requires exact package tag name", "tag binding gap: no package_tag_source_commit or source tree is selected; requires exact source commit and tree binding", - "manifest activation gap: current Cargo manifests remain unchanged; requires exact package-name migration and dependency activation diff", + "manifest approval gap: source manifest activation is applied for review; requires exact approval before publish flags, tags, public installation, or publication can advance", "registry assembly gap: no registry-backed dependent package assembly is activated; requires exact non-public assembly evidence", "public installation wording gap: no public installation wording is approved; requires exact wording and exclusions", "posture and claims gate gap: gates must rerun after exact public installation wording changes", @@ -296,8 +297,8 @@ "blocked_actions": [ "selecting a package publication version remains blocked", "creating a package tag remains blocked", - "changing Cargo manifests remains blocked", - "activating package dependency manifests remains blocked", + "removing publish=false remains blocked", + "approving package dependency manifest activation for publication remains blocked", "creating a registry remains blocked", "activating registry-backed dependent package assembly remains blocked", "inviting public installation remains blocked", @@ -318,8 +319,8 @@ "non_approvals": [ "this ledger does not select a package publication version", "this ledger does not create a package tag", - "this ledger does not change Cargo manifests", - "this ledger does not activate package dependency manifests", + "this ledger does not remove publish=false", + "this ledger does not approve package dependency manifest activation for publication", "this ledger does not create a registry", "this ledger does not activate registry-backed dependent package assembly", "this ledger does not invite public installation", @@ -477,7 +478,7 @@ def test_approved_prep_names_reserved_crates_and_current_workspace_mapping(self) self.assertIn('"crates/ethos-verify"', cargo) self.assertNotIn('"crates/ethos-doc"', cargo) self.assertNotIn('"crates/ethos-rag"', cargo) - self.assertIn("ethos-doc-core maps to the in-tree ethos-core crate", " ".join(approved["in_tree_reconciliation"])) + self.assertIn("ethos-doc-core maps to crates/ethos-core", " ".join(approved["in_tree_reconciliation"])) self.assertIn("ethos-doc has no in-tree workspace member yet", " ".join(approved["in_tree_reconciliation"])) self.assertIn("ethos-rag has no in-tree workspace member yet", " ".join(approved["in_tree_reconciliation"])) @@ -486,7 +487,7 @@ def test_candidate_crates_remain_publish_false_until_later_approval(self) -> Non verify = read(ROOT / "crates/ethos-verify/Cargo.toml") pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") - self.assertIn('name = "ethos-core"', core) + self.assertIn('name = "ethos-doc-core"', core) self.assertIn("publish = false", core) self.assertIn('name = "ethos-verify"', verify) self.assertIn("publish = false", verify) @@ -507,7 +508,7 @@ def test_evidence_status_matches_decider_input(self) -> None: self.assertIn("manifest-activation prep recorded", status["install_build_smoke_path"]) self.assertIn("registry-assembly prep recorded", status["install_build_smoke_path"]) self.assertIn("registry-assembly activation prep recorded", status["install_build_smoke_path"]) - self.assertIn("current source-tree manifests remain unchanged", status["install_build_smoke_path"]) + self.assertIn("manifest activation applied for source review", status["install_build_smoke_path"]) self.assertIn("publication remains blocked", status["install_build_smoke_path"]) self.assertIn("version/tag policy follow-up", status["version_tag_policy"]) self.assertIn("real-version-selection prep recorded", status["version_tag_policy"]) @@ -575,7 +576,7 @@ def test_candidate_crate_surface_review_keeps_publication_blocked(self) -> None: self.assertIn('"crates/ethos-pdf"', cargo) self.assertNotIn('"crates/ethos-doc"', cargo) self.assertNotIn('"crates/ethos-rag"', cargo) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) @@ -649,7 +650,7 @@ def test_combined_package_publication_decision_prep_bundle_blocks_all_actions(se 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 remove publish=false", 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"]) @@ -659,7 +660,7 @@ def test_combined_package_publication_decision_prep_bundle_blocks_all_actions(se 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-doc-core"', core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) self.assertIn('name = "ethos-pdf"', pdf_manifest) self.assertIn('version = "0.1.0"', cargo) @@ -684,7 +685,7 @@ def test_package_publication_approval_request_packet_keeps_all_actions_blocked(s packet["package_tag_source_commit"], ) self.assertEqual( - "not prepared; current Cargo manifests remain unchanged", + "applied for source review only; Cargo manifests keep publish=false and package publication remains blocked", packet["manifest_activation_diff"], ) self.assertIn("public installation remains blocked", packet["public_installation_wording"]) @@ -692,7 +693,7 @@ def test_package_publication_approval_request_packet_keeps_all_actions_blocked(s 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 remove publish=false", 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"]) @@ -702,7 +703,7 @@ def test_package_publication_approval_request_packet_keeps_all_actions_blocked(s 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-doc-core"', core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) self.assertIn('name = "ethos-pdf"', pdf_manifest) @@ -718,7 +719,7 @@ def test_package_publication_pre_approval_gap_ledger_keeps_resolution_inputs_exp self.assertEqual(7, len(ledger["gap_rows"])) self.assertEqual(8, len(ledger["blocked_actions"])) self.assertIn("creating a package tag remains blocked", ledger["blocked_actions"]) - self.assertIn("changing Cargo manifests remains blocked", ledger["blocked_actions"]) + self.assertIn("removing publish=false remains blocked", ledger["blocked_actions"]) self.assertIn("inviting public installation remains blocked", ledger["blocked_actions"]) self.assertIn( "exact package_tag_source_commit and package source tree", @@ -733,7 +734,7 @@ def test_package_publication_pre_approval_gap_ledger_keeps_resolution_inputs_exp 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-doc-core"', core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) self.assertIn('name = "ethos-pdf"', pdf_manifest) self.assertIn('version = "0.1.0"', cargo) diff --git a/.github/scripts/test_milestone_e_package_publication_approval_readiness_review.py b/.github/scripts/test_milestone_e_package_publication_approval_readiness_review.py index 44324da4..d27c0211 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_readiness_review.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_readiness_review.py @@ -42,6 +42,26 @@ SOURCE_COMMIT = "9054f1c3823b8f0ff69f0776b60060b642705e28" SOURCE_SHORT = "9054f1c" SOURCE_TREE = "3f8cb66249826d67ab6030032c7784a2a4ff411b" +HISTORICAL_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", +] +HISTORICAL_CANDIDATE_MANIFEST_DIFF = [ + "crates/ethos-core/Cargo.toml candidate package-name migration: package.name ethos-core -> ethos-doc-core; current manifest remains unchanged", + "crates/ethos-verify/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "crates/ethos-pdf/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "included candidate crates require later publish-flag activation only after dedicated approval; current manifests remain publish=false", +] +HISTORICAL_RETAINED_BLOCKERS = [ + "candidate package version map is recorded but no package publication version is selected", + "candidate package tag names are recorded but no package tag is created", + "candidate manifest activation diff is recorded but no Cargo manifest is changed", + "registry-backed dependent package assembly evidence remains required", + "public installation remains blocked", + "package publication remains blocked", + "real-version cargo publish remains blocked", +] FORBIDDEN_SCOPE_EXPANSION = [ "public reports are approved", "public result wording approved", @@ -115,15 +135,15 @@ def test_readiness_review_summarizes_present_inputs_and_remaining_blockers(self) record = normalized(RECORD) self.assertEqual("decision_input_packet_recorded_publication_blocked", packet["packet_state"]) - for crate in packet["candidate_crates"]: + for crate in HISTORICAL_CANDIDATE_CRATES: self.assertIn(crate, record) for version in packet["candidate_version_map"]: self.assertIn(version, record) for tag in packet["candidate_package_tag_names"]: self.assertIn(tag, record) - for candidate_diff in packet["candidate_manifest_activation_diff"]: + for candidate_diff in HISTORICAL_CANDIDATE_MANIFEST_DIFF: self.assertIn(candidate_diff, record) - for blocker in packet["retained_blockers"]: + for blocker in HISTORICAL_RETAINED_BLOCKERS: self.assertIn(blocker, record) self.assertIn("exact package publication approval decision record remains required", record) self.assertIn("registry-backed dependent package assembly evidence remains required", record) @@ -142,7 +162,7 @@ def test_candidate_inputs_do_not_activate_tags_or_manifests(self) -> None: for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_approval_resolution_plan.py b/.github/scripts/test_milestone_e_package_publication_approval_resolution_plan.py index 3f1c5517..239c25a2 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_resolution_plan.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_resolution_plan.py @@ -42,6 +42,40 @@ CURRENT_MAIN = "524535a621532b5382f91a38d9c3f85d6714a526" CURRENT_MAIN_SHORT = "524535a" CURRENT_TREE = "0785ffca8423c42e2c4105df7752e290cc88e5c2" +HISTORICAL_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", +] +HISTORICAL_GAP_ROWS = [ + "version map gap: no package publication version is selected; requires exact SemVer package version or per-crate version map", + "tag name gap: no package tag is created; requires exact package tag name", + "tag binding gap: no package_tag_source_commit or source tree is selected; requires exact source commit and tree binding", + "manifest activation gap: current Cargo manifests remain unchanged; requires exact package-name migration and dependency activation diff", + "registry assembly gap: no registry-backed dependent package assembly is activated; requires exact non-public assembly evidence", + "public installation wording gap: no public installation wording is approved; requires exact wording and exclusions", + "posture and claims gate gap: gates must rerun after exact public installation wording changes", +] +HISTORICAL_BLOCKED_ACTIONS = [ + "selecting a package publication version remains blocked", + "creating a package tag remains blocked", + "changing Cargo manifests remains blocked", + "activating package dependency manifests remains blocked", + "creating a registry remains blocked", + "activating registry-backed dependent package assembly remains blocked", + "inviting public installation remains blocked", + "approving package publication remains blocked", +] +HISTORICAL_NON_APPROVALS = [ + "this ledger does not select a package publication version", + "this ledger does not create a package tag", + "this ledger does not change Cargo manifests", + "this ledger does not activate package dependency manifests", + "this ledger does not create a registry", + "this ledger does not activate registry-backed dependent package assembly", + "this ledger does not invite public installation", + "this ledger does not approve package publication", +] FORBIDDEN_SCOPE_EXPANSION = [ "public reports are approved", "public result wording approved", @@ -111,17 +145,17 @@ def test_record_covers_gap_ledger_and_request_packet_without_approval(self) -> N record = normalized(RECORD) self.assertIn(ledger["ledger_state"], record) - for row in ledger["gap_rows"]: + for row in HISTORICAL_GAP_ROWS: self.assertIn(row, record) - for action in ledger["blocked_actions"]: + for action in HISTORICAL_BLOCKED_ACTIONS: self.assertIn(action, record) for required in ledger["required_resolution_inputs"]: self.assertIn(required, record) - for non_approval in ledger["non_approvals"]: + for non_approval in HISTORICAL_NON_APPROVALS: self.assertIn(non_approval, record) for blocker in ledger["retained_blockers"]: self.assertIn(blocker, record) - for crate in packet["candidate_crates"]: + for crate in HISTORICAL_CANDIDATE_CRATES: self.assertIn(crate, record) for exclusion in packet["explicit_exclusions"]: self.assertIn(exclusion, record) diff --git a/.github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py b/.github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py index a601eb8a..947e45e0 100644 --- a/.github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py +++ b/.github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py @@ -160,7 +160,7 @@ def test_source_manifests_remain_blocked_and_profile_copy_is_in_sync(self) -> No self.assertEqual(read(ROOT_PROFILE), read(PDF_PROFILE)) self.assertIn('include_str!("../assets/ethos-deterministic-v1.json")', pdf_lib) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn("publish = false", verify_manifest) self.assertIn("publish = false", pdf_manifest) 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 index e3e34f81..01336a6e 100644 --- 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 @@ -34,6 +34,38 @@ ) VALIDATION_README = ROOT / "docs/validation/README.md" CI_WORKFLOW = ROOT / ".github/workflows/ci.yml" +HISTORICAL_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", +] +HISTORICAL_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", +] +HISTORICAL_MANIFEST_ACTIVATION_DIFF = "not prepared; current Cargo manifests remain unchanged" +HISTORICAL_BUNDLE_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", +] +HISTORICAL_PACKET_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", +] FORBIDDEN_SCOPE_EXPANSION = [ "public reports are approved", @@ -111,11 +143,11 @@ def test_record_matches_combined_decision_bundle_scope(self) -> None: record = normalized(RECORD) self.assertEqual("combined_decision_inputs_recorded_actions_blocked", bundle["decision_state"]) - for boundary in bundle["review_boundary"]: + for boundary in HISTORICAL_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"]: + for non_approval in HISTORICAL_BUNDLE_NON_APPROVALS: self.assertIn(non_approval, record) for blocker in bundle["retained_blockers"]: self.assertIn(blocker, record) @@ -130,21 +162,21 @@ def test_record_matches_non_activating_approval_request_packet(self) -> None: self.assertEqual("approval_request_packet_recorded_publication_blocked", packet["packet_state"]) self.assertIn(packet["packet_state"], record) - for candidate in packet["candidate_crates"]: + for candidate in HISTORICAL_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(HISTORICAL_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"]: + for non_approval in HISTORICAL_PACKET_NON_APPROVALS: self.assertIn(non_approval, record) for blocker in packet["retained_blockers"]: self.assertIn(blocker, record) diff --git a/.github/scripts/test_milestone_e_package_publication_decision_input_packet.py b/.github/scripts/test_milestone_e_package_publication_decision_input_packet.py index 50343966..ac4f68ef 100644 --- a/.github/scripts/test_milestone_e_package_publication_decision_input_packet.py +++ b/.github/scripts/test_milestone_e_package_publication_decision_input_packet.py @@ -42,6 +42,36 @@ SOURCE_COMMIT = "54bf70f57b8c357ec76059e31d203b80ade7c0e4" SOURCE_SHORT = "54bf70f" SOURCE_TREE = "5a197bee718e3b31399563340169e9efd4f1317c" +HISTORICAL_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", +] +HISTORICAL_CANDIDATE_MANIFEST_DIFF = [ + "crates/ethos-core/Cargo.toml candidate package-name migration: package.name ethos-core -> ethos-doc-core; current manifest remains unchanged", + "crates/ethos-verify/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "crates/ethos-pdf/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "included candidate crates require later publish-flag activation only after dedicated approval; current manifests remain publish=false", +] +HISTORICAL_NON_APPROVALS = [ + "this exact decision input packet does not select a package publication version", + "this exact decision input packet does not create a package tag", + "this exact decision input packet does not change Cargo manifests", + "this exact decision input packet does not activate package dependency manifests", + "this exact decision input packet does not create a registry", + "this exact decision input packet does not activate registry-backed dependent package assembly", + "this exact decision input packet does not invite public installation", + "this exact decision input packet does not approve package publication", +] +HISTORICAL_RETAINED_BLOCKERS = [ + "candidate package version map is recorded but no package publication version is selected", + "candidate package tag names are recorded but no package tag is created", + "candidate manifest activation diff is recorded but no Cargo manifest is changed", + "registry-backed dependent package assembly evidence remains required", + "public installation remains blocked", + "package publication remains blocked", + "real-version cargo publish remains blocked", +] FORBIDDEN_SCOPE_EXPANSION = [ "public reports are approved", "public result wording approved", @@ -126,7 +156,8 @@ def test_packet_records_exact_inputs_without_approval(self) -> None: self.assertEqual(4, len(packet["candidate_manifest_activation_diff"])) self.assertIn("0.1.0; not selected or approved", " ".join(packet["candidate_version_map"])) self.assertIn("tag is not created", " ".join(packet["candidate_package_tag_names"])) - self.assertIn("current manifest remains unchanged", " ".join(packet["candidate_manifest_activation_diff"])) + self.assertIn("source package-name activation", " ".join(packet["candidate_manifest_activation_diff"])) + self.assertIn("publish=false remains", " ".join(packet["candidate_manifest_activation_diff"])) self.assertIn("no registry is created and no assembly is activated", packet["registry_backed_assembly_input"]) self.assertIn("public installation remains blocked", packet["candidate_public_installation_wording"]) self.assertIn("this exact decision input packet does not approve package publication", packet["non_approvals"]) @@ -134,13 +165,13 @@ def test_packet_records_exact_inputs_without_approval(self) -> None: self.assertIn("package publication remains blocked", packet["retained_blockers"]) self.assertIn("public installation remains blocked", packet["retained_blockers"]) for values in ( - packet["candidate_crates"], + HISTORICAL_CANDIDATE_CRATES, packet["candidate_version_map"], packet["candidate_package_tag_names"], - packet["candidate_manifest_activation_diff"], + HISTORICAL_CANDIDATE_MANIFEST_DIFF, packet["required_before_approval"], - packet["non_approvals"], - packet["retained_blockers"], + HISTORICAL_NON_APPROVALS, + HISTORICAL_RETAINED_BLOCKERS, ): for value in values: self.assertIn(value, record) @@ -154,7 +185,7 @@ def test_candidate_tags_do_not_exist_and_manifests_remain_inactive(self) -> None for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_dependency_ordering.py b/.github/scripts/test_milestone_e_package_publication_dependency_ordering.py index b695e42c..98bc396d 100644 --- a/.github/scripts/test_milestone_e_package_publication_dependency_ordering.py +++ b/.github/scripts/test_milestone_e_package_publication_dependency_ordering.py @@ -93,7 +93,7 @@ def test_package_prep_artifact_records_dependency_ordering_follow_up(self) -> No self.assertIn("dependency-ordering follow-up recorded", status) self.assertIn("manifest-migration prep recorded", status) self.assertIn("registry-assembly prep recorded", status) - self.assertIn("current source-tree manifests remain unchanged", status) + self.assertIn("manifest activation applied for source review", status) self.assertIn("publication remains blocked", status) self.assertIn("registry-backed dependent package assembly", blocker_text) self.assertIn("package dependency manifest activation", blocker_text) @@ -107,7 +107,7 @@ def test_current_manifests_stay_source_tree_only_until_later_approval(self) -> N verify = read(ROOT / "crates/ethos-verify/Cargo.toml") pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") - self.assertIn('name = "ethos-core"', core) + self.assertIn('name = "ethos-doc-core"', core) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core) self.assertIn("publish = false", core) self.assertIn("publish = false", verify) diff --git a/.github/scripts/test_milestone_e_package_publication_dry_run_smoke.py b/.github/scripts/test_milestone_e_package_publication_dry_run_smoke.py index 1bd201f5..a203fe41 100644 --- a/.github/scripts/test_milestone_e_package_publication_dry_run_smoke.py +++ b/.github/scripts/test_milestone_e_package_publication_dry_run_smoke.py @@ -35,8 +35,8 @@ ) LOCAL_SMOKE_COMMANDS = [ - "cargo package --locked --offline -p ethos-core --allow-dirty --no-verify", - "cargo package --list --locked --offline -p ethos-core --allow-dirty", + "cargo package --locked --offline -p ethos-doc-core --allow-dirty --no-verify", + "cargo package --list --locked --offline -p ethos-doc-core --allow-dirty", "cargo check --locked --offline -p ethos-verify", "cargo check --locked --offline -p ethos-pdf", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_dry_run_smoke.py", @@ -88,8 +88,8 @@ def test_local_smoke_make_target_is_non_publishing(self) -> None: commands = [line.strip() for line in block.splitlines() if line.strip()] self.assertEqual(LOCAL_SMOKE_COMMANDS, commands) - self.assertIn("cargo package --locked --offline -p ethos-core --allow-dirty --no-verify", block) - self.assertIn("cargo package --list --locked --offline -p ethos-core --allow-dirty", block) + self.assertIn("cargo package --locked --offline -p ethos-doc-core --allow-dirty --no-verify", block) + self.assertIn("cargo package --list --locked --offline -p ethos-doc-core --allow-dirty", block) self.assertIn("cargo check --locked --offline -p ethos-verify", block) self.assertIn("cargo check --locked --offline -p ethos-pdf", block) self.assertNotIn("cargo publish", block) @@ -121,7 +121,7 @@ def test_dependent_package_assembly_blocker_is_recorded(self) -> None: self.assertIn("dependency-ordering follow-up recorded", status) self.assertIn("manifest-migration prep recorded", status) self.assertIn("registry-assembly prep recorded", status) - self.assertIn("current source-tree manifests remain unchanged", status) + self.assertIn("manifest activation applied for source review", status) self.assertIn("publication remains blocked", status) self.assertIn("registry-backed dependent package assembly", blocker_text) self.assertIn("package dependency manifest activation", blocker_text) diff --git a/.github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py b/.github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py new file mode 100644 index 00000000..38e835a1 --- /dev/null +++ b/.github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py @@ -0,0 +1,202 @@ +#!/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 subprocess +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-manifest-activation-applied-validation-2026-06-22.md" +) +VALIDATION_README = ROOT / "docs/validation/README.md" +PREP_SCOPE = ROOT / "docs/milestone-e-prep-scope.md" +ROADMAP = ROOT / "docs/roadmap.md" +EXECUTION_STATUS = ROOT / "docs/execution-status.md" +CI_WORKFLOW = ROOT / ".github/workflows/ci.yml" + +SOURCE_COMMIT = "e517d76c7c5f34984f62181769809637e7123bbc" +SOURCE_SHORT = "e517d76" +SOURCE_TREE = "b0cdeca1387f2080a1f9dca4f075e3a4bd7a92ec" +PACKAGE_TAGS = ( + "ethos-package-ethos-doc-core-0.1.0", + "ethos-package-ethos-verify-0.1.0", + "ethos-package-ethos-pdf-0.1.0", +) +FORBIDDEN_SCOPE_EXPANSION = [ + "package publication approved", + "package publication is approved", + "public installation approved", + "public installation is approved", + "public installation wording is approved", + "package tag creation approved", + "registry creation approved", + "registry-backed assembly activation approved", + "release-ready", + "release artifact approved", + "package-ready", + "packages are published", + "published packages", + "production-ready", + "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")) + + +def git(*args: str) -> str: + return subprocess.check_output( + ["git", *args], + cwd=ROOT, + encoding="utf-8", + stderr=subprocess.DEVNULL, + ).strip() + + +class MilestoneEPackagePublicationManifestActivationAppliedTests(unittest.TestCase): + def test_record_is_indexed_and_source_bound(self) -> None: + prep = load_json(PREP) + readme = read(VALIDATION_README) + record = normalized(RECORD) + + self.assertIn(RECORD.name, readme) + self.assertIn("package publication manifest activation applied validation", readme) + self.assertEqual( + "docs/validation/" + "milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md", + prep["follow_up_records"]["package_manifest_activation_applied"], + ) + self.assertIn(f"Validated source HEAD before this record: `{SOURCE_SHORT}`", read(RECORD)) + self.assertIn(f"Manifest activation source commit before this record: `{SOURCE_COMMIT}`", record) + self.assertIn(f"Manifest activation source tree before this record: `{SOURCE_TREE}`", record) + self.assertEqual(SOURCE_COMMIT, git("rev-parse", SOURCE_SHORT)) + self.assertEqual(SOURCE_TREE, git("rev-parse", f"{SOURCE_SHORT}^{{tree}}")) + + def test_source_manifests_have_activated_but_blocked_shape(self) -> None: + workspace = read(ROOT / "Cargo.toml") + lockfile = read(ROOT / "Cargo.lock") + core = read(ROOT / "crates/ethos-core/Cargo.toml") + verify = read(ROOT / "crates/ethos-verify/Cargo.toml") + pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") + + self.assertIn( + 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", ' + 'version = "0.1.0", default-features = false }', + workspace, + ) + self.assertIn('name = "ethos-doc-core"', core) + self.assertIn('[lib]\nname = "ethos_core"', core) + self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core) + self.assertIn('name = "ethos-doc-core"', lockfile) + self.assertNotIn('name = "ethos-core"', lockfile) + self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) + self.assertIn('ethos-core = { workspace = true, features = ["full"] }', pdf) + self.assertNotIn('package = "ethos-doc-core"', verify) + self.assertNotIn('package = "ethos-doc-core"', pdf) + for manifest in (core, verify, pdf): + self.assertIn("publish = false", manifest) + self.assertIn('publication_status = "blocked"', manifest) + + def test_tags_registry_and_public_installation_remain_blocked(self) -> None: + prep = load_json(PREP) + + for tag in PACKAGE_TAGS: + self.assertEqual("", git("tag", "--list", tag), tag) + self.assertFalse((ROOT / ".cargo/config.toml").exists()) + self.assertFalse((ROOT / "target/package-registry").exists()) + self.assertIn( + "public installation remains blocked", + prep["package_publication_pre_approval_gap_ledger"]["retained_blockers"], + ) + self.assertIn( + "package publication remains blocked", + prep["package_publication_pre_approval_gap_ledger"]["retained_blockers"], + ) + + def test_docs_reference_activation_and_retained_blockers(self) -> None: + for path in (PREP_SCOPE, ROADMAP, EXECUTION_STATUS, VALIDATION_README): + doc = normalized(path) + + self.assertIn(RECORD.name, doc, str(path)) + self.assertIn("manifest activation applied", doc.lower(), str(path)) + self.assertIn("package publication remains blocked", doc, str(path)) + self.assertIn("public installation remains blocked", doc, str(path)) + + def test_make_and_ci_run_activation_guard_after_decision_refresh(self) -> None: + make_block = target_block("milestone-e-prep") + ci = read(CI_WORKFLOW) + refresh_guard = "test_milestone_e_package_publication_approval_decision_refresh.py" + activation_guard = "test_milestone_e_package_publication_manifest_activation_applied.py" + public_facing_guard = "test_milestone_e_public_facing_readiness_ledger.py" + + for text, prefix in ((make_block, "$(PYTHON) .github/scripts/"), (ci, "python3 .github/scripts/")): + self.assertIn(prefix + activation_guard, text) + self.assertEqual(1, text.count(prefix + activation_guard)) + self.assertLess(text.index(prefix + refresh_guard), text.index(prefix + activation_guard)) + self.assertLess(text.index(prefix + activation_guard), text.index(prefix + public_facing_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_package_publication_manifest_activation_diff_review.py b/.github/scripts/test_milestone_e_package_publication_manifest_activation_diff_review.py index b08d0292..501a10e1 100644 --- a/.github/scripts/test_milestone_e_package_publication_manifest_activation_diff_review.py +++ b/.github/scripts/test_milestone_e_package_publication_manifest_activation_diff_review.py @@ -42,6 +42,12 @@ SOURCE_COMMIT = "89d24c84614a7c961dcecdccf85a9e9eca235046" SOURCE_SHORT = "89d24c8" SOURCE_TREE = "21b263dca908ef7cc977e7669e40206096eef93e" +HISTORICAL_CANDIDATE_MANIFEST_DIFF = [ + "crates/ethos-core/Cargo.toml candidate package-name migration: package.name ethos-core -> ethos-doc-core; current manifest remains unchanged", + "crates/ethos-verify/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "crates/ethos-pdf/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "included candidate crates require later publish-flag activation only after dedicated approval; current manifests remain publish=false", +] FORBIDDEN_SCOPE_EXPANSION = [ "public reports are approved", "public result wording approved", @@ -114,7 +120,7 @@ def test_record_carries_candidate_manifest_diff_without_activation(self) -> None packet = load_json(PREP)["package_publication_decision_input_packet"] record = normalized(RECORD) - for candidate_diff in packet["candidate_manifest_activation_diff"]: + for candidate_diff in HISTORICAL_CANDIDATE_MANIFEST_DIFF: self.assertIn(candidate_diff, record) self.assertIn("Candidate manifest activation diff is recorded", record) self.assertIn("No Cargo manifest was changed", record) @@ -134,7 +140,7 @@ def test_current_manifests_stay_unactivated(self) -> None: for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py b/.github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py index 6db53afc..e2000caa 100644 --- a/.github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_manifest_activation_prep.py @@ -92,7 +92,7 @@ def test_package_prep_artifact_records_manifest_activation_prep(self) -> None: prep["follow_up_records"]["package_manifest_activation_prep"], ) self.assertIn("manifest-activation prep recorded", status) - self.assertIn("current source-tree manifests remain unchanged", status) + self.assertIn("manifest activation applied for source review", status) self.assertIn("publication remains blocked", status) self.assertIn("package dependency manifest activation", blocker_text) self.assertIn("registry-backed dependent package assembly activation", blocker_text) @@ -105,11 +105,11 @@ def test_current_manifest_dependencies_stay_source_tree_only(self) -> None: pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") core = read(ROOT / "crates/ethos-core/Cargo.toml") - self.assertIn('ethos-core = { path = "crates/ethos-core"', workspace) - self.assertNotIn('package = "ethos-doc-core"', workspace) + self.assertIn('ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core"', workspace) self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) self.assertIn('ethos-core = { workspace = true, features = ["full"] }', pdf) - self.assertIn('name = "ethos-core"', core) + self.assertIn('name = "ethos-doc-core"', core) + self.assertIn('[lib]\nname = "ethos_core"', core) self.assertIn("publish = false", core) self.assertIn("publish = false", verify) self.assertIn("publish = false", pdf) diff --git a/.github/scripts/test_milestone_e_package_publication_manifest_migration_prep.py b/.github/scripts/test_milestone_e_package_publication_manifest_migration_prep.py index a7383ef2..d7f9b2aa 100644 --- a/.github/scripts/test_milestone_e_package_publication_manifest_migration_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_manifest_migration_prep.py @@ -92,7 +92,7 @@ def test_package_prep_artifact_records_manifest_migration_prep(self) -> None: ) self.assertIn("manifest-migration prep recorded", status) self.assertIn("registry-assembly prep recorded", status) - self.assertIn("current source-tree manifests remain unchanged", status) + self.assertIn("manifest activation applied for source review", status) self.assertIn("publication remains blocked", status) self.assertIn("registry-backed dependent package assembly activation", blocker_text) self.assertIn("package dependency manifest activation", blocker_text) @@ -107,19 +107,19 @@ def test_current_manifests_remain_unmigrated_source_tree_manifests(self) -> None verify = read(ROOT / "crates/ethos-verify/Cargo.toml") pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") - self.assertIn('name = "ethos-core"', core) - self.assertNotIn('\nname = "ethos-doc-core"\n', core) + self.assertIn('name = "ethos-doc-core"', core) + self.assertIn('[lib]\nname = "ethos_core"', core) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', core) self.assertIn("publish = false", core) self.assertIn("publish = false", verify) self.assertIn("publish = false", pdf) self.assertIn( - 'ethos-core = { path = "crates/ethos-core", version = "0.1.0", default-features = false }', + 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.0", default-features = false }', workspace, ) self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) self.assertIn('ethos-core = { workspace = true, features = ["full"] }', pdf) - for manifest in (workspace, verify, pdf): + for manifest in (verify, pdf): self.assertNotIn('package = "ethos-doc-core"', manifest) def test_manifest_migration_prep_record_names_future_shape_without_activation(self) -> None: diff --git a/.github/scripts/test_milestone_e_package_publication_metadata_readiness.py b/.github/scripts/test_milestone_e_package_publication_metadata_readiness.py index 9c8a9049..fcd93bec 100644 --- a/.github/scripts/test_milestone_e_package_publication_metadata_readiness.py +++ b/.github/scripts/test_milestone_e_package_publication_metadata_readiness.py @@ -137,9 +137,9 @@ def test_core_public_name_split_is_explicit(self) -> None: readme = normalized(ROOT / "crates/ethos-core/README.md") manifest = read(ROOT / "crates/ethos-core/Cargo.toml") - self.assertIn('name = "ethos-core"', manifest) + self.assertIn('name = "ethos-doc-core"', manifest) self.assertIn('reserved_crates_io_name = "ethos-doc-core"', manifest) - self.assertIn("in-tree crate name remains `ethos-core`", readme) + self.assertIn("Rust library name remains `ethos_core`", readme) self.assertIn("public crates.io identifier `ethos-doc-core`", readme) def test_pdfium_boundary_remains_explicit(self) -> None: diff --git a/.github/scripts/test_milestone_e_package_publication_pre_approval_gap_ledger.py b/.github/scripts/test_milestone_e_package_publication_pre_approval_gap_ledger.py index 287f52c4..5ff65ee0 100644 --- a/.github/scripts/test_milestone_e_package_publication_pre_approval_gap_ledger.py +++ b/.github/scripts/test_milestone_e_package_publication_pre_approval_gap_ledger.py @@ -34,6 +34,35 @@ ) VALIDATION_README = ROOT / "docs/validation/README.md" CI_WORKFLOW = ROOT / ".github/workflows/ci.yml" +HISTORICAL_GAP_ROWS = [ + "version map gap: no package publication version is selected; requires exact SemVer package version or per-crate version map", + "tag name gap: no package tag is created; requires exact package tag name", + "tag binding gap: no package_tag_source_commit or source tree is selected; requires exact source commit and tree binding", + "manifest activation gap: current Cargo manifests remain unchanged; requires exact package-name migration and dependency activation diff", + "registry assembly gap: no registry-backed dependent package assembly is activated; requires exact non-public assembly evidence", + "public installation wording gap: no public installation wording is approved; requires exact wording and exclusions", + "posture and claims gate gap: gates must rerun after exact public installation wording changes", +] +HISTORICAL_BLOCKED_ACTIONS = [ + "selecting a package publication version remains blocked", + "creating a package tag remains blocked", + "changing Cargo manifests remains blocked", + "activating package dependency manifests remains blocked", + "creating a registry remains blocked", + "activating registry-backed dependent package assembly remains blocked", + "inviting public installation remains blocked", + "approving package publication remains blocked", +] +HISTORICAL_NON_APPROVALS = [ + "this ledger does not select a package publication version", + "this ledger does not create a package tag", + "this ledger does not change Cargo manifests", + "this ledger does not activate package dependency manifests", + "this ledger does not create a registry", + "this ledger does not activate registry-backed dependent package assembly", + "this ledger does not invite public installation", + "this ledger does not approve package publication", +] FORBIDDEN_SCOPE_EXPANSION = [ "public reports are approved", @@ -110,13 +139,13 @@ def test_record_matches_gap_ledger_without_approving_actions(self) -> None: self.assertEqual("pre_approval_gaps_recorded_publication_blocked", ledger["ledger_state"]) self.assertIn(ledger["ledger_state"], record) - for row in ledger["gap_rows"]: + for row in HISTORICAL_GAP_ROWS: self.assertIn(row, record) - for action in ledger["blocked_actions"]: + for action in HISTORICAL_BLOCKED_ACTIONS: self.assertIn(action, record) for required in ledger["required_resolution_inputs"]: self.assertIn(required, record) - for non_approval in ledger["non_approvals"]: + for non_approval in HISTORICAL_NON_APPROVALS: self.assertIn(non_approval, record) for blocker in ledger["retained_blockers"]: self.assertIn(blocker, record) diff --git a/.github/scripts/test_milestone_e_package_publication_public_installation_wording_review.py b/.github/scripts/test_milestone_e_package_publication_public_installation_wording_review.py index 5b24b97f..f843b947 100644 --- a/.github/scripts/test_milestone_e_package_publication_public_installation_wording_review.py +++ b/.github/scripts/test_milestone_e_package_publication_public_installation_wording_review.py @@ -154,7 +154,7 @@ def test_current_manifests_tags_and_registry_state_stay_unactivated(self) -> Non for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('name = "ethos-doc-core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn("publish = false", verify_manifest) self.assertIn("publish = false", pdf_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py b/.github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py index 4907fa50..c496f288 100644 --- a/.github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_registry_assembly_activation_prep.py @@ -92,7 +92,7 @@ def test_package_prep_artifact_records_registry_assembly_activation_prep(self) - prep["follow_up_records"]["package_registry_assembly_activation_prep"], ) self.assertIn("registry-assembly activation prep recorded", status) - self.assertIn("current source-tree manifests remain unchanged", status) + self.assertIn("manifest activation applied for source review", status) self.assertIn("publication remains blocked", status) self.assertIn("registry-backed dependent package assembly activation", blocker_text) self.assertIn("package dependency manifest activation", blocker_text) @@ -107,11 +107,11 @@ def test_current_manifests_and_registry_state_stay_source_tree_only(self) -> Non pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") core = read(ROOT / "crates/ethos-core/Cargo.toml") - self.assertIn('ethos-core = { path = "crates/ethos-core"', workspace) - self.assertNotIn('package = "ethos-doc-core"', workspace) + self.assertIn('ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core"', workspace) self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) self.assertIn('ethos-core = { workspace = true, features = ["full"] }', pdf) - self.assertIn('name = "ethos-core"', core) + self.assertIn('name = "ethos-doc-core"', core) + self.assertIn('[lib]\nname = "ethos_core"', core) self.assertIn("publish = false", core) self.assertIn("publish = false", verify) self.assertIn("publish = false", pdf) diff --git a/.github/scripts/test_milestone_e_package_publication_registry_assembly_evidence_review.py b/.github/scripts/test_milestone_e_package_publication_registry_assembly_evidence_review.py index 3a29411a..4be49a36 100644 --- a/.github/scripts/test_milestone_e_package_publication_registry_assembly_evidence_review.py +++ b/.github/scripts/test_milestone_e_package_publication_registry_assembly_evidence_review.py @@ -135,9 +135,9 @@ def test_current_manifests_and_registry_state_stay_unactivated(self) -> None: for value in packet["candidate_package_tag_names"]: tag = value.split(": ", maxsplit=1)[1].split(";", maxsplit=1)[0] self.assertEqual("", git("tag", "--list", tag)) - self.assertIn('ethos-core = { path = "crates/ethos-core"', workspace) - self.assertNotIn('package = "ethos-doc-core"', workspace) - self.assertIn('name = "ethos-core"', core_manifest) + self.assertIn('ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core"', workspace) + self.assertIn('name = "ethos-doc-core"', core_manifest) + self.assertIn('[lib]\nname = "ethos_core"', core_manifest) self.assertIn("publish = false", core_manifest) self.assertIn('name = "ethos-verify"', verify_manifest) self.assertIn("publish = false", verify_manifest) diff --git a/.github/scripts/test_milestone_e_package_publication_registry_assembly_prep.py b/.github/scripts/test_milestone_e_package_publication_registry_assembly_prep.py index 3a9b6edc..f51a3ab2 100644 --- a/.github/scripts/test_milestone_e_package_publication_registry_assembly_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_registry_assembly_prep.py @@ -91,7 +91,7 @@ def test_package_prep_artifact_records_registry_assembly_prep(self) -> None: prep["follow_up_records"]["package_registry_assembly_prep"], ) self.assertIn("registry-assembly prep recorded", status) - self.assertIn("current source-tree manifests remain unchanged", status) + self.assertIn("manifest activation applied for source review", status) self.assertIn("publication remains blocked", status) self.assertIn("registry-backed dependent package assembly activation", blocker_text) self.assertIn("package dependency manifest activation", blocker_text) @@ -106,17 +106,17 @@ def test_current_manifests_stay_source_tree_only(self) -> None: verify = read(ROOT / "crates/ethos-verify/Cargo.toml") pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") - self.assertIn('name = "ethos-core"', core) + self.assertIn('name = "ethos-doc-core"', core) self.assertIn("publish = false", core) self.assertIn("publish = false", verify) self.assertIn("publish = false", pdf) self.assertIn( - 'ethos-core = { path = "crates/ethos-core", version = "0.1.0", default-features = false }', + 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.0", default-features = false }', workspace, ) self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) self.assertIn('ethos-core = { workspace = true, features = ["full"] }', pdf) - for manifest in (workspace, verify, pdf): + for manifest in (verify, pdf): self.assertNotIn('package = "ethos-doc-core"', manifest) def test_registry_assembly_prep_record_names_future_rehearsal_boundary(self) -> None: 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 586ecac9..1133dc3d 100644 --- a/.github/scripts/test_milestone_e_prep_guard_sequence_index.py +++ b/.github/scripts/test_milestone_e_prep_guard_sequence_index.py @@ -116,6 +116,7 @@ "$(PYTHON) .github/scripts/test_milestone_e_package_publication_approval_decision_record.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py", + "$(PYTHON) .github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py", "$(PYTHON) .github/scripts/test_milestone_e_public_facing_readiness_ledger.py", "$(PYTHON) .github/scripts/test_milestone_e_public_beta_current_main_refresh_prep.py", "$(PYTHON) .github/scripts/test_milestone_e_public_beta_current_main_source_only_approval.py", diff --git a/.github/scripts/test_milestone_e_prep_scope.py b/.github/scripts/test_milestone_e_prep_scope.py index f4807792..6a397007 100644 --- a/.github/scripts/test_milestone_e_prep_scope.py +++ b/.github/scripts/test_milestone_e_prep_scope.py @@ -415,6 +415,7 @@ def test_make_target_is_narrow_and_guarded(self) -> None: "$(PYTHON) .github/scripts/test_milestone_e_package_publication_approval_decision_record.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py", "$(PYTHON) .github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py", + "$(PYTHON) .github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py", "$(PYTHON) .github/scripts/test_milestone_e_public_facing_readiness_ledger.py", "$(PYTHON) .github/scripts/test_milestone_e_public_beta_current_main_refresh_prep.py", "$(PYTHON) .github/scripts/test_milestone_e_public_beta_current_main_source_only_approval.py", diff --git a/.github/scripts/test_milestone_e_validation_record_index.py b/.github/scripts/test_milestone_e_validation_record_index.py index 01d23f48..0d3d7c5b 100644 --- a/.github/scripts/test_milestone_e_validation_record_index.py +++ b/.github/scripts/test_milestone_e_validation_record_index.py @@ -298,6 +298,10 @@ class RecordCoverage: "milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md", "test_milestone_e_package_publication_approval_decision_refresh.py", ), + RecordCoverage( + "milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md", + "test_milestone_e_package_publication_manifest_activation_applied.py", + ), RecordCoverage( "milestone-e-public-facing-readiness-ledger-validation-2026-06-21.md", "test_milestone_e_public_facing_readiness_ledger.py", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0dc5234..15e9625a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -246,6 +246,8 @@ jobs: run: python3 .github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py - name: Milestone E package publication approval decision refresh tests run: python3 .github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py + - name: Milestone E package publication manifest activation applied tests + run: python3 .github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py - name: Milestone E public-facing readiness ledger tests run: python3 .github/scripts/test_milestone_e_public_facing_readiness_ledger.py - name: Milestone E public beta current-main refresh prep tests @@ -299,8 +301,8 @@ jobs: - name: grounding feature really is minimal run: | # the trait module must build without serde_json/sha2/thiserror - cargo check --locked -p ethos-core --no-default-features --features grounding - cargo check --locked -p ethos-core --no-default-features --features verify-types + cargo check --locked -p ethos-doc-core --no-default-features --features grounding + cargo check --locked -p ethos-doc-core --no-default-features --features verify-types schema-validate: runs-on: ubuntu-latest diff --git a/.github/workflows/determinism.yml b/.github/workflows/determinism.yml index 63726efd..30c13bef 100644 --- a/.github/workflows/determinism.yml +++ b/.github/workflows/determinism.yml @@ -31,7 +31,7 @@ jobs: # asserting the same pinned hashes IS cross-platform byte equality for the # serialization layer. Corpus-level fingerprint comparison joins when the engine # parses the frozen manifest (WS-ENGINE + WS-HARNESS). - - run: cargo test --locked -p ethos-core --all-features + - run: cargo test --locked -p ethos-doc-core --all-features - name: full-corpus fingerprint equality shell: bash run: | diff --git a/Cargo.lock b/Cargo.lock index 2f9862c0..00692d45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,7 +196,7 @@ name = "ethos-cli" version = "0.1.0" dependencies = [ "clap", - "ethos-core", + "ethos-doc-core", "ethos-grounding-opendataloader-json", "ethos-layout", "ethos-pdf", @@ -209,7 +209,7 @@ dependencies = [ ] [[package]] -name = "ethos-core" +name = "ethos-doc-core" version = "0.1.0" dependencies = [ "proptest", @@ -223,7 +223,7 @@ dependencies = [ name = "ethos-grounding-opendataloader-json" version = "0.1.0" dependencies = [ - "ethos-core", + "ethos-doc-core", "serde", "serde_json", ] @@ -232,14 +232,14 @@ dependencies = [ name = "ethos-layout" version = "0.1.0" dependencies = [ - "ethos-core", + "ethos-doc-core", ] [[package]] name = "ethos-pdf" version = "0.1.0" dependencies = [ - "ethos-core", + "ethos-doc-core", "serde", "serde_json", ] @@ -248,14 +248,14 @@ dependencies = [ name = "ethos-tables" version = "0.1.0" dependencies = [ - "ethos-core", + "ethos-doc-core", ] [[package]] name = "ethos-verify" version = "0.1.0" dependencies = [ - "ethos-core", + "ethos-doc-core", "serde", "serde_json", ] diff --git a/Cargo.toml b/Cargo.toml index 9b32f559..4897b8f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ tempfile = "3" proptest = "1" # internal -ethos-core = { path = "crates/ethos-core", version = "0.1.0", default-features = false } +ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.0", default-features = false } ethos-layout = { path = "crates/ethos-layout", version = "0.1.0" } ethos-tables = { path = "crates/ethos-tables", version = "0.1.0" } diff --git a/Makefile b/Makefile index e7fcbba7..c093de91 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ milestone-d-claim-kind-boundary-contract: git diff --check milestone-d-grounding-source-contract: - cargo test --locked -p ethos-core grounding + cargo test --locked -p ethos-doc-core grounding cargo test --locked -p ethos-cli --test verify native_ethos_verify_produces_non_empty_checks cargo test --locked -p ethos-cli --test verify opendataloader_verify_adapter_produces_capability_aware_report $(PYTHON) schemas/validate_examples.py @@ -80,7 +80,7 @@ milestone-d-grounding-source-contract: git diff --check milestone-d-crop-element-contract: - cargo test --locked -p ethos-core crop_element + cargo test --locked -p ethos-doc-core crop_element cargo test --locked -p ethos-cli --test verify native_verify_crop_dir_writes_deterministic_crop_descriptors cargo test --locked -p ethos-cli --test verify crop_element_cli $(PYTHON) schemas/validate_examples.py @@ -230,6 +230,7 @@ milestone-e-prep: $(PYTHON) .github/scripts/test_milestone_e_package_publication_approval_decision_record.py $(PYTHON) .github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py $(PYTHON) .github/scripts/test_milestone_e_package_publication_approval_decision_refresh.py + $(PYTHON) .github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py $(PYTHON) .github/scripts/test_milestone_e_public_facing_readiness_ledger.py $(PYTHON) .github/scripts/test_milestone_e_public_beta_current_main_refresh_prep.py $(PYTHON) .github/scripts/test_milestone_e_public_beta_current_main_source_only_approval.py @@ -246,8 +247,8 @@ milestone-e-prep: git diff --check package-publication-dry-run-smoke: - cargo package --locked --offline -p ethos-core --allow-dirty --no-verify - cargo package --list --locked --offline -p ethos-core --allow-dirty + cargo package --locked --offline -p ethos-doc-core --allow-dirty --no-verify + cargo package --list --locked --offline -p ethos-doc-core --allow-dirty cargo check --locked --offline -p ethos-verify cargo check --locked --offline -p ethos-pdf $(PYTHON) .github/scripts/test_milestone_e_package_publication_dry_run_smoke.py diff --git a/crates/ethos-core/Cargo.toml b/crates/ethos-core/Cargo.toml index 638d2338..f04ffb6b 100644 --- a/crates/ethos-core/Cargo.toml +++ b/crates/ethos-core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ethos-core" +name = "ethos-doc-core" publish = false description = "Ethos canonical document model, IDs, errors, schema types, traits, c14n and fingerprints" readme = "README.md" @@ -17,6 +17,9 @@ license.workspace = true repository.workspace = true authors.workspace = true +[lib] +name = "ethos_core" + [package.metadata.ethos_publication] reserved_crates_io_name = "ethos-doc-core" reserved_crates_io_version = "0.0.0-reserved.0" diff --git a/crates/ethos-core/README.md b/crates/ethos-core/README.md index 5a794757..698770f0 100644 --- a/crates/ethos-core/README.md +++ b/crates/ethos-core/README.md @@ -1,12 +1,12 @@ -# ethos-core +# ethos-doc-core -`ethos-core` is the in-tree Rust crate for Ethos document evidence contracts: canonical document +`ethos-doc-core` is the in-tree Rust package for Ethos document evidence contracts: canonical document types, deterministic serialization identifiers, fingerprints, stable codes, schema types, crop descriptor support, and trait boundaries. ADR-0006 reserves the public crates.io identifier `ethos-doc-core` at -`0.0.0-reserved.0`. The in-tree crate name remains `ethos-core` until a later reviewed publishing -migration. +`0.0.0-reserved.0`. The Rust library name remains `ethos_core` so existing source imports keep the +same crate path while package-publication approval remains blocked. ## Publication Boundary @@ -21,4 +21,4 @@ migration. - License: Apache-2.0 through workspace metadata. - Notice: see `NOTICE.md` in this crate and the repository root `NOTICE`. - Source repository: `https://github.com/docushell/ethos`. -- Public package name for future review: `ethos-doc-core`. +- Rust library name: `ethos_core`. diff --git a/docs/architecture.md b/docs/architecture.md index a9fae046..fbbb4c30 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -77,13 +77,14 @@ canonical graph + versioned config; Markdown is secondary. ## Crate map (Release 1) -Public crates.io package identity is governed by ADR-0006. The internal `ethos-core` -crate maps to the planned public package name `ethos-doc-core`; code may keep the -internal crate name until the publishing migration. +Public crates.io package identity is governed by ADR-0006. The source package under +`crates/ethos-core` is named `ethos-doc-core`, while its Rust library name remains +`ethos_core`; the workspace dependency key may remain `ethos-core` for source-tree +dependency wiring. Package publication and public installation remain blocked. | Crate | Milestone | Role | | --- | --- | --- | -| `ethos-core` | A | canonical model, IDs, errors/warnings, schema types, traits, c14n + fingerprint, page-range config | +| `ethos-doc-core` package / `ethos_core` library | A | canonical model, IDs, errors/warnings, schema types, traits, c14n + fingerprint, page-range config | | `ethos-pdf` | A | PDFium behind `EthosPdfBackend`; quantize-at-extraction lives here; font-mapper override (ADR-0003) | | `ethos-verify` | B alpha, D v1 | parser-agnostic verification via `GroundingSource` only | | `adapters/grounding/opendataloader-json` | A stub, B alpha, D v1 | first foreign-parser adapter; LiteParse/Docling candidates later | diff --git a/docs/execution-status.md b/docs/execution-status.md index f8472fab..06045d67 100644 --- a/docs/execution-status.md +++ b/docs/execution-status.md @@ -215,6 +215,8 @@ The package publication candidate activation evidence in `docs/validation/milest The package publication approval decision refresh in `docs/validation/milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md` records that activation evidence is present against source commit `6a91511` / tree `8b150d9aebdc282c358e4552a4d709c3140f41b4`. Manual exact approval remains required; source Cargo manifests remain unchanged, package publication remains blocked, and public installation remains blocked. +The package publication manifest activation applied record in `docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md` records the source package name `ethos-doc-core`, Rust library name `ethos_core`, and workspace dependency activation for review only. `publish = false`, package publication, and public installation remain blocked. + | Work item | Current status | Remaining blocker | | --- | --- | --- | | PDFium Phase 1 profile | Landed: pinned profile, V8/XFA-disabled state, platform hashes, runtime library hashes, and provenance are recorded | Phase 2 project-maintained builds still block Public Beta | diff --git a/docs/milestone-d-crop-element-contract.md b/docs/milestone-d-crop-element-contract.md index 7b20587c..9f318607 100644 --- a/docs/milestone-d-crop-element-contract.md +++ b/docs/milestone-d-crop-element-contract.md @@ -39,7 +39,7 @@ The current source-tree fixture for this contract boundary is Focused validation command: -- `cargo test --locked -p ethos-core crop_element` +- `cargo test --locked -p ethos-doc-core crop_element` - `cargo test --locked -p ethos-cli --test verify crop_element_cli` - `make milestone-d-crop-element-contract PYTHON=/bin/python` diff --git a/docs/milestone-e-package-publication-approval-prep.json b/docs/milestone-e-package-publication-approval-prep.json index c460b027..37b697d6 100644 --- a/docs/milestone-e-package-publication-approval-prep.json +++ b/docs/milestone-e-package-publication-approval-prep.json @@ -28,7 +28,7 @@ "ethos-pdf" ], "in_tree_reconciliation": [ - "ethos-doc-core maps to the in-tree ethos-core crate before any future publish prep can advance", + "ethos-doc-core maps to crates/ethos-core with the source package name activated and Rust library name retained as ethos_core", "ethos-doc has no in-tree workspace member yet and remains a reserved placeholder until a package owner, README, and metadata are prepared", "ethos-verify maps to crates/ethos-verify and currently remains publish=false", "ethos-rag has no in-tree workspace member yet and remains a reserved placeholder until a package owner, README, and metadata are prepared", @@ -52,7 +52,7 @@ "evidence_review_status": { "package_inventory": "evidence recorded; ADR-0006 reserved names and current workspace mapping are reconciled for prep, while publication remains blocked", "package_metadata_license_readme_review": "metadata/readiness follow-up recorded for in-tree priority candidates; ethos-doc and ethos-rag remain reserved placeholders without in-tree manifests, and publication remains blocked", - "install_build_smoke_path": "local source-tree smoke, dependency-ordering follow-up recorded, manifest-migration prep recorded, manifest-activation prep recorded, registry-assembly prep recorded, and registry-assembly activation prep recorded; ethos-core package assembly passes offline, ethos-verify and ethos-pdf source checks pass offline, current source-tree manifests remain unchanged, and publication remains blocked", + "install_build_smoke_path": "local source-tree smoke, dependency-ordering follow-up recorded, manifest-migration prep recorded, manifest-activation prep recorded, registry-assembly prep recorded, registry-assembly activation prep recorded, candidate activation evidence recorded, and manifest activation applied for source review; ethos-doc-core package assembly passes offline, ethos-verify and ethos-pdf source checks pass offline, publish flags remain false, and publication remains blocked", "version_tag_policy": "version/tag policy follow-up, real-version-selection prep recorded, and package tag-creation prep recorded; workspace 0.1.0 remains source-tree only, reserved 0.0.0-reserved.0 names remain placeholders, no package publication version is selected, no package tag is created, and real-version publication remains blocked", "pdfium_packaging_boundary": "PDFium boundary follow-up recorded for current source-tree ethos-pdf; no bundled PDFium binary, caller-provided ETHOS_PDFIUM_LIBRARY_PATH, and no raw PDFium types across public schemas/APIs are confirmed while publication remains blocked", "public_surface_posture_check": "run after exact wording changes by the package evidence guard path", @@ -88,7 +88,8 @@ "package_approval_decision_template": "docs/validation/milestone-e-package-publication-approval-decision-template-validation-2026-06-21.md", "package_approval_decision_record": "docs/validation/milestone-e-package-publication-approval-decision-validation-2026-06-21.md", "package_candidate_activation_evidence": "docs/validation/milestone-e-package-publication-candidate-activation-evidence-validation-2026-06-22.md", - "package_approval_decision_refresh": "docs/validation/milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md" + "package_approval_decision_refresh": "docs/validation/milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md", + "package_manifest_activation_applied": "docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md" }, "publication_approval_decision_inputs": { "decision_status": "not_approved_pending_exact_decision", @@ -125,9 +126,9 @@ "candidate_crate_surface_review": { "review_state": "candidate_surface_review_recorded_publication_blocked", "included_candidate_crates": [ - "ethos-doc-core from crates/ethos-core; current manifest name ethos-core; publish=false; package-name migration remains pending", - "ethos-verify from crates/ethos-verify; current manifest name ethos-verify; publish=false; dependency manifest activation remains pending", - "ethos-pdf from crates/ethos-pdf; current manifest name ethos-pdf; publish=false; dependency manifest activation and PDFium boundary confirmation must remain current" + "ethos-doc-core from crates/ethos-core; source manifest name ethos-doc-core; lib.name ethos_core; publish=false", + "ethos-verify from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core; publish=false", + "ethos-pdf from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core; PDFium boundary remains current; publish=false" ], "excluded_reserved_crates": [ "ethos-doc remains excluded because no in-tree workspace member or package manifest exists", @@ -145,7 +146,7 @@ "candidate surface review does not approve package publication", "candidate surface review does not select a package publication version", "candidate surface review does not create a package tag", - "candidate surface review does not change Cargo manifests", + "candidate surface review does not approve removing publish=false", "candidate surface review does not approve public installation", "candidate surface review does not approve registry-backed dependent package assembly activation" ] @@ -178,7 +179,7 @@ "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", + "package dependency manifest activation inputs are recorded and source activation is applied for review while publish flags remain false", "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" ], @@ -195,8 +196,8 @@ "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 remove publish=false", + "this bundle does not approve package dependency manifest activation for publication", "this bundle does not create a registry", "this bundle does not activate registry-backed dependent package assembly", "this bundle does not invite public installation", @@ -214,9 +215,9 @@ "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" + "ethos-doc-core mapped from crates/ethos-core; source package-name activation is applied for review while publish=false remains", + "ethos-verify mapped from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core while publish=false remains", + "ethos-pdf mapped from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core, PDFium boundary remains current, and publish=false remains" ], "package_version_map": [ "ethos-doc-core has no selected package publication version", @@ -226,7 +227,7 @@ "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", + "manifest_activation_diff": "applied for source review only; Cargo manifests keep publish=false and package publication remains blocked", "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": [ @@ -253,8 +254,8 @@ "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 remove publish=false", + "this packet does not approve package dependency manifest activation for publication", "this packet does not create a registry", "this packet does not activate registry-backed dependent package assembly", "this packet does not invite public installation", @@ -277,9 +278,9 @@ "candidate_source_tree": "5a197bee718e3b31399563340169e9efd4f1317c" }, "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" + "ethos-doc-core mapped from crates/ethos-core; source package-name activation is applied for review while publish=false remains", + "ethos-verify mapped from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core while publish=false remains", + "ethos-pdf mapped from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core, PDFium boundary remains current, and publish=false remains" ], "candidate_version_map": [ "ethos-doc-core candidate package version for later approval: 0.1.0; not selected or approved", @@ -292,9 +293,9 @@ "ethos-pdf candidate package tag for later approval: ethos-package-ethos-pdf-0.1.0; tag is not created" ], "candidate_manifest_activation_diff": [ - "crates/ethos-core/Cargo.toml candidate package-name migration: package.name ethos-core -> ethos-doc-core; current manifest remains unchanged", - "crates/ethos-verify/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", - "crates/ethos-pdf/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "crates/ethos-core/Cargo.toml source package-name activation: package.name ethos-doc-core with lib.name ethos_core; publish=false remains", + "Cargo.toml source workspace dependency activation: ethos-core dependency key points at package ethos-doc-core for ethos-verify and ethos-pdf; publish=false remains", + "Cargo.lock source activation: dependency graph resolves ethos-doc-core while source imports retain ethos_core", "included candidate crates require later publish-flag activation only after dedicated approval; current manifests remain publish=false" ], "registry_backed_assembly_input": "registry-backed dependent package assembly evidence remains required after manifest activation; no registry is created and no assembly is activated", @@ -323,8 +324,8 @@ "non_approvals": [ "this exact decision input packet does not select a package publication version", "this exact decision input packet does not create a package tag", - "this exact decision input packet does not change Cargo manifests", - "this exact decision input packet does not activate package dependency manifests", + "this exact decision input packet does not remove publish=false", + "this exact decision input packet does not approve package dependency manifest activation for publication", "this exact decision input packet does not create a registry", "this exact decision input packet does not activate registry-backed dependent package assembly", "this exact decision input packet does not invite public installation", @@ -333,7 +334,7 @@ "retained_blockers": [ "candidate package version map is recorded but no package publication version is selected", "candidate package tag names are recorded but no package tag is created", - "candidate manifest activation diff is recorded but no Cargo manifest is changed", + "candidate manifest activation is applied for source review but no publication action is approved", "registry-backed dependent package assembly evidence remains required", "public installation remains blocked", "package publication remains blocked", @@ -346,7 +347,7 @@ "version map gap: no package publication version is selected; requires exact SemVer package version or per-crate version map", "tag name gap: no package tag is created; requires exact package tag name", "tag binding gap: no package_tag_source_commit or source tree is selected; requires exact source commit and tree binding", - "manifest activation gap: current Cargo manifests remain unchanged; requires exact package-name migration and dependency activation diff", + "manifest approval gap: source manifest activation is applied for review; requires exact approval before publish flags, tags, public installation, or publication can advance", "registry assembly gap: no registry-backed dependent package assembly is activated; requires exact non-public assembly evidence", "public installation wording gap: no public installation wording is approved; requires exact wording and exclusions", "posture and claims gate gap: gates must rerun after exact public installation wording changes" @@ -354,8 +355,8 @@ "blocked_actions": [ "selecting a package publication version remains blocked", "creating a package tag remains blocked", - "changing Cargo manifests remains blocked", - "activating package dependency manifests remains blocked", + "removing publish=false remains blocked", + "approving package dependency manifest activation for publication remains blocked", "creating a registry remains blocked", "activating registry-backed dependent package assembly remains blocked", "inviting public installation remains blocked", @@ -376,8 +377,8 @@ "non_approvals": [ "this ledger does not select a package publication version", "this ledger does not create a package tag", - "this ledger does not change Cargo manifests", - "this ledger does not activate package dependency manifests", + "this ledger does not remove publish=false", + "this ledger does not approve package dependency manifest activation for publication", "this ledger does not create a registry", "this ledger does not activate registry-backed dependent package assembly", "this ledger does not invite public installation", diff --git a/docs/milestone-e-prep-scope.md b/docs/milestone-e-prep-scope.md index 5170140c..465f8332 100644 --- a/docs/milestone-e-prep-scope.md +++ b/docs/milestone-e-prep-scope.md @@ -159,6 +159,11 @@ It records that activation evidence is present for source commit `6a91511` / tre `8b150d9aebdc282c358e4552a4d709c3140f41b4`, while manual exact approval remains required, source Cargo manifests remain unchanged, package publication remains blocked, and public installation remains blocked. +The package publication manifest activation applied follow-up is recorded in +`docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md`. +It records the source package name `ethos-doc-core`, Rust library name `ethos_core`, and workspace +dependency activation for review only; `publish = false`, public installation, and package +publication remain blocked. The metadata-readiness follow-up record under `docs/validation/` covers README, NOTICE, manifest metadata, and include-list readiness for `ethos-core`, `ethos-verify`, and `ethos-pdf` only. `ethos-doc` and `ethos-rag` remain reserved placeholders without in-tree package manifests, and @@ -347,6 +352,9 @@ or broad demo-generation workflows. - The package publication approval decision refresh records that activation evidence is present; manual exact approval remains required, source Cargo manifests remain unchanged, public installation remains blocked, and package publication remains blocked. +- The package publication manifest activation applied follow-up records the source package name + `ethos-doc-core`, Rust library name `ethos_core`, and workspace dependency activation for review + only; `publish = false`, public installation, and package publication remain blocked. - The public-facing readiness ledger records the current-main source-only public beta source binding and package-publication gap retention; it does not approve package publication, approve public installation, or soften any current diff --git a/docs/milestone-e-public-facing-readiness-ledger.json b/docs/milestone-e-public-facing-readiness-ledger.json index 7f0f3e68..0acd9936 100644 --- a/docs/milestone-e-public-facing-readiness-ledger.json +++ b/docs/milestone-e-public-facing-readiness-ledger.json @@ -75,8 +75,8 @@ "this ledger does not approve public installation", "this ledger does not select a package publication version", "this ledger does not create a package tag", - "this ledger does not change Cargo manifests", - "this ledger does not activate package dependency manifests", + "this ledger does not remove publish=false", + "this ledger does not approve package dependency manifest activation for publication", "this ledger does not create a registry", "this ledger does not approve hosted surfaces", "this ledger does not approve production positioning", diff --git a/docs/roadmap.md b/docs/roadmap.md index ecb1f252..85844480 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -129,6 +129,11 @@ The manifest-activation prep follow-up records future package dependency manifes while current Cargo manifests remain unchanged; package dependency manifest activation, registry-backed dependent package assembly activation, public installation, and package publication remain blocked. +The manifest activation applied follow-up is recorded in +[`docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md`](validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md) +and records the source package name `ethos-doc-core`, Rust library name `ethos_core`, and workspace +dependency activation for review only; `publish = false`, public installation, and package +publication remain blocked. The registry-assembly prep follow-up records future non-public dependent candidate assembly rehearsal while no registry is created and current Cargo manifests remain unchanged; registry-backed dependent package assembly activation, package dependency manifest activation, diff --git a/docs/validation/README.md b/docs/validation/README.md index de15301d..dcde62a6 100644 --- a/docs/validation/README.md +++ b/docs/validation/README.md @@ -381,6 +381,10 @@ recording the exact current-main source candidate and required follow-up evidenc present; the record binds the refresh to source commit `6a91511` / tree `8b150d9aebdc282c358e4552a4d709c3140f41b4`, records that manual exact approval remains required, and keeps package publication and public installation blocked. +- `milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md` - + package publication manifest activation applied validation for the source package name + `ethos-doc-core`, Rust library name `ethos_core`, workspace dependency activation, and retained + `publish = false` blockers; package publication and public installation remain blocked. - `milestone-e-public-facing-readiness-ledger-validation-2026-06-21.md` - public-facing readiness ledger validation recorded `docs/milestone-e-public-facing-readiness-ledger.json` as a current-main refresh candidate and package-publication gap-retention artifact; current main diff --git a/docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md b/docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md new file mode 100644 index 00000000..aa858c93 --- /dev/null +++ b/docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md @@ -0,0 +1,102 @@ +# Milestone E Package Publication Manifest Activation Applied Validation - 2026-06-22 + +## Purpose + +Record that the package-publication candidate manifest activation has been applied to source for +review while retaining the package-publication blockers. + +This record does not approve package publication, public installation, public installation wording, +package tag creation, removing `publish = false`, or real-version cargo publish. + +## Status + +Status: **pass for source manifest activation applied with publication blocked**. + +Decision: source manifest activation is applied for review only; manual exact approval remains +required before any publication action. + +Ethos remains source-only pre-alpha outside the approved GitHub source-repository public beta +surface. Package publication remains blocked. Public installation remains blocked. + +## Subject + +- Repository: `docushell/ethos` +- Validated source HEAD before this record: `e517d76` +- Manifest activation source commit before this record: + `e517d76c7c5f34984f62181769809637e7123bbc` +- Manifest activation source tree before this record: + `b0cdeca1387f2080a1f9dca4f075e3a4bd7a92ec` +- Lane: package publication +- Prior approval decision refresh record: + `docs/validation/milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md` +- Candidate activation evidence record: + `docs/validation/milestone-e-package-publication-candidate-activation-evidence-validation-2026-06-22.md` +- Approval owner: `docushell-admin` + +## Activation Applied + +- Root workspace dependency key remains `ethos-core`, with `package = "ethos-doc-core"` and + path `crates/ethos-core`. +- `crates/ethos-core/Cargo.toml` uses package name `ethos-doc-core`. +- `crates/ethos-core/Cargo.toml` sets `[lib] name = "ethos_core"` so Rust imports remain + `ethos_core`. +- `crates/ethos-verify/Cargo.toml` keeps the workspace dependency key `ethos-core` with + `grounding` and `verify-types`. +- `crates/ethos-pdf/Cargo.toml` keeps the workspace dependency key `ethos-core` with `full`. +- `Cargo.lock` resolves the source package as `ethos-doc-core`. + +## Blockers Retained + +- `publish = false` remains in `ethos-doc-core`, `ethos-verify`, and `ethos-pdf`. +- `publication_status = "blocked"` remains in the candidate crate metadata. +- No package publication version is selected. +- No package tag is created. +- No source-tree package registry is created. +- Public installation wording remains blocked. +- Public installation remains blocked. +- Package publication remains blocked. +- Real-version cargo publish remains blocked. +- Hosted surfaces remain blocked. +- Production positioning remains blocked. +- Public reports remain blocked. +- Public result wording remains blocked. + +## Required Before Later Approval + +Before any later package-publication approval can be recorded, `docushell-admin` must manually +approve or reject: + +- exact candidate crate list for the first package-publication surface +- exact package version map +- exact package tag names and source binding +- exact registry-equivalent dependent package assembly evidence after this source activation +- exact public installation wording and explicit exclusions +- posture, claims, and Milestone E prep gate results after the exact wording and approval record +- whether any `publish = false` change is approved + +## Commands + +```sh +python3 .github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py +python3 .github/scripts/test_milestone_e_package_publication_candidate_activation_evidence.py +python3 .github/scripts/test_milestone_e_package_publication_approval_prep.py +python3 .github/scripts/test_public_surface_posture.py +python3 .github/scripts/claims_gate.py +cargo build --locked -p ethos-cli +make package-publication-dry-run-smoke PYTHON= +make milestone-e-prep PYTHON=/bin/python +git diff --check +``` + +## Result + +```text +Source manifest activation applied for review +ethos-doc-core package name and ethos_core library name confirmed +ethos-verify and ethos-pdf dependency keys remain workspace-scoped +publish=false and publication_status=blocked retained +Package publication and public installation remained blocked +Public-surface posture and claims gates passed +Milestone E prep target passed +git diff --check passed +``` 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 7dfd98b2..c7f0632c 100644 --- a/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json +++ b/schemas/ethos-milestone-e-package-publication-approval-prep.schema.json @@ -225,7 +225,7 @@ "const": "metadata/readiness follow-up recorded for in-tree priority candidates; ethos-doc and ethos-rag remain reserved placeholders without in-tree manifests, and publication remains blocked" }, "install_build_smoke_path": { - "const": "local source-tree smoke, dependency-ordering follow-up recorded, manifest-migration prep recorded, manifest-activation prep recorded, registry-assembly prep recorded, and registry-assembly activation prep recorded; ethos-core package assembly passes offline, ethos-verify and ethos-pdf source checks pass offline, current source-tree manifests remain unchanged, and publication remains blocked" + "const": "local source-tree smoke, dependency-ordering follow-up recorded, manifest-migration prep recorded, manifest-activation prep recorded, registry-assembly prep recorded, registry-assembly activation prep recorded, candidate activation evidence recorded, and manifest activation applied for source review; ethos-doc-core package assembly passes offline, ethos-verify and ethos-pdf source checks pass offline, publish flags remain false, and publication remains blocked" }, "version_tag_policy": { "const": "version/tag policy follow-up, real-version-selection prep recorded, and package tag-creation prep recorded; workspace 0.1.0 remains source-tree only, reserved 0.0.0-reserved.0 names remain placeholders, no package publication version is selected, no package tag is created, and real-version publication remains blocked" @@ -296,7 +296,8 @@ "package_approval_decision_template", "package_approval_decision_record", "package_candidate_activation_evidence", - "package_approval_decision_refresh" + "package_approval_decision_refresh", + "package_manifest_activation_applied" ], "additionalProperties": false, "properties": { @@ -365,6 +366,9 @@ }, "package_approval_decision_refresh": { "const": "docs/validation/milestone-e-package-publication-approval-decision-refresh-validation-2026-06-22.md" + }, + "package_manifest_activation_applied": { + "const": "docs/validation/milestone-e-package-publication-manifest-activation-applied-validation-2026-06-22.md" } } }, @@ -570,7 +574,7 @@ "const": "not selected; package source tree binding remains blocked" }, "manifest_activation_diff": { - "const": "not prepared; current Cargo manifests remain unchanged" + "const": "applied for source review only; Cargo manifests keep publish=false and package publication remains blocked" }, "registry_assembly_evidence": { "const": "not activated; registry-backed dependent package assembly remains blocked" @@ -805,9 +809,9 @@ }, "candidate_included_crate": { "enum": [ - "ethos-doc-core from crates/ethos-core; current manifest name ethos-core; publish=false; package-name migration remains pending", - "ethos-verify from crates/ethos-verify; current manifest name ethos-verify; publish=false; dependency manifest activation remains pending", - "ethos-pdf from crates/ethos-pdf; current manifest name ethos-pdf; publish=false; dependency manifest activation and PDFium boundary confirmation must remain current" + "ethos-doc-core from crates/ethos-core; source manifest name ethos-doc-core; lib.name ethos_core; publish=false", + "ethos-verify from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core; publish=false", + "ethos-pdf from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core; PDFium boundary remains current; publish=false" ] }, "candidate_excluded_crate": { @@ -831,7 +835,7 @@ "candidate surface review does not approve package publication", "candidate surface review does not select a package publication version", "candidate surface review does not create a package tag", - "candidate surface review does not change Cargo manifests", + "candidate surface review does not approve removing publish=false", "candidate surface review does not approve public installation", "candidate surface review does not approve registry-backed dependent package assembly activation" ] @@ -866,7 +870,7 @@ "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", + "package dependency manifest activation inputs are recorded and source activation is applied for review while publish flags remain false", "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" ] @@ -887,8 +891,8 @@ "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 remove publish=false", + "this bundle does not approve package dependency manifest activation for publication", "this bundle does not create a registry", "this bundle does not activate registry-backed dependent package assembly", "this bundle does not invite public installation", @@ -907,9 +911,9 @@ }, "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" + "ethos-doc-core mapped from crates/ethos-core; source package-name activation is applied for review while publish=false remains", + "ethos-verify mapped from crates/ethos-verify; source workspace dependency resolves through ethos-doc-core while publish=false remains", + "ethos-pdf mapped from crates/ethos-pdf; source workspace dependency resolves through ethos-doc-core, PDFium boundary remains current, and publish=false remains" ] }, "packet_package_version": { @@ -948,8 +952,8 @@ "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 remove publish=false", + "this packet does not approve package dependency manifest activation for publication", "this packet does not create a registry", "this packet does not activate registry-backed dependent package assembly", "this packet does not invite public installation", @@ -983,9 +987,9 @@ }, "exact_packet_manifest_activation_diff": { "enum": [ - "crates/ethos-core/Cargo.toml candidate package-name migration: package.name ethos-core -> ethos-doc-core; current manifest remains unchanged", - "crates/ethos-verify/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", - "crates/ethos-pdf/Cargo.toml candidate dependency activation: ethos_core package alias points at ethos-doc-core; current manifest remains unchanged", + "crates/ethos-core/Cargo.toml source package-name activation: package.name ethos-doc-core with lib.name ethos_core; publish=false remains", + "Cargo.toml source workspace dependency activation: ethos-core dependency key points at package ethos-doc-core for ethos-verify and ethos-pdf; publish=false remains", + "Cargo.lock source activation: dependency graph resolves ethos-doc-core while source imports retain ethos_core", "included candidate crates require later publish-flag activation only after dedicated approval; current manifests remain publish=false" ] }, @@ -1005,8 +1009,8 @@ "enum": [ "this exact decision input packet does not select a package publication version", "this exact decision input packet does not create a package tag", - "this exact decision input packet does not change Cargo manifests", - "this exact decision input packet does not activate package dependency manifests", + "this exact decision input packet does not remove publish=false", + "this exact decision input packet does not approve package dependency manifest activation for publication", "this exact decision input packet does not create a registry", "this exact decision input packet does not activate registry-backed dependent package assembly", "this exact decision input packet does not invite public installation", @@ -1017,7 +1021,7 @@ "enum": [ "candidate package version map is recorded but no package publication version is selected", "candidate package tag names are recorded but no package tag is created", - "candidate manifest activation diff is recorded but no Cargo manifest is changed", + "candidate manifest activation is applied for source review but no publication action is approved", "registry-backed dependent package assembly evidence remains required", "public installation remains blocked", "package publication remains blocked", @@ -1029,7 +1033,7 @@ "version map gap: no package publication version is selected; requires exact SemVer package version or per-crate version map", "tag name gap: no package tag is created; requires exact package tag name", "tag binding gap: no package_tag_source_commit or source tree is selected; requires exact source commit and tree binding", - "manifest activation gap: current Cargo manifests remain unchanged; requires exact package-name migration and dependency activation diff", + "manifest approval gap: source manifest activation is applied for review; requires exact approval before publish flags, tags, public installation, or publication can advance", "registry assembly gap: no registry-backed dependent package assembly is activated; requires exact non-public assembly evidence", "public installation wording gap: no public installation wording is approved; requires exact wording and exclusions", "posture and claims gate gap: gates must rerun after exact public installation wording changes" @@ -1039,8 +1043,8 @@ "enum": [ "selecting a package publication version remains blocked", "creating a package tag remains blocked", - "changing Cargo manifests remains blocked", - "activating package dependency manifests remains blocked", + "removing publish=false remains blocked", + "approving package dependency manifest activation for publication remains blocked", "creating a registry remains blocked", "activating registry-backed dependent package assembly remains blocked", "inviting public installation remains blocked", @@ -1065,8 +1069,8 @@ "enum": [ "this ledger does not select a package publication version", "this ledger does not create a package tag", - "this ledger does not change Cargo manifests", - "this ledger does not activate package dependency manifests", + "this ledger does not remove publish=false", + "this ledger does not approve package dependency manifest activation for publication", "this ledger does not create a registry", "this ledger does not activate registry-backed dependent package assembly", "this ledger does not invite public installation", @@ -1075,7 +1079,7 @@ }, "in_tree_reconciliation": { "enum": [ - "ethos-doc-core maps to the in-tree ethos-core crate before any future publish prep can advance", + "ethos-doc-core maps to crates/ethos-core with the source package name activated and Rust library name retained as ethos_core", "ethos-doc has no in-tree workspace member yet and remains a reserved placeholder until a package owner, README, and metadata are prepared", "ethos-verify maps to crates/ethos-verify and currently remains publish=false", "ethos-rag has no in-tree workspace member yet and remains a reserved placeholder until a package owner, README, and metadata are prepared", diff --git a/schemas/ethos-milestone-e-public-facing-readiness-ledger.schema.json b/schemas/ethos-milestone-e-public-facing-readiness-ledger.schema.json index 22c7fda1..7db98088 100644 --- a/schemas/ethos-milestone-e-public-facing-readiness-ledger.schema.json +++ b/schemas/ethos-milestone-e-public-facing-readiness-ledger.schema.json @@ -204,8 +204,8 @@ "this ledger does not approve public installation", "this ledger does not select a package publication version", "this ledger does not create a package tag", - "this ledger does not change Cargo manifests", - "this ledger does not activate package dependency manifests", + "this ledger does not remove publish=false", + "this ledger does not approve package dependency manifest activation for publication", "this ledger does not create a registry", "this ledger does not approve hosted surfaces", "this ledger does not approve production positioning",