diff --git a/.github/scripts/test_app_answer_release_release_prep.py b/.github/scripts/test_app_answer_release_release_prep.py index b5ec370..f6aa481 100644 --- a/.github/scripts/test_app_answer_release_release_prep.py +++ b/.github/scripts/test_app_answer_release_release_prep.py @@ -164,7 +164,6 @@ def test_prep_packet_does_not_itself_perform_release_actions(self) -> None: self.assertIn(required, record) def test_current_public_install_surfaces_remain_on_published_baseline(self) -> None: - self.assertIn('"version": "0.2.1"', read(NPM_PACKAGE)) self.assertIn("cargo add ethos-doc-core@0.2.0", read(README)) self.assertIn("python3 -m pip install ethos-pdf==0.2.0", read(README)) self.assertIn("npm install -g @docushell/ethos-pdf@0.2.1", read(README)) diff --git a/.github/scripts/test_npm_binary_package_scaffold.py b/.github/scripts/test_npm_binary_package_scaffold.py index f0a7571..1876271 100644 --- a/.github/scripts/test_npm_binary_package_scaffold.py +++ b/.github/scripts/test_npm_binary_package_scaffold.py @@ -41,12 +41,12 @@ "darwin:arm64": { "binary": "ethos-darwin-arm64", "release_asset": "ethos-macos-arm64.tar.gz", - "release_asset_sha256": "c588ee77bbaf99a7d933673e6cd9db190f5992e47d40955def803435a9f9fc5a", + "release_asset_sha256": "efb163f140bf4afffd1caeb396f79e42f484591c3e90a86810ca6c0f0c209c96", }, "linux:x64": { "binary": "ethos-linux-x64", "release_asset": "ethos-linux-x64.tar.gz", - "release_asset_sha256": "00137b20ca2c2a2d2089df1d135920b021b0905d779b1347d134e8a2fb7bfa23", + "release_asset_sha256": "b549ba5968e04b7679a8d3e879cd45d27f3e9a6fd226eee5c270a4e4f5c01405", }, } @@ -101,9 +101,11 @@ def test_package_docs_keep_pdfium_and_publication_boundaries(self) -> None: self.assertIn("does not bundle PDFium", text) self.assertIn("ETHOS_PDFIUM_LIBRARY_PATH", text) self.assertIn("QUICKSTART.md", text) - self.assertIn("current npm package is `@docushell/ethos-pdf@0.2.1`", text) + self.assertIn("source package candidate is `@docushell/ethos-pdf@0.3.0`", text) + self.assertIn("current published npm package remains `@docushell/ethos-pdf@0.2.1`", text) self.assertIn("Version `0.2.0` is deprecated", text) - self.assertIn("`ethos 0.2.0`", text) + self.assertIn("`ethos 0.3.0`", text) + self.assertIn("npm publication and public `0.3.0` install wording remain blocked", text) self.assertIn("does not include public benchmark reports or claims", normalized) quickstart = read(QUICKSTART) diff --git a/.github/scripts/test_npm_tarball_candidate_evidence.py b/.github/scripts/test_npm_tarball_candidate_evidence.py index e775300..7767482 100644 --- a/.github/scripts/test_npm_tarball_candidate_evidence.py +++ b/.github/scripts/test_npm_tarball_candidate_evidence.py @@ -29,12 +29,12 @@ ROOT = Path(__file__).resolve().parents[2] PACKAGE_DIR = ROOT / "packages/npm/ethos-pdf" -PACKAGE_TARBALL = PACKAGE_DIR / "docushell-ethos-pdf-0.1.2.tgz" -RECORD = ROOT / "docs/validation/patch-0-1-2-npm-vendor-refresh-validation-2026-06-24.md" +PACKAGE_TARBALL = PACKAGE_DIR / "docushell-ethos-pdf-0.3.0.tgz" +RECORD = ROOT / "docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md" VALIDATION_README = ROOT / "docs/validation/README.md" -SOURCE_SHORT = "2323398" -SOURCE_COMMIT = "23233986035e0f4a20295b24a9cfafafe65aa117" -SOURCE_TREE = "750551f51094f0bc9625c781b8cc978431e431c3" +SOURCE_SHORT = "8e20db3" +SOURCE_COMMIT = "8e20db3c796f051925b059f62c294f41f981bcfa" +SOURCE_TREE = "7f528ace4993e21e457aefb5a0aa65ed40297c6c" EXPECTED_FILES = { "LICENSE", "NOTICE", @@ -49,14 +49,14 @@ "vendor/manifest.json", } EXPECTED_VENDOR_SHA256 = { - "vendor/ethos-darwin-arm64": "47c2f4aaac6cb6a1ca5cf1d9a0cc1f897ef00c48cdd8549455de70f0fbc6bcc1", - "vendor/ethos-linux-x64": "e75122f2954efbde6b8c07a98601b8d4a3b7a06647891a9e60d6aef4046649c3", - "vendor/manifest.json": "d557e081b946be0f839b17b8593027e31267b668498e202372026020f68a97a1", + "vendor/ethos-darwin-arm64": "777e1fb243425a46b83b63ed92fbf7cb810f59cfedd81cfe671cf791410c20dc", + "vendor/ethos-linux-x64": "b416993fc38e6f794611b8b71789ed85af18eb6aa63fef380d9ae7738661f154", + "vendor/manifest.json": "e313b42e49b258171611935455fd9e70bad7ce61c409df63ab90aaa2732a46af", } -EXPECTED_PACK_SHASUM = "39b85d74f588666bfbf69e423a189c2039743de4" -EXPECTED_PACK_SHA256 = "77cbc9c79dd60cc16073690a186e149ecbaabacce035fb0bd3603b267ce64112" +EXPECTED_PACK_SHASUM = "1a90cebd8d52011ea5c41629becdfb37dec73ee7" +EXPECTED_PACK_SHA256 = "1b72ef2fd9415f9edff93319ee2763e8f67cd6168ea00cd64d89a3760101c5fa" EXPECTED_PACK_INTEGRITY = ( - "sha512-3loga13tnAkUkjuOrjKjpA0D3Cm5lW6Al8OwTyRx7NGMt6EB4gMpZOoaSCPjZWchYv7as1uPaEnZyOqrmFOPxg==" + "sha512-ZWoIY5BO7O8tzN88ICGvRasmOt7/RSN/xWFM2ONT8lavQqIOuCY/bQjvxnuK9vGpNeogh8X4UXHLLSRKqqHVOQ==" ) EVIDENCE_PACK_SHASUM = EXPECTED_PACK_SHASUM EVIDENCE_PACK_SHA256 = EXPECTED_PACK_SHA256 @@ -108,8 +108,8 @@ def test_npm_pack_candidate_contents_and_checksums(self) -> None: files = {entry["path"]: entry for entry in pack["files"]} self.assertEqual("@docushell/ethos-pdf", pack["name"]) - self.assertEqual("0.1.2", pack["version"]) - self.assertEqual("docushell-ethos-pdf-0.1.2.tgz", pack["filename"]) + self.assertEqual("0.3.0", pack["version"]) + self.assertEqual("docushell-ethos-pdf-0.3.0.tgz", pack["filename"]) self.assertEqual(EXPECTED_FILES, set(files)) self.assertEqual(493, files["vendor/ethos-darwin-arm64"]["mode"]) self.assertEqual(493, files["vendor/ethos-linux-x64"]["mode"]) @@ -127,8 +127,8 @@ def test_candidate_evidence_record_is_source_bound_and_indexed(self) -> None: readme = normalized(VALIDATION_README) self.assertIn(f"Validated source HEAD before this record: `{SOURCE_SHORT}`", read(RECORD)) - self.assertIn(f"npm vendor refresh source commit: `{SOURCE_COMMIT}`", record) - self.assertIn(f"npm vendor refresh source tree: `{SOURCE_TREE}`", record) + self.assertIn(f"v0.3.0 npm vendor refresh source commit: `{SOURCE_COMMIT}`", record) + self.assertIn(f"v0.3.0 npm vendor refresh source tree: `{SOURCE_TREE}`", record) self.assertIn(EVIDENCE_PACK_SHASUM, record) self.assertIn(EVIDENCE_PACK_SHA256, record) self.assertIn(EVIDENCE_PACK_INTEGRITY, record) @@ -136,13 +136,13 @@ def test_candidate_evidence_record_is_source_bound_and_indexed(self) -> None: self.assertIn(f"npm: `{EXPECTED_NPM_VERSION}`", record) self.assertIn("durable package-content provenance", record) self.assertIn("per-file vendor SHA256 values as the durable content binding", record) - self.assertIn("ethos 0.1.2", record) - self.assertIn("exit code `12`", record) + self.assertIn("ethos 0.3.0", record) + self.assertIn("exit code 12", record) self.assertIn("npm publication remains blocked", record) - self.assertIn("Public installation wording remains blocked", record) + self.assertIn("Public `0.3.0` install wording remains blocked", record) self.assertNotIn("npm publication approved", record.lower()) self.assertIn(RECORD.name, readme) - self.assertIn("patch 0.1.2 npm vendor refresh validation", readme) + self.assertIn("v0.3.0 npm vendor refresh", readme) def test_candidate_tarball_installs_and_preserves_pdfium_boundary(self) -> None: with tempfile.TemporaryDirectory(prefix="ethos-npm-install-") as temp: @@ -178,7 +178,7 @@ def test_candidate_tarball_installs_and_preserves_pdfium_boundary(self) -> None: stderr=subprocess.PIPE, ) self.assertEqual(0, version.returncode, version.stderr) - self.assertEqual("ethos 0.1.2", version.stdout.strip()) + self.assertEqual("ethos 0.3.0", version.stdout.strip()) dummy_pdf = Path(temp) / "dummy.pdf" dummy_pdf.write_text("%PDF-1.4\n%%EOF\n", encoding="utf-8") diff --git a/.github/scripts/test_v0_3_0_npm_vendor_refresh.py b/.github/scripts/test_v0_3_0_npm_vendor_refresh.py new file mode 100644 index 0000000..b7c800c --- /dev/null +++ b/.github/scripts/test_v0_3_0_npm_vendor_refresh.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 +# +# Copyright 2026 The Ethos maintainers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# + +from __future__ import annotations + +import hashlib +import json +import os +import re +import subprocess +import tempfile +import unittest +from pathlib import Path + +from makefile_guard import target_block +from validation_record_source import assert_record_source_binding + + +ROOT = Path(__file__).resolve().parents[2] +PACKAGE_DIR = ROOT / "packages/npm/ethos-pdf" +PACKAGE_JSON = PACKAGE_DIR / "package.json" +PACKAGE_TARBALL = PACKAGE_DIR / "docushell-ethos-pdf-0.3.0.tgz" +RECORD = ROOT / "docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md" +ARTIFACT_CLOSEOUT = ROOT / ( + "docs/validation/v0-3-0-artifact-publication-closeout-validation-2026-07-02.md" +) +VALIDATION_README = ROOT / "docs/validation/README.md" +EXECUTION_STATUS = ROOT / "docs/execution-status.md" +PUBLIC_RELEASE_CHECKLIST = ROOT / "docs/public-release-checklist.md" +RELEASE_PREP = ROOT / "docs/v0-3-0-release-prep.md" +MAKEFILE = ROOT / "Makefile" + +SOURCE_SHORT = "8e20db3" +SOURCE_COMMIT = "8e20db3c796f051925b059f62c294f41f981bcfa" +SOURCE_TREE = "7f528ace4993e21e457aefb5a0aa65ed40297c6c" +MACOS_ARTIFACT_SHA256 = "efb163f140bf4afffd1caeb396f79e42f484591c3e90a86810ca6c0f0c209c96" +LINUX_ARTIFACT_SHA256 = "b549ba5968e04b7679a8d3e879cd45d27f3e9a6fd226eee5c270a4e4f5c01405" +EXPECTED_FILES = { + "LICENSE", + "NOTICE", + "QUICKSTART.md", + "README.md", + "bin/ethos-pdf.js", + "package.json", + "scripts/postinstall.js", + "scripts/prepare-vendor.js", + "vendor/ethos-darwin-arm64", + "vendor/ethos-linux-x64", + "vendor/manifest.json", +} +EXPECTED_VENDOR_SHA256 = { + "vendor/ethos-darwin-arm64": "777e1fb243425a46b83b63ed92fbf7cb810f59cfedd81cfe671cf791410c20dc", + "vendor/ethos-linux-x64": "b416993fc38e6f794611b8b71789ed85af18eb6aa63fef380d9ae7738661f154", + "vendor/manifest.json": "e313b42e49b258171611935455fd9e70bad7ce61c409df63ab90aaa2732a46af", +} +EXPECTED_PACK_SHASUM = "1a90cebd8d52011ea5c41629becdfb37dec73ee7" +EXPECTED_PACK_SHA256 = "1b72ef2fd9415f9edff93319ee2763e8f67cd6168ea00cd64d89a3760101c5fa" +EXPECTED_PACK_INTEGRITY = ( + "sha512-ZWoIY5BO7O8tzN88ICGvRasmOt7/RSN/xWFM2ONT8lavQqIOuCY/bQjvxnuK9vGpNeogh8X4UXHLLSRKqqHVOQ==" +) +EXPECTED_NODE_VERSION = "v23.11.1" +EXPECTED_NPM_VERSION = "10.9.2" +PRIVATE_PATH_MARKERS = ( + "/" + "Users/", + "/" + "private/tmp", + "/" + "private/var", + "/" + "var/folders", + "saumil" + "diwaker", + "Desktop/" + "Stuff", + "project/repo/" + "ethos", +) +FORBIDDEN_APPROVALS = ( + "npm publication approved", + "npm publish approved", + "github release artifact publication approved", + "registry publication approved", + "release tag creation approved", + "package tag creation approved", + "public installation wording approved", + "installable 0.3.0 wording approved", + "production-ready", +) + + +def sha256(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +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 pack_candidate(temp: str) -> dict[str, object]: + env = {**os.environ, "npm_config_cache": str(Path(temp) / "npm-cache")} + result = subprocess.run( + ["npm", "pack", "--json"], + cwd=PACKAGE_DIR, + check=False, + encoding="utf-8", + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + if result.returncode != 0: + raise AssertionError(result.stderr) + return json.loads(result.stdout)[0] + + +class V030NpmVendorRefreshTests(unittest.TestCase): + def test_vendor_payload_files_are_exact_v0_3_release_derived_binaries(self) -> None: + self.assertEqual("0.3.0", json.loads(read(PACKAGE_JSON))["version"]) + for relative_path, expected in EXPECTED_VENDOR_SHA256.items(): + self.assertEqual(expected, sha256(PACKAGE_DIR / relative_path)) + + manifest = json.loads(read(PACKAGE_DIR / "vendor/manifest.json")) + self.assertEqual(MACOS_ARTIFACT_SHA256, manifest["targets"]["darwin:arm64"]["release_asset_sha256"]) + self.assertEqual(LINUX_ARTIFACT_SHA256, manifest["targets"]["linux:x64"]["release_asset_sha256"]) + + def test_npm_pack_candidate_contents_and_checksums(self) -> None: + node_version = subprocess.check_output(["node", "--version"], encoding="utf-8").strip() + npm_version = subprocess.check_output(["npm", "--version"], encoding="utf-8").strip() + exact_pack_toolchain = ( + node_version == EXPECTED_NODE_VERSION and npm_version == EXPECTED_NPM_VERSION + ) + + with tempfile.TemporaryDirectory(prefix="ethos-v0-3-npm-candidate-") as temp: + try: + pack = pack_candidate(temp) + files = {entry["path"]: entry for entry in pack["files"]} + + self.assertEqual("@docushell/ethos-pdf", pack["name"]) + self.assertEqual("0.3.0", pack["version"]) + self.assertEqual("docushell-ethos-pdf-0.3.0.tgz", pack["filename"]) + self.assertEqual(EXPECTED_FILES, set(files)) + self.assertEqual(493, files["vendor/ethos-darwin-arm64"]["mode"]) + self.assertEqual(493, files["vendor/ethos-linux-x64"]["mode"]) + for relative_path, expected in EXPECTED_VENDOR_SHA256.items(): + self.assertEqual(expected, sha256(PACKAGE_DIR / relative_path)) + if exact_pack_toolchain: + self.assertEqual(EXPECTED_PACK_SHASUM, pack["shasum"]) + self.assertEqual(EXPECTED_PACK_INTEGRITY, pack["integrity"]) + self.assertEqual(EXPECTED_PACK_SHA256, sha256(PACKAGE_TARBALL)) + finally: + PACKAGE_TARBALL.unlink(missing_ok=True) + + def test_candidate_tarball_installs_and_preserves_pdfium_boundary(self) -> None: + with tempfile.TemporaryDirectory(prefix="ethos-v0-3-npm-install-") as temp: + try: + pack_candidate(temp) + env = {**os.environ, "npm_config_cache": str(Path(temp) / "npm-cache")} + install = subprocess.run( + ["npm", "install", str(PACKAGE_TARBALL), "--prefix", temp], + cwd=ROOT, + check=False, + encoding="utf-8", + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + self.assertEqual(0, install.returncode, install.stderr) + + ethos = Path(temp) / "node_modules/.bin/ethos" + version = subprocess.run( + [str(ethos), "--version"], + check=False, + encoding="utf-8", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + self.assertEqual(0, version.returncode, version.stderr) + self.assertEqual("ethos 0.3.0", version.stdout.strip()) + + missing_pdfium = subprocess.run( + [str(ethos), "doctor", "--require-pdfium"], + check=False, + encoding="utf-8", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + self.assertEqual(12, missing_pdfium.returncode) + combined = missing_pdfium.stdout + missing_pdfium.stderr + self.assertIn("ethos 0.3.0", combined) + self.assertIn("darwin:arm64", combined) + self.assertIn("approved npm vendor manifest", combined) + self.assertIn("ETHOS_PDFIUM_LIBRARY_PATH", combined) + finally: + PACKAGE_TARBALL.unlink(missing_ok=True) + + def test_evidence_record_is_source_bound_indexed_and_blocked(self) -> None: + raw = read(RECORD) + record = normalized(RECORD) + readme = normalized(VALIDATION_README) + execution = normalized(EXECUTION_STATUS) + checklist = normalized(PUBLIC_RELEASE_CHECKLIST) + release_prep = normalized(RELEASE_PREP) + block = target_block("v0-3-release-prep") + artifact_closeout_guard = ( + "$(PYTHON) .github/scripts/test_v0_3_0_artifact_publication_closeout.py" + ) + scaffold_guard = "$(PYTHON) .github/scripts/test_npm_binary_package_scaffold.py" + vendor_guard = "$(PYTHON) .github/scripts/test_v0_3_0_npm_vendor_refresh.py" + public_surface_guard = "$(PYTHON) .github/scripts/test_public_surface_posture.py" + + assert_record_source_binding( + self, + root=ROOT, + raw_record=raw, + normalized_record=record, + validated_head=SOURCE_SHORT, + source_label="v0.3.0 npm vendor refresh", + source_commit=SOURCE_COMMIT, + source_tree=SOURCE_TREE, + ) + for expected in ( + ARTIFACT_CLOSEOUT.name, + MACOS_ARTIFACT_SHA256, + LINUX_ARTIFACT_SHA256, + EXPECTED_PACK_SHASUM, + EXPECTED_PACK_SHA256, + EXPECTED_PACK_INTEGRITY, + f"Node.js: `{EXPECTED_NODE_VERSION}`", + f"npm: `{EXPECTED_NPM_VERSION}`", + "durable package-content provenance", + "per-file vendor SHA256 values as the durable content binding", + "@docushell/ethos-pdf@0.3.0", + "ethos 0.3.0", + "exit code 12", + "npm publication remains blocked", + "Public `0.3.0` install wording remains blocked", + "current published npm package remains `@docushell/ethos-pdf@0.2.1`", + ): + self.assertIn(expected, record) + for text in (readme, execution, checklist, release_prep): + self.assertIn(RECORD.name, text) + self.assertIn("v0.3.0 npm vendor refresh", text.lower()) + self.assertIn("npm publication", text) + self.assertIn("blocked", text.lower()) + for forbidden in FORBIDDEN_APPROVALS: + self.assertNotIn(forbidden, record.lower()) + for marker in PRIVATE_PATH_MARKERS: + self.assertNotIn(marker, raw) + self.assertIn(scaffold_guard, block) + self.assertIn(vendor_guard, block) + self.assertEqual(1, block.count(vendor_guard)) + self.assertLess(block.index(artifact_closeout_guard), block.index(scaffold_guard)) + self.assertLess(block.index(scaffold_guard), block.index(vendor_guard)) + self.assertLess(block.index(vendor_guard), block.index(public_surface_guard)) + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/scripts/test_v0_3_0_package_build_evidence.py b/.github/scripts/test_v0_3_0_package_build_evidence.py index d57f307..6b663e0 100644 --- a/.github/scripts/test_v0_3_0_package_build_evidence.py +++ b/.github/scripts/test_v0_3_0_package_build_evidence.py @@ -320,7 +320,8 @@ def test_python_wheel_candidate_is_0_3_0_and_helper_smoke_passes(self) -> None: def test_source_metadata_and_public_install_baseline_remain_split(self) -> None: self.assertIn('version = "0.3.0"', read(PYPROJECT)) self.assertIn('__version__ = "0.3.0"', read(PY_INIT)) - self.assertEqual("0.2.1", json.loads(read(NPM_PACKAGE))["version"]) + self.assertIn("- npm package metadata remains `@docushell/ethos-pdf@0.2.1`", read(RECORD)) + self.assertIn(json.loads(read(NPM_PACKAGE))["version"], {"0.2.1", "0.3.0"}) def test_record_keeps_publication_artifact_npm_and_docushell_boundaries_blocked(self) -> None: raw = read(RECORD) diff --git a/.github/scripts/test_v0_3_0_package_publication_approval_request.py b/.github/scripts/test_v0_3_0_package_publication_approval_request.py index 2f2f93a..8ea3caa 100644 --- a/.github/scripts/test_v0_3_0_package_publication_approval_request.py +++ b/.github/scripts/test_v0_3_0_package_publication_approval_request.py @@ -173,7 +173,8 @@ def test_request_does_not_publish_or_approve_public_wording(self) -> None: def test_source_metadata_and_package_scope_remain_bounded(self) -> None: self.assertIn('version = "0.3.0"', read(PYPROJECT)) self.assertIn('__version__ = "0.3.0"', read(PY_INIT)) - self.assertEqual("0.2.1", json.loads(read(NPM_PACKAGE))["version"]) + self.assertIn("npm alignment", normalized(RECORD)) + self.assertIn(json.loads(read(NPM_PACKAGE))["version"], {"0.2.1", "0.3.0"}) for manifest in ( ROOT / "crates/ethos-core/Cargo.toml", diff --git a/.github/scripts/test_v0_3_0_publication_approval_decision.py b/.github/scripts/test_v0_3_0_publication_approval_decision.py index 11a28ba..6b16ad1 100644 --- a/.github/scripts/test_v0_3_0_publication_approval_decision.py +++ b/.github/scripts/test_v0_3_0_publication_approval_decision.py @@ -163,7 +163,8 @@ def test_operator_actions_are_later_bounded_and_artifact_npm_lanes_are_not_execu self.assertNotIn(marker, raw) def test_source_surface_remains_bounded_before_operator_publication(self) -> None: - self.assertEqual("0.2.1", json.loads(read(NPM_PACKAGE))["version"]) + self.assertIn("No `npm publish` command is authorized by this decision record.", normalized(RECORD)) + self.assertIn(json.loads(read(NPM_PACKAGE))["version"], {"0.2.1", "0.3.0"}) for manifest in ( ROOT / "crates/ethos-core/Cargo.toml", diff --git a/.github/scripts/test_v0_3_0_publication_closeout.py b/.github/scripts/test_v0_3_0_publication_closeout.py index f523b7e..611a641 100644 --- a/.github/scripts/test_v0_3_0_publication_closeout.py +++ b/.github/scripts/test_v0_3_0_publication_closeout.py @@ -187,7 +187,7 @@ def test_retained_blockers_public_path_hygiene_and_npm_baseline(self) -> None: raw = read(RECORD) lower = normalized(RECORD).lower() - self.assertEqual("0.2.1", json.loads(read(NPM_PACKAGE))["version"]) + self.assertIn(json.loads(read(NPM_PACKAGE))["version"], {"0.2.1", "0.3.0"}) for expected in ( "Public installation wording may be updated only in a separate bounded docs lane.", "GitHub Release artifact publication remains blocked pending exact v0.3.0 artifact evidence and", diff --git a/.github/scripts/test_v0_3_0_version_activation.py b/.github/scripts/test_v0_3_0_version_activation.py index 8b399f0..c3402cb 100644 --- a/.github/scripts/test_v0_3_0_version_activation.py +++ b/.github/scripts/test_v0_3_0_version_activation.py @@ -100,7 +100,7 @@ def test_record_is_source_bound_and_indexed(self) -> None: self.assertIn("v0.3.0 version activation", text.lower(), str(path)) self.assertIn("remain blocked", text, str(path)) - def test_rust_and_python_versions_are_activated_without_npm_bump(self) -> None: + def test_rust_and_python_versions_are_activated_with_public_npm_baseline_preserved(self) -> None: cargo = read(CARGO) cli = read(CLI_CARGO) lock = read(CARGO_LOCK) @@ -119,7 +119,8 @@ def test_rust_and_python_versions_are_activated_without_npm_bump(self) -> None: self.assertGreaterEqual(lock.count(f'version = "{VERSION}"'), 7) self.assertIn(f'version = "{VERSION}"', read(PYPROJECT)) self.assertIn(f'__version__ = "{VERSION}"', read(PYTHON_INIT)) - self.assertEqual(NPM_PUBLIC_BASELINE, npm["version"]) + self.assertIn(npm["version"], {NPM_PUBLIC_BASELINE, VERSION}) + self.assertIn("npm remains at `0.2.1`", normalized(RECORD)) def test_public_install_commands_remain_on_current_published_baseline(self) -> None: readme = read(README) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fbfc49..9139dd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +- boundary-exception: refresh the `@docushell/ethos-pdf@0.3.0` npm source package candidate from + published v0.3.0 GitHub Release CLI artifacts while keeping npm publish, public install wording, + package tags, hosted, production, Windows, bundled PDFium, benchmark, `ethos-doc`, `ethos-rag`, + and DocuShell integration blocked pending separate lanes. - boundary-exception: close exact v0.3.0 macOS arm64 and Linux x64 GitHub Release CLI artifact publication with published asset evidence while keeping npm vendor refresh, npm publish, public install wording, package tags, hosted, production, Windows, bundled PDFium, benchmark, diff --git a/Makefile b/Makefile index d15f7e6..dc78d00 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,9 @@ v0-3-release-prep: $(PYTHON) .github/scripts/test_v0_3_0_artifact_publication_approval_request.py $(PYTHON) .github/scripts/test_v0_3_0_artifact_publication_approval_decision.py $(PYTHON) .github/scripts/test_v0_3_0_artifact_publication_closeout.py + $(PYTHON) .github/scripts/test_npm_binary_package_scaffold.py + npm test --prefix packages/npm/ethos-pdf + $(PYTHON) .github/scripts/test_v0_3_0_npm_vendor_refresh.py $(PYTHON) .github/scripts/test_public_surface_posture.py $(PYTHON) .github/scripts/claims_gate.py $(PYTHON) .github/scripts/public_boundary_claims_gate.py diff --git a/docs/execution-status.md b/docs/execution-status.md index c7befce..7e9942e 100644 --- a/docs/execution-status.md +++ b/docs/execution-status.md @@ -2,7 +2,15 @@ Date: 2026-07-02 Owner: product / decider -Status: v0.3.0 Rust library crates `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` are live on crates.io, and the Python `ethos-pdf` wheel is live on PyPI. GitHub Release `v0.3.0` now contains closed-out macOS arm64/Linux x64 CLI artifacts for evaluation with caller-provided PDFium. v0.2.0 remains the public CLI artifact baseline with GitHub Release `v0.2.0` macOS arm64/Linux x64 artifacts, and npm remains `@docushell/ethos-pdf@0.2.1`; npm `@docushell/ethos-pdf@0.2.0` is deprecated because it shipped stale CLI binaries that reported `ethos 0.1.2`. Public `0.3.0` install wording, npm publication/alignment, package tags, and DocuShell integration remain blocked pending their separate evidence, operator action, and closeout records. The exact GitHub Release artifact closeout is limited to the approved `v0.3.0` release assets below. PDFium-backed commands use caller-provided PDFium through `ETHOS_PDFIUM_LIBRARY_PATH`. Hosted surfaces, production positioning, Windows packaged artifacts, bundled project-maintained PDFium builds, public benchmark reports, public benchmark claims, speed, footprint, parser-quality, table-quality, `ethos-doc`, and `ethos-rag` remain blocked. +Status: v0.3.0 Rust library crates `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` are live on crates.io, and the Python `ethos-pdf` wheel is live on PyPI. GitHub Release `v0.3.0` now contains closed-out macOS arm64/Linux x64 CLI artifacts for evaluation with caller-provided PDFium. The npm source package candidate is refreshed as `@docushell/ethos-pdf@0.3.0`. v0.2.0 remains the public CLI artifact baseline with GitHub Release `v0.2.0` macOS arm64/Linux x64 artifacts, and npm remains `@docushell/ethos-pdf@0.2.1` for public install wording until a later wording closeout; npm `@docushell/ethos-pdf@0.2.0` is deprecated because it shipped stale CLI binaries that reported `ethos 0.1.2`. Public `0.3.0` install wording, npm publication/alignment, package tags, and DocuShell integration remain blocked pending their separate evidence, operator action, and closeout records. The exact GitHub Release artifact closeout is limited to the approved `v0.3.0` release assets below. PDFium-backed commands use caller-provided PDFium through `ETHOS_PDFIUM_LIBRARY_PATH`. Hosted surfaces, production positioning, Windows packaged artifacts, bundled project-maintained PDFium builds, public benchmark reports, public benchmark claims, speed, footprint, parser-quality, table-quality, `ethos-doc`, and `ethos-rag` remain blocked. + +v0.3.0 npm vendor refresh is recorded in +`docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md`. It refreshes the +`@docushell/ethos-pdf@0.3.0` source package candidate from the published GitHub Release `v0.3.0` +macOS arm64 and Linux x64 CLI artifacts, records exact vendor binary and npm tarball evidence, and +validates local install smoke with `ethos 0.3.0`. npm publication, package tag creation, public +`0.3.0` install wording, and DocuShell integration remain blocked pending separate approval, +operator, registry-smoke, and closeout lanes. v0.3.0 artifact publication closeout is recorded in `docs/validation/v0-3-0-artifact-publication-closeout-validation-2026-07-02.md`. It records diff --git a/docs/public-release-checklist.md b/docs/public-release-checklist.md index 1a291c0..07a99d3 100644 --- a/docs/public-release-checklist.md +++ b/docs/public-release-checklist.md @@ -7,16 +7,25 @@ or launch announcement. It is intentionally stricter than the day-to-day enginee Ethos v0.3.0 Rust library crates `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` are live on crates.io, and the Python `ethos-pdf` wheel is live on PyPI. GitHub Release `v0.3.0` now contains -closed-out macOS arm64/Linux x64 CLI artifacts for evaluation with caller-provided PDFium. v0.2.0 -remains the public CLI artifact baseline with GitHub Release `v0.2.0` macOS arm64/Linux x64 -artifacts, and npm remains `@docushell/ethos-pdf@0.2.1`; npm `@docushell/ethos-pdf@0.2.0` is -deprecated because it shipped stale CLI binaries that reported `ethos 0.1.2`. Public `0.3.0` -install wording, npm publication/alignment, package tags, and DocuShell integration remain blocked -pending their separate evidence, operator action, and closeout records. The exact GitHub Release -artifact closeout is limited to the approved `v0.3.0` release assets below. Hosted surfaces, -production positioning, Windows packaged artifacts, bundled project-maintained PDFium builds, -public benchmark reports, public benchmark claims, speed, footprint, parser-quality, table-quality, -`ethos-doc`, and `ethos-rag` remain blocked. +closed-out macOS arm64/Linux x64 CLI artifacts for evaluation with caller-provided PDFium. The npm +source package candidate is refreshed as `@docushell/ethos-pdf@0.3.0`. v0.2.0 remains the public +CLI artifact baseline with GitHub Release `v0.2.0` macOS arm64/Linux x64 artifacts, and npm +remains `@docushell/ethos-pdf@0.2.1` for public install wording until a later wording closeout; npm +`@docushell/ethos-pdf@0.2.0` is deprecated because it shipped stale CLI binaries that reported +`ethos 0.1.2`. Public `0.3.0` install wording, npm publication/alignment, package tags, and +DocuShell integration remain blocked pending their separate evidence, operator action, and closeout +records. The exact GitHub Release artifact closeout is limited to the approved `v0.3.0` release +assets below. Hosted surfaces, production positioning, Windows packaged artifacts, bundled +project-maintained PDFium builds, public benchmark reports, public benchmark claims, speed, +footprint, parser-quality, table-quality, `ethos-doc`, and `ethos-rag` remain blocked. + +v0.3.0 npm vendor refresh is recorded in +`docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md`. It refreshes the +`@docushell/ethos-pdf@0.3.0` source package candidate from the published GitHub Release `v0.3.0` +macOS arm64 and Linux x64 CLI artifacts, records exact vendor binary and npm tarball evidence, and +validates local install smoke with `ethos 0.3.0`. npm publication, package tag creation, public +`0.3.0` install wording, and DocuShell integration remain blocked pending separate approval, +operator, registry-smoke, and closeout lanes. v0.3.0 artifact publication closeout is recorded in `docs/validation/v0-3-0-artifact-publication-closeout-validation-2026-07-02.md`. It records diff --git a/docs/v0-3-0-release-prep.md b/docs/v0-3-0-release-prep.md index 1c931ed..3390742 100644 --- a/docs/v0-3-0-release-prep.md +++ b/docs/v0-3-0-release-prep.md @@ -111,6 +111,18 @@ blocked. The public install wording remains blocked until the relevant registry, artifact, npm, tag, and wording closeout records pass. +### 3b. Refresh npm Vendor Candidate + +The v0.3.0 npm vendor refresh is recorded in +`docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md`. It refreshes the +`@docushell/ethos-pdf@0.3.0` source package candidate from the published GitHub Release `v0.3.0` +macOS arm64 and Linux x64 CLI artifacts, records exact vendor binary and npm tarball evidence, and +validates local install smoke with `ethos 0.3.0`. + +This refresh does not approve `npm publish`. It does not approve public `0.3.0` install wording. +npm publication, package tag creation, public install wording, and DocuShell integration remain +blocked until separate approval, operator, registry-smoke, tag, and wording closeout records pass. + ### 4. Gather Package Evidence Before Any Publication Decision Before any public package or artifact decision, record exact evidence for the surfaces that are in diff --git a/docs/validation/README.md b/docs/validation/README.md index 8072209..0dc8e4a 100644 --- a/docs/validation/README.md +++ b/docs/validation/README.md @@ -10,6 +10,14 @@ in `docs/public-release-checklist.md`. Records: +v0.3.0 npm vendor refresh is recorded in +`v0-3-0-npm-vendor-refresh-validation-2026-07-02.md`. It refreshes the +`@docushell/ethos-pdf@0.3.0` source package candidate from the published GitHub Release `v0.3.0` +macOS arm64 and Linux x64 CLI artifacts, records exact vendor binary and npm tarball evidence, and +validates local install smoke with `ethos 0.3.0`. npm publication, package tag creation, public +`0.3.0` install wording, and DocuShell integration remain blocked pending separate approval, +operator, registry-smoke, and closeout lanes. + v0.3.0 artifact publication closeout is recorded in `v0-3-0-artifact-publication-closeout-validation-2026-07-02.md`. It records GitHub Release `v0.3.0` at the approved source commit with the exact macOS arm64 and Linux x64 CLI artifact diff --git a/docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md b/docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md new file mode 100644 index 0000000..a0be4a0 --- /dev/null +++ b/docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md @@ -0,0 +1,183 @@ +# v0.3.0 npm Vendor Refresh Validation - 2026-07-02 + +Validated source HEAD before this record: `8e20db3`. + +v0.3.0 npm vendor refresh source commit: +`8e20db3c796f051925b059f62c294f41f981bcfa`. + +v0.3.0 npm vendor refresh source tree: +`7f528ace4993e21e457aefb5a0aa65ed40297c6c`. + +Status: **v0.3.0 npm vendor payload refreshed from published GitHub Release assets; npm publication remains blocked** + +This record validates the checked-in `@docushell/ethos-pdf@0.3.0` npm source package candidate +after refreshing its vendor payload from the published GitHub Release `v0.3.0` macOS arm64 and +Linux x64 CLI artifacts recorded in +`v0-3-0-artifact-publication-closeout-validation-2026-07-02.md`. It does not approve `npm publish`, +public `0.3.0` install wording, package tags, release tags, hosted surfaces, production +positioning, Windows packaged artifacts, bundled project-maintained PDFium builds, `ethos-doc`, +`ethos-rag`, public benchmark reports, public benchmark claims, or DocuShell integration. + +## Published Release Artifact Inputs + +Downloaded from GitHub Release `v0.3.0`: + +- `ethos-macos-arm64.tar.gz` + - SHA256: `efb163f140bf4afffd1caeb396f79e42f484591c3e90a86810ca6c0f0c209c96` +- `ethos-linux-x64.tar.gz` + - SHA256: `b549ba5968e04b7679a8d3e879cd45d27f3e9a6fd226eee5c270a4e4f5c01405` + +Vendor binaries assembled with: + +```sh +node packages/npm/ethos-pdf/scripts/prepare-vendor.js target/v0-3-published-assets-check +``` + +Result: + +```text +prepared vendor/ethos-darwin-arm64 +prepared vendor/ethos-linux-x64 +``` + +## Vendor Payload Checksums + +- `vendor/ethos-darwin-arm64` + - SHA256: `777e1fb243425a46b83b63ed92fbf7cb810f59cfedd81cfe671cf791410c20dc` +- `vendor/ethos-linux-x64` + - SHA256: `b416993fc38e6f794611b8b71789ed85af18eb6aa63fef380d9ae7738661f154` +- `vendor/manifest.json` + - SHA256: `e313b42e49b258171611935455fd9e70bad7ce61c409df63ab90aaa2732a46af` + +The checked-in package metadata now identifies the source package candidate as +`@docushell/ethos-pdf@0.3.0`. The current published npm package remains +`@docushell/ethos-pdf@0.2.1` until a separate npm approval decision, operator publish, registry +smoke, and closeout record pass. + +## npm Pack Candidate + +Command: + +```sh +npm_config_cache= npm pack --json --pack-destination +``` + +Pack toolchain: + +- Node.js: `v23.11.1` +- npm: `10.9.2` + +The npm shasum, tarball SHA256, and integrity below are qualified by this exact pack toolchain +because npm's gzip/tar serialization can change across npm versions. The durable package-content +provenance is the packed file list plus the per-file vendor SHA256 values as the durable content +binding for the release-derived vendor payload above. + +Candidate metadata: + +- package: `@docushell/ethos-pdf@0.3.0` +- filename: `docushell-ethos-pdf-0.3.0.tgz` +- npm shasum: 1a90cebd8d52011ea5c41629becdfb37dec73ee7 +- tarball SHA256: `1b72ef2fd9415f9edff93319ee2763e8f67cd6168ea00cd64d89a3760101c5fa` +- integrity: + `sha512-ZWoIY5BO7O8tzN88ICGvRasmOt7/RSN/xWFM2ONT8lavQqIOuCY/bQjvxnuK9vGpNeogh8X4UXHLLSRKqqHVOQ==` +- size: `1865393` +- unpacked size: `4005888` +- entry count: `11` + +Packed file list: + +- `LICENSE` +- `NOTICE` +- `QUICKSTART.md` +- `README.md` +- `bin/ethos-pdf.js` +- `package.json` +- `scripts/postinstall.js` +- `scripts/prepare-vendor.js` +- `vendor/ethos-darwin-arm64` +- `vendor/ethos-linux-x64` +- `vendor/manifest.json` + +The vendor binaries were packed with executable mode `493`. + +## Local Install Smoke + +Install command: + +```sh +npm_config_cache= npm install /docushell-ethos-pdf-0.3.0.tgz \ + --prefix +``` + +Result: + +```text +added 1 package +``` + +Version smoke: + +```sh +/node_modules/.bin/ethos --version +``` + +Result: + +```text +ethos 0.3.0 +``` + +PDFium boundary smoke: + +```sh +/node_modules/.bin/ethos doctor --require-pdfium +``` + +Result: + +```text +exit code 12 +version: ethos 0.3.0 +platform: darwin:arm64 +packaged target: supported by the approved npm vendor manifest +ETHOS_PDFIUM_LIBRARY_PATH is unset +``` + +## Validation Commands + +```sh +node packages/npm/ethos-pdf/scripts/prepare-vendor.js target/v0-3-published-assets-check +packages/npm/ethos-pdf/vendor/ethos-darwin-arm64 --version +node packages/npm/ethos-pdf/test/platform-selection.test.js +node packages/npm/ethos-pdf/test/vendor-assembly.test.js +python3 .github/scripts/test_v0_3_0_npm_vendor_refresh.py +python3 .github/scripts/test_npm_binary_package_scaffold.py +npm test --prefix packages/npm/ethos-pdf +make v0-3-release-prep PYTHON=python3 +``` + +## Retained Blockers + +- npm publication remains blocked until a dedicated decider record approves `npm publish` for this + exact `0.3.0` candidate. +- Public `0.3.0` install wording remains blocked until npm publication, registry availability, + artifact/package availability, tag decisions, and a dedicated public wording closeout record pass. +- Release tag creation remains blocked. +- Package tag creation remains blocked. +- DocuShell integration remains blocked. +- Windows packaged artifacts remain blocked. +- Hosted surfaces remain blocked. +- Production positioning remains blocked. +- Public benchmark reports remain blocked. +- Public benchmark claims 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`. + +## Result + +The `@docushell/ethos-pdf@0.3.0` npm source package candidate is refreshed from the published +`v0.3.0` GitHub Release assets and locally validated. npm publication remains blocked pending a +dedicated approval request, approval decision, explicit operator action, and closeout evidence. +Public `0.3.0` install wording remains blocked. diff --git a/packages/npm/ethos-pdf/QUICKSTART.md b/packages/npm/ethos-pdf/QUICKSTART.md index 0c40259..4b6918c 100644 --- a/packages/npm/ethos-pdf/QUICKSTART.md +++ b/packages/npm/ethos-pdf/QUICKSTART.md @@ -8,13 +8,16 @@ The package does not bundle PDFium. Commands that parse or crop PDFs require a caller-provided PDFium dynamic library. -Install the current npm package with: +Install the current published npm package with: ```sh npm install -g @docushell/ethos-pdf@0.2.1 ``` -Version `0.2.0` is deprecated because it shipped stale CLI binaries that reported `ethos 0.1.2`. +This source package candidate is `@docushell/ethos-pdf@0.3.0` and vendors CLI binaries that report +`ethos 0.3.0`. npm publication and public `0.3.0` install wording remain blocked until the +separate npm approval, operator publish, registry smoke, and wording closeout records pass. Version +`0.2.0` is deprecated because it shipped stale CLI binaries that reported `ethos 0.1.2`. ## Vendor Binary Assembly diff --git a/packages/npm/ethos-pdf/README.md b/packages/npm/ethos-pdf/README.md index 0516844..b44e374 100644 --- a/packages/npm/ethos-pdf/README.md +++ b/packages/npm/ethos-pdf/README.md @@ -31,6 +31,9 @@ Vendor assembly: - the script extracts the `ethos` executable from each archive and writes `vendor/ethos-darwin-arm64` and `vendor/ethos-linux-x64`. -The current npm package is `@docushell/ethos-pdf@0.2.1`, which vendors CLI binaries that report -`ethos 0.2.0`. Version `0.2.0` is deprecated because it shipped stale CLI binaries that reported -`ethos 0.1.2`. +This source package candidate is `@docushell/ethos-pdf@0.3.0` and vendors CLI binaries that report +`ethos 0.3.0`. npm publication and public `0.3.0` install wording remain blocked until the +separate npm approval, operator publish, registry smoke, and wording closeout records pass. The +current published npm package remains `@docushell/ethos-pdf@0.2.1`, which vendors CLI binaries that +report `ethos 0.2.0`. Version `0.2.0` is deprecated because it shipped stale CLI binaries that +reported `ethos 0.1.2`. diff --git a/packages/npm/ethos-pdf/package.json b/packages/npm/ethos-pdf/package.json index b8cc610..ab5ef3b 100644 --- a/packages/npm/ethos-pdf/package.json +++ b/packages/npm/ethos-pdf/package.json @@ -1,6 +1,6 @@ { "name": "@docushell/ethos-pdf", - "version": "0.2.1", + "version": "0.3.0", "description": "Ethos PDF CLI binary package for document evidence workflows.", "license": "Apache-2.0", "repository": { diff --git a/packages/npm/ethos-pdf/vendor/ethos-darwin-arm64 b/packages/npm/ethos-pdf/vendor/ethos-darwin-arm64 index dd0cc41..ca37832 100755 Binary files a/packages/npm/ethos-pdf/vendor/ethos-darwin-arm64 and b/packages/npm/ethos-pdf/vendor/ethos-darwin-arm64 differ diff --git a/packages/npm/ethos-pdf/vendor/ethos-linux-x64 b/packages/npm/ethos-pdf/vendor/ethos-linux-x64 index 26fe8d9..21f9224 100755 Binary files a/packages/npm/ethos-pdf/vendor/ethos-linux-x64 and b/packages/npm/ethos-pdf/vendor/ethos-linux-x64 differ diff --git a/packages/npm/ethos-pdf/vendor/manifest.json b/packages/npm/ethos-pdf/vendor/manifest.json index b31bbda..649ebb2 100644 --- a/packages/npm/ethos-pdf/vendor/manifest.json +++ b/packages/npm/ethos-pdf/vendor/manifest.json @@ -5,12 +5,12 @@ "darwin:arm64": { "binary": "ethos-darwin-arm64", "release_asset": "ethos-macos-arm64.tar.gz", - "release_asset_sha256": "c588ee77bbaf99a7d933673e6cd9db190f5992e47d40955def803435a9f9fc5a" + "release_asset_sha256": "efb163f140bf4afffd1caeb396f79e42f484591c3e90a86810ca6c0f0c209c96" }, "linux:x64": { "binary": "ethos-linux-x64", "release_asset": "ethos-linux-x64.tar.gz", - "release_asset_sha256": "00137b20ca2c2a2d2089df1d135920b021b0905d779b1347d134e8a2fb7bfa23" + "release_asset_sha256": "b549ba5968e04b7679a8d3e879cd45d27f3e9a6fd226eee5c270a4e4f5c01405" } } }