Phase 7 — Decisions Ledger (FINAL)
Plan: i-want-to-ea3316 — pre-feature /brainstorm workflow Date: 2026-05-21 Phase status: completed — plan ready for execution Inputs: all prior phase artifacts (01-brainstorming.md, 02-requirements.md, 03-research.md, 04-technical-design.md, 05-tasks.md, 06-definition-of-done.md) Purpose: Single source of truth for what v1 ships. If this file conflicts with any prior phase artifact, this file WINS.
0. Executive summary
We are shipping /brainstorm "<topic>" — a new pre-feature workflow that runs an adversarial multi-agent "inquisitor" round against a user-supplied idea, then grills the user with the resulting questions, then produces two artifacts (a human-readable narrative 00-brainstorming.md and a machine-readable 00-brainstorming.context.md with FR-14 YAML structure) under .plans/<slug>/. The result feeds /feature either by reference (/feature --from-brainstorm <slug>) or inline (/feature --deep-brainstorm, which writes its brainstorm as 01-brainstorming.md inside the feature slug, no sibling chain).
The chosen shape is deliberately simple: a single-file src/commands/brainstormCommand.ts (~380 LOC) that walks stages directly rather than reusing runWorkflowStages — this side-steps workflowController.ts:56-61's force-abort-on-re-registration trap (DEC-8). Round 1 spawns 3 explorer-class inquisitors (inquisitor-ux, inquisitor-technical, inquisitor-edge-cases) via the coordinator's spawn_worker tool and harvests their [partial_result] {...} envelopes by attaching a second messageBus.subscribe('coordinator', …) handler (verified safe in MessageBus.ts:226-251). Rounds 2+ are coordinator-only follow-ups — no re-spawn. The --agents 0|1|2|3 escape hatch (DEC-13) makes the multi-agent behavior optional and gives us the A/B mechanism for OOS-14.
This feature piggybacks two critical security backports: SEC-3 (slug regex + isPathInsideDir for every plan-slug consumer, per FR-22 / OQ-4) and the askUser unattended-mode fix (FR-21 / DEC-15, which returns a rich askUser directive mirroring :1338-1351 rather than the silent empty string today). These ship in PR-1 so their value is realized even if PRs 2–3 slip. Total estimated effort is ~70–90 hours across 3 PRs, critical-path ~40h, target release v0.24.0.
The contract below — DEC-1..DEC-18 plus OQ-1..OQ-8 — is what v1 is. v1.1 inherits the multi-agent ROI question (answered by OQ-8 telemetry from production sessions), the tolerantJson.ts refactor of AgentOutcomeExtractor + SteeringExtractor (OOS-15), and the topology version-counter (H-6). Everything else is in or out.
1. The ratified design in one page
Feature: /brainstorm "<topic>" [--rounds N] [--agents 0|1|2|3] [--resume <slug>] and /feature --from-brainstorm <slug> and /feature --deep-brainstorm.
Shape:
- Single-file
src/commands/brainstormCommand.ts(~380 LOC) — orchestrator that walks stages directly (norunWorkflowStages). - Round 1: spawns 3 inquisitors (
inquisitor-ux,inquisitor-technical,inquisitor-edge-cases) as explorer-class workers via coordinator'sspawn_worker. Theirreport_to_coordinator(partial_result)JSON payloads are harvested by a secondmessageBus.subscribe('coordinator', handler)filtering the[partial_result]prefix. - Rounds 2+: coordinator-only follow-up question generation (no re-spawn). All user answers wrapped with
wrapUntrusted()before re-feed (FR-23). - User grilling per question via
context.coordinator.askUser({question})(T-153 path). - Termination: hard cap (
--rounds N, default 2, range 1-10) OR user answers "summarize". - Artifacts:
00-brainstorming.md(narrative) +00-brainstorming.context.md(FR-14 YAML structured) +.brainstorm-completesentinel — allatomicWriteFilewith{mode: 0o644}. - Slug under
.plans/<slug>/with regex/^[a-z0-9][a-z0-9-]{0,63}$/+isPathInsideDirvalidation. - Topology: command flips to
hubon entry, restores on exit (conditional per DEC-17).
Composition with /feature:
/feature --from-brainstorm <slug>: reads brainstorm context, writes Phase 1 pointer stub, prepends digest to Phase 2 prompt. (User-explicit Phase-1 requirement.)/feature --deep-brainstorm: runs brainstorm INLINE as Phase 1 (writes01-brainstorming.mdin feature slug), then proceeds to Phase 2. NO sibling-slug chain. (DEC-3 narrowly reopened by Designer 3 → DEC-12.)
Escape hatch: --agents 0 = single-coordinator mode (no inquisitor spawn, no bus-tap, no JSON parser). Mandatorily tested. Future v1.1 may flip default if telemetry (OQ-8) shows weak multi-agent ROI.
2. Decisions ledger (DEC-1 through DEC-18)
From Phase 3 (research-ratified)
DEC-1 — Clone /feature pattern (NOT /research, /init, or /code-review).
- Source: 03-research.md §C-1.
- Ratification: research-derived; critic verified counter-researcher's ALT-2 premise was false.
- Rationale:
/researchis prompt-and-return (researchCommand.ts:80-86); only/featureactually drives user-iteration on its own./featureis the right template. - Rejected: ALT-2 ("extend
/research --interactive") — see §6.
DEC-2 — Harvest inquisitor output via a second messageBus.subscribe('coordinator', handler) filtering the [partial_result] prefix.
- Source: 03-research.md §C-3.
- Ratification: research-derived; verified
MessageBus.ts:226-251returns an unsubscribe closure and tolerates multiple handlers per channel. - Rationale: Workers'
report_to_coordinator(partial_result, …)already routes through the coordinator channel with envelope prefix[partial_result](FleetManager.ts:520, 530). We can tap without changing the dispatcher. - Rejected: Adding a new
partial_resultchannel (avoidable surface-area expansion).
DEC-3 — /brainstorm artifact directory is its own slug; standalone runs chain via --from-brainstorm.
- Source: 03-research.md.
- Ratification: research-derived; NARROWLY REOPENED in Phase 4 by Designer 3 for the
--deep-brainstormcase only — see DEC-12. - Rationale: Matches existing
.plans/<slug>/convention; keeps standalone brainstorms first-class. - Exception:
--deep-brainstormdoes NOT chain via--from-brainstorm; instead runs inline (DEC-12).
DEC-4 — Dual artifact (brainstorming.md narrative + brainstorming.context.md YAML); drop schema_version for v1.
- Source: 03-research.md.
- Ratification: research-derived (counter-researcher proposal accepted-with-modification).
- Rationale: Mirrors existing context-file pattern;
schema_versionis premature YAGNI — bump only when the schema actually changes.
DEC-5 — Multi-agent inquisitors run round 1 ONLY; rounds 2+ are coordinator follow-ups.
- Source: 03-research.md.
- Ratification: research-derived; SEC-2 re-feed risk + cost-per-spawn make per-round re-spawn unjustified.
- Rationale: Round 1 produces the angle diversity; subsequent rounds need depth, which the coordinator (now context-aware) does better and cheaper.
- Rejected: Per-round multi-agent spawn (OOS-13
--full-inquisitors-each-roundflag).
DEC-6 — FR-21 (askUser unattended fix) + FR-22 (slug regex + isPathInsideDir backport) are IN-SCOPE for v1.
- Source: 03-research.md (critic).
- Ratification: research-derived.
- Rationale: Both are security/correctness blockers exposed by the brainstorm work; FR-22 backports the SEC-3 fix to existing
/feature --resume(featureCommand.ts:75-80). Ship together.
DEC-7 — Inquisitor reply format = JSON object (parsed with tolerant parser per DEC-14).
- Source: 03-research.md.
- Ratification: research-derived.
- Rationale: Preserves structured
angle/priorityfields needed by FR-5 / FR-14. Numbered-list regex would lose these. - Rejected: Numbered-list regex (see §6).
DEC-8 — /brainstorm walks the stage list DIRECTLY; does NOT call runWorkflowStages.
- Source: 03-research.md §C-2.
- Ratification: research-derived; verified
workflowController.ts:56-61force-aborts the prior workflow on re-registration. - Rationale: A nested
/feature --from-brainstormtriggered mid-brainstorm would kill the outer workflow. Walking stages directly avoids the trap and ALSO eliminates Designer 3's sibling-slug rationale (→ DEC-12).
From Phase 4 (design-ratified)
DEC-9 — Single-file brainstormCommand.ts shape; no state-machine, no DI ceremony.
- Source: 04-technical-design.md §1, §2.
- Ratification: design-ratified (Designer 1 minimal won over Designer 2 clean).
- Rationale: YAGNI — one consumer, simple loop,
makeContext()test pattern already adequate. Refactor when a second consumer appears. - Rejected: State-machine
BrainstormRoundRunner+ DI seams (Designer 2 alternative — see §6).
DEC-10 — Adopt 2 extractions; reject 2 extractions.
- Source: 04-technical-design.md §1.4.
- Ratification: design-ratified.
- Adopted:
projectContexthelper, slug validators (validateSlug+isPathInsideDir). - Rejected:
agentWaiter(wrong shape — featureCommand's is artifact-race, brainstorm needs event-based onagent.completed/agent.failed);UserGrillingloop (90% boilerplate; only shared call is the one-linercoordinator.askUser({question})).
DEC-11 — Widen MessageBusLike (commands.ts:84-92) with optional subscribe? field (1-line addition).
- Source: 04-technical-design.md.
- Ratification: design-ratified.
- Rationale: Structurally honest; preserves
*Likeconvention; keeps test stubs typecheckable. - Rejected:
messageBus as unknown as MessageBuscast (silent breakage risk in test stubs).
DEC-12 — --deep-brainstorm INLINES brainstorm into /feature Phase 1 (writes 01-brainstorming.md inside the feature slug). NO sibling-slug chain.
- Source: 04-technical-design.md §6 (Designer 3); narrowly reopens DEC-3 for this case only.
- Ratification: design-ratified.
- Rationale: DEC-8 eliminated the workflowController hazard that made sibling-slug attractive. Inline is ~5 LOC vs the chain's FR-16/17/18 dependency surface.
DEC-13 — Ship --agents <n> escape hatch in v1; default --agents 3; n=0 is the OOS-14 A/B mechanism.
- Source: 04-technical-design.md.
- Ratification: user-explicit "all default" in Phase 4 (selected OQ-2 default).
- Rationale: Preserves multi-agent identity while giving users a safety valve. Telemetry (OQ-8) will inform v1.1 default flip.
- Rejected: Drop multi-agent entirely (Designer 3 alternative); hard-wire
--agents 3with no opt-out.
DEC-14 — Tolerant JSON parser lives in src/utils/tolerantJson.ts (~40 LOC), modeled on AgentOutcomeExtractor.ts:73-117.
- Source: 04-technical-design.md.
- Ratification: user-explicit "all default" in Phase 4 (selected OQ-3 default).
- Rationale: Three current consumers (
AgentOutcomeExtractor,SteeringExtractor, inquisitor harvest) all need the same fence-stripping/trailing-comma-tolerant behavior. Refactor of the existing two callers is follow-up (OOS-15, out of v1).
DEC-15 — FR-21 returns a RICH askUser directive (mirror of CoordinatorEngine.ts:1338-1351), not an empty string.
- Source: 04-technical-design.md.
- Ratification: user-explicit "all default" in Phase 4 (selected OQ-5 default).
- Rationale: Empty-string silent failure is the bug we are fixing; matching the existing rich directive keeps unattended UX consistent across both askUser code paths. Direct callers updated.
DEC-16 — FR-25 threshold failure (zero inquisitors return ≥1 question) AUTO-DEGRADES to coordinator-only grilling. Does NOT abort.
- Source: 04-technical-design.md.
- Ratification: design-ratified.
- Rationale: A user typed a topic and waited — don't waste that effort. Emit yellow warning, write raw inquisitor bodies to NDJSON for debug, continue with coordinator-only round.
DEC-17 — Topology restore is CONDITIONAL on current === we-set-this.
- Source: 04-technical-design.md.
- Ratification: design-ratified.
- Rationale: Guards against clobbering a concurrent
/loopthat changed topology while brainstorm was running. Full version-counter (H-6) deferred to v1.1.
DEC-18 — parseFrontmatter stays module-private to its current home; brainstormContext.ts uses a focused ~15-LOC YAML reader.
- Source: 04-technical-design.md.
- Ratification: design-ratified.
- Rationale: Public-API expansion not justified; focused reader is smaller than the import-and-adapter overhead would be.
- Rejected: Promote
parseFrontmatterto public export (Designer 2 — see §6).
3. Open-question resolutions ledger (OQ-1 through OQ-8)
| OQ | Source | Question | Final answer | Ratification |
|---|---|---|---|---|
| OQ-1 | Phase 4 | Inline --deep-brainstorm artifact naming | 01-brainstorming.md inline (in feature slug); 00-brainstorming.md standalone | user-explicit "all default" (Phase 4) |
| OQ-2 | Phase 4 | --agents <n> value range | {0, 1, 2, 3}; drop order at lower n is edge → +technical → +ux | user-explicit "all default" (Phase 4) |
| OQ-3 | Phase 4 | Tolerant JSON parser location | Shared src/utils/tolerantJson.ts (~40 LOC) | user-explicit "all default" (Phase 4) |
| OQ-4 | Phase 4 | FR-22 backport breadth | ALL plan-slug consumers in same PR (PR-1) | user-explicit "all default" (Phase 4) |
| OQ-5 | Phase 4 | FR-21 directive vs empty string | RICH directive (mirror of CoordinatorEngine.ts:1338-1351) | user-explicit "all default" (Phase 4) |
| OQ-6 | Phase 6 | Coverage gate threshold | ≥85% line coverage on new code | user-explicit "all default" (Phase 6) |
| OQ-7 | Phase 6 | Latency: hard gate or observational? | Observational (telemetry only); NOT a hard ship gate | user-explicit "all default" (Phase 6) |
| OQ-8 | Phase 6 | Ship telemetry from v1 day 1 | Yes; intelDb.recordEvent('brainstorm.completed', …) from day 1 | user-explicit "all default" (Phase 6) |
All 8 OQs resolved. 5 user-default ratifications in Phase 4, 3 user-default ratifications in Phase 6.
4. Requirements amendments ratified (final canonical delta vs Phase 2 baseline)
Incorporates Phase 3 amendments + Phase 4 DEC-12.
Added (v1 in-scope)
- FR-21 —
CoordinatorEngine.askUserdirect path honors unattended mode (rich directive per DEC-15). ~25 LOC patch. - FR-22 — Slug regex
/^[a-z0-9][a-z0-9-]{0,63}$/+isPathInsideDirenforced for every plan-slug consumer (per OQ-4). Backports SEC-3 fix to existing/feature --resume. - FR-23 —
wrapUntrusted()applied to every user-answer string before it is re-fed to ANY agent (coordinator OR inquisitors). - FR-24 —
.brainstorm-completesentinel written after both artifacts succeed (atomic{mode: 0o644}). - FR-25 — Threshold: ≥1 inquisitor must return ≥1 question. On failure: AUTO-DEGRADE (per DEC-16) — do NOT abort.
- NFR-20 — Artifacts written with explicit
{mode: 0o644}. - NFR-21 — Per-string 8 KB cap on harvested inquisitor fields (truncate with elision marker).
Modified
- FR-5 — Round 1 spawns N inquisitors (N =
--agentsvalue, default 3, range 0-3). Rounds 2+ coordinator-only. - FR-12 — RETIRED — folded into FR-5 (the round-1-only behavior is now part of FR-5's spec).
- FR-19 —
--deep-brainstormruns brainstorm INLINE as/featurePhase 1, writes01-brainstorming.mdinside the feature slug. No sibling-slug chain. (DEC-12.) - FR-9 —
atomicWrite→atomicWriteFile(D-4 typo fix); explicit{mode: 0o644}per NFR-20. - NFR-1 / NFR-2 — Weakened to "best-effort, observable via telemetry" per OQ-7 (not hard ship gates).
Added to OOS (v1.1+ candidates)
- OOS-12 (Phase 3) — A/B benchmark proving multi-agent inquisitor value vs single-agent grilling. Telemetry per OQ-8 collects v1 data.
- OOS-13 (Phase 3) —
--full-inquisitors-each-roundflag. - OOS-14 (Phase 3 critic) — Multi-agent ROI A/B; mechanism resolved by DEC-13
--agentsflag; data collection via OQ-8 telemetry; decision deferred to v1.1. - OOS-15 (Phase 4) — Refactor
AgentOutcomeExtractor+SteeringExtractorto use sharedtolerantJson.ts(DEC-14 follow-up PR).
5. Critical-claim audit trail (verified by Phase 3 critic, re-verified by Phase 4 critic)
These are the technical claims this entire design hinges on. Each must hold or the design is wrong. File:line citations are the audit trail.
| Claim | Status | Evidence |
|---|---|---|
MessageBus.subscribe supports multiple handlers, returns unsubscribe closure | ✅ verified | src/messaging/MessageBus.ts:226-251 |
MessageBusLike (commands.ts:84-92) lacks subscribe field — must widen | ✅ verified | DEC-11 fix (add optional subscribe?) |
report_to_coordinator envelopes are prefixed with [<report_type>] | ✅ verified | src/fleet/FleetManager.ts:520, 530 |
CoordinatorEngine.askUser direct path (:1074-1097) lacks unattended check | ✅ verified | DEC-15 / FR-21 fix |
workflowController.setActiveWorkflowController force-aborts prior on re-registration | ✅ verified | src/skills/workflowController.ts:56-61; DEC-8 dodges by walking stages directly |
SEC-3 path-traversal exploitable today in /feature --resume | ✅ verified | src/commands/featureCommand.ts:75-80; DEC-6 / FR-22 fixes |
/research is prompt-and-return — no JS-side harvest, LLM does synthesis | ✅ verified | src/commands/researchCommand.ts:80-86, 95-107, 222-224; confirms /feature was the right template (rejects counter-researcher ALT-2) |
| Prior LLM-JSON parser pattern exists in codebase (justifies DEC-14 tolerant parser) | ✅ evidence | src/intel/AgentOutcomeExtractor.ts:73-117, src/intel/SteeringExtractor.ts:99 |
T-153 parser supports arrays-of-objects (FR-14 qa_pairs schema) | ✅ verified | src/skills/parser.ts:206-240; tested by parser.preQuestions.test.ts:11-96 |
6. Rejected alternatives ledger (so we don't relitigate)
If you re-read this plan in 3 months and wonder "why didn't we do X?", search this table first.
| Rejected proposal | Proposed by | Why rejected | Cite |
|---|---|---|---|
ALT-2: Extend /research --interactive instead of building new /brainstorm | Phase 3 counter-researcher | Premise that /research already drives askUser/iteration is false; /research is prompt-and-return (researchCommand.ts:80-86). Critic verified, ALT-2 collapses. | 03-research.md §C-1, V2 |
| Single-coord-only — drop FR-4/FR-5 entirely (no multi-agent at all) | Phase 4 Designer 3 alternative | Contradicts user Phase-1 intent + agents-fleet product identity (the product IS a multi-agent showcase). Preserved as opt-in via --agents 0. | 04-technical-design.md §6 |
State-machine + DI BrainstormRoundRunner | Phase 4 Designer 2 (clean) | YAGNI — one consumer, simple loop. makeContext() test pattern is already adequate without DI ceremony. | 04-technical-design.md §1, §2 |
Extract agentWaiter from featureCommand | Phase 4 Designer 2 | Wrong shape — featureCommand's waiter is artifact-race-based; brainstorm needs event-based on agent.completed/agent.failed for known IDs. | 04-technical-design.md §1.4 |
Extract UserGrilling loop | Phase 4 Designer 2 | 90% boilerplate; only shared API is coordinator.askUser({question}), already a one-liner. | 04-technical-design.md §1.4 |
messageBus as unknown as MessageBus cast instead of widening MessageBusLike | Phase 4 Designer 1 (minimal) | Structurally dishonest; violates *Like convention; test stubs would silently break when the interface drifts. | DEC-11 |
| Numbered-list regex parsing of inquisitor output (instead of JSON) | Phase 4 Designer 3 | Loses structured angle / priority fields needed by FR-5/FR-14. JSON parsing risk mitigated by DEC-14 tolerant parser. | 04-technical-design.md §2 |
Promote parseFrontmatter to public export | Phase 4 Designer 2 | Public-API expansion not justified; focused ~15-LOC YAML reader in brainstormContext.ts is smaller than the import-and-adapter overhead. | DEC-18 |
Sibling-slug chain for --deep-brainstorm (DEC-3 original form) | Phase 4 Designer 3 (originally accepted) | DEC-8 eliminated the workflowController hazard; sibling-slug rationale evaporated. Inline is ~5 LOC vs the chain's FR-16/17/18-dependency surface. | DEC-12 |
Hard --full-inquisitors-each-round flag (per-round respawn) | Phase 3 critic | SEC-2 re-feed risk + cost-per-spawn not justified; round-1-only multi-agent is the default per FR-12 (now folded into FR-5). | OOS-13 |
schema_version field in .context.md for v1 | Phase 3 counter-researcher | Premature YAGNI; bump only when the schema actually changes. | DEC-4 |
| Aborting on FR-25 threshold failure (zero inquisitors return ≥1 question) | (implicit alternative) | Wastes user effort already spent typing the topic; AUTO-DEGRADE to coordinator-only round is strictly better UX. | DEC-16 |
| Unconditional topology restore on exit | (implicit alternative) | Risks clobbering a concurrent /loop that changed topology mid-brainstorm. Conditional current === we-set-this restore is safer; full version-counter is v1.1. | DEC-17 |
| Make tolerant JSON parser brainstorm-private | (implicit alternative) | Three current consumers need identical behavior; sharing it from day 1 is cheap and prevents drift. (Refactor of existing two is OOS-15 follow-up.) | DEC-14 |
Return empty string from askUser under unattended mode (status quo) | (existing bug) | Silent failure; user gets nothing back, coordinator stalls. Rich directive (DEC-15) is the fix. | FR-21 |
7. Open questions left for v1.1 (not blocking v1)
These are explicitly unresolved and noted for future iteration:
- The multi-agent ROI question — does
--agents 3produce measurably better question quality than--agents 0? OQ-8 telemetry from v1 production sessions will provide the data. v1.1 may flip the default or remove the flag in either direction. UserInputDialogempty-submit (EC-3) and multi-line paste (EC-4) bugs — flagged by 03-research.md edge-case-researcher; latent in the UI layer, not blocking brainstorm but will affect grilling UX over time. Tracked separately.- Topology version-counter for safe restore under concurrent
/loop— DEC-17'scurrent === we-set-thischeck is a partial mitigation; a real version-counter is v1.1 (H-6 follow-up). - Refactor
AgentOutcomeExtractor+SteeringExtractorto use sharedtolerantJson.ts(OOS-15) — fast-follow PR after v1 ships; current duplication is tolerated for the v1 release window.
8. Plan summary — what executes from here
The plan ships as 3 PRs per 05-tasks.md §6:
- PR-1 — Foundation (~25–30h). Lands FR-21 fix + SEC-3 backport (security wins shippable on their own),
tolerantJson.ts,projectContextextract,planDirhardening, 3 inquisitor role files, workflow + prompts,brainstormContextutil. - PR-2 — Core + integration (~25–35h). Lands
brainstormCommanditself,/feature --from-brainstorm,/feature --deep-brainstorminline. - PR-3 — Tests + docs + release (~20–25h). Final polish, integration tests, telemetry plumbing (OQ-8
intelDb.recordEvent('brainstorm.completed', …)), CHANGELOG, release prep.
Critical path: ~40 hours.
Release: v0.24.0 (minor — new user-facing feature).
9. Phase exit criteria
- [x] All decisions DEC-1..DEC-18 documented with phase source + ratification status.
- [x] All open questions OQ-1..OQ-8 resolved (5 user-explicit Phase 4 + 3 user-explicit Phase 6).
- [x] All rejected alternatives documented to prevent relitigation.
- [x] Critical-claim audit trail with file:line citations preserved.
- [x] Requirements amendments consolidated into single canonical delta vs Phase 2 baseline.
- [x] v1.1 open questions enumerated separately from v1 scope.
- [x] 3-PR shipping plan summarized.
- [x] Artifact written.
10. THE COMMITMENT
This is what v1 ships. If you re-read this in 3 months and a code-review says "wait, why didn't we do X" — check §6 first. If X is already in §6, the answer is in the cited phase artifact. If X is NOT in §6, it's legitimate new feedback worth considering.
The plan is now complete. Execution can begin with PR-1 per 05-tasks.md §6.