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
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/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-approval-decision-validation-2026-06-24.md"
REQUEST = ROOT / "docs/validation/patch-0-1-1-crates-publication-approval-request-validation-2026-06-24.md"
VALIDATION_README = ROOT / "docs/validation/README.md"
MAKEFILE = ROOT / "Makefile"

SOURCE_SHORT = "5de6014"
SOURCE_COMMIT = "5de6014e0fe668bac306eb2c2f5b2963ab5baf96"
SOURCE_TREE = "6fc0207e61681da6ba868772e77bcbc808c98bfb"
PACKAGE_SOURCE_COMMIT = "a0851030e28c155c12f5f966af8fa0739a536ea9"
PACKAGE_SOURCE_TREE = "0238c3f6bfd264f8803708e4a828d8352320f08f"
CRATES = ("ethos-doc-core", "ethos-verify", "ethos-pdf")
FORBIDDEN = (
"crates are published",
"published crates",
"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()


class Patch011CratesPublicationApprovalDecisionTests(unittest.TestCase):
def test_decision_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 approval decision", readme.lower())
self.assertIn(f"Validated source HEAD before this record: `{SOURCE_SHORT}`", read(RECORD))
self.assertIn(f"Patch 0.1.1 crates publication approval decision source commit: `{SOURCE_COMMIT}`", record)
self.assertIn(f"Patch 0.1.1 crates publication approval decision 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_decision_accepts_exact_request_packet(self) -> None:
record = normalized(RECORD)

self.assertIn(REQUEST.name, record)
self.assertIn("Decision: accept exact patch `0.1.1` crates.io publication decision packet.", record)
self.assertIn(f"Package source commit accepted by this decision: `{PACKAGE_SOURCE_COMMIT}`", record)
self.assertIn(f"Package source tree accepted by this decision: `{PACKAGE_SOURCE_TREE}`", record)
for crate in CRATES:
self.assertIn(crate, record)
self.assertIn(f"{crate} = 0.1.1", record)
self.assertIn(f"cargo publish --locked -p {crate}", record)
self.assertIn("ethos-package-ethos-doc-core-0.1.1", record)
self.assertIn("ethos-package-ethos-verify-0.1.1", record)
self.assertIn("ethos-package-ethos-pdf-0.1.1", record)

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

for expected in (
"This decision record does not run `cargo publish`.",
"Publication remains a separate operator action.",
"After this decision record is merged and validation passes on merged source, an operator may run only these commands:",
"The operator must publish `ethos-doc-core` first.",
"The operator must wait for crates.io to report `ethos-doc-core = 0.1.1` before publishing dependent crates.",
"Public installation wording remains blocked until registry availability is closed out.",
"`ethos-doc` remains blocked.",
"`ethos-rag` remains blocked.",
):
self.assertIn(expected, record)
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_publish_surface_remains_limited_in_manifests(self) -> None:
for manifest in (
ROOT / "crates/ethos-core/Cargo.toml",
ROOT / "crates/ethos-verify/Cargo.toml",
ROOT / "crates/ethos-pdf/Cargo.toml",
):
text = read(manifest)
self.assertNotIn("publish = false", text, str(manifest))
self.assertIn('publication_status = "approved_for_crates_io_publication"', text, str(manifest))

for manifest in (
ROOT / "crates/ethos-cli/Cargo.toml",
ROOT / "crates/ethos-layout/Cargo.toml",
ROOT / "crates/ethos-tables/Cargo.toml",
):
self.assertIn("publish = false", read(manifest), str(manifest))

def test_release_candidate_prep_runs_decision_guard_after_request_guard(self) -> None:
makefile = read(MAKEFILE)
request_guard = "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_request.py"
decision_guard = "$(PYTHON) .github/scripts/test_patch_0_1_1_crates_publication_approval_decision.py"

self.assertIn(decision_guard, makefile)
self.assertEqual(1, makefile.count(decision_guard))
self.assertLess(makefile.index(request_guard), makefile.index(decision_guard))
self.assertLess(
makefile.index(decision_guard),
makefile.index("$(PYTHON) .github/scripts/test_pdfium_manual_setup_contract.py"),
)


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions .github/scripts/test_release_candidate_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"$(PYTHON) .github/scripts/test_npm_publication_final_approval_decision.py",
"$(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_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",
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- 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.
- boundary-exception: approve exact patch `0.1.1` npm publication decision for later operator publish; no npm publish or support-boundary change.
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ release-candidate-prep:
$(PYTHON) .github/scripts/test_npm_publication_final_approval_decision.py
$(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_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
Expand Down
4 changes: 4 additions & 0 deletions docs/validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,10 @@ recording the exact current-main source candidate and required follow-up evidenc
`ethos-verify`, and `ethos-pdf` `0.1.1` crate set, source commit, package tag names, local crate
artifact hashes, publish order, and retained blockers for decider review; `cargo publish`
remains blocked.
- `patch-0-1-1-crates-publication-approval-decision-validation-2026-06-24.md` - patch 0.1.1
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.
- `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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Patch 0.1.1 crates.io Publication Approval Decision Validation - 2026-06-24

Validated source HEAD before this record: `5de6014`.

Patch 0.1.1 crates publication approval decision source commit: `5de6014e0fe668bac306eb2c2f5b2963ab5baf96`.

Patch 0.1.1 crates publication approval decision source tree: `6fc0207e61681da6ba868772e77bcbc808c98bfb`.

Status: **patch 0.1.1 crates.io publication approval decision recorded; operator publish remains pending**

This record accepts the exact patch `0.1.1` crates.io publication request packet after decider
approval. It approves only the bounded later operator actions for `ethos-doc-core`,
`ethos-verify`, and `ethos-pdf` version `0.1.1`. It does not run `cargo publish`, publish any
crate, change public wording, approve hosted surfaces, approve production positioning, approve
Windows packaged artifacts, approve bundled project-maintained PDFium builds, approve `ethos-doc`,
approve `ethos-rag`, or approve public benchmark reports or claims.

## Subject

- Repository: `docushell/ethos`
- Lane: Rust crates publication
- Approval owner: `docushell-admin`
- Approval request record:
`docs/validation/patch-0-1-1-crates-publication-approval-request-validation-2026-06-24.md`
- Package source commit accepted by this decision: `a0851030e28c155c12f5f966af8fa0739a536ea9`
- Package source tree accepted by this decision: `0238c3f6bfd264f8803708e4a828d8352320f08f`

## Exact Decision Fields

- Decision: accept exact patch `0.1.1` crates.io publication decision packet.
- Approver: `docushell-admin` acting as decider.
- Date: 2026-06-24.
- Exact candidate crate list accepted by this decision: `ethos-doc-core`, `ethos-verify`, and
`ethos-pdf` only.
- Exact package version map accepted by this decision: `ethos-doc-core = 0.1.1`,
`ethos-verify = 0.1.1`, and `ethos-pdf = 0.1.1`.
- Exact package tag name set accepted by this decision: `ethos-package-ethos-doc-core-0.1.1`,
`ethos-package-ethos-verify-0.1.1`, and `ethos-package-ethos-pdf-0.1.1`.
- Exact package tag source commit accepted by this decision:
`a0851030e28c155c12f5f966af8fa0739a536ea9`.
- Exact package tag source tree accepted by this decision:
`0238c3f6bfd264f8803708e4a828d8352320f08f`.
- Exact operator commands accepted by this decision:
- `cargo publish --locked -p ethos-doc-core`
- `cargo publish --locked -p ethos-verify`
- `cargo publish --locked -p ethos-pdf`

## Approved Operator Action

After this decision record is merged and validation passes on merged source, an operator may run
only these commands:

```sh
cargo publish --locked -p ethos-doc-core
cargo publish --locked -p ethos-verify
cargo publish --locked -p ethos-pdf
```

The operator must publish `ethos-doc-core` first. The operator must wait for crates.io to report
`ethos-doc-core = 0.1.1` before publishing dependent crates. The operator must stop if candidate
contents differ, package versions differ, crates.io reports any unexpected version state, or any
retained blocker is softened.

Publication remains a separate operator action. This decision record does not run `cargo publish`.

## Required Operator Pre-Publish Checks

Before publishing, the operator must run:

```sh
cargo package --locked --offline -p ethos-doc-core --allow-dirty --no-verify
cargo check --locked --offline -p ethos-verify
cargo check --locked --offline -p ethos-pdf
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
make release-candidate-prep PYTHON=python3
git diff --check
```

## Explicit Exclusions

- `ethos-cli` remains excluded from crates.io publication.
- `ethos-layout` remains excluded from crates.io publication.
- `ethos-tables` remains excluded from crates.io publication.
- `ethos-grounding-opendataloader-json` remains excluded from crates.io publication.
- 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.
- Broader public wording remains blocked.

## Evidence Bound To This Decision

- Decider decision supplied: Approved; exact patch `0.1.1` Rust crates.io publication request
accepted.
- `python3 .github/scripts/test_patch_0_1_1_crates_publication_approval_request.py` passed.
- `python3 .github/scripts/test_milestone_e_package_publication_current_registry_assembly.py`
passed.
- `python3 .github/scripts/test_milestone_e_package_publication_dry_run_smoke.py` passed.
- `cargo package --locked --offline -p ethos-doc-core --allow-dirty --no-verify` passed.
- `cargo check --locked --offline -p ethos-verify` passed.
- `cargo check --locked --offline -p ethos-pdf` passed.
- `make release-candidate-prep PYTHON=python3` passed on merged `main` before this decision branch.

## Non-Actions

- This decision record does not run `cargo publish`.
- This decision record does not publish any crate.
- This decision record does not create package tags.
- This decision record does not approve public installation wording.
- This decision record does not approve hosted surfaces.
- This decision record does not approve production positioning.
- This decision record does not approve public benchmark reports.
- This decision record does not approve public benchmark claims.
- This decision record does not approve Windows packaged artifacts.
- This decision record does not approve bundled project-maintained PDFium builds.
- This decision record does not approve `ethos-doc`.
- This decision record does not approve `ethos-rag`.

## Retained Blockers

- Public installation wording remains blocked until registry availability is closed out.
- 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.

## Result

The exact patch `0.1.1` crates.io publication decision packet for `ethos-doc-core`,
`ethos-verify`, and `ethos-pdf` is accepted. Actual crates.io publication remains a separate
operator action requiring final pre-publish checks, crates.io credentials, dependency-order
discipline, and later registry closeout evidence.
Loading