Owner-ratified 2026-07-20: architect, grounding-check, tdd-author and
debugger pin fable/xhigh — cycle-reach singleton gates whose miss
silently ratifies or poisons an entire cycle (drift verdict, autonomous
sign-off signature, RED executable-spec, root-cause). The set is
closed: extending it requires fresh owner ratification, no fable agent
ever runs per-task in a loop or in a parallel fan-out, and workflow
scripts stay fable-free (the implement-loop quality gate caps at opus).
Policy home: docs/agent-template.md $ model rule 1 (effort: fable
gates stay xhigh, not max); the workflow policy headers now point at
the exception instead of the former blanket ban.
The anonymous script stages received the full standing-reading
instruction (project CLAUDE.md + git log -10 --format=full) although
a tree-footprint or text-extraction stage consumes none of it and a
verify stage needs only the build/test commands — re-executed on
every dispatch including tight repair rounds, at ~40k+ real tokens
per freshly-primed context.
Two slim variants in both workflow scripts: STANDING_FACTS
(verify-type stages — mini-verify, standard end-verify,
compiler-driven build/suite verify: project-facts build/test commands
only) and STANDING_NONE (tree/extraction stages — preflight,
plan-index, plan-extract[-all], snapshot: nothing beyond their own
instructions). Judgment roles (implementer, spec/quality reviewers,
tester/e2e, compiler-driven edit stage) keep the full read.
conventions.md § Standing reading and agent-template.md § Standing
reading list carry the tiering sentence; the precedent is the
narrowed per-role reading the named agents already practise
(tester -3, plan-recon/grounding-check -5, fieldtester -8,
docwriter --oneline).
closes#31
qual+repairs are the pipeline's largest cost pool (51M of 164.5M real
tokens, 31%, in the 206-run corpus), with opus weighing ~5x on the
quota side. The opus pin's own rationale (consequence-of-a-miss,
agent-template § model) scales with diff size — so the tier now does
too: the spec-reviewer, which runs before quality, reads the diff
itself and is independent of the implementer, reports diff_magnitude
(git diff HEAD --shortstat) and touches_contract; <=25 changed lines
and no contract-referenced path -> sonnet/high, anything larger,
contract-touching, or unmeasured -> opus/xhigh (fail conservative).
The independent end-verify/mini-verify suite gate is the
deterministic backstop that makes the lower tier defensible; the
chosen tier is logged per task (qual_tier) in the end-report.
Sampling phase per the issue's acceptance: the first ~10 real
small-diff iterations get a one-off opus second review; important+
divergences are recorded on the issue before the threshold counts as
proven.
closes#30
In worktree sessions a dispatched agent's cwd can resolve to the
primary checkout instead of the loop's working tree — observed as a
per-dispatch race: 6/9 quality dispatches returning infra_blocked with
the sha256-of-empty fingerprint over a real diff, and a tree-check
counting the primary checkout's clean tree into a false no-op BLOCKED
on a genuinely-DONE iteration.
Remedy (validated in the field on the reporting run): the carrier
gains repo_root, stamped into every stage prompt as an explicit
'git -C <root>' anchor with a wrong-directory tripwire (an empty diff
or unexpected HEAD sha = wrong cwd, re-run against the anchor). When
the carrier omits it, the first dispatched stage (mini preflight /
standard plan-index) probes 'git rev-parse --show-toplevel' as a
fallback — itself subject to the same race, so SKILL.md documents the
field as effectively required in worktree sessions.
compiler-driven-edit gets the same carrier field (same defect class,
carrier-only). agent-template stage list updated in passing
(plan-extract[-all], end-verify).
closes#25
During a multi-task run nothing commits between tasks, so one task's
file-level `git checkout -- <file>` / `git restore <file>` silently
destroys an earlier task's uncommitted DONE work in a shared file. The
loss was structurally invisible: spec- and quality-reviewers are scoped
to the current task's footprint, diff_fingerprint only detects
same-task repair cycles, and the end-of-iteration tree gate counts
files (the surviving changes keep it nonzero). Observed in the wild as
a PARTIAL run whose DONE reports did not match the tree. Two layers,
both plugin-side (harness-level prevention is ruled out — decision log
on the issue):
Prose guard — implementer.md Step 8 no longer sanctions file checkout
for scope curation: over-reach is undone by editing back, a broken
intermediate state is repaired forward or reported BLOCKED (new fourth
BLOCKED bucket in the status protocol). A matching Iron Law line in
implement/SKILL.md covers all in-loop agents, whole-file and --patch;
docs/conventions.md now marks the checkout discard idiom as the
orchestrator's, between iterations.
Mechanical guard — after every task of a multi-task run a snapshot
agent records `git stash create` (a dangling commit; HEAD, index, and
tree untouched — semantics verified empirically in a scratch repo) plus
the `git diff HEAD --name-only --no-renames` path set. A path that was
HEAD-modified at one boundary and gone at the next trips a hard
BLOCKED naming the lost paths, the boundary, and the recovery snapshot
sha (`git show <sha>:<path>`); the discard verdict outranks per-task
outcomes in blocked_detail since the reports and the tree have
diverged. Coarse by design, in both directions, and documented as
such: a checkout-then-re-edit or a --patch hunk restore escapes the
comparison (the snapshot keeps it diagnosable); a legitimate
back-to-HEAD edit trips it (the verdict says adjudicate against the
snapshot). --no-renames keeps a staged rename from reading as a loss;
untracked files are outside the threat model (checkout cannot discard
them). Cost: one sonnet/medium call per task, multi-task runs only;
single-task and mini runs are unchanged.
Verified: node --check on the async-wrapped script and a stub-agent
harness — discard trips the hard BLOCKED and stops the loop; an
accumulating happy path, a plan-intended deletion, a single-task run,
and a dead snapshot agent all pass without a false positive.
closes#23
The plan-extract step pulled every requested task's verbatim block through a
single schema-bound agent() response. On a large plan that response self-limits
and returns a well-formed PREFIX (commonly just task 1); the only guard rejected
an empty list, so a truncated non-empty subset ran to a clean DONE with the
missing tasks never attempted, yet the end-report read as a completion.
Replace the single-shot dump with an enumerate pass + per-task extraction,
guarded by cardinality checks (issue #22 suggested either direction; this does
both, plus a backstop the issue did not scope):
- plan-index enumerates ids + one-line titles only (bounded output, self-limits
far later than a verbatim dump) and reports total_tasks, the whole-plan count
computed from the fully-readable plan text independently of the emitted list.
- plan-extract:<id> carries one task's verbatim block per agent() call, removing
the across-all-tasks output ceiling. Calls fan out via parallel() (which
honours the concurrency cap on a big plan); the requested id is bound inside
each thunk and results are re-associated by it, never by array position, so
the mapping holds regardless of the order parallel() resolves in.
- Cardinality guards: (a) the whole-plan enumerate must list exactly total_tasks
(the only backstop the no-range path can have without a caller range); (b) a
task_range must be well-formed and covered exactly by the plan; (c) every
expected id must extract non-empty text. Any breach is a hard BLOCKED with a
precise "got N of M" reason, never a silent short run.
Known residual (documented in-code): a single task whose own verbatim body
overflows its dedicated response still returns an accepted prefix — bounded only
by the planner's bite-sized-task invariant, far narrower than the closed vector.
Verified by driving the real script through 11 extraction scenarios in a stubbed
harness plus an order- and self-id-independence association test, and an
adversarial three-lens review of the diff.
closes#22
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
The selector forced every task through the heaviest methodology's
critical path: a behaviour-preserving, type-enumerable change paid the
same specify -> planner -> implement front-half as a novel feature,
because it was neither new behaviour (tdd) nor an observed bug (debug)
and so fell to specify by elimination. Two coupled defects — a selector
with no verification axis, and an all-or-nothing executor — kept the
existing lighter path unreachable and uneconomical. This fixes both.
Part A — verification-keyed selector (boss/SKILL.md):
- Replace the three-way "design line" with an ordered cascade that adds
a verification/enumeration axis ahead of the settled-vs-fork question.
Each lighter arm carries a positive trigger matched by signature, not
reached by elimination.
- New `compiler-driven` arm: a type/signature edit at a definition site
that propagates mechanically. Observe-then-bounce — make the edit,
build, run the suite; clean build AND suite green unchanged commits;
a hole bounces up (specify for a design choice, tdd for discovered
test-specifiable new behaviour); a regression bounces to debug.
- The observed-bug RED-first gate is first in the cascade, so a
mechanical-looking fix cannot bypass it.
- The straddle rule ("add an enum variant") is codified as a rule:
mechanical/forwarding -> compiler-driven; encodes new behaviour ->
tdd/spec; doubt routes up.
- The executor is the elevated inline carve-out plus a shipped workflow,
not a heavy new skill ("the largest concrete win is small").
Part B — Workflow substrate (implement/workflows/):
- implement-loop.js: the per-task loop as a deterministic script. Each
phase (implementer -> spec-compliance -> quality, + tester for E2E) is
a separate top-level agent() call, so a single phase is independently
invokable and inter-phase aggregation/re-loop is code. Retires the
implement-orchestrator agent's inline-role-switch workaround (the four
phase agents survive as the agent-types the script dispatches).
- compiler-driven-edit.js: the observe-then-bounce loop.
- install.sh / uninstall.sh symlink shipped workflows into
~/.claude/workflows/.
- specify and brainstorm stay prose + interactive (human-intent oracle);
only the autonomous/mechanical loops moved. try-and-error is deferred.
Docs (pipeline taxonomy, design, agent-template, migration, README) and
all selector<->executor cross-references updated; the arm and its
executor are co-located so a future re-route through the full loop is a
visible regression.
Verified by an adversarial multi-agent pass: PASS on all six acceptance
criteria; two coherence concerns fixed. The shipped scripts are
syntax-validated but exercised only in a downstream target project (the
skills repo is not itself a pipeline target).
closes#7
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.
Add `pipeline.boss.spec_auto_sign` (default off). With it on, a /boss
run may sign a spec in the user's place — but only through a gate built
to never rely on the orchestrator's own confidence: all objective gates
green (precondition, parse, grounding-check PASS with no human override)
AND a unanimous five-lens adversarial spec-skeptic panel (criterion,
grounding, scope-fork, ambiguity, plan-readiness). Any single BLOCK
falls back to the human sign-off pause.
On a clean sign the orchestrator commits the spec ((boss-signed) in the
subject), fires a mandatory informational-with-veto notify, and proceeds
to planner without stopping. A later veto is a forward correction, never
a history rewind.
- new agent: specify/agents/spec-skeptic.md (read-only, one lens per dispatch)
- specify Step 6 + Iron Law: approval may come from the auto-sign gate,
never from model self-confidence
- boss: third notify category, §"Spec auto-sign", rationalisations, red flags
- profile-schema + template: the opt-in slot
- pipeline.md, agent-template.md, README: the auto-sign path documented
Cycle-close tidy for the glossary-skill cycle (59c2f4b..4fd5408).
Architect drift review (sole gate — repo ships no
.claude/dev-cycle-profile.yml, so commands.regression is empty and the
regression step is a documented no-op):
- [medium] FIXED. docs/agent-template.md said the Iron Law is rendered
'as a numbered list' (the schematic placeholder at l.37 and the prose
at the § Iron Law section), but all 13 existing agents render it as a
code-fenced block of short imperative lines — and the cycle's new
glossary-extractor.md correctly followed that universal convention. So
the drift was the template wording, stale relative to every one of its
instances, not the new file. Resolution: align the template to reality
(both spots now say 'a code-fenced block of short imperative lines').
The new agent file was carry-on — 'fixing' it to a numbered list would
have made it the lone deviant among 14 agents, i.e. introducing drift,
not removing it.
- [low] CARRY-ON. README now classes issue/glossary as 'utility skills'
but that taxonomy is not mirrored in issue/SKILL.md's or
glossary/SKILL.md's own frontmatter. Accepted as low-severity: the
invocation-class label is a README-level descriptor; mandating every
skill self-declare its class in frontmatter is gold-plating with no
consumer. Revisit only if a tool starts keying off a per-skill class.
What holds: single-sourcing preserved (the new skill cites
glossary-convention.md and restates no rule; paths.glossary semantics
defer to profile-schema.md); authority consistent across the boss
sentence, the convention, and the skill's Authority section; the
utility-vs-phase distinction held (no claim that glossary is a pipeline
phase); glossary-extractor.md conforms to agent-template.md.
Cycle is drift-clean. Not a milestone close (no milestone fieldtest run;
see docs/pipeline.md § Milestone-close gate).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pins canonical nomenclature per project so terminology does not drift
and LLM-driven work reuses the established term instead of coining a
synonym each session. The glossary rides the existing standing-reading
mechanism — one optional path slot, no new delivery path.
Single-sourcing, to avoid cross-doc drift:
- `paths.glossary` row in profile-schema.md owns the "set => standing
reading for every role; unset => no-op" semantics; agent-template.md
and pipeline.md each carry one referencing sentence, not a restatement.
- glossary-convention.md owns the format (flat per-term blocks: canonical
heading + Avoid line + <=2-sentence definition) and the boss
record-reality-never-invent write-rule; boss/SKILL.md only points to it.
- glossary.md dogfoods the format on the plugin's own vocabulary
(cycle, milestone, iteration, drift, hard-gate).
Write authority: user any time; boss autonomously but only to record
terms already in consistent use or to settle a drift it just resolved —
never to coin. All other roles are read-only consumers.
No executable surface; this repo has no test runner, so each task closed
on a grep presence-assertion against the file it touched. All eight gates
green (T1 3>=3, T2 5, T3 2, T4 1, T5 1, T6 1, T7 2, final sweep present).
Implements docs/specs/2026-05-31-glossary-integration-design.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Establishes the repository structure for the skills plugin:
- README + INSTALL describing the two-layer split (plugin
mechanics vs per-project profile)
- docs/design, profile-schema, pipeline, agent-template covering
the universal discipline constants and the profile slot model
- templates/project-profile.yml as a copy-and-fill starting point
- templates/CLAUDE.md.fragment with the baseline orchestrator
rules a project can import
- install.sh / uninstall.sh wiring skills/ + agents/ into
~/.claude/ via idempotent symlinks
- skills/ and agents/ directories empty except for migration
READMEs; the actual SKILL bodies and agent files migrate
from ~/dev/ailang/skills/ in the next iteration.
No skill or agent runs yet — this commit only stands up the
structure and documents the substitution model.