Resolves CI failures where Node.js 24 caused ReferenceError: window is not defined
in non-dashboard tests that shared setupFiles with dashboard tests.
Follows the same pattern already used by fusion-plugin-roadmap: split into two
vitest projects with proper environment isolation:
- reports-dashboard: jsdom, includes src/dashboard/** tests + dashboard test-setup.ts
- reports-node: node, includes all other tests, excludes dashboard tests
No test changes — same 104 tests, same pass/fail state.
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.
- Drop the tablet-tier `.board` grid rule that crammed 6 columns into
≤1024px viewports with no min-width, scrunching column content to
unreadable widths. Tablets now use the default `minmax(300px, 1fr)`
and scroll horizontally like desktop.
- Drop `maximum-scale=1.0, user-scalable=no` from the viewport meta.
Combined with `initial-scale=1.0` those flags trigger Android Chrome
layout bugs in multi-window mode; the Capacitor-feel justification
isn't worth the breakage in a browser-rendered dashboard.
- Broaden the existing iOS scroll-snap stabilization in Board.tsx from
`(max-width: 768px)` to any touch-primary device, and re-run it the
first time tasks populate so Android tablets get the same first-cards-
loaded reflow that mobile already had.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Added a runtime navigation height observer to `MobileNavBar` that captures the browser's dynamic nav-height CSS value at runtime, updated both the nav height test coverage and the Android overlap CSS contract test, and documented the new token in `AGENTS.md`.
Fusion-Task-Id: FN-5476
Added resume instrumentation to the `useAgentLogs` hook (`packages/dashboard/app/hooks/useAgentLogs.ts`) with test coverage and diagnostics documentation. The new test file is included in the dashboard test gate via `vitest.config.ts`.
Fusion-Task-Id: FN-5469
Restructured AGENTS.md from a 588-line catch-all into a lean reference of essential rules by offloading deep guidance into five new/expanded doc files: agents.md, architecture.md, dashboard-guide.md, settings-reference.md, and testing.md. Also restored a missing FN-5345 lifecycle invariant in self-h
Fusion-Task-Id: FN-5339
Fusion-Task-Lineage: e1a2dc4f-ae50-46f4-acd3-8f2c3673feb4
Contamination on fusion/<id> branches (FN-5233 was the recent example:
two untrailered feat(FN-5353): commits sitting on fusion/fn-5233) used
to be invisible until merge time, days after it happened. The executor
already runs assertCleanBranchAtBase at worktree acquisition and reclaim
— the gap was the active session window itself.
Add reportBranchAttribution(repoDir, branch, baseSha, taskId) which
walks base..branch and bins every commit into ownTrailed (healthy),
ownUntrailed (subject tag but commit-msg hook didn't fire), foreign
(different FN-id), or unattributed (no subject pattern, no trailer —
typically a hand-merge or plumbing commit). Wire it into the executor
right after captureModifiedFiles in the post-session path: when any
anomaly bucket is non-empty, emit a structured branch:attribution-
anomaly audit event and a task log entry. The audit itself is wrapped
in a try/catch so a probe failure never destabilizes a completing
session. New branch:attribution-anomaly and branch:auto-reattach-
authoritative GitMutationType variants accept the structured metadata
(the latter for the handoff re-attach added earlier this session).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
commitOrAmendMergeWithFixes used to swallow every unexpected throw as
`reason: "unknown-phantom"` and the two callers re-threw a bare
"verification fix finalize failed (unknown phantom)" with no operator-
actionable signal. FN-5422-class wedges (preAttemptHeadSha == currentHead
but branchTip ahead with task-trailered commits) couldn't be diagnosed
without re-running.
The catch now records the original error and probes whether the branch
ref itself is authoritative for the task (tip carries Fusion-Task-Id
trailer, base..branch is foreign-contamination-free). When it is — i.e.
the work isn't lost, the integration worktree just didn't advance — the
catch resets rootDir to preAttemptHeadSha so the next merge attempt
starts from a known baseline instead of inheriting partial squash state,
and returns `reason: "branch-ref-ahead-reset"`. The two callers fold
`originalError=` and `branchAuthority=` into the thrown message so the
real cause (diff-volume gate, file-scope, transient git, etc.) is
visible in the run log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The merge handoff refused with head-branch-mismatch whenever the reused
worktree's HEAD wasn't on fusion/<id> (detached, recycled to main, or on
a sibling branch), even when the branch ref itself still held a clean,
task-attributed lineage. That wedged FN-5339-class tasks in review for
no good reason.
Add isBranchAuthoritativeForTask in branch-conflicts.ts (branch ref
exists, tip carries Fusion-Task-Id trailer, base..branch is foreign-
contamination-free) and use it in acquireReuseHandoff: when HEAD drifts
but the branch ref is authoritative, run a plain `git checkout <branch>`
inside the already-asserted-clean worktree, re-read HEAD, and emit a
branch:auto-reattach-authoritative audit. Refusal still fires unchanged
when the branch ref is missing, missing the trailer, or contaminated,
so FN-5363 strict-lease and foreign-commit guards remain authoritative.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a manual merge blocker mode (FN-5438) that prevents automatic merging and provides a bypass mechanism to resume, wired through the merger, project engine, and task workflow API routes. Includes tests across core, engine route registration, and project engine layers, plus a changeset and documen
Fusion-Task-Id: FN-5438
Adds structured stream-resume instrumentation to the dashboard across four SSE hooks (PR checks, dev-server logs, research, background sessions), wiring `[wake-trigger-diagnostics]` log markers and view-resume route guards so the engine can distinguish cold starts from resume paths; includes tests f
Fusion-Task-Id: FN-5416
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
Fixed a TypeScript nullability narrow in the `MergeAdvanceNotice` component, safely handling a potential null checkout value. This is a targeted type-safety fix for the integration branch advance banner.
Fusion-Task-Id: FN-5447
Merges the Layer 2.5 scope-auto-widen feature (FN-5226) into the merger: a new evaluator module that automatically widens a task's declared file scope based on git attribution prior to the existing scope partition gate, wired into `merger.ts` with full audit taxonomy, persisted task metadata, and re
Fusion-Task-Id: FN-5226
Adds visibility resume emissions to the four managed state hooks (`useMeshState`, `useNodes`, `useProjects`, `useManagedDockerNodes`) and establishes corresponding instrumentation test coverage, with a documentation update to the diagnostics reference covering board hook telemetry.
Fusion-Task-Id: FN-5415
Test coverage hardening for FN-5440: adds stronger interaction tests across three steps covering the cwd-integration-fallback-removed path and the merge-reuse-task-worktree early fast-path, including expanded fallback audit tripwires and hardened metadata literal guards. No production code changes.
Fusion-Task-Id: FN-5440
Added a scroll-to-top action for the ChatView with per-message scroll behavior, styled to match the mobile design, with comprehensive test coverage for scroll-to-top behavior. Also preserves the mobile copy-action CSS selector.
Fusion-Task-Id: FN-5379
Removes the broad-scope detection feature end-to-end: the TaskCard chip and TaskDetailModal advisory banner are gone from the dashboard, the triage heuristic that flagged tasks as broad-scope has been deleted from the engine along with its associated run-audit events, and documentation references ha
Fusion-Task-Id: FN-5405
FN-5351 adds structured telemetry for merge audit events and integration worktree state, including typed ref-advance tracking, terminal handoff fallback audit, and integration state probes with corresponding reliability backstop tests and documentation updates.
Fusion-Task-Id: FN-5351
Implements ref-only integration branch advancement via `git update-ref` instead of checkout+commit, including a new `merger-ref-update-advance.ts` helper, a reduced and clarified `merger.ts`, comprehensive unit and real-git regression coverage, and audit event wiring.
Fusion-Task-Id: FN-5350
Removes the `cwd-main` integration fallback mode (FN-5348), eliminating the legacy shortcut path where the merger would operate directly on the project root instead of a dedicated worktree. Steps normalize the `reuse-task-worktree` integration mode as the sole path, wire stricter mode invariants in
Fusion-Task-Id: FN-5348
Fixes a stale queued-status recovery branch in self-healing and updates the corresponding test assertions to match the corrected behavior.
Fusion-Task-Id: FN-5434
A task that picked up status='queued' or overlapBlockedBy while waiting in
todo (file-scope overlap with a higher-priority peer) was carrying those
todo-dispatch markers into in-review, where the merge gate then permanently
refused with "task is marked 'queued'". Ghost-review → todo → scheduler
re-queue → stranded-completed-todo recovery → in-review formed a steady-
state loop that never let the task merge.
moveTaskInternal now treats queued/blockedBy/overlapBlockedBy as todo-only
dispatch state and clears them on every transition into in-review. failed
and awaiting-* statuses are left untouched (already covered by an existing
test, plus a new regression test for the queued case).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Added executor logic to skip retries when a review is pending for a task, introducing a `pendingReviewBlockHelper` in the task-done path and updating the retry-gate to consult it; two new reliability-interaction test suites cover the feature behavior and composition with existing retry/backstop laye
Fusion-Task-Id: FN-5436
Close the last fire-and-forget gap from the previous fixes: the task:moved
(away from in-progress) and task:deleted listeners no longer call the
synchronous fire-and-forget `abortInFlightTaskWork`. Instead they track an
awaited disposal promise per task in `pendingTaskDisposals`. The task:moved
(to in-progress) dispatch path awaits any in-flight disposal for the same
task before calling `execute()`, so a fast bounce (in-progress → todo →
in-progress) no longer races the conflict-cleanup path against a still-live
shell.
`awaitAbortInFlightTaskWork` now claims each session surface (activeSessions,
activeStepExecutors, activeWorkflowStepSessions, activeSubagentSessions)
synchronously before awaiting any async abort. This lets concurrent disposal
calls for the same task dedupe naturally — the second call finds the maps
empty and no-ops, preserving the existing single-abort/single-dispose
contract that the soft-delete and user-cancel tests assert.
Adds a regression test in executor-user-cancel covering the re-dispatch
ordering: an immediate task:moved-to-in-progress that follows a still-running
task:moved-away must wait for abort to complete before execute() runs.
The legacy `abortInFlightTaskWork` is removed (no callers).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review follow-up to cf0101be7. The merger integration worktree path
was still calling bare `activeSessionRegistry.reconcileStaleSelfOwned` for
same-task entries, bypassing the minIdleMs window introduced by the main
fix. A merger-handoff that races a warming-down session could clear a
registry entry < 5s old. Route through `reconcileSelfOwnedActiveSessionForRemoval`
with the `executingTaskLock` process probe so all reconcile sites enforce
the same liveness contract. Test updated to backdate `registeredAt`,
matching the pattern used for the other reliability-interactions tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three independent reliability fixes that all surfaced as the same bug:
live tasks losing their worktrees mid-execution and emitting
`wrong_toplevel` errors.
Fix A — executor stale-self-owned classifier:
`reconcileSelfOwnedActiveSessionForRemoval` now takes a process-active
probe (`executingTaskLock.has`) and a minimum-idle window (default 5s)
in addition to the existing in-memory `activeWorktrees` binding probe.
Recently-registered or still-running entries are refused with
`process-active-refuses` / `too-recent-refuses`, with audit-grade
log lines. Both the pre-remove path
(`reconcileSelfOwnedBeforeRemove`), the post-throw retry in
`removeOwnWorktreeWithReconcile`, and the defensive reconcile in
`removeWorktree` route through the same hardened gates.
Fix B — pause synchronously reaps the agent session:
New `awaitAbortInFlightTaskWork` mirrors the existing fire-and-forget
abort but awaits each `session.abort()` /
`stepExecutor.terminateAllSessions()` /
`workflowSession.abort()`. `parkTaskAfterWorkflowStepPause` calls it
before `moveTask("todo")`, and the `task:updated` user-pause handler
routes through it, so a fast re-dispatch can no longer race a still-
live shell.
Fix C — self-healing realpath + active-task skip:
`reconcileTaskWorktreeMetadata` now realpath-normalizes both sides of
the registry comparison (handling macOS `/private/var/...`) and
refuses to clear `worktree`/`branch` on in-progress or in-review
tasks. The skip emits a new
`task:auto-recover-worktree-metadata-skipped-active` audit event;
executor-level recovery paths remain in charge of active tasks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a fallback retry counter to the reviewer that resets on successful step completion, preventing premature escalation when earlier steps exhaust retries while later ones succeed; also aligns dashboard trace buffer types and adds comprehensive coverage for the reset semantics.
Fusion-Task-Id: FN-5435
Fixed self-healing to suppress unnecessary blocked-by refreshes when there are no changes (no-op), preventing spurious requeues. Added a regression test covering this scenario in the self-healing test suite.
Fusion-Task-Id: FN-5433
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