Repository navigation
fix(hk): drop five restated check_first defaults - #332
Conversation
69a3c36 to
18a4125
Compare
|
/fast-forward |
|
Triggered from #332 (comment) by @wenzowski. Trying to fast forward Target branch ( 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-215Pull request ( commit 18a41258b7326b718980d160064bb4f4634a6cba (pull_request/claude/rules-engine-defaults-research-lbzrbg)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 20:13:21 2026 +0000
fix(hk): drop five restated check_first defaults
check_first already defaults true at the pinned v1.54.0
(pkl/Config.pkl:515), so all five assignments restated a default rather
than overriding one. The cargo-fmt comment was the harmful part: it
explained check_first's behaviour as though the step were opting into it,
so a reader checking whether the fixer skips a clean tree found a
rationale for a line that changed nothing.
Same class the rules-engine defaults census (CLOUD-381) found across ten
tools: a config that restates a default is indistinguishable from one
that overrides it, and the reader cannot tell which layer decided.
.claude/rules/toolchain.md already states the principle for exactly these
steps -- upstream globs and check_first are upstream's authority, and
re-declaring them here is a second authority for something upstream
already tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3dCan't fast forward * 18a41258b7326b718980d160064bb4f4634a6cba fix(hk): drop five restated check_first defaults
* e428ef4b099869c7c26e772ff9085ffc7866dcc2 docs(memory): record which survey tools reach the evidence (CLOUD-381)
| * 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-187Rebase locally, and then force push to |
18a4125 to
ee03e26
Compare
|
/fast-forward |
|
Triggered from #332 (comment) by @wenzowski. Trying to fast forward Target branch ( 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-224Pull request ( commit ee03e267de19aa0acaf645a69270c6cff8f67cd4 (pull_request/claude/rules-engine-defaults-research-lbzrbg)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 20:13:21 2026 +0000
fix(hk): drop five restated check_first defaults
check_first already defaults true at the pinned v1.54.0
(pkl/Config.pkl:515), so all five assignments restated a default rather
than overriding one. The cargo-fmt comment was the harmful part: it
explained check_first's behaviour as though the step were opting into it,
so a reader checking whether the fixer skips a clean tree found a
rationale for a line that changed nothing.
Same class the rules-engine defaults census (CLOUD-381) found across ten
tools: a config that restates a default is indistinguishable from one
that overrides it, and the reader cannot tell which layer decided.
.claude/rules/toolchain.md already states the principle for exactly these
steps -- upstream globs and check_first are upstream's authority, and
re-declaring them here is a second authority for something upstream
already tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3dCan't fast forward * ee03e267de19aa0acaf645a69270c6cff8f67cd4 fix(hk): drop five restated check_first defaults
* 544ffba28c92fd72540fc7ee0e71adf535b6deb4 docs(memory): record which survey tools reach the evidence (CLOUD-381)
| * 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-215Rebase locally, and then force push to |
a2a471d to
0214abf
Compare
|
/fast-forward |
|
Triggered from #332 (comment) by @wenzowski. Trying to fast forward Target branch ( 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-386Pull request ( commit 0214abf8f8e82f7c103026c06b91db3706859023 (pull_request/claude/rules-engine-defaults-research-lbzrbg)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 20:13:21 2026 +0000
fix(hk): drop five restated check_first defaults
check_first already defaults true at the pinned v1.54.0
(pkl/Config.pkl:515), so all five assignments restated a default rather
than overriding one. The cargo-fmt comment was the harmful part: it
explained check_first's behaviour as though the step were opting into it,
so a reader checking whether the fixer skips a clean tree found a
rationale for a line that changed nothing.
Same class the rules-engine defaults census (CLOUD-381) found across ten
tools: a config that restates a default is indistinguishable from one
that overrides it, and the reader cannot tell which layer decided.
.claude/rules/toolchain.md already states the principle for exactly these
steps -- upstream globs and check_first are upstream's authority, and
re-declaring them here is a second authority for something upstream
already tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3dCan't fast forward * b642e2dd35304790923f2a63bbbf0f9f68c9b4c2 perf(ci): run the shell suite in parallel, since it is the pole of the gate
| * 0214abf8f8e82f7c103026c06b91db3706859023 fix(hk): drop five restated check_first defaults
| * dec785f4ecfdf4152dda95fa006783ad695d973d docs(memory): record which survey tools reach the evidence (CLOUD-381)
|/
* 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-217Rebase locally, and then force push to |
0214abf to
026fe22
Compare
|
/fast-forward |
|
Triggered from #332 (comment) by @wenzowski. Trying to fast forward Target branch ( commit 98aceb05393d0fdfc91d977603ae486cf34e1b7f (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 19:14:30 2026 +0000
feat(bench): measure the token economics instead of asserting them
The adoption claim is token economics, and the differentiator is that ours is
reproducible: anyone can say they are cheaper, we ship the harness that produces
the number from committed inputs with no credential and no network.
`mise run token-bench` executes what `bench/tokens/workloads.toml` declares and
prices it with what `bench/tokens/method.toml` declares — no price, divisor,
re-run coefficient or workload is baked into the program, because a constant
written into a benchmark's code is a number nobody re-derives. Every arm runs
three times and is compared byte-for-byte; an arm that is not byte-stable is
reported as such rather than averaged, since byte-stability is the property the
cache claim rests on.
`mise run token-bench-check` is the mechanism that makes "reproducible"
checkable: it regenerates the table into scratch and diffs it byte-for-byte, and
it re-reads the published bytes for the honesty predicate — a figure without
workload, baseline, run count and method is refused, and so is a capability
reporting "not measured" with no reason. The gate re-reads the artifact rather
than trusting the generator, which is what a program checking its own arithmetic
would not do.
Two capabilities carry a measured figure; `log-handle` reports "not measured"
because the capability is not shipped, and the cross-session cache hit rate
reports "not measured" because it needs a live provider credential and is a
property of the world rather than of this commit. Neither borrows a magnitude
from its neighbour. No aggregate is published: averaging across capabilities
needs a workload mix nobody here has measured.
`build-warning` is the honest one — Batten wins it by 1.47x, and the saving is
exactly the discarded `tail` window rather than the log, which `exec` tees in
full by design.
Named `token-bench` rather than `bench`: CLOUD-207's `mise run bench` measures
batten's invocation cost and landed under that name first. Two benchmarks with
two subjects need two names, so the later and more specific one moves, and
`bench/tokens/` leaves room for the sibling's own inputs beside it.
Refs: CLOUD-119Pull request ( commit 026fe22bdcf8109221c06c09fc1516bb42f4b3d5 (pull_request/claude/rules-engine-defaults-research-lbzrbg)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 20:13:21 2026 +0000
fix(hk): drop five restated check_first defaults
check_first already defaults true at the pinned v1.54.0
(pkl/Config.pkl:515), so all five assignments restated a default rather
than overriding one. The cargo-fmt comment was the harmful part: it
explained check_first's behaviour as though the step were opting into it,
so a reader checking whether the fixer skips a clean tree found a
rationale for a line that changed nothing.
Same class the rules-engine defaults census (CLOUD-381) found across ten
tools: a config that restates a default is indistinguishable from one
that overrides it, and the reader cannot tell which layer decided.
.claude/rules/toolchain.md already states the principle for exactly these
steps -- upstream globs and check_first are upstream's authority, and
re-declaring them here is a second authority for something upstream
already tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3dCan't fast forward * 026fe22bdcf8109221c06c09fc1516bb42f4b3d5 fix(hk): drop five restated check_first defaults
* 86be1162e61b96631c8952fcd570933891838449 docs(memory): record which survey tools reach the evidence (CLOUD-381)
| * 98aceb05393d0fdfc91d977603ae486cf34e1b7f feat(bench): measure the token economics instead of asserting them
|/
* b642e2dd35304790923f2a63bbbf0f9f68c9b4c2 perf(ci): run the shell suite in parallel, since it is the pole of the gate
commit b642e2dd35304790923f2a63bbbf0f9f68c9b4c2
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-386Rebase locally, and then force push to |
59af6d3 to
f7f7810
Compare
|
/fast-forward |
|
Triggered from #332 (comment) by @wenzowski. Trying to fast forward Target branch ( commit 42319f43bfdff5cdb654394d2504d1ac173cb024 (HEAD -> main, origin/main)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 20:44:36 2026 +0000
ci(stop-posture): one flagging-verb set across the worth/bears openers
`HEDGES` gave its two openers different verb sets — `worth
(noting|flagging)` beside `bears (noting|mentioning)` — so `mentioning`
was a flagging verb to this file under one opener and unknown under the
other. Nothing distinguished them; the split was an accident of how the
alternation was written.
Measured, one sentence per row: `worth naming` and `worth mentioning`
were silent while `bears mentioning` fired. The first of those is a
witnessed miss. The CLOUD-347..356 audit closed its report with "One
open thread worth naming: the census … never interrogated host
settings" — a real finding that reached chat and nothing else, and
became CLOUD-380 only because a human asked. Nothing else covered it
either: `stop-guard` consults `finding-sink-check` precisely when this
rule is silent, and that gate needs a `path:line` citation the sentence
does not carry, so the turn's one advisory slot was never claimed.
One shared `FLAG_VERB` set now, every entry either witnessed (`naming`)
or already in the file (`noting`, `flagging`, `mentioning`). `calling
out` stays out and is asserted to stay out: unwitnessed and not already
present, which is the line between completing an inflection and
inventing a phrase list. The `I would flag` / `I should note` family
keeps `(flag|note)` — "I would name that" is not natural flagging.
Not the unmeasured-literal mistake CLOUD-323 and CLOUD-326 forbid:
those govern a new SHAPE, while this is inflection completion inside a
construction already measured at 3/3, which this gate's own header
sanctions and its own history already did once.
Refs: CLOUD-387Pull request ( commit f7f781044b020d927551c3f8030aedce07d351ae (pull_request/claude/rules-engine-defaults-research-lbzrbg)
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 20:13:21 2026 +0000
fix(hk): drop five restated check_first defaults
check_first already defaults true at the pinned v1.54.0
(pkl/Config.pkl:515), so all five assignments restated a default rather
than overriding one. The cargo-fmt comment was the harmful part: it
explained check_first's behaviour as though the step were opting into it,
so a reader checking whether the fixer skips a clean tree found a
rationale for a line that changed nothing.
Same class the rules-engine defaults census (CLOUD-381) found across ten
tools: a config that restates a default is indistinguishable from one
that overrides it, and the reader cannot tell which layer decided.
.claude/rules/toolchain.md already states the principle for exactly these
steps -- upstream globs and check_first are upstream's authority, and
re-declaring them here is a second authority for something upstream
already tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3dCan't fast forward * f7f781044b020d927551c3f8030aedce07d351ae fix(hk): drop five restated check_first defaults
* cb6a27d8af552e6fe7c0edd9f927f0db1701632f docs(memory): record which survey tools reach the evidence (CLOUD-381)
| * 42319f43bfdff5cdb654394d2504d1ac173cb024 ci(stop-posture): one flagging-verb set across the worth/bears openers
|/
* 87ed39733221612abd4f99ce64c5f93e773439d4 fix(verify): refuse to receipt a HEAD whose bytes were not the ones validated
commit 87ed39733221612abd4f99ce64c5f93e773439d4
Author: Claude <noreply@anthropic.com>
Date: Tue Aug 11 18:56:29 2026 +0000
fix(verify): refuse to receipt a HEAD whose bytes were not the ones validated
`verify` runs every gate over the WORKING TREE and then writes a receipt keyed
to HEAD. Nothing asserted the two agree, so a dirty tree could attest a commit
nobody verified: the receipt is written, `verified` matches it, `ready-guard`
accepts it, and CI runs a commit that was never the thing that passed.
Measured 2026-08-09 landing CLOUD-269 — a backgrounded `land` compiled a
mid-edit snapshot and reported `verify failed on c5bfe05`, a commit containing
none of that code. That direction is loud and self-correcting; the mirror is
silent, and it is the one this closes.
`mise-tasks/tree-clean` is the predicate: `git --no-optional-locks status
--porcelain --untracked-files=normal`, exit 1 with a count and the porcelain
lines as pointers, exit 2 when it cannot look. Untracked-but-not-ignored counts
as dirty — decided, not omitted — because `cargo test` auto-discovers
`crates/batten/tests/*.rs` and the bats suite globs `tests/*.bats`, so a new
untracked file is run by `verify` with zero tracked-file change. Ignored paths
are excluded structurally.
Wired into `[tasks.verify]` at both ends of the window: in `depends` so a dirty
tree fails in seconds rather than after ~170s, and in the body — the
load-bearing one, since `depends` completes before a tree can be dirtied
mid-run. Not an hk step: `pre-commit` runs over a tree that is dirty by
definition. `land` inherits it through `verify` and re-implements nothing.
Refs: CLOUD-277Rebase locally, and then force push to |
f7f7810 to
d20b282
Compare
Scholar Gateway is Wiley-only and returned two on-topic articles across 24 passages; Consensus returned the field's standard results on the first try. GitHub reaction counts are unreachable for repos outside button-inc/batten, so the planned reception signal needs reachable substitutes named up front. Both cost a wasted call to discover on the rules-engine defaults census and neither is inferable from the tool descriptions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3d
check_first already defaults true at the pinned v1.54.0 (pkl/Config.pkl:515), so all five assignments restated a default rather than overriding one. The cargo-fmt comment was the harmful part: it explained check_first's behaviour as though the step were opting into it, so a reader checking whether the fixer skips a clean tree found a rationale for a line that changed nothing. Same class the rules-engine defaults census (CLOUD-381) found across ten tools: a config that restates a default is indistinguishable from one that overrides it, and the reader cannot tell which layer decided. .claude/rules/toolchain.md already states the principle for exactly these steps -- upstream globs and check_first are upstream's authority, and re-declaring them here is a second authority for something upstream already tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P1xT4aa59k7kKPCDXq7y3d
d20b282 to
cebd9d2
Compare
|
|
/fast-forward |



Follow-on from the rules-engine defaults census (CLOUD-381). Two small changes; the research itself lives in Linear, per the repo's rule 7.
hk.pkl: five restated
check_firstdefaults removedcheck_firstalready defaultstrueat the pinned v1.54.0 (pkl/Config.pkl:515), so all five assignments restated a default rather than overriding one. Thecargo-fmtcomment was the harmful part: it explained the behaviour as though the step were opting into it, so a reader checking whether the fixer skips a clean tree found a rationale for a line that changed nothing..claude/rules/toolchain.mdalready states the principle for exactly these steps — upstream's globs andcheck_firstare upstream's authority, and re-declaring them here is a second authority for something upstream already tests.This is the same class the census found across ten tools: a config that restates a default is indistinguishable from one that overrides it, and the reader cannot tell which layer decided. Nine of ten surveyed tools cannot answer "which layer set this value?" at all.
Memory: which survey tools reach the evidence
Two findings that each cost a wasted call to discover and are not inferable from the tool descriptions:
button-inc/batten;add_repoon a survey target is declined by the permission classifier. Shallow clones still work, so reading source is unaffected — only the issue-reaction channel is closed, and a survey's evidence plan has to name signals the environment can actually produce.Verification
mise run verifygreen after rebase.mise run pkl-check hk.pklevaluates cleanly; the gate steps whosecheck_firstwas removed (shfmt,taplo-format,pkl-format,prettier,cargo-fmt) all run inverify, so their behaviour under the inherited default is exercised by this run rather than asserted.Generated by Claude Code