From f7bae92768afa9dd96dcddd07a892707b830f00e Mon Sep 17 00:00:00 2001 From: sneak Date: Sun, 4 Oct 2026 19:45:31 +0000 Subject: [PATCH] Bring every copied template file to sneak/prompts next at dd4027b9 (closes #67) REPO_POLICIES.md is the sneak/prompts next copy at commit dd4027b907ef99cdc3187c215cc4d610b7a11efc. .gitignore and .dockerignore are that commit's copies plus keyfunc's own /keyfunc entry: both now ignore id_ecdsa_sk and id_ed25519_sk, the private key files ssh-keygen writes for hardware-backed keys, and .dockerignore keeps out a .git/config at any depth. The other copied files already matched that commit. The template Dockerfile, scripts, Makefile and workflow have not changed since keyfunc adapted them, and the new policy text asks nothing new of keyfunc's Dockerfile: its gate phases install nothing and its last stage already runs script/bootstrap. Model: opus-5-5 --- .dockerignore | 15 ++++++++++--- .gitignore | 2 ++ REPO_POLICIES.md | 56 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/.dockerignore b/.dockerignore index 946c6c5..1d67707 100644 --- a/.dockerignore +++ b/.dockerignore @@ -18,9 +18,16 @@ # does not need .git/config; that file can hold a credential, such as a # password in a remote URL or the token the CI checkout step stores there. # Each submodule keeps a config with the same exposure in its git directory -# under .git/modules/, nested again for a submodule's own submodules. -.git/config -.git/modules/**/config +# under .git/modules/, nested again for a submodule's own submodules, or in +# its own .git directory when it keeps one. +# KNOWN GAP: a submodule whose name has a `config` segment (`config`, +# `deploy/config`, `config/lib`) loses its whole git directory, because +# `**/.git/modules/**/config` also matches that segment's directory +# under .git/modules/. Go's version stamping then fails the build; +# nothing leaks. Name such a submodule without that segment: +# `git submodule add --name`. +**/.git/config +**/.git/modules/**/config # Agent scratch: one full checkout of the repo per in-flight agent. # Anchored because it occurs once where agents run at the repo root. @@ -44,7 +51,9 @@ **/[iI][dD]_[rR][sS][aA] **/[iI][dD]_[dD][sS][aA] **/[iI][dD]_[eE][cC][dD][sS][aA] +**/[iI][dD]_[eE][cC][dD][sS][aA]_[sS][kK] **/[iI][dD]_[eE][dD]25519 +**/[iI][dD]_[eE][dD]25519_[sS][kK] # Dependencies: restored inside the image, never copied in. **/node_modules diff --git a/.gitignore b/.gitignore index 0d0698d..e078f30 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,9 @@ node_modules/ [iI][dD]_[rR][sS][aA] [iI][dD]_[dD][sS][aA] [iI][dD]_[eE][cC][dD][sS][aA] +[iI][dD]_[eE][cC][dD][sS][aA]_[sS][kK] [iI][dD]_[eE][dD]25519 +[iI][dD]_[eE][dD]25519_[sS][kK] # The binary `make build` writes. /keyfunc diff --git a/REPO_POLICIES.md b/REPO_POLICIES.md index af0ea80..20382d1 100644 --- a/REPO_POLICIES.md +++ b/REPO_POLICIES.md @@ -104,10 +104,14 @@ style conventions are in separate documents: `lint` phase and a `test` phase, with the final stage depending on both so the image cannot be built unless they pass. For non-server repos the final stage brings up a development environment; for server repos it is the runtime image. - Dockerfiles install development prerequisites by running `script/bootstrap` - rather than duplicating installs inline; COPY `script/` and the dependency - manifests (`package.json` + `yarn.lock`, `go.mod` + `go.sum`, etc.) before - running it. + The gate phases and the build stage start from their pinned base images and + install what those images lack either inline, as the canonical Go `Dockerfile` + below does for `git`, or by running `script/bootstrap`, as the `prompts` + repo's own `Dockerfile` does for its yarn packages. The development + environment stage installs development prerequisites by running + `script/bootstrap` rather than duplicating its installs inline. A stage that + runs `script/bootstrap` COPYs `script/` and the dependency manifests + (`package.json` + `yarn.lock`, `go.mod` + `go.sum`, etc.) before running it. - **Linting and testing run in Docker, as phases of the `Dockerfile`.** There is no separate lint file. `script/lint` and `script/test` each build one phase @@ -156,6 +160,9 @@ style conventions are in separate documents: not evidence that anything ran: a sub-second build reporting success is a cache hit, not a result. Never invalidate by pruning — `docker builder prune` and friends destroy a build cache shared with every other build on the host. + When a check is added or changed, prove it works by planting a defect it must + catch and watching the run fail on it, then revert the defect. A green run + alone shows neither that the check ran nor that it covers what it should. - **The gate phases are separate stages, and the build stage depends on both.** The lint phase is based on the `golangci/golangci-lint` image (pinned by @@ -236,13 +243,28 @@ style conventions are in separate documents: (e.g. a web frontend compiled in a separate stage), the lint phase must create placeholder files so the embed directives resolve. Example: `RUN mkdir -p web/dist && touch web/dist/index.html web/dist/style.css`. - - If the project requires CGO or system libraries for linting (e.g. - `vips-dev`), install them in the lint phase with `apk add`. - - `.dockerignore` lets `.git` into the build context. It keeps out - `.git/config` and each submodule's `config` under `.git/modules/` at any - depth (`.git/modules/**/config`), which `git describe` does not need and - which can hold a credential: a password in a remote URL, or the token the - CI checkout step stores there. The stage that compiles has `git` (the + - If the project requires CGO or system libraries for linting, install them + in the lint phase. The `golangci/golangci-lint` image is Debian-based and + has no `apk`, so install with `apt-get` under the Debian package name + (`libvips-dev`, where alpine says `vips-dev`), and delete the package + lists in the same `RUN`, so the layer does not keep them: + + ```dockerfile + RUN apt-get update \ + && apt-get install -y --no-install-recommends libvips-dev \ + && rm -rf /var/lib/apt/lists/* + ``` + + - `.dockerignore` lets `.git` into the build context. It keeps out every git + `config` at any depth (`**/.git/config`, `**/.git/modules/**/config`): the + repository's own, each submodule's under `.git/modules/`, and that of a + submodule keeping its own `.git` directory. `git describe` does not need + them, and each can hold a credential: a password in a remote URL, or the + token the CI checkout step stores there. A submodule whose name has a + `config` segment (`config`, `deploy/config`, `config/lib`) loses its whole + git directory to `**/.git/modules/**/config`, and Go's version stamping + then fails the build: give it a name without that segment + (`git submodule add --name`). The stage that compiles has `git` (the Debian Go image has it; an alpine one needs `apk add --no-cache git`) and takes the version from the `VERSION` build argument when one is given, otherwise from `git describe --tags --always`. That gives the tag on a @@ -264,7 +286,12 @@ style conventions are in separate documents: carry the same guarantee, because its gate phases may come from the cache. The image build is uncached and so runs the gate phases a second time. That is the price of the rule above, and it is worth paying: the image that ships is built - from a run of its own gates rather than from a cache entry. + from a run of its own gates rather than from a cache entry. A separate + workflow limited to `main` by a `branches` list under `on: push` cannot be + checked by review: to try a change to it, add the feature branch to that list + and push, then remove the branch from the list again before merging. Keep any + job in it that publishes behind `if: github.ref_name == 'main'`, so the run + from the feature branch publishes nothing. - Use platform-standard formatters: `black` for Python, `prettier` for JS/CSS/Markdown/HTML, `go fmt` for Go. Always use default configuration with @@ -495,6 +522,11 @@ style conventions are in separate documents: Keep it POSIX sh: no arrays, no `[[`, no `grep -P`. + A Go tool a repo needs on the host is installed with `go install` pinned to + a commit hash (`go install @`). It is never tracked as + a `go.mod` tool dependency or through a `tools.go` file, either of which + pulls the tool's own dependencies into the repo's `go.mod` and `go.sum`. + - When pinning images or packages by hash, add a comment above the reference with the version and date (YYYY-MM-DD).