Commit Graph

4593 Commits

Author SHA1 Message Date
Fusion
fca8d27342 feat(FN-3619): preserve agent memory across import/export flows
- Extend agent company manifest contract to include memory payloads during export and parse
- Align dashboard agent import/export route generation to pass memory through unchanged
- Add parser, exporter, and route-level tests covering memory passthrough behavior
- Document memory import/export parity in agent and CLI documentation
Ref: Runfusion/Fusion#53

Fusion-Task-Id: FN-3619
2026-05-06 21:36:31 -07:00
Fusion
46f3ac2114 feat(FN-3618): surface provider icons in settings and dropdowns
Completes Step 3 of FN-3618 by surfacing AI provider icons throughout the Settings modal and model dropdowns, updating both the component styles and adding integration and unit tests to cover the new icon display behavior.

Fusion-Task-Id: FN-3618
2026-05-06 21:36:31 -07:00
gsxdsm
81e47e50eb fix(dashboard): re-snapshot keyboard metrics on focusin and page restore
Switching away from the chat view and back left the hook with stale
metrics — keyboardOpen was false at remount even though the system
keyboard was still visible, so the .chat-thread transform never
re-applied and the message list anchored too high. focusin and
synchronous reads also captured offsetTop mid-transition.

Adds a tail of delayed re-reads (50ms, 200ms, 500ms) on focusin,
visibilitychange, and pageshow so iOS has time to settle before the
final snapshot is taken.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 21:16:33 -07:00
Fusion
c071a3aab5 feat(FN-3423): show task branch metadata on cards
- Render Branch/Base chips in TaskCard when branch metadata is present
- Add responsive TaskCard styles for branch metadata chips using design tokens
- Expand TaskCard tests to cover branch/base rendering and memo comparator branch changes
- Remove unused ChatView focus-preservation refs/callback to resolve lint blockers
- Document branch metadata semantics in task-management docs

Fusion-Task-Id: FN-3423
2026-05-06 21:16:33 -07:00
Fusion
0f69b2e78f feat(FN-3449): implement distributed task-id allocator with mesh API endpoi
Implements a distributed task-ID allocator with mesh networking endpoints for multi-project coordination (FN-3449), alongside substantial ChatView and GitManager mobile polish including improved iOS keyboard handling, rubber-band containment, scroll-drift fixes, and visual viewport stabilization. In

Fusion-Task-Id: FN-3449
2026-05-06 21:16:33 -07:00
gsxdsm
592c61ff12 fix(dashboard): lock ChatView composer with touch-action: none on textarea
A pan-y gesture on the focused textarea still triggered iOS auto-
scroll-into-view, lifting the composer up off-screen even with body
locked. touch-action: none on .chat-input-textarea blocks gesture-
driven panning entirely (tap-to-focus, typing, caret moves still
work) so the composer stays anchored. Trade-off: loses gesture-
scroll within the textarea once content exceeds max-height — minor
since textareas rarely exceed 6 lines in this composer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 21:02:22 -07:00
gsxdsm
21b01f8f56 fix(dashboard): pin --vv-offset-top to resize/focus, ignore pan scrolls
iOS fires visualViewport scroll events at 60fps during a pan with the
keyboard up. Routing those through React state and into the .chat-thread
translateY(--vv-offset-top) transform amplified the pan into a visible
judder + ~300px shift + body background exposure.

useMobileKeyboard now uses two listeners: a full update (resize +
focusin/focusout) that re-snapshots all metrics including offsetTop, and
a scroll-only update that updates only height/keyboardOpen. offsetTop
is therefore frozen between keyboard open/close events — the transform
correctly compensates for iOS's initial visualViewport shift on focus
without following pan-time movement.

Restores the translateY anchor (so the thread isn't off-screen on
first focus) while keeping the swipe-jitter fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:58:04 -07:00
gsxdsm
7e33614375 fix(dashboard): drop translateY(--vv-offset-top) on ChatView mobile
The transform amplified jitter during iOS textarea swipes: visualViewport
scroll events updated --vv-offset-top rapidly, the transform followed,
and the thread juddered then shifted ~300px exposing the body background.
Removing the transform leaves the thread where iOS places it; the
height-shrink to var(--vv-height) still constrains it to the visible
area. Trade-off: on initial focus the thread anchor relies on iOS's
own viewport adjustment instead of explicit compensation, but that
beats the swipe-time jitter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:54:33 -07:00
Fusion
4fe2a8af65 feat(FN-3615): fix Codex weekly pace parsing
Fixed Codex weekly pace parsing in the usage tracking module, with corresponding test coverage added to verify the fix.

Fusion-Task-Id: FN-3615
2026-05-06 20:54:33 -07:00
gsxdsm
956a472898 fix(dashboard): contain iOS rubber-band on ChatView messages and composer
Three scoped overscroll fixes for the ChatView mobile keyboard-up case:

- .chat-messages: overscroll-behavior: contain so edge-swipes on the
  messages list don't bounce the parent / document.
- .chat-input-area: overscroll-behavior: contain so swipes on the
  composer footer don't escape upward.
- .chat-input-textarea: touch-action: pan-y + overscroll-behavior:
  contain so a vertical swipe started on the textarea stays inside
  the textarea (multi-line scroll still works) instead of
  rubber-banding the page and exposing the body background.

User-reported symptom: keyboard up + swipe up on the textarea edge,
the composer shakes and a gray box (body background) partially
covers it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:49:42 -07:00
Fusion
17998936ca feat(FN-3614): improve mobile keyboard handling in ChatView and GitManager
This merge delivers five major themes: a large mobile chat UX pass (viewport-aware GitManager CSS, compact tool-call layout, keyboard-safe modals, and iterative fixes for the send-button double-fire behavior), a complete refactor of the TaskDetailModal test suite from a 6745-line monolith into eight

Fusion-Task-Id: FN-3614
2026-05-06 20:48:50 -07:00
gsxdsm
d83fd28065 fix(dashboard): reset scroll on ChatView refocus to undo iOS drift
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>
2026-05-06 20:42:14 -07:00
gsxdsm
92d40bc519 fix(dashboard): keep keyboard up on send tap; hide status bar with keyboard
Two mobile chat regressions addressed together:

1) ChatView send button: preventDefault now fires on pointerdown for
   touch pointers, before iOS blurs the textarea. The previous
   onMouseDown.preventDefault was too late on iOS (mousedown is
   synthesized after touchend, by which point the keyboard has
   already started dismissing). Click still runs the action so quick
   taps remain reliable.

2) ExecutorStatusBar: hidden on mobile while keyboard is open,
   mirroring MobileNavBar. The bar is position:fixed against the
   layout viewport, which iOS leaves anchored below the keyboard;
   during a swipe/pan it would slide over the messages list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:34:35 -07:00
gsxdsm
ddf9f03ec8 revert(dashboard): undo imperative visualViewport write in ChatView
The imperative useLayoutEffect approach made mobile worse — first tap
flickered and didn't bring up the keyboard, while the original
swipe-overlap symptom remained. Restoring the previous React-state
flow until a better fix is identified. Removes the changeset that
shipped with the failed attempt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:29:12 -07:00
gsxdsm
6e38dad1c3 fix(dashboard): write ChatView visualViewport vars imperatively
The mobile composer/footer slid over the message list when the user
swiped with the keyboard up. Cause: --vv-height / --vv-offset-top were
routed through React state via useMobileKeyboard, so on iOS — which
fires visualViewport scroll/resize on the same frame as its keyboard
animation — the .chat-thread translation lagged by one paint, visible
as the composer momentarily floating over messages.

Now those two vars are written imperatively in a useLayoutEffect
directly to the .chat-thread DOM node on every visualViewport event,
mirroring the working pattern at QuickChatFAB.tsx:1032-1052 (which
already works correctly on mobile). Only --keyboard-overlap (a
structural open/close signal, not per-frame) still flows through
React state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:25:38 -07:00
gsxdsm
da36f8feb4 fix(dashboard): keep mobile keyboard up when ChatView send button tapped
Re-add preventDefault on mousedown so the textarea doesn't blur when
the user taps send — keyboard stays up, no viewport reflow jumping
the input to the top of the screen. The action still runs on click
(which fires reliably from the iOS touch sequence even for quick
taps), so this preserves the previous fix's quick-tap reliability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:19:28 -07:00
gsxdsm
74378dcfc7 fix(dashboard): make ChatView mobile send fire on quick tap
The mobile send button used pointerdown + touchstart with preventDefault
and a focus-preservation dance to keep the keyboard up while sending.
That path silently failed on quick taps on iOS — only a long press
registered. Switching to plain onClick (with touch-action: manipulation
to skip the click delay) fires reliably on tap. The soft keyboard may
dismiss on send now, which is a minor regression vs. the previous
intent but vastly preferable to silent failure.

QuickChat is unchanged because it already works on mobile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:15:30 -07:00
gsxdsm
073c5047ea Revert "fix(dashboard): stop mobile send-button double-fire that aborted chats"
This reverts commit 35ea499e08.
2026-05-06 20:02:02 -07:00
gsxdsm
0c1bca9915 Revert "fix(dashboard): self-clear mobile send/stop dedupe ref so subsequent taps work"
This reverts commit 157865a583.
2026-05-06 20:02:02 -07:00
gsxdsm
157865a583 fix(dashboard): self-clear mobile send/stop dedupe ref so subsequent taps work
The previous fix introduced a regression: handledMobileSendRef /
handledMobileActionRef was set in onPointerDown/onTouchStart but only
cleared in onClick. preventDefault() on pointer/touch events suppresses
the synthesized click on iOS Safari, so the ref stayed true forever
after the first tap — every subsequent tap (quick OR long press) hit
the new dedupe guard and silently bailed.

Now both handlers schedule a 500ms setTimeout to self-clear the ref
alongside their action. That covers the full pointerdown/touchstart/
click burst from one tap while still letting the next user tap go
through.

Applied to: ChatView send button, QuickChat send button, QuickChat
stop button.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 19:59:38 -07:00
gsxdsm
35ea499e08 fix(dashboard): stop mobile send-button double-fire that aborted chats
The ChatView and QuickChat send/stop buttons each had both an
onPointerDown and an onTouchStart handler invoking the action. On a
quick mobile tap both fire, so handleSend / handleSendMessage /
stopStreaming ran twice in rapid succession. The second invocation
closed the first's SSE stream (streamRef.current.close()), the server
treated that as a cancel via beginGeneration, and the chat ended with
no output — exactly matching the reported "tap silently fails, long
press works" symptom (long press happened to suppress one of the two
events).

Both handlers now early-return when the existing handledMobile*Ref
flag is already set, so only the first event for a given tap fires the
action. The send button additionally gets touch-action: manipulation
(removes the click delay that lets the textarea blur win the race) and
an expanded invisible hit area via ::before so slightly-off taps don't
land on the surrounding textarea and dismiss the keyboard without
sending.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 19:55:55 -07:00
Fusion
a296b4d3bd feat(FN-3574): add setup-aware built-in plugin rows
- Add built-in plugin catalog metadata and constants for shipped installable plugins
- Render a Built-in Plugins section with install, setup-required, and manage states
- Fetch and display plugin setup status, including setup install flow and status badges
- Add PluginManager CSS and tests covering built-in plugin install/setup behaviors

Fusion-Task-Id: FN-3574
2026-05-06 19:55:55 -07:00
Fusion
547f024717 feat(FN-3392): implement follow-up suggestion contract and policy system
Merges the evaluator follow-up suggestion system (FN-3392, Steps 1–5), which adds a normalized contract, provenance tracking, and lifecycle documentation for AI-generated follow-up tasks, alongside chat UI improvements including unread indicators in header and mobile nav, corrected message routing,

Fusion-Task-Id: FN-3392
2026-05-06 19:55:55 -07:00
Fusion
d791fa90ab feat(FN-3608): update dashboard chat documentation
Updated the dashboard chat documentation in the user guide with a minor addition.

Fusion-Task-Id: FN-3608
2026-05-06 19:55:55 -07:00
Fusion
5dcc888948 docs(FN-3608): update dashboard chat guide with mailbox tooling note
- Document that agent-backed chat sessions expose fn_send_message and fn_read_messages when MessageStore is available
- Clarify that model-only chat sessions continue to work without mailbox tools
- Complete the Step 4 dashboard chat documentation update

Fusion-Task-Id: FN-3608
2026-05-06 19:55:55 -07:00
Fusion
75341f57d8 feat(FN-3622): add canonical task-detail timing calculations and stats pane
The merge lands three commits for FN-3622's canonical task timing calculations, adding `taskTiming.ts` logic and stats timing semantics to `TaskDetailModal` and `TaskTokenStatsPanel`, backed by regression tests across those panels and the root `test-changed.mjs` script. The remaining commits introdu

Fusion-Task-Id: FN-3622
2026-05-06 19:55:55 -07:00
Fusion
7fd40c990f fix(FN-3610): isolate test home for changed-package test runs
- Create a disposable HOME/USERPROFILE env for scripts/test-changed.mjs execution
- Run isolation guard checks with the same isolated env, including cache-hit no-op paths
- Clean up temp HOME after test execution to avoid residue
- Update test coverage and contributing docs for the shared isolation behavior

Fusion-Task-Id: FN-3610
2026-05-06 18:57:37 -07:00
Fusion
c45b8619d2 feat(FN-3606): correct chat-bound message routing and stabilize merger auto
Merger receives substantial hardening: autostash race-rescue with de-duplication, advisory observer for destructive operations, and subject-line preference for step headlines. The TUI gains a narrow log-split mode on System panel with proper back-navigation to the main pane. Chat header and mobile n

Fusion-Task-Id: FN-3606
2026-05-06 18:55:10 -07:00
Fusion
6e0490544a feat(FN-3605): keep mobile header identity and toggle inline in ChatView
The merge completes Step 2 of FN-3605 by refactoring the ChatView mobile header to preserve its visual identity while converting the toggle control to an inline layout, accompanied by corresponding tests.

Fusion-Task-Id: FN-3605
2026-05-06 18:50:59 -07:00
Fusion
d370f305e9 feat(FN-3604): add chat unread indicator to header and mobile nav
Implements a chat unread indicator across the header and mobile nav bar, driven by a new unread-response tracker in the app state, with tests and a docs update for the feature.

Fusion-Task-Id: FN-3604
2026-05-06 18:47:25 -07:00
Fusion
c5ea44a41d feat(FN-3600): harden TaskDetailModal pause/unpause async assertions
Hardens async assertions in the task detail modal's pause/unpause action tests, improving test reliability for that interaction flow.

Fusion-Task-Id: FN-3600
2026-05-06 18:44:25 -07:00
Fusion
b507e78402 feat(FN-3599): align documentation with delivery process
Documentation delivery alignment completing Step 5 of FN-3369, updating the CLI reference, research docs, and research hardening preflight guide with consistent documentation delivery guidance across all three files.

Fusion-Task-Id: FN-3599
2026-05-06 18:40:52 -07:00
Fusion
705e5cc1d3 feat(FN-3596): unify board/list task ordering, split TaskDetailModal test m
The merge introduces a major TaskDetailModal test refactor (splitting a 6.7K-line monolith into five focused suites), significant merger improvements including autostash race-rescue, deduplication, and advisory logging for destructive operations, a new TUI narrow-mode log-split feature for the dashb

Fusion-Task-Id: FN-3596
2026-05-06 18:37:23 -07:00
gsxdsm
921c588fdd fix(tui): ← returns to main pane from focused log split
Previously ← in the narrow log strip cycled the section (matching n/p),
which was disorienting once the user had drilled into the strip — they
expected ← to back out, not flip them to a different panel. Now ← from
a focused log strip clears the narrow-split sub-focus and returns to
the main pane (System / Stats / Utilities / Settings) where the user
can drag-select tokens or interact with the panel as usual. p/P still
cycle sections in all states; ↑ at the top of the strip and Esc
continue to work as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:31:19 -07:00
gsxdsm
20d1f8076b fix(tui): re-enable narrow log-split on System without losing UI
Bring back the bottom log strip on the System panel and make sure
nothing that lives in System is dropped when the strip steals rows:

- Render the [Enter] / [c] / drag-to-select hint unconditionally so
  shortcuts stay discoverable when the strip has sub-focus and System
  isn't the keyboard target. The split-aware focus border still tracks
  which pane the keyboard is wired to.
- Move URL and Token to their own full-width rows under the status-chip
  wrap row. Long token values now wrap onto multiple lines instead of
  being truncated or pushed off-panel — the auth token is always
  visible (and selectable) in full.
- Keep mouse reporting OFF whenever System is the active section, even
  when the log strip below has sub-focus, so click-drag selection of
  the token text continues to work.
- Update estimateSystemContentRows to mirror the new layout: greedy
  pack of small status chips, full-width URL / Token rows that wrap by
  ceil(width / inner), and an always-counted hint row. The dynamic
  split sizer now reserves enough rows for the panel in every state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:27:18 -07:00
gsxdsm
9a281eaa5f fix(tui): skip narrow log-split on System panel
System has interactive UI — Enter to open URL, [c] to copy auth token,
and click-drag for token selection — whose [Enter]/[c] hint row only
renders when the panel has focus. Auto-shifting focus into a bottom log
strip on ↓ hid that hint and removed a clear visual path back to the
panel for token operations. Restrict the auto-split to inert sections
(Stats / Utilities / Settings); System keeps the full single-pane view
it had before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:16:58 -07:00
gsxdsm
6e8689ae3d feat(tui): split narrow main view to surface live logs
When the dashboard TUI collapses to single-pane mode (narrow width or
short terminal), show a horizontal log strip at the bottom of the screen
while the active section renders on top. The split is content-driven:
the top pane gets exactly the rows it needs to render its section
without truncating (computed from SystemPanel's chip wrap at the current
width, or each panel's known row count for Stats/Utilities/Settings),
and the log strip absorbs every remaining row to maximize log
visibility. Down-arrow shifts sub-focus into the log strip with the
same key bindings as the dedicated Logs section (j/k, Home/G, Enter to
expand, w to wrap, c to copy, f to filter, mouse wheel). Up-arrow at
the top of the strip or Esc returns focus to the main pane.
Right/Left/Tab continue to cycle sections, so the dedicated full-screen
Logs view is unchanged. The split auto-disables if the log strip would
get fewer than 6 rows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:11:49 -07:00
gsxdsm
e6dc3c7ccc fix(merger): address code-review findings on autostash + observer
P0 — parsePorcelainZ rename/copy handling
  Git's -z porcelain emits `R  <new>\0<old>\0` for renames (and
  C for copies). The naive split-and-slice treated <old> as an
  independent dirty path, which made runObservedDestructiveSyncOp
  warn about phantom "cleared paths" whenever a rename was in
  flight. Now we detect R/C status and skip the trailing entry.

P1 — race-rescue loop unstages between attempts
  `git stash create` snapshots the index without clearing it, so
  iteration 2's `git add -A` would re-stage atop iteration 1's
  leftovers. Tree differences inside the loop then reflected stale
  staging rather than genuine new writes. Added a `git reset` at
  the top of each iteration so every attempt starts from a clean
  index baseline.

P1 — writeActiveMergerStatus is now atomic
  Switched from in-place writeFileSync to temp-file + renameSync.
  POSIX guarantees rename atomicity on the same filesystem, so a
  reader can no longer catch the file mid-flush and return a
  false-negative "no merger active" advisory.

P2 — Step regex em-dash clarity
  `[—\-:]` is functionally fine but obscures intent; switched to
  `(?:—|-|:)` so the em-dash branch is obvious. Added a test case
  for the em-dash separator.

New tests:
- parse-porcelain-z.test.ts (8 cases including renames + copies)
- em-dash case added to derive-subject-summary.test.ts

247/247 merger-suite tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:04:19 -07:00
gsxdsm
fd7c88c2d5 fix(merger): de-dupe race-rescue against primary stash path set
The race-rescue loop was firing on every merger run because
`git add -A && git stash create` does not clean the working tree —
files stay dirty post-stash, so a subsequent `snapshotDirtyFiles` saw
the SAME paths the primary stash had just captured and stashed them
again, producing identical-tree race-rescue duplicates (visible in
git stash list as `fusion-merger-autostash:FN-XXXX:race-rescue-0`
sitting next to its identical `fusion-merger-autostash:FN-XXXX:`).

Fix: list the path set captured by the primary stash via
`git stash show --name-only`, and only rescue paths in the current
dirty snapshot that are NOT in that set — those are genuine
late-dirty writes from concurrent dev edits or interleaved ops.
Also drop any rescue whose tree-SHA exactly equals the primary,
as a defensive belt-and-braces.

Existing duplicate race-rescue stashes are harmless (identical
content to their primaries) and can be dropped manually.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:57:42 -07:00
Fusion
fe55e7c462 docs(FN-3421): document branch field plumbing architecture
- Document how branch field data flows through task lifecycle
- Clarify architecture-level plumbing responsibilities for branch metadata
- Capture Step 4 documentation updates in docs/architecture.md

Fusion-Task-Id: FN-3421
2026-05-06 17:54:23 -07:00
Fusion
17f7c0e40d feat(FN-3594): split TaskDetailModal test monolith and improve mobile chat/
The merge brings TaskDetailModal test coverage in line with the project's testing standards by splitting the monolithic 6,745-line test file into five focused suites. It also delivers merger reliability improvements including headline-step subject preference, redundant-merge verification skipping, a

Fusion-Task-Id: FN-3594
2026-05-06 17:51:09 -07:00
gsxdsm
2dd87b7c8b fix(merger): add active-merger advisory + observe destructive ops + log rescue stashes
- writeActiveMergerStatus: writes .git/.fusion-merger-active.json
  (taskId, pid, hostname, startedAt) at merge entry, deleted in finally.
  Not a lock — purely informational so dashboards / status lines /
  pre-Edit hooks can warn devs that rootDir is volatile during the run.
  readActiveMergerStatus(rootDir) is exported for consumers.
- runObservedDestructiveSyncOp: snapshot-before/after wrapper around
  destructive rootDir ops that are *supposed* to preserve unrelated
  working-tree edits. resetMergeWithWarn now uses it — any future
  silent wipe of dirty paths surfaces as an actionable warning instead
  of going unnoticed. Not applied to the autostash's own reset
  --hard / clean -fd; those are intentionally destructive and already
  protected by the race-rescue stash.
- Race-rescue stashes from stashUnrelatedRootDirChanges are now
  attached to the AutostashHandle and surfaced via store.logEntry so
  the recovery command lands on the task feed instead of only
  mergerLog.warn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:25:19 -07:00
gsxdsm
923411a940 fix(merger): prefer step headline subject + add autostash race-rescue
- deriveDeterministicSubjectSummary now picks the lowest-numbered
  `complete Step N` headline (or the oldest commit) instead of the most
  recent commit, so trailing quality-gate revisions stop hijacking the
  squash-merge subject (FN-3617 landed as "align mailbox modal css..."
  when 4 of 5 commits were the actual Claude OAuth fix).
- AI subject + body system prompts in ai-summarize.ts now weight by
  commit theme rather than file size, so a small token cleanup that
  touches a large CSS file no longer dominates the summary.
- stashUnrelatedRootDirChanges adds a bounded re-snapshot loop after
  the primary stash is persisted but before \`git reset --hard\`. Any
  late-dirty paths (concurrent dev edits during a long merger run,
  parallel merger runs racing on rootDir, late test/build artifacts)
  get captured in labeled \`race-rescue-N\` stashes recoverable from
  \`git stash list\`, instead of being wiped by the destructive reset.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:06:46 -07:00
Fusion
e2949ca2b6 feat(FN-3592): exclude live fusion app paths from test isolation checks
Merges FN-3592 test isolation improvements: broadens the runtime ignore list in `check-test-isolation.mjs` to filter live Fusion app paths, fixes a lint violation in the script, and updates the agents lifecycle documentation. A patch changeset is included for the `@runfusion/fusion` package.

Fusion-Task-Id: FN-3592
2026-05-06 16:25:14 -07:00
Fusion
cabd6be84b feat(FN-3617): align mailbox modal css with design tokens
Updated MailboxModal CSS to use design tokens instead of hardcoded values, and adjusted the co-located test to match.

Fusion-Task-Id: FN-3617
2026-05-06 16:14:29 -07:00
Fusion
2140148fe2 feat(FN-3609): split TaskDetailModal tests into focused suites
This merge splits the monolithic TaskDetailModal test file into six focused test suites (rendering, attachments/tabs, definition/actions, inline-editing/integrations, models/progress/workflow, responsive/dependencies), adds a changeset for the test isolation baseline, fixes chat SSE optimistic echo

Fusion-Task-Id: FN-3609
2026-05-06 16:05:44 -07:00
Fusion
2fce7b36cf feat(FN-3591): split TaskDetailModal test monolith into focused suites
The monolithic `TaskDetailModal` test suite (6,745 lines) was split into six focused test files covering attachments/tabs, definition/actions, inline editing/integrations, models/progress/workflow, rendering, and responsive/dependencies, with a shared test helpers module added for common utilities.

Fusion-Task-Id: FN-3591
2026-05-06 15:57:08 -07:00
Fusion
51f438376a test(FN-3591): split TaskDetailModal coverage into focused test suites
- Replace the monolithic TaskDetailModal test file with focused suites by behavior area
- Add shared TaskDetailModal test helpers to reduce duplication across suites
- Keep existing coverage while improving test isolation and maintainability
- Remove the legacy combined TaskDetailModal.test.tsx file

Fusion-Task-Id: FN-3591
2026-05-06 15:57:08 -07:00
Fusion
725d7fabb9 docs(FN-3589): document fn agent subcommand behavior
- Add dedicated CLI reference sections for fn agent stop/start/mailbox/export with usage, options, and behavior notes
- Document expected no-op and invalid-transition outputs for agent lifecycle commands
- Expand useful options matrix with agent import/export flags
- Add a doc contract test that asserts the new agent subcommand sections remain present

Fusion-Task-Id: FN-3589
2026-05-06 15:21:45 -07:00
Fusion
35ddb05f50 feat(FN-3585): document post-install plugin capabilities and fix mailbox sp
The merge adds a test isolation script (`scripts/check-test-isolation.mjs`) to filter runtime noise from live Fusion app paths, fixes MailboxModal spacing by replacing hardcoded values with design tokens (FN-3585), and documents post-install plugin capabilities in the plugin management guide (FN-358

Fusion-Task-Id: FN-3585
2026-05-06 15:17:07 -07:00