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/check_release_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def render_current_status(state: Mapping[str, object]) -> str:
f"and the Python `{python_package['name']}` wheel is live on PyPI. Its released version is "
f"`{python_package['version']}`. GitHub Release `{github['tag']}` is marked as the "
"repository's latest release and contains closed-out "
f"{platforms} CLI artifacts for evaluation with "
f"{platforms} CLI artifacts built against "
f"caller-provided PDFium through `{release['pdfium_environment']}`. npm "
f"`{npm_package['name']}@{npm_package['version']}` is live on npm. The exact v{version} "
f"public install wording packet is approved and closed out. Package-tag creation for "
Expand Down
8 changes: 3 additions & 5 deletions .github/scripts/claims_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,10 @@
(re.compile(r"best[- ]in[- ]class", re.I), '"best-in-class" claim'),
(re.compile(r"contracts phase", re.I), "stale pre-alpha posture"),
(re.compile(r"Gate Zero[^\n]*has not run", re.I), "stale Gate Zero posture"),
(re.compile(r"launch package", re.I), "public-surface launch/package posture"),
(re.compile(r"pre[- ]alpha", re.I), "stale pre-alpha posture"),
(re.compile(r"public beta", re.I), "stale public-beta posture"),
(re.compile(r"beta evaluation", re.I), "stale beta-evaluation posture"),
(re.compile(r"benchmark[- ]validated", re.I), "unsupported public benchmark posture"),
(re.compile(r"release[- ]ready", re.I), "unsupported public release posture"),
(re.compile(r"package[- ]ready", re.I), "unsupported public package posture"),
(re.compile(r"production[- ]ready", re.I), "unsupported public production posture"),
(re.compile(r"launch[- ]ready", re.I), "unsupported public launch posture"),
(re.compile(r"pixel[- ]level proof", re.I), '"pixel-level proof" claim'),
(re.compile(r"semantic proof", re.I), '"semantic proof" claim'),
(re.compile(r"arithmetic proof", re.I), '"arithmetic proof" claim'),
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/test_claims_gate_registry_surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ def test_npm_quickstart_rejects_banned_claim(self) -> None:
write_surface(
root,
"packages/npm/ethos-pdf/QUICKSTART.md",
"Install this production-ready package.\n",
"Install this public beta package.\n",
)
hits = find_claim_hits(root, REGISTRY_SURFACES)
self.assertEqual(Path("packages/npm/ethos-pdf/QUICKSTART.md"), hits[0][0])
self.assertEqual("unsupported public production posture", hits[0][2])
self.assertEqual("stale public-beta posture", hits[0][2])

def test_missing_optional_surface_does_not_fail_scan(self) -> None:
with tempfile.TemporaryDirectory(prefix="ethos-claims-registry-") as temp:
Expand Down
6 changes: 3 additions & 3 deletions .github/scripts/test_evidence_anchor_v1_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def test_contract_inventory_binds_existing_files_and_tests(self) -> None:

self.assertEqual(inventory["schema_version"], 1)
self.assertEqual(inventory["contract"], "evidence_anchor.v1")
self.assertEqual(inventory["status"], "source-only-public-beta-evaluation")
self.assertEqual(inventory["status"], "supported")
self.assertEqual(inventory["carrier"], "ethos evidence anchor")
for key in ["request_schema", "report_schema"]:
self.assertTrue((ROOT / inventory[key]).is_file(), key)
Expand Down Expand Up @@ -217,8 +217,8 @@ def test_status_docs_link_contract_without_expanding_posture(self) -> None:
self.assertIn("make evidence-anchor-v1-contract", text, path)

readme = README.read_text(encoding="utf-8")
self.assertIn("Status: public beta evaluation.", readme)
self.assertNotIn("production-ready", readme.lower())
self.assertIn("deterministic document evidence layer", readme)
self.assertNotIn("public beta", readme.lower())

def test_anchor_statuses_match_inventory(self) -> None:
inventory = load_json(CONTRACT_INVENTORY)
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/test_pdfium_manual_setup_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def test_readme_has_bounded_two_minute_pdf_parse_quickstart(self) -> None:
self.assertIn("ethos doc parse fixtures/synthetic/simple-text/document.pdf --format text", text)
self.assertIn("caller-provided through `ETHOS_PDFIUM_LIBRARY_PATH`", text)
self.assertIn("does not download, install, repair, or vet untrusted dynamic libraries", text)
self.assertIn("evaluation smoke path, not a benchmark", text)
self.assertIn("smoke path, not a benchmark", text)
self.assertIn("born-digital", text)

def test_rust_backend_missing_pdfium_error_names_env_var(self) -> None:
Expand Down
17 changes: 8 additions & 9 deletions .github/scripts/test_public_surface_posture.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,16 @@ def readme_boundary_claims() -> list[str]:


class PublicSurfacePostureTests(unittest.TestCase):
def test_readme_status_matches_public_beta_evaluation_scope(self) -> None:
def test_readme_status_matches_supported_release_scope(self) -> None:
text = read(README)
normalized = " ".join(line.removeprefix("> ").strip() for line in text.splitlines())

self.assertIn("public beta evaluation", text)
for claim in readme_boundary_claims():
self.assertIn(claim, normalized)
self.assertIn("deterministic document evidence layer", text)
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("release-scope work", 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)
Expand All @@ -65,11 +63,14 @@ def test_readme_status_matches_public_beta_evaluation_scope(self) -> None:
self.assertNotIn("not stable production surfaces", text.lower())
self.assertNotIn("contracts phase", text)
self.assertNotIn("has not run", text)
self.assertNotIn("public beta", text.lower())
self.assertNotIn("beta evaluation", text.lower())
self.assertNotIn("pre-alpha", text.lower())

def test_examples_readme_stays_fixture_scoped(self) -> None:
text = read(EXAMPLES_README)

self.assertIn("source-only public beta fixture set", text)
self.assertIn("Pinned fixture set", text)
self.assertIn("Pinned fixtures only", text)
self.assertNotIn("launch package", text.lower())

Expand All @@ -78,12 +79,10 @@ def test_claims_gate_blocks_stale_public_posture_terms(self) -> None:

self.assertIn("contracts phase", text)
self.assertIn("Gate Zero[^\\n]*has not run", text)
self.assertIn("launch package", text)
self.assertIn("benchmark[- ]validated", text)
self.assertIn("release[- ]ready", text)
self.assertIn("package[- ]ready", text)
self.assertIn("production[- ]ready", text)
self.assertIn("launch[- ]ready", text)
self.assertIn("pre[- ]alpha", text)
self.assertIn("public beta", text)
self.assertIn("beta evaluation", text)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/test_release_reproducibility_scaffold.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def test_patch_release_artifact_refresh_prep_stays_bounded(self) -> None:
normalized_notices = normalized(RELEASE_NOTICES)
combined = f"{runbook}\n{notices}"

self.assertIn("@docushell/ethos-pdf@0.3.0", runbook)
self.assertIn("@docushell/ethos-pdf", runbook)
self.assertIn("Patch 0.1.1 Artifact Refresh Prep", runbook)
self.assertIn("ethos 0.1.1", runbook)
self.assertIn("ethos 0.1.1", notices)
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ jobs:
- name: derive candidate version
id: version
shell: bash
run: echo "value=$(python3 -c \"import tomllib; print(tomllib.load(open('Cargo.toml','rb'))['workspace']['package']['version'])\")" >> "$GITHUB_OUTPUT"
# A block scalar, not a plain one. YAML plain scalars do not process `\"` as an escape,
# so the backslashes reached bash literally and broke the command substitution's quoting
# — `syntax error near unexpected token \'tomllib.load\'`, on every run this step ever had.
# The pwsh sibling below was always written this way and always worked.
run: |
value="$(python3 -c "import tomllib; print(tomllib.load(open('Cargo.toml','rb'))['workspace']['package']['version'])")"
echo "value=$value" >> "$GITHUB_OUTPUT"
- name: assemble draft artifact
shell: bash
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ benchmarks/results/fixtures/*.json
benchmarks/results/gate-zero/*
!benchmarks/results/gate-zero/README.md
# Cargo.lock IS committed (determinism: pinned dependency graph). Do not add it here.

# Local agent config (identity policy, rules). Not repo content.
.agents/
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@

## 0.6.0 - 2026-08-30

### The public surfaces stop describing Ethos as unreleased

- boundary-exception: removes the public-beta posture from `README.md` — the `status: public
beta` badge and the "Status: public beta evaluation" blockquote enumerating the evaluation
surfaces. It read as "not ready yet" to anyone arriving at a 0.6.0 release. The replacement
states what Ethos is and where it ships, and drops the version enumeration so the header
stops going stale on every release. Capability boundaries are untouched: no OCR, no hosted
API, no bundled PDFium, and no benchmark numbers are still stated as facts about scope.

- boundary-exception: the posture gates now enforce the new stance instead of the old one.
`test_public_surface_posture.py` asserted the beta blockquote was present — that assertion
was the reason 3777cc9 was reverted in 8c2d13f. It now asserts the beta wording is absent,
and `claims_gate.py` trades its `production-ready` / `release-ready` / `launch-ready` /
`package-ready` bans for `pre-alpha` / `public beta` / `beta evaluation`. The unearned-claim
bans — superlatives, speed, benchmark-validated — are untouched, so removing hesitation
still buys no overclaim. `docs/public-boundary-claims.json` follows the reworded sentences.

- boundary-exception: `docs/release-state.json` drops `production positioning` and `additional
release tags or release targets` from `blocked_lanes`; both blocked the release this section
describes. The remaining blockers — hosted surfaces, Windows artifacts, bundled PDFium,
benchmark claims, `ethos-doc`, `ethos-rag` — are unchanged. Published-version facts are
unchanged: the generated block still reports 0.5.0 as the published baseline, because
0.6.0 packages are not published yet.

- boundary-exception: the contract inventories carry `"status": "supported"` in place of
`"source-only-pre-alpha"` and `"source-only-public-beta-evaluation"`. Schema `const`s and
their examples changed together, and `validate_examples.py` stays green. The CLI's runtime
warning for the opt-in crop surface says `crop_element is an unstable opt-in surface`
rather than `source-only pre-alpha and unsupported`: it is still gated and still unstable,
which is a fact about that surface rather than about the project.

- `README.md` no longer calls Grounding JSON "a proposal, not a current feature". It shipped
in this release — `ethos grounding check`, `ethos.grounding.v1` schema 1.1.0 — so the
section described the repository as it stood before the work it now sits above.

Dated records under `docs/validation/`, and the sections of `docs/execution-status.md` that
its own header marks as superseded by the generated block, keep their original wording. They
record what was approved when, and rewriting them would falsify an audit trail rather than
update a posture.

### The Python wrapper and the mapper guide catch up to what shipped

- `EthosCli.verify` and `EthosCli.anchor` returned the in-toto Statement while their
Expand Down
4 changes: 2 additions & 2 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ On G2/G3 failure, G1 retry failure, or decider-selected G1 fallback, Ethos pivot

---

## 8. Milestones D-E - Weeks 23-40 (plan-level public-beta checkpoint)
## 8. Milestones D-E - Weeks 23-40 (plan-level public checkpoint)

### Milestone D (weeks 23-30): Agents And Verification (PRD 13-D)

Expand All @@ -320,7 +320,7 @@ On G2/G3 failure, G1 retry failure, or decider-selected G1 fallback, Ethos pivot
| WS-SURFACES + WS-CONTRACTS | Stable CLI/Python docs; Node beta docs and MCP experimental docs only if staffed or accepted by release-scope ADR; lightweight LangChain/LlamaIndex examples over Python API; schema compatibility tests; determinism CI hardened; Windows x64 determinism green or release re-scoped; release artifacts for target platforms (footprint check as release gate); project-maintained PDFium Phase 2 builds from `pdfium.googlesource.com` with pinned revision, flags, toolchain, patches, and hashes | Users install stable CLI/Python, parse, inspect, chunk, verify born-digital PDFs; any Node/MCP status is explicit; Public Beta does not ship on Phase 1 PDFium binaries; unresolved Windows determinism divergence blocks or re-scopes Public Beta | 6.1, 13-E |
| Gate | **Release 1 claim audit**: every included 4.1 stable capability demonstrably present (Rust core, stable CLI, stable Python, canonical JSON, deterministic md, txt, chunks, page selection, rotation/coords, failure detection, spans, headings/lists/reading order, simple tables, non-text region coordinates, security report, verification report, parser-agnostic verification, debug overlay, crop API (`crop_element`, per 13-D), LiteParse-inclusive harness, launch examples); Node beta and MCP experimental either have smoke tests with explicit labels or are removed from public claims by ADR - checklist in the release PR | Public "Release 1" only after audit passes; optional surfaces are labeled or explicitly out of scope | 4.1, 11.4, 13-D |

**Public-beta checkpoint (week 40, plan-level):** A-E complete; public beta live. Milestone F (Release 2 enrichment: complex tables, formula/LaTeX, chart classification, optional enrichment modules - PRD 13-F) is scoped *after* E from fixtures gathered during beta. Platform/hosted adoption is out of scope here.
**Public checkpoint (week 40, plan-level):** A-E complete; public surfaces live. Milestone F (Release 2 enrichment: complex tables, formula/LaTeX, chart classification, optional enrichment modules - PRD 13-F) is scoped *after* E from fixtures gathered during beta. Platform/hosted adoption is out of scope here.

---

Expand Down
Loading
Loading