Phase 6 — Definition of Done
Plan: i-want-to-ea3316 — pre-feature /brainstorm workflow Date: 2026-05-21 Phase status: completed (pending user ratification of OQ-6..OQ-8 defaults) Inputs: 05-tasks.md (44 tasks, 3-PR breakdown), 04-technical-design.md (DEC-9..DEC-18, H-1..H-7), 02-requirements.md (FR-1..25, IR-1..10, NFR-1..21, OOS-1..15), 03-research.md (DEC-1..DEC-8 baseline) DoD philosophy: Every checklist item is one of (a) a passing test name, (b) a CLI command that returns 0, (c) a file-presence check, (d) a manually-verifiable user-facing behavior with a yes/no answer. No vague "code should be clean" items. The coordinator will read this file during /start execution to validate progress.
0. Definition of Done summary
Done for v1 = the user can run /brainstorm "<topic>" end-to-end producing the two artifacts + sentinel; /feature --from-brainstorm <slug> consumes them; /feature --deep-brainstorm "<topic>" chains both; SEC-2/SEC-3/EC-2/EC-9 mitigations are in place; ≥85% line coverage on new code; docs + CHANGELOG updated; v0.24.0 published. Not in v1 = --full-inquisitors-each-round (OOS-13), multi-agent ROI A/B (OOS-14), UserInputDialog empty-submit / paste fixes (OOS-15), /brainstorm list UI (OOS-7), merge/backfill tools (OOS-6/8), and all OOS-1..12 items that were already deferred in Phase 2. Telemetry-only, not gated: NFR-1 / NFR-2 latency targets — observability via OQ-8 telemetry, no hard ship gate (Phase 3 relaxed both).
1. Functional acceptance (maps to FR-1..FR-25)
Marker meanings: ✅ done · ⏳ pending (task in 05-tasks.md) · 🔬 manual smoke · ❌ NOT in v1 (with OOS citation).
| FR | Description (1 line) | Verification | Marker |
|---|---|---|---|
| FR-1 | /brainstorm "<topic>" registers as a fleet slash command in registry.ts Workflows category | vitest -t "parseBrainstormArgs accepts topic" AND agents-fleet -p "/help" lists /brainstorm | ⏳ T-10, T-18 |
| FR-2 | New --resume-less invocation creates .plans/<slug>/ and prints slug | vitest -t "brainstorm prints slug on start" (within T-22 loop) | ⏳ T-10, T-22 |
| FR-3 | --resume <slug> continues / is idempotent if sentinel exists | vitest -t "resume rejects missing sentinel" AND vitest -t "resume idempotent when sentinel present" | ⏳ T-17, T-22 |
| FR-4 | Round 1 spawns 3 inquisitor explorer workers (ux/technical/edge-cases) with 3-8 q constraint | vitest -t "inquisitor roles discoverable" AND vitest -t "agents=3 spawns three workers" | ⏳ T-7, T-8, T-9, T-11b, T-24 |
| FR-5 | Round 1 harvests, dedupes, prioritizes ≤8 questions; rounds 2+ use coordinator-only follow-ups | vitest -t "harvest dedupe" AND vitest -t "round-2 uses coordinator follow-ups" | ⏳ T-13, T-14, T-15, T-22 |
| FR-6 | Questions asked one-at-a-time via context.coordinator.askUser (T-153 grilling path) | grep brainstormCommand for coordinator.askUser only (no other input plumbing) | ⏳ T-15 |
| FR-7 | After each round, terminator gate: auto-continue until N_min, then ask keep-grilling/summarize | vitest -t "N_min loop termination" (T-22) | ⏳ T-15, T-22 |
| FR-8 | On exit, writes 00-brainstorming.md + 00-brainstorming.context.md (or 01- under deep-brainstorm) | vitest -t "artifact pair written" AND smoke check via Test-Path | ⏳ T-16, T-20 |
| FR-9 | Artifacts written via atomicWriteFile (closed under FR-24 sentinel) | grep brainstormCommand for atomicWriteFile calls; vitest -t "sentinel written after artifacts" | ⏳ T-16, T-17 |
| FR-10 | Prints single-line success summary on exit | vitest -t "prints success summary" (T-22) | ⏳ T-15, T-22 |
| FR-11 | /brainstorm --unattended refuses with actionable error | vitest -t "brainstorm refuses --unattended" | ⏳ T-12, T-21 |
| FR-12 | RETIRED — folded into FR-5; opt-in flag moved to OOS-13 | negative test: vitest -t "--full-inquisitors-each-round not recognized" | ❌ OOS-13 |
| FR-13 | --rounds <n> clamped to [1,10] with actionable rejection out of range | vitest -t "rounds range" | ⏳ T-12, T-21 |
| FR-14 | 00-brainstorming.context.md schema v1 (frontmatter shape per FR-14) | vitest -t "context schema v1 parseable" (round-trips through custom YAML parser) | ⏳ T-16, T-22 |
| FR-15 | Optional confidence field on Q/A pairs when answer is short/hedged | vitest -t "confidence asked on short answer" | ⏳ T-15, T-22 |
| FR-16 | /feature --from-brainstorm <slug> loads context, skips Phase 1, writes pointer stub | vitest -t "from-brainstorm seeds requirements" AND vitest -t "from-brainstorm writes pointer stub" | ⏳ T-19, T-28 |
| FR-17 | --from-brainstorm <missing> errors with available-brainstorms list | vitest -t "from-brainstorm missing slug error" | ⏳ T-19, T-28 |
| FR-18 | --from-brainstorm rejects newer schema_version with actionable message | vitest -t "from-brainstorm rejects newer schema" | ⏳ T-19, T-28 |
| FR-19 | /feature --deep-brainstorm "<topic>" runs /brainstorm → then /feature --from-brainstorm (sibling slugs, no inline) | vitest -t "deep-brainstorm produces exactly one 01-brainstorming.md" (no double-write) AND vitest -t "deep-brainstorm chains from-brainstorm" | ⏳ T-20, T-29 |
| FR-20 | Plain /feature "<topic>" (no flags) unchanged | vitest run src/commands/featureCommand.test.ts legacy paths pass | ⏳ T-28 (regression) |
| FR-21 | askUser direct path honors --unattended (rich directive mirror of :1338-1351) | vitest -t "askUser unattended rich directive" | ⏳ T-5, T-5a, T-6 |
| FR-22 | Slug regex /^[a-z0-9][a-z0-9-]{0,63}$/ + isPathInsideDir backported to ALL plan-slug consumers (/feature --resume included) | vitest -t "SEC-3 path traversal regression" AND vitest run src/commands/planDir.test.ts | ⏳ T-3, T-3a, T-28 |
| FR-23 | wrapUntrusted applied to every re-fed user answer (round 2+ follow-ups) | vitest -t "round-2 prompt wraps answers" AND vitest -t "SEC-2 re-feed safety" | ⏳ T-15, T-26 |
| FR-24 | .brainstorm-complete sentinel written AFTER both artifacts | vitest -t "sentinel written after artifacts" AND vitest -t "resume rejects missing sentinel" | ⏳ T-17 |
| FR-25 | Auto-degrade to coordinator-only when no inquisitor returns ≥1 parseable question; record per-inquisitor status | vitest -t "FR-25 auto-degrade triggers when all inquisitors malformed" AND inspect context-file inquisitor_status: field in test fixture | ⏳ T-15a, T-25 |
2. Integration acceptance (maps to IR-1..IR-10)
| IR | Description | Verification | Marker |
|---|---|---|---|
| IR-1 | Existing /feature no-flag behavior preserved (7-stage pipeline, 4 with preQuestions) | vitest run src/commands/featureCommand.test.ts net-existing tests pass; npm run build exit 0 | ⏳ T-28, T-36 |
| IR-2 | Same context.coordinator.askUser path used (T-153) — no new input plumbing | grep brainstormCommand.ts for coordinator.askUser is the ONLY user-input call; grep for onUserInput|UserInputDialog returns 0 hits | ⏳ T-15 |
| IR-3 | Workflow lives under src/skills/bundled/workflows/brainstorm.workflow.md + sibling prompt files | Test-Path src/skills/bundled/workflows/brainstorm.workflow.md AND vitest run src/skills/parser.brainstorm.test.ts | ⏳ T-11, T-11a |
| IR-4 | 3 role files under src/skills/bundled/roles/inquisitor-*.role.md, discoverable by SkillRegistry.getRole | Test-Path for each of 3 files AND vitest run src/skills/SkillRegistry.brainstorm.test.ts | ⏳ T-7, T-8, T-9, T-11b |
| IR-5 | Workers spawned through coordinator's existing spawn_worker tool (not direct call) | grep brainstormCommand.ts for spawn_worker only appearing in coordinator-prompt strings, not as a direct JS import | ⏳ T-14 |
| IR-6 | Loop semantics live in brainstormCommand.ts, NOT runWorkflowStages | grep brainstormCommand.ts for runWorkflowStages returns 0 hits; loop is a plain while | ⏳ T-15 |
| IR-7 | Topology forced to hub for duration; prior topology restored in try/finally (only if we set it) | grep for setState.*activeTopology in brainstormCommand AND vitest -t "topology save/restore" | ⏳ T-31, T-27 |
| IR-8 | Artifacts under .plans/<slug>/ with 00- prefix (standalone) / 01- (deep-brainstorm); documented | grep docs/commands-manual.md for "00-brainstorming" + "01-brainstorming" prefix doc | ⏳ T-16, T-33 |
| IR-9 | Graceful shutdown discards in-memory transcript; no half-baked artifacts on /exit mid-round | Manual smoke: /exit mid-round → no .context.md persists, no sentinel; vitest -t "abort mid-round writes no artifacts" | 🔬 T-22, T-32 |
| IR-10 | All worker output via existing report_to_coordinator → MessageBus path; no new event types | grep each inquisitor-*.role.md body for report_to_coordinator as the only output mechanism | ⏳ T-7, T-8, T-9 |
3. Non-functional acceptance (maps to NFR-1..NFR-21)
| NFR | Description | Verification | Marker |
|---|---|---|---|
| NFR-1 | Round-1 spawn-to-first-question latency (observability only, NOT gated — OQ-7) | intelDb event brainstorm.completed carries spawnDurationMs; vitest -t "brainstorm.completed event recorded" asserts presence | ⏳ T-15 (telemetry) |
| NFR-2 | Total brainstorm latency (no hard cap; observed via telemetry — OQ-7) | brainstorm.completed.durationMs recorded; same test as NFR-1 asserts shape | ⏳ T-15 (telemetry) |
| NFR-3 | Plain /feature no-flag latency MUST NOT regress >5% | vitest run src/commands/featureCommand.test.ts legacy timing parity (run twice on CI, compare); ratified as observational | ⏳ T-28, T-36 |
| NFR-4 | 00-brainstorming.context.md parses in <100ms typical | vitest -t "brainstormContext loads under 100ms" | ⏳ T-30, T-30a |
| NFR-5 | No breaking changes to WorkflowStage type | npm run build exit 0 (type-check pass) AND code-review confirms only optional fields added | ⏳ T-36, T-37 |
| NFR-6 | feature-pipeline.workflow.md remains parseable | vitest run src/skills/parser.preQuestions.test.ts continues to pass | ⏳ T-11a, T-36 |
| NFR-7 | Session schema unchanged (transcript in-memory only) | grep src/session/ for any new brainstorm fields returns 0 hits; vitest -t "session save/load round-trip" unchanged | ⏳ T-15, T-37 |
| NFR-8 | Inquisitors are read-only explorer agent_type (no write/shell) | vitest -t "inquisitor roles are explorer type" AND grep role frontmatter for agent_type: explorer | ⏳ T-7, T-8, T-9, T-11b |
| NFR-9 | Topic string sanitized via escapeXml/neutralizePromptInput before injection | vitest -t "topic sanitization" | ⏳ T-12, T-14 |
| NFR-10 | Artifacts mode 0o644 | covered by NFR-20 (same row) | ⏳ T-16 |
| NFR-11 | No new MCP servers / external calls / subprocesses | code-review pass; grep brainstormCommand.ts for child_process|fetch|http returns 0 hits | ⏳ T-37 |
| NFR-12 | New unit tests in brainstormCommand.test.ts cover args / single round / N_min / summarize / keep-grilling / schema | vitest run src/commands/brainstormCommand.test.ts 0 fail | ⏳ T-21, T-22, T-23, T-24, T-25, T-26, T-27 |
| NFR-13 | New unit tests in featureCommand.test.ts cover from-brainstorm + deep-brainstorm | vitest run src/commands/featureCommand.test.ts 0 fail | ⏳ T-28, T-29 |
| NFR-14 | Parser test for brainstorm.workflow.md end-to-end | vitest run src/skills/parser.brainstorm.test.ts | ⏳ T-11a |
| NFR-15 | Full vitest suite + parity tests pass | npm test exit 0 (modulo pre-existing failures documented separately) | ⏳ T-36 |
| NFR-16 | Coverage thresholds not regressed; new code ≥85% line coverage (OQ-6 ratified) | npm run test:coverage reports ≥85% lines on each new file (brainstormCommand.ts, tolerantJson.ts, projectContext.ts, planDir.ts diff, brainstormContext.ts) | ⏳ T-36 |
| NFR-17 | docs/commands-manual.md updated with /brainstorm section + /feature flag examples | Test-Path docs/commands-manual.md AND Select-String -Path docs/commands-manual.md -Pattern '/brainstorm' has matches | ⏳ T-33 |
| NFR-18 | README.md one-line mention of /brainstorm | Select-String -Path README.md -Pattern 'brainstorm' has matches | ⏳ T-34 |
| NFR-19 | FLEET.md / architecture doc updated | Select-String -Path FLEET.md -Pattern 'brainstorm' has matches | ⏳ T-34 |
| NFR-20 | Explicit {mode: 0o644} passed to atomicWriteFile | grep brainstormCommand.ts for mode:\s*0o644 returns ≥2 matches; vitest -t "artifact mode 0o644" | ⏳ T-16 |
| NFR-21 | 8KB per-string cap with elision marker; original preserved in per-worker NDJSON | vitest -t "question text clipped to 8KB" AND vitest -t "answer text clipped to 8KB" | ⏳ T-1a, T-12, T-15 |
4. Out-of-scope (explicit NOT in v1)
| OOS | Description | Target | Verification (negative) |
|---|---|---|---|
| OOS-1 | Declarative loop semantics in runWorkflowStages | indefinite | grep runWorkflowStages for repeat: returns 0 hits |
| OOS-2 | PROMOTED → FR-21 (askUser unattended fix shipped in v1) | — | (in-scope; see FR-21) |
| OOS-3 | Auto-detect "complex domain → multi-agent" | v1.1+ if OOS-14 data warrants | n/a (always defaults to multi-agent per FR-4) |
| OOS-4 | LLM-driven topic extraction | indefinite | topic is literal string; no parsing |
| OOS-5 | Multi-user / multi-session collaboration | indefinite | single-process session model unchanged |
| OOS-6 | Backfill 00-brainstorming.context.md for existing plans | indefinite | no migration code shipped (grep src/ for 'backfill' = 0) |
| OOS-7 | /brainstorm list subcommand / REPL UI | v1.1 if demand | agents-fleet -p "/help" shows only /brainstorm (no list subcommand) |
| OOS-8 | /brainstorm merge capability | indefinite | n/a |
| OOS-9 | Hot-reload inquisitor roles mid-run | indefinite | roles loaded once at command start |
| OOS-10 | Per-brainstorm cost telemetry separate from session totals | v1.1 (overlap with OQ-8 telemetry) | session token totals unchanged; brainstorm.completed event has no token fields |
| OOS-11 | Schema v2 migration tooling | when v2 lands | runtime only checks schema_version <= 1; no migration code |
| OOS-12 | /research ↔ /brainstorm integration | indefinite | separate workflows; no cross-imports |
| OOS-13 | --full-inquisitors-each-round flag | v1.1 contingent on OOS-14 data | vitest -t "--full-inquisitors-each-round not recognized" (negative arg-parse) |
| OOS-14 | Multi-agent ROI A/B benchmark | post-v1 analysis | data feed via OQ-8 telemetry; analysis is separate project |
| OOS-15 | UserInputDialog empty-submit + paste fixes | separate task | vitest run src/components/UserInputDialog.test.tsx shows pre-existing skips unchanged |
5. Risk closeout (maps to H-1..H-7 from 04-technical-design.md §11)
| Risk | Mitigation | Verification | Marker |
|---|---|---|---|
| H-1 | Tolerant JSON parse failure → FR-25 auto-degrade | vitest -t "FR-25 auto-degrade triggers when all inquisitors malformed" AND vitest run src/utils/tolerantJson.test.ts | ⏳ T-1, T-1a, T-15a, T-25 |
| H-2 | Double-write of 01-brainstorming.md under --deep-brainstorm (artifact collision) | vitest -t "deep-brainstorm produces exactly one 01-brainstorming.md" | ⏳ T-20, T-29 |
| H-3 | --agents 0 (single-coord path) untested in v1 | vitest -t "agents=0 happy path" | ⏳ T-14, T-23 |
| H-4 | MessageBus.subscribe? optional widening → silent test stubs | code-review audit of all messageBus.subscribe call sites for if (!messageBus.subscribe) guard; no silent no-ops | ⏳ T-4, T-37 |
| H-5 | SEC-3 backport changes /feature error strings → test breakage | vitest run src/commands/featureCommand.test.ts updated to new strings AND vitest -t "SEC-3 path traversal regression" | ⏳ T-3, T-28 |
| H-6 | Topology restore race vs concurrent /loop | vitest -t "topology restore conditional on current === we-set-this" (only restore if we still own the slot) | ⏳ T-31, T-27 |
| H-7 | FR-21 directive change ripples to existing askUser callers | grep audit of all askUser callers updated to handle directive return; vitest -t "askUser unattended rich directive" AND vitest run src/commands/featureCommand.test.ts legacy callers green | ⏳ T-5, T-6 |
6. Telemetry (OQ-8 ratified — ⚠️ ASSUMPTION)
Shipped from v1 day 1; T-15 includes the recordEvent call.
intelDb.recordEvent('brainstorm.completed', {
slug: '<plan-slug>', // hash-suffixed; no PII
agentsN: 0 | 1 | 2 | 3, // OQ-2 drop order: edge-cases → technical → ux
roundsCompleted: number,
questionsAsked: number,
durationMs: number, // wall-clock total
spawnDurationMs: number, // OQ-7 — round-1 spawn-to-first-question observability
autoDegrade: boolean, // FR-25 fired?
inquisitorStatusCounts: { // matches FR-25 `inquisitor_status:` enum
success: number,
parse_error: number,
timeout: number,
empty: number,
},
});Purpose: OOS-14 multi-agent ROI analysis post-v1. v1.1 may flip --agents default based on this telemetry. No PII captured (topic NOT recorded; slug is hash-suffixed per slugify()).
Verification: vitest -t "brainstorm.completed event recorded" mocks intelDb and asserts the exact shape above. Live verification on first real session: /diagnose --json | jq '.intel.events["brainstorm.completed"].count' increments by 1.
7. Ship checklist (per-PR — derived from 05-tasks.md 3-PR breakdown)
PR-1 (Foundation) ships when:
- [ ] All T-1, T-1a, T-2, T-2a, T-3, T-3a, T-4, T-5, T-5a, T-6, T-7, T-8, T-9, T-11, T-11a, T-11b complete
- [ ]
npm run buildexit 0 - [ ]
npm test— net-new tests passing; pre-existing failures documented separately - [ ] SEC-3 regression:
vitest -t "SEC-3 path traversal regression"passes - [ ] FR-21 unattended directive:
vitest -t "askUser unattended rich directive"passes - [ ] No new public exports from
parseFrontmatter(DEC-18 — internal-only change) - [ ]
MessageBusLike.subscribe?widening compiles against all existing test stubs (compile check:npm run buildis sufficient) - [ ] CHANGELOG
[Unreleased]entry drafted (subset for foundation pieces) - [ ] Code review approved (reviewer agent or human)
PR-2 (Core + integration) ships when:
- [ ] All T-10, T-12, T-13, T-14, T-15, T-15a, T-16, T-17, T-18, T-19, T-20, T-30, T-30a, T-31 complete
- [ ] PR-1 merged to master
- [ ] Manual smoke:
/brainstorm "test topic"runs end-to-end with--agents 3(multi-agent path) → produces both artifacts + sentinel - [ ] Manual smoke:
/brainstorm "test topic" --agents 0runs end-to-end (single-coord auto-degrade equivalent path) - [ ] Manual smoke:
/feature feature --from-brainstorm <slug>reads brainstorm context AND writes pointer stub01-brainstorming.md - [ ] Manual smoke:
/feature feature --deep-brainstorm "<topic>"produces exactly ONE01-brainstorming.mdin the feature slug (no double-write — H-2 closeout) - [ ] No subscriber leaks: every
messageBus.subscribe(...)paired withdispose()in afinallyblock (manual code review) - [ ] FR-25 auto-degrade verified manually (kill inquisitor mid-spawn) + by
vitest -t "FR-25 auto-degrade" - [ ] Topology save/restore verified by
vitest -t "topology save/restore"+ manual/loopinteraction - [ ] CHANGELOG
[Unreleased]entry updated with core feature description
PR-3 (Tests + docs + release) ships when:
- [ ] All T-21, T-22, T-23, T-24, T-25, T-26, T-27, T-28, T-29, T-32, T-33, T-34, T-35 complete
- [ ]
npm run test:coverageshows ≥85% line coverage on each new file (NFR-16, OQ-6) - [ ] Manual smoke: full
/brainstorm "real topic"2-round session produces both artifacts +.brainstorm-completesentinel - [ ] Manual smoke: kill mid-round (Ctrl+C) → restart
/brainstorm --resume <slug>→ IR-9 holds (in-memory transcript discarded; offers fresh round 1; no zombie artifacts) - [ ]
gh release create v0.24.0 …published with tarball asset (or PR triggers release workflow) - [ ] Install scripts smoke:
install.ps1andinstall.shsucceed against new version - [ ]
docs/commands-manual.md+README.md+FLEET.mdupdated (NFR-17, NFR-18, NFR-19) - [ ] Live telemetry confirmation:
intelDb.recordEvent('brainstorm.completed', …)fires in a real session;/diagnose --jsonshows the event count incremented - [ ] T-36 (full suite + lint + build) green
- [ ] T-37 (code-review pass) approved
8. Open questions for ratification (3 from Phase 5)
- ⚠️ ASSUMPTION OQ-6: Coverage target ≥85% line coverage on new code adopted as DoD gate (default; matches NFR-16). REASON: NFR-16 already specifies this; making it an explicit PR-3 ship gate prevents drift. — User can override (e.g., raise to 90%, relax to 75%, or drop the gate entirely).
- ⚠️ ASSUMPTION OQ-7: NFR-1 / NFR-2 latency targets are NOT hard ship gates (observational telemetry only). REASON: Phase 3 relaxed both to "best-effort"; PERF-1 (fleet concurrency contention) makes hard limits unreliable across machines. Telemetry via OQ-8 enables post-ship analysis. — User can override (e.g., insist on a hard cap and block ship if exceeded).
- ⚠️ ASSUMPTION OQ-8: Ship
intelDb.recordEvent('brainstorm.completed', …)telemetry from v1 day 1 (§6 above). REASON: defers v1.1--agentsdefault decision to a data-driven choice; tiny cost (~5 LOC inside T-15); enables OOS-14 ROI analysis without re-instrumentation. No PII captured. — User can override (skip telemetry; accept that OOS-14 stays unmeasured indefinitely).
9. Phase exit criteria
- [x] Every FR-1..25 mapped to verification + task ID (table §1).
- [x] Every IR-1..10 mapped to verification (table §2).
- [x] Every NFR-1..21 mapped to verification or explicitly deferred (table §3).
- [x] Every OOS-1..15 enumerated with target + negative-verification where applicable (table §4).
- [x] All H-1..H-7 risks have mitigation task IDs + verification (table §5).
- [x] Per-PR ship checklists derived from task groups (§7, aligned to 05-tasks.md 3-PR breakdown).
- [x] OQ-6..OQ-8 logged as ⚠️ ASSUMPTION for user ratification (§8).
- [x] Telemetry event shape pinned (§6, OQ-8).
- [x] Out-of-scope items explicitly enumerated with deferral targets (§4).
- [x] Artifact written to
.plans/i-want-to-ea3316/06-definition-of-done.md.
Phase 6 complete. Ready for /start (or user ratification of OQ-6..OQ-8 followed by /start).