diff --git a/.github/scripts/package_publication_candidate_activation.py b/.github/scripts/package_publication_candidate_activation.py index 2e6136c..69349da 100644 --- a/.github/scripts/package_publication_candidate_activation.py +++ b/.github/scripts/package_publication_candidate_activation.py @@ -29,7 +29,6 @@ ROOT = Path(__file__).resolve().parents[2] -VERSION = "0.1.1" CORE_PACKAGE = "ethos-doc-core" CANDIDATE_PACKAGES = (CORE_PACKAGE, "ethos-verify", "ethos-pdf") CONSUMER_PACKAGE = "ethos-package-candidate-consumer" @@ -50,6 +49,23 @@ } +def current_workspace_version() -> str: + manifest = (ROOT / "Cargo.toml").read_text(encoding="utf-8") + in_workspace_package = False + for line in manifest.splitlines(): + if line == "[workspace.package]": + in_workspace_package = True + continue + if in_workspace_package and line.startswith("["): + break + if in_workspace_package and line.startswith('version = "'): + return line.split('"', 2)[1] + raise RuntimeError("unable to determine workspace package version") + + +VERSION = current_workspace_version() + + def should_ignore(_: str, names: list[str]) -> set[str]: return {name for name in names if name in IGNORE_NAMES} @@ -140,8 +156,8 @@ def materialize_candidate_workspace(workspace: Path) -> None: replace_once_if_needed( workspace / "Cargo.toml", - 'ethos-core = { path = "crates/ethos-core", version = "0.1.1", default-features = false }', - 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.1", default-features = false }', + f'ethos-core = {{ path = "crates/ethos-core", version = "{VERSION}", default-features = false }}', + f'ethos-core = {{ package = "ethos-doc-core", path = "crates/ethos-core", version = "{VERSION}", default-features = false }}', ) root_manifest = workspace / "Cargo.toml" root_text = root_manifest.read_text(encoding="utf-8") @@ -547,7 +563,7 @@ def source_manifests_have_activation_shape() -> bool: lockfile = (ROOT / "Cargo.lock").read_text(encoding="utf-8") return all( [ - 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.1", default-features = false }' + f'ethos-core = {{ package = "ethos-doc-core", path = "crates/ethos-core", version = "{VERSION}", default-features = false }}' in workspace, 'name = "ethos-doc-core"' in core, '[lib]\nname = "ethos_core"' in core, diff --git a/.github/scripts/test_milestone_e_package_publication_activation_applied.py b/.github/scripts/test_milestone_e_package_publication_activation_applied.py index 4e6ec4e..83edc63 100644 --- a/.github/scripts/test_milestone_e_package_publication_activation_applied.py +++ b/.github/scripts/test_milestone_e_package_publication_activation_applied.py @@ -128,7 +128,7 @@ def test_candidate_manifests_are_activated_and_non_candidates_stay_blocked(self) pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") self.assertIn( 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", ' - 'version = "0.1.1", default-features = false }', + 'version = "0.1.2", default-features = false }', workspace, ) self.assertIn('name = "ethos-doc-core"', lockfile) 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 7b83e2c..45fc943 100644 --- a/.github/scripts/test_milestone_e_package_publication_approval_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_approval_prep.py @@ -493,7 +493,7 @@ def test_candidate_crates_remain_publish_false_until_later_approval(self) -> Non self.assertNotIn("publish = false", verify) self.assertIn('name = "ethos-pdf"', pdf) self.assertNotIn("publish = false", pdf) - self.assertIn('version = "0.1.1"', read(ROOT / "Cargo.toml")) + self.assertIn('version = "0.1.2"', read(ROOT / "Cargo.toml")) def test_evidence_status_matches_decider_input(self) -> None: status = load_json(PREP)["evidence_review_status"] @@ -611,7 +611,7 @@ def test_semver_package_version_decision_prep_keeps_version_unselected(self) -> "semver_decision_inputs_recorded_version_unselected_publication_blocked", review["review_state"], ) - self.assertIn('version = "0.1.1"', cargo) + self.assertIn('version = "0.1.2"', cargo) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', core_manifest) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', verify_manifest) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', pdf_manifest) @@ -667,7 +667,7 @@ def test_combined_package_publication_decision_prep_bundle_blocks_all_actions(se 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.1"', cargo) + self.assertIn('version = "0.1.2"', cargo) def test_package_publication_approval_request_packet_keeps_all_actions_blocked(self) -> None: packet = load_json(PREP)["package_publication_approval_request_packet"] @@ -741,7 +741,7 @@ def test_package_publication_pre_approval_gap_ledger_keeps_resolution_inputs_exp 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.1"', cargo) + self.assertIn('version = "0.1.2"', cargo) def test_pdfium_boundary_keeps_ethos_pdf_held_until_confirmed(self) -> None: approved = load_json(PREP)["approved_package_publication_prep"] 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 1cd696e..1fff090 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 @@ -121,7 +121,7 @@ def test_candidate_activation_script_passes_with_registry_equivalent_consumer(se commands = [entry["command"] for entry in result["commands"]] self.assertEqual("pass", result["status"]) - self.assertEqual("0.1.1", result["candidate_version"]) + self.assertEqual("0.1.2", result["candidate_version"]) self.assertEqual(["ethos-doc-core", "ethos-verify", "ethos-pdf"], result["candidate_packages"]) self.assertEqual("pass", result["registry_equivalent_consumer_check"]) self.assertTrue(result["source_candidate_manifests_activated"]) @@ -151,7 +151,7 @@ def test_candidate_activation_preserves_import_and_dependency_shape(self) -> Non self.assertEqual({"ethos-doc-core", "ethos-verify", "ethos-pdf"}, set(artifacts)) for artifact in artifacts.values(): self.assertRegex(artifact["sha256"], r"^[0-9a-f]{64}$") - self.assertTrue(artifact["crate_file"].endswith("-0.1.1.crate")) + self.assertTrue(artifact["crate_file"].endswith("-0.1.2.crate")) def test_source_candidate_manifests_are_activated_and_profile_copy_is_in_sync(self) -> None: core_manifest = read(ROOT / "crates/ethos-core/Cargo.toml") diff --git a/.github/scripts/test_milestone_e_package_publication_current_registry_assembly.py b/.github/scripts/test_milestone_e_package_publication_current_registry_assembly.py index 1a00f2e..2b93fd9 100644 --- a/.github/scripts/test_milestone_e_package_publication_current_registry_assembly.py +++ b/.github/scripts/test_milestone_e_package_publication_current_registry_assembly.py @@ -115,7 +115,7 @@ def test_current_registry_equivalent_assembly_passes_after_manifest_activation(s commands = [entry["command"] for entry in result["commands"]] self.assertEqual("pass", result["status"]) - self.assertEqual("0.1.1", result["candidate_version"]) + self.assertEqual("0.1.2", result["candidate_version"]) self.assertEqual(["ethos-doc-core", "ethos-verify", "ethos-pdf"], result["candidate_packages"]) self.assertEqual("pass", result["registry_equivalent_consumer_check"]) self.assertTrue(result["source_manifest_activation_applied"]) @@ -141,7 +141,7 @@ def test_artifacts_and_manifest_shape_are_current(self) -> None: self.assertEqual({"ethos-doc-core", "ethos-verify", "ethos-pdf"}, set(artifacts)) for artifact in artifacts.values(): self.assertRegex(artifact["sha256"], r"^[0-9a-f]{64}$") - self.assertTrue(artifact["crate_file"].endswith("-0.1.1.crate")) + self.assertTrue(artifact["crate_file"].endswith("-0.1.2.crate")) def test_source_candidate_manifests_are_activated_while_tags_and_registry_stay_absent(self) -> None: for manifest in ( diff --git a/.github/scripts/test_milestone_e_package_publication_evidence_records.py b/.github/scripts/test_milestone_e_package_publication_evidence_records.py index 96eb5ad..ff8fa64 100644 --- a/.github/scripts/test_milestone_e_package_publication_evidence_records.py +++ b/.github/scripts/test_milestone_e_package_publication_evidence_records.py @@ -176,7 +176,7 @@ def test_version_tag_policy_record_keeps_placeholder_and_workspace_versions_sepa record = normalized(record_path(RECORDS["version_tag_policy"])) root_manifest = read(ROOT / "Cargo.toml") - self.assertIn('version = "0.1.1"', root_manifest) + self.assertIn('version = "0.1.2"', root_manifest) self.assertIn("Workspace package version is `0.1.0`", record) self.assertIn("`0.0.0-reserved.0` placeholders", record) self.assertIn("`ethos-source-snapshot-660f268`", record) 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 index 8a31210..50101ca 100644 --- a/.github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py +++ b/.github/scripts/test_milestone_e_package_publication_manifest_activation_applied.py @@ -127,7 +127,7 @@ def test_source_manifests_have_activated_but_blocked_shape(self) -> None: self.assertIn( 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", ' - 'version = "0.1.1", default-features = false }', + 'version = "0.1.2", default-features = false }', workspace, ) self.assertIn('name = "ethos-doc-core"', core) 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 d5ac668..4f5273c 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 @@ -114,7 +114,7 @@ def test_current_manifests_remain_unmigrated_source_tree_manifests(self) -> None self.assertNotIn("publish = false", verify) self.assertNotIn("publish = false", pdf) self.assertIn( - 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.1", default-features = false }', + 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.2", default-features = false }', workspace, ) self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) diff --git a/.github/scripts/test_milestone_e_package_publication_real_version_selection_prep.py b/.github/scripts/test_milestone_e_package_publication_real_version_selection_prep.py index fd6ea01..e092141 100644 --- a/.github/scripts/test_milestone_e_package_publication_real_version_selection_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_real_version_selection_prep.py @@ -106,7 +106,7 @@ def test_current_versions_and_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('version = "0.1.1"', workspace) + self.assertIn('version = "0.1.2"', workspace) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', core) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', verify) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', pdf) 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 3d21c3e..9b21bf1 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 @@ -111,7 +111,7 @@ def test_current_manifests_stay_source_tree_only(self) -> None: self.assertNotIn("publish = false", verify) self.assertNotIn("publish = false", pdf) self.assertIn( - 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.1", default-features = false }', + 'ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.2", default-features = false }', workspace, ) self.assertIn('ethos-core = { workspace = true, features = ["grounding", "verify-types"] }', verify) diff --git a/.github/scripts/test_milestone_e_package_publication_tag_binding_refresh.py b/.github/scripts/test_milestone_e_package_publication_tag_binding_refresh.py index b277f54..58f5c03 100644 --- a/.github/scripts/test_milestone_e_package_publication_tag_binding_refresh.py +++ b/.github/scripts/test_milestone_e_package_publication_tag_binding_refresh.py @@ -138,7 +138,7 @@ def test_binding_points_at_activated_candidate_manifest_state(self) -> None: ) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', text, str(manifest)) - self.assertIn('version = "0.1.1"', read(ROOT / "Cargo.toml")) + self.assertIn('version = "0.1.2"', read(ROOT / "Cargo.toml")) for manifest in ( ROOT / "crates/ethos-cli/Cargo.toml", diff --git a/.github/scripts/test_milestone_e_package_publication_tag_creation_prep.py b/.github/scripts/test_milestone_e_package_publication_tag_creation_prep.py index 78d5647..973da13 100644 --- a/.github/scripts/test_milestone_e_package_publication_tag_creation_prep.py +++ b/.github/scripts/test_milestone_e_package_publication_tag_creation_prep.py @@ -105,7 +105,7 @@ def test_current_manifests_and_versions_stay_unchanged(self) -> None: verify = read(ROOT / "crates/ethos-verify/Cargo.toml") pdf = read(ROOT / "crates/ethos-pdf/Cargo.toml") - self.assertIn('version = "0.1.1"', workspace) + self.assertIn('version = "0.1.2"', workspace) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', core) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', verify) self.assertIn('reserved_crates_io_version = "0.0.0-reserved.0"', pdf) diff --git a/.github/scripts/test_milestone_e_package_publication_version_tag_policy.py b/.github/scripts/test_milestone_e_package_publication_version_tag_policy.py index 12fdf1e..29536de 100644 --- a/.github/scripts/test_milestone_e_package_publication_version_tag_policy.py +++ b/.github/scripts/test_milestone_e_package_publication_version_tag_policy.py @@ -101,7 +101,7 @@ def test_workspace_and_reserved_versions_stay_separate(self) -> None: adr = normalized(ROOT / "docs/decisions/ADR-0006-package-identifiers.md") record = normalized(RECORD) - self.assertIn('version = "0.1.1"', root_manifest) + self.assertIn('version = "0.1.2"', root_manifest) self.assertIn("0.0.0-reserved.0", adr) self.assertIn("Workspace package version `0.1.0` remains a source-tree version", record) self.assertIn("ADR-0006 crates.io reservations remain `0.0.0-reserved.0` placeholders", record) diff --git a/.github/scripts/test_patch_0_1_1_python_publication_approval_request.py b/.github/scripts/test_patch_0_1_1_python_publication_approval_request.py index 0b13718..68cc091 100644 --- a/.github/scripts/test_patch_0_1_1_python_publication_approval_request.py +++ b/.github/scripts/test_patch_0_1_1_python_publication_approval_request.py @@ -140,16 +140,16 @@ def test_request_requires_decision_and_keeps_upload_blocked(self) -> None: self.assertNotIn("saumildiwaker", raw) self.assertNotIn("Desktop/Stuff", raw) - def test_source_metadata_remains_expected_for_python_wheel(self) -> None: + def test_source_metadata_keeps_current_python_surface_shape(self) -> None: pyproject = read(PYPROJECT) init = read(INIT) self.assertIn('name = "ethos-pdf"', pyproject) - self.assertIn('version = "0.1.1"', pyproject) + self.assertIn('version = "0.1.2"', pyproject) self.assertIn('requires-python = ">=3.8"', pyproject) self.assertIn('license = "Apache-2.0"', pyproject) self.assertIn('readme = "python/README.md"', pyproject) - self.assertIn('__version__ = "0.1.1"', init) + self.assertIn('__version__ = "0.1.2"', init) self.assertIn('"EthosCli"', init) self.assertIn('"EthosCommandError"', init) diff --git a/.github/scripts/test_patch_0_1_2_readiness_prep.py b/.github/scripts/test_patch_0_1_2_readiness_prep.py index f374400..6ba7341 100644 --- a/.github/scripts/test_patch_0_1_2_readiness_prep.py +++ b/.github/scripts/test_patch_0_1_2_readiness_prep.py @@ -119,11 +119,10 @@ def test_public_readme_uses_professional_beta_wording_without_version_drift(self for phrase in FORBIDDEN_RELEASE_CLAIMS: self.assertNotIn(phrase, lower) - def test_package_manifests_remain_on_published_baseline(self) -> None: - self.assertIn('version = "0.1.1"', read(WORKSPACE_CARGO)) - self.assertIn('version = "0.1.1"', read(PYPROJECT)) - self.assertIn('__version__ = "0.1.1"', read(PYTHON_INIT)) - self.assertIn('"version": "0.1.1"', read(NPM_PACKAGE)) + def test_package_manifests_do_not_rewrite_prep_record_boundary(self) -> None: + self.assertIn("current public install baseline remains `0.1.1`", normalized(RECORD)) + self.assertNotIn("python3 -m pip install ethos-pdf==0.1.2", read(README)) + self.assertNotIn("npm install -g @docushell/ethos-pdf@0.1.2", read(README)) def test_record_is_indexed_and_status_docs_reference_it(self) -> None: record_name = RECORD.name diff --git a/.github/scripts/test_patch_0_1_2_version_activation.py b/.github/scripts/test_patch_0_1_2_version_activation.py new file mode 100644 index 0000000..150bbd6 --- /dev/null +++ b/.github/scripts/test_patch_0_1_2_version_activation.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +# +# Copyright 2026 The Ethos maintainers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# + +from __future__ import annotations + +import json +import re +import unittest +from pathlib import Path + +from makefile_guard import target_block + + +ROOT = Path(__file__).resolve().parents[2] +RECORD = ROOT / "docs/validation/patch-0-1-2-version-activation-validation-2026-06-24.md" +VALIDATION_README = ROOT / "docs/validation/README.md" +EXECUTION_STATUS = ROOT / "docs/execution-status.md" +PUBLIC_RELEASE_CHECKLIST = ROOT / "docs/public-release-checklist.md" +MAKEFILE = ROOT / "Makefile" +README = ROOT / "README.md" +CARGO = ROOT / "Cargo.toml" +CARGO_LOCK = ROOT / "Cargo.lock" +CLI_CARGO = ROOT / "crates/ethos-cli/Cargo.toml" +PYPROJECT = ROOT / "pyproject.toml" +PYTHON_INIT = ROOT / "python/ethos_pdf/__init__.py" +NPM_PACKAGE = ROOT / "packages/npm/ethos-pdf/package.json" + +SOURCE_SHORT = "0252cc7" +SOURCE_COMMIT = "0252cc7800d51cb1ec673698be5646b4fb945066" +SOURCE_TREE = "ec9e4481ab237192d10942e9ce8d0b4a908c15b8" + +FORBIDDEN_RELEASE_CLAIMS = ( + "0.1.2 is released", + "v0.1.2 is released", + "0.1.2 is published", + "v0.1.2 is published", + "publish 0.1.2", + "tag v0.1.2", + "npm install -g @docushell/ethos-pdf@0.1.2", + "python3 -m pip install ethos-pdf==0.1.2", + "cargo add ethos-doc-core@0.1.2", + "cargo add ethos-verify@0.1.2", + "cargo add ethos-pdf@0.1.2", +) + + +def read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def normalized(path: Path) -> str: + return re.sub(r"\s+", " ", read(path)) + + +class Patch012VersionActivationTests(unittest.TestCase): + def test_record_binds_source_and_declares_activation_scope(self) -> None: + record = normalized(RECORD) + raw = read(RECORD) + + self.assertIn(f"Validated source HEAD before this record: `{SOURCE_SHORT}`", raw) + self.assertIn(f"Version-activation source commit: `{SOURCE_COMMIT}`", record) + self.assertIn(f"Version-activation source tree: `{SOURCE_TREE}`", record) + self.assertIn("Rust workspace and Python source/package metadata move to `0.1.2`", record) + self.assertIn("npm remains at `0.1.1` until matching `0.1.2` CLI artifacts exist", record) + + def test_rust_and_python_versions_are_activated(self) -> None: + cargo = read(CARGO) + cli = read(CLI_CARGO) + lock = read(CARGO_LOCK) + + self.assertIn('version = "0.1.2"', cargo) + self.assertIn('ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.2"', cargo) + self.assertIn('ethos-layout = { path = "crates/ethos-layout", version = "0.1.2" }', cargo) + self.assertIn('ethos-tables = { path = "crates/ethos-tables", version = "0.1.2" }', cargo) + self.assertIn('ethos-pdf = { path = "../ethos-pdf", version = "0.1.2" }', cli) + self.assertIn('ethos-verify = { path = "../ethos-verify", version = "0.1.2" }', cli) + self.assertIn('ethos-grounding-opendataloader-json = { path = "../../adapters/grounding/opendataloader-json", version = "0.1.2" }', cli) + self.assertGreaterEqual(lock.count('version = "0.1.2"'), 7) + self.assertIn('version = "0.1.2"', read(PYPROJECT)) + self.assertIn('__version__ = "0.1.2"', read(PYTHON_INIT)) + + def test_npm_and_public_install_wording_wait_for_artifacts(self) -> None: + npm = json.loads(read(NPM_PACKAGE)) + readme = read(README) + + self.assertEqual("0.1.1", npm["version"]) + self.assertIn("cargo add ethos-doc-core@0.1.1", readme) + self.assertIn("cargo add ethos-verify@0.1.1", readme) + self.assertIn("cargo add ethos-pdf@0.1.1", readme) + self.assertIn("python3 -m pip install ethos-pdf==0.1.1", readme) + self.assertIn("npm install -g @docushell/ethos-pdf@0.1.1", readme) + for phrase in FORBIDDEN_RELEASE_CLAIMS: + self.assertNotIn(phrase, readme.lower()) + + def test_boundaries_remain_closed(self) -> None: + record = normalized(RECORD) + lower = record.lower() + + for phrase in ( + "does not approve a release", + "does not approve a tag", + "does not approve package publish", + "does not approve a GitHub Release artifact", + "does not approve public installation wording for `0.1.2`", + "does not approve hosted surfaces", + "does not approve production positioning", + "does not approve Windows packaged artifacts", + "does not approve bundled project-maintained PDFium builds", + "does not approve public benchmark reports", + "does not approve public benchmark claims", + "does not approve `ethos-doc`", + "does not approve `ethos-rag`", + ): + self.assertIn(phrase, record) + for phrase in FORBIDDEN_RELEASE_CLAIMS: + self.assertNotIn(phrase, lower) + + def test_record_is_indexed_and_release_candidate_prep_runs_guard(self) -> None: + record_name = RECORD.name + block = target_block("release-candidate-prep") + readiness_guard = "$(PYTHON) .github/scripts/test_patch_0_1_2_readiness_prep.py" + activation_guard = "$(PYTHON) .github/scripts/test_patch_0_1_2_version_activation.py" + + self.assertIn(record_name, read(VALIDATION_README)) + self.assertIn(record_name, read(EXECUTION_STATUS)) + self.assertIn(record_name, read(PUBLIC_RELEASE_CHECKLIST)) + self.assertIn(activation_guard, block) + self.assertEqual(1, read(MAKEFILE).count(activation_guard)) + self.assertLess(block.index(readiness_guard), block.index(activation_guard)) + + def test_record_avoids_local_private_paths(self) -> None: + text = read(RECORD) + + for private in ( + "/" + "Users/", + "/" + "private/tmp", + "/" + "private/var", + "/" + "var/folders", + "saumil" + "diwaker", + "Desktop/" + "Stuff", + "project/repo/" + "ethos", + ): + self.assertNotIn(private, text) + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/scripts/test_python_public_api_policy.py b/.github/scripts/test_python_public_api_policy.py index 45ca90b..8d8a41f 100644 --- a/.github/scripts/test_python_public_api_policy.py +++ b/.github/scripts/test_python_public_api_policy.py @@ -70,7 +70,7 @@ def test_package_metadata_declares_public_release_policy(self) -> None: text = pyproject_text() self.assertIn('name = "ethos-pdf"', text) - self.assertIn('version = "0.1.1"', text) + self.assertIn('version = "0.1.2"', text) self.assertIn('requires-python = ">=3.8"', text) self.assertIn('license = "Apache-2.0"', text) self.assertNotIn('license = { text = "Apache-2.0" }', text) @@ -81,7 +81,7 @@ def test_package_metadata_declares_public_release_policy(self) -> None: def test_public_module_version_and_all_match_metadata(self) -> None: assignments = parse_init_assignments() - self.assertEqual("0.1.1", assignments["__version__"]) + self.assertEqual("0.1.2", assignments["__version__"]) self.assertEqual(list(PUBLIC_API), assignments["__all__"]) def test_readme_documents_semver_and_exact_public_api_boundary(self) -> None: diff --git a/.github/scripts/test_release_candidate_prep.py b/.github/scripts/test_release_candidate_prep.py index 9649fff..539825b 100644 --- a/.github/scripts/test_release_candidate_prep.py +++ b/.github/scripts/test_release_candidate_prep.py @@ -57,6 +57,7 @@ "$(PYTHON) .github/scripts/test_release_reproducibility_scaffold.py", "$(PYTHON) .github/scripts/test_launch_copy_approval_scaffold.py", "$(PYTHON) .github/scripts/test_patch_0_1_2_readiness_prep.py", + "$(PYTHON) .github/scripts/test_patch_0_1_2_version_activation.py", "$(PYTHON) .github/scripts/test_first_public_release_artifact_evidence.py", "$(PYTHON) .github/scripts/test_first_public_release_final_decider.py", "$(PYTHON) .github/scripts/test_first_public_release_linux_x64_artifact_evidence.py", diff --git a/CHANGELOG.md b/CHANGELOG.md index 911a699..f89cd97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- boundary-exception: activate Rust workspace and Python source/package metadata for patch `0.1.2` candidate validation while keeping npm and public install wording on the published `0.1.1` baseline; no release, tag, package publication, hosted, production, Windows, bundled PDFium, benchmark, `ethos-doc`, or `ethos-rag` boundary change. - boundary-exception: record narrow patch `0.1.2` readiness prep and professional public README beta wording while retaining `0.1.1` install baselines; no release, tag, package publication, hosted, production, Windows, bundled PDFium, benchmark, `ethos-doc`, or `ethos-rag` boundary change. - boundary-exception: add an `evidence_anchor` v1 guard target, CI guard step, and schema-bound inventory for the merged source-only command; no hosted, production, Windows, bundled PDFium, benchmark, parser-quality, table-quality, or release-posture boundary change. - boundary-exception: add source-only `ethos evidence anchor` schema and CLI surface for deterministic evidence refs; no hosted, production, Windows, bundled PDFium, benchmark, parser-quality, table-quality, or release-posture boundary change. diff --git a/Cargo.lock b/Cargo.lock index b6dffd6..8eab9c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,7 +193,7 @@ dependencies = [ [[package]] name = "ethos-cli" -version = "0.1.1" +version = "0.1.2" dependencies = [ "clap", "ethos-doc-core", @@ -210,7 +210,7 @@ dependencies = [ [[package]] name = "ethos-doc-core" -version = "0.1.1" +version = "0.1.2" dependencies = [ "proptest", "serde", @@ -221,7 +221,7 @@ dependencies = [ [[package]] name = "ethos-grounding-opendataloader-json" -version = "0.1.1" +version = "0.1.2" dependencies = [ "ethos-doc-core", "serde", @@ -230,14 +230,14 @@ dependencies = [ [[package]] name = "ethos-layout" -version = "0.1.1" +version = "0.1.2" dependencies = [ "ethos-doc-core", ] [[package]] name = "ethos-pdf" -version = "0.1.1" +version = "0.1.2" dependencies = [ "ethos-doc-core", "serde", @@ -246,14 +246,14 @@ dependencies = [ [[package]] name = "ethos-tables" -version = "0.1.1" +version = "0.1.2" dependencies = [ "ethos-doc-core", ] [[package]] name = "ethos-verify" -version = "0.1.1" +version = "0.1.2" dependencies = [ "ethos-doc-core", "serde", diff --git a/Cargo.toml b/Cargo.toml index a6a6470..c9f08da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ members = [ ] [workspace.package] -version = "0.1.1" +version = "0.1.2" edition = "2021" rust-version = "1.87" license = "Apache-2.0" @@ -36,9 +36,9 @@ tempfile = "3" proptest = "1" # internal -ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.1", default-features = false } -ethos-layout = { path = "crates/ethos-layout", version = "0.1.1" } -ethos-tables = { path = "crates/ethos-tables", version = "0.1.1" } +ethos-core = { package = "ethos-doc-core", path = "crates/ethos-core", version = "0.1.2", default-features = false } +ethos-layout = { path = "crates/ethos-layout", version = "0.1.2" } +ethos-tables = { path = "crates/ethos-tables", version = "0.1.2" } [profile.release] # Footprint discipline for the G2 gate (≤ 30 MB installed): strip + LTO + size-lean codegen. diff --git a/Makefile b/Makefile index 4c10c41..72271c1 100644 --- a/Makefile +++ b/Makefile @@ -308,6 +308,7 @@ release-candidate-prep: $(PYTHON) .github/scripts/test_release_reproducibility_scaffold.py $(PYTHON) .github/scripts/test_launch_copy_approval_scaffold.py $(PYTHON) .github/scripts/test_patch_0_1_2_readiness_prep.py + $(PYTHON) .github/scripts/test_patch_0_1_2_version_activation.py $(PYTHON) .github/scripts/test_first_public_release_artifact_evidence.py $(PYTHON) .github/scripts/test_first_public_release_final_decider.py $(PYTHON) .github/scripts/test_first_public_release_linux_x64_artifact_evidence.py diff --git a/crates/ethos-cli/Cargo.toml b/crates/ethos-cli/Cargo.toml index 4329269..284c108 100644 --- a/crates/ethos-cli/Cargo.toml +++ b/crates/ethos-cli/Cargo.toml @@ -17,9 +17,9 @@ path = "src/main.rs" ethos-core = { workspace = true, features = ["full", "crop-element"] } ethos-layout = { workspace = true } ethos-tables = { workspace = true } -ethos-pdf = { path = "../ethos-pdf", version = "0.1.1" } -ethos-verify = { path = "../ethos-verify", version = "0.1.1" } -ethos-grounding-opendataloader-json = { path = "../../adapters/grounding/opendataloader-json", version = "0.1.1" } +ethos-pdf = { path = "../ethos-pdf", version = "0.1.2" } +ethos-verify = { path = "../ethos-verify", version = "0.1.2" } +ethos-grounding-opendataloader-json = { path = "../../adapters/grounding/opendataloader-json", version = "0.1.2" } clap = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/docs/execution-status.md b/docs/execution-status.md index cdae262..5b898b4 100644 --- a/docs/execution-status.md +++ b/docs/execution-status.md @@ -270,6 +270,8 @@ The patch `0.1.1` readiness prep record in `docs/validation/patch-0-1-1-readines The patch `0.1.2` readiness prep record in `docs/validation/patch-0-1-2-readiness-prep-validation-2026-06-24.md` records the narrow beta patch candidate boundary after `ethos evidence anchor`, the `evidence_anchor` v1 guard, and professional public README status wording landed on `main`. This is a prep record only: it does not approve a release, tag, version bump, package publish, GitHub Release artifact, hosted surface, production positioning, Windows packaged artifact, bundled project-maintained PDFium build, public benchmark report, or public benchmark claim. The current public install baseline remains `0.1.1` until a separate release decision, version update, artifact build, smoke evidence, registry/GitHub Release evidence, and operator action are completed. +The patch `0.1.2` version activation record in `docs/validation/patch-0-1-2-version-activation-validation-2026-06-24.md` moves the Rust workspace and Python source/package metadata to `0.1.2` for candidate validation only. npm and public install wording remain on the published `0.1.1` baseline until matching `0.1.2` CLI artifacts, registry/GitHub Release evidence, and operator actions are recorded. This activation does not approve a release, tag, package publish, GitHub Release artifact, hosted surface, production positioning, Windows packaged artifact, bundled project-maintained PDFium build, public benchmark report, or public benchmark claim. + | 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/public-release-checklist.md b/docs/public-release-checklist.md index f23ccf7..3b5c5f0 100644 --- a/docs/public-release-checklist.md +++ b/docs/public-release-checklist.md @@ -27,6 +27,14 @@ install baseline at `0.1.1` and does not approve a release, tag, version bump, p GitHub Release artifact, hosted surface, production positioning, Windows packaged artifact, bundled project-maintained PDFium build, public benchmark report, or public benchmark claim. +Patch `0.1.2` version activation is recorded in +`docs/validation/patch-0-1-2-version-activation-validation-2026-06-24.md` for candidate validation +only. It moves Rust workspace and Python source/package metadata to `0.1.2`, keeps npm and public +install wording on the published `0.1.1` baseline until matching CLI artifacts and publication +evidence exist, and does not approve a release, tag, package publish, GitHub Release artifact, +hosted surface, production positioning, Windows packaged artifact, bundled project-maintained +PDFium build, public benchmark report, or public benchmark claim. + ## Required Before Public Push - Package-name and trademark decision is closed by accepted ADR-0006 in diff --git a/docs/validation/README.md b/docs/validation/README.md index 4fb0650..56c0e8d 100644 --- a/docs/validation/README.md +++ b/docs/validation/README.md @@ -653,6 +653,12 @@ recording the exact current-main source candidate and required follow-up evidenc the current public install baseline at `0.1.1` and leaving release, tag, publication, GitHub Release artifact, hosted, production, Windows, bundled PDFium, benchmark, `ethos-doc`, and `ethos-rag` surfaces unapproved. +- `patch-0-1-2-version-activation-validation-2026-06-24.md` - patch 0.1.2 version activation + validation records Rust workspace and Python source/package metadata at `0.1.2`, keeps npm and + public install wording on the published `0.1.1` baseline until matching CLI artifacts and + publication evidence exist, and leaves release, tag, publication, GitHub Release artifact, + hosted, production, Windows, bundled PDFium, benchmark, `ethos-doc`, and `ethos-rag` surfaces + unapproved. - `milestone-e-validation-command-index-validation-2026-06-20.md` - internal Milestone E validation-command index validation passed through command-alignment checks, schema enum checks, row-record checks, public-surface posture checks, `make milestone-e-prep`, and diff hygiene; the diff --git a/docs/validation/patch-0-1-2-version-activation-validation-2026-06-24.md b/docs/validation/patch-0-1-2-version-activation-validation-2026-06-24.md new file mode 100644 index 0000000..a5aeab8 --- /dev/null +++ b/docs/validation/patch-0-1-2-version-activation-validation-2026-06-24.md @@ -0,0 +1,63 @@ +# Patch 0.1.2 Version Activation Validation - 2026-06-24 + +## Purpose + +Record source/package version activation for the narrow patch `0.1.2` beta candidate after +`docs/validation/patch-0-1-2-readiness-prep-validation-2026-06-24.md` landed on `main`. + +Validated source HEAD before this record: `0252cc7`. +Version-activation source commit: `0252cc7800d51cb1ec673698be5646b4fb945066`. +Version-activation source tree: `ec9e4481ab237192d10942e9ce8d0b4a908c15b8`. + +## Activated Source Versions + +Rust workspace and Python source/package metadata move to `0.1.2`: + +- Workspace package version and internal Rust path-dependency version pins. +- `Cargo.lock` workspace package entries. +- Python `pyproject.toml` metadata. +- Python `ethos_pdf.__version__`. + +npm remains at `0.1.1` until matching `0.1.2` CLI artifacts exist and a separate npm vendor-refresh +or publication lane records exact artifact evidence. + +## Boundary + +This record does not approve a release, does not approve a tag, does not approve package publish, +does not approve npm publish, does not approve PyPI publish, does not approve crates.io publish, +does not approve a GitHub Release artifact, does not approve public installation wording for +`0.1.2`, does not approve hosted surfaces, does not approve production positioning, does not +approve Windows packaged artifacts, does not approve bundled project-maintained PDFium builds, +does not approve public benchmark reports, does not approve public benchmark claims, does not +approve speed, footprint, parser-quality, table-quality, or production claims, does not approve +`ethos-doc`, and does not approve `ethos-rag`. + +The current public install baseline remains `0.1.1` until separate package publication, +artifact-publication, registry/GitHub Release evidence, and operator action are completed. + +## Required Before Any Public 0.1.2 Install Wording + +- Build and smoke exact `0.1.2` CLI artifacts from the version-activated source commit. +- Record exact Rust crate package artifacts and dependency ordering for `0.1.2`. +- Record exact Python wheel artifacts for `0.1.2`. +- Refresh npm vendor payload only after matching `0.1.2` CLI artifacts exist. +- Re-run public posture, claims, source snapshot, license/NOTICE, and private-path checks after + any public-facing install wording changes. +- Record manual operator evidence for any credentialed publish or GitHub Release action. + +## Validation Commands + +The version-activation lane should pass at least: + +```sh +cargo check --locked -p ethos-cli +python3 .github/scripts/test_patch_0_1_2_version_activation.py +python3 .github/scripts/test_patch_0_1_2_readiness_prep.py +python3 .github/scripts/test_python_public_api_policy.py +python3 .github/scripts/test_npm_binary_package_scaffold.py +python3 .github/scripts/test_public_surface_posture.py +python3 .github/scripts/public_boundary_claims_gate.py +python3 .github/scripts/claims_gate.py +make light-check PYTHON=python3 +git diff --check +``` diff --git a/pyproject.toml b/pyproject.toml index 57bc75b..7fba5c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ethos-pdf" -version = "0.1.1" +version = "0.1.2" description = "Python wrapper for the Ethos document evidence CLI." readme = "python/README.md" requires-python = ">=3.8" diff --git a/python/ethos_pdf/__init__.py b/python/ethos_pdf/__init__.py index cbfa296..8df4c46 100644 --- a/python/ethos_pdf/__init__.py +++ b/python/ethos_pdf/__init__.py @@ -33,7 +33,7 @@ parse_pdf_text, ) -__version__ = "0.1.1" +__version__ = "0.1.2" __all__ = [ "EthosCli",