Files
fusion/docs/plugins/compound-engineering.md
gsxdsm b69dd8eb14 FN-7103: alias brainstorm artifacts to unified plans
Compound Engineering now treats brainstorm output as the requirements-only form of unified plan artifacts.

- Point the brainstorm stage at docs/plans while keeping the existing stage and skill identifiers for compatibility.
- Surface CE plan frontmatter metadata during artifact discovery and reading.
- Harden CE artifact discovery against symlink escapes for conventional artifact paths.
- Update docs, tests, and changeset coverage for the unified brainstorm/plan artifact flow.

Files changed:
 .changeset/fn-7103-ce-plan-alias.md                |   7 ++
 docs/plugins/compound-engineering.md               |  21 +++-
 .../fusion-plugin-compound-engineering/README.md   |  36 ++++--
 .../orchestrator-interrupt-resume.test.ts          |   8 +-
 .../src/__tests__/session-store.test.ts            |  38 ++++++
 .../src/__tests__/stage-registry.test.ts           |  18 +++
 .../src/__tests__/sync.test.ts                     |  36 +++++-
 .../src/artifacts/__tests__/discovery.test.ts      | 133 +++++++++++++++++++-
 .../src/artifacts/discovery.ts                     | 136 +++++++++++++++++++--
 .../src/session/stage-registry.ts                  |  10 +-
 .../src/sync/reconciler.ts                         |   2 +-
 11 files changed, 413 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-7103

Fusion-Task-Lineage: 284a5c5c-40f7-44b2-8e3e-1de671dde36a

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-27 09:28:30 -07:00

7.9 KiB

Compound Engineering Plugin

A dedicated dashboard surface for the compound-engineering (CE) workflow — an artifact hub, interactive ce-* skill sessions, a work→board bridge, and event-driven bidirectional sync. It runs alongside Fusion's native pipeline.

Install

  1. Open Settings → Plugins → Fusion Plugins.
  2. In Bundled Plugins, click Install for Compound Engineering.
  3. Enable the plugin if it is not already started.

When installed and enabled, the plugin registers the Compound Engineering dashboard view destination and installs its bundled ce-* skills into a plugin-local, discoverable directory (never a global ~/.claude/skills path).

Built-in workflow gating: the builtin:compound-engineering workflow is hidden from the workflow picker and task workflow selection until this plugin is installed and enabled. Once the plugin is active, the workflow appears automatically alongside other built-in workflows — no additional configuration is needed. If the plugin is uninstalled, the workflow is hidden again.

Dashboard view

The Compound Engineering view is registered as a primary plugin destination (viewId: "compound-engineering").

It follows dashboard UI conventions: the view's panels, controls, responsive layout, spacing, and radii use the shared --space-* / --radius-* design tokens and shared button/card/input classes so the plugin remains visually consistent across light, dark, desktop, and mobile surfaces.

It provides:

  • An artifact hub that discovers CE artifacts from conventional locations (STRATEGY.md, docs/ideation/, legacy docs/brainstorms/, unified docs/plans/, docs/work/, CONCEPTS.md, docs/solutions/) grouped by stage, with explicit empty / partial / error states and readiness metadata for unified plans.
  • Self-contained artifact previews read through plugin routes under /api/plugins/fusion-plugin-compound-engineering/.
  • A stage launcher listing the registered, operator-enabled stages.

brainstorm and plan are separate Fusion stages but share the unified docs/plans/ artifact contract: brainstorm produces a requirements-only unified plan (artifact_readiness: requirements-only, product_contract_source: ce-brainstorm), and plan enriches that same file to implementation-ready.

Sessions

Each stage maps to a bundled skill via the stage registry ({ stageId, skillId, artifactLocation, icon, label }). Launching a stage starts an interactive agent session on the host's createInteractiveAiSession seam.

The orchestrator streams thinking/text turns, surfaces a structured question (pausing in awaiting_input), accepts a structured answer, and on complete writes the artifact to the stage's conventional location (docs/plans/ for both Brainstorm and Plan under the unified-plan alias). Lifecycle: launching → active → awaiting_input → completed, plus error and interrupted. Interrupt/error auto-saves progress and emits an observable event; sessions resume/retry back to their current question.

Turn execution is detached: start/answer/resume return as soon as the session row reflects the request, with the agent turn running in the background (failures persist into session state — never an unhandled rejection). Close only leaves the flow UI; it does not stop the detached agent. Cancel is the explicit stop action for launching/active/awaiting_input sessions: it aborts any live in-process handle, flushes live working output into history, and keeps the session row as terminal interrupted with Cancelled by user so the conversation can be inspected or resumed. Discard is different: it removes a settled session row entirely after disposing any live handle.

While a turn runs, the engine streams mid-turn progress (thinking/text deltas + tool markers) through the seam's onProgress option; the orchestrator buffers it and GET /sessions/:id attaches it as transient liveActivity. The per-turn timeout is inactivity-based (progress re-arms it), so long actively-working turns are never killed; on settle/interrupt the working trace is condensed into the conversation history. Users can also steer mid-stage: answers may carry free-text guidance ({value, comment}) or be guidance-only ({feedback}).

Updates are pushed over the shared /api/events SSE stream: the orchestrator emits via ctx.emitEvent, the host forwards them as project-scoped plugin:custom events, and the view subscribes through the host subscribePluginEvents capability (no raw EventSource). Polling GET /sessions/:id remains a fallback. The projectId from start is threaded through every answer/resume/poll so they resolve the session's owning store.

HTTP endpoints (under /api/plugins/fusion-plugin-compound-engineering/):

  • POST /sessions → start a stage session
  • POST /sessions/:id/answer → answer the awaiting question (send projectId)
  • POST /sessions/:id/resume → resume an awaiting/interrupted session (send projectId)
  • POST /sessions/:id/cancel → cancel an in-flight session; stops the agent and keeps the row as interrupted
  • GET /sessions/:id → current persisted session state (push + poll fallback)
  • GET /sessions → list sessions (filter by status/stage)
  • GET /sessions/:id/links → the work→board pipeline-link records for a session
  • DELETE /sessions/:id → discard a session; stops any live handle and deletes the row

Sync model

Two separate state machines are kept in sync, never merged:

  • Board-task ownership → the task column. The board is authoritative for task state.
  • CE-pipeline ownership → ce_pipeline_state.{currentStage, status}. The CE flow is authoritative for artifact/pipeline content.

Inbound: onTaskMoved / onTaskCompleted hooks resolve the link and enqueue a sync signal under the 5s hook budget — no inline advancement.

Reconcile: reconcileCePipelines(ctx) is a single on-demand sweep (not a poll loop). It drains the queue and independently re-derives transitions from live board state, so a dropped or never-enqueued event still converges.

Outbound: when a pipeline advances to a stage that produces board work, the reconciler creates the next-stage board task and links it. Brainstorm → Plan advancement carries lastArtifactPath forward so the plan task continues the same unified docs/plans/ artifact instead of forking a second file.

Conflict policy: the reconciler only reads already-terminal board columns and only writes CE-owned fields plus a new board task, so the two writers never contend over the same cell.

The work bridge tags every CE-originated board task (source workflow_step with CE markers in sourceMetadata) and records an authoritative pipeline-link row; created tasks then run the normal lifecycle untouched.

Settings

Settings render under Settings → Plugins → Compound Engineering.

Sessions

  • defaultProvider (string) — provider for CE interactive sessions; blank uses the host default. Consumed by the orchestrator's factory call.
  • defaultModelId (string) — model within the provider; blank uses the host default. Consumed by the orchestrator's factory call.
  • disabledStages (string[], default []) — explicit opt-out list. Registered stages launch by default; the orchestrator rejects only IDs listed here.

Sync

  • reconcileOnHooks (boolean, default true) — auto-fire the reconcile sweep after task move/complete hooks. When off, the hook still enqueues so an on-demand sweep converges later.
  • reconcileIntervalMinutes (number, default 15) — cadence hint for an on-demand refresh surface; not a continuous poll loop.