Tooling
How the repository is built, tested, checked and released. Everything here is generated from the comments in the Makefile, the scripts and the workflows, which is where the reasons for each step are written.
Make targets
make substrate
No comment explains this target; its recipe is in the Makefile.
make db-up
No comment explains this target; its recipe is in the Makefile.
make db-down
No comment explains this target; its recipe is in the Makefile.
make perf-config
An isolated, durable PostgreSQL qualification stack. perf-down preserves its volume so a warm
run can follow a cold one; the destructive volume-removal command is documented rather than hidden
behind an easy-to-mistype target.
make perf-up
No comment explains this target; its recipe is in the Makefile.
make perf-down
No comment explains this target; its recipe is in the Makefile.
make perf-reset-stats
No comment explains this target; its recipe is in the Makefile.
make perf-workload
This is a repeatable database regression workload, not a production capacity claim. Replace it with the agreed HTTP workload and corpus before assigning throughput or latency targets.
make perf-stats
No comment explains this target; its recipe is in the Makefile.
make test
-timeout 30m: the store package alone takes nine minutes here and longer on a CI runner, and Go's default of ten minutes per package would fail a slow-but-passing suite as if it had hung. -count=1: a cached test result is keyed on the binary, its flags and the files and variables the test read, and the database's state is none of those. Without it a runner restoring the build cache from an earlier job on the same tree reports packages as passed that never opened a connection, and locally a schema change nothing in the Go inputs records is invisible.
make gate-image
No comment explains this target; its recipe is in the Makefile.
make gate
No comment explains this target; its recipe is in the Makefile.
make licence
Every published file carries a copyright header. Checked rather than documented, because a licence stated once at the root is one file move from a package published without one — and publishing is irreversible.
make contract
The public contract, rendered from the surface that serves it.
Generated rather than written, because a hand-maintained description of a shape diverges from the shape the first time somebody adds a field without knowing the document exists. Committed rather than built on demand, because a change to a contract other people's code depends on has to appear in a diff a reviewer sees. TestTheContractDocumentDescribesTheSurfaceThatServes fails when the two disagree, so running this is a deliberate step and never an automatic one.
make freeze-contract
Freezing is a decision, not a regeneration: it writes the snapshot every later build of the version is held to. Run it when a version is declared frozen, and read the diff.
make signoff
Who authored the commits in a change. It cannot decide who has signed the contributor agreement — that record lives with the signing service — and it makes the question answerable.
make test-inference
No comment explains this target; its recipe is in the Makefile.
make golden
Rewrite the prompt golden from the prompt file.
Run this AFTER test-inference, never instead of it. The golden is what makes a prompt edit visible; the corpus is what says the edit was an improvement rather than a trade nobody priced. Regenerating without measuring turns a failing test into a passing one and changes nothing about the behaviour it was warning about.
make version
What this commit is. x.y.z on the working history, and the x.y.0 it would be released as.
make build
No comment explains this target; its recipe is in the Makefile.
make site
No comment explains this target; its recipe is in the Makefile.
make site-serve
Serves the built site on loopback at http://127.0.0.1:3000/taisce/. It serves what make site
produced; run that again to see an edit.
Scripts
scripts/chart-image-check.sh
Refuses a chart that asks for an image tag its own release did not push.
The chart and the image are published by the same run, and nothing else ties them together: the chart names its image by repository and a tag it defaults from its appVersion, and the image is pushed under whatever tags the workflow lists. When those two conventions drifted apart the published chart named a tag that did not exist, and every install of it would have sat in ImagePullBackOff with nothing wrong in the chart that a lint could see (#21).
So this renders the packaged chart exactly as an operator would get it, collects every reference to the release's image repository, and fails unless each one is among the refs the run pushed.
What it does not cover: images from other repositories the chart names, such as the PostgreSQL operator's image, which this release does not produce and cannot vouch for.
scripts/compare-corpus.sh
Render two corpus runs side by side, case by case.
Comparing providers is something this project does now that inference is a profile, and doing it by reading two thousand-line logs is how a difference gets missed. What matters per case is small: what was produced, what was refused, and whether the case passed — so that is what this shows, and the whole point is that a line differing between two providers is visible without reading either log.
make test-inference INFERENCE_PROFILE=local > /tmp/local.txt
make test-inference INFERENCE_PROFILE=openrouter > /tmp/openrouter.txt
scripts/compare-corpus.sh /tmp/local.txt /tmp/openrouter.txt
It reports what the runs say and adds nothing: a case missing from one run is shown as missing rather than as a difference, because a run that did not measure something has not disagreed with anything.
scripts/contract.go
Renders the public contract document from the surface that serves it.
Under ignore and named explicitly by make contract, so it is not part of go build ./... and
does not ship as a command. It is a development tool: the artefact it produces is what is
published, and a test fails if the two disagree.
scripts/coverage-gate.sh
The coverage gate.
Rule 6 makes coverage a requirement. This is what makes it one: without something that fails, the rule survives exactly as long as whoever remembers it.
The floor is a ratchet, not a target. It sits at what the suite already achieves and moves up when a change earns it. A fixed percentage invites tests written to reach it; the only way to move a ratchet is to test something that was not tested.
THE FLOOR SITS BELOW THE NOISE, NOT AT THE PEAK.
The measurement is not deterministic. Some tests race deliberately — several writers against one exclusion constraint, several drivers against one advisory lock — and which branches run depends on who wins. Observed range across consecutive runs of an unchanged tree: about half a percentage point.
So the floor is set from the LOWEST number a run produces, never the highest. A ratchet raised to a lucky peak fails on the next ordinary run, and a gate that fails for reasons nobody changed is one that gets bypassed — which costs more than the tenth of a percent it was protecting.
Raising it after a real improvement means running the suite more than once and taking the smallest result.
A change that only deletes well-covered code can fail this gate, deliberately. The remedy is to cover something untested, never to lower the floor; why the alternatives were rejected is D7.
The number is computed across packages. go test -cover counts only what a package's own tests
reach, which understates a codebase exercised end to end — the same suite reports 75.4% that way
and 78.9% with -coverpkg=./... . The second is the honest one.
scripts/docsite.go
Stages the documentation site's source for the renderer in site/: the public version, with nothing named in scripts/private-paths.txt.
Under ignore and named explicitly by make site, so it is not part of go build ./... and does
not ship as a command. The logic, and the tests that hold it, are in internal/docsite.
go run scripts/docsite.go -dsn … -out site/docs -sidebars site/sidebars.generated.json -repo owner/name -ref sha
scripts/gate.sh
The gate a change passes before it merges.
It is what the hosted runner was for, run here. That runner gave this project two things the developer's machine does not: Linux, and a clean checkout of the commit rather than a working tree that might hold something uncommitted. It never gave enforcement — this repository's plan has no branch protection — so replacing it loses a check mark somebody else can see and nothing else.
So this clones the commit, starts a fresh substrate from the project's own image, and runs exactly what the workflow ran, in a Linux container under colima: the licence gate, the full suite with the coverage floor, and vet. Whether the contract document is current is a test kept with the document in the development repository (internal/api/contractdoc_test.go), so it runs in the suite here.
What it does not reproduce, stated so nobody relies on it at a wider width: the hosted runner is x86-64 and this laptop is arm64. Nothing here builds with cgo, which is where the architecture usually shows, so the gap is small — small, not zero.
scripts/licence-gate.sh
The licence gate.
A licence stated once at the root and nowhere else is one file move away from a package published with no licence header — and since publishing is irreversible, the moment that is noticed is after somebody has already depended on it.
What the header says, and why it names the authors
not an assignment, so contributors keep the copyright in what they write — a blanket notice naming only Ensera is accurate today and stops being accurate the moment somebody else contributes. Naming the authors is true in both states and needs no editing when the second one arrives.
What is exempt, and why each one
Test files. They are not published in any package and a header on each is noise in the files whose comments are doing the most work.
Nothing else. Generated files would be exempt if there were any; there are none, and adding the exemption before there is something to exempt is the thing rule 10 is about.
scripts/postgres-profile.sql
scripts/signoff-gate.sh
The sign-off gate.
D45 takes a contributor agreement rather than a Developer Certificate of Origin, and the agreement is checked where signatures live — a bot against a signature record, on a pull request. This checks the other half, which a bot cannot: that the commits in a change carry the author they claim.
What this catches that a signature bot does not
A bot verifies that the person who OPENED a pull request has signed. It says nothing about the authorship of the commits inside it, and a change can carry commits authored by somebody who never signed anything — a cherry-pick, a rebase carrying somebody else's work, a squash that credits the wrong person. The agreement then covers the submitter and not the code.
So this lists the distinct authors in a range and shows them. It cannot decide who has signed — that record lives with the signing service — and it makes the question answerable rather than invisible.
scripts/version.sh
What version this is.
Two lines, and why the patch number is computed
x.y.0 a release. Only these exist in the published repository, and each is an account of
what changed that somebody wrote deliberately.
x.y.z a commit on the working history, z counting commits since the last release. Every
commit has one, and nobody maintains it.
Computed rather than stored, because a number kept in a file is a number somebody forgets to bump — and the failure is silent: two commits claiming the same version, discovered when a bug report names one of them. Counting commits since a tag cannot disagree with the history it describes.
VERSION holds only the minor line, x.y, because that is the part a person decides. The patch is a
fact about the repository.
Continuous integration
.github/workflows/docs.yml
The documentation site. The build refuses a link or an anchor that names nothing, a document the navigation does not reach, and a package with no doc comment. The schema reference is read from a database the migrations have just built, so the job starts the same substrate the tests use.
When it runs
In the development repository, only when started by hand, like the suite's workflow: the account's
included Actions minutes are finite. On a push or a pull request there the jobs are skipped by their
conditions, and a skipped job bills no minutes. make site is the local equivalent.
In the public repository, on every push to main and every pull request, on standard GitHub-hosted runners, which GitHub's billing documentation lists as free for public repositories.
Where the renderer's dependencies are allowed to run
The renderer is a Node application with a large dependency tree, pinned by site/package-lock.json and installed with install scripts disabled (site/.npmrc). That code runs only in the build job, whose token can read the repository and nothing else. The deploy job runs no third-party package code: it takes the built pages as an artefact and publishes them. A compromised package can at worst produce a wrong artefact, and it never holds the credential that publishes.
The site is deployed only by this workflow running in the public repository, from its main branch, which receives nothing but reviewed release snapshots.
.github/workflows/release.yml
A release is a tag on the public repository, and this workflow is the only thing that makes one . It runs the complete gate the build runs on every push, then builds the image, the chart and the binaries, signs them with the workflow's own identity (Sigstore keyless: no signing key exists to steal) and attaches SLSA build provenance — Build Level 2, see D6 — so a package that did not come from here is distinguishable from one that did. Nothing here is a claim about a maintainer whose account and repository are both compromised; SECURITY.md says so.
.github/workflows/test.yml
The build is the gate a change has to pass, and it is the same target a contributor runs: the
complete uncached suite against the project's own PostgreSQL image, cross-package coverage measured
against the floor, go vet, and the licence gate. make gate runs exactly this in a container, so
a local green and a build green mean the same thing rather than two different things.
There is no skip-when-absent arm anywhere below. A missing database fails the run rather than passing it empty, because a suite that skips its own dependency is a green run that asserted nothing — which is worse than a red one, since nobody looks at it.
The live-inference target is deliberately not here. It costs money and sends text to a provider, so
it stays a command somebody types on purpose (make test-inference).
What the tooling's own tests hold
- The gate refuses a disk without room and takes its database volume with it —
TestTheGateRefusesADiskWithoutRoomAndTakesItsDatabaseVolumeWithIt - Public copy carries no secret and no unmeasured claim —
TestPublicCopyCarriesNoSecretAndNoUnmeasuredClaim - The public copy guard refuses planted secrets and claims —
TestThePublicCopyGuardRefusesPlantedSecretsAndClaims - The release verifies what it published before announcing it —
TestTheReleaseVerifiesWhatItPublishedBeforeAnnouncingIt - The security policy names the level and the pinned checks —
TestTheSecurityPolicyNamesTheLevelAndThePinnedChecks