Reference
Principles
Standards say what every project must look like; principles say why those shapes are load-bearing. Two registers feed this page. One is research on what makes agent-driven systems converge on correctness, which gives the four primitives. The other is operational discipline that emerged from running the estate's CI catalog and shipping signed releases through it. Both end at the same shape: shrink the surface where things can drift, and the rest takes care of itself.
Agent-correctness primitives
Four architectural primitives that shrink the surface where an LLM can produce wrong-but-green output. Each makes a class of failure mode harder to express; together they aim to make the path of least resistance and the path of correctness the same path.
primitive 1
Derived obligations
The rule. If an output can be derived from the spec, codegen it: the agent writes the source, tools derive everything downstream. Each derivation layer is a place where incorrect output cannot be expressed, rather than a place the agent has to remember not to express it.
Where it runs here. Contract authors declare
what must hold with check_file_exists,
check_file_contains and the rest of the closed
primitive set; _lib.sh derives the executable check,
so a new contract is a fifteen-line check.sh and not a
hand-rolled shell pipeline. A project's .gitlab-ci.yml
names a catalog component
(include: gitlab.com/dunn.dev/pipeline/go-release-binary@2.2.3)
and the inputs that vary; three hundred lines of cross-compile
matrix, signing and artifact handoff derive from the catalog, and
a version bump derives a new job body without the project's
source changing. This site's agent surface works the same way:
the Markdown at <path>/index.md and the page
list in /llms.txt are generated from the sources the
browser pages render from, so no hand-curated copy exists to fall
out of date. The routing bullets are the hand-kept exception,
which is why the build resolves every target they name and fails
on a dangling one.
Where we leave room for it. Adding a standard means dropping a directory with a CONTRACT.md and a check.sh: its page, its assertions table and its Markdown derive from that. The one hand-kept step is its row in the page list, and the build fails on a row whose target does not exist.
primitive 2
Prescriptive failure
The rule. When a check rejects an output it
names the next action, not the problem. "Lift the avatar.svg
template from repository/templates/" is
actionable; "file missing" is a postmortem. The agent
re-reads the error to produce its next attempt, so a message that
names an action replaces a prompt somebody would otherwise write.
Where it runs here. Every assertion emits one
line, PASS or FAIL, then
<contract>/<assertion-id>, then a message:
FAIL repository/file-contains:README.md: README.md does not match /^!\[hero\]\(hero\.svg\)/
The failure prints the index into the remediation and the
contract page carries the remediation: which template to lift,
what string to insert, where it lives. The catalog rejects a bad
input at pipeline-creation time, quoting the regex the value
failed, so nobody waits for a runtime error to dig the cause out
of. A .deviations.yaml that will not parse reports
ERROR with the filename and yq's own stderr, then
states the consequence: deviations are not applied this run, so
every assertion below reports its raw verdict with WAIVED
unavailable. Not "deviation register broken".
primitive 3
Bundled enforcement
The rule. Verification couples to value delivery: the only path to the artifact runs through the check. Opt-in enforcement, whether a separate lint job, a recommended pre-commit hook or a "remember to validate" note, gets bypassed under context pressure. Ask whether anyone can get the value without passing through verification.
Where it runs here. A project consuming
reference-check runs it in the same pipeline as
cloudflare-worker, so a conformance failure fails
the pipeline and the site does not deploy; they are siblings
because the catalog makes them siblings, not because the consumer
remembered to wire them together. The reference's own
just check runs just guard, the
primitive-whitelist parser, so a check.sh calling an out-of-set
command cannot ship past CI. go-release-binary and
slsa-attest sign on every release tag with no opt-in
flag: the job that uploads the artifact signs it.
Where advisory mode is right. Adopting a new
standard against a legacy consumer, where the goal is surfacing
findings rather than blocking merges that predate the check.
reference-check takes
fail_on_violation: false for it, and the trade is
that every accepted gap carries a deviation-register entry with
its reason. When the reason stops holding, the entry goes or the
project re-conforms, and enforcement bundles again.
primitive 4
Vacuity detection
The rule. Catch checks that pass while doing no meaningful work. The failure mode is the test passes and the feature is broken; the cause is a pass condition satisfied vacuously by an empty array, an always-skip branch, a regex that matches anything. Ask whether the check can be satisfied without doing the work it exists to require.
Where it runs here. The repository contract does
not assert check_file_exists README.md, which an
empty file satisfies; it asserts
check_file_contains README.md '^!\[hero\]\(hero\.svg\)',
making the observation the file's structure rather than its
presence. The pipeline contract does not look for an
@ in .gitlab-ci.yml, which
@latest would satisfy; it matches
'gitlab\.com/dunn\.dev/pipeline/[a-z][a-z0-9-]*@[0-9]+(\.[0-9]+)2([^0-9A-Za-z.-]|$)',
a major-or-fuller version on a dunn.dev/pipeline
component, and adds explicit check_file_lacks assertions for
@latest and @main. The deviation
register applies the same test to prose: an accepted gap is not
"this is fine" but "this is fine because of a named, checkable
fact about this project", and an entry without a reason is
rejected at the boundary. That is what stops the register
becoming a universal escape hatch.
Operational discipline
These did not come from agent-correctness research. They emerged from operating the dunn.dev catalog and shipping software in this estate, and they compose with the primitives because both reduce the surface where things drift.
catalog
Version pinning
The rule. Same source tree, same CI behaviour.
Every reference to a catalog, image, tool or template sits at a
strict version: no @latest, no @main,
no mixed tags across includes. The version advances in commits,
not silently between pipeline runs.
What it prevents. A floating ref makes the bug
silent: the pipeline goes green at T and red at T+1 against the
same commit because an upstream rolled forward, and finding that
means diffing the catalog's commit log against the pipeline log
and cross-referencing image hashes by hand. Pinned, the bug is
loud. A deliberate bump to @2.2.3 either changes
behaviour or does not, and the change sits in the commit.
Where it runs here. The
pipeline standard
enforces it on every consumer's .gitlab-ci.yml, and
the catalog holds the same shape internally: each component
declares
image: registry.gitlab.com/dunn.dev/pipeline/ci:$[[ component.version ]],
so a consumer pinned at @2.2.1 provably runs against
ci:2.2.1 and tooling advances with contract or not
at all. Tags from 2.0.0 on are unprefixed strict
semver, which makes a mixed-style pin (@v1.x.y
beside @2.x.y) advertise itself as the migration
window it is. A worked instance of
derived obligations: the pin
is the spec, the job body is derived from it.
release
Byte-parity shipping
The rule. The binary you sign is the binary your
container runs. Build once, ship twice: once as a signed,
attested release artifact, once as a thin runtime layer
(FROM ci-runtime-go + COPY dist/<binary>). The
same file passes through both pipes.
What it prevents. Attestation means something
only when the artifact assessed is the artifact shipped. SLSA,
cosign, SBOM tooling and scanners each inspect an
artifact; when the production one is a sibling of the inspected
one, their verdicts are advisory at best. Signing an image
attests the manifest digest and the binary inside stays an opaque
blob to cosign, so "sign the release binary" and
"sign the container image" are not substitutes. Byte
parity makes both signatures refer to one SHA-256. The tell of
the broken shape is a go build inside the
Containerfile: two builds, two binaries, two attestations that do
not reference each other, and a later investigation that has to
reverse-engineer which commit produced what.
Where it runs here. The catalog's
container-image component takes
from_artifacts: true. The package job
builds the binary, cosign-signs it and uploads it with its
.sha256 sidecar; the downstream job copies that same
artifact into ci-runtime-go, a 30 MB UBI-micro base.
A worked instance of
bundled enforcement: the job
that uploads the binary is the job that signs it.
catalog
Minimal artifacts
The rule. A shared artifact is the smallest
shape that does its job, then stops. The estate's runtime bases
(ci-runtime-go, ci-runtime-node) are a
FROM plus OCI labels: no speculative users, no Tini,
no WORKDIR, no default ENTRYPOINT. They
publish at the catalog's own semver so version coupling
propagates cleanly to consumers.
What it prevents. Every speculative addition to
a base lands in every consumer image automatically. A
USER 1001 nobody asked for becomes a thing every
consumer reasons about and overrides for the life of the
artifact, and removing it later is harder than never adding it.
The same holds for CI template inputs nobody requested and
renovate.json customManagers watching what nobody
pins. Defaults are not features.
review
Bounded complexity
The rule. Minimal is the default and complexity buys its way in, on one of three grounds. Use them as the gate when reviewing a diff or a proposal:
- Security. A trust boundary you can state in a sentence ("this token never leaves this listener"), an auditing path, or defense in depth against a named threat.
- Multi-tenant reuse. The flexibility unblocks at least two real consumers. One real plus one imagined is speculation, not reuse.
- Independent deploy lanes. One component ships without coordinating with another. Real in monorepos and shared catalogs, almost never inside a single binary.
Outside those three, remove it, ship the simpler thing, and add the hook back when the second consumer turns up. Real consumers teach you what shape to add; imagined ones teach nothing.
shape
Useful core first
The rule. Build the local-only thing that works
by itself, then layer integrations on as flags, subcommands or
separate components. bairn fetches Famly archives to
local disk before any vendor-push subcommand exists;
tutti writes evidence files to disk before the Astro
site reads them. The CLI that runs and writes a file stays the
gravitational center, and no integration is the only path through
the core.
What it prevents. Integration shapes churn: vendors deprecate APIs, schedules shift, deploy targets get re-platformed. A core that depends on the integration inherits every one of those churns. It also kills the recurring failure mode of building the integration first to make the tool useful, then finding the local-only path needed for testing or offline work was never built.
fork posture
Shape for upstream
The rule. A change layered on an open-source
project is shaped from day one as a plausible upstream
contribution: configuration knobs and hook points rather than
hardcoded branches, even when this estate is the only consumer.
The test is whether the change could land upstream with cosmetic
edits, or whether it carves out estate-specific paths. Hardcoded
dunn.dev references become configuration defaults,
hardcoded paths become arguments, hardcoded auth models become
pluggable. Roughly 20 percent more design effort.
What it buys. The shaped change survives upstream rebases where a hardcoded fork accumulates conflicts. If upstream takes it, you stop being a fork maintainer and become a consumer of a feature. And the question "could this go upstream as-is?" applies a quality bar at write time, when restructuring is still cheap. Operational config (which DNS provider, which bucket) is exempt; behavioural extensions are not.
planning
Adversarial review
The rule. Any change planned to span more than about 500 lines, touch more than one repo, or run autonomously without operator intervention gets at least two adversarial passes before execution. First pass surfaces concerns, second probes the ones that look load-bearing; stop when a round returns little new signal.
What to scan for. Stale claims, meaning anything in the plan asserting the state of another file, repo or registry (re-verify, memory decays). Reversibility: what a half-failed step leaves behind, and whether rollback loses data. Estate consistency: whether this invents a pattern or follows one. Scope discipline: anything not load-bearing for the stated goal gets cut. Silent regressions: which unknown consumer could break, and where that would surface.
What it prevents. Autonomous runs do not stop to question, so a bad assumption compounds through every step that depends on it. A pass at plan time costs one conversation; catching the same thing mid-execution costs the run plus the recovery plus the rework.
debugging
Verify in isolation
The rule. Before claiming upstream is broken, reproduce the failure in a clean environment running only upstream's quickstart: temp directory, fresh clone, the documented init command, the smallest input that triggers it. If it reproduces, file the issue. If it does not, the bug is in your tree.
What it catches. Stale generated state, an old
package-lock.json, a node_modules/ left
from a previous version, a dist/ nobody regenerated;
the fresh clone eliminates all of them at once. And sloppy
migration, a version bump that missed a consumer site, where the
symptom disappearing under a clean quickstart is itself the
diagnosis. The framing matters too: "upstream is broken" carries
an authority that "I have not reproduced this yet" does not. Get
the reproduction before borrowing the authority.
Why these and not others
A principle earns a slot by meeting two tests: it shapes at least
one executable standard on this site or explains why a standard
has the shape it does, and losing it would visibly degrade
outputs across multiple projects. Personal preference and
one-project tactics stay out. The set grows when a new standard
forces a new explanation; it shrinks when a principle is fully
absorbed into a standard's check.sh and the prose is
no longer load-bearing.