Rewrite REPO_POLICIES.md sentence by sentence (closes #136)
check / check (push) Successful in 33s

Every sentence of prompts/REPO_POLICIES.md is rewritten against the
sentence rules: one idea per sentence, about 30 words at most, lists as
bulleted lists, subject and verb early, the main rule before any
exception. No rule's meaning changed: nothing is added, removed,
loosened or tightened, every reason stays, and code blocks, digests,
URLs, file names, commands and quoted strings are unchanged. Both repo
checklists carry the same rewrite of the sentences they quote word for
word.

Model: fable-5-1
This commit is contained in:
2026-11-04 01:55:14 +00:00
parent 8400e4cd1f
commit 75c4011a2e
4 changed files with 600 additions and 441 deletions
+7
View File
@@ -21,6 +21,13 @@ fmt-check, and commit.
# Completed Steps
- 2026-11-04: Rewrote `prompts/REPO_POLICIES.md` sentence by sentence
(https://git.eeqj.de/sneak/prompts/issues/136), on sneak's yes at
https://git.eeqj.de/sneak/prompts/issues/136#issuecomment-165193. Every rule
keeps its meaning and its place, and `must` and `should` stay as they were.
Long sentences are split, comma-chained lists are now bulleted lists, and
every reason stays. Code blocks, digests, URLs, file names, commands and
quoted strings are unchanged.
- 2026-11-03: The canonical golangci-lint is now v2.15.0, still built with
go1.27.0, so the `go` directive rule is unchanged (issue 142). Repositories
pick this up on their next re-vendor. Each item in the canonical
+59 -49
View File
@@ -1,6 +1,6 @@
---
title: Existing Repo Checklist
last_modified: 2026-11-03
last_modified: 2026-11-04
---
Use this checklist when beginning work in a repo that may not yet conform to our
@@ -56,14 +56,14 @@ with your task.
- the step that runs `script/bootstrap` to install a Python `test` phase's
packages from `Pipfile.lock`
- [ ] A stage with none of these steps declares `ARG CACHEBUST` right after
`FROM`. A step that installs anything else as well, such as a
`script/bootstrap` that also installs node packages, comes after it too.
The `script/` builds pass a new `CACHEBUST` value on every build, which
reruns every `RUN` step after that line and leaves the layers above it and
the cache mounts in place; `--no-cache` would build those layers again and
empty the mounts. A stage without the `ARG` line is served from cache on
an unchanged tree, so the scripts and the `ARG` lines are re-vendored in
one commit.
`FROM`. A step that also installs anything else comes after
`ARG CACHEBUST` too. A `script/bootstrap` that also installs node packages
is one. The `script/` builds pass a new `CACHEBUST` value on every build,
which reruns every `RUN` step after that line and leaves the layers above
it and the cache mounts in place; `--no-cache` would build those layers
again and empty the mounts. A stage without the `ARG` line is served from
cache on an unchanged tree, so the scripts and the `ARG` lines are
re-vendored in one commit.
- [ ] Go: each Go stage downloads the modules (`COPY go.mod go.sum ./`,
`RUN go mod download`) above `ARG CACHEBUST`; the steps that compile
(`golangci-lint run`, `go test`, `go build`) mount Go's build cache
@@ -76,15 +76,19 @@ with your task.
- [ ] Python: a `test` phase that installs its packages from `Pipfile.lock` does
it above `ARG CACHEBUST`, with `COPY script/ script/`,
`COPY Pipfile Pipfile.lock ./` and `RUN script/bootstrap`. When
`script/bootstrap` runs in that step, it installs nothing beyond system
packages, pipenv and its dependencies, and the packages from
`Pipfile.lock`. It installs pipenv and its dependencies by hash, with
`pip install --require-hashes`. It installs the packages from
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the tests
need the development packages. It installs no Python there, because the
tests use the base image's. The tests run after `ARG CACHEBUST`, and every
other stage installs its Python packages after it, as in the Python `test`
phase example in `REPO_POLICIES.md`
`script/bootstrap` runs in that step, it installs nothing beyond these:
- system packages
- pipenv and its dependencies
- the packages from `Pipfile.lock`
It installs pipenv and its dependencies by hash, with
`pip install --require-hashes`. It installs the packages from `Pipfile.lock`
with `pipenv install --deploy`, plus `--dev` when the tests need the
development packages. It installs no Python there, because the tests use the
base image's. The tests run after `ARG CACHEBUST`, and every other stage
installs its Python packages after it, as in the Python `test` phase example
in `REPO_POLICIES.md`
- [ ] The gate phases invoke their tools directly, never through `make lint` or
`script/test` — those are themselves a `docker build` and would recurse
inside a build step
@@ -105,37 +109,43 @@ with your task.
`services/api/.claude/`: add anchored entries for those directories.
- [ ] If the repo embeds a version in a binary: `.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 tagged commit; on
a later commit, the tag, the number of commits since it and the short
commit (`v1.2.3-4-gabc1234`); and the short commit when no tag is
reachable. The stage that compiles also marks its working directory safe
for git (`git config --system --add safe.directory /src`): a context sent
as a tar stream keeps the sender's file owners, and git refuses a checkout
owned by another user, so the version would come out empty. `ARG VERSION`
has no default, and the build fails if the context carries `.git` and the
version still comes out empty, `dev` or `unknown`. A plain
`docker build .` with no build arguments must succeed; a Dockerfile that
refuses an empty build argument drops that refusal and keeps the argument.
A checkout whose `.git` is a file (a linked worktree, or a repository
checked out as a submodule) is the exception: that file points to a git
directory outside the build context, so the build cannot read the version
and a plain `docker build .` fails; pass the version with
`--build-arg VERSION=...`. `script/docker` and `script/cibuild` already
pass the version they compute on the host; it takes precedence. The
canonical `.gitea/workflows/check.yml` sets `fetch-depth: 0` on its
checkout step, which otherwise clones shallow and fetches no tags, so a CI
build finds the tag too.
(`**/.git/config`, `**/.git/modules/**/config`):
- the repository's own
- each submodule's under `.git/modules/`
- 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.
Some submodule names have a `config` segment, as in `config`,
`deploy/config` or `config/lib`. Such a submodule 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, and an alpine one needs `apk add --no-cache git`. That
stage takes the version from the `VERSION` build argument when one is given,
otherwise from `git describe --tags --always`. That gives:
- the tag, on a tagged commit
- the tag, the number of commits since it and the short commit
(`v1.2.3-4-gabc1234`), on a later commit
- the short commit, when no tag is reachable
The stage that compiles also marks its working directory safe for git
(`git config --system --add safe.directory /src`). A context sent as a tar
stream keeps the sender's file owners, and git refuses a checkout owned by
another user, so the version would come out empty. `ARG VERSION` has no
default. The build fails if the context carries `.git` and the version still
comes out empty, `dev` or `unknown`. A plain `docker build .` with no build
arguments must succeed; a Dockerfile that refuses an empty build argument
drops that refusal and keeps the argument. A checkout whose `.git` is a file
is the exception: a linked worktree, or a repository checked out as a
submodule. That file points to a git directory outside the build context, so
the build cannot read the version and a plain `docker build .` fails. Pass
the version with `--build-arg VERSION=...`. `script/docker` and
`script/cibuild` already pass the version they compute on the host; it takes
precedence. The canonical `.gitea/workflows/check.yml` sets `fetch-depth: 0`
on its checkout step, which otherwise clones shallow and fetches no tags, so
a CI build finds the tag too.
- [ ] Gitea Actions workflow in `.gitea/workflows/` runs `script/cibuild` on
push, checks out with `persist-credentials: false` and with
`fetch-depth: 0` (which fetches the tags `git describe` needs), carries
+59 -46
View File
@@ -1,6 +1,6 @@
---
title: New Repo Checklist
last_modified: 2026-11-03
last_modified: 2026-11-04
---
Use this checklist when creating a new repository from scratch. Follow the steps
@@ -75,34 +75,42 @@ Template files can be fetched from:
anchored entry.
- If the image embeds a version in a binary: `.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 tagged commit; on
a later commit, the tag, the number of commits since it and the short
commit (`v1.2.3-4-gabc1234`); and the short commit when no tag is
reachable. The stage that compiles also marks its working directory safe
for git (`git config --system --add safe.directory /src`): a context sent
as a tar stream keeps the sender's file owners, and git refuses a checkout
owned by another user, so the version would come out empty. `ARG VERSION`
has no default, and the build fails if the context carries `.git` and the
version still comes out empty, `dev` or `unknown`. A plain
`docker build .` with no build arguments must succeed; a Dockerfile that
refuses an empty build argument drops that refusal and keeps the argument.
A checkout whose `.git` is a file (a linked worktree, or a repository
checked out as a submodule) is the exception: that file points to a git
directory outside the build context, so the build cannot read the version
and a plain `docker build .` fails; pass the version with
`--build-arg VERSION=...`, as `script/docker` and `script/cibuild` already
do.
(`**/.git/config`, `**/.git/modules/**/config`):
- the repository's own
- each submodule's under `.git/modules/`
- 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. Some submodule names have a `config` segment, as in `config`,
`deploy/config` or `config/lib`. Such a submodule 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, and an alpine one needs
`apk add --no-cache git`. That stage takes the version from the
`VERSION` build argument when one is given, otherwise from
`git describe --tags --always`. That gives:
- the tag, on a tagged commit
- the tag, the number of commits since it and the short commit
(`v1.2.3-4-gabc1234`), on a later commit
- the short commit, when no tag is reachable
The stage that compiles also marks its working directory safe for git
(`git config --system --add safe.directory /src`). A context sent as a
tar stream keeps the sender's file owners, and git refuses a checkout
owned by another user, so the version would come out empty.
`ARG VERSION` has no default. The build fails if the context carries
`.git` and the version still comes out empty, `dev` or `unknown`. A
plain `docker build .` with no build arguments must succeed; a
Dockerfile that refuses an empty build argument drops that refusal and
keeps the argument. A checkout whose `.git` is a file is the exception:
a linked worktree, or a repository checked out as a submodule. That file
points to a git directory outside the build context, so the build cannot
read the version and a plain `docker build .` fails. Pass the version
with `--build-arg VERSION=...`, as `script/docker` and `script/cibuild`
already do.
- The Dockerfile carries a `lint` phase and a `test` phase, each invoking
its tool directly rather than through `make` or `script/`, and the final
stage carries a `COPY --from=` of a harmless file from each so the image
@@ -115,14 +123,14 @@ Template files can be fetched from:
- the step that runs `script/bootstrap` to install a Python `test`
phase's packages from `Pipfile.lock`
- A stage with none of these steps declares `ARG CACHEBUST` right after
`FROM`. A step that installs anything else as well, such as a
`script/bootstrap` that also installs node packages, comes after it too.
The `script/` builds pass a new `CACHEBUST` value on every build, which
reruns every `RUN` step after that line and leaves the layers above it and
the cache mounts in place; `--no-cache` would build those layers again and
empty the mounts. A stage without the `ARG` line is served from cache on
an unchanged tree, so the scripts and every stage's `ARG CACHEBUST` line
are added in the same commit.
`FROM`. A step that also installs anything else comes after
`ARG CACHEBUST` too. A `script/bootstrap` that also installs node packages
is one. The `script/` builds pass a new `CACHEBUST` value on every build,
which reruns every `RUN` step after that line and leaves the layers above
it and the cache mounts in place; `--no-cache` would build those layers
again and empty the mounts. A stage without the `ARG` line is served from
cache on an unchanged tree, so the scripts and every stage's
`ARG CACHEBUST` line are added in the same commit.
- Go: each Go stage downloads the modules (`COPY go.mod go.sum ./`,
`RUN go mod download`) above `ARG CACHEBUST`; the steps that compile
(`golangci-lint run`, `go test`, `go build`) mount Go's build cache
@@ -135,18 +143,23 @@ Template files can be fetched from:
- Python: a `test` phase that installs its packages from `Pipfile.lock` does
it above `ARG CACHEBUST`, with `COPY script/ script/`,
`COPY Pipfile Pipfile.lock ./` and `RUN script/bootstrap`. When
`script/bootstrap` runs in that step, it installs nothing beyond system
packages, pipenv and its dependencies, and the packages from
`Pipfile.lock`. It installs pipenv and its dependencies by hash, with
`pip install --require-hashes`. It installs the packages from
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the tests
need the development packages. It installs no Python there, because the
tests use the base image's. The tests run after `ARG CACHEBUST`, and every
other stage installs its Python packages after it, as in the Python `test`
phase example in `REPO_POLICIES.md`
`script/bootstrap` runs in that step, it installs nothing beyond these:
- system packages
- pipenv and its dependencies
- the packages from `Pipfile.lock`
It installs pipenv and its dependencies by hash, with
`pip install --require-hashes`. It installs the packages from
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the
tests need the development packages. It installs no Python there,
because the tests use the base image's. The tests run after
`ARG CACHEBUST`, and every other stage installs its Python packages
after it, as in the Python `test` phase example in `REPO_POLICIES.md`
- Server: the final stage builds and runs the application
- Non-server: the final stage brings up the dev environment
- Image pinned by sha256 hash with version/date comment
- [ ] Gitea Actions workflow at `.gitea/workflows/check.yml` that runs
`script/cibuild` on push, checks out with `persist-credentials: false` and
with `fetch-depth: 0` (which fetches the tags `git describe` needs),
+475 -346
View File
File diff suppressed because it is too large Load Diff