Skip to main content

Milestone 4 - Living Product Owner: Conversational Plan & PRD Evolution

Status: delivered (v0.4.0). Change requests in the monitoring phase are triaged, drafted into a new PRD revision + revised plan, proposed for approval (flagging in-flight work), then reconciled onto GitHub incrementally and re-delegated. Two scope refinements from the plan: the PRD re-approval (M4-2) and destructive-change confirmation (M4-5) are a single approval gate that surfaces destructive impact, rather than two prompts; and M4-7 surfaces plan health (escalated / blocked / changes-requested / in-progress) from live labels rather than time-based stall detection (which would need PR timestamps - deferred). Theme: Make Bloom a living Product Owner after planning. Today Bloom plans a project once and then goes read-only: the run parks at await_project_event and only reviews PRs and tracks progress. A free-text user message in the monitoring phase is routed to _handle_project_chat, which by its own docstring "replies conversationally without advancing the workflow," and the assistant is instructed to admit that "applying plan changes is not automated yet, so you have noted it for follow-up." M4 closes that gap: a user can evolve the project by conversation after planning, and Bloom actually applies it - revising the PRD to a new revision, re-planning the affected milestones/tickets, and reconciling GitHub as the source of truth - then confirming and notifying.


Why this milestone

Bloom's own PRD promises this and the code does not yet deliver it:

  • FR-3 (Living PRD): "Every conversation may update the PRD. The PRD is versioned ... upon approval it is committed to the project repository as PRD.md." Post-approval, changes are meant to "create a new PRD revision."
  • FR-4 (PRD Approval): "Future requirement changes create a new PRD revision."
  • Goals: "Manage project planning and keep it current through conversation."
  • Guiding Principles: "Maintain a living understanding of the project throughout its lifecycle."

But in the running system the only path back to prd_authoring is the post-MVP, disabled feedback loop (gather_feedback -> prd_authoring). There is no monitoring -> revise -> re-plan -> reconcile route. So once planning has synced issues to GitHub, the plan is frozen from the user's point of view - the single biggest limiter on Bloom's usefulness as an ongoing Product Owner.

The good news: the primitives already exist, so M4 is wiring and orchestration, not new infrastructure.

  • GitHub mutations are already implemented: update_issue, close_issue, update_milestone, close_milestone, put_file (integrations/github/client.py).
  • The confirm-before-destructive-op pattern is already proven for lifecycle commands (pending_lifecycle + _resolve_lifecycle); plan changes reuse it.
  • The coordination reconciler already re-labels and delegates ready tickets idempotently, so newly-added tickets flow into delegation for free.
  • The dashboard EventBus/SSE stream already exists to surface changes live.

One-liner: After planning, the user says "drop the CSV export and add SSO"; Bloom revises the PRD to a new revision, gets it re-approved, updates GitHub (adds the SSO tickets, closes the CSV ones), and tells the user what changed - all from the chat.


Scope

In scope

  1. Change-intent routing in the monitoring phase: distinguish a question from a plan/requirement change request and route accordingly (lifecycle commands already handled upstream).
  2. Post-approval PRD revision loop: a change request produces a new PRD revision (revision++, re-approval per FR-4) and commits the updated PRD.md.
  3. Incremental re-planning (a plan delta, not a from-scratch regeneration): add / update / retire milestones and tickets while preserving stable mappings to existing GitHub artifacts.
  4. GitHub plan reconcile: apply the delta idempotently (create/patch/close issues & milestones) without clobbering coordination labels.
  5. Confirm-before-apply for destructive plan changes (closing issues, dropping milestones, discarding in-progress work).
  6. Post-change notification + re-delegation + live dashboard events.
  7. Live-grounded status: ground the monitoring assistant's status answers in live GitHub progress and surface stalled / escalated / blocked work on demand.

Out of scope (future / deferred)

  • Autonomous scheduling of digests/nudges (a background scheduler) - listed as a Future Feature; M4 surfacing is on-demand and event-triggered only.
  • Re-planning that rewrites merged/closed work or rewinds delivered milestones.
  • Multi-repo or non-GitHub reconcile (still a non-goal).
  • Replacing the engineer-swarm simulator (its own track).

Key decisions to lock (asked before building)

  1. Delta vs. regenerate. Re-planning computes a delta against the current plan and its GitHub mapping, never a blind regenerate - so in-flight issues, coordination labels, and PR history survive a scope change. Recommendation: delta; regenerate only on an explicit "start the plan over."
  2. Re-approval gating. A requirement change that touches the PRD requires explicit re-approval (FR-4) before any GitHub write, matching the initial-planning contract. Recommendation: always re-approve PRD-level changes; small ticket-only tweaks may skip straight to the confirm-apply step.
  3. Destructive changes need confirmation. Closing issues / dropping milestones / anything that discards in-progress work goes through the existing pending_* confirm pattern; pure additions apply directly. Recommendation: confirm destructive, auto-apply additive.
  4. Intent classification. A structured LLM classification (question | change_request | status) reusing the Product Owner agent, with the deterministic fake provider backing tests. Recommendation: structured intent on the existing agent seam - no new dependency.

I'll default to the recommendations if you don't object, and note the decision in each ticket.


Tickets

Ordered by dependency. Each is bite-sized and independently reviewable.

M4-1 - Change-intent routing (foundation)

In the monitoring phase, classify each free-text turn as question, change_request, or status (lifecycle commands stay handled upstream). Add a structured intent step on the Product Owner agent seam; _handle_project_chat answers questions/status as today but hands a change_request off to the new evolution flow. Remove the "not automated yet / noted for follow-up" apology from PROJECT_ASSISTANT_INSTRUCTIONS for the change path. AC: unit tests over the classifier (question vs. change vs. status) using the fake provider; questions/status still answered unchanged; a change request is recognized and acknowledged ("On it - I'll revise the plan for that"); no behavior applied yet beyond routing + acknowledgement.

M4-2 - Post-approval PRD revision loop

Wire the workflow + orchestrator so a monitoring-phase change request re-enters prd_authoring, producing a new revision (revision++, status: awaiting_approval), re-requests approval (request_prd_approval, FR-4), and on approval re-freezes and commits the updated PRD.md (put_file, revision in the commit message). Add the monitoring -> prd_authoring edge and the return path back to await_project_event; declining leaves the plan untouched. AC: a change request bumps the PRD revision and re-requests approval; approval commits a new PRD.md; "changes requested" loops for another revision; declining is a no-op; integration test drives change -> revise -> approve -> commit over the fake provider.

M4-3 - Incremental re-planning (plan delta)

Add a Product Owner replan(prd, current_milestones, current_tickets) producing a structured PlanChange: milestones/tickets to add, update (title/description/acceptance criteria/labels/milestone), or retire - preserving each item's mapping to its existing GitHub id. Never regenerate wholesale; unchanged items are left untouched. AC: unit tests for pure-add, edit-in-place, and retire cases; unchanged tickets are byte-identical (not re-emitted); mapping to existing created_issues preserved; deterministic under the fake provider.

M4-4 - GitHub plan reconcile (create / update / close)

Apply the PlanChange to GitHub idempotently using the existing client methods, keyed off github_sync/created_issues: new items -> create_issue/create_milestone; changed items -> update_issue/update_milestone; retired items -> close_issue (with an explanatory comment) / close_milestone. Must not clobber coordination status:*/eng:* labels or duplicate existing issues; milestone rollup preserved. AC: reconcile is idempotent (a second apply is a no-op); coordination labels preserved across an update; a fake-GitHub test covers add/update/close; retired tickets are closed, not deleted.

M4-5 - Confirm-before-apply for destructive plan changes

Reuse the pending_lifecycle pattern with a pending_plan_change in state: before applying a destructive delta (closing issues, dropping milestones, discarding in-progress work), summarize the impact (calling out any status:in-progress tickets) and require explicit confirmation; a purely additive delta applies directly. AC: destructive delta -> confirmation prompt listing impact; "yes" applies, "no"/anything else cancels with nothing changed; additive delta skips confirmation; in-progress tickets flagged; tests for confirm and cancel paths.

M4-6 - Post-change notification + re-delegation + live events

After applying, send one concise product-level notification summarizing added / updated / closed artifacts (FR-10 style - detail lives on GitHub, not in chat), trigger the coordination reconcile so newly-ready tickets get delegated, and emit dashboard EventBus events so the live view reflects the change. AC: a single concise notification (not a per-issue dump); newly-added ready tickets are delegated on the next reconcile; an SSE event is emitted for the change; tests cover the notification content and the delegation handoff.

M4-7 - Live-grounded status & stalled-work surfacing

Ground the monitoring assistant's status answers in live GitHub progress (via track_progress), not only cached run state, and surface plan health on demand: stalled tickets (status:in-progress with no linked PR past a threshold), status:needs-attention / escalated work, and milestone progress - a concise PO-level summary. No background scheduler (out of scope). AC: a "status" question reflects live GitHub counts; stalled/escalated/blocked work is listed accurately from live status; the threshold is configurable; tests over a fake GitHub snapshot.

M4-8 - Docs, PRD reconcile & version bump (0.4.0)

Update the PRD (clarify FR-3/FR-4 post-approval revision-by-conversation; add an FR for conversational plan evolution if warranted), architecture (the monitoring -> revise -> re-plan -> reconcile loop and the plan-delta reconciler), this milestone doc's status, the docs index map, and the CHANGELOG; bump the version to 0.4.0. AC: docs reflect delivered M4; pyproject/__init__ bumped to 0.4.0; CHANGELOG entry; milestone doc linked from the docs map.


Risks / watch-list

  • Re-plan must not clobber in-flight work (M4-3/M4-4). The delta must preserve status:* and eng:* labels and never reopen/duplicate issues already delegated or merged. This is the highest-risk area - land it delta-first, idempotent, and fenced.
  • Idempotency under redelivery. The webhook layer is at-least-once; the plan reconcile must be a no-op on a repeated apply, consistent with the existing event_key fencing.
  • Re-approval UX. Two approval gates (initial + revision) must not confuse the user; the revision prompt should say what changed and which revision it is.
  • Destructive confirmation. Getting the confirm/cancel state machine right matters - reuse the proven pending_lifecycle path rather than a parallel implementation.
  • Scope creep into autonomous scheduling. M4-7 stays on-demand/event-triggered; a background digest scheduler is explicitly a future feature.