Head is the two-parent merge of main into next from issue #26, preserved as-is. Not rebased, not re-merged.
Findings
The golangci-lint v1.64.8 pin that issue #27 predicted does not exist anywhere in the tree (grep -rn '1\.64' over the working tree returns nothing). script/lint is a bare golangci-lint run and script/fmt-check is a gofmt -l . check; both are version-agnostic and already work against the v2.12.2 .golangci.yml that main carries. script/bootstrap installs golangci-lint from the host package manager, also unpinned. So DoD 1 needed no code change — it is satisfied as merged, and now proven in-container.
Likewise .gitea/workflows/check.yml already invoked script/cibuild, so DoD 5 was already satisfied.
The real gap was DoD 4.
Changes
Dockerfile — the lint stage ran make fmt-check and make lint as separate steps, and a separate stage ran make test. script/check was therefore never exercised by the container gate, so the CI entrypoint and the local entrypoint could drift apart silently. Replaced with a single check stage that runs make check, plus a build stage that copies from it (making the stage dependency explicit) and then compiles. docker build . now runs the full verification suite and only then builds, which is what script/cibuild's own comment already claimed.
script/check — reordered to fmt-check, lint, test so the cheap checks fail first. Same three checks; nothing added, nothing removed.
Both FROM lines remain digest-pinned. .golangci.yml is untouched.
Verification
Per PR #21, a host make check is not evidence in this repo, so this was verified in-container only, with --no-cache:
$ docker build --no-cache --progress=plain .
#12 [check 6/6] RUN make check
#12 0.218 level=warning msg="The linter 'gomodguard' is deprecated (since v2.12.0) due to: new major version. Replaced by gomodguard_v2."
#12 5.162 0 issues.
#12 5.897 === RUN TestJSONHandlerDeadlock
#12 5.897 === RUN TestCompile
#12 5.897 --- PASS: TestCompile (0.00s)
#12 5.897 --- PASS: TestJSONHandlerDeadlock (0.00s)
#12 5.897 PASS
#12 5.897 ok sneak.berlin/go/simplelog 0.002s
#12 5.897 ? sneak.berlin/go/simplelog/cmd/example [no test files]
#12 5.897 ? sneak.berlin/go/simplelog/tools [no test files]
#12 DONE 6.0s
#18 [build 7/7] RUN go build ./... && go build -o /out/example ./cmd/example
#18 DONE 3.5s
BUILD rc=0
golangci-lint reports 0 issues., gofmt -l . is silent, and both tests pass.
No check result came from cache. The build log contains exactly two CACHED entries, #6 [check 2/6] WORKDIR /src and #7 [build 1/7] FROM golang@sha256:1cf6c45b.... Those are a metadata-only WORKDIR and the base-image layer respectively. Every RUN step — go mod download, make check, go build — executed fresh.
Constraints observed
.golangci.yml not modified.
No linter disabled, no check weakened, no test skipped or deleted.
Every FROM digest-pinned.
No tag created.
main, next and fix/handler-attrs untouched. No force-push.
Notes for the owner (not addressed here, deliberately out of scope)
golangci-lint v2.12.2 emits a deprecation warning for gomodguard (replaced by gomodguard_v2), reached via linters.default: all. Silencing it requires editing .golangci.yml, which is owner-only, so it is left alone. It is a warning, not a failure.
script/fmt calls goimports, which script/bootstrap does not install and which is absent from the lint image. script/fmt is a write-mode developer convenience and is not on the make check / container path, so it does not affect this gate. It is outside issue #27's definition of done and is left for a separate issue rather than widened into this PR.
Phase 2 of [issue #16](https://git.eeqj.de/sneak/simplelog/issues/16). Implements [issue #27](https://git.eeqj.de/sneak/simplelog/issues/27).
**STATUS: GREEN.** `docker build --no-cache --progress=plain .` exits 0. Output below.
## Branch shape
Head is the two-parent merge of `main` into `next` from [issue #26](https://git.eeqj.de/sneak/simplelog/issues/26), preserved as-is. Not rebased, not re-merged.
## Findings
The golangci-lint v1.64.8 pin that [issue #27](https://git.eeqj.de/sneak/simplelog/issues/27) predicted **does not exist anywhere in the tree** (`grep -rn '1\.64'` over the working tree returns nothing). `script/lint` is a bare `golangci-lint run` and `script/fmt-check` is a `gofmt -l .` check; both are version-agnostic and already work against the v2.12.2 `.golangci.yml` that `main` carries. `script/bootstrap` installs golangci-lint from the host package manager, also unpinned. So **DoD 1 needed no code change** — it is satisfied as merged, and now proven in-container.
Likewise `.gitea/workflows/check.yml` already invoked `script/cibuild`, so **DoD 5 was already satisfied**.
The real gap was DoD 4.
## Changes
- **`Dockerfile`** — the lint stage ran `make fmt-check` and `make lint` as separate steps, and a separate stage ran `make test`. `script/check` was therefore never exercised by the container gate, so the CI entrypoint and the local entrypoint could drift apart silently. Replaced with a single `check` stage that runs **`make check`**, plus a `build` stage that copies from it (making the stage dependency explicit) and then compiles. `docker build .` now runs the full verification suite and only then builds, which is what `script/cibuild`'s own comment already claimed.
- **`script/check`** — reordered to fmt-check, lint, test so the cheap checks fail first. Same three checks; nothing added, nothing removed.
Both `FROM` lines remain digest-pinned. `.golangci.yml` is untouched.
## Verification
Per [PR #21](https://git.eeqj.de/sneak/simplelog/pulls/21), a host `make check` is not evidence in this repo, so this was verified **in-container only**, with `--no-cache`:
```
$ docker build --no-cache --progress=plain .
#12 [check 6/6] RUN make check
#12 0.218 level=warning msg="The linter 'gomodguard' is deprecated (since v2.12.0) due to: new major version. Replaced by gomodguard_v2."
#12 5.162 0 issues.
#12 5.897 === RUN TestJSONHandlerDeadlock
#12 5.897 === RUN TestCompile
#12 5.897 --- PASS: TestCompile (0.00s)
#12 5.897 --- PASS: TestJSONHandlerDeadlock (0.00s)
#12 5.897 PASS
#12 5.897 ok sneak.berlin/go/simplelog 0.002s
#12 5.897 ? sneak.berlin/go/simplelog/cmd/example [no test files]
#12 5.897 ? sneak.berlin/go/simplelog/tools [no test files]
#12 DONE 6.0s
#18 [build 7/7] RUN go build ./... && go build -o /out/example ./cmd/example
#18 DONE 3.5s
BUILD rc=0
```
`golangci-lint` reports `0 issues.`, `gofmt -l .` is silent, and both tests pass.
**No check result came from cache.** The build log contains exactly two `CACHED` entries, `#6 [check 2/6] WORKDIR /src` and `#7 [build 1/7] FROM golang@sha256:1cf6c45b...`. Those are a metadata-only `WORKDIR` and the base-image layer respectively. Every `RUN` step — `go mod download`, `make check`, `go build` — executed fresh.
## Constraints observed
- `.golangci.yml` not modified.
- No linter disabled, no check weakened, no test skipped or deleted.
- Every `FROM` digest-pinned.
- No tag created.
- `main`, `next` and `fix/handler-attrs` untouched. No force-push.
## Notes for the owner (not addressed here, deliberately out of scope)
1. golangci-lint v2.12.2 emits a deprecation warning for `gomodguard` (replaced by `gomodguard_v2`), reached via `linters.default: all`. Silencing it requires editing `.golangci.yml`, which is owner-only, so it is left alone. It is a warning, not a failure.
2. `script/fmt` calls `goimports`, which `script/bootstrap` does not install and which is absent from the lint image. `script/fmt` is a write-mode developer convenience and is not on the `make check` / container path, so it does not affect this gate. It is outside [issue #27](https://git.eeqj.de/sneak/simplelog/issues/27)'s definition of done and is left for a separate issue rather than widened into this PR.
Brings the scripts-to-rule-them-all scaffold from `next` (script/
entrypoints, Makefile shims, .gitea/workflows/check.yml, vendored
REPO_POLICIES.md) onto `main`, which meanwhile moved to golangci-lint
v2.12.2 with the canonical config.
Only TODO.md conflicted: both sides prepended an entry to Completed
Steps. Kept both in reverse-chronological order and normalized the
`next` entry to the file's `*` bullet style.
.golangci.yml is unchanged from `main`.
Reconciling script/lint, script/fmt-check and script/check with
golangci-lint v2.12.2 is deliberately left to phase 2.
Part of #26
The lint stage ran make fmt-check and make lint as separate steps and a
second stage ran make test, so script/check was never exercised by the
container gate. Collapse the verification into a single check stage that
runs make check, and add a build stage that depends on it so
docker build . runs the full suite and then builds.
Reorder script/check to fmt-check, lint, test so the cheap checks fail
first.
Both FROM lines remain digest-pinned.
Closed at sneak's instruction, 2026-09-05: this was opened by an agent running on another machine outside the managed fleet, under superseded rules. Reopen if the content is wanted.
Model: fable-5-1
Closed at sneak's instruction, 2026-09-05: this was opened by an agent running on another machine outside the managed fleet, under superseded rules. Reopen if the content is wanted.
Model: fable-5-1
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.
Phase 2 of issue #16. Implements issue #27.
STATUS: GREEN.
docker build --no-cache --progress=plain .exits 0. Output below.Branch shape
Head is the two-parent merge of
mainintonextfrom issue #26, preserved as-is. Not rebased, not re-merged.Findings
The golangci-lint v1.64.8 pin that issue #27 predicted does not exist anywhere in the tree (
grep -rn '1\.64'over the working tree returns nothing).script/lintis a baregolangci-lint runandscript/fmt-checkis agofmt -l .check; both are version-agnostic and already work against the v2.12.2.golangci.ymlthatmaincarries.script/bootstrapinstalls golangci-lint from the host package manager, also unpinned. So DoD 1 needed no code change — it is satisfied as merged, and now proven in-container.Likewise
.gitea/workflows/check.ymlalready invokedscript/cibuild, so DoD 5 was already satisfied.The real gap was DoD 4.
Changes
Dockerfile— the lint stage ranmake fmt-checkandmake lintas separate steps, and a separate stage ranmake test.script/checkwas therefore never exercised by the container gate, so the CI entrypoint and the local entrypoint could drift apart silently. Replaced with a singlecheckstage that runsmake check, plus abuildstage that copies from it (making the stage dependency explicit) and then compiles.docker build .now runs the full verification suite and only then builds, which is whatscript/cibuild's own comment already claimed.script/check— reordered to fmt-check, lint, test so the cheap checks fail first. Same three checks; nothing added, nothing removed.Both
FROMlines remain digest-pinned..golangci.ymlis untouched.Verification
Per PR #21, a host
make checkis not evidence in this repo, so this was verified in-container only, with--no-cache:golangci-lintreports0 issues.,gofmt -l .is silent, and both tests pass.No check result came from cache. The build log contains exactly two
CACHEDentries,#6 [check 2/6] WORKDIR /srcand#7 [build 1/7] FROM golang@sha256:1cf6c45b.... Those are a metadata-onlyWORKDIRand the base-image layer respectively. EveryRUNstep —go mod download,make check,go build— executed fresh.Constraints observed
.golangci.ymlnot modified.FROMdigest-pinned.main,nextandfix/handler-attrsuntouched. No force-push.Notes for the owner (not addressed here, deliberately out of scope)
gomodguard(replaced bygomodguard_v2), reached vialinters.default: all. Silencing it requires editing.golangci.yml, which is owner-only, so it is left alone. It is a warning, not a failure.script/fmtcallsgoimports, whichscript/bootstrapdoes not install and which is absent from the lint image.script/fmtis a write-mode developer convenience and is not on themake check/ container path, so it does not affect this gate. It is outside issue #27's definition of done and is left for a separate issue rather than widened into this PR.Closed at sneak's instruction, 2026-09-05: this was opened by an agent running on another machine outside the managed fleet, under superseded rules. Reopen if the content is wanted.
Model: fable-5-1
Pull request closed