ceremony/drills/README.md
claude-bot-andresmgsl af48581973 drill: the 0.1.0 record, and the first-release caveat in the doctrine
drills/0.1.0.md — six probes plus (g), run on the disposable scratch repo
against the candidate SHA, every refusal checked for droppings; the pin
deviation (fork ref, CEREMONY_SELF_REF -> candidate SHA in both carriers)
recorded under its own heading per triage's ruling on #11. drills/README.md
gains the first-release caveat that ruling asked for: the first drill can
never take the pure pinned consumer path, and must not fix that by putting
a tag-shaped branch in the canonical ref namespace.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:40:38 +00:00

54 lines
2.6 KiB
Markdown

# Drills
What a drill means in this repo: an **end-to-end rehearsal of both doors of
the release workflow on a disposable repo**. The contract suite proves every
decision offline — facts → decide → notes against fixtures, the merge door's
step sequence replayed in release-exercise.yml — but the doors themselves
only ever run live: gating on a real push event, the tag create, the
publish, the `-dev` re-arm (release.yml's "what is honestly untested"). The
drill is where they run live *before* a version rests on them.
## The rehearsal
1. Create a scratch **private** repo. It is disposable by design — it gets
deleted at the end.
2. Install the docs/CONSUMERS.md caller stubs, pinned to the release
candidate ref. A branch ref works: refs are static identifiers — the
family's own drill doctrine.
**Except for the first release** (learned drilling 0.1.0, #11): the
stubs' consumer path fetches ceremony at `CEREMONY_SELF_REF` — the very
ref the first drill exists to rehearse creating — so the pure pinned
path cannot run before some `X.Y.Z` ref exists, and a branch named like
the tag must NOT be created on the canonical repo to paper over it (it
would shadow the tag for every consumer until someone remembers to
delete it). The first drill instead pins the callers to a fork ref
carrying the candidate tree with `CEREMONY_SELF_REF` rewritten to the
candidate SHA in every pin carrier, and records that one-line deviation
in its record. From the second release on, this paragraph is moot.
3. Give it a fixture `VERSION` / `CHANGELOG.md` / `drills/` in the armed
state (`X.Y.Z-dev`, `## Unreleased` on top).
4. Exercise both doors, one probe at a time:
1. a merge-door ceremony publishes exactly one release and re-arms main
to `-dev`;
2. a mislabeled ordinary PR is a green NOTICE no-op;
3. a bare-version PR without the `release` label refuses;
4. a re-run of the completed ceremony refuses;
5. a tag-door release from a manual tag;
6. a mismatched tag refuses.
Every refusal must refuse **creating nothing** — a probe that leaves a
tag or a release behind on a refusal path is a failed probe.
## The record
One file per version, `drills/X.Y.Z.md` — the shape the siblings use: what
was run, where, the result of each probe, failures written down plainly. The
record is the evidence; the scratch repo is the evidence's scaffolding and
is deleted afterwards.
`actions/drill-recorded` refuses any bare-version tree whose record is
missing or blank. A waived drill is still a record: the file says WAIVED and
why — a maintainer's call, visible and reviewable in the release PR's diff,
never a silent skip.