feat(initiative-planner): cross-repo discussion_repo + PRD planning artifacts
Why
Graduating WorldChest from combsmith/incubator to combsmith/worldchest on 2026-10-21 exposed two gaps in the planner:
- The approved idea's Discussion lived in the incubator (#5) but the epic belongs in the product repo. The dispatch failed with
Could not resolve to a Discussion with the number of 5, and a mirror Discussion (worldchest #6) had to be hand-written. - The planner never read the product repo's
_bmad-output/planning-artifacts/, which orgAGENTS.mdnames as the planning source of truth. Bob planned from Discussion prose instead of John's PRD.
What changed
| Area | Change |
|---|---|
initiative-planner.yml | New optional discussion_repo input (default target_repo) → job env DISCUSSION_REPO; passed to apply-plan in Bob's prompt. GITHUB_TOKEN is used only when both target and discussion repo are self, otherwise the PAT. Concurrency key includes the discussion repo. |
gather-context.sh | Reads the Discussion and its referenced #N issues from DISCUSSION_REPO. Open epics, reconcile harvest and artifacts stay on REPO. Validates both repo slugs. New discussion_repo and planning_artifacts keys. Artifacts: contents-API listing; prd.md in full, other top-level .md truncated (PLANNING_ARTIFACT_MAX_CHARS, default 12000), at most 20 files, fetched raw into a temp dir (never on argv). 404 or no markdown → null, any other API error fails loud (same rule as decision-brief). |
apply-plan.sh / lib/mutations.sh | Cross-repo only: epic back-reference/idempotency key becomes Planned from idea discussion owner/repo#N, and issue links in the Discussion reply are qualified with the product repo. Same-repo output is byte-identical, so existing epics still bind. comment_on_discussion takes the discussion repo and logs it in DRY_RUN. The comment already routes to the Discussion's own repo through its global node id. |
redispatch.sh | Forwards DISCUSSION_REPO as discussion_repo only when set; the default dispatch is unchanged. |
prompts/bmad/scrum-master.md | New "Planning inputs" section. When a PRD exists, its FRs are the scope and its success metrics are the epic's metric; the Discussion is context. Conflicts go to open_questions. Cross-repo referenced_issues must not become blocked_by_existing_issues. |
| Docs | Graduation flow in docs/initiatives/idea-to-initiative-pipeline.md; README row updated. |
Tests
Added to tests/test_initiative_planner.bats, with gh mocked:
- cross-repo discussion read (gather-context) plus cross-repo apply (back-reference,
discussion_repoon the comment, qualified links) - same-repo apply unchanged (bare
#N) - artifacts present (PRD full, brief truncated, png/dir skipped, raw fetch)
- artifacts absent (
null, context keys otherwise unchanged) - 404 on the folder →
null, exit 0 - non-404 error → fails loud
- malformed
DISCUSSION_REPOrejected before any API call - workflow wiring (yq)
Added to tests/test_initiative_planner_redispatch.bats: discussion_repo is omitted by default, forwarded when set, and rejected when malformed.
Local runs: the planner, redispatch, reconcile and materialize suites pass (102 tests). shellcheck --severity=warning -x, actionlint -ignore SC2129, markdownlint-cli2 and check-bats-negation are clean.
Not in this PR
combsmith/.github'sinitiative-planner-reusable.ymlis untouched. It always plans same-repo, and the incubator has no planner stub, so graduation is a manual dispatch.- No release tag.
Next graduation
gh workflow run initiative-planner.yml --repo combsmith/.github-private \
-f discussion=<N> -f discussion_repo=combsmith/incubator \
-f target_repo=combsmith/<product> -f dry_run=true
🤖 Generated with Claude Code
Problem
See the linked issue.
Risk
Medium — changes GitHub Actions workflow behavior, which is exercised only post-merge; verify via the affected workflow runs.
Test plan
Tests added/updated: tests/test_initiative_planner.bats,tests/test_initiative_planner_redispatch.bats. Verification: bash scripts/dev-lead-lint.sh (shellcheck --severity=warning) ran pre-commit; the bats suite runs in CI.
Rollback
Revert this PR. No non-revertible side effects (no tags, migrations, or external state).
Monitoring
Watch the affected workflow run(s) in the Actions tab and this PR's Lint check for regressions.