From 6723bd87dd4d81dbee271ebbfe332bd3ba149a52 Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 31 May 2026 12:13:24 +0200 Subject: [PATCH] docs: implementation plan for the milestone-close gate Nine bite-sized tasks across eight files; pipeline.md as the single source, fieldtester.md for the milestone carrier, then the referencing skills and the vocabulary/profile layer, closing with a cross-file verification sweep. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/2026-05-31-milestone-close-gate.md | 732 ++++++++++++++++++ 1 file changed, 732 insertions(+) create mode 100644 docs/plans/2026-05-31-milestone-close-gate.md diff --git a/docs/plans/2026-05-31-milestone-close-gate.md b/docs/plans/2026-05-31-milestone-close-gate.md new file mode 100644 index 0000000..b425deb --- /dev/null +++ b/docs/plans/2026-05-31-milestone-close-gate.md @@ -0,0 +1,732 @@ +# 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` | `..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 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 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.