Initiative Brief: The controller decides what the operator should do next
COMPLETEDIntent— the specification (7,446 chars); the plan below decomposes it into work items. Click to expand.
# Initiative Brief: The controller decides what the operator should do next ## Desired outcome An operator looking at a held initiative should be told what to do next by the Orchestrator, in the Orchestrator's own words, and should be able to act on it without inferring anything. Today the controller computes everything needed to reach that answer and publishes none of it, so the workspace infers an action from raw booleans — and gets it wrong in the ordinary foundation-first case. This initiative moves the "what now" decision into the controller, alongside the closure verdict that already lives there, and reduces the workspace to rendering it. An operator on a held or in-progress initiative sees one recommended next action, decided by the controller, with the controller's reason for it. Destructive actions are never the recommendation. The workspace renders that decision and derives nothing. Concretely: on the Composer initiative as it stood, the panel says "ready to plan wave 2", not "held — force-close planning". ## Motivation The Composer Initiative Tools initiative finished its first wave with all work complete, its continuation decision answered, and `continuationReady` true. Its next step was to plan wave 2, which would deliver the three capabilities its brief revision was written to add. What the operator was shown instead was a panel headed "This initiative is held", listing "3 deferred-scope entries undisposed" and "Planning is still open", with two suggested next actions: dispose the deferred scope, or **force-close planning (waives 3 entries)**. Neither mentioned planning the next wave. The operator asked, reasonably, whether force-closing would prematurely end the initiative. It would have: it would have waived the in-initiative read surface, the conversational mutations and the citation approach — the entire remaining substance of that initiative — and moved it toward completion having recorded that its own goal was an accepted gap. The state was healthy. The presentation was not. An operator who trusted the interface would have destroyed scope they had asked for one screen earlier. ## Current state - `canonicalPlanningStatus` serves `planningStatus`, `planningClosed`, `closure.{canClose, blockingCount, blockers}`, `deferredScope[]`, `continuation` and `hasProposedWave`. Every input needed to decide the next action is present; the conclusion is not. - `apps/orchestrator/src/lib/heldState.ts` in `Xyence/workspaces` derives the action itself: `const forceOnly = planning.canForceClose && !planning.canClose`, then offers force-close or close. Planning the next wave is not in that expression, so it can never be recommended. - `planningStatus` is a bare `"open"`. Open because more work is coming and open because something needs disposing are indistinguishable, and the panel calls both a blocker. - `held` is computed as "there is at least one blocker", so an initiative with more waves coming is reported as held. - The pattern this initiative wants already exists elsewhere: `availableActions` in `packages/db/src/services/recovery.ts` has the controller decide which actions its state permits and serve them, rather than leaving a client to infer them. - Issues #232 and #466 already corrected this class of mistake for other values — the client must never be the source of a decided value, and planning-status carries the closure verdict so the workspace does not recompute it. The completion path's *action* is the last decided value still being derived client-side. ## Architectural principles - The API owns the decided presentation state and the workspace only renders it. This is the same correction as #466 applied to the last value in the completion path still escaping it. - One computation, not two that agree by coincidence. The precedence rule lives in the controller next to the state it reads, so the affordance the workspace shows and the transition the controller would permit cannot disagree. - Follow the shape that already works: `availableActions` in the recovery path is the precedent for a controller serving actions from state. ## Rejected / deferred alternatives - Any change to what close, force-close, dispose, retract, defer-and-file or plan actually do. - The brief-assessment view model and its holds. - Redesigning the held-state panel's visual presentation beyond rendering the new fields. - Extending this to work-item or release-plan surfaces, which have their own action models. ## Constraints - Do not change what any action DOES. This initiative changes what the operator is told, not what close, force-close, dispose or plan actually perform. - Do not remove force-close, or make it harder to reach for an operator who has decided on it. It exists for a real case; it was simply never the recommendation. - Additive to the read model. Existing fields keep their meaning and their consumers keep working, so no client is forced to change in lockstep. - The controller decides; the workspace renders. No new derivation may be introduced client-side, including "helpful" fallbacks when a field is absent. - Do not fold the brief-assessment gate into this. Assessment already has its own view model and its own holds; this is about planning. ## Repository scope - `Xyence/orchestrator` - `Xyence/workspaces` ## Expected behavior - The canonical planning-status read model carries a controller-decided `nextAction`: what the operator should do now, with a label and the controller's own rationale. - The precedence the controller applies, and owns: a proposed wave awaiting review comes first; then an unanswered continuation decision; then planning the next wave when continuation is ready and scope remains deferred; then closing planning when closure is permitted; then disposing deferred scope. - Force-close is never served as `nextAction`. It remains available and reachable, as an explicit operator choice, never as the system's recommendation. - The model carries `availableActions` — everything the current state legitimately permits — so the workspace can offer secondary paths without inventing which ones exist. - Every action the model serves carries whether it is destructive, so a scope-waiving action cannot be rendered with the same weight as an ordinary one. - `planningStatus` distinguishes why planning is open: awaiting a next wave, awaiting disposition, or ready to close. - `held` means "cannot proceed without the operator", not "not yet complete". An initiative between waves with a clear next step is in progress, not held. - The workspace's held-state view renders the controller's `nextAction` and `availableActions` instead of deriving them from `canClose`/`canForceClose`. - The existing planning-status consumers keep working: the change is additive, and no field they read changes meaning. ## Open questions - Should `nextAction` ever be absent — for example on a closed, completed initiative — or should it always carry something, with an explicit "nothing to do" kind? An always-present field is easier for a client to render; an absent one is harder to render wrongly. - Should `availableActions` include actions the operator's capability does not permit, marked as unavailable, or omit them? Showing them explains why an affordance is missing; omitting them avoids advertising what cannot be done. - Does the brief-assessment hold need the same treatment, and if so is it this initiative or a later one?
Repository scope
targets the work spans — independent of where the brief was authoredPrimary repository: orchestrator`
- orchestrator`expected · primary
- workspaces`expected
- orchestratordiscovered
- workspacesdiscovered
brief revision 2 assessed as delivered
assessed with 86% confidenceThe orchestrator now decides and serves the single recommended next action and the permitted alternatives for both planning and the brief-assessment gate, with precedence and destructive classification, and the workspace renders those values verbatim without deriving from booleans. Evidence spans: controller-side derivations (derivePlanningActions, deriveBriefAssessmentView/Actions), additive read models (canonicalPlanningStatus), held/open-reason semantics, and UI selection/rendering of the governing gate (deriveHeldState, HeldStateExplanation). Force-close/waive are never recommended but remain reachable and flagged destructive. Stale assessments are detected and recommend reassessment. Existing fields remain unchanged and consumers keep working. Tests in both repos assert all invariants, including the Composer between-waves case showing “plan next wave,” not “held/force-close.”
Plan waves — 1 approved wave
planning closed- Wave 1completeAPPROVED3 work items
Move the 'what now' decision into the Orchestrator controller for planning and brief-assessment gates, exposing nextAction (always present) and availableActions with rationale and destructive flags. The workspace stops deriving actions and simply renders the controller’s decision and permitted alternatives. Planning-status must distinguish why planning is open; 'held' must mean 'cannot proceed without operator', not merely 'not yet complete'. Force-close is never recommended but remains reachable. Changes are additive to the read model; action implementations are unchanged.
Work items
| # | Title | Repository | State | Issue | PR / CI | Review | |
|---|---|---|---|---|---|---|---|
| 0 | Planning read model: controller-decided nextAction and availableActions; distinguish open reasons; correct 'held' during planning | orchestrator | COMPLETED | #531 | #534merged · CI passed | c1: approve | |
| 1 ⛓ | Brief-assessment hold: controller-decided nextAction and availableActions; stale assessment handling; held semantics after planning | orchestrator | COMPLETED | #532 | #535merged · CI passed | c1: approve | |
| 2 ⛓ | Render controller-decided nextAction and availableActions; remove client-side derivation in held-state views | workspaces | COMPLETED | #214 | #215merged · CI passed | c1: approve |
Release candidate
ELIGIBLEAll work complete — merged, reviewed, and unblocked. Release and deployment remain manual.
d71b74a812 · review approve219eba5133 · review approvede05f7c1ef · review approveRelease planning
Releases are cut in the Release planning section. Associating this initiative requires an admin role.
Associating an initiative to a release only records the link — it never changes the initiative’s own state or work. Releases are optional.
Timeline
No events yet.