All checks were successful
check / check (push) Successful in 23s
Per the owner ruling on issue 40, linting and testing are phases of the main Dockerfile rather than a separate lint file. script/lint and script/test build one phase each by name with caching disabled, and the final stage copies a harmless file from each so the image cannot be built unless both passed — template-app-go's ordering trick, extended to the test phase. A stage that is not the last is built only when something depends on it or --target names it, so the gates are invoked by name and the edges kept. script/check runs the gates and builds no image; script/cibuild bootstraps first, because CI runs it alone and fmt-check is native. Every build in script/ is tagged and uncached. No config verify step. Issue 30 closes too: a container has its own lint cache and lock. Model: opus-5
8.6 KiB
8.6 KiB
title, last_modified
| title | last_modified |
|---|---|
| Existing Repo Checklist | 2026-09-08 |
Use this checklist when beginning work in a repo that may not yet conform to our
repository policies
(https://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md).
Work on a feature branch. Check each item and fix any gaps before proceeding with your task.
Formatting (do this first)
- If the repo has never been formatted to our standards, run
make fmtand commit the result as a standalone branch/commit/PR before any other changes. Formatting diffs can be large and should not be mixed with functional changes.
Required Files
README.mdexists with all required sections (Description, Getting Started, Rationale, Design, TODO, License, Author)LICENSEfile exists and matches the READMEREPO_POLICIES.mdexists and version date is current — fetch fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md.gitignoreis comprehensive (OS, editor, agent scratch, language artifacts, secrets) — fetch fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignoreif missing. An existing repo usually has a hand-written one that is never re-fetched, so check the entries rather than the file's presence..editorconfigexists — fetch fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.editorconfigDockerfileand.dockerignoreexist; the Dockerfile carries alintphase and atestphase, and the final stage carries aCOPY --from=of a harmless file from each — fetch.dockerignorefromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.dockerignore- Nothing has been appended after the final stage, and the gate phases are
reachable from it. A stage nothing depends on is built only when
--targetnames it, so a lostCOPY --from=edge leavesdocker build .passing while the gate never runs. Confirm by planting a violation, not by reading the file. - The gate phases invoke their tools directly, never through
make lintorscript/test— those are themselves adocker buildand would recurse inside a build step - Every depth-independent pattern in
.dockerignorecarries a**/prefix, only genuinely root-anchored entries such as.gitare unprefixed, and.gitignore's patterns have not been transplanted unmodified — the transplanted form leavesconfig/.envandcerts/server.keyin the build context while reading as solved .dockerignoreexcludes the repo's own host-built artifacts (compiled binaries, test binaries, coverage output), written root-anchored —/myapp, never**/myapp. An existing repo is where such a binary is likeliest to already be sitting in the build context, invisible to git..claude/is in.gitignore(unanchored) and.claudein.dockerignore(anchored, no**/prefix). Agent worktrees are entire checkouts of the repo, so they inflate the context by a multiple of it and can copy another session's unreviewed work into an image layer. If agents here run anywhere other than the repo root, the anchored entry missesservices/api/.claude/: add anchored entries for those directories.- If the repo embeds a version in a binary, that version is computed on the
host and passed with
--build-arg VERSION=...byscript/dockerandscript/cibuild, and no stage callsgit describe. A tag-derived version additionally needsfetch-depth: 0on the CI checkout step, which clones shallow and fetches no tags by default. - Gitea Actions workflow in
.gitea/workflows/runsscript/cibuildon push — referencehttps://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml - Language-specific config:
- Go:
go.mod,go.sum,.golangci.yml(fetch fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.golangci.yml) - JS:
package.json,yarn.lock,.prettierrc,.prettierignore(fetch fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.prettierrcandhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.prettierignore) - Python:
pyproject.toml - Docs/writing:
.prettierrc,.prettierignore(same URLs as above)
- Go:
Makefile and script/ Entrypoints
Makefileexists in root — referencehttps://git.eeqj.de/sneak/prompts/raw/branch/main/Makefile- Has targets:
test,lint,fmt,fmt-check,check,docker,hooks - Target implementations live in
script/(scripts-to-rule-them-all); Makefile targets are thin shims calling them — model scripts athttps://git.eeqj.de/sneak/prompts/raw/branch/main/script/<name> script/precommitexists and the pre-commit hook (installed byscript/install-precommit, shimmed bymake hooks) runs it- README has an Entrypoints section documenting the
script/entrypoints and linking the standard script/lintandscript/testbuild their phase by name (docker build --no-cache --target <phase> -t <name>-<phase> .), and no host invocation anywhere in the repo can produce a lint verdict — grep for the linter's own name acrossscript/, theMakefileand CI config, not justscript/lint. A second path is likeliest here: amake lint-fast, an older host-versus-container branch, or a CI step calling the binary directly.script/fmtandscript/fmt-checkare expected hits and stay on the host.- Every
docker buildinscript/is tagged — an untagged one leaves a dangling image behind on every run, on every host and CI runner script/cibuildrunsscript/bootstrapbeforescript/check, and builds the image with--no-cache. Without the bootstrap the CI run dies inscript/fmt-check, which runs the formatter on the host and finds nothing installed.script/bootstrapinstalls no linter of its own — delete the block, its version variables and its call site. A JS repo'syarn installstays; it brings a linter along with every other dependency, and no verdict is taken from it.make checkdoes not modify any files in the repomake testhas a 90-second timeout and completes within the 60-second hard cap (over 20 seconds is green but must be filed as an improvement bug)make testruns real tests, not a no-op (at minimum, import/compile check)make checkpasses on current branch
Formatting
- Platform-standard formatter is configured (
black,prettier,go fmt) - Default formatter config, only exception: four-space indents (except Go)
- All files pass
make fmt-check
Git Hygiene
- Pre-commit hook is installed (
make hooks) - No secrets in the repo (
.env, keys, credentials) - No mutable references in Dockerfiles or scripts (tags,
@latest) — all pinned by cryptographic hash with version/date comment - Using
yarn, notnpm(JS projects)
Directory Structure
- No unnecessary files in repo root
- Files organized into canonical subdirectories (
bin/,cmd/,docs/,internal/,static/, etc.) - Go migrations in
internal/db/migrations/and embedded in binary
HTTP Service Hardening (if targeting 1.0 and the repo is an HTTP/web service)
- Security headers set on all responses (HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy)
- Request body size limits enforced on all endpoints
- Read/write/idle timeouts configured on the HTTP server (slowloris defense)
- Per-handler execution time limits in place
- Password-based auth endpoints are rate-limited
- CSRF tokens on all state-mutating HTML forms
- Passwords hashed with bcrypt, scrypt, or argon2
- Session cookies use HttpOnly, Secure, and SameSite attributes
- True client IP correctly detected behind reverse proxy (trusted proxy allowlist configured)
- CORS restricted to explicit origin allowlist for authenticated endpoints
- Error responses do not leak stack traces, SQL queries, or internal paths
Final
make checkpassesscript/cibuildsucceeds in a fresh clone with nothing installed, which is what CI has, and demonstrably executed the checks — a sub-second build, orCACHEDon a gate layer, means nothing ran- A planted lint violation fails both
make lintand a plaindocker build .; revert it afterwards - Commit and merge fixes before starting your actual task