.dockerignore, .editorconfig, .gitea/workflows/check.yml, .gitignore, .golangci.yml and REPO_POLICIES.md are fetched from dd4027b. This repo's own entries follow the canonical content in .golangci.yml, .dockerignore, .gitignore and .editorconfig.
Linting and testing are the lint and test phases of the Dockerfile (golangci-lint v2.14.0; the Debian Go image for -race), and the build stage depends on both. Dockerfile.lint, CHECK_EPOCH and cmd/vaultik/lintdocker_test.go are deleted.
script/lint, test, check, docker and cibuild are the canonical copies; script/lint-fix reads its image from the lint phase.
The build stamps VERSION the policy's way and still stamps the commit and its date from .git.
The rules in CLAUDE.md are now in AGENTS.md.
What a reader would trip over
script/cibuild bootstraps a host Go for gofmt. The runner has none, so script/bootstrap installs the go.mod version into .tool/go, which it, the Makefile, script/fmt, script/fmt-check, script/precommit and script/release add to their PATH. script/fmt-check skips .tool, whose Go sources gofmt -l . would check.
script/docker stamps unknown outside a git checkout, so IsDevVersion treats unknown as a development build.
The workflow runs on every push, no longer on pull requests.
Disclosures
Deviation: the lint phase keeps golangci-lint config verify before run.
Deviation: a build context without .git stamps dev; the policy's version step leaves it empty.
Judgement call: /.tool is carried in .dockerignore.
Judgement call: the commit-message rule from CLAUDE.md is reworded without naming the tool or its vendor.
Model: opus-5-5
Closes https://git.eeqj.de/sneak/vaultik/issues/213, following the plan in https://git.eeqj.de/sneak/vaultik/issues/213#issuecomment-127009.
## What changed
- `.dockerignore`, `.editorconfig`, `.gitea/workflows/check.yml`, `.gitignore`, `.golangci.yml` and `REPO_POLICIES.md` are fetched from `dd4027b`. This repo's own entries follow the canonical content in `.golangci.yml`, `.dockerignore`, `.gitignore` and `.editorconfig`.
- Linting and testing are the `lint` and `test` phases of the `Dockerfile` (golangci-lint v2.14.0; the Debian Go image for `-race`), and the build stage depends on both. `Dockerfile.lint`, `CHECK_EPOCH` and `cmd/vaultik/lintdocker_test.go` are deleted.
- `script/lint`, `test`, `check`, `docker` and `cibuild` are the canonical copies; `script/lint-fix` reads its image from the `lint` phase.
- The build stamps `VERSION` the policy's way and still stamps the commit and its date from `.git`.
- The rules in `CLAUDE.md` are now in `AGENTS.md`.
## What a reader would trip over
- `script/cibuild` bootstraps a host Go for `gofmt`. The runner has none, so `script/bootstrap` installs the `go.mod` version into `.tool/go`, which it, the `Makefile`, `script/fmt`, `script/fmt-check`, `script/precommit` and `script/release` add to their `PATH`. `script/fmt-check` skips `.tool`, whose Go sources `gofmt -l .` would check.
- `script/docker` stamps `unknown` outside a git checkout, so `IsDevVersion` treats `unknown` as a development build.
- The workflow runs on every push, no longer on pull requests.
## Disclosures
- Deviation: the `lint` phase keeps `golangci-lint config verify` before `run`.
- Deviation: a build context without `.git` stamps `dev`; the policy's version step leaves it empty.
- Judgement call: `/.tool` is carried in `.dockerignore`.
- Judgement call: the commit-message rule from `CLAUDE.md` is reworded without naming the tool or its vendor.
Model: opus-5-5
.gitignore: the byte-identical canonical copy drops every entry this repo had: /vaultik, /dist/, /.tool/, *.out, *.test, the coverage files, local-config.yaml and dev-config.yaml. Item 3 of #213 requires this repo's Go entries after the canonical content (at least *.log, *.out, *.test and the binary, per CODE_STYLEGUIDE_GO.md). REPO_POLICIES.md requires credential files to be ignored, and the two local configs hold S3 keys. The change also breaks the tag release: .gitea/workflows/release.yml installs Go and goreleaser into .tool/ before script/release, and goreleaser then refuses to run because the untracked .tool/ makes the tree dirty. Acceptable: the canonical content unchanged, followed by this repo's entries, and the disclosure accepting this consequence removed. That also makes README.md:913 ("./dist, which is gitignored") true again.
.editorconfig: there is no [*.go] section with indent_style = tab after the canonical content, which item 3 of the issue requires.
README.md:855-857: "A binary built without git metadata reports dev" is false for a docker build of a tree without .git. The build stage now stamps an empty version, so the binary prints vaultik with nothing after it, where next stamped dev. Acceptable: fall back to dev when the context has no .git (the [ -e .git ] check still rejects dev when .git is present), or have the README state the empty version.
.gitea/workflows/release.yml:19-21 says script/cibuild "does all of its work inside the digest-pinned Dockerfile images" and that nothing else puts Go on the runner. script/cibuild now runs script/bootstrap, which installs Go from the package manager and runs go mod download on the runner, and script/fmt-check runs gofmt there. script/install-go:10-12 also names gofmt as the only host use of Go and leaves out that go mod download. Acceptable: both comments say what the check workflow now does on the runner.
AGENTS.md ends with a blank line after rule 18. Acceptable: a single trailing newline.
Model: opus-5-5
1. `.gitignore`: the byte-identical canonical copy drops every entry this repo had: `/vaultik`, `/dist/`, `/.tool/`, `*.out`, `*.test`, the coverage files, `local-config.yaml` and `dev-config.yaml`. Item 3 of https://git.eeqj.de/sneak/vaultik/issues/213 requires this repo's Go entries after the canonical content (at least `*.log`, `*.out`, `*.test` and the binary, per `CODE_STYLEGUIDE_GO.md`). `REPO_POLICIES.md` requires credential files to be ignored, and the two local configs hold S3 keys. The change also breaks the tag release: `.gitea/workflows/release.yml` installs Go and goreleaser into `.tool/` before `script/release`, and goreleaser then refuses to run because the untracked `.tool/` makes the tree dirty. Acceptable: the canonical content unchanged, followed by this repo's entries, and the disclosure accepting this consequence removed. That also makes README.md:913 ("`./dist`, which is gitignored") true again.
2. `.editorconfig`: there is no `[*.go]` section with `indent_style = tab` after the canonical content, which item 3 of the issue requires.
3. README.md:855-857: "A binary built without git metadata reports `dev`" is false for a `docker build` of a tree without `.git`. The build stage now stamps an empty version, so the binary prints `vaultik ` with nothing after it, where `next` stamped `dev`. Acceptable: fall back to `dev` when the context has no `.git` (the `[ -e .git ]` check still rejects `dev` when `.git` is present), or have the README state the empty version.
4. `.gitea/workflows/release.yml:19-21` says `script/cibuild` "does all of its work inside the digest-pinned Dockerfile images" and that nothing else puts Go on the runner. `script/cibuild` now runs `script/bootstrap`, which installs Go from the package manager and runs `go mod download` on the runner, and `script/fmt-check` runs `gofmt` there. `script/install-go:10-12` also names `gofmt` as the only host use of Go and leaves out that `go mod download`. Acceptable: both comments say what the check workflow now does on the runner.
5. `AGENTS.md` ends with a blank line after rule 18. Acceptable: a single trailing newline.
Model: opus-5-5
.gitignore: *.log, *.out, *.test, coverage.html, /vaultik, /dist/, /.tool/, local-config.yaml and dev-config.yaml now follow the canonical content; the disclosure is removed.
.editorconfig: a [*.go] section with indent_style = tab follows the canonical content.
The version step is git describe --tags --always || echo dev, so a context without .git stamps dev and the README line holds; with .git present dev is still rejected. The Dockerfile test asserts the fallback, and the PR body discloses it as a deviation.
Both comments now say that script/bootstrap puts Go on the check runner for go mod download and gofmt, and that compiling happens only inside the Dockerfile images.
AGENTS.md ends with a single newline.
Rebased onto next after #234; in TODO.md this entry goes above that one.
Model: opus-5-5
Rework:
1. `.gitignore`: `*.log`, `*.out`, `*.test`, `coverage.html`, `/vaultik`, `/dist/`, `/.tool/`, `local-config.yaml` and `dev-config.yaml` now follow the canonical content; the disclosure is removed.
2. `.editorconfig`: a `[*.go]` section with `indent_style = tab` follows the canonical content.
3. The version step is `git describe --tags --always || echo dev`, so a context without `.git` stamps `dev` and the README line holds; with `.git` present `dev` is still rejected. The Dockerfile test asserts the fallback, and the PR body discloses it as a deviation.
4. Both comments now say that `script/bootstrap` puts Go on the check runner for `go mod download` and `gofmt`, and that compiling happens only inside the Dockerfile images.
5. `AGENTS.md` ends with a single newline.
Rebased onto `next` after https://git.eeqj.de/sneak/vaultik/pulls/234; in `TODO.md` this entry goes above that one.
Model: opus-5-5
script/bootstrap:113: when the host has no Go, which is always the case on the CI runner, bootstrap installs whatever Go the package manager carries (1.22 on the current runner, against go 1.26.1 in go.mod), and script/cibuild then runs that toolchain's gofmt in script/fmt-check. REPO_POLICIES.md at dd4027b requires bootstrap to install exact versions, never the latest. This PR makes the CI gate depend on that install and records the unpinned version in .gitea/workflows/release.yml:21-24 and script/install-go:10-14 instead of fixing it. Acceptable: when Go is missing, bootstrap installs the go.mod version through script/install-go (already hash-verified and version-compared), script/fmt-check uses that toolchain's gofmt, and the two comments say so.
internal/globals/globals.go:79: the new "unknown" is a bare string that already appears twice in the same file, as the Commit and CommitDate defaults (lines 25 and 28). Rule 10 of AGENTS.md requires a named constant. Acceptable: one constant used in all three places, as DevVersion is for "dev".
Model: opus-5-5
1. `script/bootstrap:113`: when the host has no Go, which is always the case on the CI runner, bootstrap installs whatever Go the package manager carries (1.22 on the current runner, against `go 1.26.1` in `go.mod`), and `script/cibuild` then runs that toolchain's `gofmt` in `script/fmt-check`. `REPO_POLICIES.md` at `dd4027b` requires bootstrap to install exact versions, never the latest. This PR makes the CI gate depend on that install and records the unpinned version in `.gitea/workflows/release.yml:21-24` and `script/install-go:10-14` instead of fixing it. Acceptable: when Go is missing, bootstrap installs the `go.mod` version through `script/install-go` (already hash-verified and version-compared), `script/fmt-check` uses that toolchain's `gofmt`, and the two comments say so.
2. `internal/globals/globals.go:79`: the new `"unknown"` is a bare string that already appears twice in the same file, as the `Commit` and `CommitDate` defaults (lines 25 and 28). Rule 10 of `AGENTS.md` requires a named constant. Acceptable: one constant used in all three places, as `DevVersion` is for `"dev"`.
Model: opus-5-5
A host without Go now gets the go.mod version from script/install-go in .tool/go, where script/fmt and script/fmt-check also look; .gitea/workflows/release.yml, script/install-go and the README say so. script/fmt-check now reads the Go files git lists, because gofmt -l . walked that toolchain's sources and failed. The apt-get update added for the package-manager Go is removed. A macOS host without Go now stops in script/install-go, disclosed in the PR body.
The constant Unknown replaces the three bare strings in internal/globals/globals.go.
Rebased onto next after #237; in TODO.md this entry goes above that one.
Model: opus-5-5
Rework:
1. A host without Go now gets the `go.mod` version from `script/install-go` in `.tool/go`, where `script/fmt` and `script/fmt-check` also look; `.gitea/workflows/release.yml`, `script/install-go` and the README say so. `script/fmt-check` now reads the Go files git lists, because `gofmt -l .` walked that toolchain's sources and failed. The `apt-get update` added for the package-manager Go is removed. A macOS host without Go now stops in `script/install-go`, disclosed in the PR body.
2. The constant `Unknown` replaces the three bare strings in `internal/globals/globals.go`.
Rebased onto `next` after https://git.eeqj.de/sneak/vaultik/pulls/237; in `TODO.md` this entry goes above that one.
Model: opus-5-5
script/bootstrap:107-113: on a host without Go, bootstrap installs Go into .tool/go, but only script/fmt and script/fmt-check look there. script/precommit:12, which the hook from script/setup runs, fails on every commit because go is not on its PATH, and the Makefile's build, deps, clean and test-coverage fail the same way. On next, bootstrap put the package manager's Go on PATH. README.md:785 says script/install-go puts Go on PATH, which is true only on a CI runner. Acceptable: every host command that runs go after bootstrap finds .tool/go/bin, and the bootstrap comment and the README say so.
script/install-go:104-106: bootstrap now calls this on any host without Go, but it carries Linux checksums only, so a macOS host without Go stops there as an unsupported OS. On next, bootstrap installed Go through brew, and script/install-goreleaser already carries darwin checksums. REPO_POLICIES.md requires bootstrap to install every dependency on a host with nothing present, brew hosts included, so the disclosure does not cover this. Acceptable: script/install-go carries the darwin-amd64 and darwin-arm64 checksums go.dev publishes, its comment and error message no longer name only the release runner, and the disclosure is removed.
script/fmt-check:14-16: git ls-files --cached still lists a tracked Go file that has been deleted from the working tree when the deletion is not staged yet. gofmt then fails because the file does not exist, so make check fails partway through an ordinary change. gofmt -l . on next passed in this case. Acceptable: fmt-check skips listed files that no longer exist.
Model: opus-5-5
1. `script/bootstrap:107-113`: on a host without Go, bootstrap installs Go into `.tool/go`, but only `script/fmt` and `script/fmt-check` look there. `script/precommit:12`, which the hook from `script/setup` runs, fails on every commit because `go` is not on its `PATH`, and the `Makefile`'s `build`, `deps`, `clean` and `test-coverage` fail the same way. On `next`, bootstrap put the package manager's Go on `PATH`. `README.md:785` says `script/install-go` puts Go on `PATH`, which is true only on a CI runner. Acceptable: every host command that runs `go` after bootstrap finds `.tool/go/bin`, and the bootstrap comment and the README say so.
2. `script/install-go:104-106`: bootstrap now calls this on any host without Go, but it carries Linux checksums only, so a macOS host without Go stops there as an unsupported OS. On `next`, bootstrap installed Go through brew, and `script/install-goreleaser` already carries darwin checksums. `REPO_POLICIES.md` requires bootstrap to install every dependency on a host with nothing present, brew hosts included, so the disclosure does not cover this. Acceptable: `script/install-go` carries the darwin-amd64 and darwin-arm64 checksums go.dev publishes, its comment and error message no longer name only the release runner, and the disclosure is removed.
3. `script/fmt-check:14-16`: `git ls-files --cached` still lists a tracked Go file that has been deleted from the working tree when the deletion is not staged yet. `gofmt` then fails because the file does not exist, so `make check` fails partway through an ordinary change. `gofmt -l .` on `next` passed in this case. Acceptable: fmt-check skips listed files that no longer exist.
Model: opus-5-5
The Makefile and script/precommit now add .tool/go/bin to PATH, as script/fmt and script/fmt-check already do. The bootstrap comment and the README name those four, and README.md says script/install-go puts Go on PATH only on a CI runner.
script/install-go carries the darwin-amd64 and darwin-arm64 sha256 values go.dev publishes for 1.26.1 and picks the checksum by OS and architecture. Its comment and error message no longer name the release runner, and the macOS disclosure is gone from the PR body.
script/fmt-check skips listed files that are missing from the working tree.
Model: opus-5-5
Rework:
1. The `Makefile` and `script/precommit` now add `.tool/go/bin` to `PATH`, as `script/fmt` and `script/fmt-check` already do. The bootstrap comment and the README name those four, and `README.md` says `script/install-go` puts Go on `PATH` only on a CI runner.
2. `script/install-go` carries the darwin-amd64 and darwin-arm64 sha256 values go.dev publishes for 1.26.1 and picks the checksum by OS and architecture. Its comment and error message no longer name the release runner, and the macOS disclosure is gone from the PR body.
3. `script/fmt-check` skips listed files that are missing from the working tree.
Model: opus-5-5
script/fmt-check:16-22: when git ls-files fails, as in a tree without .git such as a source export, the loop collects no files and gofmt -l runs with no arguments, so it reads standard input: at a terminal it waits forever, and otherwise it passes having checked nothing. On next, gofmt -l . catches an unformatted file in the same tree. Acceptable: fmt-check stops with an error when git ls-files fails, and never runs gofmt without file arguments.
Dockerfile:56-57: the commit and its date now come only from git inside the build, and || echo unknown hides a failure there. When .git is a file pointing outside the build context (a linked worktree or a submodule checkout), script/docker and script/cibuild pass the version from the host, the .git check passes, and the image reports commit: unknown and an unknown date with no error. On next the host passed both. Acceptable: with .git present, a commit or date that comes out unknown fails the build, as an empty, dev or unknown version does.
The branch no longer rebases onto current next: TODO.md conflicts with the entry for #220. Acceptable: rebased, with this entry above that one.
Model: opus-5-5
1. `script/fmt-check:16-22`: when `git ls-files` fails, as in a tree without `.git` such as a source export, the loop collects no files and `gofmt -l` runs with no arguments, so it reads standard input: at a terminal it waits forever, and otherwise it passes having checked nothing. On `next`, `gofmt -l .` catches an unformatted file in the same tree. Acceptable: fmt-check stops with an error when `git ls-files` fails, and never runs `gofmt` without file arguments.
2. `Dockerfile:56-57`: the commit and its date now come only from git inside the build, and `|| echo unknown` hides a failure there. When `.git` is a file pointing outside the build context (a linked worktree or a submodule checkout), `script/docker` and `script/cibuild` pass the version from the host, the `.git` check passes, and the image reports `commit: unknown` and an unknown date with no error. On `next` the host passed both. Acceptable: with `.git` present, a commit or date that comes out `unknown` fails the build, as an empty, `dev` or `unknown` version does.
3. The branch no longer rebases onto current `next`: `TODO.md` conflicts with the entry for https://git.eeqj.de/sneak/vaultik/issues/220. Acceptable: rebased, with this entry above that one.
Model: opus-5-5
script/fmt-check stops with an error when git ls-files fails, and exits without running gofmt when no Go file is listed. The README says it fails outside a git checkout.
With .git present, the build stage fails when the commit or its date comes out unknown, as it already did for an empty, dev or unknown version. The Dockerfile comment, the README and the Dockerfile test now cover this.
Rebased onto current next. In TODO.md this entry is now above the #220 entry and the #216 entry, which landed during this rework.
Model: opus-5-5
Rework:
1. `script/fmt-check` stops with an error when `git ls-files` fails, and exits without running `gofmt` when no Go file is listed. The README says it fails outside a git checkout.
2. With `.git` present, the build stage fails when the commit or its date comes out `unknown`, as it already did for an empty, `dev` or `unknown` version. The Dockerfile comment, the README and the Dockerfile test now cover this.
3. Rebased onto current `next`. In `TODO.md` this entry is now above the https://git.eeqj.de/sneak/vaultik/issues/220 entry and the https://git.eeqj.de/sneak/vaultik/issues/216 entry, which landed during this rework.
Model: opus-5-5
script/fmt-check:20-21: the loop splits git's file list on whitespace, and [ -e "$f" ] silently drops any name it cannot find. An unformatted Go file whose name contains a space, or a non-ASCII character (which git prints quoted), never reaches gofmt, and fmt-check passes. gofmt -l . on next reports both. Acceptable: every Go file git lists is passed to gofmt under its real name, and the only files skipped are those deleted from the working tree.
script/release:45-89: goreleaser runs go for its before-hook and its builds, but script/release does not add .tool/go/bin to its PATH. On a host where script/bootstrap installed Go into .tool/go, script/release-snapshot and script/release therefore stop with go not found; only make release-snapshot works, because the Makefile exports that PATH. On next, bootstrap put Go on PATH and both scripts worked. This part of the first finding of #236 (comment) is still open. Acceptable: script/release adds .tool/go/bin to its PATH, as script/fmt, script/fmt-check and script/precommit do, and the comment at script/bootstrap:107-110 and README.md:767-769 name it.
Model: opus-5-5
1. `script/fmt-check:20-21`: the loop splits git's file list on whitespace, and `[ -e "$f" ]` silently drops any name it cannot find. An unformatted Go file whose name contains a space, or a non-ASCII character (which git prints quoted), never reaches `gofmt`, and fmt-check passes. `gofmt -l .` on `next` reports both. Acceptable: every Go file git lists is passed to `gofmt` under its real name, and the only files skipped are those deleted from the working tree.
2. `script/release:45-89`: goreleaser runs `go` for its before-hook and its builds, but `script/release` does not add `.tool/go/bin` to its `PATH`. On a host where `script/bootstrap` installed Go into `.tool/go`, `script/release-snapshot` and `script/release` therefore stop with `go` not found; only `make release-snapshot` works, because the `Makefile` exports that `PATH`. On `next`, bootstrap put Go on `PATH` and both scripts worked. This part of the first finding of https://git.eeqj.de/sneak/vaultik/pulls/236#issuecomment-128562 is still open. Acceptable: `script/release` adds `.tool/go/bin` to its `PATH`, as `script/fmt`, `script/fmt-check` and `script/precommit` do, and the comment at `script/bootstrap:107-110` and `README.md:767-769` name it.
Model: opus-5-5
Linting and testing become the lint and test phases of the Dockerfile,
and the build stage depends on both. Dockerfile.lint, CHECK_EPOCH and
the tests that checked them are removed. Every docker build in script/
passes --no-cache, and script/cibuild runs script/bootstrap first. A
host without Go gets the go.mod version from script/install-go in
.tool/go, which bootstrap, the Makefile, fmt, fmt-check, precommit and
release add to PATH; fmt-check skips .tool. The image takes its version
from the VERSION build arg or git describe, dev without .git. This
repo's own entries follow the canonical content in .gitignore and
.editorconfig. The golangci-lint v2.14.0 findings are fixed. The rules
in CLAUDE.md move into AGENTS.md. IsDevVersion counts "unknown".
Model: opus-5-5
script/fmt-check no longer lists files through git or loops over them: it runs gofmt -l through find on every Go file outside .tool, so names with spaces or non-ASCII characters reach gofmt intact, and it fails when gofmt prints a file or fails.
script/release adds .tool/go/bin to its PATH, and script/release-snapshot runs it. The comment in script/bootstrap and README.md now name exactly the places that add it: script/bootstrap, the Makefile, script/fmt, script/fmt-check, script/precommit and script/release. script/install-go runs its own Go by full path and script/install-goreleaser only asks goreleaser for its version, so neither needs it.
Rebased onto next after #242; in TODO.md this entry goes above that one.
Model: opus-5-5
Rework:
1. `script/fmt-check` no longer lists files through git or loops over them: it runs `gofmt -l` through `find` on every Go file outside `.tool`, so names with spaces or non-ASCII characters reach `gofmt` intact, and it fails when `gofmt` prints a file or fails.
2. `script/release` adds `.tool/go/bin` to its `PATH`, and `script/release-snapshot` runs it. The comment in `script/bootstrap` and `README.md` now name exactly the places that add it: `script/bootstrap`, the `Makefile`, `script/fmt`, `script/fmt-check`, `script/precommit` and `script/release`. `script/install-go` runs its own Go by full path and `script/install-goreleaser` only asks goreleaser for its version, so neither needs it.
Rebased onto `next` after https://git.eeqj.de/sneak/vaultik/pulls/242; in `TODO.md` this entry goes above that one.
Model: opus-5-5
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.
Closes #213, following the plan in #213 (comment).
What changed
.dockerignore,.editorconfig,.gitea/workflows/check.yml,.gitignore,.golangci.ymlandREPO_POLICIES.mdare fetched fromdd4027b. This repo's own entries follow the canonical content in.golangci.yml,.dockerignore,.gitignoreand.editorconfig.lintandtestphases of theDockerfile(golangci-lint v2.14.0; the Debian Go image for-race), and the build stage depends on both.Dockerfile.lint,CHECK_EPOCHandcmd/vaultik/lintdocker_test.goare deleted.script/lint,test,check,dockerandcibuildare the canonical copies;script/lint-fixreads its image from thelintphase.VERSIONthe policy's way and still stamps the commit and its date from.git.CLAUDE.mdare now inAGENTS.md.What a reader would trip over
script/cibuildbootstraps a host Go forgofmt. The runner has none, soscript/bootstrapinstalls thego.modversion into.tool/go, which it, theMakefile,script/fmt,script/fmt-check,script/precommitandscript/releaseadd to theirPATH.script/fmt-checkskips.tool, whose Go sourcesgofmt -l .would check.script/dockerstampsunknownoutside a git checkout, soIsDevVersiontreatsunknownas a development build.Disclosures
lintphase keepsgolangci-lint config verifybeforerun..gitstampsdev; the policy's version step leaves it empty./.toolis carried in.dockerignore.CLAUDE.mdis reworded without naming the tool or its vendor.Model: opus-5-5
.gitignore: the byte-identical canonical copy drops every entry this repo had:/vaultik,/dist/,/.tool/,*.out,*.test, the coverage files,local-config.yamlanddev-config.yaml. Item 3 of #213 requires this repo's Go entries after the canonical content (at least*.log,*.out,*.testand the binary, perCODE_STYLEGUIDE_GO.md).REPO_POLICIES.mdrequires credential files to be ignored, and the two local configs hold S3 keys. The change also breaks the tag release:.gitea/workflows/release.ymlinstalls Go and goreleaser into.tool/beforescript/release, and goreleaser then refuses to run because the untracked.tool/makes the tree dirty. Acceptable: the canonical content unchanged, followed by this repo's entries, and the disclosure accepting this consequence removed. That also makes README.md:913 ("./dist, which is gitignored") true again..editorconfig: there is no[*.go]section withindent_style = tabafter the canonical content, which item 3 of the issue requires.dev" is false for adocker buildof a tree without.git. The build stage now stamps an empty version, so the binary printsvaultikwith nothing after it, wherenextstampeddev. Acceptable: fall back todevwhen the context has no.git(the[ -e .git ]check still rejectsdevwhen.gitis present), or have the README state the empty version..gitea/workflows/release.yml:19-21saysscript/cibuild"does all of its work inside the digest-pinned Dockerfile images" and that nothing else puts Go on the runner.script/cibuildnow runsscript/bootstrap, which installs Go from the package manager and runsgo mod downloadon the runner, andscript/fmt-checkrunsgofmtthere.script/install-go:10-12also namesgofmtas the only host use of Go and leaves out thatgo mod download. Acceptable: both comments say what the check workflow now does on the runner.AGENTS.mdends with a blank line after rule 18. Acceptable: a single trailing newline.Model: opus-5-5
6dc134a50etodcf5f7555bRework:
.gitignore:*.log,*.out,*.test,coverage.html,/vaultik,/dist/,/.tool/,local-config.yamlanddev-config.yamlnow follow the canonical content; the disclosure is removed..editorconfig: a[*.go]section withindent_style = tabfollows the canonical content.git describe --tags --always || echo dev, so a context without.gitstampsdevand the README line holds; with.gitpresentdevis still rejected. The Dockerfile test asserts the fallback, and the PR body discloses it as a deviation.script/bootstrapputs Go on the check runner forgo mod downloadandgofmt, and that compiling happens only inside the Dockerfile images.AGENTS.mdends with a single newline.Rebased onto
nextafter #234; inTODO.mdthis entry goes above that one.Model: opus-5-5
script/bootstrap:113: when the host has no Go, which is always the case on the CI runner, bootstrap installs whatever Go the package manager carries (1.22 on the current runner, againstgo 1.26.1ingo.mod), andscript/cibuildthen runs that toolchain'sgofmtinscript/fmt-check.REPO_POLICIES.mdatdd4027brequires bootstrap to install exact versions, never the latest. This PR makes the CI gate depend on that install and records the unpinned version in.gitea/workflows/release.yml:21-24andscript/install-go:10-14instead of fixing it. Acceptable: when Go is missing, bootstrap installs thego.modversion throughscript/install-go(already hash-verified and version-compared),script/fmt-checkuses that toolchain'sgofmt, and the two comments say so.internal/globals/globals.go:79: the new"unknown"is a bare string that already appears twice in the same file, as theCommitandCommitDatedefaults (lines 25 and 28). Rule 10 ofAGENTS.mdrequires a named constant. Acceptable: one constant used in all three places, asDevVersionis for"dev".Model: opus-5-5
dcf5f7555btod98b1a55dbRework:
go.modversion fromscript/install-goin.tool/go, wherescript/fmtandscript/fmt-checkalso look;.gitea/workflows/release.yml,script/install-goand the README say so.script/fmt-checknow reads the Go files git lists, becausegofmt -l .walked that toolchain's sources and failed. Theapt-get updateadded for the package-manager Go is removed. A macOS host without Go now stops inscript/install-go, disclosed in the PR body.Unknownreplaces the three bare strings ininternal/globals/globals.go.Rebased onto
nextafter #237; inTODO.mdthis entry goes above that one.Model: opus-5-5
script/bootstrap:107-113: on a host without Go, bootstrap installs Go into.tool/go, but onlyscript/fmtandscript/fmt-checklook there.script/precommit:12, which the hook fromscript/setupruns, fails on every commit becausegois not on itsPATH, and theMakefile'sbuild,deps,cleanandtest-coveragefail the same way. Onnext, bootstrap put the package manager's Go onPATH.README.md:785saysscript/install-goputs Go onPATH, which is true only on a CI runner. Acceptable: every host command that runsgoafter bootstrap finds.tool/go/bin, and the bootstrap comment and the README say so.script/install-go:104-106: bootstrap now calls this on any host without Go, but it carries Linux checksums only, so a macOS host without Go stops there as an unsupported OS. Onnext, bootstrap installed Go through brew, andscript/install-goreleaseralready carries darwin checksums.REPO_POLICIES.mdrequires bootstrap to install every dependency on a host with nothing present, brew hosts included, so the disclosure does not cover this. Acceptable:script/install-gocarries the darwin-amd64 and darwin-arm64 checksums go.dev publishes, its comment and error message no longer name only the release runner, and the disclosure is removed.script/fmt-check:14-16:git ls-files --cachedstill lists a tracked Go file that has been deleted from the working tree when the deletion is not staged yet.gofmtthen fails because the file does not exist, somake checkfails partway through an ordinary change.gofmt -l .onnextpassed in this case. Acceptable: fmt-check skips listed files that no longer exist.Model: opus-5-5
d98b1a55dbto376b76860eRework:
Makefileandscript/precommitnow add.tool/go/bintoPATH, asscript/fmtandscript/fmt-checkalready do. The bootstrap comment and the README name those four, andREADME.mdsaysscript/install-goputs Go onPATHonly on a CI runner.script/install-gocarries the darwin-amd64 and darwin-arm64 sha256 values go.dev publishes for 1.26.1 and picks the checksum by OS and architecture. Its comment and error message no longer name the release runner, and the macOS disclosure is gone from the PR body.script/fmt-checkskips listed files that are missing from the working tree.Model: opus-5-5
script/fmt-check:16-22: whengit ls-filesfails, as in a tree without.gitsuch as a source export, the loop collects no files andgofmt -lruns with no arguments, so it reads standard input: at a terminal it waits forever, and otherwise it passes having checked nothing. Onnext,gofmt -l .catches an unformatted file in the same tree. Acceptable: fmt-check stops with an error whengit ls-filesfails, and never runsgofmtwithout file arguments.Dockerfile:56-57: the commit and its date now come only from git inside the build, and|| echo unknownhides a failure there. When.gitis a file pointing outside the build context (a linked worktree or a submodule checkout),script/dockerandscript/cibuildpass the version from the host, the.gitcheck passes, and the image reportscommit: unknownand an unknown date with no error. Onnextthe host passed both. Acceptable: with.gitpresent, a commit or date that comes outunknownfails the build, as an empty,devorunknownversion does.next:TODO.mdconflicts with the entry for #220. Acceptable: rebased, with this entry above that one.Model: opus-5-5
376b76860etofc6a392ccdfc6a392ccdto94c577e22aRework:
script/fmt-checkstops with an error whengit ls-filesfails, and exits without runninggofmtwhen no Go file is listed. The README says it fails outside a git checkout..gitpresent, the build stage fails when the commit or its date comes outunknown, as it already did for an empty,devorunknownversion. The Dockerfile comment, the README and the Dockerfile test now cover this.next. InTODO.mdthis entry is now above the #220 entry and the #216 entry, which landed during this rework.Model: opus-5-5
script/fmt-check:20-21: the loop splits git's file list on whitespace, and[ -e "$f" ]silently drops any name it cannot find. An unformatted Go file whose name contains a space, or a non-ASCII character (which git prints quoted), never reachesgofmt, and fmt-check passes.gofmt -l .onnextreports both. Acceptable: every Go file git lists is passed togofmtunder its real name, and the only files skipped are those deleted from the working tree.script/release:45-89: goreleaser runsgofor its before-hook and its builds, butscript/releasedoes not add.tool/go/binto itsPATH. On a host wherescript/bootstrapinstalled Go into.tool/go,script/release-snapshotandscript/releasetherefore stop withgonot found; onlymake release-snapshotworks, because theMakefileexports thatPATH. Onnext, bootstrap put Go onPATHand both scripts worked. This part of the first finding of #236 (comment) is still open. Acceptable:script/releaseadds.tool/go/binto itsPATH, asscript/fmt,script/fmt-checkandscript/precommitdo, and the comment atscript/bootstrap:107-110andREADME.md:767-769name it.Model: opus-5-5
94c577e22ato53926fbea5Rework:
script/fmt-checkno longer lists files through git or loops over them: it runsgofmt -lthroughfindon every Go file outside.tool, so names with spaces or non-ASCII characters reachgofmtintact, and it fails whengofmtprints a file or fails.script/releaseadds.tool/go/binto itsPATH, andscript/release-snapshotruns it. The comment inscript/bootstrapandREADME.mdnow name exactly the places that add it:script/bootstrap, theMakefile,script/fmt,script/fmt-check,script/precommitandscript/release.script/install-goruns its own Go by full path andscript/install-goreleaseronly asks goreleaser for its version, so neither needs it.Rebased onto
nextafter #242; inTODO.mdthis entry goes above that one.Model: opus-5-5
Review passed.
Model: opus-5-5