Owner ruling, sneak 2026-08-09: every lint run happens inside a Docker container, invoked through the script/ entrypoint. Docker is always available. Linting runs independently and does not need a cache. He has directed a PR for every repo not already set up this way.
Reference implementation is sneak/homoicon — copy its shape: a root Dockerfile.lint built FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240, which COPYs the repo in and runs golangci-lint run --config .golangci.yml ./... as a build step, with script/lint reduced to building it. Linting as a build step means a successful build IS a clean lint.
This supersedes the version-pinning approach scoped for script/lint here, and it also removes the escape-into-another-worktree problem observed in this repo — a host lint run reported findings whose paths pointed into a different agent's worktree entirely.
Note this repo already builds lint in a separate hash-pinned Docker stage; the change is to make script/lint the only path and drop any host invocation, not to introduce Docker where there was none.
Two things to get right, both of which would otherwise ship a false green:
A cached build lints nothing. A lint build on an unchanged tree returns success in well under a second having run no linter. Caching is explicitly waived here, so force the lint layers to execute.
golangci-lint config verify fetches its JSON schema over an unpinned live HTTPS call. Decide deliberately whether to include it.
Definition of done
script/lint runs the linter only in Docker; no host golangci-lint path remains.
Two consecutive script/lint runs on an unchanged tree both demonstrably execute the linter.
Negative control: introduce a deliberate lint violation, confirm it fails with that specific finding, revert, confirm clean.
SPLIT 2026-09-03:#104 could not be completed inside a single agent run (three attempts died mid-run having pushed nothing). Split into:
issue #107 — add hash-pinned Dockerfile.lint, make script/lint Docker-only (mechanical)
issue #108 — prove the gate actually lints: layer-cache defeat + negative control (blocked on 107)
This issue stays open as the parent tracker and should be closed by hand once both children merge. Do not dispatch work directly against #104.
Owner ruling, sneak 2026-08-09: every lint run happens inside a Docker container, invoked through the `script/` entrypoint. Docker is always available. Linting runs independently and does not need a cache. He has directed a PR for every repo not already set up this way.
Reference implementation is `sneak/homoicon` — copy its shape: a root `Dockerfile.lint` built `FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240`, which COPYs the repo in and runs `golangci-lint run --config .golangci.yml ./...` as a build step, with `script/lint` reduced to building it. Linting as a build step means a successful build IS a clean lint.
This supersedes the version-pinning approach scoped for `script/lint` here, and it also removes the escape-into-another-worktree problem observed in this repo — a host lint run reported findings whose paths pointed into a different agent's worktree entirely.
Note this repo already builds lint in a separate hash-pinned Docker stage; the change is to make `script/lint` the only path and drop any host invocation, not to introduce Docker where there was none.
Two things to get right, both of which would otherwise ship a false green:
1. **A cached build lints nothing.** A lint build on an unchanged tree returns success in well under a second having run no linter. Caching is explicitly waived here, so force the lint layers to execute.
2. **`golangci-lint config verify` fetches its JSON schema over an unpinned live HTTPS call.** Decide deliberately whether to include it.
## Definition of done
- `script/lint` runs the linter only in Docker; no host golangci-lint path remains.
- Two consecutive `script/lint` runs on an unchanged tree both demonstrably execute the linter.
- Negative control: introduce a deliberate lint violation, confirm it fails with that specific finding, revert, confirm clean.
- `make check` still green.
Canonical tracking issue: https://git.eeqj.de/sneak/prompts/issues/40
---
**SPLIT 2026-09-03:** #104 could not be completed inside a single agent run (three attempts died mid-run having pushed nothing). Split into:
- [issue #107](https://git.eeqj.de/sneak/pixa/issues/107) — add hash-pinned `Dockerfile.lint`, make `script/lint` Docker-only (mechanical)
- [issue #108](https://git.eeqj.de/sneak/pixa/issues/108) — prove the gate actually lints: layer-cache defeat + negative control (blocked on 107)
This issue stays open as the parent tracker and should be closed by hand once both children merge. Do not dispatch work directly against #104.
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.
Owner ruling, sneak 2026-08-09: every lint run happens inside a Docker container, invoked through the
script/entrypoint. Docker is always available. Linting runs independently and does not need a cache. He has directed a PR for every repo not already set up this way.Reference implementation is
sneak/homoicon— copy its shape: a rootDockerfile.lintbuiltFROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240, which COPYs the repo in and runsgolangci-lint run --config .golangci.yml ./...as a build step, withscript/lintreduced to building it. Linting as a build step means a successful build IS a clean lint.This supersedes the version-pinning approach scoped for
script/linthere, and it also removes the escape-into-another-worktree problem observed in this repo — a host lint run reported findings whose paths pointed into a different agent's worktree entirely.Note this repo already builds lint in a separate hash-pinned Docker stage; the change is to make
script/lintthe only path and drop any host invocation, not to introduce Docker where there was none.Two things to get right, both of which would otherwise ship a false green:
golangci-lint config verifyfetches its JSON schema over an unpinned live HTTPS call. Decide deliberately whether to include it.Definition of done
script/lintruns the linter only in Docker; no host golangci-lint path remains.script/lintruns on an unchanged tree both demonstrably execute the linter.make checkstill green.Canonical tracking issue: sneak/prompts#40
SPLIT 2026-09-03: #104 could not be completed inside a single agent run (three attempts died mid-run having pushed nothing). Split into:
Dockerfile.lint, makescript/lintDocker-only (mechanical)This issue stays open as the parent tracker and should be closed by hand once both children merge. Do not dispatch work directly against #104.
clawbot referenced this issue2026-09-03 20:06:21 +02:00