A field test and a fixture are orthogonal artefacts. A fixture **pins**
behaviour for the future: something executes it, so a change that breaks it
turns a test red. A field test **proves** behaviour at one moment: a downstream
consumer reached the shipped surface from outside, and the green cycle records
that. Calling the field test's output "fixtures" imported the first artefact's
lifecycle onto the second one, which gave it a birth and no death — every
fieldtested cycle grew the repository permanently, and the recorded command
lines stayed on the agenda of every agent that grepped the tree.
`docs/conventions.md` § Lifecycle is now the single source of both rules, beside
the spec/plan lifecycle it mirrors:
1. **Rotation depth 1.** The next field test clears the previous corpus as it
files its own, so `fieldtests/` always holds exactly the proof for the tree
as it stands. No staleness detection, because there is no signal to detect:
a transcript never turns red. `git log --grep='^fieldtest: '` is the index and
`git show <sha>:<path>` returns any of it verbatim.
2. **No durable artefact may point into the corpus.** A pointer into a rotating
directory either dangles at the next rotation or keeps a dead surface on the
agenda. Replace it with the description it stood in for, drop it if it serves
nothing, or promote the artefact to a real fixture with a test that runs it.
`fieldtest/SKILL.md` § Dispatch owns the mechanics. The orchestrator rotates
*before* dispatching, not at commit time: the directory the fieldtester reads is
then the one it writes, which is what keeps a predecessor's retired flags off its
agenda — commit-time rotation would tidy the tree and leave that leak open. The
commands are written over a resolved `<corpus>` (default `fieldtests`, project
fact may override) with a refusal condition, because an unsubstituted path makes
the rotation a silent no-op and can stage a deletion of the predecessor under a
subject claiming the new corpus' examples. `rm -rf`, not `git rm`, so untracked
build output goes too; the orchestrator ensures the repo-root ignore entry
first, since wholesale staging would otherwise commit a build tree into history
that rotation cannot reclaim. An outcome with no new proof (bounce, or an empty
`examples_added`) restores the predecessor with `rm -rf` + `git restore` and
files no commit — `git clean -fd` was rejected: it leaves exactly the ignored
build output while `git status` reports clean (verified, git 2.55).
Rule 2 needs reach beyond the fieldtester, which authors almost nothing durable.
Enforcement is by reference at the actors that walk the tree: `architect` flags
new pointers in the cycle range and is told the corpus is not live surface (a
corpus example is not the property-protecting test a feature owes, and a
wholesale corpus swap in the diff is the routine rotation, not drift);
`plan-recon` excludes it from every sweep, with the promotion iteration as the
one carve-out where the corpus path is the change site; `tester` no longer reads
it for fixture style; `grounding-check` and `spec-skeptic` may never ratify from
it (nothing executes it, so reverting a mechanism cannot turn it red);
`synthetic-user` may not ground a stance in it. Filed findings carry their
evidence inline — an issue outlives many rotations and no gate sees it.
Deliberately not done: a rule block in `templates/CLAUDE.md.fragment`. The
fragment does not re-seed a fixed convention that lives in conventions.md
(ratified in dacadba), so the fragment gains only the project-fact wording.
closes#38
Implements the three efficiency findings from the #310 pipeline
measurement (refs #35): ~691k subagent tokens / ~3.5 h for a
deliberately small cycle, with recon duplication as the single
biggest obligatory per-cycle cost.
1. Cycle recon (pipeline.md § Cycle recon; specify, planner,
brainstorm, boss, plan-recon): recon fan-out is budgeted per
cycle, not per phase. One full plan-recon dispatch — normally
specify Step 1, in a new pre-spec sources/recon_scope carrier
form — serves both the spec's concrete code shapes and the
plan's file-map. planner Step 2 becomes reuse-first (freshness /
quotability / coverage conditions) with narrowly-bounded delta
dispatches (new Delta dispatch contract in plan-recon.md);
broad Explore-type grounding sweeps are banned in every mode.
Field evidence: 151k (Explore) + 99k (plan-recon) with ~40 %
overlap in one bounded cycle.
2. Fieldtest probe tier (fieldtest, fieldtester, pipeline.md,
agent-template.md § model rule 2): a cycle whose user-visible
delta is a single narrow axis dispatches the per-cycle
fieldtest at tier: probe — 1-2 examples on exactly that axis,
~200-word report, explicit model:sonnet dispatch override (no
dispatch-level effort override exists; frontmatter effort
applies). Probe is a tier, not a skip; the milestone fieldtest
always runs full tier on the frontmatter model, keeping the
milestone-close gate's >=2-example floor unconditional.
3. Assumption economy (specify Step 3 + self-review item 6):
grounding-check cost scales with the spec's assumption count,
so specs state current-behaviour claims only where the change
relies on them (the gate's own falsity test), demote
context-only mentions to ledger citations, and keep iteration
scope tight — fewer restatements, never fewer reliances. The
gate itself is unchanged.
Design reviewed pre-implementation (opus plan review); diff
adversarially verified by a 3-lens review workflow (consistency,
operability, cross-reference), confirmed findings folded in.
refs #35
Effort joins model as a mandatory pin: an omitted field inherits the
session effort, coupling every dispatch's thinking budget to whatever
the user happens to be chatting at (often xhigh) — the same
session-state coupling the model pin removes. The assignment follows
the model split:
- xhigh on every opus agent (judgement roles are the pipeline's
quality floor and must not degrade with the session);
- high on every sonnet agent (tightly-scoped plan execution gains
little from xhigh but pays its latency per dispatch, and these are
the per-task in-loop roles — wall-clock is the efficiency metric;
not lower than high, since re-loops cost more than saved thinking);
- medium inline in the workflow scripts for schema-bound
extraction/verification stages that author no code (preflight,
plan-extract, mini-verify, tree-check, finalize, build/suite
verify).
Workflow agent() calls pass effort explicitly on every call — whether
frontmatter effort propagates through an agentType dispatch is
undocumented, so the scripts do not rely on it. Policy documented in
docs/agent-template.md § effort, mirroring § model.
Agents and workflows previously carried no model field, so every
dispatch inherited the session model — including fable, which is
banned for all plugin agents and workflows by owner decree. Every
dispatch now pins opus or sonnet explicitly.
- opus (low-volume judgment gates whose misses silently poison
downstream work): architect, bencher, debugger, fieldtester,
grounding-check, plan-recon, quality-reviewer, spec-skeptic,
tdd-author
- sonnet (mechanical scope, in-loop or fanned out): docwriter,
glossary-extractor, implementer, spec-reviewer, synthetic-user,
tester
- workflows: all 13 agent() call sites pin a model — sonnet
everywhere except the quality-reviewer gate in implement-loop,
the loop's last correctness check (spec-reviewer only gates
task-text correspondence; real-bug finding is the documented
opus strength)
- docs/agent-template.md: model is now a mandatory frontmatter
field, with the assignment rule and the fable ban recorded
An adversarial review of 08bc2aa found three gaps:
- templates/CLAUDE.md.fragment still described the OLD git-tracked /
git-rm-at-close model verbatim — the worst place to miss it, since new
projects import this fragment into their CLAUDE.md. Rewritten to the
gitignored / shell-rm / ledger-only model.
- INSTALL.md still cited "4-digit naming" — now slug-only.
- The fieldtest cross-cycle deletion rule was self-defeating: it keyed
the spare/delete decision on the permanent fieldtest- prefix, which
cannot encode "spare once, then delete." Because fieldtest runs only
AFTER audit closes, the fresh fieldtest spec never exists at the
cycle-close sweep, so the rule is simply "audit discards every
working-tree spec/plan"; the spent fieldtest spec present at N+1's
close was already consumed and goes with the rest. The prefix is now
only a working-tree label, not a delete discriminator. Reconciled
across audit, conventions, pipeline, fieldtest, fieldtester.
Per-cycle specs and plans stop being git-tracked commit-then-git-rm
artefacts and become git-ignored working files: created on disk for the
active cycle, read across sessions from the working tree, and shell-rm'd
at cycle close by audit. Nothing is committed, so there is no
git-history copy — the durable record of a cycle's intent is the design
ledger only, and no durable artefact (code, test, doc, ledger) may cite
a spec/plan by number or path.
- conventions/pipeline/design/README: invert the git-tracked -> git-rm
-> git-history-recovery model to gitignored -> shell-rm -> ledger-only.
- naming: drop the NNNN file counter; files are slug.md (fieldtest specs
keep a fieldtest- prefix as the cycle-close discriminator).
- cycle number: separated from the (now-gone) file number, sourced from
the feat(NNNN)/audit(NNNN) commit subjects, which cycle commits carry.
- specify/planner/fieldtest/fieldtester: no commit step; fieldtest splits
fixtures (committed as code) from its spec (gitignored), with the
cross-cycle rule that a fieldtest- spec belongs to the next cycle.
- boss: auto-sign auditability moves from the (boss-signed) commit
subject to the run's reference issue; rollback reverts only code.
- audit: new Step 5 shell-rm's the cycle spec+plan after the architect
reads them, sparing fieldtest- specs.
Companion machine config (outside this repo): the global git excludes
(~/.config/git/ignore) gains docs/specs/ and docs/plans/ so the ignore
applies to every project at once.
The profile was never parsed — it was prose the skill bodies told the model to read, so most slots were dead, constant across every project, or fiction (the whole pipeline block, including the "tdd is opt-in" claim, was enforced by nothing).
Split it in two: constants become fixed conventions named directly by the skills (new docs/conventions.md), and the few genuinely per-project facts move to each project's CLAUDE.md under '## Skills plugin: project facts'. tdd/fieldtest/docwriter are now always available; the only behavioural toggle left is spec auto-sign.
Delete docs/profile-schema.md and templates/project-profile.yml; add docs/conventions.md and a project-facts section to templates/CLAUDE.md.fragment; rewrite all SKILL/agent prose and the pipeline/design/migration/README/INSTALL docs accordingly.
Authoritative carrier contract for the milestone fieldtest: scoped to
milestone_promise, scenarios derived top-down rather than as a union of
per-cycle axes.
A field test that runs a stale pre-built binary inverts its own
purpose — it reports the previously-shipped state as current, producing
false positives on already-fixed bugs and masking newly-introduced
ones. This bit an AILang raw-buf field test: the agent ran a
target/release binary built before a fix landed, reported a fixed bug as
still-broken, and masked a real check-clean/build-crash defect until
orchestrator re-verification against a fresh build.
Phase 2 now opens with a mandatory build-from-HEAD step (run
commands.build, or invoke the tool through the build system rather than
a path to a pre-existing artefact; build the release profile if the
examples invoke a release binary), and the agent records which build the
run exercised.
Apply the debug-skill pattern (commits 6410732..de42974) to the
remaining skills: the agent file is the single source for each
interface field's semantics; the SKILL.md copy is reduced to field
names plus a pointer, marking the agent's contract table
authoritative. Because SKILL.md loads into orchestrator context and
agents/*.md into the subagent's fresh system prompt with no
transclusion, duplicated field tables drift apart over time.
- brainstorm: carrier (spec_path/iteration_scope) -> grounding-check;
the absolute-path requirement now lives only in the agent.
- planner: carrier (spec_path/iteration_scope/focus_hint) ->
plan-recon, including the mandatory/optional markers and the
BLOCKED-on-missing rule SKILL.md had omitted.
- fieldtest: carrier + produced fields -> fieldtester; the skill-level
`status` roll-up (clean/friction_found/bugs_found/infra_blocked),
which is not part of the agent's run-status protocol, stays defined
in SKILL.md only.
- docwriter: carrier + produced fields -> docwriter agent.
- implement: carrier (iter_id scratch-dir/stats/not-a-branch
semantics) -> implement-orchestrator; per-task sub-status vocabulary
moved into the orchestrator-agent (it runs the loop in a fresh
context and could not read SKILL.md at runtime, yet referenced "the
sub-status table" by name); task_text_path single-sourced in
implementer with spec-reviewer cross-referencing.
audit was already the reference implementation (pointers, no restated
contracts) and is unchanged.
closes#2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fifth skill via the boss pattern. fieldtest empirically tests
whether a shipped cycle is usable by a downstream consumer
who has only the public interface.
Profile gains two slots:
- `paths.public_interface` — list of dirs/files the fieldtester
may read (the project's outward-facing surface: README, design
ledger, docs, examples)
- `paths.fieldtest_examples` — where the fieldtester writes its
fixtures
The forbidden zone is derived: everything not in
`paths.public_interface` (especially `paths.code_roots` and
`paths.bench_dir`) is closed to the fieldtester. This is the
load-bearing source-isolation discipline.
Vocabulary substitutions:
- AILang → "this project"
- milestone → cycle
- Boss → orchestrator
- ailang-fieldtester → fieldtester
- "AIL Surface form / .ail" → "the project's canonical
authoring or consumer form"
- "design/INDEX.md + design/models/" → `paths.public_interface`
- "crates/, runtime/, bench/" → `paths.code_roots`,
`paths.bench_dir`
AILang-specific bits dropped:
- The form-a-default-authoring milestone history (2026-05-13)
and the eight `.ail.json` carve-outs — AILang-specific
schema-migration detail; the universal rule is just
"canonical authoring form only"
- The ail check / ail build / ail emit-ir CLI commands — the
fieldtester now uses "the project's user-facing entry point"
- Per-iter journals reference — replaced with recent iter
commit bodies (universal)
- Example ideas calibrated to AILang (FizzBuzz, Newton's method
on Float, JSON-tree depth, ADT functors) — generalised to
"realistic tasks an end-user might be asked to do"
- `design/contracts/0004-feature-acceptance.md` cross-ref —
dropped (AILang-specific contract); the empirical-vs-
prospective brainstorm symmetry survives in prose
Universal substance preserved verbatim:
- All three Iron Law clauses (public-interface-only,
canonical-form-only, record-don't-fix)
- Five-phase process structure
- Four-class finding taxonomy (bug / friction / spec_gap /
working)
- Spec template
- Status protocol (DONE / DONE_WITH_CONCERNS / NEEDS_CONTEXT /
BLOCKED)
- All 8 Common Rationalisations rows (vocabulary-substituted)
- All 10 Red Flags bullets (vocabulary-substituted, with the
AILang-specific .ail.json hand-write bullet generalised to
"intermediate representations")
The source-isolation contract (Iron Law clause 1) is the
load-bearing discipline. Profile slot
`paths.public_interface` makes it machine-checkable; the
agent's hard limit on opening paths outside that list is the
discipline.