4 Commits

Author SHA1 Message Date
60442ce103 build: add a make build target, drop README's raw go build (closes #19)
The executable builds to build/rogue. All generated artifacts go under
build/, which .gitignore covers as a whole; a target writing outside it
can commit its output.

build is in neither check nor test: check stays fmt-check lint test and
still writes nothing into the working tree.

README's "Building and running" block and the run examples use
./build/rogue, and no raw go invocation is left in the file.

Verified: make build writes build/rogue and git status stays clean;
GOFLAGS=-count=1 make check green in 34s with the lint layer executing
(21.9s, "0 issues.", not CACHED) and the suite running for real (cmd/rogue
1.027s, game 3.450s), git status clean afterwards.
2026-08-10 13:48:58 +00:00
6f997b8d5c docs: trim the lint-gate comments to the traps (closes #44)
Comments and documentation only; the docker build invocation and its three
flags are byte-identical and .dockerignore's effective rules are unchanged.

script/lint and Dockerfile.lint stated how the shape was derived — why two
stages, why `golangci-lint config verify` was omitted, what earlier drafts
of the comments claimed. That is in the history. What survives is the three
traps, each of which yields a green run over an unlinted or partly linted
tree: --target and --no-cache-filter must both stay with $stage matching the
stage name in Dockerfile.lint; --target checks that the stage exists, not
that it runs golangci-lint, and halts the build there; and .dockerignore
decides what reaches the container, so excluding a self-contained Go file
drops it from the lint silently.

The TODO.md entry loses its "Hardened" and "Corrected" paragraphs, which
argued with earlier versions of themselves, and keeps the flags, the durable
property, the three unguarded seams, and the evidence that the gate was
verified rather than assumed.
2026-08-10 13:38:15 +00:00
3eb9f81fc4 docs: name the two required flags, and record .dockerignore as part of the gate
Comments and documentation only; the docker build invocation and its flags
are untouched, and .dockerignore's effective rules are unchanged.

Two prose gaps from review. First, "both flags below must stay" had lost
its anchor: it ended a paragraph naming only --no-cache-filter, --target
was not introduced until the next one, and three flags follow on the
command, so a reader could pick the wrong pair. It now names --target and
--no-cache-filter explicitly.

Second, the list of things the tooling does not check covered the $stage
seam but not .dockerignore, which sits in the same trust boundary and is
the more likely thing to be edited — the first review on this change
actively suggested extending it for build artifacts. Only what reaches the
container is linted, so excluding a Go source there removes it from the
lint with no warning. Verified rather than asserted: a planted violation
plus that one path in .dockerignore yields `0 issues.` at exit 0 with the
violation still in the working tree, while excluding a file other code
still references fails loudly on `undefined:` typecheck errors instead.
The warning is recorded in script/lint alongside the $stage seam and in
.dockerignore itself, where the edit would actually be made.
2026-08-10 13:29:44 +00:00
599286a88e build: run golangci-lint in a pinned container via script/lint (closes #41)
golangci-lint is no longer invoked on the host anywhere in the repo.
Dockerfile.lint pins golangci/golangci-lint:v2.12.2 by digest and runs
the linter as a build step, so a successful build IS a clean lint, and
`make lint` becomes a thin shim over script/lint. This removes the host
linter install that produced a false green here, where a branch that was
genuinely red with a goconst finding reported "0 issues" off the shared
host cache; a container per run has its own cache and lock.

Two deliberate divergences from the sneak/homoicon reference shape:

  - Two stages rather than one. A cached `deps` stage holds
    `go mod download`, then `FROM deps AS lint` carries the source copy
    and the lint run, and script/lint builds with
    `--no-cache-filter=lint`. Caching of the lint result is explicitly
    waived (a cached build lints nothing), and splitting the stages means
    busting the lint layer does not re-fetch the module cache over the
    network on every run.

  - No `golangci-lint config verify` step. It resolves its JSON schema
    over a live, unpinned HTTPS call: an unpinned network input inside
    the one step whose purpose is a pinned, reproducible gate, and a
    schema-host outage would surface as a red build. `golangci-lint run`
    already fails on a malformed config. The reason is recorded in a
    comment in Dockerfile.lint.

.dockerignore excludes .git only; the lint reads the Go sources,
go.mod/go.sum and .golangci.yml, none of which come from there.

The TODO.md scaffold-exemption note is narrowed rather than dropped:
Dockerfile.lint and script/lint are now permitted and required, while CI
config, REPO_POLICIES.md, an application Dockerfile and any other
script/ entrypoint still are not.

Verified, since a green docker build is the classic false green: two
consecutive script/lint runs on an unchanged tree each showed the
`golangci-lint run` layer executing (9.8s and 7.9s, both "0 issues.")
while the deps layers reported CACHED; a deliberate indent-error-flow
violation failed the build naming that finding and the unused one, and a
revert went clean again. `make check` green.
2026-08-10 12:33:41 +00:00