Skip to content

feat(tickets): preview a parent initiative chain in the dry run and TUI (DW-574, 3/3) - #1013

Merged
pbean merged 4 commits into
dw-ledger-1028/05-chain-driverfrom
dw-ledger-1028/06-chain-preview
Oct 30, 2026
Merged

pbean merged 4 commits into
dw-ledger-1028/05-chain-driverfrom
dw-ledger-1028/06-chain-preview

Conversation

@pbean

@pbean pbean commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Part 6 of 8 of the deferred-work ledger stack (DW-574, 3 of 3).

What

Preview, TUI, E2E and docs for the parent initiative chain.

Why

Without this, run --dry-run on a parent exits 1, the TUI start preview cannot show what a chain builds, and a chained run's board reads the wrong tree.

How

  • run --dry-run on a parent lists its children in build order (status, ticket counts, what each waits on, a tag), prints the first child's tickets block, and ends with the predicted chain start or the end line.
  • TUI: the start-run preview shows the chain. A chained run's tickets board reads through its child folder.
  • E2E row 15 (real tmux, zero tokens): a parent with children A then B. A pauses at its epic boundary, A's epic is closed and the run resumed, A is closed, and B builds and pauses.
  • Docs and CHANGELOG.

Testing

  • uv run pytest -q -n logical at this PR's tip: 17607 passed, 124 skipped.
  • uv run pyright (1.1.411): 0 errors.
  • CI.

Changelog

## [Unreleased] / Added: build a parent initiative's children one run each (DW-574).

Summary by CodeRabbit

  • New Features
    • Parent initiatives can now run their child initiatives in build order, with a shared story limit. Runs pause at each epic boundary and continue to the next child after the completed child is closed.
    • The CLI dry run and TUI preview show the child build order, readiness, dependencies, ticket counts, and expected chain outcome. The tickets board displays the current child’s tickets.
  • Bug Fixes
    • Preflight checks now report parent-initiative issues, and parent runs refuse unsupported epic or story selectors.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Walkthrough

Parent-initiative runs now build child initiatives in separate runs, with worktree isolation and epic-boundary pauses. The CLI previews the chain, and the TUI shows child status and ticket boards. Tests cover previews, isolation checks, and resumed child runs.

Changes

Parent-initiative ticket chains

Layer / File(s) Summary
Chain checks and CLI preview
src/bmad_loop/cli.py, src/bmad_loop/install.py, src/bmad_loop/initiativechain.py, tests/test_cli.py, docs/reference/cli.md, docs/tickets-guide.md, CHANGELOG.md
The CLI checks parent-chain preflight conditions, refuses --epic and --story selectors on parent initiatives, and previews children, ticket counts, prerequisites, and predicted chain outcomes. Tests verify selector refusals and that previews do not change repository state.
TUI chain preview and child board
src/bmad_loop/tui/data.py, src/bmad_loop/tui/screens/modals.py, tests/test_tui_data.py, tests/test_tui_app.py, docs/tui-guide.md, docs/FEATURES.md
The TUI lists children and their status, prerequisites, and ticket counts. It reads the selected child’s board while pinning the ticket tree to the parent initiative.
Chained-run integration coverage
tests/test_tickets_e2e.py, tests/test_conftest.py
End-to-end tests cover ordered child runs, epic-boundary pauses, resumption, and isolation preflight. Test helpers create parent-child ticket trees and inspect individual runs.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  actor Operator
  participant RunCLI
  participant ParentInitiative
  participant ChildRun
  participant TicketTree
  Operator->>RunCLI: start run for parent initiative
  RunCLI->>ParentInitiative: select next eligible child
  RunCLI->>ChildRun: start child run in isolated worktree
  ChildRun->>TicketTree: build child tickets
  ChildRun-->>RunCLI: pause at epic-boundary
  Operator->>RunCLI: close epic and resume chain
  RunCLI->>ParentInitiative: close drained child and select next child
  RunCLI->>ChildRun: start next child run
Loading

Suggested reviewers: dracic

Merge Risk: Minimal · up to 57041

No actionable issue is established before merge. The reported tests and static checks are not independently verified here; complete the normal CI checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the main change: a dry-run and TUI preview of a parent initiative chain in the tickets flow. The changeset adds chain previews to run --dry-run (cli.py, tests/test_cli.py), the TUI s…
Docstring Coverage Passed Docstring coverage is 91.30% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentati…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: a dry-run and TUI preview of a parent initiative chain in the tickets flow. The changeset adds chain previews to run --dry-run (cli.py, tests/test_cli.py), the TUI start-run preview (tui/screens/modals.py, tui/data.py), and matching docs. The ticket reference (DW-574, 3/3) and the feat(tickets) prefix are accurate and specific enough for a teammate to scan history.

Full details: Docstring Coverage

Explanation

Docstring coverage is 91.30% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 23 functions across 7 files. (8 skipped: 5 unsupported, 3 too large.)

Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks the children’s queue,
Then hops along the ticket trail.
At each epic, pauses to review,
Resumes when work can set sail.
The next child waits, ears alert,
While carrots mark each completed quest.

Comment @coderabbitai help to get the list of available commands.

@pbean
pbean added this pull request to stack #1016 October 29, 2026 17:19
@pbean pbean changed the title dw ledger 1028/06 chain preview feat(tickets): preview a parent initiative chain in the dry run and TUI (DW-574, 3/3) Oct 29, 2026
@pbean
pbean force-pushed the dw-ledger-1028/06-chain-preview branch from d017010 to 58be106 Compare October 29, 2026 18:17
@pbean
pbean force-pushed the dw-ledger-1028/06-chain-preview branch 2 times, most recently from 49db530 to fa19a23 Compare October 29, 2026 21:44
t added 4 commits October 29, 2026 19:00
…DW-574)

`run --dry-run` on a v7 parent initiative exited 1: it read the tree
unpinned, which refuses a parent. It now lists the parent's children in
build order (status, ticket counts, what each waits on, and a tag: next,
ready, waiting, no folder, done/dropped, drained), prints the first
child's tickets block through that child's folder, and ends with
`predicted: chain starts with <child>; later children are chosen as each
finishes` -- or, when no child can start, the end line `run` prints.
--epic/--story on a parent are refused with `run`'s own text. The
tickets block is extracted into `_dry_run_ticket_block`, which the
one-initiative dry run prints unchanged.

The dry-run banner now mirrors the tickets preflight's refusal of a
parent initiative (`install.tickets_parent_problems`): before, a parent
under `isolation = "none"` (or `gates.retrospective = "auto"`, or a
refused child store) got no warning, though the real run refuses it.

Decisions:
- The dry run never writes. A real run first closes drained children
  (`_close_drained_children`: marks `status: done`, may commit); the dry
  run does not call it and does not simulate it. It tags such a child
  `drained (the run closes it first)`, picks as the read-only tree
  answers (`_chain_pick`, which only reads, now takes the already-read
  view), and the predicted line says the run closes those children
  before its first pick, which the preview does not simulate.
- --max-stories caps the first child's listing as before. It is one cap
  across the chain, but the dry run predicts only the first child.
… through its child (DW-574)

Start-run preview: `project_tickets_overview` detects a parent active
initiative as `bmad-loop run` does (`install._initiative_children`; a read
fault is the board's fault) and returns the chain: the parent, one
`ChainChild` per child in build order (`next <parent>` pinned to the parent:
status, closed/total tickets, what it waits on, a tag) and the board of the
child a run builds first, read through that child's folder with the tree
pinned to the parent. `TicketsBoard` grows defaulted `parent`, `children`
and `chain_end` fields; a fault still carries no rows. The modal renders the
children lines, then that board's counts and checkpoint flags (or why no
child can start).

"First" is the pure `initiativechain.next_child` with `drained` as the only
pass-over probe, tagged "first ready": the CLI pick (`cli._chain_pick`) also
passes over a ready child whose fresh pick dispatches nothing, which costs a
`next`/`status` spawn per child, so in that corner the preview can name a
different child than the run. A dim line points at `run --dry-run` for the
exact chain prediction.

Dashboard board: a chained child run pinned its child, but the live
`[core] active_initiative` names the parent, so `tickets.py status` refused
it with pin-mismatch. It now pins and reads as `bmad-loop status` does
(`runs.recorded_tree_pin`'s main-checkout arm: `tree_pin` over
`paths_for_state`), from the stat-gated tickets-mode paths rather than a
`load_paths` per poll tick; a config that no longer names the parent is the
board's fault. `initiative_board` takes `parent=` to pin the parent and read
through the child folder; its cache key carries the parent. Unchained runs
read as before.
…mux (DW-574)

Row 15: a parent initiative with children A and B (B after A), one epic
and one ticket each, store T1, `isolation = "worktree"`, retrospective
`never`. `run` builds A's ticket in a unit mount and pauses at A's epic
boundary; the test closes A's epic; `resume` finishes A's run, closes A
(`status: done`, committed as `chore(tickets): <A> done`), and the chain
launches B's run, which builds B's ticket and pauses at B's epic
boundary. Asserts both run journals' sides of the switch
(`initiative-chain-next`, `initiative-chain`), both plans done, each
session in its unit mount, `tickets.parent_initiative` in B's status,
the user's config.user.toml bytes unchanged, and a clean checkout. The
fake build-auto is unchanged: its `tickets.py find` resolves the child
through the mount's rewritten config.

Row 16: the same parent under `isolation = "none"` exits 1 at preflight,
creates no run dir, leaves the tree clean, and `validate` reports
`tickets.initiative-parent`.

`_scaffold` takes `children` (parent layout via `_write_parent`); new
`_child`, `_run_journal`, `_runs_by_initiative`; `_status_doc` takes a
run dir. The real-tmux E2E inventory counts 16 tickets rows.

Ablations performed: no child in the mount config rewrite
(WorktreeFlow) -> row 15's A run escalates; no isolation cause in
`install._tickets_parent_findings` -> row 16's run composes.
@pbean

pbean commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T04:50:58.120030Z 57041cf Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 57041cf850

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pbean
pbean merged commit a0463f9 into main Oct 30, 2026
17 of 33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant