Commit Graph
11 Commits
Author SHA1 Message Date
clawbot d43c1d31ac Merge branch 'next': run all linting in Docker (closes #46)
check / check (push) Successful in 1m19s
2026-08-10 15:55:42 +02:00
clawbot e6a91711b0 Merge branch 'dockerfile-bootstrap': bootstrap the builder stage, guard the linter pin (closes #42)
check / check (push) Successful in 1m19s
The build stage installed prerequisites inline instead of running
script/bootstrap, which canonical REPO_POLICIES forbids. It now copies
script/ and the manifests and runs bootstrap.

The first attempt claimed that reordering COPY --from=lint made the
build fail loudly on linter drift. It did the opposite: bootstrap
reinstalled to GOPATH/bin, which ENV PATH placed ahead of the copied
binary, so verification passed by construction and lint and build
stages could silently run different linters. Rather than soften the
claim, the guarantee is now implemented. script/verify-linter-pin runs
against the copied binary before bootstrap and fails, naming both
versions, unless it matches the pin read out of script/bootstrap.

Reviewed independently. The reviewer reproduced the negative control in
both directions, including one the PR did not claim - bumping the pin
alone also fails the build - and established that no version output or
mangled pin file yields a silent pass.
2026-08-09 17:43:57 +02:00
clawbot 47fd4e8def Merge branch 'refresh-repo-policies': re-vendor REPO_POLICIES.md (closes #20)
check / check (push) Successful in 1m7s
The vendored policy copy had drifted to 368 lines against the canonical
408 while still declaring last_modified: 2026-07-06, so nothing about
it signalled staleness. Agents read this file to learn the rules, and
the drift has already caused real defects: the missing scripts-to-rule-
them-all section is why script/fmt lost its Markdown pass (#19) and why
the README had no Entrypoints section (#21).

Replaced wholesale with the canonical copy, sha256
117dde7f148ed3cd693b333312f6345a0a0ee84fadbbe5cca559ca6fed4a1775.
Verified byte-identical by diff; REPO_POLICIES.md is the only file
touched.

The drift turned out to be bidirectional: the vendored copy also held a
repo-memory paragraph the canonical file does not have, so re-vendoring
removes it. That is the correct action for a vendored copy — if the
paragraph should exist it belongs upstream — but it is the one part of
this diff that is not a pure restoration, and it is flagged for a
decision rather than buried.

Docs-only, so the adversarial review was skipped per the standing
exception. make check green.
2026-08-09 12:00:54 +02:00
clawbot 99d757c31d Re-vendor REPO_POLICIES.md from the canonical copy (closes #20)
check / check (push) Successful in 1m14s
The vendored copy had drifted to 368 lines against the canonical 408
while still declaring `last_modified: 2026-07-06`, so nothing about the
file signalled that it was stale. Agents working in this repo read the
vendored copy to learn the rules, which makes a silent 40-line gap a
source of real defects rather than untidiness: two have already been
traced to exactly this drift, `script/fmt` having dropped the prettier
Markdown pass (#19, still open) and the README having no Entrypoints
section (#21, since fixed).

Restored by copying the canonical file wholesale — no hand-editing, no
partial merge, no local adaptation, because it is a vendored copy and
its value comes from matching upstream byte for byte. What comes back:

- the entire Scripts to Rule Them All section, including the POSIX sh
  requirement, the repo-root discovery idiom, and the division between
  the standard's canonical scripts and our four extensions
- `bootstrap`, `setup` and `hooks` in the required Makefile target list
- the `script/precommit` paragraph and how the pre-commit hook is wired
  through `script/install-precommit`
- the README **Entrypoints** section requirement
- the Dockerfile bootstrap-layer guidance and the `script/cibuild`
  wording in the Gitea Actions bullet

Verified: `diff` against the canonical file is empty, sha256 is
117dde7f148ed3cd693b333312f6345a0a0ee84fadbbe5cca559ca6fed4a1775, and
`REPO_POLICIES.md` is the only changed path. `make check` is green.

No `TODO.md` entry accompanies this commit. The repo convention is to
record the work in the same commit, but the issue's definition of done
restricts the change to `REPO_POLICIES.md` alone; that scope discipline
is what lets a docs-only change skip adversarial review.
2026-08-09 09:57:43 +00:00
clawbot a5fa600c98 Merge branch 'readme-entrypoints': document the entrypoints, drop the tooling line (closes #21)
check / check (push) Successful in 1m10s
Removes the tooling attribution sentence from the Description, adds the
required Entrypoints section documenting all twelve script/ entrypoints
written from reading each script, corrects the stale Build section that
still claimed the Makefile was the single source of truth after every
target became a shim, and fixes the scan summary example, whose figures
did not sum to the stated total.

Docs-only (README.md alone), so the adversarial review was skipped per
the standing exception. Scope verified independently: git diff
--name-only reports README.md and nothing else. make check green.
2026-08-09 09:53:49 +02:00
clawbot a102b8fb06 Merge branch 'cibuild-cache-bust': make the Docker gates actually execute (closes #32)
check / check (push) Successful in 1m12s
script/cibuild and script/docker were bare docker build invocations, so
on an unchanged tree Docker served the gate layers from cache: no
tests, no lint, exit 0. Confirmed live three times by reviewers, once
as a 17-layer total cache hit.

ARG CHECK_EPOCH is now declared in both stages, since ARG is scoped per
stage and this Dockerfile gates in two of them, and is interpolated
into each gate RUN so BuildKit's command hash actually changes. Both
scripts pass a fresh epoch. Dependency layers stay cached.

Reviewed independently. The reviewer re-established its own cache
baseline after a host-wide BuildKit prune landed mid-review, then
tested the counterfactual: holding the epoch constant reproduces
exactly the 17-layer false green this fixes. It also confirmed the
lint stage still gates the build stage by planting a finding, and that
the non-root drop remains load-bearing by showing the hardlink
permission test fails when the same image runs as root.
2026-08-09 09:47:02 +02:00
clawbot b8ebe5f578 Merge branch 'bootstrap-version-check': check the linter version, not just presence (closes #24)
check / check (push) Successful in 4s
script/bootstrap installed the pinned golangci-lint only when the
command was absent, so a version bump was inert on any host that
already had the tool. This one ran v2.10.1 against a v2.12.2 pin: local
make check went green while make docker rejected the same commit with
six goconst findings.

Bootstrap now compares the installed version against the pin, which
lives in exactly one place, and reinstalls on mismatch. It then
verifies the install actually took effect: go install writes to
GOPATH/bin, but the binary make lint runs is whatever PATH resolves, so
a wrong-version linter shadowing it earlier on PATH would otherwise
leave bootstrap printing success having changed nothing. On mismatch it
now names both paths on stderr and exits non-zero.

The first review caught that shadowing case. Re-reviewed independently
by a fresh reviewer, who rebuilt the reproduction from scratch across
seven PATH layouts, ran a 20-row version-parse matrix confirming no
input yields a false match, and forced a cold Docker build after
finding the cached one executed nothing. Confirmed along the way that
v2.10.1 was hiding no findings on main.
2026-08-09 08:38:36 +02:00
clawbot 076d82231b Merge branch 'hash-pool-cleanup': unwind the hash worker pool on error (closes #6)
check / check (push) Successful in 5s
hashPhase returned early on a recordRun error, abandoning the feeder
goroutine and the hash workers, which parked forever on channel sends.
The pool is now owned: every blocking send selects on ctx.Done(), and
hashPhase defers a stop() that cancels and then drains results. ctx is
threaded from cmd.Context() through runScan, syncScan, both pools and
the database layer, as contextcheck requires.

The walk pool gets the same treatment. It does not leak today, because
walkPhase has no early return, but #5 introduces one. That change also
required a ctx.Err() guard after the walk: a cancelled walk yields a
partial size census, and without the guard the update phase reads every
unreached file as vanished and deletes its record.

First review failed this: the test covering that guard was vacuous,
cancelling before the walk began. Replaced with a deterministic
mid-walk cancellation. Re-reviewed independently by a fresh reviewer,
who reproduced both falsification checks, measured the census across
four parallelism settings, mutation-verified all nine cancellation
branches, ran 120 randomised mid-flight cancellations over 18,000 files
with zero records lost, and forced a cold Docker build after finding
the cached one proved nothing. Coverage 88.5%.
2026-08-09 07:46:43 +02:00
clawbot 2a055c0104 Merge branch 'db-close-on-fatal': close the database on every exit path (closes #4)
check / check (push) Successful in 5s
fatalf called os.Exit(1), which skips deferred functions, so every
defer db.Close() was dead on the fatal path and the SQLite WAL was
never checkpointed. fatalf is gone; runScan, runReport and runTrees
return errors, and a single run(args, stderr) int in main.go is the
only exit point, which also makes these paths testable in-process.

Exit-code behaviour is unchanged: 0 success, 1 fatal, 2 usage. A runE
adapter keeps cobra from reclassifying runtime failures as usage errors
or printing usage text alongside them.

Independently reviewed. The reviewer verified all 15 documented exit
paths against binaries built from both base and head, confirmed the
sidecar WAL files no longer survive a fatal exit, and mutation-tested
the new assertions by reintroducing the defect to confirm they fail.
Coverage 64% to 86.9%. make check and make docker both green.
2026-08-09 04:39:28 +02:00
clawbot ce6d29dffb Merge branch 'todo-next-step-stale': point TODO.md at the tracker (closes #27)
check / check (push) Successful in 11s
TODO.md's Next Step still named the scripts-to-rule-them-all conversion,
which landed in 3abeacf on 2026-07-26 without recording itself in
Completed Steps, so the file pointed the next contributor at finished
work. Next Step now names the 1.0.0 milestone on the tracker, the
scaffold gains its missing Completed Steps entry, and Workflow matches
the issue-branch-review-merge process actually in use.

Docs-only change (TODO.md only), so the adversarial review was skipped
per the standing exception. make check green.
2026-08-09 04:05:04 +02:00
clawbot 38a01bd27c Merge branch 'golangci-v2.12.2': golangci-lint v2.12.2 and canonical config (closes #3)
check / check (push) Has been cancelled
Bumps the pinned golangci-lint from v2.12.1 to v2.12.2 in the Dockerfile
lint stage and script/bootstrap, and replaces .golangci.yml with the
canonical org-standard file (sha256
021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb).

The material change is that the lll, funlen, cyclop and dupl thresholds
move from the v1-style top-level linters-settings key, which
golangci-lint v2 silently ignores, to linters.settings, where they are
actually enforced. Independent review proved the migration claim with a
controlled experiment and confirmed the code passes the now-live
thresholds with zero findings.

Reviewed independently; make check and make docker both green.
2026-08-09 03:57:09 +02:00