chore: remove this repo's own committed specs/plans

These four cycles' specs and plans (glossary integration + skill,
milestone-close gate, specify entry path) were self-development
artefacts committed before specs/plans became gitignored working files
(08bc2aa). They are all long shipped and nothing references them.
Remove them from HEAD to match the new convention — git history retains
them, and docs/specs/ + docs/plans/ are now globally gitignored.
This commit is contained in:
2026-07-02 11:38:55 +02:00
parent 08bc2aa027
commit 9ca2c8ab87
8 changed files with 0 additions and 3882 deletions
@@ -1,421 +0,0 @@
# Glossary Integration — Implementation Plan
> **Parent spec:** `docs/specs/2026-05-31-glossary-integration-design.md`
>
> **For agentic workers:** REQUIRED SUB-SKILL: use the
> `implement` skill to run this plan. Steps use `- [ ]`
> checkboxes for tracking.
**Goal:** Add an optional `paths.glossary` profile slot whose file
becomes standing reading for every role, a convention doc that owns
the format and the boss write-rule, and a dogfooded `docs/glossary.md`
for the plugin's own vocabulary.
**Architecture:** The glossary rides the existing standing-reading
mechanism — one optional path slot, no new delivery path. The
"set ⇒ standing reading for every role" semantics are single-sourced
at the `paths.glossary` row in `profile-schema.md`; `agent-template.md`
and `pipeline.md` carry one referencing sentence each. The format and
write-rule live once in `docs/glossary-convention.md`; `boss/SKILL.md`
only points to it.
**Tech Stack:** Markdown docs, one YAML template. No executable
surface — this repo has no test runner, so each task verifies with a
`grep` presence assertion against the file it touched.
---
## Note on verification & the parse gate
This repo ships **no** `.claude/dev-cycle-profile.yml`, so
`commands.test` is empty and `spec_validation` is undeclared. Per the
planner self-review parse gate (`docs/profile-schema.md`
§ `spec_validation`), the inlined blocks here are `markdown` / `yaml`
fences with **no configured parser** — the parse-the-bytes-you-inline
gate is a documented no-op for this plan. Each task therefore closes
on a `grep` assertion whose pattern is named to match ≥1 real line in
the file just written (self-review item 8), not a test-runner result.
---
## Task 1: Create `docs/glossary-convention.md`
The single source for the glossary format, the standing-reading
obligation, and the boss record-reality write-rule. Created first so
later tasks can cross-reference it.
**Files:**
- Create: `docs/glossary-convention.md`
- [ ] **Step 1: Write the convention doc**
Create `docs/glossary-convention.md` with exactly this content (the
outer fence is four backticks so the inner three-backtick format
example below survives — write only the inner content to the file):
````markdown
# Glossary convention
A project's glossary pins canonical nomenclature so terminology does
not drift over time, and so that LLM-driven work reuses the
established term for a concept instead of coining a fresh synonym each
session. This file owns the format, the reading obligation, and the
write discipline; an individual project's glossary is an instance of
this convention.
## Where it lives
A project opts in by setting `paths.glossary` in its
`.claude/dev-cycle-profile.yml` (see `profile-schema.md` § `paths`).
When the slot is set, the file it names is standing reading for every
role — no separate `standing_reading.always` entry is required. When
the slot is unset, the whole feature is a documented no-op.
## Format
The glossary is a flat list of per-term blocks (not a table), so an
appended entry produces a clean line-wise diff. Each block has exactly
three fields:
1. a level-3 heading naming the **canonical term** to use;
2. an **Avoid:** line listing known synonyms that must NOT be used;
3. a definition of at most two sentences.
```
### canonical-term
**Avoid:** synonym-one, synonym-two
A definition of at most two sentences.
```
A term with no known synonyms still carries an `**Avoid:** —` line so
every block has the same three-field shape.
## Reading obligation
Every skill and agent reads the glossary as part of its standing
reading and, when producing prose or naming a concept, uses the
canonical term and avoids the listed synonyms. If a concept is not
listed, reuse the closest existing term — do not silently coin a new
one.
## Extending the glossary (user + boss only)
The user may edit the glossary at any time. In a `/boss` session the
orchestrator may extend it autonomously — but only to **record
reality, never to invent**:
- A term already used consistently across shipped artefacts but not
yet listed → add it, with its known synonyms under **Avoid**.
- A drift the orchestrator just resolved (two terms for one concept)
→ record the winner as the canonical entry, the loser under
**Avoid**.
The orchestrator never coins a brand-new term into the glossary: a
term earns its entry by already being in consistent use. All other
skills and agents are read-only consumers of the glossary.
````
- [ ] **Step 2: Verify the three load-bearing parts are present**
Run: `grep -c -e '## Format' -e 'reality, never to invent' -e 'standing reading' docs/glossary-convention.md`
Expected: a count of at least `3` (the format section, the
record-reality rule, and the reading obligation are all present).
The `reality, never to invent` pattern matches the unwrapped line in
the verbatim content (the words `record reality` are split across a
line break, so a `record reality` pattern would spuriously miss).
---
## Task 2: Create `docs/glossary.md` (dogfood)
The plugin's own glossary, proving the format on real vocabulary.
Content is lifted verbatim from the spec's primary artefact (spec
lines 58-92).
**Files:**
- Create: `docs/glossary.md`
- [ ] **Step 1: Write the dogfood glossary**
Create `docs/glossary.md` with exactly this content:
```markdown
# Glossary
Canonical nomenclature for this project. Use the **canonical term**;
never use a term under **Avoid**. If you need a concept that is not
listed here, reuse the closest existing term — do not silently coin
a new one. New entries are added only to record nomenclature already
in consistent use; see `glossary-convention.md`.
---
### cycle
**Avoid:** release, epic, round, sprint
One round in the pipeline graph (design → plan → execute → review →
close). Not the top-level container — that is a *milestone*.
### milestone
**Avoid:** epic, phase, big-ticket
A tracker container spanning potentially many cycles; closes only
when its promised work is complete and functional. A cycle close is
never a milestone close.
### iteration
**Avoid:** sprint, story, step
The default sub-unit of a cycle; one pass through the inner loop. A
project may rename it via `vocabulary.subcycle`.
### drift
**Avoid:** divergence, rot, skew
Accumulated mismatch between the codebase and its design ledger.
Surfaced by the architect agent at audit, not by any synonym check.
### hard-gate
**Avoid:** checkpoint, barrier, blocker
A pipeline point that forbids downstream work until an artefact
exists and is approved (e.g. an approved spec before any plan).
```
- [ ] **Step 2: Verify every entry conforms to the three-field shape**
Run: `grep -c '^\*\*Avoid:\*\*' docs/glossary.md`
Expected: `5` (one Avoid line per term: cycle, milestone, iteration,
drift, hard-gate).
---
## Task 3: Document the slot in `docs/profile-schema.md`
Add the `glossary` row to the `paths` table (single source for the
"set ⇒ standing reading" semantics) and a referencing sentence in the
`standing_reading` section.
**Files:**
- Modify: `docs/profile-schema.md:13` (paths table) and `:152`
(standing_reading tail)
- [ ] **Step 1: Add the `glossary` row after the `plan_dir` row**
Exact-string replace this anchor:
```
| `plan_dir` | string | `docs/plans` | Where the planner skill writes plans. |
```
with:
```
| `plan_dir` | string | `docs/plans` | Where the planner skill writes plans. |
| `glossary` | string | (unset) | Canonical-nomenclature file (optional). If set, it is standing reading for every role — no separate `standing_reading.always` entry is needed; unset is a documented no-op. See `glossary-convention.md`. |
```
- [ ] **Step 2: Add the cross-reference sentence at the end of `standing_reading`**
Exact-string replace this anchor (end of the `standing_reading`
section, just before `## \`git\``):
```
Entries may be shell commands as well as file paths — they are
read as opaque strings the agent should fetch / execute, e.g.
`"git log -10 --format=full"`.
## `git`
```
with:
```
Entries may be shell commands as well as file paths — they are
read as opaque strings the agent should fetch / execute, e.g.
`"git log -10 --format=full"`.
A set `paths.glossary` is implicitly appended to every role's
`always` list — it does not need its own entry here. The slot's
authoritative semantics live at the `paths` row above.
## `git`
```
- [ ] **Step 3: Verify both edits landed**
Run: `grep -c 'glossary' docs/profile-schema.md`
Expected: a count of `2` (the new `paths` table row line, and the one
new sentence line in the `standing_reading` section). `grep -c` counts
matching lines, so the table row counts once even though it names the
glossary twice.
---
## Task 4: Add the commented slot to `templates/project-profile.yml`
**Files:**
- Modify: `templates/project-profile.yml:9` (paths block)
- [ ] **Step 1: Insert the commented `glossary` line after `plan_dir`**
Exact-string replace this anchor:
```
spec_dir: docs/specs
plan_dir: docs/plans
# design_ledger: design/INDEX.md # optional
```
with:
```
spec_dir: docs/specs
plan_dir: docs/plans
# glossary: docs/glossary.md # optional — if set, read as
# standing reading by every role
# design_ledger: design/INDEX.md # optional
```
- [ ] **Step 2: Verify the commented slot is present**
Run: `grep -c 'glossary: docs/glossary.md' templates/project-profile.yml`
Expected: `1`.
---
## Task 5: Add the standing-reading sentence to `docs/agent-template.md`
**Files:**
- Modify: `docs/agent-template.md:125` (Standing reading list section)
- [ ] **Step 1: Append the `paths.glossary` sentence to the standing-reading paragraph**
Exact-string replace this anchor:
```
and passes the resolved list to the agent via the carrier. The
agent's body says, prosaically: "Read everything in the standing
reading list before doing anything else."
The agent file itself does not hardcode file paths.
```
with:
```
and passes the resolved list to the agent via the carrier. The
agent's body says, prosaically: "Read everything in the standing
reading list before doing anything else."
A set `paths.glossary` is implicitly part of `always`, so every role
reads the project glossary without a per-role entry (see
`profile-schema.md` § `paths`).
The agent file itself does not hardcode file paths.
```
- [ ] **Step 2: Verify the sentence landed**
Run: `grep -c 'paths.glossary' docs/agent-template.md`
Expected: `1`.
---
## Task 6: Add the standing-reading sentence to `docs/pipeline.md`
`pipeline.md` does not currently mention standing reading; the
natural home is the tail of the "Pipeline configuration" section,
which already cross-references the profile.
**Files:**
- Modify: `docs/pipeline.md:178` (end of Pipeline configuration)
- [ ] **Step 1: Append the glossary sentence after the configuration cross-reference**
Exact-string replace this anchor (the final line of the file):
```
See `profile-schema.md` for the syntax.
```
with:
```
See `profile-schema.md` for the syntax.
If the profile sets `paths.glossary`, that file is standing reading
for every role — the canonical-nomenclature source every skill and
agent consults (see `glossary-convention.md`). Unset, it is a no-op.
```
- [ ] **Step 2: Verify the sentence landed**
Run: `grep -c 'paths.glossary' docs/pipeline.md`
Expected: `1`.
---
## Task 7: Add the cross-reference pointer to `boss/SKILL.md`
Boss gets a pointer to the convention's write-rule in two places: the
loop (Step 4) and the Cross-references list. No rule text is
duplicated.
**Files:**
- Modify: `boss/SKILL.md` (Step 4 loop area; Cross-references section)
- [ ] **Step 1: Add the write-rule pointer after the Step-4 decision bullets**
Exact-string replace this anchor:
```
fieldtest green and stays a deliberate manual act (see
`../docs/pipeline.md` § Milestone-close gate).
### Step 5 — On done-state: Notify
```
with:
```
fieldtest green and stays a deliberate manual act (see
`../docs/pipeline.md` § Milestone-close gate).
If a term-drift is resolved during the loop — two names collapsed to
one, or a settled term not yet listed — record it in the project
glossary per `../docs/glossary-convention.md`: record reality, never
invent. This is the only glossary write authority outside the user.
### Step 5 — On done-state: Notify
```
- [ ] **Step 2: Add the Cross-references bullet**
Exact-string replace this anchor:
```
- **Queue:** the URL configured under `git.issue_tracker.url` in
the profile; CLI command at `git.issue_tracker.list_cmd`.
- **Downstream skills dispatched:** `../brainstorm`,
```
with:
```
- **Queue:** the URL configured under `git.issue_tracker.url` in
the profile; CLI command at `git.issue_tracker.list_cmd`.
- **Glossary write-rule:** `../docs/glossary-convention.md` —
record-reality discipline for the only autonomous glossary writer.
- **Downstream skills dispatched:** `../brainstorm`,
```
- [ ] **Step 3: Verify both pointers landed**
Run: `grep -c 'glossary-convention.md' boss/SKILL.md`
Expected: `2`.
---
## Final acceptance sweep
- [ ] **Step 1: Confirm all spec acceptance criteria are covered**
Run: `ls docs/glossary.md docs/glossary-convention.md && grep -l 'glossary' docs/profile-schema.md templates/project-profile.yml docs/agent-template.md docs/pipeline.md boss/SKILL.md`
Expected: both new files listed, and all five modified files reported
as containing `glossary`.
-506
View File
@@ -1,506 +0,0 @@
# glossary skill — Implementation Plan
> **Parent spec:** `docs/specs/2026-05-31-glossary-skill-design.md`
>
> **For agentic workers:** REQUIRED SUB-SKILL: use the `implement`
> skill to run this plan. Steps use `- [ ]` checkboxes for tracking.
**Goal:** Add a `glossary` utility skill (two procedures — maintain and
bootstrap) plus its dedicated read-only `glossary-extractor` agent, and
wire three single-sentence references, so a project can build and
conformance-check its glossary.
**Architecture:** A new top-level `glossary/` skill directory (picked up
by `install.sh`'s existing glob) holding `SKILL.md` (mode dispatch
`maintain | bootstrap`) and `agents/glossary-extractor.md`
(template-conforming, read-only). The skill applies the rules in
`docs/glossary-convention.md` and restates none. Three referencing edits
in `boss/SKILL.md`, `docs/glossary-convention.md`, and `README.md`.
**Tech Stack:** Markdown skill + agent files; docs/prose-only repo, no
test runner — every task closes on a `grep` presence-assertion against
the touched file, each calibrated against a verified zero baseline.
---
**Files this plan creates or modifies:**
- Create: `glossary/SKILL.md` — the mode-dispatch utility skill.
- Create: `glossary/agents/glossary-extractor.md` — read-only per-slice prose extractor.
- Modify: `boss/SKILL.md:131` — append the bootstrap bounce-back sentence to the glossary-write paragraph.
- Modify: `docs/glossary-convention.md:66` — append the one-line tooling pointer to § Extending.
- Modify: `README.md:17,28` — reword the count-pinned framing line; add a utility-skills note after the table.
Read-only references (not edited): `docs/glossary.md` (collision-scan
example), `docs/profile-schema.md` § `paths` (slot semantics),
`docs/agent-template.md` (agent skeleton), `install.sh` (glob covers the
new dir — AC 8, no edit).
---
### Task 1: `glossary/SKILL.md`
**Files:**
- Create: `glossary/SKILL.md`
- [ ] **Step 1: Create the directory and write the skill file**
Create `glossary/SKILL.md` with exactly this content:
````markdown
---
name: glossary
description: Use when adding, changing, or removing a glossary entry (maintain), or building a new glossary for an existing project from its prose surface (bootstrap). The skill applies the rules in docs/glossary-convention.md — it restates none of them. maintain keeps the existing user-any-time / boss-record-reality write authority and adds a conformance check; bootstrap is user-only (high-context multi-agent work; boss may recommend it via bounce-back but never runs it).
---
# glossary — build and maintain a project's glossary
> **Violating the letter of these rules is violating the spirit.**
## Overview
A project's glossary pins canonical nomenclature so terminology does not
drift over time, and so LLM-driven work reuses the established term for a
concept instead of coining a fresh synonym each session.
`../docs/glossary-convention.md` owns the rules — the three-field format,
the reading obligation, the record-reality write-rule, and the
glossary-as-source-of-truth declaration. This skill is the *procedure*
that applies those rules; it restates none of them.
It carries two procedures. **maintain** adds, changes, or removes a
single entry under a conformance check. **bootstrap** builds a fresh
glossary for a project that has none, by fanning out read-only
`glossary-extractor` agents over the project's prose surface and
synthesising their observations into conforming entries.
## When to Use / Skipping
Triggers:
- **maintain** — a term is to be added, changed, or removed in an
existing glossary, by the user any time, or by boss to record reality
(a term already in consistent use, or a drift boss just resolved).
- **bootstrap** — a project has terminology to pin but no glossary
(`paths.glossary` unset, or naming an empty file), and the user invokes
the build.
Skip or refuse:
- maintain asked with no `paths.glossary` slot set: there is nowhere to
write. Stop and instruct the user to set `paths.glossary` (see
`../docs/profile-schema.md` § `paths`) first.
- bootstrap asked on a glossary that already has entries: do not clobber.
Stop with the entry count and recommend maintain.
- bootstrap asked in a boss (autonomous) session: refuse. bootstrap is
user-only; boss may recommend it via bounce-back but never runs it (see
Authority).
## Authority
maintain inherits the existing write authority unchanged
(`../docs/glossary-convention.md` § Extending): the user any time; boss
autonomously but only to record reality, never to invent. This skill adds
the conformance check around that authority; it does not widen it.
bootstrap is **user-only**. It is high-context multi-agent work analogous
to a fresh `brainstorm`, which boss bounces back rather than starting
autonomously. In a boss session, recommend a bootstrap via bounce-back
when a project lacks a glossary and drift is visible — do not run one.
## Mode dispatch
On invocation, route on the argument:
- `maintain` (or `add` / `change` / `remove`) → the maintain procedure.
- `bootstrap` → the bootstrap procedure (user-only).
If the mode is ambiguous, ask once; do not guess.
## The maintain procedure
1. **Read the glossary and the convention.** Read the file named by
`paths.glossary` and `../docs/glossary-convention.md`. If
`paths.glossary` is unset, stop (see When to Use / Skipping).
2. **Take the proposed entry.** A canonical-term heading, an `**Avoid:**`
line, and a definition — the user's, or (in a boss session bound by
record-reality) the term already in consistent use.
3. **Run the local conformance check** against the proposed entry and the
rest of the glossary:
- the three-field shape the convention defines;
- the definition is at most two sentences;
- collision scan: the proposed canonical term must not already sit
under another entry's **Avoid**, and a proposed **Avoid** synonym
must not be another entry's canonical term.
On any failure, REJECT — name the violated rule, do not write the
entry, and ask for a corrected one.
4. **Run the stale-usage sweep** (on add / change / rename): grep the
prose surface for the old canonical term (change/rename) and for each
**Avoid** synonym, and report the hits as drift the user may want to
fix. The sweep reports; it does not block — guidance, not enforcement.
5. **Write the conforming entry UNSTAGED.** Add, edit, or remove the
entry in the glossary file, preserving the flat per-term-block shape so
the diff stays line-wise clean. Leave it unstaged for review.
6. **Hand back** to the user for review. In a boss session, the
record-reality discipline governs whether the write was permitted at
all (boss never coins).
## The bootstrap procedure (user-only)
1. **Guard.** Read `paths.glossary`. If it names a file that already has
entries, stop with the count and recommend maintain. If the slot is
unset, continue, and note the build will also propose setting the slot
(see `../docs/profile-schema.md` § `paths`).
2. **Partition the prose surface into slices** — the readable prose of
the project: `docs/`, `README.md`, the design ledger (if
`paths.design_ledger` is set), the spec directory. One slice per
coherent group, sized so a single agent can sweep it.
3. **Fan out one `glossary-extractor` per slice.** Dispatch the read-only
agent (`agents/glossary-extractor.md`) with the carrier: the slice and
the extraction task. Agents do not nest; the skill curates each
carrier.
4. **Merge and cluster.** Collect the reports. Cluster variants that name
the same concept across slices, summing frequencies.
5. **Synthesise.** For each cluster:
- a clear cluster (one dominant variant) → auto-include it as a
conforming entry: canonical heading = the dominant variant,
**Avoid** = the other variants, a ≤2-sentence definition drawn from
the observed usage;
- a contested cluster (≥2 comparable variants) → surface it to the user
with the variants, frequencies, and locations, and ask which is
canonical. Never decide a contested canonical yourself.
6. **Handle the unresolved.** A contested cluster the user does not
resolve is left OUT of the glossary and noted as deferred. Never coin a
term to fill a gap.
7. **Assemble UNSTAGED.** Write the conforming glossary to
`paths.glossary` (proposing the slot value if it was unset), in the
convention's flat per-term-block format. Leave it unstaged for review.
## Iron Law
```
THE CONVENTION OWNS THE RULES; THIS SKILL ONLY APPLIES THEM — RESTATE NOTHING.
A NON-CONFORMING ENTRY IS REJECTED, NOT WRITTEN.
BOOTSTRAP IS USER-ONLY. NEVER COIN A TERM — RECORD REALITY.
```
## Handoff Contract
| Direction | Carrier |
|-----------|---------|
| user → glossary (maintain) | the proposed entry + the operation (add / change / remove) |
| user → glossary (bootstrap) | the build request |
| glossary → glossary-extractor (bootstrap) | one prose slice + the extraction task |
| boss → user (bounce-back) | a recommendation to run a bootstrap; boss never runs one itself |
## Common Rationalisations
| Excuse | Reality |
|--------|---------|
| "The entry is obviously fine, skip the conformance check" | The check is the skill's whole reason to exist over hand-editing. Run it. |
| "Two variants are close; I'll pick the more frequent as canonical" | A contested cluster is a nomenclature judgement that belongs to the user. Surface it; do not decide it. |
| "The concept clearly needs a term, I'll coin one" | The glossary records reality, never invents. An unresolved concept is left out and deferred. |
| "boss is running and the project has no glossary, I'll bootstrap it" | bootstrap is user-only. Recommend it via bounce-back; do not run it. |
| "I'll restate the format here so the skill is self-contained" | The convention is the single source for the rules. Cite it; restating it is the cross-doc drift this split exists to prevent. |
| "The stale-usage hits should block the write" | The sweep is guidance, not enforcement. Report the drift; write the entry regardless. |
## Red Flags — STOP
- About to write a non-conforming entry instead of rejecting it.
- About to pick a canonical term for a genuinely contested cluster.
- About to coin a term for a concept that has no observed term.
- About to run a bootstrap in a boss / autonomous session.
- About to restate the convention's format or write-rule in this file.
- About to clobber a populated glossary with a bootstrap.
## Cross-references
- **Rules (the single source):** `../docs/glossary-convention.md` —
format, reading obligation, write-rule, glossary-as-SoT. This skill
applies these; it restates none.
- **Slot semantics:** `../docs/profile-schema.md` § `paths` — the
`paths.glossary` slot (set ⇒ standing reading for every role; unset ⇒
no-op).
- **Agent dispatched:** `agents/glossary-extractor.md` — read-only
per-slice prose extraction, fanned out in bootstrap.
- **Glossary instance (dogfood):** `../docs/glossary.md` — this plugin's
own glossary.
- **boss write authority:** `../boss/SKILL.md` — the record-reality rule
for the only autonomous glossary writer, and the bootstrap bounce-back.
````
- [ ] **Step 2: Verify the file is present and conforming**
Run: `grep -c "BOOTSTRAP IS USER-ONLY" glossary/SKILL.md`
Expected: `1` (the Iron-Law fence line; baseline before this task: file does not exist).
Run: `grep -c "^## The bootstrap procedure (user-only)$" glossary/SKILL.md`
Expected: `1` (the bootstrap-procedure heading is present).
Run: `grep -c "^name: glossary$" glossary/SKILL.md`
Expected: `1` (frontmatter `name` slug is correct).
---
### Task 2: `glossary/agents/glossary-extractor.md`
**Files:**
- Create: `glossary/agents/glossary-extractor.md`
- [ ] **Step 1: Create the agents directory and write the agent file**
Create `glossary/agents/glossary-extractor.md` with exactly this content:
````markdown
---
name: glossary-extractor
description: Read-only per-slice prose extractor for glossary bootstrap. Sweeps one slice of a project's prose surface and reports the recurring domain-concept terms and their competing synonyms as actually written, with frequencies and locations. Coins nothing; dispatched fan-out by the glossary skill's bootstrap procedure.
tools: Read, Glob, Grep, Bash
---
> Violating the letter of these rules is violating the spirit.
## What this role is for
This role exists to prevent an orchestrator from sweeping a whole
project's prose in its own context to coin a glossary — which blows the
context window, conflates orchestration with execution, and tempts
invention over observation. The extractor sweeps exactly one assigned
slice, reports the concept terms and competing variants it actually
finds, and coins nothing. The glossary skill fans out one extractor per
slice and merges their reports.
## Standing reading list
Read everything in the standing reading list passed in the carrier before
doing anything else. A set `paths.glossary` is part of every role's
standing reading, and `docs/glossary-convention.md` defines what a
glossary-worthy concept term is versus incidental vocabulary — consult it
so you report concepts, not every capitalised word.
## Carrier contract
| Field | Content |
|-------|---------|
| `slice` | the one prose region this agent sweeps (e.g. `docs/`, `README.md`) — do not read outside it |
| `task` | the extraction instruction: recurring domain-concept terms and their competing synonyms, as actually written |
You receive the carrier inline in the dispatch prompt. Do NOT widen your
sweep beyond the assigned slice; another extractor covers the rest.
## Iron Law
```
REPORT TERMS YOU OBSERVE IN THE SLICE. NEVER COIN A TERM.
EVERY REPORTED VARIANT CARRIES A FREQUENCY AND AT LEAST ONE LOCATION.
SWEEP ONLY THE ASSIGNED SLICE.
A CANONICAL CHOICE IS NOT YOURS TO MAKE — REPORT VARIANTS, NOT A WINNER.
```
## The Process
1. Read the standing reading list, then `docs/glossary-convention.md` for
what counts as a concept term.
2. Enumerate the files in the assigned slice (`Glob` / `ls`).
3. Sweep for recurring domain-concept terms: nouns and noun-phrases that
name a project concept and recur across the slice. Use `grep -c` for
frequencies and `grep -n` for locations.
4. Cluster variants that name the same concept within the slice (e.g.
"design ledger" / "design index"). Do not decide which is canonical.
5. Drop incidental vocabulary: terms that appear once, generic English,
and code identifiers that are not concept names.
6. Emit the report in the format below. If the slice yields no recurring
concept terms, say so — fabricate nothing.
## Status protocol
| Status | Meaning |
|--------|---------|
| `DONE` | The slice was swept; the report lists every recurring concept term found (possibly none). |
| `PARTIAL` | The slice was too large to finish; report what was swept and name the unswept files. |
| `BLOCKED` | The slice could not be read (missing path, permission). Explanation in the report. |
| `NEEDS_CONTEXT` | The carrier is ambiguous (no slice, or an unreadable task). |
This is a read-only role: it writes no files under any status.
## Output format
Plain text, word-budgeted. One block per concept:
```
- concept: <short concept label>
variants: [<variant> (<count>x), <variant> (<count>x), ...]
locations: [<path:line>, <path:line>, ...]
```
End with a one-line `Swept: <n> files in <slice>` summary. On an empty
slice, emit `No recurring concept terms found in <slice>.`
## Common Rationalisations
| Excuse | Reality |
|--------|---------|
| "This concept obviously needs a canonical term, I'll mark one" | Picking the canonical is the skill's job (and the user's for contested clusters). Report variants, not a winner. |
| "There's a clearly better word the project should use" | You report what is written, not what should be. Coining is forbidden. |
| "The neighbouring slice has related terms, let me peek" | Sweep only your slice. Another extractor covers the rest; merging is the skill's job. |
| "This term appears once but feels important" | A single occurrence is not a recurring concept. Drop it, or the merge fills with noise. |
| "I'll skip frequencies, the list is enough" | Frequencies are how the skill tells a clear cluster from a contested one. Every variant carries a count. |
## Red Flags — STOP
- About to write or edit any file.
- About to report a term that does not appear in the slice.
- About to name a canonical winner instead of listing variants.
- About to read files outside the assigned slice.
- About to report a variant with no frequency or no location.
````
- [ ] **Step 2: Verify the agent file is present and conforming**
Run: `grep -c "NEVER COIN A TERM" glossary/agents/glossary-extractor.md`
Expected: `1` (the Iron-Law fence line; baseline before this task: file does not exist).
Run: `grep -c "^name: glossary-extractor$" glossary/agents/glossary-extractor.md`
Expected: `1` (frontmatter slug correct).
Run: `grep -c "^tools: Read, Glob, Grep, Bash$" glossary/agents/glossary-extractor.md`
Expected: `1` (read-only tool set, AC 2).
---
### Task 3: `boss/SKILL.md` — bootstrap bounce-back sentence
**Files:**
- Modify: `boss/SKILL.md:131`
- [ ] **Step 1: Append the bootstrap sentence to the glossary-write paragraph**
Find this exact line (`boss/SKILL.md:131`, the tail of the Step-4
glossary-write paragraph):
```
invent. This is the only glossary write authority outside the user.
```
Replace it with:
```
invent. This is the only glossary write authority outside the user.
Building a glossary from scratch (the `glossary` skill's bootstrap) is
*not* this authority — it is high-context, user-only work; when a project
lacks a glossary and drift is visible, recommend a bootstrap via
bounce-back, never run one autonomously.
```
This keeps maintain-by-boss (record-reality) and bootstrap (user-only)
consistent with the existing "only glossary write authority outside the
user" claim on the same line.
- [ ] **Step 2: Verify the sentence landed**
Run: `grep -c "bootstrap" boss/SKILL.md`
Expected: `≥1` (verified baseline before this task: `0`).
---
### Task 4: `docs/glossary-convention.md` — tooling pointer
**Files:**
- Modify: `docs/glossary-convention.md:66`
- [ ] **Step 1: Append the tooling pointer to § Extending**
Find this exact line (`docs/glossary-convention.md:66`, the last line of
the file / § Extending):
```
skills and agents are read-only consumers of the glossary.
```
Append immediately after it (new paragraph at the section tail):
```
skills and agents are read-only consumers of the glossary.
The `glossary` skill (`../glossary/SKILL.md`) is the executable procedure
for building and extending a glossary under these rules: this file stays
the rules, the skill applies them.
```
- [ ] **Step 2: Verify the pointer landed**
Run: `grep -c "glossary/SKILL.md" docs/glossary-convention.md`
Expected: `≥1` (verified baseline before this task: `0`; `glossary/SKILL.md`
is a contiguous token, no line-wrap risk).
---
### Task 5: `README.md` — list glossary, reconcile the stale framing
**Files:**
- Modify: `README.md:17` (the count-pinned framing line)
- Modify: `README.md:28` (append a utility-skills note after the table)
- [ ] **Step 1: Reword the count-pinned framing line**
Find this exact line (`README.md:17`):
```
Eight skills, each with the agents it primarily dispatches:
```
Replace it with (count-free, since the table omits the existing utility
skill `issue` and now also `glossary`):
```
The pipeline skills, each with the agents it primarily dispatches:
```
- [ ] **Step 2: Add a utility-skills note after the skill table**
Find the last table row (`README.md:28`):
```
| `boss` | User types `/boss` | autonomous-orchestrator session — dispatches the other skills until done-state or bounce-back | User-invoked, never auto-dispatched |
```
Append immediately after it (a blank line, then the note):
```
| `boss` | User types `/boss` | autonomous-orchestrator session — dispatches the other skills until done-state or bounce-back | User-invoked, never auto-dispatched |
Two further **utility skills** are invoked on demand rather than as
pipeline phases: `issue` (file or update a tracker item) and `glossary`
(build or maintain the project glossary — see `docs/glossary-convention.md`).
```
- [ ] **Step 3: Verify the listing change landed**
Run: `grep -c "glossary" README.md`
Expected: `≥1` (verified baseline before this task: `0`).
Run: `grep -c "utility skills" README.md`
Expected: `≥1` (the reconciled framing names the utility-skill class; baseline: `0`).
---
### Final sweep
- [ ] **Step F1: All new and changed surfaces present**
Run:
```
test -f glossary/SKILL.md && \
test -f glossary/agents/glossary-extractor.md && \
grep -q "bootstrap" boss/SKILL.md && \
grep -q "glossary/SKILL.md" docs/glossary-convention.md && \
grep -q "glossary" README.md && \
echo ALL_PRESENT
```
Expected: `ALL_PRESENT`
- [ ] **Step F2: install.sh glob covers the new skill (AC 8, no edit needed)**
Run: `bash -n install.sh && grep -c 'SKILL.md' install.sh`
Expected: `bash -n` exits 0 (installer still parses) and the glob gate on
`SKILL.md` is present (`≥1`); confirms the new `glossary/` dir with its
`SKILL.md` + `agents/` subdir is linked with no installer change.
@@ -1,732 +0,0 @@
# Milestone-close gate Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Make `audit` unable to imply a milestone is finished — separate `cycle` (a pipeline round) from `milestone` (a tracker container closed only when complete ∧ functional), and add a milestone-wide fieldtest as the closing gate.
**Architecture:** Documentation/skill-file change across the plugin. The milestone-close gate is defined **once** in `docs/pipeline.md`; `audit`, `fieldtest`, `boss` reference it without restating it (single-source, matching the repo's recent carrier/handoff single-sourcing). The milestone fieldtest is a carrier-scope variant of the existing `fieldtest` skill — its carrier contract is extended in the authoritative agent file. The root conflation `cycle ≡ milestone` is corrected in `README.md`, `templates/project-profile.yml`, and `docs/profile-schema.md`.
**Tech Stack:** Markdown skill/agent files; YAML profile template. No code. "Tests" are `grep` assertions over file content and a YAML parse check — the observable verification this repo admits. Each task: a RED check that pins the current state, the edit(s), a GREEN check that confirms the new state, then a commit.
**Spec:** `docs/specs/2026-05-31-milestone-close-gate-design.md`
**Scope note:** The spec's edit list named seven files. This plan adds an eighth — `fieldtest/agents/fieldtester.md` — because the carrier contract the spec references (`milestone_promise`) lives there authoritatively; documenting the variant in `fieldtest/SKILL.md` without defining it in the agent file would be a dangling reference. Task 2 covers it.
**Task order rationale:** `docs/pipeline.md` first (it is the single source the others reference); then the fieldtester agent (single source of the carrier contract); then the referencing skills; then the vocabulary/profile layer; then a final cross-file verification sweep.
---
### Task 1: `docs/pipeline.md` — the single-source gate definition
**Files:**
- Modify: `docs/pipeline.md` (ASCII graph lines 10 & 15; new sections after the graph, before `## Phase descriptions`)
- [ ] **Step 1: RED — confirm the conflated wording and the absence of the gate**
Run:
```bash
cd ~/dev/skills
grep -n "\[cycle close\]\|--(clean)-+" docs/pipeline.md
grep -c "Milestone-close gate\|Cycle vs. milestone" docs/pipeline.md
```
Expected: the first grep prints the two ASCII lines (`[cycle close]` and `--(clean)-+`); the second prints `0` (neither new section exists yet).
- [ ] **Step 2: Relabel the cycle-close ASCII node**
In `docs/pipeline.md`, replace:
```
[cycle close]
```
with:
```
[cycle close — a loop step, not a milestone close]
```
- [ ] **Step 3: Rename the audit `clean` edge to `drift-clean`**
In `docs/pipeline.md`, replace:
```
--(clean)-+
```
with:
```
--(drift-clean)-+
```
- [ ] **Step 4: Add the two single-source sections**
In `docs/pipeline.md`, immediately after the closing ``` ``` of the ASCII diagram (the line before `## Phase descriptions`), insert:
```markdown
## Cycle vs. milestone
These are two distinct axes, and conflating them is a bug.
- A **cycle** is one round in the pipeline graph above
(`brainstorm → planner → implement → audit → [fieldtest]`).
A cycle close is an internal loop step.
- A **milestone** is a tracker container (Gitea milestone,
GitHub milestone, Linear project — whatever the project's
tracker calls a long-running work scope). A milestone spans
potentially many cycles and closes only when the work it
promised is **complete and functional** (see the gate below).
`audit` runs at cycle close and proves *drift-clean* — the code
matches the design ledger. It is blind to whether the work is
*functional* from a downstream consumer's point of view; that is
what `fieldtest` measures. So no `audit` result closes a
milestone, and neither does a `/boss` done-state.
## Milestone-close gate
A milestone may be closed in the tracker only when **both** legs
hold:
1. **Complete** — every cycle filed under the milestone is
`audit` drift-clean (or its drift explicitly ratified), and
the milestone container has no open iterations / issues left.
2. **Functional** — the **milestone fieldtest** has run its
curated end-to-end scenarios against the milestone's promise
and its status roll-up is `clean`: every scenario
demonstrably delivers what the milestone promised; no open
`bug` findings; `friction` / `spec_gap` findings resolved or
ratified into the design ledger.
The milestone fieldtest is the milestone-wide variant of the
`fieldtest` skill: the same fieldtester agent, a carrier scoped
to the milestone's promise rather than one cycle's surface. Its
scenarios are chosen top-down from what the milestone as a whole
promised, not assembled as the union of per-cycle axes.
A milestone whose entire scope is internal (no user-visible
surface) is exempt from the functional leg — the milestone
fieldtest is *not applicable* and the complete leg suffices.
This gate defines *when* a milestone is closeable. The actual
close stays a deliberate human / orchestrator act (`tea
milestone close`, or the tracker equivalent); no skill performs
it automatically.
```
- [ ] **Step 5: GREEN — confirm the rename and the new sections**
Run:
```bash
cd ~/dev/skills
grep -n "a loop step, not a milestone close\|--(drift-clean)-+" docs/pipeline.md
grep -c "## Milestone-close gate" docs/pipeline.md
grep -c "## Cycle vs. milestone" docs/pipeline.md
grep -n "\-\-(clean)-+" docs/pipeline.md || echo "OK: no bare clean edge remains"
```
Expected: first grep prints both relabelled lines; the two `grep -c` print `1`; the last prints `OK: no bare clean edge remains`.
- [ ] **Step 6: Commit**
```bash
cd ~/dev/skills
git add docs/pipeline.md
git commit -m "docs(pipeline): single-source the milestone-close gate
Define the cycle/milestone distinction and the complete-and-functional
close gate once in pipeline.md; rename audit's cycle-close edge to
drift-clean so it no longer reads as a milestone close."
```
---
### Task 2: `fieldtest/agents/fieldtester.md` — milestone-scope carrier variant
**Files:**
- Modify: `fieldtest/agents/fieldtester.md` (Carrier contract section, after line 73)
- [ ] **Step 1: RED — confirm the carrier knows only the cycle scope**
Run:
```bash
cd ~/dev/skills
grep -c "milestone_promise\|Milestone-scope variant" fieldtest/agents/fieldtester.md
```
Expected: `0` (no milestone carrier variant defined).
- [ ] **Step 2: Add the milestone-scope variant to the carrier contract**
In `fieldtest/agents/fieldtester.md`, immediately after the line:
```
both are also empty, return `NEEDS_CONTEXT`.
```
(the last line of the empty-`axis_hints` fallback, before `## The Iron Law`), insert:
```markdown
### Milestone-scope variant
When dispatched as the **milestone fieldtest** — the closing
gate for a tracker milestone (see `../../docs/pipeline.md`
§ Milestone-close gate) — the carrier is scoped to the
milestone's promise rather than one cycle's surface:
| Field | Content |
|-------|---------|
| `milestone_id` | e.g. `milestone-7` |
| `milestone_promise` | the milestone's stated goal / acceptance from the tracker (and its spec, if one exists) — what the work as a whole promises to deliver |
| `commit_range` | `<milestone-start>..HEAD` |
In this mode, Phase 1 derives 2-4 **curated end-to-end
scenarios top-down from `milestone_promise`** — each scenario a
realistic downstream task that, run end to end, demonstrates the
milestone delivers what it promised. Do **not** assemble the
scenarios as the union of per-cycle axes; the per-cycle
fieldtests already covered axis-local surface. There is no
`axis_hints` fallback in this mode: if `milestone_promise` is
empty, infer it from the milestone's spec / tracker entry, and
if that is also empty, return `NEEDS_CONTEXT`.
```
- [ ] **Step 3: GREEN — confirm the variant exists and references the gate**
Run:
```bash
cd ~/dev/skills
grep -n "### Milestone-scope variant" fieldtest/agents/fieldtester.md
grep -n "milestone_promise" fieldtest/agents/fieldtester.md
grep -n "docs/pipeline.md.*Milestone-close gate" fieldtest/agents/fieldtester.md
```
Expected: each grep prints at least one matching line.
- [ ] **Step 4: Commit**
```bash
cd ~/dev/skills
git add fieldtest/agents/fieldtester.md
git commit -m "fieldtester: add milestone-scope carrier variant
Authoritative carrier contract for the milestone fieldtest: scoped to
milestone_promise, scenarios derived top-down rather than as a union of
per-cycle axes."
```
---
### Task 3: `fieldtest/SKILL.md` — document the milestone fieldtest variant
**Files:**
- Modify: `fieldtest/SKILL.md` (new section after the Overview ending at line 35, before `## When to Use / Skipping`; Cross-references block)
- [ ] **Step 1: RED — confirm the skill documents only the per-cycle scope**
Run:
```bash
cd ~/dev/skills
grep -c "milestone fieldtest\|Two scopes" fieldtest/SKILL.md
```
Expected: `0`.
- [ ] **Step 2: Add a "Two scopes" section after the Overview**
In `fieldtest/SKILL.md`, immediately before the line `## When to Use / Skipping`, insert:
```markdown
## Two scopes: per-cycle and milestone
`fieldtest` runs at two scopes, both using the same fieldtester
agent — the carrier picks the scope:
- **Per-cycle fieldtest** (the default this file otherwise
describes): dispatched after a surface-touching cycle's audit,
carrier scoped to that cycle (`cycle_id` / `cycle_scope`).
Catches cycle-local friction early. Optional / orchestrator
judgement, as below.
- **Milestone fieldtest**: the closing gate for a tracker
milestone. Carrier scoped to the milestone's promise
(`milestone_id` / `milestone_promise`); the fieldtester
derives curated end-to-end scenarios top-down from that
promise and proves the shipped implementation delivers it. Its
green status roll-up is required before a surface-touching
milestone may be closed.
Both carriers are defined authoritatively under **Carrier
contract** in `agents/fieldtester.md` (the milestone variant
under its **Milestone-scope variant** sub-heading). The gate the
milestone fieldtest feeds is defined once in
`../docs/pipeline.md` § Milestone-close gate — not restated
here. The milestone fieldtest is skippable on the same terms as
the per-cycle one, lifted to milestone level: a milestone whose
entire scope is internal (no user-visible surface) is exempt.
```
- [ ] **Step 3: Add a gate cross-reference to the Cross-references block**
In `fieldtest/SKILL.md`, find the `**Upstream gate:**` bullet:
```
- **Upstream gate:** `../audit/SKILL.md` runs first;
fieldtest comes after a clean (or ratified) audit.
```
Replace it with:
```
- **Upstream gate:** `../audit/SKILL.md` runs first;
fieldtest comes after a clean (or ratified) audit.
- **Closing gate it feeds:** `../docs/pipeline.md`
§ Milestone-close gate — the milestone fieldtest's green
roll-up is the functional leg of that gate.
```
- [ ] **Step 4: GREEN — confirm both additions**
Run:
```bash
cd ~/dev/skills
grep -n "## Two scopes: per-cycle and milestone" fieldtest/SKILL.md
grep -n "Closing gate it feeds" fieldtest/SKILL.md
```
Expected: each grep prints one matching line.
- [ ] **Step 5: Commit**
```bash
cd ~/dev/skills
git add fieldtest/SKILL.md
git commit -m "fieldtest: document the milestone fieldtest variant
Name the per-cycle vs milestone scopes; the milestone fieldtest feeds
the functional leg of the milestone-close gate (single-sourced in
pipeline.md)."
```
---
### Task 4: `audit/SKILL.md` — drift-gate wording and the milestone red flag
**Files:**
- Modify: `audit/SKILL.md` (Step 2 table line 74; carry-on path lines 107-110; Red Flags list)
- [ ] **Step 1: RED — confirm "Audit can close" and no milestone red flag**
Run:
```bash
cd ~/dev/skills
grep -n "Audit can close" audit/SKILL.md
grep -c "milestone" audit/SKILL.md
```
Expected: first grep prints the Step 2 table line; the count is `0`.
- [ ] **Step 2: Reword the green-exit row to a drift gate**
In `audit/SKILL.md`, replace:
```
| `0` | Green | All metrics within tolerance vs. the script's baseline. Audit can close. |
```
with:
```
| `0` | Green | All metrics within tolerance vs. the script's baseline. The cycle's drift gate is clear (drift-clean, not a milestone close — see `../docs/pipeline.md` § Milestone-close gate). |
```
- [ ] **Step 3: Annotate the carry-on commit body as drift-clean**
In `audit/SKILL.md`, replace:
```
- **carry-on path:** the audit-close commit body says
`cycle <X> tidy (clean)` and ratifies whatever the
regression check drove. Audit commits always exist at cycle
close — they carry the architect findings, the regression
numbers, and the resolution.
```
with:
```
- **carry-on path:** the audit-close commit body says
`cycle <X> tidy (clean)` and ratifies whatever the
regression check drove. Here `clean` means *drift-clean* —
the cycle's code matches the ledger; it is **not** a milestone
close, which additionally requires a green milestone fieldtest
(see `../docs/pipeline.md` § Milestone-close gate). Audit
commits always exist at cycle close — they carry the architect
findings, the regression numbers, and the resolution.
```
- [ ] **Step 4: Add the milestone red flag**
In `audit/SKILL.md`, in the `## Red Flags — STOP` list, after the line:
```
- "We'll re-run after the holidays" without a dated backlog issue
```
add:
```
- Declaring a milestone closeable on the strength of an
audit-clean while the milestone fieldtest has not run green —
audit proves drift-clean, never functional (see
`../docs/pipeline.md` § Milestone-close gate)
```
- [ ] **Step 5: GREEN — confirm all three edits**
Run:
```bash
cd ~/dev/skills
grep -n "drift-clean, not a milestone close" audit/SKILL.md
grep -n "Here \`clean\` means \*drift-clean\*" audit/SKILL.md
grep -n "Declaring a milestone closeable" audit/SKILL.md
grep -n "Audit can close" audit/SKILL.md || echo "OK: stale wording gone"
```
Expected: the first three print a line each; the last prints `OK: stale wording gone`.
- [ ] **Step 6: Commit**
```bash
cd ~/dev/skills
git add audit/SKILL.md
git commit -m "audit: clarify clean means drift-clean, not milestone close
Reword the green-exit row, annotate the carry-on commit body, and add a
red flag: an audit-clean never licenses closing a milestone — that needs
a green milestone fieldtest (gate in pipeline.md)."
```
---
### Task 5: `boss/SKILL.md` — done-state references the gate
**Files:**
- Modify: `boss/SKILL.md` (Done-state bullet, lines 120-121)
- [ ] **Step 1: RED — confirm done-state restates the formula locally**
Run:
```bash
cd ~/dev/skills
grep -n "audit clean, fieldtest clean if applicable" boss/SKILL.md
grep -c "Milestone-close gate\|not an automatic milestone close" boss/SKILL.md
```
Expected: first grep prints the done-state line; the count is `0`.
- [ ] **Step 2: Point done-state at the single-source gate**
In `boss/SKILL.md`, replace:
```
- **Done-state** — queue is empty AND the cycle is fully
ratified (audit clean, fieldtest clean if applicable). Go to
Step 5.
```
with:
```
- **Done-state** — queue is empty AND the cycle is fully
ratified (audit drift-clean, fieldtest clean if applicable).
Go to Step 5. A `/boss` done-state means this run has nothing
left to dispatch; it is **not** an automatic milestone close —
closing a tracker milestone needs its end-to-end milestone
fieldtest green and stays a deliberate manual act (see
`../docs/pipeline.md` § Milestone-close gate).
```
- [ ] **Step 3: GREEN — confirm the reference**
Run:
```bash
cd ~/dev/skills
grep -n "not an automatic milestone close" boss/SKILL.md
grep -n "docs/pipeline.md.*Milestone-close gate" boss/SKILL.md
```
Expected: each grep prints one matching line.
- [ ] **Step 4: Commit**
```bash
cd ~/dev/skills
git add boss/SKILL.md
git commit -m "boss: done-state is not a milestone close
Reference the single-source gate; a /boss done-state means the queue is
empty, not that the tracker milestone may be closed."
```
---
### Task 6: `README.md` — fix the root cycle≡milestone conflation
**Files:**
- Modify: `README.md` (lines 30-32; the `fieldtest` table row line 26)
- [ ] **Step 1: RED — confirm the conflation and the bare "Optional" row**
Run:
```bash
cd ~/dev/skills
grep -n "AILang calls a cycle a \*milestone\*" README.md
grep -n "surface-touching cycle | example fixtures" README.md
```
Expected: both grep print their respective lines.
- [ ] **Step 2: Rewrite the vocabulary paragraph to separate the axes**
In `README.md`, replace:
```
Vocabulary is configurable. AILang calls a cycle a *milestone*
and a sub-cycle an *iteration*; your project may call them
*release* and *sprint*, or *epic* and *story*, or whatever fits.
```
with:
```
Vocabulary is configurable. A **cycle** is one round in the
pipeline graph; your project may call it a *release*, an *epic*,
or whatever fits, and its sub-unit (the default *iteration*) a
*sprint* or a *story*. A **milestone** is a distinct, higher
axis — a tracker container (Gitea/GitHub milestone, Linear
project) that spans potentially many cycles and closes only when
the work it promised is complete *and* functional (see
`docs/pipeline.md` § Milestone-close gate). A cycle close is a
loop step; it is never a milestone close.
```
- [ ] **Step 3: Nuance the `fieldtest` table row**
In `README.md`, replace:
```
| `fieldtest` | Orchestrator-dispatched post-audit, surface-touching cycle | example fixtures + friction spec | Optional |
```
with:
```
| `fieldtest` | Orchestrator-dispatched post-audit | example fixtures + friction spec | Per-cycle optional; milestone fieldtest is the closing gate for a surface-touching milestone |
```
- [ ] **Step 4: GREEN — confirm the conflation is gone**
Run:
```bash
cd ~/dev/skills
grep -n "calls a cycle a \*milestone\*" README.md || echo "OK: conflation removed"
grep -n "A \*\*milestone\*\* is a distinct, higher" README.md
grep -n "milestone fieldtest is the closing gate" README.md
```
Expected: first prints `OK: conflation removed`; the other two print a line each.
- [ ] **Step 5: Commit**
```bash
cd ~/dev/skills
git add README.md
git commit -m "docs(readme): cycle is not a milestone
Separate the pipeline-round axis (cycle) from the tracker-container axis
(milestone); note the milestone fieldtest as the closing gate."
```
---
### Task 7: `templates/project-profile.yml` — vocabulary and pipeline phase
**Files:**
- Modify: `templates/project-profile.yml` (vocabulary block lines 40-43; pipeline block lines 66-74)
- [ ] **Step 1: RED — confirm the wrong comment and missing milestone slots**
Run:
```bash
cd ~/dev/skills
grep -n "what a top-level work unit is called" templates/project-profile.yml
grep -c "milestone" templates/project-profile.yml
```
Expected: first grep prints the `cycle:` comment line; the count is `0`.
- [ ] **Step 2: Fix the vocabulary block**
In `templates/project-profile.yml`, replace:
```
vocabulary:
cycle: cycle # what a top-level work unit is called
subcycle: iteration # what a sub-unit is called
ledger_entry: contract # what one design-ledger entry is called
```
with:
```
vocabulary:
cycle: cycle # one round in the pipeline graph (NOT the top-level container)
subcycle: iteration # a sub-unit of a cycle
milestone: milestone # tracker container spanning many cycles; closes only when complete AND functional
ledger_entry: contract # what one design-ledger entry is called
```
- [ ] **Step 3: Add the milestone-fieldtest phase to the pipeline block**
In `templates/project-profile.yml`, replace:
```
# fieldtest: { boss_only: true, when: surface_touch }
```
with:
```
# fieldtest: { boss_only: true, when: surface_touch } # per-cycle usability test
# milestone_fieldtest: { boss_only: true, when: surface_touch, gates_close: milestone } # closing gate: end-to-end proof of the milestone's promise
```
- [ ] **Step 4: GREEN — confirm the slots and that the YAML still parses**
Run:
```bash
cd ~/dev/skills
grep -n "milestone: milestone" templates/project-profile.yml
grep -n "milestone_fieldtest" templates/project-profile.yml
python3 -c "import yaml,sys; yaml.safe_load(open('templates/project-profile.yml')); print('YAML OK')"
```
Expected: first two grep print a line each; the python prints `YAML OK` (commented lines do not affect the parse, and the active vocabulary block stays valid).
- [ ] **Step 5: Commit**
```bash
cd ~/dev/skills
git add templates/project-profile.yml
git commit -m "profile: add milestone vocabulary slot and milestone_fieldtest phase
Correct the cycle comment (a cycle is a pipeline round, not the
top-level container); add the milestone tracker-container slot and a
commented milestone_fieldtest phase that gates the milestone close."
```
---
### Task 8: `docs/profile-schema.md` — schema doc for the new slots
**Files:**
- Modify: `docs/profile-schema.md` (vocabulary table line 130; pipeline example lines 184-186; minimal-profile example line 213)
- [ ] **Step 1: RED — confirm the same conflation in the schema doc**
Run:
```bash
cd ~/dev/skills
grep -n "What a top-level work unit is called" docs/profile-schema.md
grep -n " cycle: milestone" docs/profile-schema.md
grep -c "milestone_fieldtest" docs/profile-schema.md
```
Expected: the first two grep print their lines (the table row and the minimal-profile example); the count is `0`.
- [ ] **Step 2: Fix the vocabulary table row and add the milestone row**
In `docs/profile-schema.md`, replace:
```
| `cycle` | string | `cycle` | What a top-level work unit is called. Examples: `milestone`, `release`, `epic`. |
| `subcycle` | string | `iteration` | What a sub-unit is called. Examples: `iteration`, `sprint`, `story`. |
```
with:
```
| `cycle` | string | `cycle` | One round in the pipeline graph (NOT the top-level container). Examples: `cycle`, `release`, `epic`. |
| `subcycle` | string | `iteration` | A sub-unit of a cycle. Examples: `iteration`, `sprint`, `story`. |
| `milestone` | string | `milestone` | Tracker container spanning many cycles; closes only when complete AND functional (see `pipeline.md` § Milestone-close gate). Examples: `milestone`, `epic`, `release`. |
```
- [ ] **Step 3: Fix the minimal-profile example so it stops equating cycle with milestone**
In `docs/profile-schema.md`, replace:
```
vocabulary:
cycle: milestone
subcycle: iteration
```
with:
```
vocabulary:
cycle: cycle
subcycle: iteration
```
- [ ] **Step 4: Document the milestone-fieldtest phase in the pipeline section**
In `docs/profile-schema.md`, in the `## pipeline` fenced YAML example, replace:
```
fieldtest:
boss_only: true # only orchestrator dispatches
when: surface_touch # condition tag (orchestrator judgement)
```
with:
```
fieldtest:
boss_only: true # only orchestrator dispatches
when: surface_touch # condition tag (orchestrator judgement)
milestone_fieldtest:
boss_only: true
when: surface_touch # end-to-end proof of the milestone's promise
gates_close: milestone # its green roll-up is the functional leg of the milestone-close gate
```
- [ ] **Step 5: GREEN — confirm the schema doc is consistent**
Run:
```bash
cd ~/dev/skills
grep -n "One round in the pipeline graph (NOT the top-level container)" docs/profile-schema.md
grep -n "| \`milestone\` | string" docs/profile-schema.md
grep -n "gates_close: milestone" docs/profile-schema.md
grep -n "^ cycle: milestone" docs/profile-schema.md || echo "OK: minimal example no longer equates cycle with milestone"
```
Expected: the first three print a line each; the last prints the `OK:` message.
- [ ] **Step 6: Commit**
```bash
cd ~/dev/skills
git add docs/profile-schema.md
git commit -m "docs(schema): document milestone slot and milestone_fieldtest phase
Correct the cycle vocabulary description, add the milestone container
slot, fix the minimal-profile example, and document the
milestone_fieldtest phase that gates the milestone close."
```
---
### Task 9: Final cross-file verification sweep
**Files:** none modified — verification only.
- [ ] **Step 1: No file still equates cycle with milestone**
Run:
```bash
cd ~/dev/skills
grep -rn "calls a cycle a \*milestone\*\|top-level work unit\|^ cycle: milestone" \
README.md docs/ templates/ audit/ fieldtest/ boss/ \
&& echo "FAIL: stale conflation remains" || echo "OK: no conflation remains"
```
Expected: `OK: no conflation remains`.
- [ ] **Step 2: The gate is defined once and referenced, not restated**
Run:
```bash
cd ~/dev/skills
echo "definition (expect exactly 1, in pipeline.md):"
grep -rln "^## Milestone-close gate" docs/ audit/ fieldtest/ boss/ README.md
echo "references (expect audit, fieldtest, boss, README, profile-schema):"
grep -rln "Milestone-close gate" docs/ audit/ fieldtest/ boss/ README.md
```
Expected: the definition list contains exactly `docs/pipeline.md`; the reference list additionally contains `audit/SKILL.md`, `fieldtest/SKILL.md`, `boss/SKILL.md`, `README.md`, `docs/profile-schema.md`.
- [ ] **Step 3: The milestone carrier is single-sourced in the agent file**
Run:
```bash
cd ~/dev/skills
echo "carrier definition (expect fieldtester.md):"
grep -rln "### Milestone-scope variant" fieldtest/
echo "milestone_promise mentions:"
grep -rln "milestone_promise" fieldtest/
```
Expected: the variant heading appears only in `fieldtest/agents/fieldtester.md`; `milestone_promise` appears in both `fieldtest/agents/fieldtester.md` and `fieldtest/SKILL.md` (the skill references the field, the agent defines it).
- [ ] **Step 4: The profile template still parses**
Run:
```bash
cd ~/dev/skills
python3 -c "import yaml; yaml.safe_load(open('templates/project-profile.yml')); print('YAML OK')"
```
Expected: `YAML OK`.
- [ ] **Step 5: No commit needed** — this task only verifies. If any check fails, return to the owning task and fix before proceeding.
---
## Notes for the executor
- This repo commits directly on a working branch (`milestone-close-gate`); do not open PRs unless asked. `main` is sacrosanct — never reset/revert it.
- All prose is English (repo rule: anything committed is English).
- There is no build/test toolchain here; the `grep`/YAML checks above are the verification. Do not invent a test runner.
- Single-source discipline is the spine of this change: if a check in Task 9 shows the gate defined in more than one place, the fix is to replace the duplicate with a reference to `docs/pipeline.md`, not to keep both.
File diff suppressed because it is too large Load Diff
@@ -1,252 +0,0 @@
# Glossary Integration — Design Spec
**Date:** 2026-05-31
**Status:** Draft — awaiting user spec review
**Authors:** orchestrator + Claude
## Goal
Give consuming projects a single, canonical place that pins
nomenclature so terminology does not drift over time, and so that
LLM-driven work reuses the established term for a concept instead of
coining a fresh synonym each session. The glossary is **guidance,
not enforcement**: it becomes standing reading for every skill and
agent, but no tool scans artefacts for forbidden synonyms.
The plugin stays mechanics-only. This cycle adds:
1. an optional profile slot `paths.glossary`,
2. a convention doc that owns the glossary format and the write
discipline,
3. standing-reading wiring so a set `paths.glossary` is read by
every role automatically,
4. a boss write-rule (record reality, never invent),
5. a dogfooded `docs/glossary.md` in this repo proving the format
on the plugin's own vocabulary.
## Architecture
The glossary rides the **existing standing-reading mechanism**
rather than introducing a new delivery path. One optional path slot
carries the whole feature:
- `paths.glossary` (optional). **If set, the file it points to is
automatically standing reading for every agent** — no separate
`standing_reading.always` entry is required. If unset, the whole
feature is a documented no-op, exactly matching the plugin's
existing "missing optional slot = silent skip" contract.
Semantics ("set ⇒ standing reading for all roles") live in
`docs/profile-schema.md` next to the slot, so the wiring is
single-sourced and a project cannot set the path yet forget to make
it read.
The format and the write discipline live in a new
`docs/glossary-convention.md`, following the established
`docs/`-doc pattern (`pipeline.md`, `profile-schema.md`). Skills and
`boss` cross-reference it rather than restating it.
## Concrete code shapes
### 1. The delivered `docs/glossary.md` (dogfood — primary artefact)
This is the actual file the feature produces, shown on the plugin's
own vocabulary. Per-term blocks (not a table) so boss-appended
entries produce clean line-wise diffs.
```markdown
# Glossary
Canonical nomenclature for this project. Use the **canonical term**;
never use a term under **Avoid**. If you need a concept that is not
listed here, reuse the closest existing term — do not silently coin
a new one. New entries are added only to record nomenclature already
in consistent use; see `docs/glossary-convention.md`.
---
### cycle
**Avoid:** release, epic, round, sprint
One round in the pipeline graph (design → plan → execute → review →
close). Not the top-level container — that is a *milestone*.
### milestone
**Avoid:** epic, phase, big-ticket
A tracker container spanning potentially many cycles; closes only
when its promised work is complete and functional. A cycle close is
never a milestone close.
### iteration
**Avoid:** sprint, story, step
The default sub-unit of a cycle; one pass through the inner loop. A
project may rename it via `vocabulary.subcycle`.
### drift
**Avoid:** divergence, rot, skew
Accumulated mismatch between the codebase and its design ledger.
Surfaced by the architect agent at audit, not by any synonym check.
### hard-gate
**Avoid:** checkpoint, barrier, blocker
A pipeline point that forbids downstream work until an artefact
exists and is approved (e.g. an approved spec before any plan).
```
### 2. The profile slot (worked author example)
What a consuming project writes — one line opts the whole project
in:
```yaml
# <project>/.claude/dev-cycle-profile.yml
paths:
spec_dir: docs/specs
plan_dir: docs/plans
glossary: docs/glossary.md # optional — if set, every agent reads
# it as standing reading
code_roots: [src]
```
### 3. The boss write-rule (lives in `docs/glossary-convention.md`)
`boss/SKILL.md` carries only a cross-reference pointer; the rule
text itself is single-sourced here:
```markdown
## Extending the glossary (user + boss only)
The user may edit the glossary at any time. In a `/boss` session the
orchestrator may extend it autonomously — but only to **record
reality, never to invent**:
- A term already used consistently across shipped artefacts but not
yet listed → add it, with its known synonyms under **Avoid**.
- A drift the orchestrator just resolved (two terms for one concept)
→ record the winner as the canonical entry, the loser under
**Avoid**.
The orchestrator never coins a brand-new term into the glossary: a
term earns its entry by already being in consistent use. All other
skills and agents are read-only consumers of the glossary.
```
### Implementation shape (secondary — before → after)
**`templates/project-profile.yml`**, `paths:` block:
```yaml
# before
paths:
spec_dir: docs/specs
plan_dir: docs/plans
# design_ledger: design/INDEX.md # optional
code_roots: [src]
# after
paths:
spec_dir: docs/specs
plan_dir: docs/plans
# glossary: docs/glossary.md # optional — if set, read as
# standing reading by every role
# design_ledger: design/INDEX.md # optional
code_roots: [src]
```
**`docs/profile-schema.md`**, `paths` section: add a `glossary`
entry documenting the slot AND the "set ⇒ standing reading for all
roles" semantics, and a no-op-when-unset note.
**`docs/agent-template.md`** and **`docs/pipeline.md`**: where
standing reading is described, add one sentence: a set
`paths.glossary` is part of every role's standing reading.
**`boss/SKILL.md`**: add a short pointer (in the process/loop and a
cross-reference entry) to `docs/glossary-convention.md` for the
record-reality write-rule. No rule text duplicated.
## Components
- **`docs/glossary.md`** (new) — dogfooded glossary for the plugin's
own vocabulary; the lived proof of the format.
- **`docs/glossary-convention.md`** (new) — single source for the
format (three fields: canonical term, Avoid synonyms, ≤2-sentence
definition), the standing-reading obligation, and the boss
record-reality write-rule.
- **`paths.glossary` slot** — in `templates/project-profile.yml`
(commented) and `docs/profile-schema.md` (documented).
- **Standing-reading wiring** — one sentence each in
`docs/agent-template.md` and `docs/pipeline.md`.
- **`boss/SKILL.md`** — cross-reference pointer to the convention.
## Data flow
Author/consume:
1. A project sets `paths.glossary: docs/glossary.md` and writes the
file using the convention's three-field block format.
2. Every dispatched skill/agent, per the standing-reading contract,
reads the glossary alongside `CLAUDE.md` and the git-log entries.
3. When producing prose or naming a concept, the role uses the
canonical term and avoids the listed synonyms.
Extend (boss):
1. In `/boss`, when the orchestrator observes a term already in
consistent use but unlisted, or has just resolved a two-term
drift, it appends/edits one block per the convention.
2. The edit is an ordinary working-tree change committed under the
only-orchestrator-commits rule; no separate gate.
Unset:
- No `paths.glossary` ⇒ standing reading omits it, the convention
doc is inert reference, boss has nothing to extend. Documented
no-op.
## Error handling
- **Slot set but file missing:** a role that cannot read the
glossary treats it as it treats any missing standing-reading
source — notes the gap, proceeds; this is a profile error for the
project to fix, not a plugin failure.
- **Boss tempted to invent:** guarded by the convention's
red-flag/rationalisation framing ("a term earns its entry by
already being in use"); mirrors the existing boss anti-invention
discipline.
- **Convention vs. glossary drift:** the convention owns format and
rule; `docs/glossary.md` is an instance. The dogfood file is
expected to conform and serves as the conformance example.
## Testing strategy
This is a docs/profile cycle with no executable surface; the plugin
has no test runner (`commands.test` is empty for this repo). The
acceptance evidence is therefore the concrete artefacts above plus
two manual conformance checks:
1. **Dogfood conformance:** every block in `docs/glossary.md` has
exactly the three fields the convention mandates (canonical term
heading, **Avoid:** line, ≤2-sentence definition).
2. **No-op proof:** the wording added to `profile-schema.md`,
`agent-template.md`, and `pipeline.md` states the unset-slot case
so a profile without `glossary` provably skips the feature.
No fenced block in this spec targets a configured `spec_validation`
parser (this repo declares none); the parse-every-block gate is a
documented no-op here.
## Acceptance criteria
- `paths.glossary` documented in `docs/profile-schema.md` (slot +
"set ⇒ standing reading" semantics + unset no-op) and present
commented in `templates/project-profile.yml`.
- `docs/glossary-convention.md` exists and owns: the three-field
format, the standing-reading obligation, and the boss
record-reality write-rule (with the never-invent guard).
- `docs/agent-template.md` and `docs/pipeline.md` each state that a
set `paths.glossary` is standing reading for every role.
- `boss/SKILL.md` cross-references the convention for the write-rule
without duplicating its text.
- `docs/glossary.md` exists, dogfoods the plugin vocabulary, and
every entry conforms to the three-field format.
- With no `paths.glossary` set, the feature is a provable no-op.
@@ -1,299 +0,0 @@
# glossary skill — Design Spec
**Date:** 2026-05-31
**Status:** Draft — awaiting user spec review
**Authors:** orchestrator + Claude
## Goal
Give the plugin an executable procedure for a project's glossary. Today
`docs/glossary-convention.md` declares the rules (three-field format,
reading obligation, the boss record-reality write-rule, glossary-as-SoT)
and `docs/glossary.md` dogfoods them — but nothing *does* anything. Two
gaps follow:
- **No way to build a glossary for an existing project.** The convention
assumes a glossary already exists and is hand-maintained. A project
with terminology drift but no glossary has no on-ramp.
- **Hand-maintenance has no conformance check.** A user (or boss) adding
a term can silently break the three-field shape, exceed the
two-sentence limit, or collide with another entry (a new **Avoid**
synonym that is some other entry's canonical term, or vice versa).
The `glossary` skill closes both gaps with one skill carrying two
procedures: **maintain** (guided, conformance-checked add / change /
remove of a single entry) and **bootstrap** (a fan-out of read-only
extraction agents that build a fresh glossary from a project's prose
surface). The skill is the executable procedure; the convention stays
the rules. The skill never restates the convention's format or
write-rule — it points to it and applies it.
## Architecture
`glossary` is a **utility skill**, invoked on demand like `issue` — not a
pipeline phase. It does **not** appear in the `design → plan → implement
→ audit` loop, takes no `pipeline:` profile entry, and gates nothing.
It lives at `glossary/` with the standard layout:
- `glossary/SKILL.md` — a mode dispatch at the head (`maintain` |
`bootstrap`) followed by the two procedures.
- `glossary/agents/glossary-extractor.md` — one dedicated, read-only,
template-conforming agent.
`install.sh` links any top-level directory with a `SKILL.md` (and its
`agents/` subdir) by glob; the new skill and agent are picked up with no
change to the installer.
**Role split, single-sourced.** `docs/glossary-convention.md` owns the
rules: the three-field format, the reading obligation, the boss
record-reality write-rule, and the glossary-as-source-of-truth
declaration. The `glossary` skill owns the *procedure* that applies those
rules. The skill points to the convention for every rule it enforces and
restates none of them, exactly as `boss/SKILL.md` points to the
convention for the write-rule rather than copying it.
**Authority.**
- *maintain* is governed by the existing write authority unchanged: the
user any time; boss autonomously but only to record reality, never to
invent (`glossary-convention.md` § Extending). The skill adds the
conformance check around that authority; it does not widen it.
- *bootstrap* is **user-only**. It is high-context multi-agent work
analogous to a fresh `brainstorm`, which boss bounces back rather than
starting autonomously. boss MAY recommend a bootstrap via a bounce-back
when a project lacks a glossary and drift is visible, but never runs
one itself.
## Concrete code shapes
### User-facing: a bootstrap run
```
User: /glossary bootstrap
Skill:
1. read paths.glossary → file is unset or empty (else: refuse, see Error handling)
2. partition the prose surface into slices:
docs/, README.md, design-ledger (if paths.design_ledger set), specs/
3. fan out one glossary-extractor per slice (read-only)
4. merge reports → cluster variants of the same concept
5. clear cluster (one dominant variant) → draft entry, auto-included
contested cluster (≥2 comparable variants) → surface to user
6. assemble the conforming glossary, write it UNSTAGED to paths.glossary
7. user reviews the working-tree file
```
### Carrier and report (the glossary-extractor contract)
```
# carrier skill → glossary-extractor
slice: docs/ # the one prose slice this agent sweeps
task: "extract recurring domain-CONCEPT terms and their competing
synonyms as actually written; do NOT coin terms"
# report glossary-extractor → skill (word-budgeted, structured)
- concept: cycle
variants: [cycle (41x), round (6x), sprint (2x)]
locations: [docs/pipeline.md:3, README.md:30]
- concept: design ledger
variants: [design ledger (12x), design index (9x)]
locations: [docs/profile-schema.md:15, docs/specs/...]
```
### Synthesis — a clear cluster becomes a conforming entry automatically
```
### cycle
**Avoid:** round, sprint, release, epic
One round in the pipeline graph (design -> plan -> execute -> review ->
close). Not the top-level container — that is a milestone.
```
### A contested cluster is surfaced, never auto-decided
```
Contested: "design ledger" (12x, docs/) vs "design index" (9x, specs/)
name the same concept. Which is canonical?
[design ledger] [design index] [other]
```
If the user does not resolve it, the concept is left OUT of the glossary
and noted as deferred — never coined.
### User-facing: a maintain run, and the must-reject case
```
User: /glossary add (proposes)
### design ledger
**Avoid:** drift
The canonical specification index ... <three sentences> ...
Skill (local conformance, before writing):
REJECT — two violations, entry not written:
1. definition is 3 sentences; the format allows at most 2.
2. "drift" under **Avoid** is the canonical term of an existing
entry (docs/glossary.md "### drift"). A synonym cannot be
another entry's canonical term.
Fix and resubmit.
```
A conforming add, by contrast, passes the local check, then triggers the
stale-usage sweep:
```
Skill: conformance OK. Stale-usage sweep for the **Avoid** terms:
"design index" still appears at docs/profile-schema.md:15, specs/foo.md:8
→ these are drift you may want to fix; entry written UNSTAGED regardless.
```
### Implementation shape (secondary — what files change)
New files:
- `glossary/SKILL.md` — head: `> Violating the letter...` lead-in,
Overview, When to Use / Skipping, a **Mode dispatch** section routing
`maintain` vs `bootstrap`, then the two numbered procedures, Handoff
Contract, Common Rationalisations, Red Flags, Cross-references.
- `glossary/agents/glossary-extractor.md` — per `docs/agent-template.md`:
frontmatter (`name: glossary-extractor`, third-person description,
`tools: Read, Glob, Grep, Bash`), spirit-letter lead-in, What this role
is for, Standing reading list, Carrier contract, Iron Law, The Process,
Status protocol, Output format, Common Rationalisations, Red Flags.
Edited files (one referencing sentence each — no rule restated):
- `boss/SKILL.md` — in § Direction freedom / Notifications, one sentence:
boss may recommend a bootstrap via bounce-back when a project lacks a
glossary and drift is visible, but never runs one autonomously (it is
high-context work like a fresh brainstorm).
- `docs/glossary-convention.md` — in § Extending, one tooling pointer:
the `glossary` skill is the executable procedure for building and
extending a glossary; this file stays the rules.
- `README.md` — the skill listing is updated to include `glossary` as a
utility skill (like `issue`). Note the current README has **no**
agent-roster note to extend (its "Eight skills" table carries only
Trigger / Output / Mandatory columns), and that "Eight skills" framing
is already stale — it omits the existing utility skill `issue`. The
edit therefore adds `glossary` to the listing and reconciles the
framing so the listing is accurate, rather than appending to a roster
note that does not exist. No agent-roster surface is created — the
agent roster lives in the per-skill `agents/` directories, not in
README.
## Components
### `glossary/SKILL.md`
A mode-dispatch skill. The head routes on the invocation:
- **maintain** — add / change / remove one entry. Steps: (1) read the
glossary and the convention; (2) take the proposed entry; (3) run the
**local conformance check** — three-field shape, definition ≤ 2
sentences, and the collision scan (a proposed canonical term must not
already sit under another entry's **Avoid**; a proposed **Avoid**
synonym must not be another entry's canonical term); reject with the
named rule on failure, do not write; (4) on add / change / rename, run
the **stale-usage sweep** — grep the old canonical and the **Avoid**
synonyms across the prose surface and report the hits as drift the user
may want to fix; (5) write the conforming entry UNSTAGED; (6) hand back
to the user (or, in a boss session, the boss record-reality discipline
governs whether the write was permitted at all).
- **bootstrap** — build a new glossary. Steps as in § Concrete code
shapes: empty/unset check, partition, fan-out, merge + cluster,
auto-include clear winners, surface contested clusters, assemble
UNSTAGED, user review.
The skill restates none of the convention's rules; it cites
`docs/glossary-convention.md` for the format and the write-rule and
`docs/profile-schema.md` § `paths` for the `paths.glossary` semantics.
### `glossary/agents/glossary-extractor.md`
A read-only extraction agent. **Failure mode it exists to prevent:** an
orchestrator sweeping a whole project's prose in its own context to coin
a glossary — blowing context and conflating orchestration with
execution, and tempting invention over observation. The agent sweeps one
slice, reports *observed* concept terms and their competing variants with
frequencies and locations, and coins nothing. The skill fans out one
agent per slice and curates each carrier; agents do not nest (Claude Code
platform constraint).
## Data flow
**maintain.** proposal → local conformance (format, ≤2 sentences,
collision scan) → reject-with-rule on failure / continue on pass → (add /
change / rename) stale-usage sweep → report stale hits → write conforming
entry UNSTAGED → user review. boss-initiated writes stay bound to
record-reality.
**bootstrap.** user invokes → empty/unset guard → partition prose surface
into slices → fan out N × glossary-extractor → merge reports → cluster
variants → clear cluster auto-included as entry / contested cluster
surfaced to user for the canonical choice → unresolved contested cluster
left out (deferred, never coined) → assemble conforming glossary file
UNSTAGED → user review.
## Error handling
- **`paths.glossary` unset.** bootstrap still builds a glossary and
proposes setting the slot (pointing at `docs/profile-schema.md` §
`paths`); maintain has no target and stops, instructing the user to set
the slot first.
- **bootstrap on a populated glossary.** No clobber. The skill stops with
a diagnosis ("glossary already has N entries") and recommends maintain
for incremental work.
- **conformance failure in maintain.** The entry is rejected with the
specific rule cited and is NOT written. (This is the must-fail evidence
for the feature-acceptance criterion: a wrong entry must fail the
check.)
- **glossary-extractor returns empty or BLOCKED.** The skill reports the
empty slice and fabricates no terms — record reality, never invent.
- **contested cluster the user does not resolve.** Left out of the
glossary entirely and noted as deferred. The skill never picks a
canonical term for a genuinely contested cluster on its own.
## Testing strategy
This repo ships no test runner; it is docs / prose only. Following the
glossary-integration cycle precedent, each implementation task closes on
a grep presence-assertion against the file it touches, calibrated against
a verified zero baseline (the `git log` for that cycle records the
mis-calibrated-grep failure mode to avoid: assert against the unwrapped
line, not a pattern that straddles a line break).
The behavioural evidence is the worked examples embedded in § Concrete
code shapes: a conforming entry accepted, a non-conforming entry rejected
with the named rule, and a contested cluster surfaced to the user. These
are the empirical evidence the feature-acceptance criterion demands for a
no-executable-surface infra cycle.
No `spec_validation` parser is configured for this repo, so the
brainstorm parse-every-block gate is a documented no-op here: the fenced
blocks in this spec are illustrative CLI / prose, none carrying a fence
label with a configured parser.
## Acceptance criteria
1. `glossary/SKILL.md` exists with a mode dispatch (`maintain` |
`bootstrap`) and both procedures.
2. `glossary/agents/glossary-extractor.md` exists, conforms to
`docs/agent-template.md`, and is read-only (`tools: Read, Glob, Grep,
Bash`).
3. The skill single-sources against `docs/glossary-convention.md`: it
cites the format and write-rule and restates neither.
4. bootstrap is user-only; `boss/SKILL.md` carries one sentence wiring
the boss-may-recommend-via-bounce-back rule.
5. maintain runs the local conformance check plus the stale-usage sweep;
a non-conforming proposed entry is rejected with the named rule and
not written.
6. bootstrap surfaces contested clusters to the user, auto-includes clear
winners, and never coins a contested canonical term.
7. `README.md`'s skill listing includes `glossary` as a utility skill and
the stale "Eight skills" framing (which omits the existing `issue`
utility skill) is reconciled so the listing is accurate; no
agent-roster note is added (none exists). `docs/glossary-convention.md`
carries a one-line tooling pointer to the skill.
8. `install.sh` links the new skill and agent with no change to the
installer (the existing glob covers them).
@@ -1,241 +0,0 @@
# Milestone-close gate: separating `cycle` from `milestone`
**Date:** 2026-05-31
**Status:** approved (design)
**Topic:** make `audit` unable to imply a milestone is finished;
add a milestone-wide fieldtest as the closing gate.
## Problem
`audit` runs at cycle close and emits a "clean" signal whose
commit body reads `cycle <X> tidy (clean)`. `audit` only proves
*drift-clean* — the code matches the design ledger. It is blind
to whether the work is *functional* from a downstream
consumer's point of view; that is exactly what `fieldtest`
measures, and `fieldtest` runs *after* `audit`.
Two defects follow:
1. **Conflation of `cycle` and `milestone`.** `README.md`
("AILang calls a cycle a *milestone*") and
`templates/project-profile.yml:41` (`cycle: # what a
top-level work unit is called`) treat a cycle as the
top-level work unit. It is not. A **milestone** is a tracker
(Gitea) container that closes only when the work is
*completely implemented and functional*. A **cycle** is one
round in the pipeline graph — a step in the loop. A milestone
spans potentially many cycles.
2. **An audit-clean signal can leak into a milestone close.**
Because `audit`'s "clean" reads like "done", an orchestrator
can be led to close a Gitea milestone on the strength of an
audit, before any fieldtest has demonstrated the work is
functional. No skill closes a milestone today, so this is a
conceptual hazard rather than a code path — but the wording
actively invites the mistake.
The fix is **not** to swap the `audit → fieldtest` order:
`fieldtest` needs the drift-clean state to test against, so
`audit` must stay first. The fix is to **decouple the gate**
`audit`'s "clean" never closes anything, and a separate,
explicitly defined milestone-close gate requires both
completeness and functional validation.
## Conceptual model
### Two distinct axes
- **Cycle** — one round in the pipeline graph
(`brainstorm → planner → implement → audit → [per-cycle
fieldtest]`). A cycle close is an internal loop step. Many
cycles per milestone.
- **Milestone** — a tracker (Gitea) container. Closes **only**
when *complete* (every cycle drift-clean / ratified, no open
iterations) **and** *functional* (milestone fieldtest green).
### Three disentangled "clean" terms
| Term | Owner | Means | Closes a milestone? |
|------|-------|-------|---------------------|
| `drift-clean` | `audit` | code matches the ledger | never |
| cycle functionally validated | per-cycle `fieldtest` | cycle-local surface usable | never |
| milestone closeable | milestone-close gate | complete ∧ functional | yes (manual act) |
### Two fieldtest scopes
The milestone fieldtest is a **scope variant** of the existing
`fieldtest` skill — same `fieldtester` agent, a different
carrier. No new skill; keeps the surface DRY.
- **Per-cycle fieldtest** (existing, unchanged): carrier carries
`cycle_id` / `cycle_scope`; dispatched after a
surface-touching cycle's audit; catches cycle-local friction
early; optional / orchestrator-dispatched as today.
- **Milestone fieldtest** (new variant): carrier carries
`milestone_id` and `milestone_promise` — the milestone's
stated goal / acceptance in the tracker (and its spec, if one
exists). The fieldtester derives a small set of **curated
end-to-end scenarios** that, run as a downstream consumer,
prove the shipped implementation delivers **what the milestone
as a whole promised**. Scenarios are chosen *top-down from the
milestone's promise*, not assembled bottom-up as the
mechanical union of per-cycle axes — the per-cycle fieldtests
already cover axis-local surface; the milestone fieldtest's
job is to demonstrate the promise end to end. Its green status
roll-up is the closing gate.
## The milestone-close gate (authoritative)
A milestone may be closed in the tracker only when **both** legs
hold:
1. **Complete** — every cycle filed under the milestone is
`audit` drift-clean (or its drift explicitly ratified), and
the milestone container has no open iterations / issues
remaining.
2. **Functional** — the milestone fieldtest has run its curated
end-to-end scenarios against the milestone's promise and its
status roll-up is `clean`: every scenario demonstrably
delivers what the milestone promised; no open `bug` findings;
`friction` / `spec_gap` findings either resolved or
explicitly ratified into the design ledger.
No `audit` result, and no `/boss` done-state, closes a milestone
on its own. `/boss` done-state means "this `/boss` run has
nothing left to dispatch" — it is **not** a milestone close.
The actual close (`tea milestone close`, or the tracker
equivalent) stays a **deliberate human / orchestrator act**,
performed only after the gate reads green. This design defines
*when* a milestone is closeable; it does **not** mechanise the
close. (`issue/SKILL.md` is out of scope here.)
### Edge cases
- **Non-surface milestone.** A milestone whose entire scope is
internal (refactor, infra, docs) touches no user-visible
surface. The milestone fieldtest is then *not applicable*
(same skip logic as the per-cycle fieldtest, lifted to
milestone level). The "functional" leg is satisfied vacuously;
the "complete" leg (audit-clean across cycles) suffices.
- **Single-cycle milestone.** Nothing special: the milestone
fieldtest still runs (if surface-touching), proving the
milestone's promise end to end even though that promise
happened to ship in a single cycle. The per-cycle and
milestone fieldtests may coincide in surface but remain
conceptually distinct gates — axis-local validation versus
promise-level proof.
- **Ratified drift.** A cycle whose drift was ratified
(`--update-baseline` + ratify paragraph) counts as satisfying
the "complete" leg for that cycle — ratification is the
documented form of "complete".
## Per-file changes
Single-source discipline (consistent with the recent
carrier/handoff single-sourcing): the gate is **defined once**
in `docs/pipeline.md`; every other file **references** it rather
than restating it, so the files cannot drift.
### `docs/pipeline.md` (single source)
- ASCII graph: rename `audit --(clean)` to `audit
--(drift-clean)`; annotate `[cycle close]` explicitly as a
loop step, not a milestone end.
- New subsection **"Cycle vs. milestone"** — defines the two
axes authoritatively (a milestone spans many cycles; a cycle
is one loop round).
- New subsection **"Milestone-close gate"** — the authoritative
gate definition above (complete ∧ functional), names the
milestone fieldtest as a mandatory precondition for
surface-touching milestones, and states plainly that no
`audit` and no `/boss` done-state closes a milestone.
### `audit/SKILL.md`
- Step 2 table: "Audit can close" → drift-gate wording. `audit`
clears the *cycle drift check*; it does not close the cycle or
the milestone.
- Close-commit wording (`cycle <X> tidy (clean)`): kept, but
annotated explicitly as *drift-clean, not a milestone signal*.
- New **Red Flag**: "Declaring a milestone closeable on the
strength of an audit-clean, while the milestone fieldtest has
not run green." Cross-reference the gate in `docs/pipeline.md`.
- Overview: clarify `audit` ↔ cycle close (never milestone).
### `fieldtest/SKILL.md`
- Document the second trigger variant — the **milestone
fieldtest** (milestone-wide, end-to-end): carrier carries
`milestone_id` and `milestone_promise`; the fieldtester
derives curated end-to-end scenarios from the milestone's
promise (top-down, not a union of per-cycle axes) and proves
the shipped implementation delivers it; its green status
roll-up is the closing gate. Reference the gate in
`docs/pipeline.md` rather than restating it.
- The "audit first" precondition stays, for both variants.
- The milestone-fieldtest skip logic mirrors the per-cycle one,
lifted to milestone level (non-surface milestone → exempt).
### `boss/SKILL.md`
- Done-state: reference the `docs/pipeline.md` gate instead of
restating the formula. Clarify that a `/boss` done-state is
**not** an automatic milestone close — the milestone close
needs the milestone fieldtest green and is a manual act.
### `README.md`
- **Root fix**: correct the `cycle ≡ milestone` conflation
(the "AILang calls a cycle a *milestone*" lines). Cycle = a
pipeline round; milestone = a tracker container spanning many
cycles, closed only when complete ∧ functional.
- `fieldtest` row: per-cycle fieldtest stays optional; note the
milestone fieldtest as the mandatory gate before a
surface-touching milestone closes.
### `templates/project-profile.yml`
- Fix the `cycle:` comment ("top-level work unit" is wrong — a
cycle is the pipeline round).
- Add a `milestone:` vocabulary field for the tracker container.
- Add the milestone-fieldtest phase to the pipeline config (so a
project can name / gate it), consistent with the existing
`pipeline:` configuration model.
### `docs/profile-schema.md`
- Same root conflation lives here: the `vocabulary` table
(`cycle` = "top-level work unit", with `milestone` as an
example value) and the minimal-profile example (`cycle:
milestone`). Correct both — document `cycle` as the pipeline
round and add the `milestone` vocabulary field as the tracker
container.
- Document the milestone-fieldtest phase in the `pipeline`
section alongside the existing `fieldtest` phase.
## Scope boundaries
**In scope:** the gate definition and the wording/decoupling
across `docs/pipeline.md`, `audit`, `fieldtest`, `boss`,
`README.md`, `templates/project-profile.yml`; the milestone
fieldtest as a carrier-scope variant of the existing skill.
**Out of scope:** mechanising the tracker close (no
`issue/SKILL.md` change, no automated `tea milestone close`);
reordering `audit → fieldtest`; any change to the per-cycle
fieldtest's existing behaviour beyond naming it "per-cycle".
## Verification
- Grep sweep: no remaining file equates `cycle` with
`milestone`; the only authoritative gate definition lives in
`docs/pipeline.md`, and `audit` / `fieldtest` / `boss`
reference it without restating it.
- `audit/SKILL.md` carries the new Red Flag and drift-gate
wording; its close-commit example is annotated as drift-clean.
- `fieldtest/SKILL.md` documents both carrier scopes and the
milestone-level skip rule.
- `templates/project-profile.yml` parses (YAML) with the new
`milestone:` vocabulary field and the milestone-fieldtest
phase, and `docs/profile-schema.md` stays consistent with it.
@@ -1,308 +0,0 @@
# `specify` — Spec-Production Entry Path — Design Spec
**Date:** 2026-06-04
**Status:** Draft — awaiting user spec review
**Authors:** orchestrator + Claude
## Goal
Add a third entry path into the dev cycle: a `specify` skill that
produces an approved spec from **given sources** (a long in-context
design discussion, an exhaustive tracker issue, settled design
docs) — with review, but **without an interview**.
The driving observation: when the design is already settled, today's
`brainstorm` forces redundant work — it re-opens an interview and
re-litigates decisions the sources already made. That is friction,
and worse, the re-litigation invites reactive churn on settled
calls. But the *production* half of `brainstorm` — apply the
acceptance criterion, write the spec, parse-gate it, ground-check
it, get user sign-off — is wanted in every case. `specify` is that
production half, callable on its own.
The split is the existing toolchain philosophy applied one level up.
`tdd → implement` and `debug → implement` split a discipline across
two dispatches so the spec stays honest (the test is written before
any implementation). `specify` does the same to design work: a
**deciding** phase (`brainstorm`) and a **producing** phase
(`specify`), split so the producing phase reads the decision as a
*source* rather than making it inline.
## Architecture
Three co-equal entry paths feed one production core. `specify` is
the sole home of the production gates; `brainstorm` becomes an
**optional** discovery front-end.
```
brainstorm ──► specify ──► planner ──► implement design open (discovery + production)
specify ──► planner ──► implement design settled in sources
tdd ─────────────────────► implement (mini) test-specifiable (test = spec)
debug ───────────────────► implement (mini) bug (RED-first)
└── bounce ── specify / tdd unresolved design fork → discovery
```
**The hard-gate moves.** Today `brainstorm` itself is the "no plan
without an approved spec" gate. After this cycle, **`specify`**
carries that invariant (it produces and gets sign-off on the spec,
and gates `planner`); `brainstorm` is no longer itself a gate — it
is the optional discovery stage before `specify`. The universal
invariant — *no plan without an approved spec* — is unchanged
word-for-word; only its carrier moves from `brainstorm` to
`specify`.
**The bounce-back symmetry.** `specify` is a fast path that is only
legitimate when its precondition holds — the sources resolve every
load-bearing design decision. The moment writing the spec would force
a choice between plausible designs the sources do not resolve, it
STOPs and bounces to `brainstorm`. This is structurally identical to
`tdd`'s bounce: `tdd` bounces when one honest assertion cannot pin
the behaviour; `specify` bounces when the sources cannot pin the
design. Both fast paths fall back to the same discovery skill.
**Discovery vs. production, by verb.** `brainstorm` owns *deciding*:
interview, explore 23 approaches, ratify the chosen design with the
user. `specify` owns *producing*: render the decision into the
canonical spec artefact, run all gates, get artefact sign-off. The
two reviews are different: `brainstorm`'s per-section ratification
asks "is this design right?"; `specify`'s Step-8 review asks "is the
written spec faithful and complete?". In the direct path there is no
design ratification (no discovery happened) — only the artefact
review. That absence *is* "with review, but without interview".
## Concrete code shapes
The canonical authoring form for this prose-skill project is the
SKILL.md body and the cross-skill topology. The user-facing artefact
the cycle delivers is `specify/SKILL.md` and the edited dispatch
logic in `boss`.
### `specify/SKILL.md` — the Iron Law (the load-bearing shape)
```
THE SOURCES MUST RESOLVE EVERY LOAD-BEARING DESIGN DECISION BEFORE THE SPEC IS WRITTEN.
IF WRITING THE SPEC FORCES A CHOICE BETWEEN PLAUSIBLE DESIGNS THE SOURCES DO NOT RESOLVE,
STOP AND BOUNCE TO `brainstorm`. DO NOT SILENTLY PICK ONE.
THE PRODUCTION GATES — ACCEPTANCE CRITERION, PARSE-EVERY-BLOCK, GROUNDING-CHECK, USER-REVIEW —
ARE NON-NEGOTIABLE REGARDLESS OF ENTRY PATH.
NO PLAN OR CODE WORK UNTIL THE SPEC HAS BEEN PRESENTED AND THE USER HAS APPROVED IT.
```
### `specify/SKILL.md` — process spine
```
Step 1 Explore / re-ground context
- direct entry: read the sources (issue body, in-context
discussion, design docs) + git log; this IS the design input.
- chain entry (from brainstorm): the ratified design narrative
is in-context; re-ground lightly (fresh git log, touched files).
Step 1.5 PRECONDITION GATE
- enumerate the load-bearing design decisions the spec must encode.
- for each: do the sources resolve it, or am I about to pick one?
- any unresolved fork → BOUNCE to brainstorm (see Error handling).
Step 2 Apply the feature-acceptance criterion + write the concrete code
(the worked user-facing example = the criterion's empirical evidence).
Step 3 Write the spec under paths.spec_dir (mandated structure).
Step 4 Self-review (placeholder / consistency / scope / ambiguity /
concrete-code / parse-every-block gate).
Step 5 Grounding-check (hard-gate) — dispatch read-only grounding-check.
Step 6 User-review gate — spec sits uncommitted; await approval;
on change request re-run Step 4 AND re-dispatch Step 5.
Step 7 Hand off to planner (spec path + iteration scope).
```
`specify` has **no interview step and no approaches step** — those
are `brainstorm`'s. It dispatches the existing `grounding-check`
agent; it introduces **no new agent**.
### `boss` — the three-way Entry-path reflection
```
boss Entry-path reflection (feature work, tdd-enabled profile):
one honest minimal assertion pins the behaviour → tdd [autonomous]
sources resolve every load-bearing decision → specify [autonomous]
writing one assertion / spec forces an unresolved
design choice → brainstorm [bounce-back]
asymmetry: tdd and specify are bounded (no open Q&A) → dispatch autonomously.
brainstorm is high-context discovery the orchestrator cannot
compact on its own → bounce-back before dispatch.
specify in /boss still pauses internally at its Step-6 user-review gate
(problem-state notify: "spec X ready, please sign off") — that is the
final sign-off pause, NOT a pre-dispatch checkpoint.
```
### Implementation shape (secondary — the before → after of each edited file)
```
brainstorm/SKILL.md
- Step 69 (write spec, self-review, grounding-check, user-review, hand off
to planner) ──► REMOVED (moved to specify).
- Step 9 terminal "invoke planner" ──► "hand ratified design to specify".
- Hard-Gate block + "spec before plan" framing ──► removed / re-pointed:
brainstorm is no longer itself the gate.
- Skip rules: brainstorm gains an explicit "optional when design is settled
in sources — that is specify's direct path" clause.
boss/SKILL.md
- Entry-path reflection: two-way ──► three-way (add the specify branch).
- Pipeline ASCII block: add specify node on the brainstorm→planner edge.
- Common Rationalisations / Red Flags: add the "route settled design to
brainstorm to be safe" anti-pattern (mirror of the existing tdd one).
docs/pipeline.md
- ASCII graph: brainstorm ─► specify ─► plan; specify ─► plan direct edge;
specify ─(design fork)─► brainstorm bounce edge.
- Phase descriptions: new `specify` block; brainstorm block trimmed to discovery.
- Skip rules: "brainstorm is never skipped at cycle start" ──► "specify is
never skipped at cycle start; brainstorm is the optional discovery stage
before it, skipped when the design is already settled in the sources".
docs/profile-schema.md, docs/design.md, README.md
- profile-schema pipeline: gates:[planner] moves brainstorm ──► specify;
specify documented as a CORE node (not opt-in, unlike tdd).
- design.md pipeline-form line + README skill table: add specify row,
flip brainstorm's "Mandatory?" cell to optional-discovery.
tdd/SKILL.md
- Cross-references: name specify as the sibling fast path with the same
bounce-to-brainstorm discipline.
```
## Components
- **`specify/SKILL.md` (new).** The production core. Follows the
skill template: Overview, When to Use / Skipping, the Iron Law
(precondition gate + bounce-back + non-negotiable gates), the
numbered process spine above, Handoff Contract, Common
Rationalisations, Red Flags, Cross-references. Dispatches
`grounding-check`; no new agent.
- **`brainstorm/SKILL.md` (edited).** Shrinks to discovery: explore
context, interview, 23 approaches, per-section design
ratification. Terminal state changes from `planner` to `specify`.
The hard-gate language and the spec-writing / self-review /
grounding-check / user-review / planner-handoff steps are removed
(they now live in `specify`). brainstorm no longer writes a spec
file; it hands a ratified design narrative to `specify` in-context.
- **`boss/SKILL.md` (edited).** Entry-path reflection becomes
three-way. `specify` direct-entry is autonomously dispatchable
(bounded, like `tdd`/`debug`), pausing only at its internal
user-review gate. The pre-dispatch bounce-back stays reserved for
a fresh `brainstorm` cycle (high-context) and for a surfaced fork.
- **`tdd/SKILL.md` (edited).** Cross-references gain `specify` as the
sibling fast path sharing the bounce-to-`brainstorm` discipline.
- **`docs/pipeline.md`, `docs/design.md`, `README.md`,
`docs/profile-schema.md` (edited).** Pipeline graph, phase
descriptions, skip rules, skill table, and the profile pipeline
block updated so all four renderings of the pipeline agree on the
three-path shape and on `specify` as the new production gate.
## Data flow
Carrier contracts (the in-context narrative is the carrier where two
skills run in the same orchestrator context — no intermediate
artefact, exactly as `tdd → implement` carries the chat history plus
the RED-test path):
| Direction | Carrier |
|-----------|---------|
| user / issue (design settled) → `specify` | the sources: issue body, in-context design discussion, design docs |
| `brainstorm``specify` | ratified design narrative (approaches chosen, constraints, sections approved) — in-context; brainstorm writes no spec file |
| `specify``grounding-check` (Step 5) | `spec_path` (absolute) + `iteration_scope` — same carrier brainstorm uses today |
| `specify``planner` (Step 7, on PASS or overridden BLOCK) | path to spec + iteration scope |
| `specify``brainstorm` (precondition bounce, or no-override BLOCK route) | the unresolved design question as a cycle request |
| `boss` Entry-path reflection | dispatches `tdd` / `specify` autonomously, or bounces back a fresh `brainstorm` cycle |
## Error handling
- **Precondition fails (Step 1.5).** `specify` finds, while
enumerating the load-bearing decisions, a fork the sources do not
resolve. It STOPs *before writing the spec* and bounces to
`brainstorm` with the design question as a cycle request. The
working tree is clean — nothing was written. This is the cheap,
early bounce (cheaper than `tdd`'s, which may discard a written
test).
- **grounding-check `BLOCK` (Step 5).** Identical failure-mode
procedure to today's `brainstorm`: present the report; on no
override, delete the just-written spec from the working tree, file
a forward backlog issue (or milestone container) naming the
unratified dependency, tell the user, end the session.
- **grounding-check `INFRA_ERROR`.** Abort; spec stays on disk;
debug the workspace out-of-band; re-dispatch.
- **Step-6 change request.** Edit the spec in place (still
uncommitted), re-run Step 4 (self-review) AND re-dispatch Step 5
(grounding-check) — the previous PASS no longer covers the edited
bytes — then return to the review gate.
- **`specify` in `/boss`.** Dispatched autonomously; runs criterion,
parse-gate, and grounding-check without a checkpoint; **pauses at
the Step-6 user-review gate** as a problem-state notify ("spec X
ready, please sign off"). The distinction from `brainstorm`: no
*pre-dispatch* checkpoint (specify is bounded, no interview), only
the final artefact sign-off.
## Testing strategy
This is a prose / Markdown skill repo with no executable test suite
and (currently) no `dev-cycle-profile.yml`. "Tests" are
**internal-consistency** properties, verified by `audit` /
architect drift-review at cycle close:
1. **No path-count drift.** No skill or doc still asserts the
two-path model. Every mention of the entry paths names three.
2. **Pipeline renderings agree.** The pipeline graph in
`docs/pipeline.md`, `README.md`, `docs/design.md`, and `boss`
are mutually consistent on the three-path shape and on `specify`
as the production gate.
3. **`specify/SKILL.md` follows the template.** Iron Law, numbered
process, Handoff Contract, Common Rationalisations, Red Flags,
Cross-references all present.
4. **No orphaned gate language in `brainstorm`.** No leftover
hard-gate / spec-writing / planner-handoff prose; its terminal
state names `specify`.
5. **Carrier contracts close.** Every `specify` carrier has a named
counterpart skill, and every skill that hands to `specify` (user,
brainstorm, boss reflection) is reflected in `specify`'s own
Handoff Contract.
**Note on the Step-5 grounding-check during this very cycle.** Because
this repo has no test suite and no profile, the `grounding-check`
hard-gate is degenerate here — there is nothing green to ratify and
the agent is under-configured. The spec's load-bearing assumptions are
plain SKILL.md content facts (brainstorm's current terminal is planner;
tdd is opt-in; boss has a two-way reflection), read and verified
directly during exploration. The agent is therefore **not dispatched
into the void**; this paragraph is the visible trace that the gate was
consciously skipped for a degenerate setup, not silently bypassed.
## Acceptance criteria
Default criterion (no project CLAUDE.md): solves a real user-facing
problem; contradicts no stated design commitment.
- **Real problem solved.** When the design is settled in the
sources, the orchestrator reaches `planner` through `specify`
with no interview and no re-litigation of settled decisions —
while still passing every production gate.
- **Anti-deference preserved (the load-bearing one).** `specify`
cannot become the lazy "sources look exhaustive, skip the
interview" path: the Step-1.5 precondition gate forces an honest
fork check, an unresolved fork bounces to `brainstorm`, and the
grounding-check and user-review gates are retained unchanged. The
reactive-deference failure class `brainstorm` exists to prevent is
not reintroduced.
- **Consistent with the toolchain's deepest commitment.** The
deciding→producing split mirrors the RED→GREEN split that keeps
`tdd`/`debug` honest; `specify` is a co-equal third entry path,
chosen by reflection, never a default.
- **No drift.** All four pipeline renderings and every cross-
reference agree on the three-path shape (verified by audit).