#32 stopped script/cibuild and script/docker from serving cached gate layers, by interpolating a fresh CHECK_EPOCH into each gate RUN. That works — the reviewer proved it by holding the epoch constant and watching the 17-layer false green come straight back.
But CHECK_EPOCH has no default and nothing asserts it is non-empty (Dockerfile:24 and Dockerfile:64). So anyone who runs docker build . directly, rather than through the sanctioned entrypoints, gets the old behaviour with no warning at all. Measured by the reviewer: two bare docker build . runs in a row produce 17 CACHED steps with all three gates cached and exit 0.
Not a regression — both sanctioned paths pass the argument, and this is exactly how things behaved before #32. But the whole point of #32 is that a gate must not be able to report a green it did not earn, and right now the failure mode is one habit away. docker build . is what people type.
Definition of done
Each gate stage asserts the epoch is present, e.g. RUN test -n "${CHECK_EPOCH}" || { echo "CHECK_EPOCH is unset; build via script/cibuild or script/docker" >&2; exit 1; }, so a bare docker build . fails loudly instead of quietly serving cache. Both stages, since ARG is per-stage.
Verified by running docker build . directly and showing it fails with that message, and that script/cibuild and script/docker still succeed.
Consider whether the epoch should be tightened to "$(date +%s)-$$". Second resolution alone means two builds starting in the same second share a value. The reviewer judged that non-blocking and gave the correct reason, which is worth recording because the original justification was wrong: it is safe not because builds take 50-80 seconds, but because a collision needs the same second and a byte-identical tree, in which case the reused result really was computed for that exact tree. Note date +%s%N is GNU-only and degrades silently to one-second resolution on macOS, which is a supported host class here — prefer -$$ if tightening.
TODO.md:59 says twelve CACHED steps in steady state; the measured figure is thirteen (the extra is the lint stage's WORKDIR /src). Correct it.
make check green, and make docker green with the gates demonstrably executing.
#32 stopped `script/cibuild` and `script/docker` from serving cached gate layers, by interpolating a fresh `CHECK_EPOCH` into each gate `RUN`. That works — the reviewer proved it by holding the epoch constant and watching the 17-layer false green come straight back.
But `CHECK_EPOCH` has no default and nothing asserts it is non-empty (`Dockerfile:24` and `Dockerfile:64`). So anyone who runs `docker build .` directly, rather than through the sanctioned entrypoints, gets the old behaviour with no warning at all. Measured by the reviewer: two bare `docker build .` runs in a row produce 17 `CACHED` steps with all three gates cached and exit 0.
Not a regression — both sanctioned paths pass the argument, and this is exactly how things behaved before #32. But the whole point of #32 is that a gate must not be able to report a green it did not earn, and right now the failure mode is one habit away. `docker build .` is what people type.
## Definition of done
1. Each gate stage asserts the epoch is present, e.g. `RUN test -n "${CHECK_EPOCH}" || { echo "CHECK_EPOCH is unset; build via script/cibuild or script/docker" >&2; exit 1; }`, so a bare `docker build .` fails loudly instead of quietly serving cache. Both stages, since `ARG` is per-stage.
2. Verified by running `docker build .` directly and showing it fails with that message, and that `script/cibuild` and `script/docker` still succeed.
3. Consider whether the epoch should be tightened to `"$(date +%s)-$$"`. Second resolution alone means two builds starting in the same second share a value. The reviewer judged that non-blocking and gave the correct reason, which is worth recording because the original justification was wrong: it is safe not because builds take 50-80 seconds, but because a collision needs the same second **and** a byte-identical tree, in which case the reused result really was computed for that exact tree. Note `date +%s%N` is GNU-only and degrades silently to one-second resolution on macOS, which is a supported host class here — prefer `-$$` if tightening.
4. `TODO.md:59` says twelve `CACHED` steps in steady state; the measured figure is thirteen (the extra is the lint stage's `WORKDIR /src`). Correct it.
5. `make check` green, and `make docker` green with the gates demonstrably executing.
clawbot
added this to the 1.0.0 milestone 2026-08-09 09:47:35 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
#32 stopped
script/cibuildandscript/dockerfrom serving cached gate layers, by interpolating a freshCHECK_EPOCHinto each gateRUN. That works — the reviewer proved it by holding the epoch constant and watching the 17-layer false green come straight back.But
CHECK_EPOCHhas no default and nothing asserts it is non-empty (Dockerfile:24andDockerfile:64). So anyone who runsdocker build .directly, rather than through the sanctioned entrypoints, gets the old behaviour with no warning at all. Measured by the reviewer: two baredocker build .runs in a row produce 17CACHEDsteps with all three gates cached and exit 0.Not a regression — both sanctioned paths pass the argument, and this is exactly how things behaved before #32. But the whole point of #32 is that a gate must not be able to report a green it did not earn, and right now the failure mode is one habit away.
docker build .is what people type.Definition of done
RUN test -n "${CHECK_EPOCH}" || { echo "CHECK_EPOCH is unset; build via script/cibuild or script/docker" >&2; exit 1; }, so a baredocker build .fails loudly instead of quietly serving cache. Both stages, sinceARGis per-stage.docker build .directly and showing it fails with that message, and thatscript/cibuildandscript/dockerstill succeed."$(date +%s)-$$". Second resolution alone means two builds starting in the same second share a value. The reviewer judged that non-blocking and gave the correct reason, which is worth recording because the original justification was wrong: it is safe not because builds take 50-80 seconds, but because a collision needs the same second and a byte-identical tree, in which case the reused result really was computed for that exact tree. Notedate +%s%Nis GNU-only and degrades silently to one-second resolution on macOS, which is a supported host class here — prefer-$$if tightening.TODO.md:59says twelveCACHEDsteps in steady state; the measured figure is thirteen (the extra is the lint stage'sWORKDIR /src). Correct it.make checkgreen, andmake dockergreen with the gates demonstrably executing.clawbot referenced this issue2026-09-04 11:36:06 +02:00
clawbot referenced this issue2026-09-04 11:51:02 +02:00
clawbot referenced this issue2026-09-04 11:53:24 +02:00