Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions .github/scripts/test_execution_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from __future__ import annotations

import json
import unittest
from pathlib import Path

Expand All @@ -29,23 +30,33 @@ def status_text() -> str:
return EXECUTION_STATUS.read_text(encoding="utf-8")


def published_version() -> str:
"""The published release, from the ledger the status block is rendered from."""
return json.loads((ROOT / "docs/release-state.json").read_text(encoding="utf-8"))["release"]["version"]


class ExecutionStatusTests(unittest.TestCase):
def test_status_is_scoped_to_internal_continuation(self) -> None:
text = status_text()

# Derived from the ledger. These sentences are RENDERED from docs/release-state.json by
# check_release_state.py, so transcribing the version here made a generated block need a
# hand edit in its own test every release — and the test then asserted the previous
# release's prose against a block that had correctly moved on.
published = published_version()
self.assertIn(
"Status: v0.5.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.",
f"Status: v{published} 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.",
text,
)
self.assertIn(
"The exact v0.5.0 public install wording packet is approved and closed out",
f"The exact v{published} public install wording packet is approved and closed out",
text,
)
self.assertIn("docs/validation/v0-3-0-public-install-wording-approval-decision-validation-2026-07-02.md", text)
self.assertIn("docs/validation/v0-3-0-public-install-wording-closeout-validation-2026-07-02.md", text)
self.assertIn("GitHub Release `v0.3.0`", text)
self.assertIn("npm `@docushell/ethos-pdf@0.5.0` is live on npm", text)
self.assertIn(f"npm `@docushell/ethos-pdf@{published}` is live on npm", text)
self.assertIn("v0.3.0 npm publication closeout", text)
self.assertIn("DocuShell integration remain blocked", text)
self.assertIn("Internal Milestone D source-only closeout remains complete", text)
Expand Down Expand Up @@ -89,6 +100,7 @@ def test_internal_check_command_is_documented(self) -> None:

def test_public_posture_boundary_remains_explicit(self) -> None:
text = status_text()
published = published_version()

self.assertIn(
"Public language may use this exact approved sentence on the current source, Rust crate, Python wheel, "
Expand All @@ -106,15 +118,15 @@ def test_public_posture_boundary_remains_explicit(self) -> None:
text,
)
self.assertIn(
"v0.5.0 Rust library crates `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` are live on crates.io",
f"v{published} Rust library crates `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` are live on crates.io",
text,
)
self.assertIn("the Python `ethos-pdf` wheel is live on PyPI", text)
self.assertIn("npm `@docushell/ethos-pdf@0.5.0` is live on npm", text)
self.assertIn("The exact v0.5.0 public install wording packet is approved and closed out", text)
self.assertIn("GitHub Release `v0.5.0`", text)
self.assertIn(f"npm `@docushell/ethos-pdf@{published}` is live on npm", text)
self.assertIn(f"The exact v{published} public install wording packet is approved and closed out", text)
self.assertIn(f"GitHub Release `v{published}`", text)
self.assertIn("macOS arm64/Linux x64 CLI artifacts", text)
self.assertIn("`@docushell/ethos-pdf@0.5.0`", text)
self.assertIn(f"`@docushell/ethos-pdf@{published}`", text)
self.assertIn("docs/validation/v0-3-0-publication-closeout-validation-2026-07-01.md", text)
self.assertIn("ethos-doc-core", text)
self.assertIn("ethos-verify", text)
Expand Down
13 changes: 11 additions & 2 deletions .github/scripts/test_npm_binary_package_scaffold.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,17 @@ 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 published npm package is `@docushell/ethos-pdf@0.5.0`", text)
self.assertIn("`ethos 0.6.0`", text)
# Derived: the published npm version comes from the ledger, the vendored CLI version
# from the payload manifest. They differ during a refresh window and transcribing either
# made this gate need a hand edit every release.
published_npm = json.loads(
(ROOT / "docs/release-state.json").read_text(encoding="utf-8")
)["release"]["npm_package"]["version"]
vendored = json.loads(VENDOR_MANIFEST.read_text(encoding="utf-8"))["cli_version"]
self.assertIn(
f"current published npm package is `@docushell/ethos-pdf@{published_npm}`", text
)
self.assertIn(f"`ethos {vendored}`", text)
self.assertIn("release-archive and extracted-executable SHA256 values", text)
self.assertIn("does not include public benchmark reports or claims", normalized)

Expand Down
36 changes: 26 additions & 10 deletions .github/scripts/test_public_surface_posture.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from __future__ import annotations

import json
import re
import unittest
from pathlib import Path

Expand Down Expand Up @@ -49,16 +50,31 @@ def test_readme_status_matches_supported_release_scope(self) -> None:
self.assertIn("Rust library crates `ethos-doc-core`, `ethos-verify`, and `ethos-pdf`", normalized)
self.assertIn("Python `ethos-pdf` wheel", normalized)
self.assertIn("caller-provided PDFium", text)
self.assertIn("cargo add ethos-doc-core@0.5.0", text)
self.assertIn("cargo add ethos-verify@0.5.0", text)
self.assertIn("cargo add ethos-pdf@0.5.0", text)
self.assertIn("python3 -m pip install ethos-pdf==0.5.0", text)
self.assertIn("npm install -g @docushell/ethos-pdf@0.5.0", text)
self.assertIn("GitHub Release `v0.5.0`", text)
self.assertNotIn("cargo add ethos-doc-core@0.2.0", text)
self.assertNotIn("python3 -m pip install ethos-pdf==0.2.0", text)
self.assertNotIn("npm install -g @docushell/ethos-pdf@0.2.1", text)
self.assertNotIn("@docushell/ethos-pdf@0.2.0` is deprecated", text)
# Derived from the ledger, not transcribed. These were hand-pinned literals that needed
# editing every release and were the last version strings in this file anchored to
# nothing. `release.version` is what is published, so an install command naming any
# other version is by definition wrong.
published = json.loads(read(ROOT / "docs/release-state.json"))["release"]["version"]
for command in (
f"cargo add ethos-doc-core@{published}",
f"cargo add ethos-verify@{published}",
f"cargo add ethos-pdf@{published}",
f"python3 -m pip install ethos-pdf=={published}",
f"npm install -g @docushell/ethos-pdf@{published}",
f"GitHub Release `v{published}`",
):
self.assertIn(command, text, command)

# No install command may name any version other than the published one. This replaces
# the negative assertions retired with test_v0_6_0_version_activation.py, which were
# the only guard against a stale install string surviving in README.md.
for pattern, label in (
(r"cargo add ethos-(?:doc-core|verify|pdf)@([0-9]+\.[0-9]+\.[0-9]+)", "cargo add"),
(r"pip install ethos-pdf==([0-9]+\.[0-9]+\.[0-9]+)", "pip install"),
(r"npm install -g @docushell/ethos-pdf@([0-9]+\.[0-9]+\.[0-9]+)", "npm install"),
):
found = set(re.findall(pattern, text))
self.assertEqual({published}, found, f"{label} versions in README.md: {sorted(found)}")
self.assertNotIn("not production-ready", text.lower())
self.assertNotIn("not stable production surfaces", text.lower())
self.assertNotIn("contracts phase", text)
Expand Down
142 changes: 0 additions & 142 deletions .github/scripts/test_v0_6_0_version_activation.py

This file was deleted.

107 changes: 107 additions & 0 deletions .github/scripts/test_version_activation_lockstep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/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.
#
"""Version lockstep guards, read from the ledger rather than a hard-coded release.

This replaces `test_v0_6_0_version_activation.py`, the sixth hand-written generation of one
gate. That module hard-coded ACTIVATED and PUBLISHED, so every release needed a new copy and
the old one asserted a premise that had become false. Both constants now come from
`docs/release-state.json`: `release.activated` is what the tree prepares, `release.version` is
what is published.

Two assertions are worth keeping across releases:

1. Core release metadata moves in lockstep. A version bump that reaches Cargo.toml but not
pyproject.toml, or the workspace but not the CLI manifest, ships a tree that disagrees with
itself about what it is.

2. The npm payload's four version fields move as one set. 1d23604 moved three of them and left
`vendor/manifest.json` behind, producing a package labelled 0.6.0 whose vendored CLI reported
`ethos 0.5.0` with the full suite green; 46d9584 had to revert it. The set may sit at the
published version, or at the activated version with its recorded boundary exception, and
nothing else.
"""

from __future__ import annotations

import json
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
INTERNAL_WORKSPACE_DEPENDENCIES = ("ethos-core", "ethos-layout", "ethos-tables")
INTERNAL_CLI_DEPENDENCIES = ("ethos-pdf", "ethos-verify", "ethos-grounding-opendataloader-json")


def read(relative: str) -> str:
return (ROOT / relative).read_text(encoding="utf-8")


def ledger() -> dict:
return json.loads(read("docs/release-state.json"))["release"]


class VersionActivationLockstepTests(unittest.TestCase):
def setUp(self) -> None:
release = ledger()
self.activated = release["activated"]
self.published = release["version"]

def test_core_release_metadata_is_activated_in_lockstep(self) -> None:
activated = self.activated
cargo = read("Cargo.toml")
cli = read("crates/ethos-cli/Cargo.toml")
lock = read("Cargo.lock")

self.assertIn(f'version = "{activated}"', cargo)
for dependency in INTERNAL_WORKSPACE_DEPENDENCIES:
line = next(line for line in cargo.splitlines() if line.startswith(dependency))
self.assertIn(f'version = "{activated}"', line, dependency)
for dependency in INTERNAL_CLI_DEPENDENCIES:
line = next(line for line in cli.splitlines() if line.startswith(dependency))
self.assertIn(f'version = "{activated}"', line, dependency)

# Every workspace member resolves at the activated version.
self.assertGreaterEqual(lock.count(f'version = "{activated}"'), 7)
self.assertIn(f'version = "{activated}"', read("pyproject.toml"))
self.assertIn(f'__version__ = "{activated}"', read("python/ethos_pdf/__init__.py"))

def test_npm_payload_versions_move_as_one_set(self) -> None:
manifest = json.loads(read("packages/npm/ethos-pdf/vendor/manifest.json"))
package = json.loads(read("packages/npm/ethos-pdf/package.json"))
lock = json.loads(read("packages/npm/ethos-pdf/package-lock.json"))
versions = {
manifest["cli_version"],
package["version"],
lock["version"],
lock["packages"][""].get("version"),
}

self.assertEqual(1, len(versions), f"npm payload versions disagree: {sorted(versions)}")
moved = versions.pop()

if moved != self.published:
# A payload ahead of the published release is a refresh, allowed only with its
# recorded exception — the governance 46d9584 restored after 1d23604 skipped it.
self.assertEqual(self.activated, moved)
self.assertIn(
f"boundary-exception: refresh the v{moved} npm B payload from frozen core-A",
read("CHANGELOG.md"),
)


if __name__ == "__main__":
unittest.main()
Loading
Loading