fix(ci): CLOUD-1672 pin mise to the version the tree declares, and CLOUD-1477 warm the x64 ci- family - #914
Conversation
|
Warning Review limit reachedNext included review available in 47 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (34)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (27)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe workflows pin mise to Priority: ⬆️ High — Prioritize the CI and release workflow changes because mise failures were blocking artifact jobs and producing releases with zero binaries, while the x64 cache fix affects recurring build duration. Severity of issue fixed: High Merge Risk: ⚪ Minimal · up to The cache-warming, policy, and workflow-version changes are consistent at the current head, with no actionable merge-blocking issue identified. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
38dff57 to
8c64199
Compare
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
ci- family a warm writer, and gate the orphaningci- family
8c64199 to
52ec48b
Compare
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
The pin half of CLOUD-1672 landed across 24 workflows and nothing held it there. This is the mechanism, so the rule is not prose (non-negotiable 2). `action-version-matches-the-pin` refuses a workflow step installing the toolchain at a version the tree does not pin: `job pin other` where a declared version disagrees with the `[[provision]]` row, `job pin missing` where the step declares none and hands the choice to the installer. The comparison is against the committed row and never a literal -- a module carrying `2026.9.1` would be a THIRD authority and would go stale the first time the pin moved. Both documents are found by SHAPE, never by filename: a document carrying `jobs`, a document carrying `provision`. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row's `sources` is where this consumer says which of its files those are. No provision row for the tool means the row ABSTAINS rather than refuses. A project that pins nothing has nothing to disagree with, and refusing there would be a verdict about their configuration instead of about drift between two of their own statements. THE ENGINE HALF: A MANIFEST DECLARES A SCOPE PER MODULE. `Manifest.scope` said a preset decides exactly one surface -- true of every preset that existed when it was written, false the moment a subject has something to say about both. `mise` is that subject: whether an agent reproduces a task's argv is a question about a CALL, whether the toolchain a workflow installs matches the pin is a question about the TREE. They are one preset because they are one concern, and a consumer should not have to know the engine once could not express that. Two constraints assumed the old shape and both now key on the pair: - the load-time scope check compared one manifest scope for equality; it asks `decides(scope)` now, and names the scopes the preset does decide. - the duplicate-registration check keyed on the source name, so the second row enabling one preset at the other scope read as dead config. It is not: each row compiles only the modules at its own scope, so they share a name and decide disjoint surfaces. Selecting modules by scope is load-bearing rather than tidy. A tree module compiled onto the call surface reads keys the engine never builds there, Rego reads undefined as "does not hold", and the result is a dead gate byte-identical to a clean tree. `check_tree_paths_are_emittable` catches that today; this keeps the case from arising rather than relying on a downstream guard to notice. VERIFIED, AND THE REAL-TREE ARM IS THE ONE THAT COUNTS. `policy test` 64 bundles, 814 passed; the four preset tiers 39/39. Both of those supply their own pin document, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` -- and if it did not, the pin would be absent, the module would abstain by design, and the gate would report clean forever. So it was driven over this checkout: clean as committed, and moving one workflow's version produced `.github/workflows/scorecard.yml:53 action-version-matches-the-pin`, exit 2, pointer-only. The file was restored with `git checkout --` and the diff is unchanged. `a_drifted_version_in_this_repository_is_refused` is that same proof as a standing case. Refs: CLOUD-1672, CLOUD-1181, CLOUD-404 Admits: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3 Admits-answer-lost: The gate half of CLOUD-1672 does not run. The pin is landed across all 24 workflows but nothing holds it there, so the next architecture move, Renovate bump or hand edit silently reintroduces the drift that published v0.0.152 with zero binaries. A rule without its mechanism is half a change by this repository's own non-negotiable rule 2. Admits-answer-precondition: CLOUD-1672 gate half. The redirect for `batten.toml` is "change it in a pull request" with `config-lint` as the check before it lands — a statement about how the change must LAND, not a surface that can express it: only a direct write can add a `[[rule]]` row. The row enables the `mise` preset at tree scope with the `sources` globs the predicate reads; without it the module ships and decides nothing, which is the dead-gate shape the whole row exists to close. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the `ci-hygiene` row was read as the shape to copy, since it is the existing tree-scoped preset row carrying workflow `sources` and `line_sources`. Admits: 6e8cd01a0028a1c5510ed46c8c6539d3976ffc6486db86b606b140723b76865f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 3b025bfdaaedf9f46a55c4b09fba627a7d599c231956e6730c43863d886b4d05 Admits-author: alec@wenzowski.com Admits-prev: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-answer-lost: The gate ships unproven on the surface that matters. The load-time and compiled tiers both supply their own fixture documents, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` to the module — and if it does not, the pin document is absent, the module abstains BY DESIGN, and the gate reports clean forever over a tree it never compared. That is the exact dead-gate shape this row exists to close, reachable only through the row's own configuration. Admits-answer-precondition: A VERIFICATION WRITE, reverted in the same turn. CLOUD-1672's new gate reports clean over this tree, and clean is byte-identical to a dead gate — so one workflow's `version:` is being changed to a wrong value to confirm the predicate names it, then changed straight back. Only a direct write can do that; no read surface can make a gate fire. Nothing of it reaches a commit: the file is restored with `git checkout --` before the tree is staged, and the diff will show it unchanged. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s new `mise-preset-tree` row and its `sources` list were read, and reading them is what identified the glob as the one thing no fixture can verify.
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
52ec48b to
10dbdff
Compare
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
The pin half of CLOUD-1672 landed across 24 workflows and nothing held it there. This is the mechanism, so the rule is not prose (non-negotiable 2). `action-version-matches-the-pin` refuses a workflow step installing the toolchain at a version the tree does not pin: `job pin other` where a declared version disagrees with the `[[provision]]` row, `job pin missing` where the step declares none and hands the choice to the installer. The comparison is against the committed row and never a literal -- a module carrying `2026.9.1` would be a THIRD authority and would go stale the first time the pin moved. Both documents are found by SHAPE, never by filename: a document carrying `jobs`, a document carrying `provision`. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row's `sources` is where this consumer says which of its files those are. No provision row for the tool means the row ABSTAINS rather than refuses. A project that pins nothing has nothing to disagree with, and refusing there would be a verdict about their configuration instead of about drift between two of their own statements. THE ENGINE HALF: A MANIFEST DECLARES A SCOPE PER MODULE. `Manifest.scope` said a preset decides exactly one surface -- true of every preset that existed when it was written, false the moment a subject has something to say about both. `mise` is that subject: whether an agent reproduces a task's argv is a question about a CALL, whether the toolchain a workflow installs matches the pin is a question about the TREE. They are one preset because they are one concern, and a consumer should not have to know the engine once could not express that. Two constraints assumed the old shape and both now key on the pair: - the load-time scope check compared one manifest scope for equality; it asks `decides(scope)` now, and names the scopes the preset does decide. - the duplicate-registration check keyed on the source name, so the second row enabling one preset at the other scope read as dead config. It is not: each row compiles only the modules at its own scope, so they share a name and decide disjoint surfaces. Selecting modules by scope is load-bearing rather than tidy. A tree module compiled onto the call surface reads keys the engine never builds there, Rego reads undefined as "does not hold", and the result is a dead gate byte-identical to a clean tree. `check_tree_paths_are_emittable` catches that today; this keeps the case from arising rather than relying on a downstream guard to notice. VERIFIED, AND THE REAL-TREE ARM IS THE ONE THAT COUNTS. `policy test` 64 bundles, 814 passed; the four preset tiers 39/39. Both of those supply their own pin document, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` -- and if it did not, the pin would be absent, the module would abstain by design, and the gate would report clean forever. So it was driven over this checkout: clean as committed, and moving one workflow's version produced `.github/workflows/scorecard.yml:53 action-version-matches-the-pin`, exit 2, pointer-only. The file was restored with `git checkout --` and the diff is unchanged. `a_drifted_version_in_this_repository_is_refused` is that same proof as a standing case. Refs: CLOUD-1672, CLOUD-1181, CLOUD-404 Admits: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3 Admits-answer-lost: The gate half of CLOUD-1672 does not run. The pin is landed across all 24 workflows but nothing holds it there, so the next architecture move, Renovate bump or hand edit silently reintroduces the drift that published v0.0.152 with zero binaries. A rule without its mechanism is half a change by this repository's own non-negotiable rule 2. Admits-answer-precondition: CLOUD-1672 gate half. The redirect for `batten.toml` is "change it in a pull request" with `config-lint` as the check before it lands — a statement about how the change must LAND, not a surface that can express it: only a direct write can add a `[[rule]]` row. The row enables the `mise` preset at tree scope with the `sources` globs the predicate reads; without it the module ships and decides nothing, which is the dead-gate shape the whole row exists to close. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the `ci-hygiene` row was read as the shape to copy, since it is the existing tree-scoped preset row carrying workflow `sources` and `line_sources`. Admits: 6e8cd01a0028a1c5510ed46c8c6539d3976ffc6486db86b606b140723b76865f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 3b025bfdaaedf9f46a55c4b09fba627a7d599c231956e6730c43863d886b4d05 Admits-author: alec@wenzowski.com Admits-prev: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-answer-lost: The gate ships unproven on the surface that matters. The load-time and compiled tiers both supply their own fixture documents, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` to the module — and if it does not, the pin document is absent, the module abstains BY DESIGN, and the gate reports clean forever over a tree it never compared. That is the exact dead-gate shape this row exists to close, reachable only through the row's own configuration. Admits-answer-precondition: A VERIFICATION WRITE, reverted in the same turn. CLOUD-1672's new gate reports clean over this tree, and clean is byte-identical to a dead gate — so one workflow's `version:` is being changed to a wrong value to confirm the predicate names it, then changed straight back. Only a direct write can do that; no read surface can make a gate fire. Nothing of it reaches a commit: the file is restored with `git checkout --` before the tree is staged, and the diff will show it unchanged. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s new `mise-preset-tree` row and its `sources` list were read, and reading them is what identified the glob as the one thing no fixture can verify.
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
The pin half of CLOUD-1672 landed across 24 workflows and nothing held it there. This is the mechanism, so the rule is not prose (non-negotiable 2). `action-version-matches-the-pin` refuses a workflow step installing the toolchain at a version the tree does not pin: `job pin other` where a declared version disagrees with the `[[provision]]` row, `job pin missing` where the step declares none and hands the choice to the installer. The comparison is against the committed row and never a literal -- a module carrying `2026.9.1` would be a THIRD authority and would go stale the first time the pin moved. Both documents are found by SHAPE, never by filename: a document carrying `jobs`, a document carrying `provision`. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row's `sources` is where this consumer says which of its files those are. No provision row for the tool means the row ABSTAINS rather than refuses. A project that pins nothing has nothing to disagree with, and refusing there would be a verdict about their configuration instead of about drift between two of their own statements. THE ENGINE HALF: A MANIFEST DECLARES A SCOPE PER MODULE. `Manifest.scope` said a preset decides exactly one surface -- true of every preset that existed when it was written, false the moment a subject has something to say about both. `mise` is that subject: whether an agent reproduces a task's argv is a question about a CALL, whether the toolchain a workflow installs matches the pin is a question about the TREE. They are one preset because they are one concern, and a consumer should not have to know the engine once could not express that. Two constraints assumed the old shape and both now key on the pair: - the load-time scope check compared one manifest scope for equality; it asks `decides(scope)` now, and names the scopes the preset does decide. - the duplicate-registration check keyed on the source name, so the second row enabling one preset at the other scope read as dead config. It is not: each row compiles only the modules at its own scope, so they share a name and decide disjoint surfaces. Selecting modules by scope is load-bearing rather than tidy. A tree module compiled onto the call surface reads keys the engine never builds there, Rego reads undefined as "does not hold", and the result is a dead gate byte-identical to a clean tree. `check_tree_paths_are_emittable` catches that today; this keeps the case from arising rather than relying on a downstream guard to notice. VERIFIED, AND THE REAL-TREE ARM IS THE ONE THAT COUNTS. `policy test` 64 bundles, 814 passed; the four preset tiers 39/39. Both of those supply their own pin document, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` -- and if it did not, the pin would be absent, the module would abstain by design, and the gate would report clean forever. So it was driven over this checkout: clean as committed, and moving one workflow's version produced `.github/workflows/scorecard.yml:53 action-version-matches-the-pin`, exit 2, pointer-only. The file was restored with `git checkout --` and the diff is unchanged. `a_drifted_version_in_this_repository_is_refused` is that same proof as a standing case. Refs: CLOUD-1672, CLOUD-1181, CLOUD-404 Admits: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3 Admits-answer-lost: The gate half of CLOUD-1672 does not run. The pin is landed across all 24 workflows but nothing holds it there, so the next architecture move, Renovate bump or hand edit silently reintroduces the drift that published v0.0.152 with zero binaries. A rule without its mechanism is half a change by this repository's own non-negotiable rule 2. Admits-answer-precondition: CLOUD-1672 gate half. The redirect for `batten.toml` is "change it in a pull request" with `config-lint` as the check before it lands — a statement about how the change must LAND, not a surface that can express it: only a direct write can add a `[[rule]]` row. The row enables the `mise` preset at tree scope with the `sources` globs the predicate reads; without it the module ships and decides nothing, which is the dead-gate shape the whole row exists to close. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the `ci-hygiene` row was read as the shape to copy, since it is the existing tree-scoped preset row carrying workflow `sources` and `line_sources`. Admits: 6e8cd01a0028a1c5510ed46c8c6539d3976ffc6486db86b606b140723b76865f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 3b025bfdaaedf9f46a55c4b09fba627a7d599c231956e6730c43863d886b4d05 Admits-author: alec@wenzowski.com Admits-prev: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-answer-lost: The gate ships unproven on the surface that matters. The load-time and compiled tiers both supply their own fixture documents, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` to the module — and if it does not, the pin document is absent, the module abstains BY DESIGN, and the gate reports clean forever over a tree it never compared. That is the exact dead-gate shape this row exists to close, reachable only through the row's own configuration. Admits-answer-precondition: A VERIFICATION WRITE, reverted in the same turn. CLOUD-1672's new gate reports clean over this tree, and clean is byte-identical to a dead gate — so one workflow's `version:` is being changed to a wrong value to confirm the predicate names it, then changed straight back. Only a direct write can do that; no read surface can make a gate fire. Nothing of it reaches a commit: the file is restored with `git checkout --` before the tree is staged, and the diff will show it unchanged. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s new `mise-preset-tree` row and its `sources` list were read, and reading them is what identified the glob as the one thing no fixture can verify.
10dbdff to
267bd13
Compare
`batten doctor` reported six checks and none of them asked whether a commit in this clone runs the gate. In the container this repository provisions for itself, those came apart: `git commit` ran neither `pre-commit` nor `commit-msg`, so every commit bypassed the gate while `batten startup` reported every row green. The session-start advisory's "every declared repair has already run this session; what is listed is what it did not fix" was TRUE and useless — the hooks were never in the declared set at all. `mise-tasks/doctor.sh` did see it and emitted two `::error::` lines, which is the CLOUD-1454 shape one layer up: a reporter is not a gate. Worse, its remedy named `.claude/hooks/session-start.sh`, a program 7d18858 deleted, so the refusal was right and its instruction could not be followed — an agent reading it top to bottom gets `No such file or directory` and has to re-read the sentence to find the half that works. Both remedies now name `mise run session:git-hooks`, and a case asserts the named task and hook body resolve in the tree, because prose cannot hold that and a case over the tracked file can. `diagnose_commit_gate` is the predicate, and it is one predicate with two callers: the row the bare report pushes, and the `doctor commit-gate` sub-verb. A second implementation of it would be the defect this change repairs, one layer along — `doctor.sh` and the committed authority disagreeing about what an installed gate is. THE SUB-VERB IS NOT A DUPLICATE OF THE ROW, and `the_bare_diagnosis_is_unchanged_by_the_sub_verb` is where that has to be argued. The axis that case defends is `Mediator`'s: bare `doctor` answers a property of the COMMIT, a sub-verb answers a property of the WORLD. `doctor mediator` is excluded because install recency is a container fact that would make a commit gate answer on it. Whether THIS clone's commit path runs the gate is neither — it is a property of the checkout, byte-stable across machines, the same class as `git-repo`. The sub-verb exists for an unrelated reason: a `[[startup]]` row decides on an exit status and cannot select one line out of a report, so it needs a command answering this question alone. THE COMMON DIR, NEVER THE PER-WORKTREE ONE. `git::git_dir` is per-worktree and is right for receipts and HEAD; hooks are not per-worktree, and git resolves `hooks/<name>` against the common dir — so a linked worktree checked the other way would report the gate missing while every commit in it runs the gate correctly. `core.hooksPath` outranks both, resolved across every scope exactly as git resolves it: a repository that redirects its hooks has hooks, and a probe ignoring the key would send its owner to install a second copy somewhere git never reads. STATS, NEVER EXECUTES, and follows the symlink deliberately. Running the hook to see whether it works is what `doctor.sh` does behind a probe variable; reaching user-supplied code from a `read` verb on the derived allowlist is CLOUD-170's actual invariant. Following the link is required rather than incidental — the installer makes these symlinks into the tree precisely so the checked-in body stays the one authority, and a check refusing to follow one would fail the shape it certifies. The executable bit is asked because it is what git itself asks: a present, non-executable hook is one git skips silently, which a file-existence probe reports as healthy. Pointer-only. The subjects are the hook NAMES — git's own vocabulary — and never the directory they were looked for in: that path is absolute and per-machine, which would defeat byte-stability and put the layout of somebody's disk in a diagnostic that promises not to carry one. Could-not-look passes, this module's posture: a directory whose hooks path cannot be resolved is one `git-repo` has already failed on, and double-counting it would redden a checkout for a read that failed elsewhere. Refs: CLOUD-1398
The engine-side check landed in the previous commit and nothing asked it. This is the half that makes it a gate rather than a reporter — `batten startup` now carries a sixth row, and `--repair` installs the hooks a fresh clone is missing. Measured on this container before the row existed: `batten startup` reported five rows green while `git commit` ran neither `pre-commit` nor `commit-msg`. The session-start advisory's "every declared repair has already run this session; what is listed is what it did not fix" was true and useless, because the hooks were never in the declared set at all. NOT `hk install`, and that is the row's §8 answered by measurement rather than preference. On this container `hk` resolves only through the pin — `mise exec -- hk --version` answers 1.56.1 while doctor's bare-PATH probe reports `program-not-on-path hk` and the pin record is absent. `hk install` generates a hook whose body calls `hk` BARE, so the hook it installs makes every `git commit` fail with `hk: not found`: a repair that reads as installed and breaks the thing it installed. `session:git-hooks` is the symlink-based form that works and is already the session-start step, so this row adds an ASSERTION rather than a second installer. THE SUB-VERB RATHER THAN BARE `doctor`, which is `host-dependencies-present`'s trap approached from the other side. A row decides on an exit status and cannot select one line out of a report, so `check = ["batten", "doctor"]` would fail here whenever any unrelated declared program was unreachable — the state this very container is in, on the `hk` reading above — and would then fire a git-hook repair that cannot fix that, reporting `repair-failed` forever over a gate that is installed. The repair writes under `$GIT_DIR/hooks`, outside the worktree and so outside `protected`; the `repair` key in the committed authority is the authorisation to run it. Verified on this clone with the new binary installed: `batten doctor commit-gate` reports `commit-gate ok` and `batten startup` reports six rows, none failed. On a clone with no hooks the sub-verb reports `commit-gate failed commit-hook-missing commit-msg pre-commit` at exit 1 and the row reports `failed not-provisioned`. Refs: CLOUD-1398 Admits: 520e162f8cc4f9bc5202f66af1d7b60ebdbcd5ded6055a13c8d59ed8c7732584 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:12a12ca9677cc60befac3409f65d4b6ddb44e448 Admits-epoch: 34a3ca72f9f6da3b52df73c607444383dade972800f4d78cdf198bbede317b2e Admits-author: alec@wenzowski.com Admits-prev: 05ef30b5f6748b6aaf3d352dbe1c58268a1577c5b58e6abf898c802635b84d6f Admits-answer-lost: CLOUD-1398 cannot be implemented at all. Its Ready block's §1 names the `[[startup]]` table in batten.toml as the authority for the declared precondition, and the engine-side `doctor commit-gate` check without a row asking it is precisely the reporter-that-is-not-a-gate defect the row was filed to close (the CLOUD-1454 class). The concrete cost is that `git commit` in a fresh clone keeps bypassing pre-commit and commit-msg while `batten startup` reports every row green, which is the measured state of this container. Admits-answer-precondition: The class names `mise run config-lint` and `batten config` as the surface, and neither can ADD a row: batten has no verb that writes its own committed authority, deliberately, so a `[[startup]]` row can only arrive as a direct edit to batten.toml. The write is one a reviewer sees in the diff it lands in — it is on branch claude/cloud-1398-doctor-commit-gate, off origin/main, and lands through a draft PR that `land` readies only after `verify` (which runs config-lint) is green. Admits-answer-rejected-route: Both. `config read first` is not a route to this outcome: I did read the config first — the five existing rows, the `protected` list and the `[[redirect]]` table are what this change is written against — but reading cannot add a row, so it is a precondition I satisfied rather than an alternative I could take instead. `patch run first` does not apply either: it addresses changing an EXISTING declaration, and this is an addition of a sixth row that no patch anchor exists for. Neither route weakens anything: this edit only ADDS a gate, it removes and loosens nothing, which is the opposite direction from the maximal-weakening case the protected list exists for.
Three corrections to the previous two commits, each made by a gate rather than by argument. The engine-side check and its `[[startup]]` row stand; where the check is ASKED changed, the verb was renamed, and the shell task is left alone. THE ROW CAME OUT OF THE BARE REPORT, and the suite is what said so. `container-health` renders `diagnose` at session start, so a `commit-gate` row there made every checkout with no git hooks announce itself as unhealthy — measured, it reddened `contract_drift::a_session_seeded_at_session_start_is_silent_and_stays_silent` over a fixture that has no hooks and wants none. The argument for putting it there was that a clone's commit path is a property of the CHECKOUT rather than of the world, byte-stable across machines, the same class as `git-repo`. That is right about the predicate and wrong about the report: batten requires git hooks of nobody, so WHETHER a commit path should run a gate is the consumer's judgement, and minting it in `crates/batten` is non-negotiable rule 1's violation. The predicate stays in the engine where a caller asks for it; the judgement lives in this repository's own `[[startup]]` row. `doctor gate` RATHER THAN `doctor commit-gate`, on a constraint measured rather than reasoned. A man page is committed as the hyphen-joined command path, and `surface.rs`'s suite maps that filename back by replacing EVERY hyphen — so `batten-doctor-commit-gate.1` reads back as the command `doctor commit gate`, renders nothing, and takes three cases down at once. No verb on this surface has ever carried an internal hyphen; the reason is now written at the declaration and beside the row, so the next author does not rediscover it. THE SHELL TASK IS LEFT ALONE, and CLOUD-1398's own body is wrong about why it could be edited. It claims the remedy-string fix "is exactly the class `only_drops_a_retired_reference` and `drops_a_retired_name` already admit". Measured, that arm requires every removed line to name a path THIS SAME DELTA deleted, and this delta deletes nothing — `.claude/hooks/session-start.sh` went in 7d18858. So `shell-rule-retired` refuses the edit and the two landable shapes are retire it whole or leave it alone. Both governed files are reverted, and the case that asserted the remedy is re-aimed at the half this change owns: the `[[startup]]` row's own `repair` argv, which must name a task the manifest declares and a hook body present in the tree. The stale `::error::` string survives; it needs a retirement, which is not this row's shape. Three obligations a new verb owes here, each found by its own gate: the derived read-only allowlist and the emitted row set (both sorted, both committed), a declared pointer-only disposition, and the generated man page and completions. AND ONE DEFECT IN THE NEW CASE ITSELF. Its fixture row spawned bare `batten`, so `startup` resolved it on PATH and the case graded the container's INSTALL currency rather than this tree — it passed while the installed copy happened to carry the verb and went red the moment the verb was renamed here. Pinned to `CARGO_BIN_EXE_batten`. That is CLOUD-1650's subject arriving inside this suite, which is worth recording rather than quietly fixing. Refs: CLOUD-1398 Admits: 075493a65c80d64b2e6be85464946f2de0323a507426be70bf3f45427fd885ef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:30f7730dec1c3a06f1caf172617dcdba08c3a24c Admits-epoch: 4326c29555225ffac55fc1d3db17442d15d8697c4d6659204ee9c5553a08d068 Admits-author: alec@wenzowski.com Admits-prev: 520e162f8cc4f9bc5202f66af1d7b60ebdbcd5ded6055a13c8d59ed8c7732584 Admits-answer-lost: CLOUD-1398 cannot be implemented at all. Its Ready block's §1 names the `[[startup]]` table in batten.toml as the authority for the declared precondition, and the engine-side `doctor commit-gate` check without a row asking it is precisely the reporter-that-is-not-a-gate defect the row was filed to close (the CLOUD-1454 class). The concrete cost is that `git commit` in a fresh clone keeps bypassing pre-commit and commit-msg while `batten startup` reports every row green, which is the measured state of this container. Admits-answer-precondition: The class names `mise run config-lint` and `batten config` as the surface, and neither can ADD a row: batten has no verb that writes its own committed authority, deliberately, so a `[[startup]]` row can only arrive as a direct edit to batten.toml. The write is one a reviewer sees in the diff it lands in — it is on branch claude/cloud-1398-doctor-commit-gate, off origin/main, and lands through a draft PR that `land` readies only after `verify` (which runs config-lint) is green. Admits-answer-rejected-route: Both. `config read first` is not a route to this outcome: I did read the config first — the five existing rows, the `protected` list and the `[[redirect]]` table are what this change is written against — but reading cannot add a row, so it is a precondition I satisfied rather than an alternative I could take instead. `patch run first` does not apply either: it addresses changing an EXISTING declaration, and this is an addition of a sixth row that no patch anchor exists for. Neither route weakens anything: this edit only ADDS a gate, it removes and loosens nothing, which is the opposite direction from the maximal-weakening case the protected list exists for.
The previous commit claimed to revert `mise-tasks/doctor.sh` and did not. `git checkout -- <path>` restores from HEAD, and HEAD already carried the edit, so the revert restored the edited bytes and the PR kept a change `shell-retirement` refuses. Reverted against `origin/main` this time, which is the comparison that was actually meant. The finding channel did not catch it either: `shell-rule-retired` read 0 while the file still differed from the base. What surfaced it was a review bot listing the file among the PR diff, which is worth recording — the store lagged the tree, and the tree wins. So the stale `::error::` remedy naming `.claude/hooks/session-start.sh` survives on main, and `tests/doctor.bats` still asserts it, which keeps the two consistent. Fixing it needs a retirement rather than an edit; the reason is on CLOUD-1398. Refs: CLOUD-1398
… it is too The `windows` job reddened on 9891539 and nothing local could have caught it: `verify` type-checks the Windows triple through `cross-check` but runs the suite on this host, so a case whose PREMISE is unix-only passes here and fails there. `a_present_but_unrunnable_hook_reads_as_missing` asserted that a mode-0644 hook reads as missing. On Windows there is no executable bit for git to consult and it runs any hook file it finds, so `is_runnable_hook` answering `true` for a present file is CORRECT rather than a gap — the predicate tracks what git will actually do on each platform, which is the whole point of asking about the bit at all on the platform that has one. What was wrong is a case asserting the unix reading everywhere. Measured: `left: "commit-gate ok"` against `right: "commit-gate failed commit-hook-missing pre-commit"`. The two sibling cases stay UNGATED deliberately, and that asymmetry is the statement: they turn on a hook being ABSENT, which a `git init` produces on both platforms, so their premise holds everywhere. Both passed on the same Windows runner that failed this one, which is what makes the split a reading rather than a guess. Refs: CLOUD-1398
…se away The previous commit's `#[cfg(unix)]` was itself the defect this repository has a gate for, and `platform-gated-test-added` refused it by name. Its rationale is exactly right: narrowing a case to one platform turns a red leg green while leaving the other contract UNSTATED and one arm never compiled on the host that authors it, so the next edit to that arm is discovered by CI rather than locally. `cfg!` in the body is the remedy the rule's own comment names. Both arms compile on every target, and the Windows expectation is written down: with no executable bit for git to consult, a present hook file IS a live hook, so the row is honestly satisfied and `commit-gate ok` is the right answer there. The unix arm keeps the reading that matters on a platform with a mode bit — a 0644 hook is one git will skip, and a probe that only stats for existence calls that healthy. Both readings are correct; that is the substance rather than a workaround. `is_runnable_hook` tracks what git will actually do on each platform, and the case now asserts both instead of asserting one and hiding the other. Refs: CLOUD-1398
`CommandDecl` gained a required `exits` field on `main` while this branch was in flight, so the rebase left the `doctor gate` row uncompilable — the cost of a long-lived branch against a trunk this active, and the compiler caught it rather than a reviewer. `EXITS_STANDARD`, whose content is the code it OMITS: `Violation` is unreachable here, inheriting the promise bare `doctor` makes. A mediating harness reads `2` as a deny, and "this clone has no commit hooks" is not "policy says no". Refs: CLOUD-1398
…d base Reverts dd6b75695178049d04a28a3c7a433fff63b18601. The `exits` field it declared does not exist on `main`. `land` had rebased this branch onto a base BORROWED from another branch's unlanded work — its own output says so, "this tree is SPECULATIVE — it carries 0f2f85c borrowed from 0f2f85c..." — so the required-field compile error that prompted it came from that speculative base rather than from the trunk. The commit was therefore correct against a tree that does not exist yet and wrong against the one this branch lands on: `git show origin/main:crates/batten/src/surface.rs` carries no `exits:` at all, and with the branch back on real `main` the row stopped compiling for the opposite reason it was written. The speculative warning is load-bearing rather than noise, which is the lesson worth keeping: a fix authored against a borrowed base is a fix for somebody else's branch, and it fails in the direction that looks like progress — the compiler was satisfied at the moment of writing. If `CommandDecl` does gain `exits`, this row wants `EXITS_STANDARD`, whose content is the code it omits: `Violation` is unreachable, because a mediating harness reads `2` as a deny and "this clone has no commit hooks" is not "policy says no". That belongs in the change that adds the field, not here. Refs: CLOUD-1398
`command -v batten` asks whether a binary is on PATH. The failure that matters here is a binary that IS on PATH and cannot read this tree — the release predating a `batten.toml` key, which this repository reaches constantly because keys land between releases. Measured on this branch's own landing lap: the installed 0.0.151 refused `[lease]` with "the config declares a key this build predates". A presence-only guard sends the task to that binary and fails; `&&` sends it to the build. This restores what the unconditional `cargo run` gave for free and what `target-prune` has always done — try the installed binary, fall back to a build when it cannot do the job. The previous revision claimed to copy that shape and copied only half of it. Refs: CLOUD-1620
Self-correction. The previous commit raised `LAND_LOCK_MAX_WAITS` and taught AGENTS.md about exit codes 4 and 5. Both described `mise-tasks/land.sh`, which CLOUD-843 has already retired onto the engine — it is absent from `origin/main`, and nothing under `crates/batten/src` reads that variable. So the knob was dead config the moment it was written, and the contract named exit codes that no longer exist: `exit.rs` is the house-style table, 0/1/2/3, with no 4 or 5. The error was reading the tree as it stood at session start and acting on it after a rebase had moved `main` 129 commits forward underneath. The same stale-reading class as the defect this branch opened on. What survives is the property rather than the numbers, because the numbers have now moved once: a stop that spent nothing is not a failing branch. The engine already says so in its own refusal — "A saturated fleet is not a failing branch — run this again" — which is the imperative the shell task's lease exit never carried, so the fix this branch was going to file against CLOUD-843 largely arrived with it. AGENTS.md keeps the correction that mattered: the loop has no wall clock but does have counted stops, where it previously claimed "no cap" and "three things only" while six further stops existed. Refs: CLOUD-1620
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
267bd13 to
f4e190d
Compare
The pin half of CLOUD-1672 landed across 24 workflows and nothing held it there. This is the mechanism, so the rule is not prose (non-negotiable 2). `action-version-matches-the-pin` refuses a workflow step installing the toolchain at a version the tree does not pin: `job pin other` where a declared version disagrees with the `[[provision]]` row, `job pin missing` where the step declares none and hands the choice to the installer. The comparison is against the committed row and never a literal -- a module carrying `2026.9.1` would be a THIRD authority and would go stale the first time the pin moved. Both documents are found by SHAPE, never by filename: a document carrying `jobs`, a document carrying `provision`. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row's `sources` is where this consumer says which of its files those are. No provision row for the tool means the row ABSTAINS rather than refuses. A project that pins nothing has nothing to disagree with, and refusing there would be a verdict about their configuration instead of about drift between two of their own statements. THE ENGINE HALF: A MANIFEST DECLARES A SCOPE PER MODULE. `Manifest.scope` said a preset decides exactly one surface -- true of every preset that existed when it was written, false the moment a subject has something to say about both. `mise` is that subject: whether an agent reproduces a task's argv is a question about a CALL, whether the toolchain a workflow installs matches the pin is a question about the TREE. They are one preset because they are one concern, and a consumer should not have to know the engine once could not express that. Two constraints assumed the old shape and both now key on the pair: - the load-time scope check compared one manifest scope for equality; it asks `decides(scope)` now, and names the scopes the preset does decide. - the duplicate-registration check keyed on the source name, so the second row enabling one preset at the other scope read as dead config. It is not: each row compiles only the modules at its own scope, so they share a name and decide disjoint surfaces. Selecting modules by scope is load-bearing rather than tidy. A tree module compiled onto the call surface reads keys the engine never builds there, Rego reads undefined as "does not hold", and the result is a dead gate byte-identical to a clean tree. `check_tree_paths_are_emittable` catches that today; this keeps the case from arising rather than relying on a downstream guard to notice. VERIFIED, AND THE REAL-TREE ARM IS THE ONE THAT COUNTS. `policy test` 64 bundles, 814 passed; the four preset tiers 39/39. Both of those supply their own pin document, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` -- and if it did not, the pin would be absent, the module would abstain by design, and the gate would report clean forever. So it was driven over this checkout: clean as committed, and moving one workflow's version produced `.github/workflows/scorecard.yml:53 action-version-matches-the-pin`, exit 2, pointer-only. The file was restored with `git checkout --` and the diff is unchanged. `a_drifted_version_in_this_repository_is_refused` is that same proof as a standing case. Refs: CLOUD-1672, CLOUD-1181, CLOUD-404 Admits: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3 Admits-answer-lost: The gate half of CLOUD-1672 does not run. The pin is landed across all 24 workflows but nothing holds it there, so the next architecture move, Renovate bump or hand edit silently reintroduces the drift that published v0.0.152 with zero binaries. A rule without its mechanism is half a change by this repository's own non-negotiable rule 2. Admits-answer-precondition: CLOUD-1672 gate half. The redirect for `batten.toml` is "change it in a pull request" with `config-lint` as the check before it lands — a statement about how the change must LAND, not a surface that can express it: only a direct write can add a `[[rule]]` row. The row enables the `mise` preset at tree scope with the `sources` globs the predicate reads; without it the module ships and decides nothing, which is the dead-gate shape the whole row exists to close. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the `ci-hygiene` row was read as the shape to copy, since it is the existing tree-scoped preset row carrying workflow `sources` and `line_sources`. Admits: 6e8cd01a0028a1c5510ed46c8c6539d3976ffc6486db86b606b140723b76865f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 3b025bfdaaedf9f46a55c4b09fba627a7d599c231956e6730c43863d886b4d05 Admits-author: alec@wenzowski.com Admits-prev: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-answer-lost: The gate ships unproven on the surface that matters. The load-time and compiled tiers both supply their own fixture documents, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` to the module — and if it does not, the pin document is absent, the module abstains BY DESIGN, and the gate reports clean forever over a tree it never compared. That is the exact dead-gate shape this row exists to close, reachable only through the row's own configuration. Admits-answer-precondition: A VERIFICATION WRITE, reverted in the same turn. CLOUD-1672's new gate reports clean over this tree, and clean is byte-identical to a dead gate — so one workflow's `version:` is being changed to a wrong value to confirm the predicate names it, then changed straight back. Only a direct write can do that; no read surface can make a gate fire. Nothing of it reaches a commit: the file is restored with `git checkout --` before the tree is staged, and the diff will show it unchanged. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s new `mise-preset-tree` row and its `sources` list were read, and reading them is what identified the glob as the one thing no fixture can verify.
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
The pin half of CLOUD-1672 landed across 24 workflows and nothing held it there. This is the mechanism, so the rule is not prose (non-negotiable 2). `action-version-matches-the-pin` refuses a workflow step installing the toolchain at a version the tree does not pin: `job pin other` where a declared version disagrees with the `[[provision]]` row, `job pin missing` where the step declares none and hands the choice to the installer. The comparison is against the committed row and never a literal -- a module carrying `2026.9.1` would be a THIRD authority and would go stale the first time the pin moved. Both documents are found by SHAPE, never by filename: a document carrying `jobs`, a document carrying `provision`. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row's `sources` is where this consumer says which of its files those are. No provision row for the tool means the row ABSTAINS rather than refuses. A project that pins nothing has nothing to disagree with, and refusing there would be a verdict about their configuration instead of about drift between two of their own statements. THE ENGINE HALF: A MANIFEST DECLARES A SCOPE PER MODULE. `Manifest.scope` said a preset decides exactly one surface -- true of every preset that existed when it was written, false the moment a subject has something to say about both. `mise` is that subject: whether an agent reproduces a task's argv is a question about a CALL, whether the toolchain a workflow installs matches the pin is a question about the TREE. They are one preset because they are one concern, and a consumer should not have to know the engine once could not express that. Two constraints assumed the old shape and both now key on the pair: - the load-time scope check compared one manifest scope for equality; it asks `decides(scope)` now, and names the scopes the preset does decide. - the duplicate-registration check keyed on the source name, so the second row enabling one preset at the other scope read as dead config. It is not: each row compiles only the modules at its own scope, so they share a name and decide disjoint surfaces. Selecting modules by scope is load-bearing rather than tidy. A tree module compiled onto the call surface reads keys the engine never builds there, Rego reads undefined as "does not hold", and the result is a dead gate byte-identical to a clean tree. `check_tree_paths_are_emittable` catches that today; this keeps the case from arising rather than relying on a downstream guard to notice. VERIFIED, AND THE REAL-TREE ARM IS THE ONE THAT COUNTS. `policy test` 64 bundles, 814 passed; the four preset tiers 39/39. Both of those supply their own pin document, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` -- and if it did not, the pin would be absent, the module would abstain by design, and the gate would report clean forever. So it was driven over this checkout: clean as committed, and moving one workflow's version produced `.github/workflows/scorecard.yml:53 action-version-matches-the-pin`, exit 2, pointer-only. The file was restored with `git checkout --` and the diff is unchanged. `a_drifted_version_in_this_repository_is_refused` is that same proof as a standing case. Refs: CLOUD-1672, CLOUD-1181, CLOUD-404 Admits: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3 Admits-answer-lost: The gate half of CLOUD-1672 does not run. The pin is landed across all 24 workflows but nothing holds it there, so the next architecture move, Renovate bump or hand edit silently reintroduces the drift that published v0.0.152 with zero binaries. A rule without its mechanism is half a change by this repository's own non-negotiable rule 2. Admits-answer-precondition: CLOUD-1672 gate half. The redirect for `batten.toml` is "change it in a pull request" with `config-lint` as the check before it lands — a statement about how the change must LAND, not a surface that can express it: only a direct write can add a `[[rule]]` row. The row enables the `mise` preset at tree scope with the `sources` globs the predicate reads; without it the module ships and decides nothing, which is the dead-gate shape the whole row exists to close. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the `ci-hygiene` row was read as the shape to copy, since it is the existing tree-scoped preset row carrying workflow `sources` and `line_sources`. Admits: 6e8cd01a0028a1c5510ed46c8c6539d3976ffc6486db86b606b140723b76865f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 3b025bfdaaedf9f46a55c4b09fba627a7d599c231956e6730c43863d886b4d05 Admits-author: alec@wenzowski.com Admits-prev: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-answer-lost: The gate ships unproven on the surface that matters. The load-time and compiled tiers both supply their own fixture documents, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` to the module — and if it does not, the pin document is absent, the module abstains BY DESIGN, and the gate reports clean forever over a tree it never compared. That is the exact dead-gate shape this row exists to close, reachable only through the row's own configuration. Admits-answer-precondition: A VERIFICATION WRITE, reverted in the same turn. CLOUD-1672's new gate reports clean over this tree, and clean is byte-identical to a dead gate — so one workflow's `version:` is being changed to a wrong value to confirm the predicate names it, then changed straight back. Only a direct write can do that; no read surface can make a gate fire. Nothing of it reaches a commit: the file is restored with `git checkout --` before the tree is staged, and the diff will show it unchanged. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s new `mise-preset-tree` row and its `sources` list were read, and reading them is what identified the glob as the one thing no fixture can verify.
f4e190d to
96352c8
Compare
`batten-check` reads the `ci-` cache family on x64 while its only warm writer,
`cache-warm-linux`, runs on arm64. rust-cache composes `runnerOS-runnerArch`
into the key at `config.ts:93`, inside the prefix assigned to `restoreKey` at
`:133`, so those are two entries that can never touch: the job restored nothing
and built cold on every run, at 683s the critical path of the whole workflow.
CLOUD-1453 landed the eviction half and is released in v0.0.142, but eviction
was not the cause. Measured across jobs 100903936005 and 101280975479, a swept
store moved this job 683s -> 600s: 12%, which is eviction pressure lifting
rather than a restore landing.
`ci.yml` declined the fix on a ceiling that no longer exists ("10.72 GiB over a
10 GiB ceiling"), naming two alternatives that are both closed -- `cache-sweep`
took the store to 3.16 GiB, and CLOUD-1431 is Done having landed a gate over
the release-target/provision-platform pairing rather than an arm64 scanner, so
the job still cannot move. So the second writer is what lands:
- `cache-warm-linux-x64` writes `ci-` on x64 from the trunk, mirroring
`cache-warm-linux`'s guarded-compile shape.
- `batten-check` becomes `save-if: false` like every other pull-request
consumer of the family; its per-lap multi-gigabyte write into a 10 GiB store
bought only the next lap of its own PR, which a warm entry now serves.
- the stale comment at `ci.yml:601-618` is corrected rather than left for the
next reader to re-derive the wrong trade from.
Rules ship with their mechanism, so the class is gated rather than just fixed.
`ci-cache-declared`'s three predicates are all about a family's WRITERS, which
is why the orphaning survived CLOUD-1410's own review: the reader kept a valid
`shared-key`, the module kept a warm writer, and the two were on different
machines. `read-family-has-a-warm-writer` is the fourth -- a pull-request job
that is read-only against a family nothing fills on its architecture is
refused, raising the new `job read empty` verdict.
Scoped to pure consumers (`save-if: false`) deliberately. Every rust-cache step
restores, so judging every reader would reach `cross-`, `semver-`,
`${{ matrix.target }}`, `coverage-`, `fuzz-` and `perf-` -- families this
repository writes from the pull request on purpose because they have no trunk
writer, which `ci.yml` records as a deferred follow-up. Those still get their
own entry on a later lap; a `save-if: false` job gets nothing, ever. That is
the same bound rule 3 draws when it excludes the scheduled writers from
`warmed`.
Verified: `mise run policy-test` clean, and the engine tier 17/17 including
`this_repository_is_clean_today` over the committed workflows.
Recorded rather than absorbed: a `sed -i` against `batten.toml` in this session
was NOT refused by the protected-path gate, which is a gap in the
mutating-verb table's coverage of that verb. It was reported in the admission
below and not relied on; the declared route was taken instead.
Refs: CLOUD-1477, CLOUD-1453, CLOUD-1431, CLOUD-1410
Admits: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239
Admits-rule: protected-mutation
Admits-verdict: path write refused
Admits-subject: .github/workflows/release-plz.yml
Admits-anchor: call:7fe35efd0b28cf086de2086028764a0a8eb7cf9b
Admits-epoch: ed0cc67ec403a5849f97cbe66586e656ab21f7b6d2015725b2d51a2a2c6f5b91
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: CLOUD-1477 cannot be implemented at all. `batten-check` keeps paying a cold ~600s build on every CI lap as the critical path of the whole workflow, because the `ci-` family has no warm writer on x64; and the fourth predicate that would make the orphaning a finding rather than a silent green cannot be added, so the next architecture move reintroduces it unseen.
Admits-answer-precondition: The redirect this class names for `.github/workflows/**` is "change it in a pull request", which is a statement about how the change must LAND rather than an alternative surface that can express it: no tool other than a direct write can add a job to a workflow file. The write is one a reviewer will see in the diff it lands in — it goes to branch claude/glacial-ci-regression-d9qtr3 as a draft PR, reviewed before merge, and CLOUD-1477 is a refined row whose §1 and §3 mandate edits to these exact paths.
Admits-answer-rejected-route: `patch run first` does not apply: the protected-path gate is the intersection of the protected paths with the mutating-verb table, and that table already refuses `>`, `tee`, `sed`, `cp`, `install` and `git` over these same paths. Routing the identical bytes through a patch program reaches the identical refusal under a different program name, which is laundering rather than a second route. `config read first` was TAKEN, not rejected — batten.toml's protected and redirect tables and `batten policy explain protected-mutation` were read before this request, and reading them is what established that no expressing surface exists.
Admits: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc
Admits-rule: protected-mutation
Admits-verdict: path write refused
Admits-subject: .github/workflows/ci.yml
Admits-anchor: call:7fe35efd0b28cf086de2086028764a0a8eb7cf9b
Admits-epoch: ed0cc67ec403a5849f97cbe66586e656ab21f7b6d2015725b2d51a2a2c6f5b91
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The `batten-check` job keeps writing a multi-gigabyte `ci-` entry per lap that no other pull request can read, and `main` keeps carrying a comment that declines the fix on a 10 GiB ceiling `cache-sweep.yml` already removed — which is how the next reader re-derives the wrong trade, and is the defect CLOUD-1477 was filed on.
Admits-answer-precondition: The redirect this class names for `.github/workflows/**` is "change it in a pull request", which is a statement about how the change must LAND rather than an alternative surface that can express it: no tool other than a direct write can add `save-if: false` to a step or correct a job's comment. The write is one a reviewer will see in the diff it lands in — branch claude/glacial-ci-regression-d9qtr3, draft PR, reviewed before merge. CLOUD-1477 §3 names this file's lines 601-618 as the thing to correct.
Admits-answer-rejected-route: `patch run first` does not apply: the protected-path gate is the intersection of the protected paths with the mutating-verb table, and that table already refuses `>`, `tee`, `sed`, `cp`, `install` and `git` over these same paths, so routing the identical bytes through a patch program reaches the identical refusal under a different program name. `config read first` was TAKEN, not rejected — batten.toml's protected and redirect tables and `batten policy explain protected-mutation` were read first, and that is what established no expressing surface exists.
Admits: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3
Admits-rule: protected-mutation
Admits-verdict: path write refused
Admits-subject: batten.toml
Admits-anchor: call:7fe35efd0b28cf086de2086028764a0a8eb7cf9b
Admits-epoch: ee766a19306de59b2c367442e936067d33bd4fae08bdbbc4cc0a061144665d8d
Admits-author: alec@wenzowski.com
Admits-prev: a607863046171bb3f3d1d7909d8eb2b29f17214df9248c89d76a25c8a29db340
Admits-answer-lost: The row keeps prose written for a word it no longer uses, so the registry's gloss and its id disagree — and `job read empty` would ship describing itself as "nothing warms" while the vocabulary defines the condition as "declared and holding nothing". That is the drift the controlled vocabulary exists to prevent, in the row that introduces the word.
Admits-answer-precondition: The redirect this class names for `batten.toml` is "change it in a pull request", with `mise run config-lint` as the check before it lands — which states how the change must LAND rather than naming a surface that can express it: no tool other than a direct write can edit a `[[verdict]]` row's gloss. This is the same `[[verdict]]` addition the previous admission on this subject covered, corrected after `batten policy test` refused the token: `unwarmed` is not in the declared `[[vocabulary.condition]]` list, so the row is being renamed to `job read empty` and its prose brought into line with that word's gloss, "declared and holding nothing". Branch claude/glacial-ci-regression-d9qtr3, draft PR, reviewed before merge.
Admits-answer-rejected-route: `patch run first` does not apply: the protected-path gate is the intersection of the protected paths with the mutating-verb table, which already refuses `>`, `tee`, `sed`, `cp`, `install` and `git` over this path, so a patch program reaches the identical refusal under a different name. Recorded rather than absorbed: a `sed -i` earlier in this session mutated this file WITHOUT being refused, which is a gap in that table's coverage of the verb — it is being reported rather than spent, and this request is the declared route taken in its place. `config read first` was TAKEN — the vocabulary tables at batten.toml:9124-9257 were read before this request, and reading them is what produced the corrected token.
Admits: cee2adcf16471bed1304548e3122e430942c321d2eb748b1a130cd2d39292e28
Admits-rule: protected-mutation
Admits-verdict: path write refused
Admits-subject: policy/ci-cache-declared.rego
Admits-anchor: call:7fe35efd0b28cf086de2086028764a0a8eb7cf9b
Admits-epoch: 81c654046fb5b5547138aa9ab501ee774f5c6294be621104fd4c4e271a31a309
Admits-author: alec@wenzowski.com
Admits-prev: ea7b294412f1a37b4ed1d26406aca2aaa661363e55c8bfe4c15a58b6f2c34661
Admits-answer-lost: The module does not load. A module raising a token no `[[verdict]]` row declares is refused at load time, and the registry now declares `job read empty` — so leaving the module raising `job read unwarmed` takes the whole of `ci-cache-declared` down, all four predicates, not just the new one.
Admits-answer-precondition: The redirect this class names for `policy/**` is "change it in a pull request", which states how the change must LAND rather than naming a surface that can express it: no tool other than a direct write can change a verdict token inside a Rego module. This is the same predicate the previous admission on this subject covered, corrected after `batten policy test` refused `job read unwarmed` — `unwarmed` is not in the declared `[[vocabulary.condition]]` list, and the registry row has been renamed to `job read empty`, so the module must raise the same token or fail to load. Branch claude/glacial-ci-regression-d9qtr3, draft PR, reviewed before merge.
Admits-answer-rejected-route: `patch run first` does not apply: the protected-path gate is the intersection of the protected paths with the mutating-verb table, which already refuses `>`, `tee`, `sed`, `cp`, `install` and `git` over these paths, so a patch program reaches the identical refusal under a different name. `config read first` was TAKEN — the vocabulary tables at batten.toml:9124-9257 were read before this request, and that reading is what produced the corrected token.
…declares `batten.toml:352-357` pins mise to 2026.9.1 by per-platform URL and digest. `jdx/mise-action` cannot see it. The `uses:` digest pins the ACTION; which MISE that action installs is a separate resolution, and unset it takes whatever is newest when the job starts. So the tree declares one toolchain and CI runs another, with nothing comparing them. Measured 2026-09-08, latest resolved to v2026.9.3 whose linux-x64 asset 404s: curl -fsSL .../v2026.9.3/mise-v2026.9.3-linux-x64.tar.zst curl: (22) The requested URL returned error: 404 x5 retries Every job in every workflow died at that step inside 11 seconds. `release-artifacts` run 34206034815 lost all 8 jobs in 56s and v0.0.152 published carrying `batten.schema.json` and none of its seven target binaries; `ci.yml` run 34220313465 lost 5 jobs in 53s, so nothing could land at all. THE PROVISION ROW ALREADY NAMED THIS HARM, one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement `[[provision]]`'s pinning exists to remove." That is exactly what happened, and the pin written to prevent it does not reach the layer where it occurred. This carries the pin only. The gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two cannot drift again -- is not in this commit, and the remaining workflows are not yet pinned. Both follow on this branch. Pinned here: `ci.yml` (4 steps), `release-artifacts.yml` (3), `release-plz.yml` (4), `auto-bot-land.yml` (1). Refs: CLOUD-1672, CLOUD-1574, CLOUD-1455 Admits: 14a7813f18d11c452bb5851acf9aad131e3f63a3e7c0ede84f7ca15db7325b7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: d6ff1328442bc15a7f1017cdb28a0190b0c3575b6a85e67a75752d80dbe6f9bc Admits-answer-lost: CI stays down. Every job in this workflow dies at `jdx/mise-action` in ~11s because the action resolves mise latest (v2026.9.3) whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Nothing in the repository can land until the action installs the version the tree declares. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 5a69f466467c58937d55e1c7d5b79e3259b2d190cac2e69e9d4a695d3f734106 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-artifacts.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: v0.0.152 published with zero binaries and the next release does the same. All 8 jobs of run 34206034815 died at `jdx/mise-action` in 11s because the action resolves mise latest (v2026.9.3), whose linux-x64 asset 404s, while `batten.toml` pins 2026.9.1. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 4690dbacf228821c8ab51e1aee4bf72d157a3bda3edeb61d491cb9a426c38239 Admits-answer-lost: The release lane keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins, so the tree declares one toolchain and the release runs another — the drift that published v0.0.152 with zero binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e320b15216a7f81f8b17b231e5f62f128ca8b373499501bcc3fdbbf7d8ecf45f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-plz.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: 168f6f87f302b1fd73d8e77e621eae3c7f5e3d5752d7ee1f7c61fcc2eb1e76b6 Admits-answer-lost: The one job that actually cuts the release stays unpinned while the three cache-warm jobs beside it are pinned — the worst of both, since the file would read as fixed while the step that publishes the tag still installs whatever mise is newest. Admits-answer-precondition: CLOUD-1672, second write to this file. The three steps carrying a `with:` block were pinned by the previous admission; the fourth (the `release-plz` job's own step, line 338) declares no `with:` at all, so it needs a different insertion and a separate write. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name; the mutating-verb table covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the file was re-read to find that this fourth step carries no `with:` block. Admits: 8a95229ff41806a9b5a05b08a17e49af42dfe91abdcf79f76bd1a625bb686797 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-bot-land.yml Admits-anchor: call:7fc52c56faed1bc3b4407c796505462a81307d86 Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: .github/workflows/auto-bot-land.yml keeps installing whatever mise is newest at job start rather than the 2026.9.1 that `batten.toml` pins. Measured 2026-09-08: latest resolved to v2026.9.3, whose linux-x64 asset 404s, and every job in every workflow died at this step inside 11 seconds. A workflow left unpinned reintroduces the outage on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
…lows Continues the CLOUD-1672 pin across seven more workflows: `rust.yml` (4 steps), `commit-lint.yml`, `fast-forward.yml`, `perf.yml`, `coverage.yml`, `zizmor.yml` and `fuzz.yml`. Three of these are load-bearing beyond their own run. `commit-lint` is a required check, so an unpinned step there reds every pull request. `fast-forward` is the landing path itself. `perf` records the series from a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Thirteen workflows remain, and the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's -- is still to come on this branch. Refs: CLOUD-1672 Admits: 8efa23f5401b475d58c607f3ae8e2adf60dbca5cd2df506ffb00546de908fcb6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/rust.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 71b4de9ae1a0041ffa6098d40137230060304c3db9d59a92f0fb951848ce293f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/commit-lint.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. `commit-lint` is a required check, so an unpinned step here reds every pull request on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: b2ce26a31ad7115c22e0a454348b17fd5de11435bde11478b92e86dab28e560e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fast-forward.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the landing path itself. It keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins; measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the fast-forward that lands every branch fails on its own next run. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: ed675dc23520c7be2878c592f48d6a67b2c5a7e4b61a81be4e372ee08abd32b6 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/perf.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also records the perf series from a clock, so an unpinned toolchain silently changes what the series measures. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e6bdca0e483274fb95b00b750830540c12fb431e14186b8ddf90c7ef5f161cc3 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/coverage.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e328c82bb610d6dfab5c7457f7f754ea003496c4f464488a7529465336a3a3f5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 32cdb5543b38da755a3b2e116dffa060cbe7e321802749e2b6a0c3c66c6d8465 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/fuzz.yml Admits-anchor: call:f937fa2d0a92f95600ef96474885e1fa44b5ad1a Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
Completes the CLOUD-1672 pin. Every `jdx/mise-action` step in `.github/workflows/**` now declares `version: 2026.9.1`, matching `batten.toml`'s `[[provision]]` row; `git grep -L` reports no workflow carrying a `mise-action` step without it. Three of these are pinned for a reason beyond their own install, and each says so at the step rather than here: - `lock-currency` is the clock that BUMPS pins, so unpinned it is the one job a bad upstream release stops -- the job that would have surfaced this. - `arch-probe` compares two runner architectures whose validity rests on the arms differing only in `runs-on`; an unpinned mise lets them install different toolchains and destroys the comparison silently rather than failing it. - `hook-latency-drift` and `nonverdict-rate` record series on a clock, where a drifting toolchain changes what is measured rather than reddening. Still to come on this branch: the gate half of CLOUD-1672 -- a predicate refusing a `mise-action` step whose declared version differs from the `[[provision]]` row's, so the two authorities cannot drift apart again. Refs: CLOUD-1672 Admits: 53fe1b9a28fb798ee6a9fe6ec34dbd51ff974ca27d8923e89ad919695f31cb5f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/release-assets.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow publishes release assets and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, it reintroduces the outage that published v0.0.152 with no binaries. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 9127e19ea5c4a7b38d85eab3f54dc5572b0c0611be0ce158f0d57f2b5d40e536 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/auto-release-land.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow lands the release PR and keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. Unpinned, the release lane stays broken at its landing step. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 54cc2b5a7371515470c55b5911e812cad54824759c7e04b83b394f4795f0d7c7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/mutant.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 53c89ed482c8e3b6e2262eefd30c407714eeea6beb70a300c0e8bc376f2ffb84 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/lock-currency.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the clock that bumps pinned tools, so an unpinned mise here means the job that MOVES pins cannot run at all. Measured 2026-09-08: the action resolved v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s — including the one that would otherwise have surfaced the bad upstream release. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: c36024aa70f3e151f72e152f48965917416625d2bd16216b9abf8848a9501e70 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/ci-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 523d9f0aa526c4181f9d9d9999c2d6a5031be9496707953e17c4be535d211f24 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/timeout-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 75b185566d9fd6163a2549832a838e1ada9326be61d72c59723faedb42707aef Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/land-divergence.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 4649eab6a0922340d2be1ce0e47a8ffd507b47740ae55f85453dc6af35d2bfad Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/hook-latency-drift.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It also measures the gate's own latency on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: d2fb5c29b070b9f91cbdb94a9608bcf2e0cf9963b49c675e44216fbe85391a7e Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/nonverdict-rate.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. It records a rate on a clock, so an unpinned toolchain silently changes what the series measures rather than failing. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. This step declares no `with:` block, so the write adds one. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 614a8ab2953de8ff590164a654d0c667b821895e4c92af1273e92116e10aa28d Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/zizmor-advisories.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: e74e0af2f0245d98a75d0ef01619e24b90929e67fbeb016e9d9fa42689a7d6c9 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/branch-hygiene.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This workflow keeps installing whatever mise is newest at job start rather than the 2026.9.1 `batten.toml` pins. Measured 2026-09-08 that was v2026.9.3, whose linux-x64 asset 404s, and every job died at this step in 11s. A workflow left unpinned reintroduces the outage on its own next run, and the gate this row also lands will refuse it. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from. Admits: 0d5560b6a87c0ed0a7917002a7eedb5634d010b4200eb65cc46bb866516c8381 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/arch-probe.yml Admits-anchor: call:a134f824acba494f16226b89be4869ab292bd3da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: - Admits-answer-lost: This is the matched arm-versus-x64 probe, whose whole validity rests on both arms differing ONLY in `runs-on`. An unpinned mise means the two arms can install different toolchains, which silently destroys the comparison rather than failing it — and the last unpinned resolution, v2026.9.3, 404s on linux-x64 so the probe cannot run at all. Admits-answer-precondition: CLOUD-1672. The redirect for `.github/workflows/**` is "change it in a pull request", which says how the change must LAND, not a surface that can express it: only a direct write can add a `version:` input to a `mise-action` step. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s `[[provision]]` row was read and is where the 2026.9.1 pin comes from.
The pin half of CLOUD-1672 landed across 24 workflows and nothing held it there. This is the mechanism, so the rule is not prose (non-negotiable 2). `action-version-matches-the-pin` refuses a workflow step installing the toolchain at a version the tree does not pin: `job pin other` where a declared version disagrees with the `[[provision]]` row, `job pin missing` where the step declares none and hands the choice to the installer. The comparison is against the committed row and never a literal -- a module carrying `2026.9.1` would be a THIRD authority and would go stale the first time the pin moved. Both documents are found by SHAPE, never by filename: a document carrying `jobs`, a document carrying `provision`. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row's `sources` is where this consumer says which of its files those are. No provision row for the tool means the row ABSTAINS rather than refuses. A project that pins nothing has nothing to disagree with, and refusing there would be a verdict about their configuration instead of about drift between two of their own statements. THE ENGINE HALF: A MANIFEST DECLARES A SCOPE PER MODULE. `Manifest.scope` said a preset decides exactly one surface -- true of every preset that existed when it was written, false the moment a subject has something to say about both. `mise` is that subject: whether an agent reproduces a task's argv is a question about a CALL, whether the toolchain a workflow installs matches the pin is a question about the TREE. They are one preset because they are one concern, and a consumer should not have to know the engine once could not express that. Two constraints assumed the old shape and both now key on the pair: - the load-time scope check compared one manifest scope for equality; it asks `decides(scope)` now, and names the scopes the preset does decide. - the duplicate-registration check keyed on the source name, so the second row enabling one preset at the other scope read as dead config. It is not: each row compiles only the modules at its own scope, so they share a name and decide disjoint surfaces. Selecting modules by scope is load-bearing rather than tidy. A tree module compiled onto the call surface reads keys the engine never builds there, Rego reads undefined as "does not hold", and the result is a dead gate byte-identical to a clean tree. `check_tree_paths_are_emittable` catches that today; this keeps the case from arising rather than relying on a downstream guard to notice. VERIFIED, AND THE REAL-TREE ARM IS THE ONE THAT COUNTS. `policy test` 64 bundles, 814 passed; the four preset tiers 39/39. Both of those supply their own pin document, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` -- and if it did not, the pin would be absent, the module would abstain by design, and the gate would report clean forever. So it was driven over this checkout: clean as committed, and moving one workflow's version produced `.github/workflows/scorecard.yml:53 action-version-matches-the-pin`, exit 2, pointer-only. The file was restored with `git checkout --` and the diff is unchanged. `a_drifted_version_in_this_repository_is_refused` is that same proof as a standing case. Refs: CLOUD-1672, CLOUD-1181, CLOUD-404 Admits: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 549ff209e932fdcaedf859d520794afa6a1a3125e363212214b1d9c737338b7e Admits-author: alec@wenzowski.com Admits-prev: e1aaff7ef76c6a51d8d71c951a03bfdfec14b5cbaebe9bb738612f15bcda99f3 Admits-answer-lost: The gate half of CLOUD-1672 does not run. The pin is landed across all 24 workflows but nothing holds it there, so the next architecture move, Renovate bump or hand edit silently reintroduces the drift that published v0.0.152 with zero binaries. A rule without its mechanism is half a change by this repository's own non-negotiable rule 2. Admits-answer-precondition: CLOUD-1672 gate half. The redirect for `batten.toml` is "change it in a pull request" with `config-lint` as the check before it lands — a statement about how the change must LAND, not a surface that can express it: only a direct write can add a `[[rule]]` row. The row enables the `mise` preset at tree scope with the `sources` globs the predicate reads; without it the module ships and decides nothing, which is the dead-gate shape the whole row exists to close. Branch claude/glacial-ci-regression-d9qtr3, draft PR #914, reviewed before merge. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — the `ci-hygiene` row was read as the shape to copy, since it is the existing tree-scoped preset row carrying workflow `sources` and `line_sources`. Admits: 6e8cd01a0028a1c5510ed46c8c6539d3976ffc6486db86b606b140723b76865f Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: .github/workflows/scorecard.yml Admits-anchor: call:8c6419950ad9ffd05f57f842005d1004860e85da Admits-epoch: 3b025bfdaaedf9f46a55c4b09fba627a7d599c231956e6730c43863d886b4d05 Admits-author: alec@wenzowski.com Admits-prev: 14c4bf8e70e719ee233f6ea75a26e6c39ad884427ec74509fdc8765bcb2e133c Admits-answer-lost: The gate ships unproven on the surface that matters. The load-time and compiled tiers both supply their own fixture documents, so neither can show that this consumer's `sources` glob actually delivers `batten.toml` to the module — and if it does not, the pin document is absent, the module abstains BY DESIGN, and the gate reports clean forever over a tree it never compared. That is the exact dead-gate shape this row exists to close, reachable only through the row's own configuration. Admits-answer-precondition: A VERIFICATION WRITE, reverted in the same turn. CLOUD-1672's new gate reports clean over this tree, and clean is byte-identical to a dead gate — so one workflow's `version:` is being changed to a wrong value to confirm the predicate names it, then changed straight back. Only a direct write can do that; no read surface can make a gate fire. Nothing of it reaches a commit: the file is restored with `git checkout --` before the tree is staged, and the diff will show it unchanged. Admits-answer-rejected-route: `patch run first` reaches the same refusal under another program name: the mutating-verb table already covers `>`, `tee`, `sed`, `cp`, `install` and `git` over this path. `config read first` was TAKEN — `batten.toml`'s new `mise-preset-tree` row and its `sources` list were read, and reading them is what identified the glob as the one thing no fixture can verify.
The header opened on "the surface it decides" and named scope the manifest's load-bearing omission, both written when a manifest carried exactly one. The mechanism moved onto each module in the previous commit and the prose did not, which is the same stale-comment-beside-a-changed-mechanism defect CLOUD-1477 was filed on -- caught here in this branch's own diff rather than by the next reader. The CLOUD-1181 paragraph is kept rather than rewritten: why a preset needed to declare a scope at all is still exactly right, and it is the reason the field survives in a different shape rather than being dropped. WHY THIS COMMIT CARRIES THE BREAK. `semver check` reports `struct_pub_field_missing` against this branch: `Manifest.scope` is gone, and a removed public field is a break however non-exhaustive the struct is. The break is in the PREVIOUS commit, whose message cannot carry the footer without rewriting it -- so the declaration rides here, which is the pattern `9ea4da6a` already followed for a waiver landed two commits after it was written. Refs: CLOUD-1672 BREAKING CHANGE: `preset::Manifest` loses its `scope` field and `modules` becomes `&[PresetModule]` rather than `&[(&str, &str)]`. A consumer reading either must move to `Manifest::decides`, `Manifest::scopes` or `Manifest::modules_at`, which answer the same questions per module. The field could not stay: it asserted that a preset decides exactly one surface, which is false for any preset whose subject spans a call and the tree.
`every_class_a_preset_raises_is_declared_by_its_own_manifest` and its mirror destructured `manifest.modules` as `(pointer, source)`, which stopped compiling when a module became a struct carrying its own scope. FOUND BY `cross-check`, NOT BY THE CHECK THAT SHOULD HAVE. `cargo check -p batten` does not build test targets, so the in-crate census compiled nowhere until the Windows leg type-checked `lib test` -- a verify lap spent on something `--all-targets` answers in six seconds. The two cases are the manifest's own anti-vacuity pair, so a silent break here is a preset shipping a class with no gloss, or declaring one nothing raises. Verified: `cargo check -p batten --all-targets` clean, and `mise run cross-check` green on x86_64-pc-windows-gnu, which is the gate that refused. Refs: CLOUD-1672
`batten-check` refused the new module under this repository's own `no-appeal-to-authority` row, at the literal and at both fixtures. The rule is right and the module was wrong: a bare repository name is indistinguishable from citing a vendor as an authority, and the row's exemption recognises the forms a coordinate actually takes -- a step's `uses:` key, or a forty-character digest. So the value is written the way a workflow writes it and the parts are derived, which is the shape `mise-action-floor` already uses for the same reason and which also means the action name and its pin cannot drift apart inside the file. The fixtures carry full digests rather than truncated ones, which is both what the exemption recognises and what a real workflow contains. The digest is illustrative and nothing compares it: pinning the ACTION is a separate question from pinning the mise it installs, and conflating the two is what let CLOUD-1672's defect exist at all. Verified: `policy test` 64 bundles, 814 passed -- unchanged, so deriving the name did not move any predicate -- and `batten check --rule no-appeal-to-authority` exits clean over the tree. Refs: CLOUD-1672
`rebase-not-hand-stepped` separates the lap it bans from the rebase it must leave alone by asking whether the line names `origin/main`. But `git rebase --onto <newbase> <upstream> <branch>` names it too and is not a lap at all: it replays a RANGE somewhere else, dropping commits from the bottom, which the landing loop has no notion of and cannot perform. So the row refused an operation its own remedy does not offer -- and a `shape` row declares no `[[verdict]]` class and this one carries no `bypass_env`, so there was no sanctioned route to it whatsoever. MEASURED: a branch carrying four commits that `closing-key-check` required be dropped could not drop them, and the refusal's advice named `land`, which would have replayed all twelve. THE DISCRIMINATOR HAS TO BE A FLAG, which is the one thing `pattern` cannot see: the operand matcher drops flags before comparing, so the only predicate over a flag a row could previously write was "must be present". `unless_contains` is `contains` in the other polarity, `shape` only -- a column that switches a deny off has no business on a precondition row, where the same bytes would silently stop DEMANDING a receipt. It is matched against the same LINE as `contains`, and that is load-bearing in the permissive direction: matched against the segment, an `echo --onto` on line one would exempt a genuine lap on line two. The row's `reason` also still told every reader it warns rather than denies, which the comment block above it had already recorded as false in every clause. Verified: `land_hand_stepping` carries both directions -- `a_range_move_onto_main_is_not_this_rows_business` and `the_exemption_does_not_reach_another_lines_lap` -- judged against the committed `batten.toml` over the compiled binary, with the existing deny arms unchanged so the exemption cannot widen into the lap itself. 11 passed. Weakens: rebase-not-hand-stepped no longer refuses a `git rebase --onto` naming `origin/main`. The narrowing is a corrected false deny rather than a relaxation: the exempted command is a history edit the landing loop cannot perform, so no call this row exists to catch is now permitted. The deny arms for every lap spelling are unchanged and `the_exemption_does_not_reach_another_lines_lap` pins that the exemption cannot be borrowed from a neighbouring line. Refs: CLOUD-1461 Admits: e95ab54d2a1069aeef8fabd76c18613979c1aefd6a2e28930ddd85e3546265f7 Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:52ec48bc576c1c1aa70126081654573118c23855 Admits-epoch: cfc384e2524c60c47a938159b26cdfafcea35e08bfdebdddbeeb2a90c84c1162 Admits-author: alec@wenzowski.com Admits-prev: 48d1eec18e1480b0a3f1f941763ee6705ff0eadb5140db2bb02a5fbc101081c5 Admits-answer-lost: The row keeps refusing `git rebase --onto origin/main <upstream> <branch>` — a range move the landing loop cannot perform — with no [[verdict]] class to override and no bypass_env. A wrongly refusing gate is a defect, not an answer; leaving it means the branch cannot drop the four commits `closing-key-check` requires be dropped, and the reason string keeps telling every reader the row warns when it denies. Admits-answer-precondition: No surface writes a [[rule]] column. `batten config` reads the table and never edits it, so adding `unless_contains` to `rebase-not-hand-stepped` and correcting its stale `reason` prose can only be a direct write to batten.toml. It is a fifteen-line diff a reviewer sees whole in the PR. Admits-answer-rejected-route: config read first — rejected because it is a read: it prints the table and returns, and there is no `config set` or `config patch` for a rule column. patch run first — rejected because no patch surface exists for batten.toml; the only patch route is the write itself. Admits: 7b50267372a83706050e0f3c0537978e5fc258d6c6bfffbc2cf6a73de7587b4b Admits-rule: protected-mutation Admits-verdict: path write refused Admits-subject: batten.toml Admits-anchor: call:52ec48bc576c1c1aa70126081654573118c23855 Admits-epoch: 25b643b9be1ee81860f72805ef8554a00e5c0b1f5d5b1e8b3ea86233e88bd405 Admits-author: alec@wenzowski.com Admits-prev: e95ab54d2a1069aeef8fabd76c18613979c1aefd6a2e28930ddd85e3546265f7 Admits-answer-lost: The `unless_contains` column lands with its reasoning nowhere — the block would still read as though `contains` were the whole predicate, and the next reader tightening this row would delete the exemption as unexplained. The block already carries a recorded correction for exactly this failure (a comment overstating its own gate); leaving it silent repeats it in the other direction. Admits-answer-precondition: Second write of the same change: the comment block above `rebase-not-hand-stepped` records why each of its columns is what it is, and a new column landing with no entry there is the drift that block exists to prevent. No surface edits a config comment; only a direct write can. It is in the same reviewed diff as the row itself. Admits-answer-rejected-route: config read first — rejected: it prints the table and returns, and it does not read comments at all, let alone write them. patch run first — rejected: there is no patch surface over batten.toml; the write is the only route.
`every_rule_column_carries_a_fact_verdict` reads the `Rule` struct's own source and requires every column to say what it declares. The new exemption column said nothing, which is the silence that arm exists to refuse -- an unclassified column is declarable on a mediated row and read by nothing. It is not fact-bearing for `contains`'s reason and in the other polarity: it is a condition over the command line another column already declared, not a new fact about the tree. FOUND BY `verify`, ONE LAP LATE. The arm lives in `crates/batten/src/rules.rs`'s own test module, so `cargo check -p batten --all-targets` type-checks it and does not run it -- the same gap between checking and running that cost a lap two commits ago, seen from the other side. Refs: CLOUD-1461 Weakens: rule-predicate-changed rule[rebase-not-hand-stepped].unless_contains
96352c8 to
2ce05b8
Compare
|
❌ The last analysis has failed. |
|
/fast-forward |
|
Refusing to fast-forward #914 at |
Closes CLOUD-1672. Closes CLOUD-1477.
DO-NOT-CLOSE CLOUD-1461
DO-NOT-CLOSE CLOUD-1398
DO-NOT-CLOSE CLOUD-1620
Two rows on one branch, plus one gate repaired in passing. CLOUD-1672 is the urgent one — it is a live outage fix, and nothing in the repository could land while it held.
On the declined keys. The lease is contended, so
landserialises by stacking this branch on the queue ahead of it — this head currently carries #905 (CLOUD-1398) and #912 (CLOUD-1620) below its own ten commits. Those PRs close their own rows; this one carries them so the stack can land in order, and declines them explicitly rather than stranding them. CLOUD-1461 is landed and Done already; the section below says what this branch repaired in its gate.CLOUD-1672 — the toolchain CI installs was not the one the tree pins
batten.tomlpins mise to 2026.9.1 by per-platform URL and digest.jdx/mise-actionis digest-pinned at3c2e0cf8, but that pins the action — it resolves which mise to install on its own, at job start. Two authorities on one version, and nothing compared them.On 2026-09-08 the action resolved v2026.9.3, whose linux-x64 asset 404s:
All 8 jobs of
release-artifactsrun 34206034815 died at that step inside 11 seconds. v0.0.152 published carryingbatten.schema.jsonand none of its seven binaries.ci.ymlrun 34220313465 failed the same way in 53s, so nothing could land — the landing lease was contended across the whole fleet for the same reason.The
[[provision]]row's own comment already named the harm one layer down: "a runner that updated itself under a container would make two sessions on one commit run different toolchains, which is the disagreement[[provision]]'s pinning exists to remove." The pin was committed and correct throughout; it simply did not reach the layer where the install happened.The fix, both halves. All 35
mise-actionsteps across 24 workflows declareversion: 2026.9.1. And because a rule without a runnable gate is half a change,action-version-matches-the-pinnow refuses drift:job pin otherwhere a declared version disagrees with the provision row,job pin missingwhere a step declares none and hands the choice to the installer.Three properties worth calling out:
2026.9.1would be a third authority and would go stale the first time the pin moved.jobs, one carryingprovision— never by filename. A preset ships to every consumer, so rule 1 forbids naming their paths; the enabling row'ssourcesis where this consumer says which files those are.Engine half: a manifest declares a scope per module.
Manifest.scopesaid a preset decides exactly one surface — true of every preset that existed, false once a subject has something to say about both.miseis that subject: reproducing a task's argv is a question about a call; the toolchain a workflow installs is a question about the tree. Two constraints assumed the old shape and both now key on the pair: the load-time scope check (decides(scope), naming the scopes the preset does decide), and the duplicate-registration check, which read the second enabling row as dead config when it decides a disjoint surface.CLOUD-1477 —
batten-checkread a cache family nothing filled on its architecturebatten-checkreadci-on x64 while its only warm writer ran on arm64. rust-cache composesrunnerOS-runnerArchatconfig.ts:93, inside the restore prefix assigned at:133— two entries that can never touch. Not a partial hit: no hit, ever, at 683s the critical path of the workflow.CLOUD-1453 shipped the eviction half (
cache-sweep.yml, v0.0.142), but eviction was not the cause: across jobs 100903936005 and 101280975479 a swept store moved this job 683s → 600s, 12%, which is pressure lifting rather than a restore landing.ci.yml:601-618declined the fix on a 10 GiB ceiling the sweep had already removed, and named two alternatives that are both closed.So
cache-warm-linux-x64writesci-on x64,batten-checkbecomessave-if: falselike every other pull-request consumer, andread-family-has-a-warm-writerrefuses a read-only consumer whose family nothing fills on its architecture — scoped to pure consumers deliberately, sincecross-,semver-,perf-and friends write their own entries on purpose.One cost, stated rather than buried: the release workflow serialises (
cancel-in-progress: false), and the first run after merge compiles the x64 entry cold, so that one run stretches and the next release queues behind it. Self-correcting, and the price of the fix.CLOUD-1461's gate refused an operation its own remedy does not offer
Not this PR's subject, and not closing that row — it is landed and Done. But
rebase-not-hand-steppedwas wrongly refusing, which is a defect rather than an answer, and repairing it is what let this branch reach a landable shape at all.The row bans a hand-driven landing lap and separates it from the rebase it must leave alone by asking whether the line names
origin/main.git rebase --onto <newbase> <upstream> <branch>names it too, and is not a lap: it replays a range somewhere else, dropping commits from the bottom, whichlandhas no notion of and cannot perform. Ashaperow declares no[[verdict]]class and this one carries nobypass_env, so there was no sanctioned route to it whatsoever. Measured here: this branch arrived carrying four commits it did not author thatclosing-key-checkrequired be dropped, and the refusal's own advice namedland, which would have replayed all twelve.The discriminator has to be a flag, which is the one thing
patterncannot see — the operand matcher drops flags before comparing, so the only predicate over a flag a row could previously write was "must be present".unless_containsiscontainsin the other polarity:shapeonly, since a column that switches a deny off has no business on a precondition row where the same bytes would silently stop demanding a receipt; and matched against the same line, which is load-bearing in the permissive direction — matched against the segment, anecho --ontoon line one would exempt a genuine lap on line two.the_exemption_does_not_reach_another_lines_lapis that arm.The row's
reasonalso still told every reader it warns rather than denies, which the comment block above it had already recorded as false in every clause. Groomed asrule-predicate-changedon CLOUD-1477, since the narrowing is a corrected false deny: no call the row exists to catch is now permitted, and every lap spelling stays denied.Verification
mise run policy-test: 64 bundles, 814 passed.ci-cache-declaredengine tier 17/17;land_hand_stepping11/11.sourcesglob actually deliversbatten.toml— and without it the module abstains by design and reports clean forever. Driven over this checkout instead: clean as committed, and moving one workflow's version produced.github/workflows/scorecard.yml:53 action-version-matches-the-pin, exit 2, pointer-only. Restored withgit checkout --; the diff is unchanged.a_drifted_version_in_this_repository_is_refusedis that proof as a standing case.git rebase --onto origin/main <upstream> <branch>ran unrefused where it had been denied.mise run verifyhas returnedfast-forward-greenon every head this branch has had tonight; every failed lap was the landing lease, spending zero CI matrices.Overrides
protected-mutationrefuses writes to.github/workflows/**,policy/**andbatten.toml. Every one went throughbatten override request/spend; theAdmits-*blocks are commit trailers, each answering the class's declared precondition, what is lost, and the rejected route.A gate hole found while doing that, filed rather than absorbed: a
sed -iagainstbatten.tomlwas not refused where theEdittool on the same path was.sedis in the[[verb]]table andpolicy explainprints that it is covered, so this is the engine's call resolution rather than the config — CLOUD-1664, §1 onhook.rs. It was reported in the admission and not relied on.Follow-ups filed
sed -iwrites a protected path unrefusedperf's 574s cause, named in CLOUD-1453's title and never establishedmcp callrenders a failed write as{}and exits 0CLOUD-1440 already owns the stale timeout budgets.