Prevent done-task diff endpoints from counting base-commit-only lineage as task-owned changes.
- add base-boundary handling in done-task merge SHA resolution so `baseCommitSha` is excluded by default and only consulted for boundary checks
- short-circuit `/diff` and `/file-diffs` responses to empty results when resolved done-task SHA is at or below `baseCommitSha`
- export and use an ancestry helper to detect base-boundary cases, while preserving normal and rebase range behavior
- extend done-task diff route tests with FN-5666 cases for no-op merge SHA, lineage association at base commit, normal post-base commits, and rebase ranges
- add a patch changeset for `@runfusion/fusion`
Files changed:
.changeset/fn-5666-base-commit-exclusive.md | 5 +
.../src/__tests__/routes-diff-done-tasks.test.ts | 217 ++++++++++++++++++++-
.../src/routes/register-session-diff-routes.ts | 57 +++++-
3 files changed, 273 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-5666
Fusion-Task-Lineage: 782f9875-856a-4d31-9505-0bcd638c9c29
Introduces a Goals REST API (`GET/POST/PUT /api/goals` and `GET/PUT /api/goals/:id`) backed by a new `@fusion/core` goal store and typed goal types, including comprehensive route and store test coverage. Documentation on architecture and storage is updated to reflect the new domain, and a changeset
Fusion-Task-Id: FN-5622
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5622
Implements source issue delete handling in the task dashboard, including prompt-based user interaction for source-linked issues, new GitHub tracking state logic in `packages/dashboard/src/github-tracking-state.ts`, and corresponding test coverage, with documentation added to `docs/task-management.md
Fusion-Task-Id: FN-5618
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5618
This merge implements an OAuth relogin banner feature (FN-5595) that displays in the dashboard when OAuth tokens expire. The feature includes a new `OAuthReloginBanner` component with styling and tests, an OAuth validity logger in the engine for tracking token state, and corresponding API route inte
Fusion-Task-Id: FN-5595
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5595
- fix(perf): use messagesRef.current in loadMoreMessages to avoid
recreating callback on every streamed token; messagesRef is already
kept in sync on every render so no useEffect needed — removes
`messages` from useCallback deps
- fix(api): reject invalid order query param with 400 instead of
silently ignoring; valid values are 'asc' and 'desc'
Tests:
- useChat: loadMoreMessages identity is stable when messages array changes
- chat-routes: GET /messages?order=invalid returns 400
Multiple coordinated fixes for the perceived "dashboard takes forever to
load" complaint. Per-page-load HTTP requests drop from ~177 to ~101 and
duplicate per-project InProcessRuntime creation is eliminated.
- engine: shouldUseHybridExecutor no longer auto-enables for local-only
multi-project setups (set FUSION_HYBRID_EXECUTOR=1 to force). The
duplicate-runtime path was running self-healing twice per project and
contending on the same SQLite file. ProjectEngineManager already
handles N local projects with one InProcessRuntime each.
- dashboard cli: parallelized independent store inits, started
CentralCore.init early in background, ran plugin loading concurrently
with extension resolution. Sequenced SQLite store inits to avoid a
TOCTOU race in addColumnIfMissing migrations across TaskStore /
AutomationStore / PluginStore / AgentStore (all open the same
.fusion/fusion.db). Restored try/catch around HybridExecutor.initialize
and engineManager.ensureEngine so a paused or broken cwd project no
longer aborts dashboard startup.
- dashboard client: added in-flight request dedupe wrapped around the
top API offenders. /api/plugins/ui-slots drops from 17x to 1x per load.
dedupe.forceFresh redirects ALL in-flight waiters to receive the fresh
post-mutation response, not just the forcing caller. Generation
counters in useAgents and AgentListModal protect against slow polls
overwriting fresh state.
- dashboard SSE: agent event handler now debounces 250ms with a
trailing-edge guard so multi-agent activity bursts coalesce to at
most 2 refetches per burst.
- dashboard route: PATCH /api/projects/:id with isolationMode change
returns 503 with actionable guidance when HybridExecutor is
unavailable, instead of silently persisting a config the live runtime
won't honor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve conflict in register-chat-routes.ts: keep per-project
ChatManager routing via resolveScopedChatManager while preserving
main's resolveProjectChatContext-based store resolution for read
routes. The auto-merged chat-project-services.ts correctly combines
main's fallback-safe resolveProjectChatContext with the PR's new
getOrCreateScopedChatManager cache.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
In multi-project mode the global chatManager was backed by ~/.fusion/fusion.db.
Secondary project chat sessions live in per-project DBs, so
chatManager.sendMessage() failed with 'Chat session not found' for any
project that is not the daemon's CWD.
Fix: add getOrCreateScopedChatManager to chat-project-services.ts (cached by
fusionDir, same pattern as the existing chatStore cache). POST /messages,
GET /stream, POST /cancel, and GET /sessions isGenerating enrichment all
resolve the per-project ChatManager when projectId is provided.
Fallback to global chatManager when no projectId (preserves single-project mode).
Tests: added multi-project chat routing describe block in chat-routes.test.ts.
Group A (2 failures): resolveProjectChatContext was calling
getOrCreateProjectStore even when no engine existed for the
project. This triggered real FS lookups in tests, causing the
catch to return the default store instead of the engine store.
Fix: only take the engine path when an engine is actually found.
Group B (1 failure): createSSERequest() returned a bare
EventEmitter with no .query property. The refactored handler
reads req.query.projectId at the top, throwing TypeError.
Fix: initialise .query = {} in createSSERequest().
Group C (4 failures): createMockStore() in routes-agents.test.ts
was missing getFusionDir(), which getOrCreateScopedChatStore()
calls to compute the cache key. The resulting TypeError caused
every lookup=resume handler invocation to 500.
Fix: add getFusionDir() to the mock.
Adds planning branch controls to the PlanningModeModal, extending the planning API and routes with supporting tests and documentation. The changeset bumps `@runfusion/fusion` as a minor release.
Fusion-Task-Id: FN-5585
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5585
Replace execFileAsync("mkdir", ["-p", ...]) with fs.mkdir({ recursive: true })
in the cloudflared install fallback path. The -p flag is Unix-only and breaks
on Windows cmd.exe ("A subdirectory or file -p already exists"). Test mocks
updated to verify the fs.mkdir call instead of the shelled-out mkdir.
The original report covered both this site and packages/engine/src/worktree-hooks.ts;
the latter was already converted to fs.mkdir independently, so only the
dashboard route change is needed.
Co-Authored-By: kenlin8827 <kenlin8827@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously, getProjectContext awaited ensureEngine() which could block the
HTTP request handler for several seconds while a project engine initialised
(e.g. for newly-registered projects). This caused curl --max-time timeouts
and empty responses on the first request to a new project.
Change: replace await ensureEngine() with onProjectAccessed() (fire-and-forget).
- First request to an unstarted project uses getOrCreateProjectStore directly
(fast, reads from SQLite) — no blocking.
- Engine starts in background; subsequent requests use the running engine.
- Eliminates timing-dependent restart workarounds in init scripts.
Fixes: fn settings import followed by immediate API calls returning empty.
Adds integration test coverage for the GitHub tracking delete flow in `github-tracking-delete.test.ts`.
Fusion-Task-Id: FN-5582
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5582
Added GitHub tracking reconciliation to sync hidden and deleted archived tasks on engine startup, spanning a new reconcile task listing method in the core store, a reconciler pass in the dashboard, and comprehensive test coverage for both the store listing and the deleted-archived reconciliation log
Fusion-Task-Id: FN-5577
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5577
Implements the allow-resurrection toggle for task deletion, letting users prevent deleted tasks from being automatically restored. Changes span the `ConfirmDialog` component, `TaskDetailModal`, and the `useConfirm` hook, with comprehensive test coverage across the dashboard API and UI layers.
Fusion-Task-Id: FN-5475
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5475
When the merger advances local `refs/heads/<integrationBranch>` via
`update-ref` without pushing, the user's project-root worktree HEAD
(symbolic to that branch) follows immediately to the new sha, but the
working files and index don't. The integration-mode pull only ran
`git merge --ff-only origin/<branch>`, which short-circuits as
"already up to date" when local is ahead of origin — leaving the
worktree visibly stale even though "Pull completed" was reported.
Pull now explicitly `git reset --hard <localIntegrationTip>` after
the origin fast-forward step. The autostash above protects user edits,
so the reset is safe regardless of whether the origin FF ran.
Regression test in routes-git.test.ts simulates the
local-ahead-of-origin scenario and asserts the reset-to-local-tip is
issued.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a fast-path method for scopes-related settings calls in the memory routes handler, replacing the previous implementation with a more efficient approach; tests are updated to cover the new route behavior.
Fusion-Task-Id: FN-5563
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5563
Implements the FN-5233 tombstone system for soft-delete resurrection: a configurable `tombstoneWindowSeconds` deduplicates recreation of recently deleted tasks, with an `allowResurrection` flag that permits explicit resurrect-on-recreate, tombstone recreate guards in the store layer, and cleanup of
Fusion-Task-Id: FN-5233
Implements a pull-based merge workflow by wiring the merger pull helpers from the engine, extending the git pull and stash routes, and aligning the `MergeAdvanceNotice` and `StashConflictModal` components to gate dismissal on stash drop. The `run-audit` module is updated with pull mutation documenta
Fusion-Task-Id: FN-5419
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5419
Adds a push-to-origin workflow to the merge notice system, introducing a new `useMergeAdvanceNotice` hook, a `merge-advance-push-origin` route handler, and corresponding UI affordance in the `MergeAdvanceNotice` banner component. The engine gains TOCTOU and refusal audit assertions, and coverage exp
Fusion-Task-Id: FN-5359
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5359
Implements project identity tracking and recovery across the Fusion system (FN-5411), enabling persistent identity for projects across storage migrations, daemon reattaches, and CLI session management. Adds a project identity metadata API and central reattach ensure mechanism, wires identity stampin
Fusion-Task-Id: FN-5411
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5411
Surface the live mode / modalOpen / keyboardOpen / footerVisible / view
values that MobileNavBar uses for its early-return so the ?vpdebug overlay
can show which one is hiding the bar on Android. Also dumps the
.project-content className so we can correlate with `--with-mobile-nav`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds retry-reset logic that clears the user-paused flag on tasks, ensuring they can resume automatically after a retry is triggered, with regression tests covering the behavior across the CLI extension and core manual-reset module.
Fusion-Task-Id: FN-5485
In multi-project mode, all /chat/sessions* handlers used options.chatStore
(the home-dir project's store) regardless of the projectId query param.
Sessions in secondary projects were invisible via the API.
Root cause: registerChatRoutes accessed options.chatStore directly instead
of routing through resolveProjectChatContext (already used correctly in
registerChatRoomRoutes for the rooms API).
Fix: introduce resolveScopedChatStore(projectId) helper that delegates to
resolveProjectChatContext, replacing all ten options.chatStore usages.
Falls back to default store when engineManager is absent (backward compat).
Tests: add two cases to verify engine-scoped chatStore is used when
engineManager is configured for the requested projectId.
Implement the hard-archived delete contract: add a typed `ArchivedTaskDeleteError`, map hard-archived task deletes to HTTP 410 Gone at both the store and routes layers, and document the invariant in the soft-delete verification matrix.
Fusion-Task-Id: FN-5196
Implements stash conflict detection and resolution with a new smart pull API route, resolution endpoints, and a dedicated conflict modal UI — backed by extended git audit taxonomy and route tests.
Fusion-Task-Id: FN-5358
Raised room transcript defaults (`messagesBefore` and `daysBefore`) in the core settings schema and updated project-level setting defaults, with corresponding documentation refresh in the settings reference. Added full test coverage for room compaction defaults, pinned room default settings in Setti
Fusion-Task-Id: FN-5374
Scheduler now gates task update invalidation, preventing spurious invalidations when engine lifecycle changes (soft-delete, lease recovery) touch task metadata, with coverage via new scheduler invalidation tests and a small dashboard server test adjustment.
Fusion-Task-Id: FN-5430
Exposes the `opencode-go` provider via `startup-model-sync`, wires it into the daemon and serve commands, and adds a refresh-status indicator in the SettingsModal that triggers model reloading whenever the provider key is saved. Includes a changeset, settings documentation, and corresponding tests a
Fusion-Task-Id: FN-5424
Removes a title-length guard from mission routes (4-line deletion in `mission-routes.ts`) and adds end-to-end coverage for long interview mission titles (`mission-e2e.test.ts`).
Fusion-Task-Id: FN-5406
Added manifest-gated checksum verification for cloudflared remote access tunnels: a pinned manifest validator (Step 1) and enforcement logic (Step 2) wired into the settings memory routes, with aligned tests and documentation covering fail-closed install behavior and pending-manifest guidance.
Fusion-Task-Id: FN-5375
Adds an explicit duplicate-marker guard (FN-5220) spanning core helper, dashboard API endpoint, triage short-circuit, and self-healing sweep to detect and handle duplicate task creation attempts; includes comprehensive test coverage across unit, API, and integration layers plus documentation.
Fusion-Task-Id: FN-5220
The dashboard's git pull endpoint failed outright when the working tree had
local edits or untracked files. It now stashes (including untracked) under a
fusion-dashboard-pull-autostash label, performs the pull, and reapplies the
stash. If reapplying conflicts, the stash is preserved and GitPullResult
surfaces autostashed/stashReapplied/stashConflict plus a message pointing at
the stash label so the user can resolve from the Stashes view.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>