diff --git a/.github/scripts/test_patch_0_1_1_crates_publication_closeout.py b/.github/scripts/test_patch_0_1_1_crates_publication_closeout.py new file mode 100644 index 0000000..650c235 --- /dev/null +++ b/.github/scripts/test_patch_0_1_1_crates_publication_closeout.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# +# Copyright 2026 The Ethos maintainers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# + +from __future__ import annotations + +import re +import subprocess +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] +RECORD = ROOT / "docs/validation/patch-0-1-1-crates-publication-closeout-validation-2026-06-24.md" +VALIDATION_README = ROOT / "docs/validation/README.md" +MAKEFILE = ROOT / "Makefile" + +SOURCE_SHORT = "7bc50f0" +SOURCE_COMMIT = "7bc50f09f6ce0385737e9b978dcb249f161195b0" +SOURCE_TREE = "88bc7969652d56c534c5a101824926a8e9bbb4d0" +CRATES = ("ethos-doc-core", "ethos-verify", "ethos-pdf") +FORBIDDEN = ( + "hosted surfaces approved", + "production-ready", + "windows packaged artifacts approved", + "bundled pdfium approved", + "ethos-doc approved", + "ethos-rag approved", +) + + +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 git(*args: str) -> str: + return subprocess.check_output( + ["git", *args], + cwd=ROOT, + encoding="utf-8", + stderr=subprocess.DEVNULL, + ).strip() + + +def cargo_search(crate: str) -> str: + return subprocess.check_output( + ["cargo", "search", crate, "--limit", "1"], + cwd=ROOT, + encoding="utf-8", + stderr=subprocess.DEVNULL, + ).strip() + + +class Patch011CratesPublicationCloseoutTests(unittest.TestCase): + def test_closeout_record_is_source_bound_and_indexed(self) -> None: + record = normalized(RECORD) + readme = normalized(VALIDATION_README) + + self.assertIn(RECORD.name, readme) + self.assertIn("patch 0.1.1 crates.io publication closeout", readme.lower()) + self.assertIn(f"Validated source HEAD before this record: `{SOURCE_SHORT}`", read(RECORD)) + self.assertIn(f"Patch 0.1.1 crates publication closeout source commit: `{SOURCE_COMMIT}`", record) + self.assertIn(f"Patch 0.1.1 crates publication closeout source tree: `{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_closeout_records_all_published_crates_and_commands(self) -> None: + record = normalized(RECORD) + + for crate in CRATES: + self.assertIn(f"{crate} = 0.1.1", record) + self.assertIn(f"cargo publish --locked -p {crate}", record) + self.assertIn(f"Published {crate} v0.1.1 at registry `crates-io`", record) + self.assertIn("`ethos-doc-core` was published before dependent crates", record) + self.assertIn("`ethos-verify` was published after ethos-doc-core was visible", record) + self.assertIn("`ethos-pdf` was published after ethos-doc-core was visible", record) + + def test_live_crates_io_reports_patch_versions(self) -> None: + for crate in CRATES: + self.assertIn(f'{crate} = "0.1.1"', cargo_search(crate)) + + def test_closeout_keeps_other_surfaces_blocked(self) -> None: + raw = read(RECORD) + lower = normalized(RECORD).lower() + + for expected in ( + "Public installation wording remains blocked until a separate wording and availability record.", + "Hosted surfaces remain blocked.", + "Production positioning remains blocked.", + "Windows packaged artifacts remain blocked.", + "Bundled project-maintained PDFium builds remain blocked.", + "`ethos-doc` remains blocked.", + "`ethos-rag` remains blocked.", + "PDFium remains caller-provided through `ETHOS_PDFIUM_LIBRARY_PATH`.", + ): + self.assertIn(expected, raw) + for forbidden in FORBIDDEN: + self.assertNotIn(forbidden, lower) + self.assertNotIn("/Users/", raw) + self.assertNotIn("/private/tmp", raw) + self.assertNotIn("/var/folders", raw) + self.assertNotIn("saumildiwaker", raw) + + def test_release_candidate_prep_runs_closeout_after_decision_guard(self) -> None: + makefile = read(MAKEFILE) + decision_guard = "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_decision.py" + closeout_guard = "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_closeout.py" + + self.assertIn(closeout_guard, makefile) + self.assertEqual(1, makefile.count(closeout_guard)) + self.assertLess(makefile.index(decision_guard), makefile.index(closeout_guard)) + self.assertLess( + makefile.index(closeout_guard), + makefile.index("$(PYTHON) .github/scripts/test_pdfium_manual_setup_contract.py"), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/scripts/test_release_candidate_prep.py b/.github/scripts/test_release_candidate_prep.py index a315c80..31f1525 100644 --- a/.github/scripts/test_release_candidate_prep.py +++ b/.github/scripts/test_release_candidate_prep.py @@ -39,6 +39,7 @@ "$(PYTHON) .github/scripts/test_npm_publication_closeout.py", "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_request.py", "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_decision.py", + "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_closeout.py", "$(PYTHON) .github/scripts/test_pdfium_manual_setup_contract.py", "$(PYTHON) .github/scripts/test_release_artifact_workflow_prep.py", "$(PYTHON) .github/scripts/test_patch_0_1_1_release_artifact_evidence.py", diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c8c2e6..0831bcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- boundary-exception: close patch `0.1.1` Rust crates.io publication with exact registry evidence; no public installation wording or support-boundary change. - boundary-exception: approve exact patch `0.1.1` Rust crates.io publication decision for later operator publish; no `cargo publish` or support-boundary change. - boundary-exception: request exact patch `0.1.1` Rust crates.io publication approval for decider review; no `cargo publish` or support-boundary change. - boundary-exception: close patch `0.1.1` npm publication with exact registry evidence; no hosted, production, Windows, bundled PDFium, benchmark, `ethos-doc`, or `ethos-rag` boundary change. diff --git a/Makefile b/Makefile index 83d2731..44e35c2 100644 --- a/Makefile +++ b/Makefile @@ -281,6 +281,7 @@ release-candidate-prep: $(PYTHON) .github/scripts/test_npm_publication_closeout.py $(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_request.py $(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_decision.py + $(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_closeout.py $(PYTHON) .github/scripts/test_pdfium_manual_setup_contract.py $(PYTHON) .github/scripts/test_release_artifact_workflow_prep.py $(PYTHON) .github/scripts/test_patch_0_1_1_release_artifact_evidence.py diff --git a/docs/validation/README.md b/docs/validation/README.md index 0d0dfe3..5bdb6fc 100644 --- a/docs/validation/README.md +++ b/docs/validation/README.md @@ -611,6 +611,10 @@ recording the exact current-main source candidate and required follow-up evidenc crates.io publication approval decision validation accepts the exact `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` `0.1.1` crate set, package source binding, package tag names, dependency-ordered operator commands, and retained blockers; operator publish remains pending. +- `patch-0-1-1-crates-publication-closeout-validation-2026-06-24.md` - patch 0.1.1 crates.io + publication closeout validation records successful crates.io publication and live registry + verification for `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` `0.1.1`, while keeping public + installation wording and unrelated public/support surfaces blocked. - `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-1-crates-publication-closeout-validation-2026-06-24.md b/docs/validation/patch-0-1-1-crates-publication-closeout-validation-2026-06-24.md new file mode 100644 index 0000000..48a0c92 --- /dev/null +++ b/docs/validation/patch-0-1-1-crates-publication-closeout-validation-2026-06-24.md @@ -0,0 +1,120 @@ +# Patch 0.1.1 crates.io Publication Closeout Validation - 2026-06-24 + +Validated source HEAD before this record: `7bc50f0`. + +Patch 0.1.1 crates publication closeout source commit: `7bc50f09f6ce0385737e9b978dcb249f161195b0`. + +Patch 0.1.1 crates publication closeout source tree: `88bc7969652d56c534c5a101824926a8e9bbb4d0`. + +Status: **patch 0.1.1 Rust crates published to crates.io** + +This record closes the bounded patch `0.1.1` crates.io publication lane for `ethos-doc-core`, +`ethos-verify`, and `ethos-pdf`. It records operator publish evidence and live crates.io +verification. It does not approve hosted surfaces, production positioning, Windows packaged +artifacts, bundled project-maintained PDFium builds, `ethos-doc`, `ethos-rag`, public benchmark +reports, public benchmark claims, or broader public wording. + +## Published Crates + +- `ethos-doc-core = 0.1.1` +- `ethos-verify = 0.1.1` +- `ethos-pdf = 0.1.1` + +## Operator Publish Evidence + +`ethos-doc-core` command: + +```text +cargo publish --locked -p ethos-doc-core +``` + +Observed result: + +```text +Uploaded ethos-doc-core v0.1.1 to registry `crates-io` +Published ethos-doc-core v0.1.1 at registry `crates-io` +``` + +Registry visibility check: + +```text +ethos-doc-core = "0.1.1" +``` + +`ethos-verify` command: + +```text +cargo publish --locked -p ethos-verify +``` + +Observed result: + +```text +Uploaded ethos-verify v0.1.1 to registry `crates-io` +Published ethos-verify v0.1.1 at registry `crates-io` +``` + +Registry visibility check: + +```text +ethos-verify = "0.1.1" +``` + +`ethos-pdf` command: + +```text +cargo publish --locked -p ethos-pdf +``` + +Observed result: + +```text +Uploaded ethos-pdf v0.1.1 to registry `crates-io` +Published ethos-pdf v0.1.1 at registry `crates-io` +``` + +Registry visibility check: + +```text +ethos-pdf = "0.1.1" +``` + +## Dependency-Order Evidence + +- `ethos-doc-core` was published before dependent crates. +- `ethos-verify` was published after ethos-doc-core was visible on crates.io. +- `ethos-pdf` was published after ethos-doc-core was visible on crates.io. + +## Retained Blockers + +- Public installation wording remains blocked until a separate wording and availability record. +- Hosted surfaces remain blocked. +- Production positioning remains blocked. +- Public benchmark reports remain blocked. +- Public benchmark claims remain blocked. +- Windows packaged artifacts remain blocked. +- Bundled project-maintained PDFium builds remain blocked. +- `ethos-doc` remains blocked. +- `ethos-rag` remains blocked. +- PDFium remains caller-provided through `ETHOS_PDFIUM_LIBRARY_PATH`. + +## Commands + +```sh +python3 .github/scripts/test_patch_0_1_1_crates_publication_closeout.py +python3 .github/scripts/test_patch_0_1_1_crates_publication_approval_decision.py +python3 .github/scripts/test_patch_0_1_1_crates_publication_approval_request.py +cargo search ethos-doc-core --limit 1 +cargo search ethos-verify --limit 1 +cargo search ethos-pdf --limit 1 +make release-candidate-prep PYTHON=python3 +git diff --check +``` + +## Result + +```text +patch 0.1.1 Rust crates.io publication closeout recorded +ethos-doc-core, ethos-verify, and ethos-pdf 0.1.1 are live on crates.io +Public installation wording and unrelated public/support surfaces remain blocked +```