feat(decision-brief): wire the decision-brief stage (Mary → ideas/<slug>/brief.md at Ripe)

Merged
DO
5d ago
+3737-10

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:

PieceFileWhat it does
Central run (org-private automation).github/workflows/decision-brief.ymlMary (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.shRuns 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 openerscripts/decision-brief/open-pr.shLands 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.ymlWhat 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 stubstandards/workflows/decision-brief.ymlThe 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/.
Overlaysprompts/incubation/decision-brief-stage.md, producer-ost.mdThe four inputs the decider needs (from the BA advisory on the issue), the scoring rubric, the no-fabrication rule.
Teststests/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.
Wiringregistry, docsfleet-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 TAM with no URL is a failure. The validator makes that mechanical.
  • The incubation gate in the incubator requires all four artifacts (brainstorm.md, prd.md too) 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)

  1. combsmith/incubator — a PR adding .github/workflows/decision-brief.yml (copy of standards/workflows/decision-brief.yml) and creating the needs-brief and idea:approved labels (plus decision-brief for the PRs, created automatically on first use). ideas/_TEMPLATE/ is already there. Optional: adopt idea-triage.yml so the Ripe sweep has a queue to read.
  2. Release — cut decision-brief/v1.0.0 + decision-brief/v1-stable with scripts/cut-release.sh decision-brief 1.0.0 --channel stable --push once merged (autocut covers next only for registered agents; decision-brief is not in standards/canary-rings.json yet), and add decision-brief/** to the release-channel-tags ruleset (admin).
  3. combsmith/.github — promote the stub to standards/workflows/decision-brief.yml and add the stage to ci-standards.md §10; register the agent in standards/canary-rings.json.

🤖 Generated with Claude Code