make test cap to 60s, backstop timeout to 90s (#42)
## The question this answers Is the 60-second test-time cap the new **org-wide** ceiling, or an approved **dnswatcher-only** divergence? - Question: #41 - Origin: sneak/dnswatcher#93 This PR implements **org-wide**. ## The ruling On sneak/dnswatcher#93 (comment) (2026-08-09), verbatim: > make the cap 60s in both and never use mocking, always use live resolvers and > assume the build and run environments have full unmodified unrestricted > internet access. it is ok if they fail due to a bad build environment that > alters dns packets. And on #41 (comment), disambiguating the scope: > org wide. the hard cap is 60 for ci/green, but over 20s should be filed as an > improvement bug. That second comment landed after this work was started, and it confirms the option implemented here. The two-tier shape it describes (60s hard, 20s target, overage filed as a bug) is encoded in the policy text. ## What changed, and the number chosen The backstop moves from `30s` to **`90s`**. The old pairing was incoherent under the new cap: a 60-second ceiling with a 30-second `-timeout` means the timeout kills the suite long before the ceiling is reached, so the ceiling would never be the thing that fails. The backstop has to sit above the cap, where it does its actual job of catching a hung test rather than a merely slow one. `90s` preserves the 1.5x backstop-to-cap ratio the old `20s`/`30s` pair already had, so the relationship between the two numbers is unchanged and only the scale moves. Every place a number changed: | File | What | | --- | --- | | `prompts/REPO_POLICIES.md` | Prose ceiling: `20 seconds` to `60 seconds`, plus the new 20s target / improvement-bug tier | | `prompts/REPO_POLICIES.md` | Backstop prose: `30-second timeout` to `90-second timeout`, with the rationale for why it exceeds the cap | | `prompts/REPO_POLICIES.md` | Go example Makefile snippet, first run: `go test -timeout 30s` to `-timeout 90s` | | `prompts/REPO_POLICIES.md` | Go example Makefile snippet, verbose rerun: `go test -timeout 30s` to `-timeout 90s` | | `prompts/EXISTING_REPO_CHECKLIST.md` | `make test` has a `30-second` timeout, to `90-second` timeout plus the 60s hard cap and the 20s filing rule | | `prompts/NEW_REPO_CHECKLIST.md` | `script/test` / `make test` entrypoint line: `30-second timeout` to `90-second timeout, 60-second hard cap on wall time` | I swept the whole repo for `20 second`, `30-second`, `20s`, `30s`, `timeout 20`, `timeout 30`, and `under 20`/`under 30`. After this change the only remaining occurrences of `20` in a test-timing context are the two intentional references to the new 20-second target. The other `timeout` hits in the repo are unrelated (`.golangci.yml` lint timeout, HTTP server `ReadTimeout`/`WriteTimeout` examples, `middleware.Timeout`) and were left alone. One deliberate non-change: the Python example Makefile snippet in `prompts/REPO_POLICIES.md` carries no timeout flag today and still carries none. `pytest` has no built-in timeout, so adding one would mean mandating the `pytest-timeout` plugin org-wide, which is a new dependency requirement rather than a renumbering, and outside what was ruled on. It is a pre-existing gap between the prose and that snippet, not one this PR introduces. Happy to file it separately or add `--timeout=90` here if you want it in scope. ## The alternative that was not implemented **Keep canonical at 20s and let `sneak/dnswatcher` carry a documented per-repo divergence.** That was the recommendation originally written up in #41, on the reasoning that the 20s ceiling is doing real work in repos with fast deterministic suites and only dnswatcher needs the headroom. Org-wide was chosen instead for two reasons. First, the pressure is not specific to DNS: any repo whose tests exercise real infrastructure over the network inherits the same variance, and there is no principled line that admits dnswatcher and excludes the next such repo. Second, and more decisively, `REPO_POLICIES.md` is a vendored file. A sanctioned per-repo divergence in a vendored file is indistinguishable, on inspection, from a stale vendored copy: the next re-vendoring silently reverts the divergence, and nobody reading a consuming repo can tell whether the number they are looking at is an intentional exception or drift. That is the bidirectional-drift problem already tracked in #31. The two-tier cap gets the same outcome without the drift, since a fast repo that regresses from 4s to 45s still generates an improvement bug. ## Status This PR was opened speculatively, ahead of a decision, on the standing "open it rather than wait" instruction. The scope question has since been answered org-wide in the issue, but the specific backstop value of `90s` and the two-tier wording are still my proposals rather than anything ruled on, so closing this or sending it back for a different number is a perfectly fine outcome. `make check` passes; `make fmt` was run and the result is included (it was a no-op, the edits were already prettier-conformant). `sneak/dnswatcher` is landing the matching 60s edit to its vendored copy in parallel, and will match whichever way this is decided. Co-authored-by: clawbot <clawbot@eeqj.de> Reviewed-on: #42 Co-authored-by: clawbot <clawbot@noreply.example.org> Co-committed-by: clawbot <clawbot@noreply.example.org>
prompts
prompts is an MIT-licensed collection of LLM prompts by @sneak, including development policy prompts and other useful prompts for working with large language models.
Quick Start
Existing Repo
Run from within the repo you want to bring up to standards. Clone the prompts repo once, then run both commands in order.
export TD="$(mktemp -d)"
git clone --depth 1 https://git.eeqj.de/sneak/prompts.git "$TD"
Repository structure and policies:
claude "Read $TD/prompts/REPO_POLICIES.md and
$TD/prompts/EXISTING_REPO_CHECKLIST.md, then bring this repo up to those
standards. Your scope is repo scaffolding and policy compliance:
Makefile, Dockerfile, .dockerignore, .gitignore, .editorconfig, CI
workflow, README sections, LICENSE, REPO_POLICIES.md, and any
language-specific config files (.golangci.yml, .prettierrc, etc.).
You must also run the formatter (make fmt) and fix any linter errors
(make lint) so that make check passes — this will touch source code,
but do not restructure, refactor, or rewrite any application logic.
Follow the policies yourself: work on a feature branch, never git add -A,
and make each logical change a separate commit (e.g. one commit for
formatting, one for linter fixes, one for README updates, one for each
new repo file added, etc.)."
Code style and conventions:
claude "Read $TD/prompts/CODE_STYLEGUIDE.md and whichever
language-specific styleguides in $TD/prompts/ apply to this repo
(CODE_STYLEGUIDE_GO.md, CODE_STYLEGUIDE_JS.md, CODE_STYLEGUIDE_PYTHON.md,
GO_HTTP_SERVER_CONVENTIONS.md). Then review the application code in this
repo and bring it into compliance with those coding standards. Your scope
is application code structure and style: naming, patterns, error
handling, project layout, and conventions described in the styleguides.
Do not modify repo scaffolding (Makefile, Dockerfile, CI workflow,
.gitignore, .editorconfig, etc.) — only application code. Work on a
feature branch, never git add -A, and make each logical change a
separate commit."
New Repo
Run from inside the directory where you want to create a new repo. Clone the prompts repo once, then run both commands in order.
export TD="$(mktemp -d)"
git clone --depth 1 https://git.eeqj.de/sneak/prompts.git "$TD"
Repository scaffolding:
claude "Read $TD/prompts/REPO_POLICIES.md and
$TD/prompts/NEW_REPO_CHECKLIST.md, then set up this new repo according
to those standards. Your scope is repo structure and required files:
README.md, LICENSE, REPO_POLICIES.md, Makefile, Dockerfile, .dockerignore,
.gitignore, .editorconfig, CI workflow, and language-specific config.
Run the formatter (make fmt) and fix any linter errors (make lint) so
that make check passes — this will touch source code, but do not
restructure, refactor, or rewrite any application logic. Follow the
policies yourself: work on a feature branch, never git add -A, and make
each logical change a separate commit (e.g. one commit for formatting,
one for linter fixes, one for README, one for each new repo file, etc.)."
Code style and conventions:
claude "Read $TD/prompts/CODE_STYLEGUIDE.md and whichever
language-specific styleguides in $TD/prompts/ apply to this repo
(CODE_STYLEGUIDE_GO.md, CODE_STYLEGUIDE_JS.md, CODE_STYLEGUIDE_PYTHON.md,
GO_HTTP_SERVER_CONVENTIONS.md). Then review the application code in this
repo and bring it into compliance with those coding standards. Your scope
is application code structure and style: naming, patterns, error
handling, project layout, and conventions described in the styleguides.
Do not modify repo scaffolding (Makefile, Dockerfile, CI workflow,
.gitignore, .editorconfig, etc.) — only application code. Work on a
feature branch, never git add -A, and make each logical change a
separate commit."
Getting Started
git clone https://git.eeqj.de/sneak/prompts.git
cd prompts
Prompts are stored as Markdown files in prompts/. Copy or reference them as
needed in your projects.
Entrypoints
This repository adheres to the
Scripts to Rule Them All
standard: normalized scripts in script/ are the entrypoints for the
development workflow, and the Makefile targets are thin shims that call them.
The scripts are POSIX sh (not bash) so they run in minimal containers such as
alpine. We provide:
script/bootstrap— install all dependencies (yarn install)script/setup— set up the repo for development after a fresh clone: runsscript/bootstrap, thenscript/install-precommitscript/projectname— output the project name (our own extension); used byscript/dockerfor the image tagscript/test— run the test suite (no tests defined here)script/lint— lint the markdown files with prettierscript/fmt— format all markdown files with prettier (writes)script/fmt-check— check formatting (read-only)script/check— run all checks:test,lint,fmt-check(our own extension)script/docker— build the Docker image, tagged viascript/projectname(byte-identical across repos)script/cibuild— cd to the repo root anddocker build .(what CI runs; the image build runsscript/check)script/precommit— run by the git pre-commit hook (our own extension); callsscript/checkscript/install-precommit— installs the git pre-commit hook (our own extension);make hooksshims to it
make hooks installs the pre-commit hook that runs script/precommit.
Rationale
LLM prompts, especially development policies, benefit from version control and a single authoritative source. This repo provides a central place to maintain, share, and evolve prompts across projects.
Design
The repository is a collection of Markdown files organized in the prompts/
subdirectory. Each file contains one or more related prompts or policy
documents. There is no build step or runtime component; the prompts are consumed
by copying them into other projects or referencing them directly.
Template Repos
These template repositories implement the policies defined in this repo and serve as starting points for new projects. They must be kept in sync when policies change.
- template-app-go — Go HTTP server template (Uber fx, chi, SQLite, session auth, Prometheus metrics)
- template-app-js — JavaScript SPA template (Vite, Tailwind CSS v4, nginx Docker deployment)
- template-app-python — Python web application template (FastAPI, uvicorn, pytest, black, ruff)
When updating policies in this repo, also update the template repos to match (Makefile targets, Dockerfile conventions, CI workflows, required files, etc.).
See Also
- clawpub — Real-world examples, rationale, and operational lessons from applying these policies with an OpenClaw AI agent. Includes detailed documentation on how the interlocking check system (CI → Docker → Makefile → tests/lint/fmt) works in practice, why checklists complement prose policies, and failure stories from production use.
TODO
- Add more prompt templates for common development tasks
License
MIT. See LICENSE.