From 133b6e2e7f44b13de9192945096535c48fdf0205 Mon Sep 17 00:00:00 2001 From: arpan Date: Mon, 14 Sep 2026 05:10:51 +0530 Subject: [PATCH 1/2] Regenerate for needs_approval's new signature, and readiness at 6,080 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pairs with ctrlrun#191, which builds two of SPEC-v0.10 §9.4's three rows. `needs_approval` now takes `task=` and `hop=`, so its API page picks up the signature and the paragraph saying what they are for. `banner.mdx` moves with it because the two share a source line range. Readiness 6,070 to 6,080. All seven generators, 19 recipes 0 drifted, 83 pages, claims re-pointed 0 unresolved 0, and the kernel worktree came back clean after the cookbook write. --- docs.mdx | 2 +- docs/production/index.mdx | 2 +- docs/reference/api/banner.mdx | 2 +- docs/reference/api/needs_approval.mdx | 9 ++++++++- generated/readiness.full.mdx | 2 +- generated/readiness.json | 2 +- generated/readiness.mdx | 2 +- generated/readiness.readme.md | 2 +- 8 files changed, 15 insertions(+), 8 deletions(-) diff --git a/docs.mdx b/docs.mdx index f343dd4..9ffb2d3 100644 --- a/docs.mdx +++ b/docs.mdx @@ -219,7 +219,7 @@ the framework's own interrupt, and a framework with no such primitive does not n {/* generated from the suite, pyproject and the soak (mdx) — run the generator */} - **Version 0.10.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,070 tests**, every version specified before it was written and every requirement mutation-tested. +- **6,080 tests**, every version specified before it was written and every requirement mutation-tested. - **27 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. - **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. - **Soaked for 20m 0s on postgres**: 889,735 actions, 0 unattributed ambiguous outcomes, positive control fired. Nothing here establishes what only accumulates over days. [What it does not establish](https://ctrlrun.dev/docs/production/soak). diff --git a/docs/production/index.mdx b/docs/production/index.mdx index 1165fe8..20df822 100644 --- a/docs/production/index.mdx +++ b/docs/production/index.mdx @@ -28,7 +28,7 @@ need. `test_the_first_line_of_the_section_says_which_store_and_why` asserts the {/* generated from the suite, pyproject and the soak (full) — run the generator */} - **Version 0.10.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,070 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). +- **6,080 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). - **27 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. [Read more](/docs/security/verify-guarantees). - **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. [Read more](/docs/production/postgres). - **Soaked for 20m 0s on postgres**: 889,735 actions, 0 unattributed ambiguous outcomes, positive control fired. Nothing here establishes what only accumulates over days. [Read more](/docs/production/soak). diff --git a/docs/reference/api/banner.mdx b/docs/reference/api/banner.mdx index 92e33ba..9f01813 100644 --- a/docs/reference/api/banner.mdx +++ b/docs/reference/api/banner.mdx @@ -5,7 +5,7 @@ description: "Log SPEC-v0.3 §6.5's observe banner, once per `Control`. An adapt {/* generated by tools/docs_audit/render_api.py from the docstrings — edit the docstring, never this page */} -`ctrlrun.banner` — function, defined at `src/ctrlrun/adapter.py:475` +`ctrlrun.banner` — function, defined at `src/ctrlrun/adapter.py:484` ```python from ctrlrun import banner diff --git a/docs/reference/api/needs_approval.mdx b/docs/reference/api/needs_approval.mdx index 86d5b20..eafed2c 100644 --- a/docs/reference/api/needs_approval.mdx +++ b/docs/reference/api/needs_approval.mdx @@ -13,7 +13,7 @@ from ctrlrun import needs_approval ```python -def needs_approval(control: Control, action: str, arguments: Mapping[str, Any], *, resource: str | None = None) -> bool +def needs_approval(control: Control, action: str, arguments: Mapping[str, Any], *, resource: str | None = None, task: str | None = None, hop: str | None = None) -> bool ``` Does this call need a human? For a framework that asks before it invokes (SPEC-v0.5 §3.5). @@ -42,6 +42,13 @@ it to belongs in the evidence log. matters: authority matches on resource patterns (SPEC-v0.3 §4.2), so a predicate that skipped it would evaluate a different action from the one that runs. +`task` and `hop` are that same argument one frame further out (SPEC-v0.10 §9). Without them +this predicate evaluates against the receiver's **whole candidate set** while `execute` +evaluates against the hop **alone** (§2.3), so it answers "no human needed" for a call +`execute` then refuses. That is not a wider grant -- `Control.execute` is the enforcement +point and decides against the hop either way -- but it costs the framework its own approval +item, and a human is not asked before an invocation that then fails. + ## Next - [Python API index](/docs/reference/api/index). diff --git a/generated/readiness.full.mdx b/generated/readiness.full.mdx index 3fbafe3..f797016 100644 --- a/generated/readiness.full.mdx +++ b/generated/readiness.full.mdx @@ -1,6 +1,6 @@ {/* generated from the suite, pyproject and the soak (full) — run the generator */} - **Version 0.10.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,070 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). +- **6,080 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). - **27 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. [Read more](/docs/security/verify-guarantees). - **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. [Read more](/docs/production/postgres). - **Soaked for 20m 0s on postgres**: 889,735 actions, 0 unattributed ambiguous outcomes, positive control fired. Nothing here establishes what only accumulates over days. [Read more](/docs/production/soak). diff --git a/generated/readiness.json b/generated/readiness.json index d031ea6..24cdd23 100644 --- a/generated/readiness.json +++ b/generated/readiness.json @@ -18,6 +18,6 @@ "positive_control": true, "unexplained": 0 }, - "tests": 6070, + "tests": 6080, "version": "0.10.0" } diff --git a/generated/readiness.mdx b/generated/readiness.mdx index fead10d..5d095a0 100644 --- a/generated/readiness.mdx +++ b/generated/readiness.mdx @@ -1,6 +1,6 @@ {/* generated from the suite, pyproject and the soak (mdx) — run the generator */} - **Version 0.10.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,070 tests**, every version specified before it was written and every requirement mutation-tested. +- **6,080 tests**, every version specified before it was written and every requirement mutation-tested. - **27 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. - **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. - **Soaked for 20m 0s on postgres**: 889,735 actions, 0 unattributed ambiguous outcomes, positive control fired. Nothing here establishes what only accumulates over days. [What it does not establish](https://ctrlrun.dev/docs/production/soak). diff --git a/generated/readiness.readme.md b/generated/readiness.readme.md index 4113bc2..2539a25 100644 --- a/generated/readiness.readme.md +++ b/generated/readiness.readme.md @@ -1,6 +1,6 @@ - **Version 0.10.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,070 tests**, every version specified before it was written and every requirement mutation-tested. +- **6,080 tests**, every version specified before it was written and every requirement mutation-tested. - **27 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. - **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. - **Soaked for 20m 0s on postgres**: 889,735 actions, 0 unattributed ambiguous outcomes, positive control fired. Nothing here establishes what only accumulates over days. [What it does not establish](https://ctrlrun.dev/docs/production/soak). From 619d555761d5dc1a446c3b4b175c331a805b2735 Mon Sep 17 00:00:00 2001 From: arpan Date: Mon, 14 Sep 2026 05:14:54 +0530 Subject: [PATCH 2/2] CI re-measures the test count, which its own docstring said it already did `render_readiness.py`'s docstring calls `--check` "what CI runs". CI did not run it. That is the sentence one level up from the comment beside the audit step: a guard CI does not run is prose. The count is the one figure on the site that is a **measurement** rather than a claim, and nothing in CI re-took it. `test_the_readiness_block_is_the_generators_in_every_place_it_appears` compares the embedded block against the stored `generated/readiness.json`, so the page and the state file agreed with each other while both drifted away from the library. Today they are four apart: the site says 6,066, ctrlrun `main` collects 6,070. **It cannot flap between a paired kernel and docs merge**, which is why it is safe to add mid-stack. The count is a floor: `--check` fails when the suite has *fewer* tests than the page claims and passes when it has more, so a kernel PR that adds tests leaves docs `main` green until its docs pair lands. Verified both ways against real checkouts -- docs `main` against kernel `main`: 0 drifted; this branch against ctrlrun#191: 0 drifted. `test_ci_runs_the_three_checks_and_the_drift_check` reads the workflow, so the list and the job cannot disagree. --- .github/workflows/ci.yml | 14 ++++++++++++-- tests/test_docs_audit.py | 11 ++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 903afe3..cfa9db7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,9 +91,18 @@ jobs: CTRLRUN_SOURCE: ${{ github.workspace }}/ctrlrun run: ./scripts/check.sh - # The four drift checks, named individually because `STYLE.md` says the CI job runs them - # and `test_ci_runs_the_three_checks_and_the_drift_check` reads this file to prove it. + # The drift checks, named individually because `STYLE.md` says the CI job runs them and + # `test_ci_runs_the_three_checks_and_the_drift_check` reads this file to prove it. # A guard CI does not run is prose. + # + # `render_readiness.py --check` joined them on 2026-09-14. Its own docstring called it + # "what CI runs" and CI did not run it, which is the same sentence one level up: the test + # count is the one figure on the site that is a measurement rather than a claim, and the + # pytest check on it compares the embedded block against the *stored* `readiness.json` + # rather than against the suite, so the two agreed with each other while both drifted away + # from the library. It cannot flap between a paired kernel and docs merge, because the + # count is a **floor**: it fails when the suite has fewer tests than the page claims, and + # passes when it has more. - name: The documentation audit working-directory: ctrlrun-docs env: @@ -103,3 +112,4 @@ jobs: python tools/docs_audit/lint.py python tools/docs_audit/links.py python tools/docs_audit/render_capabilities.py --check + python tools/docs_audit/render_readiness.py --check diff --git a/tests/test_docs_audit.py b/tests/test_docs_audit.py index c1c4324..f70c19d 100644 --- a/tests/test_docs_audit.py +++ b/tests/test_docs_audit.py @@ -660,7 +660,16 @@ def test_ci_runs_the_three_checks_and_the_drift_check(): """`STYLE.md` says the `docs` job runs them. A guard that CI does not run is prose.""" workflow = (REPO_ROOT / ".github" / "workflows" / "ci.yml").read_text(encoding="utf-8") - for script in ("snippets.py", "lint.py", "links.py", "render_capabilities.py --check"): + for script in ( + "snippets.py", + "lint.py", + "links.py", + "render_capabilities.py --check", + # The count is a measurement, and until 2026-09-14 nothing in CI re-took it: the pytest + # check compares the embedded block against the stored `readiness.json`, so the two + # agreed with each other while both drifted from the library. + "render_readiness.py --check", + ): assert f"python tools/docs_audit/{script}" in workflow, script