From c6f078f71f32d875d5e2f4d14d291bd3aad7930d Mon Sep 17 00:00:00 2001 From: arpan Date: Mon, 14 Sep 2026 23:31:15 +0530 Subject: [PATCH 1/2] ROADMAP: v0.11 shipped, and the three sentences that did not survive the build Exit criteria against what actually ran, not against what the line promised: five released wheels rather than fixtures, the released 0.10.0 from PyPI rather than a store this build wrote and called 0.10.0's, and two prunes racing under the multi-process standard against a real Postgres server. Three sentences are reconciled rather than quietly edited. The anchor does not detect an append, and the bullet said "erased or appended" until today. Coverage does not come from events, because `ACTION_PROPOSED` carries an `action_hash` and nothing that maps it back to a name. And `CONTROL-MAPPING.md` is still not written, which the v0.11 line cited in the present tense. Readiness re-measured, and the version moves to 0.11.0. Signed-off-by: arpan --- docs.mdx | 4 ++-- docs/ROADMAP.md | 34 +++++++++++++++++++++++++++++++++- docs/production/index.mdx | 4 ++-- generated/readiness.full.mdx | 4 ++-- generated/readiness.json | 6 +++--- generated/readiness.mdx | 4 ++-- generated/readiness.readme.md | 4 ++-- 7 files changed, 46 insertions(+), 14 deletions(-) diff --git a/docs.mdx b/docs.mdx index 01463cf..311ad79 100644 --- a/docs.mdx +++ b/docs.mdx @@ -218,8 +218,8 @@ the framework's own interrupt, and a framework with no such primitive does not n ## Where it stands {/* 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,201 tests**, every version specified before it was written and every requirement mutation-tested. +- **Version 0.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. +- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. - **32 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/ROADMAP.md b/docs/ROADMAP.md index 3cc19e8..6f29788 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -371,7 +371,7 @@ raises. The upgrade was checked against the **released** 0.9.0 from PyPI rather Standards: A2A, as code. No conformance claim. -## v0.11 — Evidence +## v0.11 — Evidence · shipped 2026-09-14 One question: can the record be trusted after the fact, and kept? @@ -384,6 +384,38 @@ One question: can the record be trusted after the fact, and kept? **Does not close.** Authorship. An anchor proves the log existed in this form at that time; it does not prove who wrote it, and a malicious administrator who rewrites everything before the next anchor is still out of scope. Signed receipts stay off the roadmap for the reason `SPEC-v0.6.md` §11 gives. +Exit criteria met: `ctrlrun.guarantees/v7` with `G28` to `G32` each grading `PASS` and each grading +the same under `--only` as in a full run; `examples/anchored-chain` exercises an anchor and prints +what one does **not** prove; a chain written by the **released** 0.6.1, 0.7.0, 0.8.0, 0.9.0 and +0.10.0 wheels verifies end to end across five receipt schema versions; a prune across a checkpoint +verifies and anchors that checkpoint before deleting anything; a held range refuses to prune; and +two prunes racing under the multi-process standard against Postgres leave no break the store did not +already have. The upgrade was checked against the **released** 0.10.0 from PyPI rather than a +fixture: 0.11.0 migrates the store, the chain verifies across the boundary, and 0.10.0 then refuses +it with `SchemaMismatch` rather than corrupting it. + +**Reconciled against what shipped**, because three sentences above were written before the code +existed and two of them were wrong. + +- **The anchor detects truncation and NOT append**, and the bullet above said "erased or appended" + until 2026-09-14. A forged receipt lands at head + 1, above every anchored `seq`, so nothing stops + reproducing and the next anchor freezes it like any other. `T531` runs a forged append and + requires both reports to stay clean, so the limit is a tested property rather than a sentence + somebody has to remember. +- **Enforcement coverage does not come "from events already written."** `ACTION_PROPOSED` carries an + `action_hash` and nothing that maps it back to a name. It comes from receipts, which every decided + action leaves, **a denial included** -- so an action that is always denied counts as exercised. +- **`ctrlrun scan --coverage` is the surface**, and `docs/CONTROL-MAPPING.md` is still not written. + The v0.11 line cited it in the present tense; roadmap line 136 says it is written only when a + design partner asks, and none has. + +Three surfaces this milestone amends rather than adds to, each named because an amendment to a +frozen surface is not a patch: `StateStore` gains anchor, checkpoint and hold methods +(`SPEC-v0.6.md` §9.2), `StateStore.receipts()` may now hand back an `UnreadableReceipt` instead of +raising, and `verify_chain` seeds from a checkpoint where a store has one. **`CHAIN_BREAKS` is +unchanged and stays closed at six**: the anchor has its own set, because putting its kinds in +`CHAIN_BREAKS` would fail `G11`'s control with `control failed` on every anchoring deployment. + Do not build: a SIEM · dashboards over receipts · a receipt query language · export formats beyond JSON and OTel. Exit: **the truncation case** that `SPEC-v0.6.md` §6.4 lists as undetected now detects, with the anchor as the positive control and the two-statement attack as the scenario (append is **not** in this criterion, and §2.4 of `SPEC-v0.11.md` says why); a prune across a checkpoint verifies, and the prune's checkpoint is anchored before anything is deleted; a held range refuses to prune; a chain written across **five** receipt schema versions verifies end to end, and the checkpoint receipt of a prune carries the version current when it was written. diff --git a/docs/production/index.mdx b/docs/production/index.mdx index 6bb76fb..0a7c0fc 100644 --- a/docs/production/index.mdx +++ b/docs/production/index.mdx @@ -27,8 +27,8 @@ need. `test_the_first_line_of_the_section_says_which_store_and_why` asserts the ## Where it stands {/* 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,201 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). +- **Version 0.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. +- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). - **32 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.full.mdx b/generated/readiness.full.mdx index 144e7cf..b743a19 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,201 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). +- **Version 0.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. +- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). - **32 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 96c0544..72b84e7 100644 --- a/generated/readiness.json +++ b/generated/readiness.json @@ -9,7 +9,7 @@ "3.14" ] }, - "released": "0.10.0", + "released": "0.11.0", "soak": { "actions": 889735, "backend": "postgres", @@ -18,6 +18,6 @@ "positive_control": true, "unexplained": 0 }, - "tests": 6201, - "version": "0.10.0" + "tests": 6204, + "version": "0.11.0" } diff --git a/generated/readiness.mdx b/generated/readiness.mdx index 552c0be..4102712 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,201 tests**, every version specified before it was written and every requirement mutation-tested. +- **Version 0.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. +- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. - **32 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 7e2f5f3..34b5f7b 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,201 tests**, every version specified before it was written and every requirement mutation-tested. +- **Version 0.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. +- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. - **32 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 436d8696fb79cb464b62274a5e3b98cd25b9d24e Mon Sep 17 00:00:00 2001 From: arpan Date: Mon, 14 Sep 2026 23:35:43 +0530 Subject: [PATCH 2/2] The release pass: what an operator now schedules, and three stale transcripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `operations.mdx` is the page this milestone most changes and said nothing about either new command. Anchoring and pruning are the two things v0.11 gives an operator to run, and both are runs **their** scheduler makes: nothing sweeps, nothing reaps, and no hold expires, which is the same rule about a timer that `SPEC-v0.9.md` §4 applied to a budget hold. The interval is the claim. An anchor freezes a prefix, so the window you are exposed to is `(last anchored seq, current head]`, and that number is what to quote rather than any sentence about tamper-evidence. Three pages quoted a verify transcript headed `ctrlrun 0.10.0`. The guard that runs verify and compares caught all three. `ROADMAP.md` gains the line about retention shipping twice: the review the build order required for the prune found seven defects, and the merge did not wait for it. `SPEC-v0.11.md` §13.4 has all seven. Readiness re-measured at 6,221 against a checkout carrying the extras CI installs, and `CLAIMS.md` needed no repointing. Signed-off-by: arpan --- docs.mdx | 2 +- docs/ROADMAP.md | 5 +++++ docs/cookbook/verify-in-github-actions.mdx | 2 +- docs/guides/verify-in-ci.mdx | 2 +- docs/production/index.mdx | 2 +- docs/production/operations.mdx | 21 ++++++++++++++++++--- docs/verify.md | 2 +- generated/readiness.full.mdx | 2 +- generated/readiness.json | 2 +- generated/readiness.mdx | 2 +- generated/readiness.readme.md | 2 +- tests/test_release_documents.py | 7 ++++++- 12 files changed, 38 insertions(+), 13 deletions(-) diff --git a/docs.mdx b/docs.mdx index 311ad79..8e702a7 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.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. +- **6,221 tests**, every version specified before it was written and every requirement mutation-tested. - **32 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/ROADMAP.md b/docs/ROADMAP.md index 6f29788..64bc161 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -408,6 +408,11 @@ existed and two of them were wrong. - **`ctrlrun scan --coverage` is the surface**, and `docs/CONTROL-MAPPING.md` is still not written. The v0.11 line cited it in the present tense; roadmap line 136 says it is written only when a design partner asks, and none has. +- **Retention shipped twice.** The build order made an independent review required for the prune, + *the one not to skip*, and the merge did not wait for it. The review found seven defects, the + first of which made a forged checkpoint launderable with one row in the store's own `anchors` + table, and the fixes went in as a second pull request. `SPEC-v0.11.md` §13.4 records all seven + and the rule this milestone adds: **a required review is a merge gate, not a step in the item.** Three surfaces this milestone amends rather than adds to, each named because an amendment to a frozen surface is not a patch: `StateStore` gains anchor, checkpoint and hold methods diff --git a/docs/cookbook/verify-in-github-actions.mdx b/docs/cookbook/verify-in-github-actions.mdx index 8116a4f..a1dd3be 100644 --- a/docs/cookbook/verify-in-github-actions.mdx +++ b/docs/cookbook/verify-in-github-actions.mdx @@ -62,7 +62,7 @@ by tag where you want a ref nobody can move. The agent sees nothing; this is the operator's check. The build sees: ```text -CTRLRun verify — ctrlrun 0.10.0, catalogue ctrlrun.guarantees/v7 +CTRLRun verify — ctrlrun 0.11.0, catalogue ctrlrun.guarantees/v7 policy /Users/arpanghoshal/ctrlrun-project/wt/v11-i3/examples/cookbook/verify-in-github-actions/ctrlrun.yaml (ctrlrun.policy/v2, mode: enforce) authority none store sqlite, scratch (created and destroyed for this run) diff --git a/docs/guides/verify-in-ci.mdx b/docs/guides/verify-in-ci.mdx index 7f2b17c..52348eb 100644 --- a/docs/guides/verify-in-ci.mdx +++ b/docs/guides/verify-in-ci.mdx @@ -32,7 +32,7 @@ guarantees pass. ``` ```text - CTRLRun verify — ctrlrun 0.10.0, catalogue ctrlrun.guarantees/v7 + CTRLRun verify — ctrlrun 0.11.0, catalogue ctrlrun.guarantees/v7 policy /Users/arpanghoshal/ctrlrun-project/wt/v11-i3/examples/cookbook/verify-in-github-actions/ctrlrun.yaml (ctrlrun.policy/v2, mode: enforce) authority none store sqlite, scratch (created and destroyed for this run) diff --git a/docs/production/index.mdx b/docs/production/index.mdx index 0a7c0fc..c4355fc 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.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). +- **6,221 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). - **32 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/production/operations.mdx b/docs/production/operations.mdx index 32dabae..3d29d7c 100644 --- a/docs/production/operations.mdx +++ b/docs/production/operations.mdx @@ -49,11 +49,24 @@ and there will not be one. - **A reporting role still needs `CREATE` on the schema.** Opening the store migrates it, so a read-only role cannot run `--verify-chain` — it is refused before a receipt is read, naming the missing privilege. Read-only is for your own queries against the tables, not for the CLI. +- **Anchor on an interval you choose, and say what it is.** `ctrlrun anchor --provider ...` + records the chain's head outside the database, which is what makes a truncation detectable at + all: the head that would catch one is otherwise a row in the same database. The window you are + exposed to is `(last anchored seq, current head]`, so the interval **is** the claim, and it is + the number to quote rather than any sentence about tamper-evidence. See + [anchoring](/docs/production/anchoring). +- **Prune with a window, not with a `DELETE`.** `ctrlrun prune` removes a prefix and leaves a + checkpoint the reader seeds from; deleting receipts yourself is detected as a break, by design. + It refuses rather than warns, and there is no `--force`. See + [retention](/docs/production/retention). ## What this does not do - **There is nothing to run.** No agent, no sidecar, no scheduler. Every command above is a - one-shot read of the store. + one-shot read of the store, and the two that write — `anchor` and `prune` — run when **your** + scheduler runs them. Nothing sweeps, nothing reaps, and **no hold expires**: a hold that lapsed + on a timer would release evidence on a schedule nobody reviewed, so a person places it and a + person ends it. - **It does not retry for you.** A proven non-execution leaves the key retryable — the next attempt is admitted rather than refused — and nothing performs that attempt but your code. Every other outcome refuses one. @@ -64,11 +77,13 @@ and there will not be one. **Verified by** `T160` and `T177d` — an expired lease frees nothing, and displaying it changes nothing — `T161` for the two authorities that can move an unknown outcome and what each is -recorded as, and `T177c` for the CLI surface these commands come from, asserted against the -command list so a new one cannot appear unnoticed. +recorded as, `T545c` for the hold that no timer lifts, and `T177c` for the CLI surface these +commands come from, asserted against the command list so a new one cannot appear unnoticed. ## Next - [Recovery after a crash](/docs/production/recovery): why nothing sweeps. +- [Anchoring](/docs/production/anchoring) and [retention](/docs/production/retention): the two + things this milestone gives an operator to schedule. - [Reconcile automatically](/docs/guides/reconcile-automatically): the hook that answers without a person. - [Get started](/docs/get-started/quickstart) · [Why](/docs/why). diff --git a/docs/verify.md b/docs/verify.md index b10b59c..1da34ff 100644 --- a/docs/verify.md +++ b/docs/verify.md @@ -14,7 +14,7 @@ what could not be tested at all. ```console $ ctrlrun verify -CTRLRun verify — ctrlrun 0.10.0, catalogue ctrlrun.guarantees/v7 +CTRLRun verify — ctrlrun 0.11.0, catalogue ctrlrun.guarantees/v7 policy examples/authority/payments.yaml (ctrlrun.policy/v7, mode: enforce) authority same document, 3 grants store sqlite, scratch (created and destroyed for this run) diff --git a/generated/readiness.full.mdx b/generated/readiness.full.mdx index b743a19..b14d7bf 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.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). +- **6,221 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built). - **32 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 72b84e7..012afe1 100644 --- a/generated/readiness.json +++ b/generated/readiness.json @@ -18,6 +18,6 @@ "positive_control": true, "unexplained": 0 }, - "tests": 6204, + "tests": 6221, "version": "0.11.0" } diff --git a/generated/readiness.mdx b/generated/readiness.mdx index 4102712..322708b 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.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. +- **6,221 tests**, every version specified before it was written and every requirement mutation-tested. - **32 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 34b5f7b..ba89b4b 100644 --- a/generated/readiness.readme.md +++ b/generated/readiness.readme.md @@ -1,6 +1,6 @@ - **Version 0.11.0**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14. -- **6,204 tests**, every version specified before it was written and every requirement mutation-tested. +- **6,221 tests**, every version specified before it was written and every requirement mutation-tested. - **32 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/tests/test_release_documents.py b/tests/test_release_documents.py index 61ddb0a..0a2db31 100644 --- a/tests/test_release_documents.py +++ b/tests/test_release_documents.py @@ -93,7 +93,12 @@ def _load(name: str) -> set[str]: # not do". Both halves survived the cut, which is the half §6.4 cares about: the chain # detects alteration, and the same sentence says alteration is not authorship. "README.md": ( - "is detected. They are not signed: alteration is not authorship. The badge above means the", + # v0.11 rewrapped this paragraph: the chain detects alteration, and the sentence beside + # it now names the two things it does **not** detect, a truncation at the end and a + # forged append, and says `ctrlrun anchor` is what closes them. Only this line carries a + # word the scan looks for, and the list must not carry lines that do not: T180's staleness + # check fails on an entry matching nothing, which is how a softened allow-list is caught. + "signed: alteration is not authorship. The badge above means the", ), "CHANGELOG.md": ( '- **`docs/docs/ROADMAP.md`\'s v0.6 bullet said "receipt integrity (hash chain / signatures)", and the', # noqa: E501