Skip to content

02 — Requirements: Pre-Feature Deep Brainstorming Workflow

Plan slug: i-want-to-ea3316Stage: 2 of 7 — requirements Date: 2026-05-21 Source: 01-brainstorming.md

Scope: requirements for the brainstorming feature itself, not for agents-fleet as a whole. Every requirement is testable against the actual src/ codebase.


Functional Requirements

/brainstorm slash command (standalone)

  • FR-1/brainstorm "<topic>" registers as a new slash command in the Workflows category of src/commands/registry.ts, with type: 'fleet' and aliases brain, bs. Usage line: /brainstorm [--rounds <n>] [--resume <slug>] "<topic>".

  • FR-2 — Invoking /brainstorm "<topic>" with no --resume creates a new plan dir .plans/<slug>/ using the same slug-generation pattern as /feature (descriptive prefix + 6-char hash). The slug is printed once at startup so the user can copy it for later --resume or /feature --from-brainstorm.

  • FR-3/brainstorm --resume <slug> continues an in-progress brainstorm if its artifact pair has not yet been written. If the artifacts already exist, the command prints the artifact paths and exits without re-running (idempotent).

  • FR-4/brainstorm "<topic>" spawns exactly 3 parallel inquisitor workers on round 1 via spawn_worker:

    • inquisitor-ux (role file src/skills/bundled/roles/inquisitor-ux.role.md, agent_type explorer)
    • inquisitor-technical (role file inquisitor-technical.role.md, agent_type explorer)
    • inquisitor-edge-cases (role file inquisitor-edge-cases.role.md, agent_type explorer)

    Each inquisitor receives: the topic, the active project context (.fleet/context/*.md), and a role-specific system prompt that constrains its angle. Each MUST return between 3 and 8 questions via report_to_coordinator with report_type: 'partial_result', then exit without writing files.

  • FR-5 — After round 1 inquisitor workers complete, the coordinator collects all question payloads from the message bus, deduplicates them (case-insensitive substring + cosine-similar enough heuristics), and prioritizes them so that no more than 8 questions are surfaced per round.

  • FR-6 — Prioritized questions are asked one at a time via context.coordinator.askUser({ question }) — the deterministic T-153 grilling path. The full Q/A pairs are accumulated in a transcript buffer in FleetStateStore (or a command-scoped in-memory list).

  • FR-7 — After each completed round, the coordinator decides whether to continue or summarize:

    • If roundsSoFar < N_min (default N_min = 2, overridable via --rounds <n>), automatically start the next round (re-spawn inquisitors OR generate follow-ups from the coordinator itself; see FR-12).
    • If roundsSoFar >= N_min, ask the user via askUser({ question: 'Should I keep grilling or summarize?', choices: ['keep grilling', 'summarize'] }). On summarize, exit the loop. On keep grilling, run another round.
  • FR-8 — On loop exit, the coordinator writes two artifacts to .plans/<slug>/:

    • 00-brainstorming.md — human-readable narrative (Vision / Where it Fits / Constraints / Per-Inquisitor Findings / Full Q&A Transcript / Assumptions / Open Questions). Renders cleanly in Markdown viewers.
    • 00-brainstorming.context.md — structured machine-readable file with YAML frontmatter schema_version: 1 and downstream-consumable fields (see FR-14).
  • FR-9 — The artifact pair MUST be written atomically (use atomicWrite from src/utils/index.ts) so a crashed /brainstorm leaves either both files or neither.

  • FR-10/brainstorm MUST print a single-line success summary on exit: ✓ Brainstorm complete: <N> questions across <M> rounds → .plans/<slug>/00-brainstorming.md.

  • FR-11/brainstorm --unattended MUST refuse to run with an actionable error (/brainstorm is interactive by design; --unattended is not supported. Omit the flag or use /feature --unattended for non-interactive planning.). This is enforced even when invoked from inside /loop --unattended or /loop-target --unattended.

  • FR-12 — Round 2+ question generation MUST use coordinator-only follow-ups (not re-spawn inquisitors) by default, to control cost. A --full-inquisitors-each-round flag (or equivalent) re-spawns the 3 inquisitors every round if the user wants maximum coverage. Default = coordinator-only follow-ups after round 1.

  • FR-13 — The --rounds <n> flag overrides N_min. Valid range: 1 ≤ n ≤ 10. Out-of-range values are rejected with an actionable error.

  • FR-1400-brainstorming.context.md schema (v1):

    yaml
    ---
    schema_version: 1
    slug: <plan-slug>
    topic: <verbatim topic from /brainstorm>
    created_at: <ISO-8601 UTC>
    rounds_completed: <number>
    questions_asked: <number>
    qa_pairs:
      - round: 1
        angle: ux | technical | edge-cases | coordinator-followup
        question: "..."
        answer: "..."
        asked_at: <ISO-8601>
    assumptions:
      - id: A-1
        text: "..."
        reason: "..."
        confidence: certain | likely | guess  # see FR-15
    open_questions:
      - id: OQ-1
        text: "..."
        blocking: true | false
    carry_forward_hints:
      - phase: requirements | research | design | validation | dod | tasks
        hint: "..."
    ---
  • FR-15 — Each qa_pairs entry MAY carry an optional confidence field (certain | likely | guess). The coordinator asks the user this only when their answer was very short (< 10 chars) or contained hedging words ("maybe", "probably", "I think"). Otherwise the field is omitted and downstream phases treat absence as certain. (This resolves Phase 1 OQ-5.)

/feature integration

  • FR-16/feature --from-brainstorm <slug> loads .plans/<slug>/00-brainstorming.context.md, validates schema_version <= 1, and uses its qa_pairs + assumptions + carry_forward_hints as seed input for Phase 2 (requirements). Phase 1 (brainstorm) is skipped entirely — no 01-brainstorming.md is written by /feature in this mode; instead /feature creates a reference file 01-brainstorming.md containing only a > Brainstorm imported from .plans/<source-slug>/00-brainstorming.md pointer.
  • FR-17/feature --from-brainstorm <missing-slug> MUST error with an actionable message listing available brainstorms (Available brainstorms in .plans/: <list>). If no brainstorms exist, the error suggests /brainstorm "<topic>" first.
  • FR-18/feature --from-brainstorm <slug> when 00-brainstorming.context.md exists but has a higher schema_version than the current loader supports MUST error with Brainstorm artifact schema_version <N> is newer than this CLI supports (max <M>). Upgrade agents-fleet or regenerate the brainstorm.
  • FR-19/feature --deep-brainstorm "<topic>" runs the /brainstorm workflow inline as Phase 1 of /feature. The brainstorm artifacts are written inside the feature's plan dir (same slug, not a separate slug). Downstream phases consume them like any other Phase 1 output.
  • FR-20 — Plain /feature "<topic>" (no flags) continues to work exactly as today — the 3 fixed preQuestions light grilling. Backward compatibility is preserved (see IR-1, NFR-3).

Integration Requirements

  • IR-1 — Existing /feature behavior MUST be preserved when invoked without --from-brainstorm and without --deep-brainstorm. Test: the current feature-pipeline.workflow.md parsing (7 stages, 4 with preQuestions) must continue to produce the same 7 artifacts in the same order. No regression in src/commands/featureCommand.test.ts.
  • IR-2/brainstorm MUST use the same askUser path that /feature Phase 1 grilling uses (context.coordinator.askUser({ question })CoordinatorEngine.askUsereventHandler.onUserInput → Ink UserInputDialog). No new user-input plumbing. The T-153 explorer mapped this path; reuse verbatim.
  • IR-3/brainstorm MUST use the same workflow definition format (*.workflow.md with YAML frontmatter + sibling <workflow-name>/<stage>.prompt.md files) as /feature. New file: src/skills/bundled/workflows/brainstorm.workflow.md + src/skills/bundled/workflows/brainstorm/*.prompt.md. The parser fix from T-153 (nested string lists under empty-value keys) MUST cover any preQuestions: blocks in the new workflow.
  • IR-4 — Inquisitor roles MUST live under src/skills/bundled/roles/ and follow the existing *.role.md format (YAML frontmatter with name, description, agent_type, version; body as system prompt). They MUST be discoverable by SkillRegistry.getRole(name) after the next bundled-asset cache rebuild.
  • IR-5/brainstorm MUST register through src/commands/registry.ts (createBrainstormCommand() in src/commands/brainstormCommand.ts) so it appears in /help under Workflows and is discoverable by findCommand().
  • IR-6 — The loop semantics (round-by-round until summarize) MUST be implemented in brainstormCommand.ts, not as a declarative construct in the workflow runner. The workflow file holds the per-round stage list (spawn-inquisitors → collect-and-prioritize → grill-round → decide); the command handler drives iteration. No changes to runWorkflowStages core. (Resolves Brainstorming Risk #1.)
  • IR-7/brainstorm MUST declare and enforce topology: hub for the duration of the brainstorm session (workers report only to coordinator, no peer-to-peer). If the active topology is mesh or silent, the command MUST temporarily flip to hub and restore the prior topology on exit (try/finally). (Resolves Brainstorming Risk #7.)
  • IR-8 — The artifact pair written by /brainstorm MUST live in .plans/<slug>/ with prefix 00- (not 01-), signaling Phase 0 / pre-feature. /feature artifacts retain the 01-07- numbering. This convention is documented in docs/commands-manual.md.
  • IR-9/brainstorm MUST integrate with the existing graceful-shutdown flow (GracefulShutdown in src/utils/errors.ts): if the user /exits mid-brainstorm, any in-progress round MUST be aborted cleanly and the partial Q&A transcript MUST be discarded (do not write half-baked artifacts). Resuming via /brainstorm --resume <slug> starts a fresh round 1 against the same topic, not a partial recovery (v1 simplicity).
  • IR-10 — All worker output capture for inquisitors MUST go through the existing report_to_coordinatorMessageBus path. No new bus types or event variants.

Non-Functional Requirements

Performance

  • NFR-1 — Round 1 spawn-to-first-question latency MUST be under 15 seconds on a warm cache (3 explorer workers in parallel; explorers don't require git worktree creation). Acceptable on cold cache: < 30 seconds.
  • NFR-2 — A typical 2-round, 8-question brainstorm MUST complete (excluding user think-time on answering questions) in under 3 minutes of fleet activity. Outliers acceptable when the inquisitors do heavy investigation.
  • NFR-3 — Plain /feature "<topic>" (no flags) latency MUST NOT regress by more than 5% compared to today's baseline. Test: a benchmark of /feature brainstorm phase against a fixed topic, before/after, on the same machine.
  • NFR-400-brainstorming.context.md MUST be loadable in under 100ms (typical < 50ms) by /feature --from-brainstorm. The schema parser uses the existing custom YAML parser; no js-yaml dep added.

Backward compatibility

  • NFR-5 — No changes to the existing WorkflowStage type that would break out-of-tree consumers. Any new field MUST be optional with default-undefined semantics.
  • NFR-6feature-pipeline.workflow.md MUST remain parseable by existing tests after this feature ships. The Phase 1 preQuestions block stays as a fallback for plain /feature.
  • NFR-7 — Session schema MUST NOT change. The brainstorm transcript is in-memory only during the run, then committed to the artifact pair on exit. No persistence in the session JSON.

Security

  • NFR-8 — Inquisitor workers are explorer agent_type (read-only). They MUST NOT receive write or shell permissions, even under --provider claude (the permissionGate in src/providers/claude/permissionGate.ts enforces this for non-bypassed types).
  • NFR-9 — The topic string passed to /brainstorm "<topic>" MUST be sanitized with escapeXml / neutralizePromptInput before injection into inquisitor system prompts. Same defense the existing slash commands use.
  • NFR-1000-brainstorming.md and 00-brainstorming.context.md MUST be written with mode 0o644 (consistent with other plan artifacts). .plans/ dir mode unchanged.
  • NFR-11 — No new MCP servers, no new external network calls, no new subprocesses outside the existing worker spawn path.

Testing

  • NFR-12 — New unit tests in src/commands/brainstormCommand.test.ts covering:
    • Argument parsing (--rounds, --resume, --unattended refusal, missing topic).
    • Single-round flow with mocked askUser and mocked coordinator.askUser returning predetermined answers.
    • N_min loop termination (continues until N_min, then asks summarize).
    • "summarize" choice exits the loop and writes both artifacts.
    • "keep grilling" choice runs another round.
    • Artifact schema v1 contents and YAML parseability.
  • NFR-13 — New unit tests in src/commands/featureCommand.test.ts covering:
    • --from-brainstorm <slug> loads context file and skips Phase 1.
    • --from-brainstorm <missing> errors with available-brainstorms list.
    • --from-brainstorm with newer schema_version errors actionably.
    • --deep-brainstorm "<topic>" runs the brainstorm workflow inline as Phase 1.
  • NFR-14 — New parser test (extension of T-153's parser.preQuestions.test.ts or sibling file): parses brainstorm.workflow.md end-to-end and validates stage count, preQuestions (if any), artifact field, dependency declarations.
  • NFR-15 — Full vitest suite + parity tests MUST pass before the feature ships. Same gate as T-153.
  • NFR-16 — Coverage thresholds (statements 80, branches 67, functions 75, lines 81) MUST NOT regress. New code in brainstormCommand.ts aims for ≥ 85% line coverage (loops are tricky; mock the askUser path heavily).

Documentation

  • NFR-17docs/commands-manual.md gains a /brainstorm section and updates the /feature section with --from-brainstorm and --deep-brainstorm examples.
  • NFR-18README.md gains a one-line mention of /brainstorm in the feature list.
  • NFR-19 — A new .fleet/context/architecture.md (or FLEET.md) entry mentions the brainstorm workflow alongside the existing /feature description.

Out of Scope

The following are explicitly NOT part of this feature. They MAY be done as follow-ups but MUST NOT block shipping:

  • OOS-1 — Declarative loop semantics in runWorkflowStages (e.g., repeat: until-user-says-stop stage attribute). The loop lives in brainstormCommand.ts for v1.
  • OOS-2 — Fix for the CoordinatorEngine.askUser() latent bug where --unattended mode doesn't short-circuit (the T-153 explorer's recommendation #3). /brainstorm refuses --unattended outright as a workaround. The fix is a separate task.
  • OOS-3 — Auto-detection of "complex enough domain to use multi-agent vs simple enough for single-agent" (the adaptive option D rejected during brainstorming). Always uses multi-agent on round 1.
  • OOS-4 — LLM-driven topic extraction (e.g., parse a long paste into a topic + sub-topics). Topic is the literal user-supplied string.
  • OOS-5 — Multi-user / multi-session collaboration on a single brainstorm. Each /brainstorm is a single-user session.
  • OOS-6 — Backfilling existing .plans/<slug>/ plans with a 00-brainstorming.context.md derived from their 01-brainstorming.md. New artifacts only.
  • OOS-7 — A /brainstorm list subcommand or REPL UI for browsing prior brainstorms. Users ls .plans/ for now. Could be added later if demand surfaces.
  • OOS-8 — A "merge two brainstorms" capability (/brainstorm merge <slug-a> <slug-b>).
  • OOS-9 — Hot-reload of inquisitor roles during a brainstorm. Roles are loaded at command start; mid-run edits don't apply.
  • OOS-10 — Cost telemetry per brainstorm (input/output tokens budgeted separately from the rest of the session). Token usage rolls up into the session totals as usual.
  • OOS-11 — Schema migration tooling for 00-brainstorming.context.md when schema_version bumps. v1 is the only schema for now; bump handling is a follow-up if/when v2 lands.
  • OOS-12 — Integration with /research (a sibling workflow). The two are conceptually similar but separate; cross-pollination is a future design choice.

Assumptions

  • ⚠️ ASSUMPTION: Slug naming uses the same slugify() from planDir.ts as /feature (descriptive prefix + 6-char hash) — REASON: consistency, plus this function is already battle-tested. No need for a brainstorm-specific naming convention. (Resolves Phase 1 OQ-2.)
  • ⚠️ ASSUMPTION: /feature --deep-brainstorm writes brainstorm artifacts inside the feature's plan dir (same slug) — REASON: the brainstorm IS Phase 1 in this mode; keeping artifacts together makes the plan dir self-contained. The 00- prefix still distinguishes brainstorm artifacts from the 01-07- feature artifacts. (Resolves Phase 1 OQ-3.)
  • ⚠️ ASSUMPTION: The askUser --unattended short-circuit fix is a STRICT pre-requisite for /feature --deep-brainstorm --unattended but NOT for standalone /brainstorm (which refuses --unattended outright). REASON: /brainstorm is interactive by design; /feature may run unattended and the deep-brainstorm flag should respect that. We can ship /brainstorm + plain /feature --from-brainstorm first; --deep-brainstorm --unattended waits on the askUser fix. (Resolves Phase 1 OQ-4.)
  • ⚠️ ASSUMPTION: Round 2+ defaults to coordinator-only follow-up questions (no re-spawn of inquisitors) — REASON: cost control. Re-spawning 3 explorers per round burns tokens and time; coordinator-driven follow-ups are sufficient for most cases. --full-inquisitors-each-round is the opt-in. (Resolves Brainstorming Risk #2.)
  • ⚠️ ASSUMPTION: Confidence scoring per Q/A is opt-in via heuristic, not always-asked — REASON: asking "how confident are you?" after every answer is fatiguing. Only ask when the answer is short or hedged. (Resolves Phase 1 OQ-5.)
  • ⚠️ ASSUMPTION: The custom YAML parser handles the schema v1 frontmatter shape (nested arrays of objects under qa_pairs, assumptions, etc.) — REASON: post-T-153, the parser correctly handles nested string lists under empty-value keys; nested objects-in-arrays was already supported. TO VERIFY in design phase by running a real schema instance through parseFrontmatter(). If not supported, we extend the parser similarly to T-153.
  • ⚠️ ASSUMPTION: Inquisitors are spawned via spawn_worker with explicit role: 'inquisitor-<angle>' — REASON: the existing crew system supports role-based spawning. We don't need a brainstorm-specific crew; the active crew (if any) is bypassed for these workers via the explicit role.
  • ⚠️ ASSUMPTION: A brainstorm aborted by /exit or Ctrl+C is discarded entirely (no partial artifacts) — REASON: a partial brainstorm misleads downstream /feature --from-brainstorm consumers. Simpler v1; recovery is just "run /brainstorm again".

Open Questions for Phase 3 (Research)

  • ⚠️ OPEN QUESTION (RES-1): What's the exact deduplication algorithm for collected questions across the 3 inquisitor outputs? (Lowercase + token overlap? Embedding similarity? Manual exclusion list?)
  • ⚠️ OPEN QUESTION (RES-2): How does the prioritization heuristic rank questions when more than 8 are returned? Need to understand the per-angle vs cross-cutting tradeoff.
  • ⚠️ OPEN QUESTION (RES-3): What's the exact prompt template structure for each inquisitor role that maximizes question quality without over-fitting to a particular project type?
  • ⚠️ OPEN QUESTION (RES-4): How are coordinator-driven follow-up questions (round 2+) generated — directly by the coordinator LLM, or by a small short-lived inquisitor spawn? Cost vs context-window tradeoff.
  • ⚠️ OPEN QUESTION (RES-5): How should the user signal "skip this question, it's irrelevant" mid-round? A special answer like skip parsed by the coordinator? A separate askUser choice?
  • ⚠️ OPEN QUESTION (RES-6): For /feature --from-brainstorm, what's the format of the "Phase 2 seed input" actually injected into the requirements prompt? Verbatim Q&A pairs, a synthesized summary, or both?

Pre-stage user answer

Q: Do these requirements look right? Anything to add or change? A: yes (answered before requirements existed; effectively "proceed". User-confirmation of these specific requirements happens implicitly via the next phase advancing — if requirements were off-base, user will catch in Phase 3.)


Phase 2 complete. Ready for Phase 3 (research).