$ cat workspace-template.yaml

B

Brainstorm to Design Spec

// Interactively turn an idea into a reviewed design spec the way a thoughtful collaborator would - ask clarifying questions one at a time, assess scope (and decompose if it is too big for one spec), explore 2-3 approaches and let you choose, draft the design and revise it with you, then self-review the spec for placeholders, contradictions, scope creep, and ambiguity before you take it into implementation planning. Gated and conversational, not a one-shot generator.

Document Generation
#brainstorm#design#spec#requirements#planning#architecture

// Canvas Preview

canvas.flow

// Instruction

instruction.md

Brainstorm to Design Spec

Overview

This workspace turns an idea into a structured, reviewed design spec through a real back-and-forth - the way a thoughtful collaborator would. It asks clarifying questions one at a time, assesses scope (and helps decompose if the idea is too big for one spec), explores 2-3 approaches and lets the user pick, drafts the design and revises it with them, then self-reviews the spec for placeholders, contradictions, scope creep, and ambiguity. The graph nodes hold the durable, inspectable artifacts (requirements brief -> approaches -> design -> finalized spec); the dialogue around them is the user's. It produces a spec and stops - it never writes code, and it saves the spec only if asked. The far-left Context section holds the source nodes: Idea & Clarifications is the required input (already wired into Make Array); the optional Drive and web sources start disconnected and you connect only the ones the user provides.

Workflow Chain

[Context]  (section, far left)  [Idea & Clarifications (Text)] -----------------------+   (REQUIRED - already wired into Make Array item_0)  [Drive Document Reader]   (optional - start DISCONNECTED)|  [Web Search] -> [Fetch URL as Markdown]  (optional - Fetch starts DISCONNECTED from Make Array)        |                                                  |        |  (Phase 1: connect ONLY the provided context source(s) into a free Make Array item port)        v                                                  v   [Make Array] -> [Synthesize Requirements (Text Summarizer)]   (Phase 3)                      -> [Explore Approaches (Text Transform)]    (Phase 4)                         -> [Compose Design Spec (Text Transform)]  (Phase 5)                            -> [Self-Review Spec (Text Transform)]   (Phase 6)                               -> [Save Spec (Save File)]   (Phase 7 - only if the user asks)

Node Reference

  • Context (section) - visual group holding the source nodes.
  • Idea & Clarifications (Text) - the REQUIRED input: the user's idea plus the clarifying answers you collect in Phase 2. Configure value via upsertNode. Output value is already wired to Make Array item_0 - do not disconnect it. It is also a reusable canvas store - see "Text Nodes as a Canvas Store".
  • Drive Document Reader - reads existing project context from Drive (prior specs, README, design docs). Configure driveItemId via selectDriveItem. Output port: content. Starts disconnected from Make Array.
  • Web Search - finds prior-art / landscape URLs. Configure query, num_results. Output urls already feeds its Fetch node.
  • Fetch URL as Markdown - fetches the searched URLs as Markdown. Input urls from Web Search (pre-wired). Output port: markdown. Starts disconnected from Make Array.
  • Make Array - collects the connected source texts into one ordered array. Item ports item_0..item_9 (item_0 = the idea, already wired). Output items -> Synthesize Requirements content.
  • Synthesize Requirements (Text Summarizer) - reads everything and produces a structured REQUIREMENTS BRIEF (purpose, constraints, success criteria, in/out of scope, scope assessment, open questions). Configure: prompt (baked; substitute {{topic}}), llmModel. Output: summary.
  • Explore Approaches (Text Transform) - proposes 2-3 distinct approaches with trade-offs and a recommendation, carrying the brief forward. Input input_text from the brief. Output: output_text.
  • Compose Design Spec (Text Transform) - writes the full design for the SELECTED approach. Input input_text from the approaches. Configure: prompt (baked; substitute {{topic}}, append SELECTED APPROACH: / REVISION NOTES: lines). Output: output_text = the design spec.
  • Self-Review Spec (Text Transform) - reviews the spec with fresh eyes and fixes placeholders / contradictions / scope / ambiguity inline. Input input_text from the design spec. Output: output_text = the finalized spec.
  • Save Spec (Save File) - saves the finalized spec to Drive. Configure destinationFolder via selectDriveItem, name. Output: driveItemId. Side-effect terminal - offered in followUp, never auto-run.

Text Nodes as a Canvas Store

The Text node type (the same node template as Idea & Clarifications) is a general-purpose, inspectable store: it just holds a value string and outputs it unchanged. Use Text nodes to keep the dialogue's durable state ON THE CANVAS, instead of only in chat or buried inside a node's prompt.

  • Update an existing store: upsertNode the Text node's value (this is exactly how Phase 2 records the idea + clarifications into Idea & Clarifications).
  • Add a new store: cloneNodes the Idea & Clarifications node, then upsertNode the clone's label (e.g. "Chosen Approach", "Decomposition Plan", "Revision Log") and its value, and place it in the Context section. If the clone inherits the idea's edge, deleteEdge it - a store stays DISCONNECTED unless you actually want its text to flow into a downstream node (an unconnected Text node is inspectable but never executed, so it can never block the run). NEVER remove the required Idea & Clarifications -> Make Array item_0 edge.
  • Why: storing a decision as a Text node makes it a durable artifact a teammate can open and audit, and lets a later edit turn re-read it instead of re-deriving it. Anything that must FLOW into a node's computation (the chosen approach, revision notes) is still appended to that node's prompt as well; the Text store is the inspectable record of it.

Execution Strategy

You MUST complete all 7 phases in order: Phase 1 -> Phase 2 -> Phase 3 -> Phase 4 -> Phase 5 -> Phase 6 -> Phase 7. Do NOT skip any phase. This template is deliberately interactive: the clarifying dialogue in Phase 2 happens in NORMAL CHAT, one question at a time, and there are explicit user-approval gates at Phases 4 and 5. Do NOT collapse the dialogue into a single up-front form, and do NOT run the pipeline to the end without the gates.

Phase 1: Understand the idea and set up sources

  1. Read the idea from the Idea & Clarifications node value (seeded from {{idea}}). If it is empty or a single vague line, ask the user in chat for the core idea before continuing - one short message, then wait for their reply.
  2. Assess raw scope from the idea alone. If it already obviously spans multiple independent subsystems (e.g. "a platform with chat, billing, storage, and analytics"), make a mental note - you will handle decomposition at Phase 3; do not let it derail Phase 2.
  3. Call requestUserDecision ONCE to set up context sources (this is the only structured setup prompt): key sources (allowMultiple), question "What project context can I pull in?", context "Optional - the idea alone is enough; pick any that apply.", options: New / greenfield (none), Existing docs in Drive, Research prior art on the web. The free-text box captures the web-search topic and/or any context to paste. Store sourcesChoice = answers.find(a => a.key === "sources")?.selectedIds ?? []; if cancelled, treat as greenfield (no extra sources).
  4. For EACH chosen source, configure it and upsertEdge its text output into the next free Make Array item port (item_1, then item_2, ...):
    • Existing docs in Drive: selectDriveItem -> upsertNode Drive Document Reader driveItemId -> upsertEdge its content -> Make Array item_1.
    • Research prior art: upsertNode Web Search query (from the free text; Web Search already feeds its Fetch node) -> upsertEdge the Fetch markdown -> Make Array item_2.
    • Greenfield: connect no extra source. If the user pasted context in the free text, fold it into the Idea node value in Phase 2. The Drive picker (selectDriveItem) is unavoidable and is NOT a clarifying question. Never touch a source the user did not pick (an empty Drive reader / empty query would fail and block the run).

Phase 1 complete. Now proceed to Phase 2. Do NOT skip to Phase 3.

Phase 2: Clarify the idea - one question at a time, in chat

  1. Hold a short clarifying dialogue IN NORMAL CHAT. Do NOT use requestUserDecision for this - these are open, adaptive questions, not config buttons. Focus on purpose, constraints, and success criteria, and prefer one concrete question per message so each follows from the last answer.
  2. Run the clarifying loop with an explicit bound: a. Ask ONE clarifying question in chat. Wait for the user's reply. b. Decide whether another question is genuinely needed. If yes, return to (a). c. Stop when you can state the purpose, the key constraints, and the success criteria - OR the user says to proceed. Ask at least 1 and at most 6 questions; never interrogate past what you need (YAGNI applies to questions too).
  3. Write the accumulated understanding into the Idea & Clarifications node: upsertNode its value to the idea plus the clarifying Q&A and any pasted context, as labelled sections (## Idea, ## Clarifications, ## Context). This node is already wired to Make Array item_0; do not add another edge.

Phase 2 complete. Now proceed to Phase 3.

Phase 3: Synthesize requirements and confirm scope

  1. Substitute {{topic}} into the Synthesize Requirements and Compose Design Spec prompts via upsertNode (derive a short working title from the idea if the user did not give one). Then nodeExecutor Synthesize Requirements - it auto-resolves Make Array and every connected source upstream.
  2. getNodeOutput and present the REQUIREMENTS BRIEF in chat. Do NOT poll in a loop.
  3. Scope gate (single step, inline branch):
    • If the brief's Scope Assessment says the idea needs decomposing into independent subsystems: stop and help the user decompose in chat - name the independent pieces and a build order, agree which ONE sub-project to design now, then upsertNode the Idea & Clarifications value to narrow it to that sub-project and re-run step 8-9. Note the rest as follow-on specs. Capture the decomposition (the pieces, the build order, the chosen sub-project) in a disconnected "Decomposition Plan" Text store so the split stays inspectable on the canvas (see "Text Nodes as a Canvas Store").
    • Otherwise: confirm in chat that the brief looks right ("Anything to correct before I explore approaches?") and continue. This is a chat confirmation, not a requestUserDecision.

Phase 3 complete. Now proceed to Phase 4.

Phase 4: Explore approaches and let the user choose

  1. nodeExecutor Explore Approaches - it auto-resolves the brief upstream.
  2. getNodeOutput and present the 2-3 approaches in chat, leading with your recommendation and why.
  3. Approach gate - call requestUserDecision ONCE: key approach, question "Which approach should I design?", context "I will write the full design for the one you pick.", options built from the approaches (e.g. Approach A - <name> (recommended), Approach B - <name>, ...). The free-text box lets the user ask for a different or blended approach. Store approachChoice = answers.find(a => a.key === "approach")?.selectedIds?.[0].
    • If the user asked for something different (free text), or cancelled with feedback: revise in chat, upsertNode the Explore Approaches prompt with the steer, and re-run step 11-13. Do NOT proceed to Phase 5 until an approach is chosen.

Phase 4 complete. Now proceed to Phase 5.

Phase 5: Compose the design and approve it together

  1. Record the choice on the design node: upsertNode Compose Design Spec prompt, appending a line SELECTED APPROACH: <the chosen approach> after its baked instructions. You may also keep it as a durable artifact - clone Idea & Clarifications into a disconnected "Chosen Approach" Text store and set its value (see "Text Nodes as a Canvas Store").
  2. nodeExecutor Compose Design Spec - it auto-resolves the approaches upstream. getNodeOutput.
  3. Present the design to the user section by section in chat (Summary, Architecture, Components, Data Flow, Error Handling, Testing) - scale each to its complexity and ask, per section, whether it looks right.
  4. Design approval gate - this is the HARD GATE. Repeat until the user approves: a. Collect the user's feedback across the sections (chat). b. If they request any change: upsertNode the Compose Design Spec prompt, appending a line REVISION NOTES: <their feedback>, then re-run step 15-16. c. If they approve: continue. Do NOT proceed to Phase 6 until the user has explicitly approved the design. Do NOT write code or invoke any implementation step - producing the spec is the terminal goal.

Phase 5 complete. Now proceed to Phase 6.

Phase 6: Self-review the spec and let the user review it

  1. nodeExecutor Self-Review Spec - it auto-resolves the approved design upstream and fixes placeholders / contradictions / scope / ambiguity inline. getNodeOutput.
  2. Present the finalized spec and ask the user to review it: "Spec finalized below. Review it and tell me if you want any changes before we wrap." Wait for the reply (chat, not requestUserDecision). If they request changes, feed them back - upsertNode the relevant node's prompt (Compose for content changes, Self-Review for tightening) with the notes, re-run from that node, and re-present. Loop until they approve.

Phase 6 complete. Now proceed to Phase 7.

Phase 7: Verify and finish

  1. verification - present the final audit (requirements -> chosen approach -> finalized spec) to the user. The spec is the terminal artifact; do NOT invoke any implementation step or write code.
  2. followUp - summarize, and OFFER (do NOT auto-run) to: save the spec to Drive (run Save Spec with a selectDriveItem destination and a <YYYY-MM-DD>-<topic>-design.md name only if the user then asks - saving is a side effect, so it is never automatic), and note the natural next step is to take this spec into implementation planning. Saving is the only side effect and is offered here, so calling followUp directly after verification is correct. On an edit turn, infer intent from prior state (previously saved -> refresh) without re-running the dialogue.

Configuration Tips

User saysConfigure
"It's a greenfield idea"Phase 1 sources=New / greenfield; connect no extra sources
"Here are our existing design docs"Configure Drive Document Reader; upsertEdge its content -> next free Make Array item port
"Look at how others solved this"Set Web Search query; upsertEdge Fetch markdown -> next free Make Array item port
"Stop asking, just draft it"End the Phase 2 clarifying loop early and proceed to Phase 3
"This is a big system"Phase 3 scope gate: if the brief says decompose, agree on the first sub-project and design only that
"I want Approach B"Phase 4: store approachChoice; append SELECTED APPROACH: B to Compose Design Spec prompt
"Change the error-handling section"Phase 5/6: append REVISION NOTES: ... to Compose Design Spec prompt; re-run Compose -> Self-Review
"Use the bigger model"Synthesize / Explore / Compose / Review: llmModel=gpt-oss-120b
"Just give me the requirements"Run Phases 1-3 only; skip Approaches, Compose, Review, Save
"Save it to this folder"Phase 7 followUp: selectDriveItem on Save Spec, then run it
"Keep a record of the decisions"Clone Idea & Clarifications into disconnected Text stores (e.g. Chosen Approach, Decomposition Plan) - see "Text Nodes as a Canvas Store"

Incremental Edits to an Existing Spec

If the canvas already holds a built, executed pipeline and a finalized spec from a PRIOR turn, and the user asks for a small change ("add a caching section", "tighten the testing part", "switch to Approach B"), treat it as an EDIT - do NOT re-run the Phase 2 clarifying dialogue or the Phase 4/5 gates from scratch:

  • Content change -> upsertNode Compose Design Spec prompt with REVISION NOTES: <delta>, re-run Compose -> Self-Review, re-present, get approval.
  • Different approach -> upsertNode Compose prompt SELECTED APPROACH: <new>, re-run Compose -> Self-Review.
  • Re-tighten only -> re-run Self-Review Spec. Then re-present and, if the spec was previously saved, offer to refresh the saved copy (do NOT auto-save). A bundled "build AND tweak" request is a full build - run all 7 phases.

Error Handling

  • Empty or thin REQUIREMENTS BRIEF -> the Idea & Clarifications node is empty or item_0 got disconnected; confirm the idea text is set on the node and its value -> Make Array item_0 edge exists, then re-run.
  • A context source node left disconnected by design - that is correct; only connected sources execute. Never connect a source the user did not provide (an empty Drive reader / empty query would fail and block the run).
  • Web Search rate_limited=true or empty urls -> fall back to a Drive doc or proceed greenfield (the idea alone is enough).
  • Fetch failed_count high -> some URLs were unreachable/SSRF-blocked; the array still carries the successful entries; supply different URLs or skip web research.
  • User keeps requesting design changes -> that is the Phase 5 revise loop working; keep appending REVISION NOTES: and re-running Compose until they approve. Do NOT proceed to Phase 6 unapproved.
  • Spec still has "TBD"/placeholders after Self-Review -> the brief had unresolved Open Questions; surface them in chat, get the missing facts, update the Idea & Clarifications node, and re-run from Synthesize Requirements.
  • Spec sprawls across multiple subsystems -> the idea needed decomposing at the Phase 3 scope gate; narrow to the first sub-project and note the rest under Out of Scope.
  • "destinationFolder required" on Save Spec -> the selectDriveItem step was skipped; pick a folder then re-run Save Spec.

// Dependencies

requirements.py
1from input import Text2from input import DriveDocumentReader3from input import WebSearch4from process import FetchURLAsMarkdown5from process import MakeArray6from process import TextSummarizer7from process import TextTransform8from output import SaveFile

// Variables

variables.yaml
1idea:2  type: undefined3  label: "Idea"4  description: "The feature, change, or idea to brainstorm into a design spec."5  required: undefined67topic:8  type: undefined9  label: "Topic"10  description: "Short name for the design, used in the spec title and filename."11  required: undefined

$ git log --oneline

v1.0.3
HEAD
2026-06-18
v1.0.22026-06-18
v1.0.12026-06-13
v1.0.02026-06-13