Add settingsSchema (default session provider/model, enabled stages, sync
reconcile-on-hooks toggle, reconcile cadence hint) aligned across manifest.json
and the runtime manifest, with typed getters. Wire the consumed getters:
orchestrator passes defaultProvider/defaultModelId into sessions and rejects
disabled stages; hooks gate their reconcile drain on reconcileOnHooks. Add the
plugin README and docs/plugins/compound-engineering.md documenting the hub,
interactive sessions, work bridge, and the sync ownership model.
reconcileIntervalMinutes is exposed as an operator cadence hint but not yet
consumed (no host scheduler; reconcile is on-demand by design).
Add a ce_pipeline_state machine (currentStage/status) kept distinct from
board-task ownership (task column) — separate tables, no shared column, per
FN-5719. onTaskMoved/onTaskCompleted hooks do only an indexed lookup + enqueue
and return well under the 5s budget; advancement happens in an on-demand
reconciler sweep that re-derives correct pipeline state from board truth, so a
dropped hook event still converges (no tight poll loop). Outbound CE-flow
changes create the next-stage board task. Conflict policy: board authoritative
for task state, CE flow authoritative for artifact/pipeline content (inbound
read and outbound write target different rows, so they cannot contend).
Host-scheduler note: no host timer wired; sweeps run on hook-drain and on the
dashboard/route refresh surface (tracked for the host event-publish follow-up).
When the work stage completes with a derived task list, create Fusion tasks via
ctx.taskStore.createTask tagged CE-originated (sourceType workflow_step +
sourceMetadata marker) and record an authoritative ce_pipeline_links row per
task (back-reference lives in the link table, not task-row JSON, per FN-5719).
Tasks then run the normal lifecycle untouched. Zero derived tasks is a clean
no-op. The link store is intentionally minimal for U8 to extend with the
bidirectional pipeline-state machine.
Extend the stage registry with presentation metadata (icon/label/glob) so adding
a stage stays data-only. Add CeFlow renderer for text/single_select/multi_select/
confirm questions over the U5 polling session routes, with a visibly-marked chat
fallback (AE1) that still completes the stage. Wire the artifact-hub launcher to
list and start registered stages. Add the skill-interaction audit test producing
a measured rich-vs-chat coverage ratio (declared classification: 8/8=100% across
brainstorm/ideate/plan), failing on unclassified interactions.
Add allowlist-based artifact discovery over the conventional CE locations
(STRATEGY.md, docs/ideation, docs/brainstorms, docs/plans, docs/solutions,
CONCEPTS.md), grouped by stage, with error entries for unreadable artifacts and
no reads outside the allowlist. Add list/read/preview routes (self-contained
sandboxed HTML, data-section markers) and the primary CompoundEngineeringView
with explicit empty/partial/error states, viewport-gated fetch, and a short-TTL
cache. Bind the view via registerBundledPluginViews + dashboard workspace dep
(the real binding; manifest componentPath is cosmetic).
Add ce_sessions schema (onSchemaInit), CeSessionStore (via
ctx.taskStore.getDatabase()), and CeOrchestrator driving a stage's skill on the
U4 interactive seam: streams thinking/text, persists questions as
awaiting_input, writes the stage artifact on complete, and auto-saves +
emits an observable event on interrupt/error (never silent loss). Lifecycle:
launching/active/awaiting_input/completed/error/interrupted with resume and an
interval-relative staleness rubric. Start/answer/resume/get-state routes.
Streaming transport is client polling of the get-session-state route for v1:
plugin routes have no native SSE and the loader emitEvent is a logging stub, so
true server push needs a host publish-to-/api/events seam (tracked follow-up).
Skill discovery is cwd+prompt-based; forwarding install paths through the seam
is a tracked follow-up.
Bundle pinned copies of 7 CE pipeline-stage skills (strategy, ideate,
brainstorm, plan, work, code-review, compound) under src/skills/ and declare
them via PluginSkillContribution. Empirical finding: the skills contribution
alone does not make a SKILL.md resolvable in a session -- the engine ingests it
as a name only. So onLoad runs an idempotent, isolation-guarded physical install
into a plugin-local .fusion-ce-skills/ dir (never a global ~/.claude/skills),
which the engine skill-resolver can then discover. Proven against the real
loadSkills + resolveSessionSkills pipeline.
Expose createInteractiveAiSession on route/loader PluginContext alongside the
one-shot createAiSession. The prompt->parse->retry->pause->resume loop is
reimplemented in an engine seam modeled on planning.ts (no engine await-input
primitive exists). Reuses PlanningQuestion/PlanningResponse; stays generic with
no plugin-specific concepts. Injected on route contexts only; tool/runtime
contexts omit it (parity with createAiSession).
Keep mobile discovered-skill rows aligned after toggles and skill enablement.
- keep .skills-view-item rows from wrapping at the mobile breakpoint
- let .skills-view-item-info flex instead of forcing full-width stacking
- add CSS regression coverage for the mobile row layout and toggle geometry
- add component coverage that preserves row structure across enabled and disabled toggle states
Files changed:
packages/dashboard/app/components/SkillsView.css | 5 ++-
.../components/__tests__/SkillsView.css.test.ts | 49 ++++++++++++++++++++++
.../app/components/__tests__/SkillsView.test.tsx | 47 +++++++++++++++++++++
.../__tests__/skills-view-mobile.test.tsx | 9 ++--
4 files changed, 104 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-5903
Fusion-Task-Lineage: 1004a702-28e7-4e7e-af22-591cc122be01
Keep MissionManager mission interview state and detail rendering in sync while stabilizing the failing test coverage.
- reload assertion-linked feature data when mission details or milestone panels load
- keep selected mission detail state synchronized after mission update events instead of forcing a full mission reload
- hide the sidebar edit form while the selected mission is already being edited in the detail pane
- add a non-destructive Send to background action for resume-launched mission interview modals
- tighten MissionManager tests to target the detail pane and slice-scoped controls that now render alongside sidebar content
Files changed:
docs/missions.md | 2 +-
.../app/components/MissionInterviewModal.tsx | 30 ++++++++
.../dashboard/app/components/MissionManager.tsx | 77 +++++++++++--------
.../components/__tests__/MissionManager.test.tsx | 88 +++++++++++++++-------
4 files changed, 137 insertions(+), 60 deletions(-)
Fusion-Task-Id: FN-5895
Fusion-Task-Lineage: d018a945-33a7-4471-9636-35bc36dc88a9
Document that workflow IR v1 keeps agent-call and typed-edge semantics as conventions rather than a 1.1 schema bump.
- replace the deferred-v1.1 note with the FN-5769 evaluation outcome
- record that prompt config and edge.condition remain the canonical v1 representation for parity rollout
Files changed:
docs/workflow-steps.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Fusion-Task-Id: FN-5769
Fusion-Task-Lineage: 341ce4fe-d87d-4c25-a1fc-652ccfbc2e94
Ensure agent-created ntfy notifications fall back to the task description when the title is still empty.
- pass task descriptions through task-created notification payloads
- cover empty-title task creation in notification service tests
- verify ntfy task-created messages render the id+description fallback
- add a patch changeset for the published CLI package
Files changed:
.changeset/fn-5890-task-created-title.md | 5 +++++
.../engine/src/__tests__/notification-service.test.ts | 12 +++++++++++-
packages/engine/src/__tests__/ntfy-provider.test.ts | 16 ++++++++++++++++
packages/engine/src/notification/notification-service.ts | 1 +
4 files changed, 33 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-5890
Fusion-Task-Lineage: 4a67a4d0-c3a8-4923-a506-7a67a8836127
Retry incomplete executor work with a fresh session after non-continuable session errors.
- add executor recovery handling that clears session state and requeues incomplete tasks to todo while retry budget remains
- preserve terminal failure behavior once the fresh-session retry budget is exhausted
- extend reliability coverage and AGENTS.md backstop notes for the new retry path
Files changed:
AGENTS.md | 1 +
.../post-done-continuation-no-wedge.test.ts | 48 +++++++++++++++++++++-
packages/engine/src/executor.ts | 40 ++++++++++++++++++
3 files changed, 87 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-5888
Fusion-Task-Lineage: 4ebce260-8923-4599-aced-541533b94543
Keep mission interview drafts recoverable when closing and refreshing Missions.
- make MissionInterviewModal use a single non-destructive close path for header, Escape, and backdrop actions
- refresh mission interview draft/session rows on mission and ai-session SSE updates and reconnects
- open Plan New Mission as a fresh interview instead of always resuming the last session, with regression coverage and docs updates
Files changed:
docs/missions.md | 2 +-
.../app/components/MissionInterviewModal.tsx | 89 +++-----
.../dashboard/app/components/MissionManager.tsx | 156 ++++++++++----
.../__tests__/MissionInterviewModal.test.tsx | 100 ++++++++-
.../components/__tests__/MissionManager.test.tsx | 224 +++++++++++++++++++++
5 files changed, 455 insertions(+), 116 deletions(-)
Fusion-Task-Id: FN-5882
Fusion-Task-Lineage: 75de9e94-edef-4564-a266-91782e60c2ac
Keep quick chat warm and restore the last opened conversation per project.
- persist the active quick chat session id in per-project local storage and restore it before falling back to latest activity
- retain in-memory quick chat state across close/reopen while resetting chat state correctly when the project changes
- add storage, hook, and FAB coverage for restored sessions, warm reopen behavior, and project switching; document the updated quick chat behavior
Files changed:
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/components/QuickChatFAB.tsx | 29 ++++--
.../app/components/__tests__/QuickChatFAB.test.tsx | 112 +++++++++++++++++++--
.../__tests__/quickChatLastSessionStorage.test.ts | 55 ++++++++++
.../app/hooks/__tests__/useQuickChat.test.ts | 70 +++++++++++++
.../app/hooks/quickChatLastSessionStorage.ts | 41 ++++++++
packages/dashboard/app/hooks/useQuickChat.ts | 25 +++++
7 files changed, 319 insertions(+), 16 deletions(-)
Fusion-Task-Id: FN-5884
Fusion-Task-Lineage: 4d689611-1824-41db-8fc2-d543407316ff
Handle empty usage responses without leaving the panel in its loading skeleton.
- add a hasFetched flag to useUsageData so the UI can distinguish initial loading from an empty completed response
- update UsageIndicator to render the skeleton only before the first fetch completes and show the empty state afterward
- refresh dashboard hook and component tests to cover empty fetches, refresh behavior, and the new loading semantics
Files changed:
.../dashboard/app/components/UsageIndicator.tsx | 19 +-
.../components/__tests__/UsageIndicator.test.tsx | 395 +++++++++++----------
.../app/hooks/__tests__/useUsageData.test.ts | 42 ++-
packages/dashboard/app/hooks/useUsageData.ts | 5 +
4 files changed, 245 insertions(+), 216 deletions(-)
Fusion-Task-Id: FN-5886
Fusion-Task-Lineage: 8fa901a9-3167-4e33-a082-e5de95f692da
Restore expected terminal clipboard shortcuts.
- intercept Ctrl/Cmd+C in the dashboard terminal to copy the current selection while preserving plain SIGINT when nothing is selected
- intercept Ctrl/Cmd+V to read clipboard text and send it into the active PTY session
- add terminal shortcut regression coverage and document the new integrated terminal behavior
- add a patch changeset for @runfusion/fusion
Files changed:
.changeset/friendly-ravens-hammer.md | 5 +
docs/dashboard-guide.md | 2 +
packages/dashboard/app/components/TerminalModal.tsx | 48 +++++++++
packages/dashboard/app/components/__tests__/TerminalModal.test.tsx | 113 +++++++++++++++++++++
4 files changed, 168 insertions(+)
Fusion-Task-Id: FN-5885
Fusion-Task-Lineage: f8b3658c-2b52-4094-8cef-79c762f4d78d
Reduce SettingsModal test setup overhead around Remote and Notifications flows.
- switch key authentication assertions to await section controls directly instead of waiting for full modal readiness
- share a zero-delay user-event instance across Remote and Notifications suites and consolidate default-render setup in nested describe blocks
- replace several clear/type interaction sequences with direct change events to cut async churn while preserving coverage
Files changed:
.../components/__tests__/SettingsModal.test.tsx | 473 ++++++++++-----------
1 file changed, 224 insertions(+), 249 deletions(-)
Fusion-Task-Id: FN-5873
Fusion-Task-Lineage: d1f33301-a43f-467f-97e8-b7bfad28e009
Keep the task detail tab strip scrollable on desktop without shrinking tab labels.
- move horizontal tab-strip scrolling and momentum styles into the base .detail-tabs rule
- keep .detail-tab items from shrinking at all viewport sizes so overflow remains scrollable
- add a CSS contract test for the base tab strip behavior and extend task detail API mocks with refreshPrStatus
Files changed:
packages/dashboard/app/components/TaskDetailModal.css | 7 ++++---
.../dashboard/app/components/__tests__/TaskDetailModal.css.test.ts | 7 +++++++
.../app/components/__tests__/TaskDetailModal.test-helpers.ts | 1 +
3 files changed, 12 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-5879
Fusion-Task-Lineage: b990a88e-7b1d-44d9-b222-986a28ae143d
Persist merge metadata for AI fast-forward landings and done-task recovery.
- capture landed files and shortstat metadata from the single landed commit in the AI merge finalizer
- persist mergeDetails and modifiedFiles for landed squash commits, and record commit associations without setting no-op attribution flags
- extend done-task self-healing to backfill merge metadata when baseCommitSha exists but mergeDetails is empty
- add reliability and self-healing coverage for landed-file persistence, empty AI merges, and recovery behavior
Files changed:
AGENTS.md | 1 +
.../ai-merge-ff-landed-files.test.ts | 150 +++++++++++++++++++++
packages/engine/src/__tests__/self-healing.test.ts | 76 +++++++++++
packages/engine/src/merger-ai.ts | 40 +++++-
packages/engine/src/merger.ts | 30 ++++-
packages/engine/src/self-healing.ts | 11 +-
6 files changed, 303 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-5874
Fusion-Task-Lineage: a407910c-9ce8-4049-86ef-e80f045c981a
Add a one-click Remotes sync flow that rebases on pull before pushing.
- add a Sync button in Git Manager Remotes that runs pull --rebase and then push
- stop before pushing when the rebase pull reports a conflict or fails, and surface toasts/status updates
- cover successful, conflicting, failing, and loading sync behavior in GitManagerModal tests
- document the new Sync action in the dashboard guide
Files changed:
docs/dashboard-guide.md | 1 +
.../dashboard/app/components/GitManagerModal.tsx | 39 ++++++++
.../components/__tests__/GitManagerModal.test.tsx | 100 +++++++++++++++++++++
3 files changed, 140 insertions(+)
Fusion-Task-Id: FN-5877
Fusion-Task-Lineage: 2e28c00d-b965-4f44-a6fa-26536d91d16d
Let users hide a revealed secret again from the row visibility toggle.
- add a hideSecret helper that clears reveal timers and resets the revealed value
- make the row eye toggle switch between reveal and hide states instead of reveal-only
- add a SecretsView regression test covering reveal, hide, and copy button state changes
Files changed:
packages/dashboard/app/components/SecretsView.tsx | 18 +++++++++-
packages/dashboard/app/components/__tests__/SecretsView.test.tsx | 40 ++++++++++++++++++++++
2 files changed, 57 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-5878
Fusion-Task-Lineage: 936195db-88c9-48f5-8273-9b930bf6b858
Reduce SettingsModal test overhead by reusing setup and waiting on stable UI signals.
- replace generic waitFor polling with findBy* queries and direct mock call assertions
- consolidate project-general persistence coverage and split default-value checks from save-path assertions
- share Memory and Merge section setup across related tests to avoid repeated navigation and duplicate work
Files changed:
packages/dashboard/app/components/__tests__/SettingsModal.test.tsx | 333 ++++++++-------------
1 file changed, 127 insertions(+), 206 deletions(-)
Fusion-Task-Id: FN-5871
Fusion-Task-Lineage: 1b625571-f16e-4aec-8640-22d8f3bb8139
Keep the usage indicator's hidden-row toggle in sync with rendered duplicate windows.
- count hidden usage rows from the currently rendered provider windows instead of persisted label entries
- preserve the Show hidden button when duplicate live windows share a stored hidden label
- add a regression test covering duplicate Daily windows with persisted hidden state
Files changed:
.../dashboard/app/components/UsageIndicator.tsx | 12 ++++++-
.../components/__tests__/UsageIndicator.test.tsx | 42 ++++++++++++++++++++++
2 files changed, 53 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-5875
Fusion-Task-Lineage: 648f9cb9-ea0a-4573-b08f-b1a412a46ae4
The lineage commit associations panel surfaced low-value provenance
metadata. Remove the UI section, its dead state/fetch wiring in
TaskChangesTab, the orphaned .task-lineage-* CSS, and the obsolete
tests. The fetchTaskCommitAssociations API helper is retained.
Preselect the resolved default model when creating a new model-based chat.
- pass the resolved default model into the new chat dialog
- preserve and restore the default model selection when switching into model mode
- add ChatView coverage for default-model preselection, create enablement, and unresolved-default fallback
Files changed:
packages/dashboard/app/components/ChatView.tsx | 18 +++++-
packages/dashboard/app/components/__tests__/ChatView.test.tsx | 65 ++++++++++++++++++++--
2 files changed, 75 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-5854
Fusion-Task-Lineage: d1ace008-0354-44b4-90c8-e0370f38b6bf
Split the dashboard quality Vitest lane into bounded heap-managed shards to avoid signal exits.
- replace the single dashboard quality test command with sequential app and API shard scripts
- add a heap wrapper plus Vitest config shard definitions for foundation, component, App, ChatView, and SettingsModal coverage
- add guard tests for the sharded dashboard test configuration and restore spinner-animation.css.test.ts to foundation-ui coverage
- update the CLI package-config test expectations for the new dashboard test script layout
Files changed:
packages/cli/src/__tests__/package-config.test.ts | 8 +-
packages/dashboard/package.json | 18 +-
packages/dashboard/scripts/run-vitest-with-heap.mjs | 41 ++++
packages/dashboard/src/__tests__/dashboard-test-config-guard.test.ts | 77 ++++++
packages/dashboard/vitest.config.ts | 273 ++++++++++++++++++++-
5 files changed, 407 insertions(+), 10 deletions(-)
Fusion-Task-Id: FN-5849
Fusion-Task-Lineage: 522f3963-4647-4a59-bb6b-a3dacfbf620e
Make the ChatView skill-menu keyboard navigation test wait for async UI updates.
- wrap the highlighted-option assertion after ArrowUp in waitFor to avoid synchronous timing races
- wait for the textarea value update after Enter selection before asserting the chosen skill command
Files changed:
packages/dashboard/app/components/__tests__/ChatView.test.tsx | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-5864
Fusion-Task-Lineage: 9f1b3988-7022-415f-8d4b-83b0b3b25dfb
Tighten the branch-conflicts recovery test to use an isolated secondary worktree root.
- create a unique temporary parent directory for the detached secondary worktree
- track the temporary root for cleanup instead of only the nested worktree path
- keep the reanchor regression focused on detached worktree recovery behavior
Files changed:
packages/engine/src/__tests__/branch-conflicts-recovery.test.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-5863
Fusion-Task-Lineage: 6cfb02c0-e9fd-456d-a78b-451e3e0707b2