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
2 changes: 1 addition & 1 deletion .github/scripts/test_release_artifact_workflow_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def test_workflow_generates_draft_artifacts_without_publication(self) -> None:
self.assertIn("cargo build --locked --release -p ethos-cli", text)
self.assertIn("write_release_artifact_inventory.py", text)
self.assertIn("smoke_release_cli_artifact.py", text)
self.assertIn('--expected-version "ethos 0.2.0"', text)
self.assertIn('--expected-version "ethos 0.3.0"', text)
self.assertIn("--target \"${{ matrix.artifact_target }}\"", text)
self.assertIn("*.smoke.json", text)
self.assertIn("validate_release_artifact_inventory.py", text)
Expand Down
13 changes: 9 additions & 4 deletions .github/scripts/test_v0_2_0_package_build_evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,16 @@ def test_npm_and_cross_platform_artifact_blockers_remain_explicit(self) -> None:
):
self.assertIn(expected, record)

def test_release_workflow_expects_v0_2_smoke(self) -> None:
workflow = read(RELEASE_WORKFLOW)
def test_record_captures_historical_v0_2_workflow_smoke(self) -> None:
record = normalized(RECORD)

self.assertIn('--expected-version "ethos 0.2.0"', workflow)
self.assertNotIn('--expected-version "ethos 0.1.2"', workflow)
self.assertIn('`--expected-version "ethos 0.2.0"`', record)
self.assertIn(
'python3 .github/scripts/smoke_release_cli_artifact.py --expected-version "ethos 0.2.0" --target macos-arm64',
record,
)
self.assertIn("version_stdout: ethos 0.2.0", record)
self.assertNotIn('`--expected-version "ethos 0.1.2"`', record)

def test_boundaries_private_paths_and_v0_2_release_prep_guard(self) -> None:
raw = read(RECORD)
Expand Down
148 changes: 148 additions & 0 deletions .github/scripts/test_v0_3_0_cli_artifact_evidence_prep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/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 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]
RECORD = ROOT / "docs/validation/v0-3-0-cli-artifact-evidence-prep-validation-2026-07-01.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"
WORKFLOW = ROOT / ".github/workflows/release.yml"
MAKEFILE = ROOT / "Makefile"

SOURCE_SHORT = "3ae36b9"
SOURCE_COMMIT = "3ae36b95f9fe7c1f74f58075eacbbaaa7c469bea"
SOURCE_TREE = "d9d6313cd28b647eba89e02b29adcba54349c190"
EXPECTED_VERSION = "ethos 0.3.0"
GUARD_NAME = "test_v0_3_0_cli_artifact_evidence_prep.py"
PRIVATE_PATH_MARKERS = (
"/" + "Users/",
"/" + "private/tmp",
"/" + "private/var",
"/" + "var/folders",
"saumil" + "diwaker",
"Desktop/" + "Stuff",
"project/repo/" + "ethos",
)
FORBIDDEN_APPROVALS = (
"github release artifact publication approved",
"github release publication approved",
"npm vendor refresh approved",
"npm publication approved",
"release tag creation approved",
"package tag creation approved",
"public installation wording approved",
"installable 0.3.0 wording approved",
"docushell integration approved",
"production-ready",
"hosted surfaces approved",
"windows packaged artifacts approved",
"bundled pdfium approved",
"public benchmark claims 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))


class V030CliArtifactEvidencePrepTests(unittest.TestCase):
def test_record_is_source_bound_and_indexed(self) -> None:
raw = read(RECORD)
record = normalized(RECORD)

assert_record_source_binding(
self,
root=ROOT,
raw_record=raw,
normalized_record=record,
validated_head=SOURCE_SHORT,
source_label="v0.3.0 CLI artifact evidence prep",
source_commit=SOURCE_COMMIT,
source_tree=SOURCE_TREE,
)

for path in (VALIDATION_README, EXECUTION_STATUS, PUBLIC_RELEASE_CHECKLIST):
text = normalized(path)
self.assertIn(RECORD.name, text, str(path))
self.assertIn("v0.3.0 CLI artifact evidence prep", text, str(path))
self.assertIn("GitHub Release artifact upload remains blocked", text, str(path))

def test_release_workflow_is_aligned_to_v0_3_draft_artifact_smoke(self) -> None:
workflow = read(WORKFLOW)

self.assertIn("cli-draft-artifacts", workflow)
self.assertIn("macos-arm64", workflow)
self.assertIn("linux-x64", workflow)
self.assertIn("cargo build --locked --release -p ethos-cli", workflow)
self.assertIn("write_release_artifact_inventory.py", workflow)
self.assertIn("smoke_release_cli_artifact.py", workflow)
self.assertIn(f'--expected-version "{EXPECTED_VERSION}"', workflow)
self.assertNotIn('--expected-version "ethos 0.2.0"', workflow)
self.assertIn("validate_release_artifact_inventory.py", workflow)
self.assertIn("actions/upload-artifact@v4", workflow)
self.assertNotIn("gh release create", workflow)
self.assertNotIn("gh release upload", workflow)
self.assertNotIn("npm publish", workflow)

def test_record_names_required_later_artifact_evidence_without_claiming_it(self) -> None:
raw = read(RECORD)
record = normalized(RECORD)
lower = record.lower()

for expected in (
"No workflow run is recorded by this prep record.",
'The workflow now passes `--expected-version "ethos 0.3.0"`',
"The next record must capture the workflow run URL and run id.",
"The next record must capture macOS arm64 and Linux x64 archive SHA256 values",
'"version_stdout": "ethos 0.3.0"',
"GH_PROMPT_DISABLED=1 gh workflow run release.yml --repo docushell/ethos --ref dev/v0-3-cli-artifact-evidence-prep",
"python3 .github/scripts/validate_release_artifact_inventory.py <artifact-download-dir>/*/*.inventory.json",
"GitHub Release artifact publication remains blocked.",
"npm vendor refresh remains blocked.",
"npm publication remains blocked.",
"Public installation wording remains blocked.",
"DocuShell integration remains blocked.",
):
self.assertIn(expected, record)
for forbidden in FORBIDDEN_APPROVALS:
self.assertNotIn(forbidden, lower)
for marker in PRIVATE_PATH_MARKERS:
self.assertNotIn(marker, raw)

def test_release_prep_and_v0_3_gate_include_the_artifact_prep_guard(self) -> None:
release_prep = normalized(RELEASE_PREP)
makefile = read(MAKEFILE)
block = target_block("v0-3-release-prep")
closeout_guard = "$(PYTHON) .github/scripts/test_v0_3_0_publication_closeout.py"
prep_guard = f"$(PYTHON) .github/scripts/{GUARD_NAME}"
public_surface_guard = "$(PYTHON) .github/scripts/test_public_surface_posture.py"

self.assertIn('`--expected-version "ethos 0.3.0"`', release_prep)
self.assertIn("v0.3.0 CLI artifact evidence prep", release_prep)
self.assertIn(prep_guard, block)
self.assertEqual(1, makefile.count(prep_guard))
self.assertLess(block.index(closeout_guard), block.index(prep_guard))
self.assertLess(block.index(prep_guard), block.index(public_surface_guard))


if __name__ == "__main__":
unittest.main()
8 changes: 4 additions & 4 deletions .github/scripts/test_v0_3_0_version_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,13 @@ def test_v0_3_release_prep_runs_activation_guard_after_decision_guard(self) -> N
self.assertLess(block.index(decision_guard), block.index(activation_guard))
self.assertLess(block.index(activation_guard), block.index(claims))

def test_release_prep_keeps_current_artifact_workflow_out_of_scope(self) -> None:
def test_release_prep_keeps_artifact_workflow_bound_to_separate_evidence_lane(self) -> None:
text = normalized(RELEASE_PREP)

self.assertIn("`.github/workflows/release.yml` artifact workflow", text)
self.assertIn('`--expected-version "ethos 0.2.0"`', text)
self.assertIn("Do not use that workflow as evidence for `0.3.0` CLI artifact readiness", text)
self.assertIn("separate CLI artifact lane", text)
self.assertIn('`--expected-version "ethos 0.3.0"`', text)
self.assertIn("v0.3.0 CLI artifact evidence prep", text)
self.assertIn("Draft artifacts remain CI evidence only until a later artifact evidence", text)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
run: |
python3 .github/scripts/smoke_release_cli_artifact.py \
--artifact-dir "target/release-artifacts/ethos-${{ matrix.artifact_target }}" \
--expected-version "ethos 0.2.0" \
--expected-version "ethos 0.3.0" \
--target "${{ matrix.artifact_target }}" \
--out "target/release-artifacts/ethos-${{ matrix.artifact_target }}.smoke.json"
- name: validate draft artifact inventory
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

- boundary-exception: align the v0.3.0 draft CLI artifact workflow smoke expectation to
`ethos 0.3.0` and record CLI artifact evidence prep while keeping GitHub Release artifact
upload, npm vendor refresh, npm publish, public install wording, release/package tags, hosted,
production, Windows, bundled PDFium, benchmark, `ethos-doc`, `ethos-rag`, and DocuShell
integration blocked pending later evidence and approval lanes.
- boundary-exception: close v0.3.0 Rust crates.io and Python PyPI publication with exact live
registry evidence while keeping GitHub Release artifact upload, npm publish, public install
wording, release/package tags, hosted, production, Windows, bundled PDFium, benchmark,
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ v0-3-release-prep:
$(PYTHON) .github/scripts/test_v0_3_0_package_publication_approval_request.py
$(PYTHON) .github/scripts/test_v0_3_0_publication_approval_decision.py
$(PYTHON) .github/scripts/test_v0_3_0_publication_closeout.py
$(PYTHON) .github/scripts/test_v0_3_0_cli_artifact_evidence_prep.py
$(PYTHON) .github/scripts/test_public_surface_posture.py
$(PYTHON) .github/scripts/claims_gate.py
$(PYTHON) .github/scripts/public_boundary_claims_gate.py
Expand Down
8 changes: 8 additions & 0 deletions docs/execution-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ Date: 2026-07-01
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. 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, GitHub Release artifact upload, npm publication/alignment, release/package tags, and DocuShell integration remain blocked pending separate evidence, approval, and closeout records. 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 CLI artifact evidence prep is recorded in
`docs/validation/v0-3-0-cli-artifact-evidence-prep-validation-2026-07-01.md`. It aligns the draft
CLI artifact workflow to smoke `ethos 0.3.0` for macOS arm64 and Linux x64 draft artifacts. It does
not record a workflow run, artifact bytes, checksums, GitHub Release upload, npm vendor refresh,
npm publication, release/package tag creation, public install wording, or DocuShell integration.
GitHub Release artifact upload remains blocked pending later workflow evidence, approval, operator
action, and closeout records.

v0.3.0 publication closeout is recorded in
`docs/validation/v0-3-0-publication-closeout-validation-2026-07-01.md`. It records successful
publication and live registry verification for `ethos-doc-core`, `ethos-verify`, and `ethos-pdf`
Expand Down
8 changes: 8 additions & 0 deletions docs/public-release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ positioning, Windows packaged artifacts, bundled project-maintained PDFium build
reports, public benchmark claims, speed, footprint, parser-quality, table-quality, `ethos-doc`, and
`ethos-rag` remain blocked.

v0.3.0 CLI artifact evidence prep is recorded in
`docs/validation/v0-3-0-cli-artifact-evidence-prep-validation-2026-07-01.md`. It aligns the draft
CLI artifact workflow to smoke `ethos 0.3.0` for macOS arm64 and Linux x64 draft artifacts. It does
not record a workflow run, artifact bytes, checksums, GitHub Release upload, npm vendor refresh,
npm publication, release/package tag creation, public install wording, or DocuShell integration.
GitHub Release artifact upload remains blocked pending later workflow evidence, approval, operator
action, and closeout records.

v0.3.0 publication closeout is recorded in
`docs/validation/v0-3-0-publication-closeout-validation-2026-07-01.md`. It records successful
publication and live registry verification for `ethos-doc-core`, `ethos-verify`, and `ethos-pdf`
Expand Down
15 changes: 10 additions & 5 deletions docs/v0-3-0-release-prep.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,17 @@ The target runs the workspace Rust test suite, app-answer-release contract guard
surface checks, 0.3.0 approval and activation guards, public posture checks, claims gates, and
diff hygiene.

### 3a. Keep The Artifact Workflow Out Of Scope
### 3a. Prepare CLI Artifact Evidence

The current `.github/workflows/release.yml` artifact workflow remains pinned to the published
`0.2.x` CLI artifact lane and still smokes `--expected-version "ethos 0.2.0"`. Do not use that
workflow as evidence for `0.3.0` CLI artifact readiness until a separate CLI artifact lane updates
the expected version, records package evidence, and closes the release boundary.
The `.github/workflows/release.yml` artifact workflow is aligned to the v0.3.0 CLI artifact
evidence lane and smokes `--expected-version "ethos 0.3.0"`. The v0.3.0 CLI artifact evidence
prep record documents this workflow alignment without running the workflow, publishing artifacts,
creating tags, refreshing npm vendor payloads, or changing public install wording.

Draft artifacts remain CI evidence only until a later artifact evidence record captures the
workflow run URL, source commit, macOS arm64 and Linux x64 archive SHA256 values, inventory
sidecars, and smoke sidecars. GitHub Release artifact upload remains blocked until a separate
approval decision and operator closeout pass.

### 4. Gather Package Evidence Before Any Publication Decision

Expand Down
8 changes: 8 additions & 0 deletions docs/validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ in `docs/public-release-checklist.md`.

Records:

v0.3.0 CLI artifact evidence prep is recorded in
`v0-3-0-cli-artifact-evidence-prep-validation-2026-07-01.md`. It aligns the draft
`.github/workflows/release.yml` CLI artifact workflow to smoke `ethos 0.3.0` for macOS arm64 and
Linux x64 draft artifacts. No workflow run, artifact bytes, checksums, GitHub Release upload, npm
vendor refresh, npm publication, release/package tag creation, public install wording, or
DocuShell integration is approved by this prep record. GitHub Release artifact upload remains
blocked pending later workflow evidence, approval, operator action, and closeout records.

v0.3.0 publication closeout is recorded in
`v0-3-0-publication-closeout-validation-2026-07-01.md`. It records successful crates.io
publication for `ethos-doc-core`, `ethos-verify`, and `ethos-pdf` at `0.3.0`, successful PyPI
Expand Down
Loading
Loading