1 Commits
Author SHA1 Message Date
clawbot c64bbbb78e Re-vendor the canonical files from sneak/prompts at c55a0cb (closes #95)
check / check (push) Waiting to run
Every vendored file, REPO_POLICIES.md and every model script is the
copy at sneak/prompts c55a0cb, with this repository's own entries kept
after the canonical content. Lint and test are phases of the Dockerfile
that write no image, built uncached. make test runs the suite under the
race detector as nobody, because root reads the files the tests make
unreadable. Dockerfile.lint, script/verify-lint-image-pin and
make test-race are gone. Prettier runs on the host, from the node and
yarn that script/bootstrap installs. golangci-lint v2.14.0 raises no
findings. .claude/settings.json is deleted.

Deviation: the set comes from c55a0cb on next rather than dd4027b, as
the instructions on sneak/prompts#78 allow.

Model: opus-5-5
2026-10-08 01:32:30 +00:00
+30 -66
View File
@@ -46,8 +46,9 @@
https://git.eeqj.de/sneak/sfdupes/issues/12) https://git.eeqj.de/sneak/sfdupes/issues/12)
- cut the narration from `TODO.md` Completed Steps and from the comments in - cut the narration from `TODO.md` Completed Steps and from the comments in
`script/` and both Dockerfiles; §Workflow now branches from and merges to `script/`, `Dockerfile` and `Dockerfile.lint` (gone since
`next` (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/49) https://git.eeqj.de/sneak/sfdupes/issues/95); §Workflow now branches from and
merges to `next` (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/49)
- `make test-race` ran the test suite under the race detector in a cgo-enabled - `make test-race` ran the test suite under the race detector in a cgo-enabled
container, outside `make check` (2026-10-04, container, outside `make check` (2026-10-04,
@@ -176,82 +177,45 @@
- fix the lint-image pin comments and `FROM` form in `Dockerfile` and - fix the lint-image pin comments and `FROM` form in `Dockerfile` and
`Dockerfile.lint` (2026-08-10, branch `next`, closes `Dockerfile.lint` (2026-08-10, branch `next`, closes
https://git.eeqj.de/sneak/sfdupes/issues/25): both pins are now the policy https://git.eeqj.de/sneak/sfdupes/issues/25): both pins became the policy
`# image:vX.Y.Z, YYYY-MM-DD` comment over a bare `FROM image@sha256:...`, `# image:vX.Y.Z, YYYY-MM-DD` comment over a bare `FROM image@sha256:...`,
without the false `(Debian-based)` note or the tag; digest unchanged. without the false `(Debian-based)` note or the tag. Since
`script/verify-lint-image-pin` still matches the tagless form, and a tag on https://git.eeqj.de/sneak/sfdupes/issues/95 the `Dockerfile`'s `lint` phase
one side only is caught as a plain mismatch. holds the only golangci-lint pin, in that form, so `Dockerfile.lint` and
`script/verify-lint-image-pin`, which compared the two pins, are gone.
- run all linting in Docker via `Dockerfile.lint` and `script/lint` (2026-08-10, - run all linting in Docker via `Dockerfile.lint` and `script/lint` (2026-08-10,
branch `next`, closes https://git.eeqj.de/sneak/sfdupes/issues/46): per the branch `next`, closes https://git.eeqj.de/sneak/sfdupes/issues/46): per the
owner ruling the linter is never installed on a host. `Dockerfile.lint` copies owner ruling the linter is never installed on a host, and
the repo into the digest-pinned `golangci/golangci-lint:v2.12.2` image and `golangci-lint config verify` runs before `golangci-lint run`.
runs `golangci-lint config verify` and `golangci-lint run` as build steps; `script/bootstrap` stopped installing or pinning the linter, and
`script/lint` builds it. `script/bootstrap` no longer installs or pins the `script/verify-linter-pin` was retired. Since
linter, and warns rather than fails when `docker` is absent; https://git.eeqj.de/sneak/sfdupes/issues/95 both commands run in the
`ENV PATH=/home/builder/go/bin:$PATH` went with its `go install`. `Dockerfile`'s `lint` phase, which `script/lint` builds alone and the build
`script/verify-linter-pin` is retired; `script/verify-lint-image-pin`, a gate stage depends on through `COPY --from=lint /src/go.sum /dev/null`;
in both files, compares their two `FROM` lines and restates neither pin. `Dockerfile.lint` and `script/verify-lint-image-pin` are gone. Nothing inside
Traps: nothing inside an image build may shell out to docker, so the an image build may run docker, so the phase calls `golangci-lint` directly.
`Dockerfile` lint stage calls `golangci-lint` directly and the build stage
runs `make test` and `make fmt-check` instead of `make check`, through `make`
because the Makefile's `export CGO_ENABLED = 0` only reaches what it invokes.
`COPY --from=lint /src/go.sum /dev/null` replaces the copied linter binary as
the only edge making the build stage wait for lint; dropping it would end
fail-fast linting under a still-green build. `golangci-lint config verify`,
included per the ruling, validates from an embedded schema with no network
call, but `go mod download` above the gates still needs the network on a cold
cache. Verified: `make lint` green with no `golangci-lint` on `PATH`; two
back-to-back `script/lint` runs on an untouched tree both ran the linter
(27.7s and 28.7s in the lint step, `COPY . .` `CACHED` above); a planted
unused variable failed `script/lint`, and failed `make docker` at `[lint 9/9]`
with the build stage stopped at `[builder 3/12]`; the drift guard fails on a
tag-only, a digest-only and an unreadable reference, naming both sides; under
`--network none` config verify passes a valid config and rejects an invalid
one; `make docker` green in 5m35s with all six gates run (lint 37.6s, test
25.2s reporting `ok sneak.berlin/go/sfdupes 1.938s coverage: 88.5%`, not
`(cached)`); in the builder image with the Go test cache off, `--user 0:0`
still fails `TestScanHardlinkRunFailsTogether` where the unprivileged user
passes. Noted for follow-up, not fixed here: `golangci-lint` warns that
`gomodguard` is deprecated since v2.12.0 in favour of `gomodguard_v2`.
- install the Docker build stage's prerequisites by running `script/bootstrap` - install the Docker build stage's prerequisites by running `script/bootstrap`
instead of `apk add --no-cache make` inline (2026-08-09, branch instead of `apk add --no-cache make` inline (2026-08-09, branch
`dockerfile-bootstrap`, closes https://git.eeqj.de/sneak/sfdupes/issues/42): `dockerfile-bootstrap`, closes https://git.eeqj.de/sneak/sfdupes/issues/42),
the stage copies `script/` plus `go.mod`/`go.sum` and runs `script/bootstrap`, with `script/verify-linter-pin` failing the build unless the linter copied
which ends in `go mod download`, so the separate call to it is gone. from the lint stage was the version `script/bootstrap` pinned. Builds then
`COPY --from=lint /usr/bin/golangci-lint` stays and moves above the bootstrap took up to 5m14s cold, mostly in a `chown -R` of the module cache, filed as
layer: it is the only edge making this stage depend on the lint stage, so https://git.eeqj.de/sneak/sfdupes/issues/43. Since
deleting it would end fail-fast linting silently. A new https://git.eeqj.de/sneak/sfdupes/issues/95 the build stage installs `git` and
`script/verify-linter-pin`, run in the build stage before bootstrap, fails the `make` with `apk add --no-cache` and only compiles; the `lint` and `test`
build naming both versions unless that copied binary is the version phases are the gates
`script/bootstrap` pins; a pin it cannot read is a hard failure, not a skip.
`$GOPATH/bin` joins `PATH`, where bootstrap's `go install` lands. The `chown`
and `USER builder` still precede `make check`. Verified: the guard fails the
build with both versions named when the lint stage's linter is faked to
another version, and passes an unmodified build; bootstrap runs clean under
Alpine's `sh` and `apk`, finding the copied linter already at the pin; a
second build served the bootstrap and dependency layers `CACHED` while both
gates ran; a planted `unused` finding failed the build at the lint gate in
48.9s with the build stage's `make check` never starting; and the suite run in
the image as `--user 0:0` fails `TestScanHardlinkRunFailsTogether`, so the
drop to the unprivileged user is still needed. That last check needs the Go
test cache off: as root it first reported `ok ... (cached)`, reusing the
build-time result. Build times on a noisy shared host: 2m13s on an unchanged
tree, 2m17s and 4m29s after a source change, 5m14s cold, which breaches the
policy ceiling; `chown -R builder:builder /src /home/builder` walks the module
cache and alone varied from 77s to 210s across those builds, and `main`
measured 5m03s cold with a 209s `chown`. Filed as
https://git.eeqj.de/sneak/sfdupes/issues/43
- bust the Docker layer cache for the gate steps, so `script/cibuild` and - bust the Docker layer cache for the gate steps, so `script/cibuild` and
`script/docker` cannot report a green they did not earn (2026-08-09, branch `script/docker` cannot report a green they did not earn (2026-08-09, branch
`cibuild-cache-bust`, closes https://git.eeqj.de/sneak/sfdupes/issues/32): the `cibuild-cache-bust`, closes https://git.eeqj.de/sneak/sfdupes/issues/32): the
`Dockerfile` copies the tree before its gates, so on an unchanged tree Docker `Dockerfile` copies the tree before its gates, so on an unchanged tree Docker
served them from cache and the build exited 0 having run nothing. Every served them from cache and the build exited 0 having run nothing. The fix was
`docker build` in `script/` now passes `--no-cache` instead a `CHECK_EPOCH` build argument; since
(https://git.eeqj.de/sneak/sfdupes/issues/95). Run as root, the tests fail https://git.eeqj.de/sneak/sfdupes/issues/95 every `docker build` in `script/`
passes `--no-cache` instead. Run as root, the tests fail
`TestScanHardlinkRunFailsTogether`, because root reads through the `chmod(0)` `TestScanHardlinkRunFailsTogether`, because root reads through the `chmod(0)`
the test relies on, so they run as an unprivileged user the test relies on, so the `test` phase runs them as `nobody`
- check the installed golangci-lint version in `script/bootstrap` instead of - check the installed golangci-lint version in `script/bootstrap` instead of
only its presence (2026-08-09, branch `bootstrap-version-check`, closes only its presence (2026-08-09, branch `bootstrap-version-check`, closes
https://git.eeqj.de/sneak/sfdupes/issues/24): the version lives only in https://git.eeqj.de/sneak/sfdupes/issues/24): the version lives only in