1 Commits
Author SHA1 Message Date
sneak 36e6329602 Rewrite REPO_POLICIES.md sentence by sentence (closes #136)
check / check (push) Canceled after 0s
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
2026-11-04 01:18:41 +00:00
3 changed files with 53 additions and 62 deletions

No files matched your search

+26 -30
View File
@@ -56,14 +56,14 @@ with your task.
- the step that runs `script/bootstrap` to install a Python `test` phase's - the step that runs `script/bootstrap` to install a Python `test` phase's
packages from `Pipfile.lock` packages from `Pipfile.lock`
- [ ] A stage with none of these steps declares `ARG CACHEBUST` right after - [ ] A stage with none of these steps declares `ARG CACHEBUST` right after
`FROM`. A step that also installs anything else comes after `FROM`. A step that installs anything else as well, such as a
`ARG CACHEBUST` too. A `script/bootstrap` that also installs node packages `script/bootstrap` that also installs node packages, comes after it too.
is one. The `script/` builds pass a new `CACHEBUST` value on every build, The `script/` builds pass a new `CACHEBUST` value on every build, which
which reruns every `RUN` step after that line and leaves the layers above reruns every `RUN` step after that line and leaves the layers above it and
it and the cache mounts in place; `--no-cache` would build those layers the cache mounts in place; `--no-cache` would build those layers again and
again and empty the mounts. A stage without the `ARG` line is served from empty the mounts. A stage without the `ARG` line is served from cache on
cache on an unchanged tree, so the scripts and the `ARG` lines are an unchanged tree, so the scripts and the `ARG` lines are re-vendored in
re-vendored in one commit. one commit.
- [ ] Go: each Go stage downloads the modules (`COPY go.mod go.sum ./`, - [ ] Go: each Go stage downloads the modules (`COPY go.mod go.sum ./`,
`RUN go mod download`) above `ARG CACHEBUST`; the steps that compile `RUN go mod download`) above `ARG CACHEBUST`; the steps that compile
(`golangci-lint run`, `go test`, `go build`) mount Go's build cache (`golangci-lint run`, `go test`, `go build`) mount Go's build cache
@@ -76,19 +76,15 @@ with your task.
- [ ] Python: a `test` phase that installs its packages from `Pipfile.lock` does - [ ] Python: a `test` phase that installs its packages from `Pipfile.lock` does
it above `ARG CACHEBUST`, with `COPY script/ script/`, it above `ARG CACHEBUST`, with `COPY script/ script/`,
`COPY Pipfile Pipfile.lock ./` and `RUN script/bootstrap`. When `COPY Pipfile Pipfile.lock ./` and `RUN script/bootstrap`. When
`script/bootstrap` runs in that step, it installs nothing beyond these: `script/bootstrap` runs in that step, it installs nothing beyond system
- system packages packages, pipenv and its dependencies, and the packages from
- pipenv and its dependencies `Pipfile.lock`. It installs pipenv and its dependencies by hash, with
- the packages from `Pipfile.lock` `pip install --require-hashes`. It installs the packages from
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the tests
It installs pipenv and its dependencies by hash, with need the development packages. It installs no Python there, because the
`pip install --require-hashes`. It installs the packages from `Pipfile.lock` tests use the base image's. The tests run after `ARG CACHEBUST`, and every
with `pipenv install --deploy`, plus `--dev` when the tests need the other stage installs its Python packages after it, as in the Python `test`
development packages. It installs no Python there, because the tests use the phase example in `REPO_POLICIES.md`
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 - [ ] The gate phases invoke their tools directly, never through `make lint` or
`script/test` — those are themselves a `docker build` and would recurse `script/test` — those are themselves a `docker build` and would recurse
inside a build step inside a build step
@@ -115,15 +111,15 @@ with your task.
- that of a submodule keeping its own `.git` directory - that of a submodule keeping its own `.git` directory
`git describe` does not need them, and each can hold a credential: a `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. password in a remote URL, or the token the CI checkout step stores there. A
Some submodule names have a `config` segment, as in `config`, submodule name may have a `config` segment, as in `config`, `deploy/config`
`deploy/config` or `config/lib`. Such a submodule loses its whole git or `config/lib`. Such a submodule loses its whole git directory to
directory to `**/.git/modules/**/config`, and Go's version stamping then `**/.git/modules/**/config`, and Go's version stamping then fails the build.
fails the build. Give it a name without that segment Give it a name without that segment (`git submodule add --name`). The stage
(`git submodule add --name`). The stage that compiles has `git`: the Debian that compiles has `git`: the Debian Go image has it, and an alpine one needs
Go image has it, and an alpine one needs `apk add --no-cache git`. That `apk add --no-cache git`. That stage takes the version from the `VERSION`
stage takes the version from the `VERSION` build argument when one is given, build argument when one is given, otherwise from
otherwise from `git describe --tags --always`. That gives: `git describe --tags --always`. That gives:
- the tag, on a tagged commit - the tag, on a tagged commit
- the tag, the number of commits since it and the short commit - the tag, the number of commits since it and the short commit
(`v1.2.3-4-gabc1234`), on a later commit (`v1.2.3-4-gabc1234`), on a later commit
+18 -22
View File
@@ -82,7 +82,7 @@ Template files can be fetched from:
`git describe` does not need them, and each can hold a credential: a `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 password in a remote URL, or the token the CI checkout step stores
there. Some submodule names have a `config` segment, as in `config`, there. A submodule name may have a `config` segment, as in `config`,
`deploy/config` or `config/lib`. Such a submodule loses its whole git `deploy/config` or `config/lib`. Such a submodule loses its whole git
directory to `**/.git/modules/**/config`, and Go's version stamping then directory to `**/.git/modules/**/config`, and Go's version stamping then
fails the build. Give it a name without that segment fails the build. Give it a name without that segment
@@ -123,14 +123,14 @@ Template files can be fetched from:
- the step that runs `script/bootstrap` to install a Python `test` - the step that runs `script/bootstrap` to install a Python `test`
phase's packages from `Pipfile.lock` phase's packages from `Pipfile.lock`
- A stage with none of these steps declares `ARG CACHEBUST` right after - A stage with none of these steps declares `ARG CACHEBUST` right after
`FROM`. A step that also installs anything else comes after `FROM`. A step that installs anything else as well, such as a
`ARG CACHEBUST` too. A `script/bootstrap` that also installs node packages `script/bootstrap` that also installs node packages, comes after it too.
is one. The `script/` builds pass a new `CACHEBUST` value on every build, The `script/` builds pass a new `CACHEBUST` value on every build, which
which reruns every `RUN` step after that line and leaves the layers above reruns every `RUN` step after that line and leaves the layers above it and
it and the cache mounts in place; `--no-cache` would build those layers the cache mounts in place; `--no-cache` would build those layers again and
again and empty the mounts. A stage without the `ARG` line is served from empty the mounts. A stage without the `ARG` line is served from cache on
cache on an unchanged tree, so the scripts and every stage's an unchanged tree, so the scripts and every stage's `ARG CACHEBUST` line
`ARG CACHEBUST` line are added in the same commit. are added in the same commit.
- Go: each Go stage downloads the modules (`COPY go.mod go.sum ./`, - Go: each Go stage downloads the modules (`COPY go.mod go.sum ./`,
`RUN go mod download`) above `ARG CACHEBUST`; the steps that compile `RUN go mod download`) above `ARG CACHEBUST`; the steps that compile
(`golangci-lint run`, `go test`, `go build`) mount Go's build cache (`golangci-lint run`, `go test`, `go build`) mount Go's build cache
@@ -143,19 +143,15 @@ Template files can be fetched from:
- Python: a `test` phase that installs its packages from `Pipfile.lock` does - Python: a `test` phase that installs its packages from `Pipfile.lock` does
it above `ARG CACHEBUST`, with `COPY script/ script/`, it above `ARG CACHEBUST`, with `COPY script/ script/`,
`COPY Pipfile Pipfile.lock ./` and `RUN script/bootstrap`. When `COPY Pipfile Pipfile.lock ./` and `RUN script/bootstrap`. When
`script/bootstrap` runs in that step, it installs nothing beyond these: `script/bootstrap` runs in that step, it installs nothing beyond system
- system packages packages, pipenv and its dependencies, and the packages from
- pipenv and its dependencies `Pipfile.lock`. It installs pipenv and its dependencies by hash, with
- the packages from `Pipfile.lock` `pip install --require-hashes`. It installs the packages from
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the tests
It installs pipenv and its dependencies by hash, with need the development packages. It installs no Python there, because the
`pip install --require-hashes`. It installs the packages from tests use the base image's. The tests run after `ARG CACHEBUST`, and every
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the other stage installs its Python packages after it, as in the Python `test`
tests need the development packages. It installs no Python there, phase example in `REPO_POLICIES.md`
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 - Server: the final stage builds and runs the application
- Non-server: the final stage brings up the dev environment - Non-server: the final stage brings up the dev environment
- Image pinned by sha256 hash with version/date comment - Image pinned by sha256 hash with version/date comment
+9 -10
View File
@@ -235,7 +235,7 @@ style conventions are in separate documents:
executes, and the build still exits 0. Every `docker build` in `script/` executes, and the build still exits 0. Every `docker build` in `script/`
therefore passes `--build-arg CACHEBUST="$(date +%s)-$$"`, the time and the therefore passes `--build-arg CACHEBUST="$(date +%s)-$$"`, the time and the
script's process id. So no two builds share a value, not even the three in one script's process id. So no two builds share a value, not even the three in one
`script/cibuild`. Four scripts do this, and there is no fifth: `script/cibuild`. These are the four, and there is no fifth:
- `script/lint` - `script/lint`
- `script/test` - `script/test`
- `script/cibuild` - `script/cibuild`
@@ -440,7 +440,7 @@ style conventions are in separate documents:
`git describe` does not need them, and each can hold a credential: a `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 password in a remote URL, or the token the CI checkout step stores
there. Some submodule names have a `config` segment, as in `config`, there. A submodule name may have a `config` segment, as in `config`,
`deploy/config` or `config/lib`. Such a submodule loses its whole git `deploy/config` or `config/lib`. Such a submodule loses its whole git
directory to `**/.git/modules/**/config`, and Go's version stamping then directory to `**/.git/modules/**/config`, and Go's version stamping then
fails the build. Give it a name without that segment fails the build. Give it a name without that segment
@@ -499,8 +499,8 @@ style conventions are in separate documents:
dependencies by hash. It does so with `pip install --require-hashes -r` dependencies by hash. It does so with `pip install --require-hashes -r`
and a requirements file in `script/` that lists each of them with `==` and and a requirements file in `script/` that lists each of them with `==` and
its `--hash`. pip refuses to install a dependency the file does not list. its `--hash`. pip refuses to install a dependency the file does not list.
- `script/bootstrap` then runs `pipenv install --deploy`, with `--dev` when - It then runs `pipenv install --deploy`, with `--dev` when the tests need
the tests need the development packages. `--deploy` does all of these: the development packages. `--deploy` does all of these:
- installs only what `Pipfile.lock` names - installs only what `Pipfile.lock` names
- checks every package against the lockfile's hashes - checks every package against the lockfile's hashes
- fails when the lockfile is out of date with `Pipfile` - fails when the lockfile is out of date with `Pipfile`
@@ -850,15 +850,14 @@ style conventions are in separate documents:
- after installing, re-resolves the binary the way callers do, with - after installing, re-resolves the binary the way callers do, with
`hash -r` and then through `PATH`, not through the directory the installer `hash -r` and then through `PATH`, not through the directory the installer
wrote to. A shadowing binary can hide an install, which then succeeds wrote to. It fails and names the resolved path. A shadowing binary can
while no caller sees any change. In that case it fails and names the hide an install, which then succeeds while no caller sees any change.
resolved path.
- is actually called, and prints the version on both success paths. A - is actually called, and prints the version on both success paths. A
function defined and never invoked has the same exit status and the same function defined and never invoked has the same exit status and the same
empty output as one that worked. empty output as one that worked.
Node is the exception to the whole-token comparison. The canonical Node is the exception to the whole-token comparison. The canonical
`script/bootstrap` compares only node's major version. That is because the `script/bootstrap` compares only node's major version, because the
`Dockerfile` stages start from a node 22 alpine image, which is not the `Dockerfile` stages start from a node 22 alpine image, which is not the
exact pin, and nvm cannot install a prebuilt node on alpine. exact pin, and nvm cannot install a prebuilt node on alpine.
@@ -928,8 +927,8 @@ style conventions are in separate documents:
an explicit allowlist of known origins. Wildcard (`*`) is acceptable an explicit allowlist of known origins. Wildcard (`*`) is acceptable
only for public, unauthenticated read-only APIs. only for public, unauthenticated read-only APIs.
- **Error handling:** - **Error handling:**
- Internal errors must never leak implementation details to the client. - Internal errors must never leak implementation details to the client,
Those details include: such as:
- stack traces - stack traces
- SQL queries - SQL queries
- file paths - file paths