<!-- Authored per the the-loop:writing skill. -->
Bugfix spec: a brainstorm moves on before its author has finished with it
Phase 1 (bugfix → design → testing plan → tasks). Tier 3 (
human-approves-pr): it adds a human gate to the shipped outer-loop graph and a row to thephase-selectionchecklist. No credential, token scope or schema changes.
Summary
Issue #494, opened by @MadaraUchiha-314: "Any comment on the PR or work item in the brainstorming phase immediately moves it to requirements phase." The fix the issue asks for: "an approval phase for the brainstorming phase as well … so that the author can add multiple comments during the brainstorming phase and ask clarification questions."
Impact. Brainstorming is the one phase meant to stay open while the author thinks out loud. Today it closes on the first reply, so the author's second comment arrives in requirements, and the thing being discussed is no longer the brainstorm.
Steps to reproduce
- Arm a work item and leave
brainstormingticked atphase-selection. - The session writes
brainstorm.md, pushes it to the PR and runsthe-loop graph complete <id>. - The author comments on the PR with a question.
- The session answers, edits
brainstorm.md, and runsgraph completeagain (or has already). The pointer is onrequirements-definition, and the label isloop:requirements-definition.
Expected vs actual
- Expected: the brainstorm stays open across any number of comments and questions. It moves to requirements only when an authorized person approves it, as requirements and design already do.
- Actual:
brainstorminghas no approval node after it. Its exit chain checks shape only (validate-artifactsfor Problem / opportunity and Open questions, thenlint-artifacts), so it passes as soon asbrainstorm.mdexists, and itspassedge goes straight torequirements-definition.
Root cause (confirmed)
issue-281 decided that brainstorm.md has no gate and advances on shape alone (skills/the-loop/SKILL.md, Gate-less artifacts advance on shape alone). That rule holds for tasks.md, which is derived from a pair the human has just approved. It does not hold for brainstorm.md: a brainstorm is the root artifact, nothing upstream of it was approved, and its whole job is to be discussed. The graph (cli/the_loop/graph/pdlc-work-item-loop.yaml) encodes the rule as {from: brainstorming, to: requirements-definition, on: pass}.
Requirements
Requirement 1 — the brainstorm waits for its author's approval
User story: as the author of a brainstorm, I want it to stay open until I approve it, so that I can comment and ask questions as many times as I need first.
Acceptance criteria (EARS)
- WHEN
brainstormingpasses withbrainstorm.mdpresent THEN the outer loop SHALL enter a human approval node,brainstorm-approval, rather thanrequirements-definition. - WHILE the pointer is on
brainstorm-approval, WHEN a comment arrives that does not decide the review (a question, a partial review, a remark) THEN the gate SHALL keep waiting, and the work item SHALL stay in thebrainstormingphase, its labelloop:brainstorming. - WHEN an authorized user approves (or approves with comments) at
brainstorm-approvalTHEN the loop SHALL record the feedback inbrainstorm.md's Review comments, setstatus: approvedand the approvers in its front matter, and move torequirements-definition. - WHEN an authorized user requests changes at
brainstorm-approvalTHEN the loop SHALL return tobrainstorming. - The gate SHALL reuse the existing human-gate hooks (
request-review,notify,classify-feedback,record-feedback,lock-artifacts), so its authorization and classification are identical torequirements-approval's. - The fix SHALL include regression tests that fail before the fix and pass after it: a graph walk where an indecisive comment leaves the item at
brainstorm-approval, and one where an approval locksbrainstorm.mdand reachesrequirements-definition.
Requirement 2 — a work item that does not brainstorm is not held
User story: as an author whose scope is already clear, I want to leave brainstorming out without being asked to approve a document that does not exist.
Acceptance criteria (EARS)
- WHEN
brainstormingcompletes without producingbrainstorm.mdTHEN the loop SHALL route directly torequirements-definitionand SHALL NOT enterbrainstorm-approval. - WHEN
brainstormingis declared skipped THEN the loop SHALL route torequirements-definition, andbrainstorm-approvalSHALL NOT be entered. brainstorm-approvalSHALL be selectable atphase-selection(a ticked-by-default row, likerequirements-approval) and a member of thespec-chainskip set. WHEN it alone is declared skipped THENbrainstormingSHALL route torequirements-definitiononpass, as it does today.- A custom graph whose optional node does not ask for the new routing SHALL behave exactly as before: the "nothing produced" route is opted into per hook entry.
Requirement 3 — the documentation says what the graph does
- The skill, the workflow reference, the
brainstorm,new-requirementandwork-oncommands and thespec-workflowcapability doc SHALL describebrainstorm-approval, and SHALL no longer say thatbrainstorm.mdhas no gate or is never approved. new-requirement's instruction to lock an unlocked brainstorm first SHALL account for abrainstorm-approvalthat was declared skipped.
Security considerations
No new attack surface, and the one trust boundary involved is reused, not widened.
- Untrusted actors. Anyone who can comment on the public issue or PR. Their comment text reaches
classify-feedback. - Trust boundary. The comment → gate classification boundary, which
requirements-approvalanddesign-approvalalready cross. The new gate uses the same hooks, so onlyauthorizedUsersare read, self-authored comments are ignored, and the classification is a closed set that only the graph's declared edges route on. - Abuse case. An unauthorized commenter writes "approved" on a brainstorm PR to push the item into requirements. Defeated by
classify-feedbackreading authorized authors only; the regression test asserts the gate keeps waiting. - Abuse case. A repository-supplied (
x-) hook declares the new "not entered" outcome to bypass the gate. Defeated by the chain's existing_disarm_routing, which drops any outcome a repository hook declares. - Fail closed. No reply, or a reply that is not decisive, leaves the gate waiting. It never times out into approval.
Out of scope
- Changing how
classify-feedbackdecides what is "decisive". The gate inherits it as it is. - An approval gate for
tasks.md. It is derived from a pair the human has just approved, which is the case issue-281's rule was right about. - Migrating work items already past
brainstorming.
Open questions
None open. The issue states the fix, and the owner declared requirements-approval and design-approval skipped for this item, so the spec is reviewed on the PR with the code.