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>
In reuse-task-worktree mode the merger detaches HEAD in the task worktree so
the squash commit lands on detached HEAD; nothing previously advanced the
project root's local integration branch, so changes never appeared on main.
Step 5c now applies the squash to projectRootDir via git merge --ff-only,
falling back to a regular merge with AI conflict resolution if main has
diverged. pushAfterMerge (when enabled) now runs from projectRootDir where
the branch was just advanced, so parsePushRemoteTarget can resolve a branch
instead of failing on the worktree's detached HEAD.
Also tightens acquireReuseHandoff: the executor-lease check above the
queue-lease acquisition was non-atomic, letting a local executor grab the
task between checks. Re-check after acquisition and release the queue
lease with a precise diagnostic instead of proceeding into a generic
failure later.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous commit wired targetTaskId through the engine caller but the
store's acquireMergeQueueLease SQL still grabbed the queue head unconditionally,
leaving the no-lease loop intact. This lands the store-side change: when
targetTaskId is provided it attempts a direct-match UPDATE first; only falls
back to queue-head ordering if that row isn't available (backward-compatible).
Adds regression test covering the polluted-queue-head scenario (FN-5363).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When targetTaskId is passed, the lease attempt must target that task only.
The previous code silently fell back to queue-head selection if the targeted
task was not available — producing a lease for a different task, then
returning it with the wrong taskId. acquireReuseHandoff would then see
lease.taskId !== input.task.id and emit a misleading 'no-lease' diagnostic
that hid the real cause (queue head was occupied by an unrelated task).
The fix: when targetTaskId is set and the lease for that task returns null,
return null immediately instead of falling through to the queue-head SELECT.
Callers (acquireReuseHandoff) already validate the returned taskId and emit
structured 'no-lease' diagnostics including acquiredTaskId so the polluter
is identifiable in audit logs.
Queue-head fallback is preserved for callers that omit targetTaskId
(backward-compatible).
The merge handoff path in acquireReuseHandoff called acquireMergeQueueLease
without a targetTaskId, which grabbed the priority/FIFO-sorted queue head
instead of the specific in-review task. When the queue head was a different
task (e.g. a polluted non-review entry), the returned lease had a mismatched
taskId and triggered 'no-lease' for every in-review task.
Fix:
- Pass targetTaskId: input.task.id to acquireMergeQueueLease so the merge
lane targets its specific task instead of grabbing the queue head.
MergeQueueAcquireOptions.targetTaskId is already wired in store.ts.
- Replace the broken typeof check (typeof object !== 'object' is always false
for plain JSON objects returned by RETURNING *) with a proper 'taskId' in
lease guard.
- Add acquiredTaskId to the no-lease error payload for better observability.
Reliability backstop: merge-reuse-task-worktree.test.ts guards this path.
Fixes: FN-5363
The behavioral cwd-main fallback is gone (fresh-acquire on refusal
replaces it), but the type string was left as a dead entry in the
emitReuseHandoffAuditEvent union (merger.ts) and the
DatabaseMutationType union (run-audit.ts). Remove both so the dead
string cannot be accidentally reintroduced.
Before: when reuse-task-worktree was configured but task worktree was missing/unusable,
merger fell back to cwd-main, losing the task worktree isolation benefit.
After: merger creates a fresh worktree for the task branch inline (using the standard
git worktree add pattern with identity guard installation) and retries the reuse handoff.
Only falls back to cwd-main if fresh acquisition also fails.
Three new audit events track the recovery path:
- merge:reuse-worktree-fresh-acquire — fresh acquisition started
- merge:reuse-worktree-fresh-acquired — fresh worktree created and bound to task
- merge:reuse-fallback-cwd-main — only when fresh acquisition itself fails (last resort)
Behavior:
- Missing/unusable task worktree → fresh worktree created, merge continues from it
- Fresh acquisition fails → cwd-main fallback (last resort, fully audited)
- Genuine liveness conflict (usable worktree but lease refused) → re-thrown, not masked
Regression test covers the missing-worktree case: verifies fresh acquisition + handoff
succeeds without any cwd-main fallback event.
After merge:reuse-handoff-refused with no usable task worktree:
- Acquire a fresh worktree and restore the fusion/<task-id> branch
from baseCommitSha before continuing merge
- Hard-fail only if fresh acquisition itself fails (not cwd-main fallback)
- Emit merge:reuse-worktree-fresh-acquire / merge:reuse-worktree-fresh-acquired
audit events around the acquisition lifecycle
Replaces the incorrect cwd-main fallback (499784581) with correct
reacquire path. Updates regression test in merge-reuse-task-worktree.test.ts
to assert fresh-acquire audit trail instead of cwd-main fallback.
Refs: FN-5353
When mergeIntegrationWorktree=reuse-task-worktree but the task has no
worktree or the worktree classifies as unusable, the merger now:
1. Creates a fresh worktree at the standard path with the fusion/<id> branch
2. Installs identity-guard hooks
3. Updates task.worktree + task.branch in the store
4. Emits merge:reuse-worktree-fresh-acquire / merge:reuse-worktree-fresh-acquired
5. Retries the handoff from the new worktree
Only falls back to cwd-main as last resort when fresh acquisition also
fails. Lease/liveness conflicts (worktree exists and classifies OK but
handoff refused on active-session or lease grounds) are re-thrown — not
masked with cwd-main.
New audit event types: merge:reuse-worktree-fresh-acquire,
merge:reuse-worktree-fresh-acquired
Clears agent logs when a task is soft-deleted, with new regression tests covering the end-to-end behavior and documentation updated in the storage guide. The core logic lives in `store.ts` while `store-upsert.test.ts` is updated to reflect the new expectations.
Fusion-Task-Id: FN-5143
Adds broad-scope advisory chips to TaskCard and banner to TaskDetailModal with comprehensive test coverage and a dashboard guide entry. TaskCard gains an inline advisory chip (with styles), TaskDetailModal gets a matching banner, and both components have dedicated test suites covering the new UI ele
Fusion-Task-Id: FN-5314
Fusion-Task-Lineage: cbc88f36-d029-4e4b-ac9c-32a77560b8b9
Implements the `mergeIntegrationWorktree` setting (FN-5279) that allows tasks to reuse their own worktree as the integration root instead of spawning a separate one. Steps 1–2 added the settings schema, types, and SettingsModal surface with documentation; Step 3 wired an integration-root resolver th
Fusion-Task-Id: FN-5279
FN-5275 aligns the fallback copy in TaskChangesTab with updated wording, and updates the corresponding test assertions to match the new text.
Fusion-Task-Id: FN-5275
- Add a merger guard that verifies source fusion/FN branch attribution when rebase capture reports zero own commits
- Fail finalize with explicit no-op attribution mismatch handling instead of marking mergeConfirmed on ambiguous no-op ranges
- Type and emit dedicated audit events for mismatch and source-ref-unavailable skip diagnostics
- Expand branch attribution, merger, and reliability interaction tests to cover the full no-op guard matrix
Fusion-Task-Id: FN-5304
Implements canonical worktrunk binary naming and manifest handling (FN-5320), adding a worktrunk installer that canonicalizes the executable name and manifest data, with documentation updates for architecture and settings, plus test alignments across routes, audit, and worktree acquisition fixtures.
Fusion-Task-Id: FN-5320
Fixes the main chat composer flex sizing so the input area properly expands (FN-5322), with regression guards in the autosize test suite and a new browser layout smoke script covering the composer expand behavior.
Fusion-Task-Id: FN-5322
Add regression tests for queued concurrency in the scheduler and tighten the memo key used to track queued tasks, improving correctness of scheduler dispatch decisions.
Fusion-Task-Id: FN-5319
Adds pre-commit identity guard handling for branch case normalization (FN-5271), updating the worktree hooks implementation and adding a real-git integration test alongside a changeset for `@runfusion/fusion`.
Fusion-Task-Id: FN-5271
Restores visibility of action icons in SecretsView (CSS styling and component adjustments), accompanied by updated test coverage. A test stabilization commit for the process supervisor fallback rounds out the merge.
Fusion-Task-Id: FN-5257
- Standardize SecretsView action icon sizing and color so header, row, loading, and modal toggle icons stay visible in dark and light themes
- Expand SecretsView tests to load app CSS and assert icon visibility across both themes
- Stabilize the process supervisor fallback test by removing an unnecessary maxLifetime override
Fusion-Task-Id: FN-5257
The merge adds a file scope sanitizer to the task store that deduplicates and normalizes path entries, with test coverage in `store-parsing.test.ts`; a small documentation fix accompanies the change in AGENTS.md.
Fusion-Task-Id: FN-5216
The merge adds a new self-healing recovery path for tasks stuck in `in-progress` limbo (no pending step updates but not marked done), hardening `resetTask` and `recoverInProgressLimboTasks` with proper worker binding cleanup, audit event coverage, and integration tests validating the invariant acros
Fusion-Task-Id: FN-5219
Fixes a race condition where task deletion could race against move-related GitHub tracking logs. Both `GitHubTrackingCommentService` and `GitHubTrackingStateService.handleTaskMoved` are hardened to gracefully swallow deleted-task races, with a regression test covering the delete-after-move scenario.
Fusion-Task-Id: FN-5245
Merges FN-5218: adds hash mention support (`#`) in chat composers, grouping task and file reference results in a unified popup, with wiring into `ChatView` and `QuickChatFAB`, plus test coverage and docs. The hook `useFileMention` is extended and refactored, and the file mention popup UI is updated
Fusion-Task-Id: FN-5218
- Add project-scoped Pause All Agents and Resume All Agents actions to the AgentsView controls menu
- Load bulk-action eligibility on menu open and skip ephemeral or ineligible agents
- Surface bulk action confirmations, success/error toasts, and refresh agent state after updates
- Add dashboard tests and agent docs coverage for the new bulk controls
Fusion-Task-Id: FN-5227
Two test-only commits for FN-5305 improve timing reliability and assertion accuracy in the delete route and GitHub-tracking-delete test suites by replacing unreliable one-tick flushes with explicit async synchronization and aligning expectations with audit context behavior.
Fusion-Task-Id: FN-5305
This merge introduces SWR-style caching across the dashboard to eliminate redundant fetches for models, agents, and skills, significantly refactoring ChatView.tsx (reduced by ~140 lines) by offloading cache coordination to three new dedicated hooks (`useAgentsMapCache`, `useDiscoveredSkillsCache`, `
Fusion-Task-Id: FN-5202
Adds a reconcile script to recover leaked soft-deleted tasks, threads delete audit context through all callers, and records soft-delete audit events with archive column tracking across core/engine/cli/dashboard, with reliability backstop tests covering caller alignment.
Fusion-Task-Id: FN-5175
- Add the optional Task.source field back to the core Task interface
- Preserve durable task creation and import provenance typing alongside sourceIssue metadata
- Unblock workspace typechecking for consumers that read task source metadata
Fusion-Task-Id: FN-5193
Adds paginated PR review snapshots to the dashboard GitHub module with corresponding test coverage across the unit and route layers.
Fusion-Task-Id: FN-5181
Implements in-flight abort for soft-deleted tasks across all three execution lanes: executor, merger, and triage now check for `deletedAt` before proceeding and emit `task:soft-delete-in-flight-abort` audits rather than continuing work on a deleted task. The 829-line addition is dominated by integra
Fusion-Task-Id: FN-5264
Fusion-Task-Lineage: 4ee8e63b-abf0-43e2-9130-39a05434d8f9
The merge introduces an atomic review handoff seam in the core store (`packages/core/src/store.ts`) and migrates executor and self-healing transitions to use it, replacing the previous multi-step mutable-state handoff with a single transactional operation. Extensive reliability backstops and regress
Fusion-Task-Id: FN-5241
Adds a near-duplicate guard to the CLI task creation command (FN-5171), preventing creation of tasks with titles that are visually or semantically identical to existing ones, with 262 new test cases covering the detection logic and the standard changeset entry.
Fusion-Task-Id: FN-5171
- Replace host tar invocation in parseCompanyArchive with in-process archive extraction
- Add core regression coverage for parsing archive contents without shell tar behavior
- Add unmocked dashboard route tests covering CLI company archive imports end to end
- Add a changeset for the published @runfusion/fusion package update
Fusion-Task-Id: FN-5170
Restores toggle icon styling in `SecretsView.css` and adds test coverage for the eye-toggle reveal/hide behavior in `SecretsView`, completing the FN-5161 test suite for the secrets view.
Fusion-Task-Id: FN-5161
Adds a tablet board override to fix overflow regressions on the dashboard, with a corresponding test covering the regression path and a hardening fix to the parsing logic.
Fusion-Task-Id: FN-5281
Adds a per-machine singleton lock that engages in
ProjectEngineManager.createAndStart() before any engine subsystems
spin up. Two fn dashboard processes can no longer run engines for the
same project on the same host — previously they would share .fusion/
state and corrupt worktrees / task rows for in-process projects.
The guard combines two independent checks:
- A proper-lockfile file at <project>/.fusion/engine.lock with
stale-lock recovery (auto-released on process death).
- A loopback listener on a hashed per-project address — UDS on
POSIX, named pipe on Windows. Stale UDS files are probed and
unlinked before a retry bind.
Failures raise EngineAlreadyRunningError. Both guards are released
from stopAll() and pauseProject(); a release on engine.start()
failure lets retries re-acquire cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>