bmad-brainstorming: selectable ideas + Export, in the artifact's own style#2559
Conversation
…t's own visual style Every generated brainstorm.html now lets the user mark favorites — every idea, every synthesis insight, every chosen-direction card — using a selection control built in that session's own visual language, never a generic bolted-on toolbar. An in-theme Export button (visible once something's selected) downloads the picks as selection.json, since a static local HTML page can't write files or invoke a script directly. scripts/export-ideas.py is the other half of that handoff: it reads the downloaded selection.json and writes a clean selected-ideas.md next to the artifact, ready to feed into bmad-forge-idea, bmad-product-brief, or another round of bmad-brainstorming scoped to just the picks.
🤖 Augment PR SummarySummary: This PR makes brainstorm HTML keepsakes actionable by letting users mark favorite ideas/insights/directions and export them for downstream skills. Changes:
Technical Notes: The export script is designed as a “bridge” between static HTML constraints and markdown artifacts that can be fed into 🤖 Was this summary useful? React with 👍 or 👎 |
| for item in items: | ||
| if not isinstance(item, dict): | ||
| continue | ||
| text = " ".join(str(item.get("text", "")).split()) # collapse whitespace, no prose bloat |
There was a problem hiding this comment.
src/core-skills/bmad-brainstorming/scripts/export-ideas.py:45 — If an item has "text": null, str(None) becomes the literal string "None", so the output markdown would include a bogus bullet instead of skipping it like other blank texts.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| try: | ||
| data = json.loads(path.read_text(encoding="utf-8")) | ||
| except OSError as e: | ||
| raise SystemExit(f"error: could not read {path}: {e}") |
There was a problem hiding this comment.
src/core-skills/bmad-brainstorming/scripts/export-ideas.py:32 — load_selection() raises SystemExit, but main() returns status code 2 for other input problems; this means malformed JSON/non-array JSON will typically exit with code 1 instead of 2, which may be surprising if callers/scripts interpret exit codes.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
|
|
||
| workspace = Path(args.workspace) | ||
| workspace.mkdir(parents=True, exist_ok=True) | ||
| out_path = workspace / args.out_name |
There was a problem hiding this comment.
src/core-skills/bmad-brainstorming/scripts/export-ideas.py:90 — out_path = workspace / args.out_name will ignore workspace if --out-name is absolute (and can also traverse with ../), so the script can write outside the intended session directory even though the flag help says it’s “within --workspace”.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Why
While reviewing a brainstorm, there was no way to act on it — just scroll and read. This lets the user mark the ideas (and insights, and chosen-direction cards) they like as they read, then export that shortlist for later — into
bmad-forge-idea,bmad-product-brief, or another round ofbmad-brainstorming.What's in this PR
references/finalize.md: every generatedbrainstorm.htmlmust let the user mark favorites — every idea, every synthesis insight, every chosen-direction/convergence card — using a selection control built in that session's own visual language (checkbox, toggle, tap-to-star, whatever fits), never a generic bolted-on toolbar. An in-theme Export button appears once something's selected.{text, section}for every selected item and downloads it asselection.json— a static local HTML page can't write files or invoke a script directly, so a browser download is the only thing its JS can do. The page then shows an in-page note pointing the user at the next step.src/core-skills/bmad-brainstorming/scripts/export-ideas.py: reads thatselection.jsonand writes a cleanselected-ideas.mdnext to the artifact, grouped by section, with pointers to what to feed it into next.Test plan
uv run --with pytest pytest scripts/tests/test_export_ideas.py— 10/10 passingselection.jsonmatching what a real click would produce, ranexport-ideas.pyagainst it, confirmedselected-ideas.mdlanded correctly grouped next to the artifact