Skip to content

feat(install): ship a single-binary-first install path with a verified download - #310

Merged
wenzowski merged 1 commit into
mainfrom
wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager
Aug 11, 2026
Merged

wenzowski merged 1 commit into
mainfrom
wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager

Conversation

@wenzowski

Copy link
Copy Markdown
Contributor

Releases have carried seven target archives since CLOUD-108, with nothing on the
consuming side. There was no install script, no [package.metadata.binstall],
and nothing asserting that the asset name a consumer resolves is the one
mise-tasks/dist writes. "Single-binary-first" is an ordering claim — the binary
works with no package manager, and package managers are conveniences on top — and
the repo could not make it: the only way to get a release binary was to read a
workflow.

What lands

install.sh — POSIX sh, assuming only what curl … | sh already proves is
present. Detects the target (musl on Linux, so the binary runs whatever the
host's glibc), resolves the release through the API, downloads the archive and
installs batten to ${XDG_BIN_HOME:-$HOME/.local/bin}. Pointer-only KEY=VALUE
output; exit 0/1/2 per house-style §7.

It refuses to install unverified bytes. Every asset is checked against the
SHA-256 digest the release API reports for it, and a mismatch — or an asset the
API reports no digest for — installs nothing. There is no flag to skip it. What
that digest is not is a supply-chain signature: both halves come from GitHub,
so it proves the bytes arrived intact, not that they are the bytes a maintainer
intended. CLOUD-278 (checksum manifest) and CLOUD-264 (signature format) remain
the stronger claims; this is the floor beneath them, and it needed neither to
land — the API already carries the digest, measured on all ten assets of
v0.0.61.

Two things measured rather than assumed. api.github.com answers
pretty-printed JSON (403 lines for v0.0.61) where every other client here
sees compact, so the parsing commits to neither wire form and a test pins both.
And the token reaches curl through --config - on stdin rather than argv, where
ps would show it to any other user on the box — which is also why there is no
wget fallback, since wget has no equivalent.

mise run install-check — the mechanism CLOUD-65's three acceptance clauses
did not have. A rename in dist that forgets one of its two readers is green in
CI, green in the release matrix, and a 404 on a user's machine. So the gate
proves the contract by running it: dist owns archive naming
(archive_stem, archive_ext — the latter extracted from main so it is
callable), install.sh owns its target list (--targets) and what it will ask
for (--asset-name), and the gate calls each. The matrix has one authority and
it is the workflow's, the same property release-assets-check holds. The
Windows exclusion is derived through dist's own is_windows_target, never
restated. It also fails on a committed executable, judged on format magic rather
than a path convention, reporting the path and never a byte.

The one restatement that cannot be avoided is the binstall template — cargo
reads TOML, not a shell function — so the gate resolves it, honouring pkg-fmt
and its per-target override, and compares against dist's answer for all seven
targets.

What this deliberately does not claim

cargo binstall batten by name needs the crate on a registry, which
CLOUD-205 defers along with the public repository. What works today is
cargo binstall --git …, and the registry form starts working on the day that
decision is revisited with no further edit. The remaining half of
"package-manager distribution" — Homebrew, the mise/aqua registries — is
downstream of both a public repo and CLOUD-278's manifest, and is recorded on
CLOUD-65 rather than attempted here.

README keeps its existing status note verbatim and gains an Install section that
states plainly that a token is required while the repository is private. That
reads CLOUD-205's "no install docs" as "do not imply public availability", not
"do not build or document the private path" — the same decision asks the release
machinery to keep running "so the flip is cheap when it comes."

Verification

  • mise run install-check green; tests/install-check.bats (11) red on each
    mistake it names — a matrix target install.sh does not serve, a target it
    claims that no leg builds, a rename in dist, a binstall URL resolving
    elsewhere, a committed ELF — and exit 2 on each way of being unable to look.
  • tests/install.bats (13) drives the real code path against a file://
    fixture API rather than a stubbed curl, so the request shape and redirect
    handling are exercised. Both refusal cases assert nothing reached the
    destination.
  • End-to-end on a real tag: install.sh against v0.0.61 in this sandbox
    installed a static-pie musl binary reporting batten 0.0.61, with
    verified=sha256. That clause matters because a release-triggered path
    reaches no PR and no gate — the hole that cost CLOUD-258 six silent releases.

Refs: CLOUD-65

@linear-code

linear-code Bot commented Aug 11, 2026 •

Copy link
Copy Markdown
CLOUD-65 Ship a single-binary-first install path and package-manager distribution

Why
Batten should install as a standalone binary first, then through cargo binstall, mise, and package managers, without committing binaries.

Acceptance

  • A one-line install works
  • cargo binstall batten works
  • No binary is committed to the repository

Review in Linear

@wenzowski
wenzowski marked this pull request as ready for review August 11, 2026 19:18
@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch 2 times, most recently from 905ccc6 to ce1fda5 Compare August 11, 2026 19:27
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (ec3639a) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (ce1fda5).

Target branch (main):

commit ec3639a5f87a043c350ff85159db768a3fe3cfcf (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 18:51:35 2026 +0000

    fix(session-start): run doctor inside the hook's synchronous window
    
    `mise install` returning is not "the toolchain is settled". doctor provisions
    what mise does not own — the rustup cross targets above all — and left outside
    the SessionStart window it runs for the first time inside the first
    `mise run verify`, concurrently with whatever the sandbox is still laying down.
    Measured on a cold container 2026-08-07: that first verify died in doctor with a
    `detected conflict` rollback on rust-std-aarch64-apple-darwin, and a second
    doctor, nothing changed but time, exited 0. The message names cross-compilation,
    so it costs the reader a debugging session on a machine where nothing is broken.
    
    This is not a retry. It does not make the race survivable, it empties the window
    the race needs: by the time any task runs, the targets are already installed.
    CLOUD-220's per-toolchain mutex in target-ensure serializes concurrent writers
    and still stands — it covers the warm case (the verify graph racing itself,
    CLOUD-201), this covers the cold one. doctor itself is unchanged.
    
    The step goes through the hook's existing `step` helper, so it inherits the
    loud-failure contract, and runs after mise install (its rustup half needs the
    provisioned toolchain) and before container-preflight (a halt, which wants
    provisioning finished). tests/session-start.bats records every mise invocation
    through its stub and asserts that ordering, rather than grepping the source;
    doctor joins container-preflight in being neutralised there, because its rustup
    half reaches the network and test:bats already depends on `doctor --no-targets`.
    
    Refs: CLOUD-218

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit ce1fda51c8d5e3a12e2abca2725db7ded19d12ed (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (ec3639a) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (ce1fda5). main (ec3639a) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (ce1fda5). Branches appear to have diverged at 37bf48d:

* ce1fda51c8d5e3a12e2abca2725db7ded19d12ed feat(install): ship a single-binary-first install path with a verified download
| * ec3639a5f87a043c350ff85159db768a3fe3cfcf fix(session-start): run doctor inside the hook's synchronous window
|/  
* 37bf48d4f645e57937455ef8ca4d791a4859bf4a feat(spec): emit the derived read-only allowlist beside the tree

commit 37bf48d4f645e57937455ef8ca4d791a4859bf4a
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 18:58:45 2026 +0000

    feat(spec): emit the derived read-only allowlist beside the tree
    
    `spec::read_only_allowlist` derives §5's agent allowlist from the same walk
    that builds the emitted tree, so an unclassified command cannot leak in — but
    it had no caller outside this crate's own tests. A derivation nothing emits is
    one every consumer has to re-implement, and this filter's failure mode is
    advertising a write-bearing verb as agent-safe: `enforce` may run user-supplied
    commands and `hook` adjudicates someone else's write, and both stay off the
    list only because the filter is `effect == read`.
    
    So emit it. `SpecDocument` flattens the command tree at the document root and
    adds `read_only_allowlist` beside it, which keeps every root key a consumer
    already reads (`path`, `subcommands`, …) exactly where it was.
    
    The pinning test asserts the emitted key IS the `effect == read` filter over
    the emitted tree, recomputed from the same document — not a second copy of the
    path list, which `allowlist_is_exactly_the_read_commands` already holds.
    
    Refs: CLOUD-217

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch from ce1fda5 to fa488f4 Compare August 11, 2026 19:35
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (f34f99a) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (fa488f4).

Target branch (main):

commit f34f99a3a2c842b064087c3deb6e2476f412ed29 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 18:59:53 2026 +0000

    test(findings): hold the no-escalation law over the bytes, not over a struct
    
    CLOUD-80's residual acceptance clause — "escalation on re-touch is absent" —
    was carried by an in-memory test that drives `FindingRecord::upsert` on a
    struct. That test cannot see either way a stored tier could actually move: a
    write path that re-derives it, and a later scan that re-rates the rule. Both
    need a real store dir.
    
    Two store-level tests, asserted over the record file:
    
    - `an_nth_observation_never_re_tiers_the_stored_record` runs the same identity
      through `record` five times, total over `RuleSeverity::ALL` so every
      `AdvisoryTier` is exercised, and compares the persisted `"tier"` line
      byte-for-byte against the first observation's — while asserting the
      occurrence count did move, so it cannot pass on a store that recorded
      nothing.
    - `a_re_rated_rule_never_re_tiers_a_settled_finding` records one identity at
      `warn`, then again at `deny`, and pins that the settled record keeps tier
      `caution` and severity `warn`. Severity is not an identity input, so the
      re-rating routes to the same record; `record` reusing it rather than
      refreshing from the rule now firing was documented and untested.
    
    Negative control run before landing: re-deriving the tier in `record`'s update
    path, plus a count-keyed escalation, fails both new tests and leaves the
    in-memory sibling green.
    
    Refs: CLOUD-80

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit fa488f43daccc14b3a9698a6a514bb89217c50d6 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (f34f99a) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (fa488f4). main (f34f99a) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (fa488f4). Branches appear to have diverged at ec3639a:

* fa488f43daccc14b3a9698a6a514bb89217c50d6 feat(install): ship a single-binary-first install path with a verified download
| * f34f99a3a2c842b064087c3deb6e2476f412ed29 test(findings): hold the no-escalation law over the bytes, not over a struct
|/  
* ec3639a5f87a043c350ff85159db768a3fe3cfcf fix(session-start): run doctor inside the hook's synchronous window

commit ec3639a5f87a043c350ff85159db768a3fe3cfcf
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 18:51:35 2026 +0000

    fix(session-start): run doctor inside the hook's synchronous window
    
    `mise install` returning is not "the toolchain is settled". doctor provisions
    what mise does not own — the rustup cross targets above all — and left outside
    the SessionStart window it runs for the first time inside the first
    `mise run verify`, concurrently with whatever the sandbox is still laying down.
    Measured on a cold container 2026-08-07: that first verify died in doctor with a
    `detected conflict` rollback on rust-std-aarch64-apple-darwin, and a second
    doctor, nothing changed but time, exited 0. The message names cross-compilation,
    so it costs the reader a debugging session on a machine where nothing is broken.
    
    This is not a retry. It does not make the race survivable, it empties the window
    the race needs: by the time any task runs, the targets are already installed.
    CLOUD-220's per-toolchain mutex in target-ensure serializes concurrent writers
    and still stands — it covers the warm case (the verify graph racing itself,
    CLOUD-201), this covers the cold one. doctor itself is unchanged.
    
    The step goes through the hook's existing `step` helper, so it inherits the
    loud-failure contract, and runs after mise install (its rustup half needs the
    provisioned toolchain) and before container-preflight (a halt, which wants
    provisioning finished). tests/session-start.bats records every mise invocation
    through its stub and asserts that ordering, rather than grepping the source;
    doctor joins container-preflight in being neutralised there, because its rustup
    half reaches the network and test:bats already depends on `doctor --no-targets`.
    
    Refs: CLOUD-218

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch 2 times, most recently from a0b4190 to 3febad6 Compare August 11, 2026 19:52
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (42ef663) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (3febad6).

Target branch (main):

commit 42ef66342352cf2219fd94ab2503dc228e1dd8b5 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:09:46 2026 +0000

    test(session): compare the whole store across a restart, not a subset
    
    The predicate is that a kill-and-restart preserves the findings store
    byte-for-byte, and the assertion was over the fields the test helper
    happens to parse — fingerprint, rule and instance counts. It would not
    have noticed the tier, the presentation or a disposition changing across
    the restart, which are exactly the fields no verb can vary yet and so the
    ones nothing else is watching.
    
    Refs: CLOUD-83

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit 3febad6dfeb8f98563d95b03741f3695b27ac4e0 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (42ef663) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (3febad6). main (42ef663) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (3febad6). Branches appear to have diverged at 78d313a:

* 3febad6dfeb8f98563d95b03741f3695b27ac4e0 feat(install): ship a single-binary-first install path with a verified download
| * 42ef66342352cf2219fd94ab2503dc228e1dd8b5 test(session): compare the whole store across a restart, not a subset
| * 497f6d5b98b533c525d6da0dc678604082dfa83a test(session): pin what a warm fork must keep
| * e7165259b0afb55ca82b7d23a72b18bb6987cb88 feat(state): record where a session left the journal
| * 708d12c6e7e58b4653f18373c94798ec9eb33233 feat(session): give a warm fork somewhere to resume from
|/  
* 78d313aea99ff609bf6e24360538bd8ba4543354 fix(lock-complete): name lock-check as the remedy, not the raw regeneration command

commit 78d313aea99ff609bf6e24360538bd8ba4543354
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 18:56:11 2026 +0000

    fix(lock-complete): name lock-check as the remedy, not the raw regeneration command
    
    The unlocked-tool pointer spelled out the regeneration command, which put the
    literal into an executable line — where tests/lock-complete.bats's "makes no
    network call" assertion reads it as this gate fetching. That assertion is a
    coarse string match on purpose and is worth keeping coarse, so the message
    moves instead.
    
    `mise run lock-check` is also the better pointer on its own terms: it is the
    single sanctioned lockfile writer, since `[settings] lockfile = false` denies
    the write to everything else (CLOUD-223).
    
    Refs: CLOUD-333

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch 2 times, most recently from 06d03b7 to 652c038 Compare August 11, 2026 20:09
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (3fde7a8) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (652c038).

Target branch (main):

commit 3fde7a81593c6a60d838b6006f8db6a638b4738f (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:30:27 2026 +0000

    fix(bench): keep the workflow's summary block off shellcheck's SC2016
    
    A backtick pair inside single quotes reads as legacy command substitution
    to shellcheck, which actionlint runs over every `run:` block, so the
    summary line failed the gate. Double-quoted with escaped backticks keeps
    the markdown code span and says nothing shellcheck has to guess at.
    
    Prettier's table realignment in README rides along — hk staged it.
    
    Refs: CLOUD-207

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit 652c0386b7172840672f590770e0600f7ce55b44 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (3fde7a8) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (652c038). main (3fde7a8) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (652c038). Branches appear to have diverged at 040fa56:

* 652c0386b7172840672f590770e0600f7ce55b44 feat(install): ship a single-binary-first install path with a verified download
| * 3fde7a81593c6a60d838b6006f8db6a638b4738f fix(bench): keep the workflow's summary block off shellcheck's SC2016
| * 8854916d55b1126fcae162c601404edfc5cc6f9e feat(bench): measure the invocation cost, publish it, and gate it
|/  
* 040fa566b81b0c89387ac7bdb833e0e43d028e1c docs(resolve): mark §5's max_effect as specified, not implemented

commit 040fa566b81b0c89387ac7bdb833e0e43d028e1c
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:24:16 2026 +0000

    docs(resolve): mark §5's max_effect as specified, not implemented
    
    Two module headers asserted `max_effect` as an invariant already in the tree:
    `resolve.rs` said the raise-only override rule "extends §5's `max_effect`
    invariant to the config layer", and `verbs.rs` said sharing the effect
    vocabulary keeps "the raise-only `max_effect` rule" meaning one thing across
    the tool. Neither is true today. `max_effect` is per-flag effect annotations
    plus a monotone maximum over them; `Effect` is declared per command and carries
    no ordering, so there is nothing to take a maximum of.
    
    That is the CLOUD-198 class, and `resolve.rs` was the costly instance: it
    presented this layer's raise-only rule as a corollary of a mechanism that
    exists, so a reader checking whether config-layer monotonicity was load-bearing
    on its own found a sentence telling them it was not.
    
    Both now name the invariant as specified-not-implemented and point at CLOUD-27,
    which is where the implementation rides. No test: the Ready block puts the test
    obligation on the implementation path, and a doc comment stating a gap has
    nothing to assert until the gap closes.
    
    Refs: CLOUD-217

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch 3 times, most recently from 5574b57 to 466e90e Compare August 11, 2026 20:35
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (6569aeb) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (466e90e).

Target branch (main):

commit 6569aeb303e942642dd22feab96f221c67f7027e (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:02:59 2026 +0000

    feat(rules)!: rename the command kind's `run` column to `check`, reserve `fix`
    
    House style §9 specifies the `command` rule kind as a check/fix duality: an
    inspection-only `check` is the gate — the only side enforcement ever runs — and
    an optional mutating `fix` repairs what it condemned. The shipped `Rule` carried
    one `run` column, which does not express the split.
    
    §2 declares no back-compatibility surface and no deprecation aliases, so every
    config written against `run` becomes a breaking migration later. Today the key
    appears in no shipped config at all — only fixtures, tests and the README — so
    the rename costs nothing. It will not stay that way.
    
    `fix` parses and is executed by nothing: serialised fix execution is a
    capability this engine does not have. `enforce` refuses a row declaring one
    rather than running the check side and silently ignoring the repair, which would
    report green over work nobody did. Reserving the key now means an author who
    writes it is writing the final spelling.
    
    `run` survives as a refusal-only field, the shape `OverrideConfig::
    min_batten_version` already uses: "unknown field `run`" reads as a typo, where
    this is a rename with one specific fix, and the refusal has to carry it
    (CLOUD-122). It is deliberately outside `Rule::columns` — that census classifies
    the columns a kind may carry, and no kind carries this one.
    
    Both refusals are exit 1, not the exit 2 the issue's §5/§7 asked for. §7 makes 2
    the policy verdict — a violation found in the repository, or a mediated call
    denied — while a config naming a key or a capability this build does not have is
    the config-or-usage class. §5 spells the structurally identical sibling refusal
    (a rule the read-only half cannot honestly run) as exit 1, and `run_static` has
    implemented it that way since CLOUD-170; the issue's §3 describes that same
    landed refusal as exit 2, which is falsified by the code it describes. Emitting
    2 here would also make an engine gap read to a harness as a policy deny, which
    is what the structural fail-open exists to prevent.
    
    Refs: CLOUD-215

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit 466e90e572b3cbcfff37dc60a88bb0867e0ae8ae (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (6569aeb) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (466e90e). main (6569aeb) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (466e90e). Branches appear to have diverged at 18bb416:

* 466e90e572b3cbcfff37dc60a88bb0867e0ae8ae feat(install): ship a single-binary-first install path with a verified download
| * 6569aeb303e942642dd22feab96f221c67f7027e feat(rules)!: rename the command kind's `run` column to `check`, reserve `fix`
|/  
* 18bb41610d628560c9babe07224ae6c30478c81c ci(hooks): remind once when the instruction surface moves under a running session

commit 18bb41610d628560c9babe07224ae6c30478c81c
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:29:23 2026 +0000

    ci(hooks): remind once when the instruction surface moves under a running session
    
    A session loads its hook wiring and reads its instruction files once, at start.
    When the contract then changes on `main`, the running session keeps executing the
    old one with no signal that it drifted: `issue-guard` landed mid-session and a
    live session readied a PR whose branch and commits carried no `CLOUD-<n>` key,
    because that hook was never in that session's wiring.
    
    `contract-drift` hashes the tracked contract surface (`AGENTS.md`,
    `.claude/rules`, `.claude/settings.json`, `hk.pkl`, `mise-tasks`) in one
    `git hash-object` pass — 63 files, 8ms — keyed per session under `.git/`, and
    names the paths that moved. Silence is the default; a change-set is reported once,
    because reporting overwrites the snapshot. Pointer-only: paths and a count, never
    a byte of the file, since a reminder carrying the new text is a mirror and a
    mirror is cleared by reading the hook instead of the file.
    
    Not `PreToolUse`, which the Ready block specified: that event's only model-facing
    channel is exit 2, which blocks the call, and CLOUD-97 and CLOUD-219 each ruled a
    deny out independently. `PostToolBatch` documents `additionalContext` firing
    "before the next model request", which is the same instant as "before the next
    lifecycle step"; `SessionStart` seeds the snapshot before any tool runs, since an
    autonomous session's first batch is routinely fetch+rebase and a snapshot written
    after it would record the drift as its baseline.
    
    Measured while building it: the `PostToolBatch` entry took effect within the
    session that added it, so the channel works and the premise is narrower than the
    title reads. The reminder therefore tells the agent to check whether a new hook is
    loaded rather than asserting it cannot be.
    
    Refs: CLOUD-187

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch from 466e90e to cba3551 Compare August 11, 2026 20:43
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (6947232) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (cba3551).

Target branch (main):

commit 6947232b13bc17174986a0e3bfe528d848617519 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:57:59 2026 +0000

    perf(hk): glob batten-check and macos-link-check, and gate the glob's honesty
    
    `hk check` ran three steps unconditionally, because a step with no `glob` is
    never skipped. `batten-check` is `cargo run -p batten -- check`, so every
    commit paid a debug build whatever it touched: 9.47s cold from a fresh clone
    (CLOUD-212 run 1, D8) against 0.16s for the cheapest gate in the same run, and
    133-141ms warm, forever.
    
    The glob is the union of what `batten check` ACTUALLY reads, which is not the
    two things the obvious reading gives. Read at run_check_with in
    crates/batten/src/lib.rs, it evaluates every `[[rule]]` over that rule's own
    glob — and those reach outside crates/, to mise.toml, .github/workflows/*.yml
    and tests/*.bats — plus `budget::measure_all`, because a declared budget is a
    gate under `check` and not only under `policy budget` (CLOUD-50). That last one
    makes AGENTS.md and .serena/project.yml genuine inputs, so "a Markdown-only
    change cannot change this verdict" is false for the most-edited Markdown file
    in the repo, and a glob written from the obvious reading would have switched
    the gate off for it. Cargo.toml and Cargo.lock are in because the task uses
    `cargo run` deliberately, to judge the engine and the config as the pair that
    ships.
    
    `macos-link-check` globs the manifests alone: its predicate is `cargo metadata
    --filter-platform` over the resolved graph, and nothing else can move that
    graph. `no-docs-tree` deliberately keeps no glob — its input is the whole
    index, including a docs/ path an earlier commit left behind, and at ~95ms that
    is affordable.
    
    Deriving batten-check's list from batten.toml by hand makes hk.pkl a second
    authority over a set the config already defines, and a second authority narrows
    silently: add a rule whose glob names a new path and the step stops running for
    commits that touch only it, with nothing going red. So the glob ships with its
    mechanism (non-negotiable 2). `mise run batten-glob-check` is a pure function
    of the two committed files — every rule glob and every declared budget path
    must be covered verbatim or subsumed by a `P/**` entry, and a config it can
    parse nothing out of is exit 2 rather than a vacuous pass.
    
    Selection is asserted as data, never as a timing: `hk check --plan --json`
    prints each step's status without running it, and tests/hk-selection.bats pins
    both directions over the repository's own hk.pkl — README.md skips
    batten-check, AGENTS.md does not.
    
    Refs: CLOUD-224

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit cba3551b83c8aa06856f963002510f66a420a42b (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (6947232) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (cba3551). main (6947232) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (cba3551). Branches appear to have diverged at 6569aeb:

* cba3551b83c8aa06856f963002510f66a420a42b feat(install): ship a single-binary-first install path with a verified download
| * 6947232b13bc17174986a0e3bfe528d848617519 perf(hk): glob batten-check and macos-link-check, and gate the glob's honesty
|/  
* 6569aeb303e942642dd22feab96f221c67f7027e feat(rules)!: rename the command kind's `run` column to `check`, reserve `fix`

commit 6569aeb303e942642dd22feab96f221c67f7027e
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:02:59 2026 +0000

    feat(rules)!: rename the command kind's `run` column to `check`, reserve `fix`
    
    House style §9 specifies the `command` rule kind as a check/fix duality: an
    inspection-only `check` is the gate — the only side enforcement ever runs — and
    an optional mutating `fix` repairs what it condemned. The shipped `Rule` carried
    one `run` column, which does not express the split.
    
    §2 declares no back-compatibility surface and no deprecation aliases, so every
    config written against `run` becomes a breaking migration later. Today the key
    appears in no shipped config at all — only fixtures, tests and the README — so
    the rename costs nothing. It will not stay that way.
    
    `fix` parses and is executed by nothing: serialised fix execution is a
    capability this engine does not have. `enforce` refuses a row declaring one
    rather than running the check side and silently ignoring the repair, which would
    report green over work nobody did. Reserving the key now means an author who
    writes it is writing the final spelling.
    
    `run` survives as a refusal-only field, the shape `OverrideConfig::
    min_batten_version` already uses: "unknown field `run`" reads as a typo, where
    this is a rename with one specific fix, and the refusal has to carry it
    (CLOUD-122). It is deliberately outside `Rule::columns` — that census classifies
    the columns a kind may carry, and no kind carries this one.
    
    Both refusals are exit 1, not the exit 2 the issue's §5/§7 asked for. §7 makes 2
    the policy verdict — a violation found in the repository, or a mediated call
    denied — while a config naming a key or a capability this build does not have is
    the config-or-usage class. §5 spells the structurally identical sibling refusal
    (a rule the read-only half cannot honestly run) as exit 1, and `run_static` has
    implemented it that way since CLOUD-170; the issue's §3 describes that same
    landed refusal as exit 2, which is falsified by the code it describes. Emitting
    2 here would also make an engine gap read to a harness as a policy deny, which
    is what the structural fail-open exists to prevent.
    
    Refs: CLOUD-215

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch 2 times, most recently from 4e9769b to 573b93b Compare August 11, 2026 21:00
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b642e2d) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (573b93b).

Target branch (main):

commit b642e2dd35304790923f2a63bbbf0f9f68c9b4c2 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 20:47:33 2026 +0000

    perf(ci): run the shell suite in parallel, since it is the pole of the gate
    
    `hk` runs two chains concurrently, and the shell one was the longer by 133s:
    on run 31531728503 the cargo chain's last step finished 166s into `mise run
    ci`, while `test:bats` ran to 247.01s of the step's 298.87s. 800 tests, one at
    a time. `verify` runs the same gate, so a `land` lap paid it twice.
    
    That put it in the exponent of the lap economics. A lap dies whenever `main`
    moves under it, so with mean inter-land gap 487s the expected CI runs per
    landed PR is e^(L/G) — which is why shortening the lap is the one lever that
    cuts latency and the bill together rather than trading one for the other.
    
    Measured here: 248s serial -> 72.73s, 808 tests, same assertions, nothing
    skipped or sampled. The remaining pole is the cargo chain at 166s.
    
    `rush` rather than GNU parallel, which bats would otherwise look for: GNU
    parallel ships as a source tarball with no aqua/ubi/release coordinate, so it
    cannot be a [tools] key at all, and an `apt-get install` in ci.yml is the
    second-authority drift `ci-tools-check` exists to refuse. rush is prebuilt per
    platform, so `mise.lock` holds a checksum for every platform this repo
    installs on.
    
    Across files, never within one. The suites that model lock and race behaviour
    are precisely the ones a within-file schedule would interleave with their own
    setup, and across-files is already enough — the largest file is 49 of 808
    tests, so the schedule is not tail-bound.
    
    Two things ship with it:
    
    - `tests/attribution-check.bats` built its end-to-end fixture in the real
      worktree and the real index. Serially that was invisible; in parallel it is
      a race against the sibling case that reads the same tracked set, plus
      .git/index.lock contention. It now builds a throwaway repo, which is the
      convention issue-guard.bats already set.
    - A speed-up is the kind of fix that rots silently — drop the flag and
      everything still passes, just slower, and `timeout-check`'s 3.4x headroom
      absorbs a return to serial without a red build. So the invocation is now a
      gate over mise.toml: serial is an exit code, not a slower Tuesday.
    
    Refs: CLOUD-386

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit 573b93b152e69c4045e0282c803caafc69c32035 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b642e2d) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (573b93b). main (b642e2d) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (573b93b). Branches appear to have diverged at 5532160:

* 573b93b152e69c4045e0282c803caafc69c32035 feat(install): ship a single-binary-first install path with a verified download
| * b642e2dd35304790923f2a63bbbf0f9f68c9b4c2 perf(ci): run the shell suite in parallel, since it is the pole of the gate
|/  
* 55321601f0fb1cf8e5d9c5a97129e36b11df62fb chore(deps): drop dev-dependencies that duplicate the normal ones

commit 55321601f0fb1cf8e5d9c5a97129e36b11df62fb
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 20:04:52 2026 +0000

    chore(deps): drop dev-dependencies that duplicate the normal ones
    
    `serde_json` was listed in both `[dependencies]` and `[dev-dependencies]`, and
    so were `flate2`, `tar` and `toml` — the identical redundancy, in the same
    table, filed as one bullet because one of the four was noticed. A normal
    dependency is already in scope for every test target, so all four entries
    declared nothing; the comment above them explained a provision-suite need that
    `[dependencies]` had long since covered.
    
    `jsonschema` stays: it is the one crate the tests link and the shipped binary
    does not.
    
    Predicate is the Ready block's — the crate and its test targets still build.
    
    Refs: CLOUD-217

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (37e69f1) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (80ada24).

Target branch (main):

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit 80ada245f839c4efb546e5df5db15994a7aeb079 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (37e69f1) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (80ada24). main (37e69f1) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (80ada24). Branches appear to have diverged at eee9bb4:

* 80ada245f839c4efb546e5df5db15994a7aeb079 feat(install): ship a single-binary-first install path with a verified download
| * 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage
|/  
* eee9bb4bade0799923aff7d983911a169743d839 feat(config): gate the predecessor consumer's repo name

commit eee9bb4bade0799923aff7d983911a169743d839
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:10:41 2026 +0000

    feat(config): gate the predecessor consumer's repo name
    
    CLOUD-73 asks what stays in the consumer's repo and what moves into Batten. Its
    structural half is settled by history — this repository was scaffolded fresh, so
    none of the domain modules it names (entity grep, pdfium, CA privacy detectors,
    evidence and provenance semantics, the ICM design protocol) has ever been here,
    and there is no `tools/batten/` to keep them out of. Its other half is
    non-negotiable rule 1, and that one had a hole.
    
    CLOUD-26's acceptance named four literals. Two are rows; the comment beside them
    dropped the other two on the ground that `forbid` was a case-sensitive literal
    substring check, so a literal with an English reading was wrong in both
    directions at once. CLOUD-283 gave `forbid` a `regex` alternative, which retires
    that premise — so the two exclusions are re-decided on the merits rather than
    inherited from a limit that no longer exists.
    
    The predecessor consumer's repo name goes in, as `(?i)complian`: it is squarely
    what rule 1 forbids, `(?i)` catches the capitalised form the old literal would
    have missed, and it costs nothing — zero lines under crates/ carry it, and this
    engine's vocabulary is policy / gate / predicate / verdict.
    
    The vendor name stays out, and the comment now says that is a decision rather
    than a gap: it names the vendor, not a consumer, `github.com/button-inc/batten`
    is Batten's own home, and the consumer-facing half is already gated by
    `no-origin-literal-in-fixtures`.
    
    The fixture test spells the new shape with a capital, which is precisely the
    half a literal could not have caught.
    
    Refs: CLOUD-73

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch from 80ada24 to a141a2d Compare August 11, 2026 21:50
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Can't fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). main (b913c98) is not a direct ancestor of wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (a141a2d). Branches appear to have diverged at 37e69f1:

* b913c980bda0a9ade266915b4bf527918576a4c7 docs(fanout): re-measure land contention — a lap now loses by arithmetic
* a517ff7e7d3c690c25a9185a333d74c23db5f430 feat(refusal): one refusal type, so no deny can ship a bare "no"
| * a141a2d02a3b3cddd2194d305ba8cdafd5dc4b32 feat(install): ship a single-binary-first install path with a verified download
|/  
* 37e69f1f2bf15e960b74104a027df9b3a4d82026 build(release): publish a SHA256SUMS manifest and gate its coverage

commit 37e69f1f2bf15e960b74104a027df9b3a4d82026
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:31:44 2026 +0000

    build(release): publish a SHA256SUMS manifest and gate its coverage
    
    A release carried no checksum of any kind, so every packaging channel that
    consumes one was blocked: a Homebrew formula pins it, an aqua/mise registry
    entry carries it, and `cargo binstall` resolves assets whose integrity nobody
    could check. It is also the floor beneath CLOUD-264's signature decision and
    independent of it.
    
    `mise-tasks/checksums` hashes the release's OWN assets, read back after upload,
    rather than a list restated in the workflow. The seven dist legs are independent
    with `fail-fast: false`, so no leg can see the whole release — and deriving from
    what is published means a future asset is covered by the edit that starts
    publishing it, with no second edit here. The format is `sha256sum`'s own, so
    verifying is the ordinary tool with no flags.
    
    `release-assets-check` grows the rules that catch a manifest a packager would
    otherwise discover: `checksums-missing`, `-omits`, `-orphan`, `-self`, `-empty`,
    and `-mismatch`. The last one reads BYTES, not names: uploads are `--clobber`
    idempotent and the stated recovery is a per-target re-run, so an asset can be
    replaced after the manifest was cut and names alone would still agree.
    
    Refs: CLOUD-278

Rebase locally, and then force push to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager.

@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch from a141a2d to b490fa0 Compare August 11, 2026 21:56
@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (b490fa0).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit b490fa05e8b70055f712f61cc6b2d6b2b9bace09 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Fast forwarding main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (b490fa0).

$ git push origin b490fa05e8b70055f712f61cc6b2d6b2b9bace09:main
remote: error: GH013: Repository rule violations found for refs/heads/main.        
remote: Review all repository rules at https://github.com/button-inc/batten/rules?ref=refs%2Fheads%2Fmain        
remote: 
remote: - Required status check "final" is expected.        
remote: 
To https://github.com/button-inc/batten.git
 ! [remote rejected] b490fa05e8b70055f712f61cc6b2d6b2b9bace09 -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/button-inc/batten.git'

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (b490fa0).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit b490fa05e8b70055f712f61cc6b2d6b2b9bace09 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Fast forwarding main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (b490fa0).

$ git push origin b490fa05e8b70055f712f61cc6b2d6b2b9bace09:main
remote: error: GH013: Repository rule violations found for refs/heads/main.        
remote: Review all repository rules at https://github.com/button-inc/batten/rules?ref=refs%2Fheads%2Fmain        
remote: 
remote: - Required status check "final" is expected.        
remote: 
To https://github.com/button-inc/batten.git
 ! [remote rejected] b490fa05e8b70055f712f61cc6b2d6b2b9bace09 -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/button-inc/batten.git'

@wenzowski

Copy link
Copy Markdown
Contributor Author

Triggered from #310 (comment) by @​wenzowski.

Trying to fast forward main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (b490fa0).

Target branch (main):

commit b913c980bda0a9ade266915b4bf527918576a4c7 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 21:17:30 2026 +0000

    docs(fanout): re-measure land contention — a lap now loses by arithmetic
    
    The measurement recorded three hours earlier had `main` at a 487s mean gap
    against a ~170s `verify`, giving N ≈ 2.9 with the WIP cap at 2 — "at the
    ceiling", and the model held. It no longer does. Over `main`'s ten commits to
    21:09Z the mean gap is 436s while a full lap is `verify` + CI + the
    fast-forward wait, call it 8–10 minutes. CLOUD-122 lost 16 consecutive laps
    across two `mise run land` invocations, every one green on CI.
    
    The interesting half is a lap-loss shape the N model does not price. Three of
    the sixteen were the documented case — `main` moved before CI finished, the
    verdict void, cancelled early and cheap. Five were not: CI went green,
    `/fast-forward` was posted, and the bot then stayed SILENT while `main` moved.
    `land` infers a refusal from `main` moving rather than from the bot answering,
    so the log reads as a refusal that never happened. The bot is not rejecting the
    fast-forward; it is slower than `main`, and that silence is a third term the
    verify + CI lap cost never included.
    
    Raising `LAND_MAX_LAPS` buys more attempts per invocation without changing the
    per-lap odds, so it spends CI minutes against a losing bet. The lever is
    unchanged and now more urgent: shorten the lap, or quiet `main`; never add
    sessions.
    
    Refs: CLOUD-122

Pull request (wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager):

commit b490fa05e8b70055f712f61cc6b2d6b2b9bace09 (pull_request/wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager)
Author: Claude <noreply@anthropic.com>
Date:   Tue Aug 11 19:08:09 2026 +0000

    feat(install): ship a single-binary-first install path with a verified download
    
    Releases have carried seven target archives since CLOUD-108, with nothing on the
    consuming side: no install script, no binstall metadata, and nothing asserting
    that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
    "Single-binary-first" was an ordering claim the repo could not make.
    
    install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
    present, and verifies every download against the SHA-256 digest the release API
    reports — a mismatch, or an asset with no digest, installs nothing and there is
    no flag to skip it. Measured: api.github.com answers pretty-printed, so the
    parsing commits to neither wire form. The token reaches curl on stdin rather
    than argv, where ps would show it.
    
    install-check is the gate. dist owns archive naming and install.sh owns its
    target list; the gate calls both rather than scraping either, derives the matrix
    from the workflow that decides it, resolves the binstall template against the
    same answer, and fails on a committed executable.
    
    Refs: CLOUD-65

Fast forwarding main (b913c98) to wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager (b490fa0).

$ git push origin b490fa05e8b70055f712f61cc6b2d6b2b9bace09:main
remote: error: GH013: Repository rule violations found for refs/heads/main.        
remote: Review all repository rules at https://github.com/button-inc/batten/rules?ref=refs%2Fheads%2Fmain        
remote: 
remote: - Required status check "final" is expected.        
remote: 
To https://github.com/button-inc/batten.git
 ! [remote rejected] b490fa05e8b70055f712f61cc6b2d6b2b9bace09 -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/button-inc/batten.git'

@wenzowski
wenzowski marked this pull request as draft August 11, 2026 23:34
@wenzowski
wenzowski marked this pull request as ready for review August 11, 2026 23:34
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

…d download

Releases have carried seven target archives since CLOUD-108, with nothing on the
consuming side: no install script, no binstall metadata, and nothing asserting
that the asset name a consumer resolves is the one `mise-tasks/dist` writes.
"Single-binary-first" was an ordering claim the repo could not make.

install.sh is POSIX sh, assumes only what `curl … | sh` already proves is
present, and verifies every download against the SHA-256 digest the release API
reports — a mismatch, or an asset with no digest, installs nothing and there is
no flag to skip it. Measured: api.github.com answers pretty-printed, so the
parsing commits to neither wire form. The token reaches curl on stdin rather
than argv, where ps would show it.

install-check is the gate. dist owns archive naming and install.sh owns its
target list; the gate calls both rather than scraping either, derives the matrix
from the workflow that decides it, resolves the binstall template against the
same answer, and fails on a committed executable.

Refs: CLOUD-65
@wenzowski
wenzowski force-pushed the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch from b490fa0 to 99691f7 Compare August 11, 2026 23:39
@sonarqubecloud

Copy link
Copy Markdown

@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski
wenzowski merged commit 99691f7 into main Aug 11, 2026
7 checks passed
@wenzowski
wenzowski deleted the wenzowski/cloud-65-ship-a-single-binary-first-install-path-and-package-manager branch August 11, 2026 23:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants