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
- Change-intent routing in the monitoring phase: distinguish a question from a plan/requirement change request and route accordingly (lifecycle commands already handled upstream).
- 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. - 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.
- GitHub plan reconcile: apply the delta idempotently (create/patch/close issues & milestones) without clobbering coordination labels.
- Confirm-before-apply for destructive plan changes (closing issues, dropping milestones, discarding in-progress work).
- Post-change notification + re-delegation + live dashboard events.
- 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)
- 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."
- 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.
- 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. - 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:*andeng:*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_keyfencing. - 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_lifecyclepath 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.