feat(decision-brief): wire the decision-brief stage (Mary → ideas/<slug>/brief.md at Ripe)
Summary
Implements combsmith/incubator#3 — Wire the decision-brief agent stage (Mary → brief.md at "Ripe"). References it; does not close it (the incubator side is a follow-up, below).
Before this, a human applied idea:approved on one feature-ideation enhancement comment and a triage score; nothing ever produced a decision brief. This adds the stage, built the same way as idea-triage / initiative-planner:
| Piece | File | What it does |
|---|---|---|
| Central run (org-private automation) | .github/workflows/decision-brief.yml | Mary (BMAD Analyst, vendored skills read by path via prompts/incubation/decision-brief-stage.md) fills the target repo's own ideas/_TEMPLATE/{brief,market-research,ost}.md for one Ideas Discussion: problem + JTBD with the evidence, cited market context, OST, ICE by default (RICE only with a cited Reach; Confidence tied to the evidence rung), a riskiest-assumption + cheapest-test table, and a go / no-go / park recommendation that names the idea:approved gate. Triggers: needs-brief label (redispatch bridge — claude-code-action aborts on discussion events) or from_queue=true (brief every idea idea-triage ranked Ripe that has no brief yet, capped). AGENTS_PAUSED-gated; manual dispatch defaults dry_run: true. |
| Provenance guard (#1160) | scripts/decision-brief/validate-package.sh | Runs as its own step after the model. Any quantified market claim without a URL / [^n] footnote / [ASSUMPTION] / "unknown — needs discovery", a missing score or Confidence, an empty assumptions table, a recommendation that takes no position, or a leftover template placeholder fails the run — the package stays an artifact and never becomes a PR. market-research.md must end with ## Sources. |
| PR opener | scripts/decision-brief/open-pr.sh | Lands the package on incubate/<slug> (the incubator's own naming) via the Git Data API — one commit, author = the business-analyst persona's runtime account — opens or refreshes the PR (label decision-brief), links it from the Discussion. Never applies idea:approved. |
| Fleet dispatch reusable (hosted here) | .github/workflows/decision-brief-reusable.yml | What caller stubs pin at @decision-brief/v1-stable: trusted-actor guard on the label path; schedule/manual → the sweep; dispatches the central run with target_repo=<caller>. |
| Thin caller stub | standards/workflows/decision-brief.yml | The file the incubator adds under .github/workflows/. Staging copy here so stub + reusable ship in one reviewed change; to be promoted to combsmith/.github/standards/workflows/. |
| Overlays | prompts/incubation/decision-brief-stage.md, producer-ost.md | The four inputs the decider needs (from the BA advisory on the issue), the scoring rubric, the no-fabrication rule. |
| Tests | tests/test_decision_brief.bats (34), tests/test_decision_brief_workflow.bats (21) | gh mocked; fixtures under tests/fixtures/decision-brief/ (a passing package, the untouched incubator template — which must fail — and a queue body). Wired into lint.yml. |
| Wiring | registry, docs | fleet-pause registry row (+ regenerated AGENTS.md table), §4 row + exclusion row in docs/agentic-interaction-model.md, cut-release.sh valid_agent, versioning table, pipeline doc, READMEs, AGENTS.md exception bullet. |
Design notes:
- The sweep is how "reaches Ripe in idea-triage" fires without touching idea-triage: it reads the target's Idea Promotion Queue Ripe table and dispatches one run per idea, so each idea has its own concurrency lane and PR.
- A brief that honestly says market size unknown — needs discovery; Confidence 1/5; recommendation: park, run five problem interviews is a correct output. A confident
$2.4B TAMwith no URL is a failure. The validator makes that mechanical. - The incubation gate in the incubator requires all four artifacts (
brainstorm.md,prd.mdtoo) to go green. A brief PR will therefore show the gate red until a human adds the brainstorm and John writes the PRD. That is by design in the incubator's package spec, not a defect of this stage; the PR body Mary writes says so.
Verified locally
shellcheck · actionlint · yamllint (CI config) · markdownlint · check-model-pins · validate-workflow-schedules · validate-caller-inputs (incl. stub↔reusable pair) · validate-interaction-model · interaction contracts · reusable-pin compliance · verify-persona-identity · fleet-pause coverage (python + bats, 60/60) · duplicate-decl + fixed-tmp gates · bats-negation · test_decision_brief*.bats 55/55 · test_cut_release.bats.
Follow-ups (not in this PR)
- combsmith/incubator — a PR adding
.github/workflows/decision-brief.yml(copy ofstandards/workflows/decision-brief.yml) and creating theneeds-briefandidea:approvedlabels (plusdecision-brieffor the PRs, created automatically on first use).ideas/_TEMPLATE/is already there. Optional: adoptidea-triage.ymlso the Ripe sweep has a queue to read. - Release — cut
decision-brief/v1.0.0+decision-brief/v1-stablewithscripts/cut-release.sh decision-brief 1.0.0 --channel stable --pushonce merged (autocut coversnextonly for registered agents;decision-briefis not instandards/canary-rings.jsonyet), and adddecision-brief/**to therelease-channel-tagsruleset (admin). - combsmith/.github — promote the stub to
standards/workflows/decision-brief.ymland add the stage toci-standards.md§10; register the agent instandards/canary-rings.json.
🤖 Generated with Claude Code