This merge lands three major features and a significant dashboard enhancement. FN-3276 adds a full Review tab to the task detail modal with multi-step lifecycle: review metadata persistence in the task store, new task workflow routes for refresh and same-task revision, and the review tab UI surface
Fusion-Task-Id: FN-3276
This merge introduces several dashboard and engine improvements: agent inbox wake controls (FN-3087, FN-3588) with immediate message triggers; separated plugin lifecycle from setup probe state (FN-3704); assigned-agent triage inheritance in the engine (FN-3703); inline fast mode toggle in the task d
Fusion-Task-Id: FN-3711
This merge delivers five major feature clusters: a fully rebuilt dependency graph plugin with draggable nodes, position persistence, modular architecture, highlighting and selection states, toolbar navigation, and keyboard controls; a new roadmap plugin with domain store, ordering logic, and compreh
Fusion-Task-Id: FN-3581
After dismissing and re-bringing up the mobile keyboard, iOS could
leave window.scrollY > 0 and visualViewport.offsetTop > 0. With
useMobileScrollLock then pinning body{position:fixed} relative to that
drifted scroll, the message thread anchored above the visible viewport
and a large blank area appeared below it.
handleInputFocus now resets window scroll to (0,0) on mobile in a
zero-delay timeout — late enough that iOS finishes its own
scroll-into-view first, but before useMobileScrollLock observes the
drifted state.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes no-op `agents.filter((a) => true)` calls (a leftover from the
terminated AgentState refactor) flagged by eslint and updates affected
tests and fixtures so `terminated` is no longer referenced. Also:
- Deletes the duplicate `state === "paused"` render branch in
AgentListModal list view that produced two "Resume" buttons.
- Updates the AgentDetailView help text to reflect the current
deletable states ("idle or paused").
- Aligns the bundled-plugin-install test with the new auto-load
behavior for already-installed enabled plugins.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops "terminated" from AGENT_STATES. The agent lifecycle now runs through
idle | active | running | paused | error. paused (carrying a pauseReason)
absorbs every former terminated use case — manual stop, heartbeat run
termination, spawned-child cleanup. Run status (agentRuns.status) is
unchanged: "terminated" stays a valid run-status value.
AGENT_VALID_TRANSITIONS allows direct any→idle transitions so resetAgent
no longer needs the intermediate hop.
Stack-wide:
- core/agent-store: lastError clearing + resetAgent simplified.
- engine/agent-heartbeat, executor, in-process-runtime: terminated state
writes → paused; halt-state listener fires on paused/error.
- dashboard: AgentsView/AgentListModal/AgentDetailView lose the Terminated
badge/option/state-block; agent pickers no longer filter terminated;
agentHealth drops the Terminated branch; routes/state cast widened to
the new AgentState union.
Tests across core and engine updated to assert paused for AgentState and
left "terminated" intact for run-status assertions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merges the documentation update for FN-3287, adding 2 lines to the dashboard README covering PR link visibility behavior. This completes Step 5 of the task.
Fusion-Task-Id: FN-3287
This merge introduces autosave for agent and task detail settings in the dashboard (`TaskDetailModal.tsx`, `AgentDetailView.tsx`), adds an agent self-improvement service with heartbeat evaluation logic (`agent-self-improve.ts`, `agent-heartbeat.ts`), and expands agent tools for direct-report managem
Fusion-Task-Id: FN-3382
Fixes CSS token consistency issues in TaskDetailModal and SettingsModal, and updates the corresponding mobile overflow test to match the refactored styles.
Fusion-Task-Id: FN-3308
Removed fallback logic for task status colors in TaskDetailModal, simplifying the component by relying on proper CSS token fallbacks instead of inline JavaScript defaults.
Fusion-Task-Id: FN-3270
This merge lands FN-3231 across two steps: it preserves a merge-active fix when verification bounces occur (step 1) and ensures the fix is retained during board routing transitions (step 2). Changes span the dashboard Board routing logic and the engine executor, with corresponding test coverage adde
Fusion-Task-Id: FN-3231
Fixes task detail modal danger/error styling by switching to token-based CSS variables for consistent theming across dark and light modes.
Fusion-Task-Id: FN-3350
- Add useMobileScrollLock hook using position:fixed body lock (Bootstrap/
Headless UI/Stripe pattern) to prevent iOS Safari from shifting the
document and visualViewport when an input inside a fixed-position modal
is focused. Wire into 15 input-bearing modals plus ChatView, replacing
ChatView's inline body-overflow effect.
- Widen computeBuildVersion in vite.config.ts to hash the entire app/ tree
so the version-check poll actually notices rebuilds (FN-3333 follow-up;
previously only main.tsx and package.json were hashed).
- ChatView: on input blur, suppress keyboard-aware sizing for 450ms while
reserving mobile-nav-bar space, so the composer snaps to its final
height in one move instead of crawling down with iOS's keyboard slide
and then jumping again when the nav bar reappears.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes a type compatibility issue with the list view detail callback in the dashboard App component, restoring proper typing for the callback.
Fusion-Task-Id: FN-3241
Fixes task link navigation in ListView so embedded links continue working when the split pane is active, including a new test case for FN-3191.
Fusion-Task-Id: FN-3191
The merge brings in a fix (FN-2998) that scopes the bottom safe-area padding in ResearchView to mobile devices only, correcting an over-application of the padding on desktop or larger screens.
Fusion-Task-Id: FN-2998
This merge implements a "preserve progress" option for task resets across the system. FN-3185 adds a `preserveProgress` flag to `moveTask` that keeps status/history when resetting tasks back to `todo`, with required explicit confirmation dialogs to prevent accidental resets. The feature is wired thr
Fusion-Task-Id: FN-3185
Merges FN-3181, FN-3190, and FN-3203: adds an initial runs tab to the agent detail view with auto-expand for the selected run, fixes ListView split-pane UX issues, aligns agent run duration calculation with the `AgentHeartbeatRun.endedAt` field, and restores task detail PR spacing. Updates include n
Fusion-Task-Id: FN-3203
Adds an inline priority picker to the Quick Entry Box and Task Detail Modal with shared badge styling and proper mobile tap targets (FN-3183, FN-3186), updates agent tools tests and documentation for layered memory access patterns (FN-3179), and fixes styling alignment between the modal and inline c
Fusion-Task-Id: FN-3183
Polished the GitHub source issue summary in the TaskDetailModal with UI refinements to its CSS and component markup, along with updated tests covering the new behavior.
Fusion-Task-Id: FN-3176
This release (v0.15.0) introduces plugin dashboard views and a new dependency graph plugin, extends the plugin slot system with richer metadata surfaces and UX improvements, adds SQLite WAL tuning with integrity checks, and stabilizes agent run log streaming with enriched session labels. It also fix
Fusion-Task-Id: FN-3066
Three coordinated fixes for the FN-2978 incident class — auto-requeues
that orphaned committed work and watchdog kills on long verification runs.
**Auto-requeue branch reuse** (executor.ts, worktree-pool.ts)
- executor.ts:1782 now uses `task.branch || fusion/<id>` so persisted
branches are honored on requeue. Previously the hardcoded fallback
always tried to re-create the original branch, hit a conflict with
the prior run's ref, and got suffix -2/-3. Other call sites already
honor task.branch — this aligns the worktree-acquisition path.
- worktree-pool.ts:181 prepareForTask now probes existing branches with
`git rev-parse --verify` and checks them out as-is. Falls through to
suffixed creation only when the branch is genuinely in use by another
live worktree. Previously force-reset with `checkout -B`, destroying
prior commits.
- New private reconcileStepsFromGitHistory walks `git log
baseCommitSha..HEAD` for `feat(FN-X): complete Step N` commits and
marks matching steps[] as done so resumes don't redo committed work.
**Manual reset endpoint + UI** (dashboard)
- POST /api/tasks/:id/reset (requires `confirm: true`) — clears worktree,
branch, all retry counters, resets steps[] to pending, moves to todo.
Distinct from /retry which is the soft-resume path.
- Reset button alongside Retry in TaskDetailModal with confirm dialog,
wired through useTasks → AppModals → API.
**fn_run_verification tool** (run-verification-tool.ts, executor.ts)
- New custom tool wrapping test/lint/build commands with a heartbeat
callback (per-line + 60s synthetic), 200KB head+tail output cap, hard
timeout with SIGTERM→SIGKILL escalation, and auto-bootstrap detection
for missing node_modules. Prevents the inactivity watchdog from
killing sessions during long compiles.
- Cross-platform via `shell: true` (Node picks /bin/sh on POSIX,
cmd.exe on Windows). Prompt section in EXECUTOR_SYSTEM_PROMPT and
EXECUTOR_PROMPT_TEXT instructs agents to prefer package-scoped
verification first and reserve workspace-scoped runs for final
integration.
**Tests** (64 passing)
- detect-pseudo-pause.test.ts (27 tests) — covers all 7 regex patterns,
structural fallback, FN-2978 regression text.
- reconcile-step-regex.test.ts (25 tests) — pins the commit-message
regex against a wide variant set.
- run-verification-command.test.ts (12 tests) — basic execution, output
capture, heartbeat callbacks, timeout, error handling. POSIX-specific
cases (multi-cmd `;`, `>&2`, `\$USER`) gated behind itPosix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add `triage` to VALID_TRANSITIONS["in-review"] so the dashboard's
`Request AI Revision` and `Rebuild Spec` actions work for in-review
tasks. moveTask now applies the same full reset on in-review → triage
as on in-review → todo (clears branch/baseBranch/baseCommitSha/summary/
recovery metadata and workflowStepResults) so the respec'd task starts
from scratch. The in-review task card's Move menu also gains Planning
as a destination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The FN-2869 merge resolution claimed to keep this block removed but
the diff actually re-added it, so it started showing up on the task
details "definition" tab again.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- docs(FN-2869): pluggable notification providers reference + architecture
- chore: changeset for pluggable notification providers
- ui(merge): clarify mergeConflictStrategy option labels — both "smart" and "prefer-main" run the full smart cascade; differ only in the final fallback (-X theirs vs -X ours)
- TaskDetailModal: keep Node Routing summary block removed
Conflicts in executor.ts, core/index.ts, and RoutingTab.* resolved by
keeping HEAD — fn-2869 branched from a stale main and was dragging in
older versions of files that have since been updated by sibling tasks
(including the FN-2887 rebase fix on executor.ts itself).
- Replace notifications UI with reusable provider cards for ntfy and webhook settings
- Add event option metadata rendering and provider-specific test notification actions
- Align notification card gutters with existing settings layout and mobile behavior
- Expand SettingsModal and mobile tests to cover provider card visibility and interactions
On a fresh install useAuthOnboarding's effect ran at mount before the
setup wizard's 500ms auto-open timer fired. The one-shot ref locked,
and the resolved fetch could either stack model onboarding on top of
the wizard or never re-trigger after the wizard closed.
- Gate the trigger on projectId being set so the wizard owns the
bootstrap phase; the auth check only fires once a project exists.
- Re-check setupWizardOpen via a ref when the auth fetch resolves to
avoid stacking onboarding on top of a wizard opened mid-fetch.
- Release the one-shot in that suppressed branch so the effect retries
when the wizard closes.
Adds two regression tests: fresh-install handoff and mid-fetch wizard
suppression.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace split move control with a single move button that supports primary action plus arrow-zone menu toggling
- Add keyboard support for move options via ArrowDown to open and Escape to close and refocus the trigger
- Update task detail styling for the unified move button and arrow affordance states
- Refresh TaskDetailModal and TaskForm tests to cover the new move control behavior and preset selection query
- Extend batch task update APIs and route handlers to accept nodeId overrides alongside model settings
- Update ListView bulk edit UX to load nodes and apply node overrides through batch updates
- Add node routing visibility improvements in task detail/settings UI and align related labels/styles
- Expand dashboard/API test coverage for node override batch updates and bulk edit behavior
- Add a core node-override-guard module, export it from @fusion/core, and enforce conflicts in store updates
- Add API route and CLI extension safeguards so nodeId override updates are blocked when ownership would conflict
- Wire node override routing and validation through dashboard quick-create, list, modal, settings, and task form/detail surfaces
- Add focused unit and integration tests for core guard logic, workflow routes, and dashboard node override UX
When a user drags the native CSS resize grip from inside a modal and
releases the mouse over the overlay, the synthesised click event
targets the common ancestor (the overlay) — fooling the existing
e.target === e.currentTarget dismiss check. Audited every modal with
`resize: both` and switched them to a shared mousedown→mouseup tracking
pattern (new useOverlayDismiss hook) so dismiss only fires when both
events land on the overlay.
Modals fixed: TaskDetail, Settings, FileBrowser, GitHubImport,
GitManager, ScheduledTasks, Scripts, WorkflowStepManager. (Terminal
and AgentDetail were already fixed in 95566795e; PlanningModeModal
already had the right pattern inline.)
Also: in Settings → Authentication, the "Anthropic via Claude CLI"
card now lives inside the Authenticated group when authenticated and
the Available group otherwise, instead of floating at the top.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update-check frequency (end-to-end)
- Add `updateCheckFrequency: "manual" | "on-startup" | "daily" | "weekly"`
to GlobalSettings (default: "daily").
- Backend `performUpdateCheck` honors the frequency: TTL = day/week,
`manual` returns cache or empty without hitting npm, `on-startup`
refreshes once per process lifetime then serves cache. `/refresh`
route forces network regardless.
- Settings → Updates surfaces a working `<select>` for the cadence,
disabled when auto-checks are off entirely.
- Tests: 4 new cases covering ttlForFrequency mapping, weekly window,
manual semantics, on-startup once-per-process behavior.
TUI update notice
- Read cached update result synchronously on TUI startup. When an
update is available, render a yellow notice line on the splash and
a colored ● next to the version in the status bar.
Settings modal header polish
- Add "Star on GitHub" pill (icon + Star + cached star count from the
GitHub API, 1h localStorage TTL) and "Help" button (opens project
Discussions). Both link to the Runfusion/Fusion repo.
- Star button auto-hides after the user clicks it (intent = star),
tracked in localStorage `fusion:github-star-clicked`.
- Settings → General gets a "Show Star on GitHub button" checkbox so
users can hide it preemptively. New global setting
`showGitHubStarButton: boolean` (default true) gates rendering.
More resizable modals
- Task Detail modal: 85vh default, resize: both, persisted via
useModalResizePersist (key `fusion:task-detail-modal-size`).
- Quick Chat FAB: full 8-direction resize (4 corners + 4 edges) via
pointer-event handlers; persisted to
`fusion:quick-chat-size-<projectId>`. Each handle has the right
cursor + role="separator" for accessibility.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The live-token-usage refactor (d30edfda5) merged the SSE-updated `task`
prop on top of `fullDetail` to keep tokenUsage/status fresh. SSE strips
`log` to [] (stripTaskListHeavyFields) for list payloads, so the spread
clobbered fullDetail.log and the Activity timeline rendered empty.
Carve `log` out of the merge alongside `prompt`. Adds a regression test
that simulates the SSE-stripped task prop with a populated fullDetail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Capture per-session token usage from pi-coding-agent's getSessionStats()
after each promptWithFallback in the executor and merger paths, so
task.tokenUsage populates live during runs and reflects final totals on
done tasks. Previously the executor never read session usage and only
the heartbeat path bumped agent token totals, leaving task.tokenUsage
undefined even after completion.
Stats panel and done-card timing also now reflect live state: the modal
overlays the SSE-updated task prop on top of the one-shot fullDetail
snapshot, in-progress workflow steps contribute live elapsed to the
Workflow runtime metric, and the done card uses Timed duration (matching
the stats tab) with workflow runtime as fallback. Time indicator labels
coarsened to <1m / Nm / Nh / Nd.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add reusable ConfirmDialog component, styles, and useConfirm hook to provide async confirmation flows
- Wire ConfirmProvider at app level and migrate confirm call sites across task, agent, roadmap, plugin, and settings UI actions
- Update modal interaction patterns to support dialog reentry and consistent destructive-action confirmations
- Expand dashboard tests with confirm dialog and hook coverage plus migrated component test assertions
- Rework TaskDetailModal move controls to use split-button primary/secondary transitions with in-review-specific options
- Add dedicated split-button styling for divider, chevron menu, focus states, and mobile sizing using design tokens
- Keep in-review merge action visible while move options remain accessible through secondary menu actions
- Expand TaskDetailModal tests to cover split-button rendering, primary click behavior, and secondary transition menu contents