feat: in-app Orchestrator (Phase 2) — multi-agent conductor
Brings the deterministic Han-flow conductor into BooCode: launch any read-only flow from BooChat or BooCoder, watch each agent stream live in a Paseo-style run pane, get an evidence-disciplined report — on local Qwen, persisted and resumable. Read-only enforced hard via qwen --approval-mode plan (orchestrator tasks fail closed if qwen is unavailable; never fall to write-capable native). Backend (apps/coder): re-homed conductor defs, flow_runs/flow_steps schema, flow-runner + dispatcher onTaskTerminal hook, restart-resume, runs routes (launch/list/get/cancel), user-channel WS. Contracts: two flow_run_* frames. Web: orchestrator pane kind + OrchestratorPane, Workflow button + slash flows (BooChat/BooCoder parity), FlowLauncherDialog, "New Orchestrator" in the + and split menus, runs history + export. Plan: openspec/changes/orchestrator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
129
apps/coder/src/conductor/flows/planning.ts
Normal file
129
apps/coder/src/conductor/flows/planning.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Han planning skills as best-effort ONE-PASS flows. Han intends these to be
|
||||
* human-in-the-loop refinement loops; run unattended they produce a first-draft
|
||||
* artifact that still gets the adversarial-validator gate. Phase 2 (in-app)
|
||||
* gives them the interactive surface they really want.
|
||||
*/
|
||||
import type { Spine } from '../types.js';
|
||||
import { q, repoLine } from './_util.js';
|
||||
|
||||
export const planFeature: Spine = {
|
||||
name: 'plan-a-feature',
|
||||
description: 'feature spec draft (one-pass; human-in-loop intended)',
|
||||
contracts: ['evidence', 'yagni'],
|
||||
angles: [
|
||||
{
|
||||
id: 'pm',
|
||||
agent: 'project-manager',
|
||||
label: 'Scope & requirements (project-manager)',
|
||||
task: (ctx) =>
|
||||
`Draft the scope and requirements for the feature below — the problem, the user, in-scope vs out-of-scope, acceptance criteria, and the open questions a team must resolve. Evidence-based; flag assumptions.${repoLine(ctx)}\n\nFEATURE: ${q(ctx)}`,
|
||||
},
|
||||
{
|
||||
id: 'ux',
|
||||
agent: 'user-experience-designer',
|
||||
label: 'UX considerations (user-experience-designer)',
|
||||
minBand: 'medium',
|
||||
task: (ctx) =>
|
||||
`Surface the usability and interaction considerations the feature below must address — flows, affordances, accessibility, input modalities, cognitive load.\n\nFEATURE: ${q(ctx)}`,
|
||||
},
|
||||
{
|
||||
id: 'prior',
|
||||
agent: 'research-analyst',
|
||||
label: 'Prior art (research-analyst)',
|
||||
minBand: 'large',
|
||||
task: (ctx) =>
|
||||
`Research, with sources, how similar features are typically built and the options/trade-offs worth considering before specifying the feature below. STRICT evidence; no codebase context.\n\nFEATURE: ${q(ctx)}`,
|
||||
},
|
||||
],
|
||||
synthesizer: {
|
||||
agent: 'software-architect',
|
||||
label: 'Feature spec draft (software-architect)',
|
||||
task: (ctx) =>
|
||||
`Synthesise the inputs below into a first-draft feature spec — problem, scope, a build approach with the components to create/modify, data flow, and a sequenced plan. Mark every unresolved decision as an open question rather than guessing.\n\n----- INPUTS -----\n${ctx.results.fold ?? ''}`,
|
||||
},
|
||||
};
|
||||
|
||||
export const planImplementation: Spine = {
|
||||
name: 'plan-implementation',
|
||||
description: 'implementation plan draft (one-pass)',
|
||||
contracts: ['evidence', 'yagni'],
|
||||
angles: [
|
||||
{
|
||||
id: 'arch',
|
||||
agent: 'software-architect',
|
||||
label: 'Implementation blueprint (software-architect)',
|
||||
task: (ctx) =>
|
||||
`Produce an implementation blueprint for the work below — the specific files to create/modify, component designs, data flow, and an ordered build sequence, grounded in the existing codebase patterns. Cite repo/path:line where it anchors on existing code.${repoLine(ctx)}\n\nWORK: ${q(ctx)}`,
|
||||
},
|
||||
{
|
||||
id: 'tests',
|
||||
agent: 'test-engineer',
|
||||
label: 'Test strategy (test-engineer)',
|
||||
minBand: 'medium',
|
||||
task: (ctx) =>
|
||||
`Recommend the test strategy that should accompany the implementation below — what to test at which level, and where test doubles isolate collaborators.\n\nWORK: ${q(ctx)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const planPhasedBuild: Spine = {
|
||||
name: 'plan-a-phased-build',
|
||||
description: 'phased build plan draft (one-pass)',
|
||||
contracts: ['evidence', 'yagni'],
|
||||
angles: [
|
||||
{
|
||||
id: 'pm',
|
||||
agent: 'project-manager',
|
||||
label: 'Phasing & sequencing (project-manager)',
|
||||
task: (ctx) =>
|
||||
`Break the initiative below into a sequence of independently shippable phases — each with a goal, the slice of work it contains, its dependencies on prior phases, and a definition of done. Flag the riskiest phase.${repoLine(ctx)}\n\nINITIATIVE: ${q(ctx)}`,
|
||||
},
|
||||
{
|
||||
id: 'arch',
|
||||
agent: 'software-architect',
|
||||
label: 'Technical sequencing (software-architect)',
|
||||
minBand: 'medium',
|
||||
task: (ctx) =>
|
||||
`Advise on the technical sequencing of the initiative below — which abstractions/boundaries must land first so later phases don't require rework.\n\nINITIATIVE: ${q(ctx)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const planWorkItems: Spine = {
|
||||
name: 'plan-work-items',
|
||||
description: 'break work into tracked items (one-pass)',
|
||||
contracts: ['evidence', 'yagni'],
|
||||
angles: [
|
||||
{
|
||||
id: 'pm',
|
||||
agent: 'project-manager',
|
||||
label: 'Work items (project-manager)',
|
||||
task: (ctx) =>
|
||||
`Break the work below into discrete, individually completable work items — each with a clear title, a one-line outcome, its dependencies, and a rough size. Order them by dependency.${repoLine(ctx)}\n\nWORK: ${q(ctx)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const iterativePlanReview: Spine = {
|
||||
name: 'iterative-plan-review',
|
||||
description: 'stress-test an existing plan (one pass of the loop)',
|
||||
contracts: ['evidence', 'yagni'],
|
||||
angles: [
|
||||
{
|
||||
id: 'junior',
|
||||
agent: 'junior-developer',
|
||||
label: 'Generalist stress-test (junior-developer)',
|
||||
task: (ctx) =>
|
||||
`Stress-test the plan below as a sharp generalist teammate: reframe it simply, surface hidden assumptions, unstated prerequisites, muddied scope, and the open questions it leaves unanswered. Cite the part of the plan each concern attaches to.${repoLine(ctx)}\n\nPLAN: ${q(ctx)}`,
|
||||
},
|
||||
{
|
||||
id: 'risk',
|
||||
agent: 'risk-analyst',
|
||||
label: 'Risk review (risk-analyst)',
|
||||
minBand: 'medium',
|
||||
task: (ctx) =>
|
||||
`Assess the risks the plan below carries or ignores — likelihood, severity, blast radius, reversibility — and which steps most need de-risking before commitment.\n\nPLAN: ${q(ctx)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user