Commit Graph

116 Commits

Author SHA1 Message Date
gsxdsm
e172b13612 fix(dashboard): never show raw landing/reviewing on task status badges
Share one badge label mapper for board and list so AI-merge pipeline
statuses always display as Merging… instead of engine strings.
2026-07-15 10:39:57 -07:00
gsxdsm
bc2d22df6e feat(dashboard): offer AI translation in Import Tasks preview (#2128)
## Summary

Import Tasks can now offer on-demand AI translation when a selected
GitHub or GitLab issue/PR title and body appear to be in a different
language than the active dashboard locale.

- Detect foreign-language content with a conservative client heuristic
(Unicode scripts + Latin stopwords)
- Show an opt-in banner: **Translate**, then **Show original / Show
translation**, plus **Dismiss**
- Call new `POST /api/ai/translate-text` (shared AI-helper rate limit
with refine/draft)
- Translation is **display-only** in the preview; imported task text
stays the original source language

## Why

Operators working in a non-English dashboard (or reading
non-dashboard-language issues) needed a way to understand import
candidates without leaving the preview or changing what gets imported.

## Test plan

- [x] Unit tests for language detection (`detectContentLanguage`)
- [x] Unit tests for translate request validation, response parsing, and
AI agent path
- [x] GitHub import modal: French content shows translate controls;
English content does not
- [x] Dashboard typecheck clean for app + server packages
- [ ] Manual: open Import Tasks with dashboard language English, select
a French/Korean issue, translate and toggle original
- [ ] Manual: confirm Import still creates the task with original
title/body
- [ ] Manual: dismiss banner for a selection and confirm it stays
dismissed for that item

## Notes

- Comments are not translated (title + body only)
- zh-CN / zh-TW share a CJK family so Chinese content does not prompt
translation when the UI is either Chinese locale
- Secondary locale catalogs have empty placeholders for the new
`git.translate*` keys (runtime falls back to English)
2026-07-15 02:18:43 -07:00
gsxdsm
cdf67c1d98 fix(dashboard): stop Planning Mode retry loop, make AI sessions multi-tab (#2101)
## Problem

Reported: planning gets stuck in a cycle of retrying and regenerating
after a response was already supplied.

After the user answers a planning question, `submitResponse` pushed the
answer to history but left `session.currentQuestion` pointing at the
just-answered question for the whole next generation. The planning SSE
route's catch-up path re-emits `currentQuestion` to every fresh
connection — and each FN-7946 auto-retry (#2073) opens a fresh
connection. So after any generation error:

1. Auto-retry connects a fresh stream → the server re-emits the
**already-answered** question.
2. The client treats any question event as progress: it **resets the
3-attempt auto-retry budget** and re-shows the answered question.
3. The retry regenerates; if it errors again the cycle repeats with a
fresh budget — an unbounded retry/regenerate loop. Re-answering the
stale question also 409-collided with the in-flight generation, feeding
the same loop.

## Fix

Invariant: `currentQuestion` is only set while the session is genuinely
awaiting user input.

- `submitResponse` clears it the moment an answer is accepted (normal
turns and the deepening checkpoint), while preserving the legacy 200
respond contract on generation failure (the modal ignores the body and
lets the SSE error drive recovery).
- `retrySession` scrubs stale questions persisted by pre-fix builds
before regenerating.
- `buildSessionFromRow` only restores a question when the persisted row
is `awaiting_input`.
- `didSubmitSameAnswer` now compares against the last history entry so
the duplicate-submit 409 message survives.
- Agent onboarding gets the same fix (its SSE route also re-emits
`currentQuestion` on connect); retry now asks the next question instead
of re-asking the answered one.

Surface enumeration: mission and milestone interviews keep questions the
same way but their SSE routes never re-emit on connect, and the
auto-retry budget machinery is Planning-Mode-only — planning +
onboarding were the two affected surfaces.

## Symptom Verification

- **Original symptom:** after answering a question, Planning Mode loops
between "Retrying…" and regenerating, re-showing the already-answered
question, with the auto-retry budget never exhausting.
- **Exact reproduction:** answer a question, have the next generation
fail (stuck watchdog/provider error), let the client auto-retry open a
fresh SSE connection.
- **Assertion it is gone:** new regression suite
`planning-answered-question-reemit.test.ts` asserts `currentQuestion` is
cleared mid-generation, on generation failure, on retry, and on restore
from non-`awaiting_input` rows — so the SSE catch-up path has nothing
stale to re-emit. All 5 tests fail against pre-fix code and pass with
the fix; an onboarding regression test covers the sibling surface.

## Verification

- New regression tests: 5/5 fail on pre-fix code, pass with the fix
(plus 1 onboarding test).
- Existing suites: 137 planning server tests pass (3 failures in
`routes-planning.test.ts` fail identically without this change —
pre-existing on the branch); all 69 `PlanningModeModal.planning-flow`
client tests pass; `tsc --noEmit` clean; `pnpm check:changesets` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Made Planning Mode (and related planning controls) lock-free and
multi-tab—no more take-over/active-in-another-tab lock overlays.

* **Bug Fixes**
* Fixed Planning Mode retry/generation flows where already-answered
questions could reappear.
* Ensured answered questions clear immediately and aren’t re-emitted
during session recovery/SSE catch-up.
* Improved session restoration and preserved legacy recovery behavior
when generation fails after an answer.

* **Tests**
* Added regression coverage for the answered-question invariant and
updated existing tests to reflect lock-free behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---

## Follow-up: Planning Mode is now multi-tab via DB state (lock-free)

Second commit removes all cross-tab coordination from planning — the
persisted session row is the single source of truth and multiple tabs
can read and interact with the same session:

- **Server:** `/planning/*` routes no longer run `checkSessionLock` or
parse `tabId`; a stale `tabId` from an older client is ignored instead
of 409'd. Subtask/mission interview routes keep their existing lock
behavior.
- **Client:** `PlanningModeModal` drops `useSessionLock`, the
`useAiSessionSync` BroadcastChannel broadcasts,
`sessionTabId`/`lockSessionId` state, and the "Take Control" overlay.
Tabs stay current via the per-session SSE stream plus the global
`ai_session:updated` events `useBackgroundSessions` already consumes;
concurrent writes resolve via the server's generation-in-progress guard
(409).
- **API client:** planning functions lose their `tabId` params.
- **Fix uncovered by the refactor:** the 8s stuck-poll now resolves the
session id inside each tick — the removed lock state was what previously
re-armed the poll after Start Planning resolved the session id.
- Also fixes a pre-existing PG-cutover break in
`planning-generation-cancellation.test.ts` (`getSession` is async).

Verification: 144 client planning tests and 137 server planning tests
pass (the 3 remaining `routes-planning.test.ts` failures are
pre-existing on the branch and fail identically without these changes);
`tsc --noEmit` and eslint clean on changed files; `pnpm
check:changesets` passes. Lock-conflict route tests were rewritten to
assert lock-free semantics, plus a new modal test proving a session
stays fully interactive with no lock acquisition even when another tab
is active.


---

## Follow-up 2: the per-tab session lock is gone entirely

Third commit extends the multi-tab model from planning to **every** AI
interview surface (planning, subtask breakdown, mission interview,
milestone/slice interview) and deletes the lock machinery root and
branch.

**Server**
- Deleted the `/ai-sessions/:id/lock`, `/lock/force`, and `/lock/beacon`
routes.
- Dropped `checkSessionLock` from every
planning/subtask/mission/milestone route (both copies — `routes.ts` and
`mission-routes.ts`). A `tabId` from an older client is ignored, never
409'd; all `tabId` body parsing is gone.
- Dropped `acquireLock` / `releaseLock` / `forceAcquireLock` /
`getLockHolder` / `releaseStaleLocks` from `AiSessionStore`, plus the
`@fusion/core` async helpers (`acquireAiSessionLock` et al) and core's
re-exports.
- Removed `lockedByTab`/`lockedAt` from
`AiSessionRow`/`AiSessionSummary`, the upsert SQL, and all four session
producers.

**Client**
- Deleted `useSessionLock` and the now-orphaned `getSessionTabId` util.
- Removed the Take Control overlay, the "active in another tab" banners,
and `BackgroundTasksIndicator`'s active-elsewhere gate (the confirm
prompt and lock badge — sessions now just open).
- Reduced `useAiSessionSync` to what its own comments already called it
— a low-latency *status* supplement to SSE: no `activeTabMap`,
`broadcastLock/Unlock/Heartbeat`, `owningTabId`, `tab:*` messages, or
stale-heartbeat sweep.
- Dropped `tabId` from every session API client function; removed the
lock CSS.

**Deliberately kept: the two DB columns.** `ai_sessions.locked_by_tab` /
`locked_at` remain as dead, always-NULL columns with a deprecation note.
Dropping them is an irreversible migration, and released binaries still
name those columns explicitly in their upsert — an older install pointed
at the same database would fail every session write. They can be dropped
once no such binary can reach it. No code reads or writes them.

**Verification**: 397 client tests and 137 server planning tests pass
(the same 3 `routes-planning.test.ts` failures are pre-existing —
verified identical on a clean stash); `tsc --noEmit` clean for
`@fusion/core` and `@fusion/dashboard`; eslint clean on all changed
files; the 30 PG `schema-applier` tests pass (they exercise the retained
columns); `pnpm check:changesets` passes. The lock-conflict route tests
and both modal lock tests were rewritten to assert the inverse: routes
and modals stay fully interactive while another tab "holds" a lock, and
the lock API is never called.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 18:47:53 -07:00
gsxdsm
b77e12351e FN-7872: add custom terminal shortcut buttons to the Preferences panel
Lets users define, edit, and remove custom terminal shortcut buttons (label + injected key sequence) from the terminal Preferences panel, persisted client-side.

- Add a customShortcuts list to terminalPreferences (kb-terminal-preferences localStorage) with add/edit/remove management
- Add decodeTerminalShortcutSequence to decode \n, \t, \r, \e/\x1b, and \\ escapes for injected sequences
- Render custom shortcut buttons in TerminalModal's shortcut panel, injecting via the focus-preserving sendLiteralShortcut path
- Add management UI (add/edit/remove) for custom shortcuts in the terminal Preferences panel, styled in TerminalModal.css
- Extend TerminalModal and terminalPreferences test coverage for the new custom shortcut behavior
- Document custom terminal shortcuts in docs/dashboard-guide.md
- Add a minor changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7872-terminal-custom-shortcuts.md    |   7 +
 docs/dashboard-guide.md                            |   7 +-
 .../dashboard/app/components/TerminalModal.css     | 106 +++++++++++
 .../dashboard/app/components/TerminalModal.tsx     | 202 ++++++++++++++++++++-
 .../components/__tests__/TerminalModal.test.tsx    | 183 +++++++++++++++++++
 .../utils/__tests__/terminalPreferences.test.ts    |  68 +++++++
 .../dashboard/app/utils/terminalPreferences.ts     | 140 +++++++++++++-
 7 files changed, 708 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7872

Fusion-Task-Lineage: 9b2df0da-0eb7-4cec-a42b-767e23ff4c2c

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 13:06:08 -07:00
gsxdsm
c7c6c5a8c4 FN-7842: color-code priority icons by urgency across quick add, task form, and task cards
Adds a shared urgency color source to priorityIndicator and wires it into every priority-glyph surface so low/normal/high/urgent read consistently by color, not just icon shape.

- priorityIndicator.tsx: add colorVar (low=info/blue, normal=muted, high=warning/amber, urgent=error/red) and new getPriorityColorVar() export as the single source of truth
- QuickEntryBox: tint the icon-only priority trigger and each option row in the priority picker with the matching urgency color
- TaskForm: tint the New Task inline priority glyph using the same color source
- TaskCard: render a colored priority glyph alongside the existing text label in the card-priority-badge (kept the non-normal visibility gate and badge geometry via a small CSS gap addition)
- Updated/added tests for QuickEntryBox, TaskCard (badge, badge-height, badge-wrap), and priorityIndicator to assert the new colors; added a patch changeset and a dashboard-guide.md doc update

Files changed:
 .changeset/fn-7842-priority-color-coding.md        |  7 +++++
 docs/dashboard-guide.md                            |  7 +++--
 .../dashboard/app/components/QuickEntryBox.tsx     |  7 +++--
 packages/dashboard/app/components/TaskCard.css     |  2 ++
 packages/dashboard/app/components/TaskCard.tsx     |  6 +++-
 packages/dashboard/app/components/TaskForm.tsx     |  7 +++--
 .../components/__tests__/QuickEntryBox.test.tsx    | 17 +++++++++--
 .../__tests__/TaskCard.badge-height.test.tsx       |  5 ++++
 .../__tests__/TaskCard.badge-wrap.test.tsx         |  5 ++++
 .../app/components/__tests__/TaskCard.test.tsx     | 33 +++++++++++++++++++++-
 .../app/utils/__tests__/priorityIndicator.test.tsx | 13 +++++----
 packages/dashboard/app/utils/priorityIndicator.tsx | 16 ++++++++---
 12 files changed, 103 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-7842

Fusion-Task-Lineage: 0b2d0d15-6e61-45fc-9378-bc09002bef55

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 22:16:48 -07:00
gsxdsm
fc07bdfc7e FN-7831: add Reviewing badge for active Plan Review on task cards and list rows
Adds a distinct "Reviewing" status badge that surfaces on TaskCard and ListView rows while a task's optional plan-review workflow step is actively running, reusing the unified progress predicate so board and list surfaces stay in sync.

- Add isPlanReviewRunning(task) helper in taskProgress.ts, derived from getUnifiedTaskProgress's workflow-plan-review item status
- Render a pulsing "Reviewing" badge on TaskCard header (additive to existing status badges, with title/data-testid) while plan-review is running
- Render the matching "Reviewing" badge on both grouped and ungrouped ListView row layouts for parity with TaskCard
- Add supporting CSS for .card-status-badge--reviewing and .list-status-badge--reviewing
- Add unit tests for isPlanReviewRunning and component tests for the new badge across TaskCard and ListView
- Add minor changeset documenting the new operator-facing badge

Files changed:
 .changeset/tidy-reviewing-badges.md                |  7 ++
 packages/dashboard/app/components/ListView.css     | 10 +++
 packages/dashboard/app/components/ListView.tsx     | 22 +++++-
 packages/dashboard/app/components/TaskCard.css     | 10 +++
 packages/dashboard/app/components/TaskCard.tsx     | 25 ++++++-
 .../app/components/__tests__/ListView.test.tsx     | 78 ++++++++++++++++++++++
 .../app/components/__tests__/TaskCard.test.tsx     | 31 +++++++++
 .../app/utils/__tests__/taskProgress.test.ts       | 16 ++++-
 packages/dashboard/app/utils/taskProgress.ts       | 10 +++
 9 files changed, 205 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7831

Fusion-Task-Lineage: d36f8c63-9b84-400a-8b10-3b9f3b04212b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 20:37:26 -07:00
gsxdsm
937650472a FN-7820: add Cost tab to task detail and optional card cost badge
Adds a shared cost-derivation utility and surfaces token/cost info in a new Cost tab on the task detail modal, plus an opt-in per-card cost badge on the board.

- Extract token-cost calculation into a shared taskTokenCost helper (read-time costFor derivation) reused by the Summary tab, new Cost tab, and card badge
- Add TaskDetailModal Cost tab (TaskCostTab.tsx/.css) showing cost breakdown for a task
- Simplify TaskSummaryTab by delegating cost math to the shared helper
- Add default-off project setting showCostBadgeOnCards (settings-schema.ts, types.ts) with a SettingsModal/AppearanceSection toggle
- Add CostBadgeContext to thread the setting into TaskCard without prop drilling
- Show an optional cost badge on TaskCard when the setting is enabled
- Update i18n strings across en/es/fr/ko/zh-CN/zh-TW locales
- Update docs (dashboard-guide.md, settings-reference.md) and add changeset fn-7820-cost-tab-and-card-badge.md

Files changed:
 .changeset/fn-7820-cost-tab-and-card-badge.md      |   7 ++
 docs/dashboard-guide.md                            |   4 +
 docs/settings-reference.md                         |   1 +
 .../core/src/__tests__/settings-defaults.test.ts   |  13 ++
 packages/core/src/settings-schema.ts               |   5 +
 packages/core/src/types.ts                         |   5 +
 packages/dashboard/app/App.tsx                     |   5 +
 .../dashboard/app/components/SettingsModal.tsx     |   6 +
 packages/dashboard/app/components/TaskCard.css     |   7 +-
 packages/dashboard/app/components/TaskCard.tsx     |  27 +++-
 packages/dashboard/app/components/TaskCostTab.css  |  51 ++++++++
 packages/dashboard/app/components/TaskCostTab.tsx  |  91 ++++++++++++++
 .../dashboard/app/components/TaskDetailModal.tsx   |  14 ++-
 .../dashboard/app/components/TaskSummaryTab.tsx    | 123 +-----------------
 .../app/components/__tests__/TaskCard.test.tsx     |  81 +++++++++++-
 .../app/components/__tests__/TaskCostTab.test.tsx  |  55 ++++++++
 .../TaskDetailModal.attachments-and-tabs.test.tsx  |  11 +-
 .../settings/sections/AppearanceSection.tsx        |   8 ++
 .../sections/__tests__/AppearanceSection.test.tsx  |  20 +++
 .../settings-default-descriptions.test.tsx         |   1 +
 .../dashboard/app/context/CostBadgeContext.tsx     |  19 +++
 packages/dashboard/app/hooks/useAppSettings.ts     |  15 +++
 .../app/utils/__tests__/taskTokenCost.test.ts      |  62 +++++++++
 packages/dashboard/app/utils/taskTokenCost.ts      | 139 +++++++++++++++++++++
 packages/i18n/locales/en/app.json                  |  29 ++++-
 packages/i18n/locales/es/app.json                  |  30 ++++-
 packages/i18n/locales/fr/app.json                  |  27 +++-
 packages/i18n/locales/ko/app.json                  |  30 ++++-
 packages/i18n/locales/zh-CN/app.json               |  30 ++++-
 packages/i18n/locales/zh-TW/app.json               |  30 ++++-
 30 files changed, 789 insertions(+), 157 deletions(-)

Fusion-Task-Id: FN-7820

Fusion-Task-Lineage: d33c5678-a68c-4b29-9db1-8ff0369dfd72

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
3da9da28f3 FN-7818: replace placeholder Cursor icon with official brand mark
Swap the hand-drawn Cursor CLI placeholder SVG for Cursor's official cube/arrow brand mark and ensure model-id-shaped provider strings resolve to it.

- Replace CursorCliIcon's placeholder rounded-square+badge SVG with Cursor's official cube/arrow brand mark path data
- Add cursor -> cursor-cli mapping in inferProviderIconKey so cursor, cursor-agent, and cursor/<model> strings resolve to the branded icon instead of falling through to the generic CPU icon
- Update ProviderIcon and providerIconKey tests to cover the new brand mark paths and provider-string inference
- Add a patch changeset documenting the fix

Files changed:
 .changeset/fn-7818-cursor-logo.md                  |  7 +++++
 packages/dashboard/app/components/ProviderIcon.tsx | 33 +++++++++++-----------
 .../app/components/__tests__/ProviderIcon.test.tsx | 12 ++++++--
 .../app/utils/__tests__/providerIconKey.test.ts    |  4 +++
 packages/dashboard/app/utils/providerIconKey.ts    |  8 ++++++
 5 files changed, 44 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-7818

Fusion-Task-Lineage: 73e85e18-e98a-4dc3-b89d-f831525620de

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
60b8b4e4c5 FN-7805: redesign quick-add priority indicators as icon-only controls
Redesigns the Quick Add composer's priority selector to icon-only glyph buttons and relocates GitHub tracking beside attach, backed by a new shared priorityIndicator helper.

- Add packages/dashboard/app/utils/priorityIndicator.tsx as the single source of ArrowUp/ArrowDown/Flag/TriangleAlert priority glyphs, shared by QuickEntryBox and TaskForm
- Rework QuickEntryBox.tsx to render icon-only priority/Fast controls and move GitHub tracking + Priority into the .quick-entry-primary-group, with matching QuickEntryBox.css layout updates
- Update TaskForm.tsx to reuse the new priorityIndicator helper instead of duplicating icon/label logic
- Update quick-entry height-parity/trigger-height tests and QuickEntryBox/TaskForm/NewTaskModal tests for the new icon-only layout
- Add priorityIndicator.test.tsx covering the shared helper
- Update docs/dashboard-guide.md and add changeset fn-7805-quick-add-priority-indicators.md (patch, feature)

Files changed:
 .../fn-7805-quick-add-priority-indicators.md       |   7 +
 docs/dashboard-guide.md                            |   3 +-
 .../quick-entry-action-row-height-parity.test.tsx  |  13 +-
 .../quick-entry-workflow-trigger-height.test.tsx   |  10 +-
 .../dashboard/app/components/QuickEntryBox.css     |  19 +-
 .../dashboard/app/components/QuickEntryBox.tsx     | 197 +++++++++++----------
 packages/dashboard/app/components/TaskForm.tsx     |  33 ++--
 .../app/components/__tests__/NewTaskModal.test.tsx |   3 +
 .../components/__tests__/QuickEntryBox.test.tsx    | 113 ++++++++----
 .../app/components/__tests__/TaskForm.test.tsx     |   3 +
 .../app/utils/__tests__/priorityIndicator.test.tsx |  21 +++
 packages/dashboard/app/utils/priorityIndicator.tsx |  30 ++++
 12 files changed, 300 insertions(+), 152 deletions(-)

Fusion-Task-Id: FN-7805

Fusion-Task-Lineage: 404fe8d6-0851-44cb-b31d-f47896aaaaba

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 22:25:21 -07:00
gsxdsm
0755fc5747 fix(FN-7693): mobile terminal blank — exempt xterm measurement from * { max-width: 100% }
Real root cause of the blank mobile terminal (the FN-7692 remeasure guard did not
fix it and is reverted here). styles.css has a mobile-only reset
`@media (max-width: 768px) { * { max-width: 100% } }` to prevent horizontal
overflow. That universal selector also matches xterm's hidden character-measurement
subtree (`.xterm-helpers` / `.xterm-char-measure-element`). That subtree's containing
block (`.xterm-helpers`) is a 0x0 absolutely-positioned box, so `max-width: 100%`
resolves to `max-width: 0` and hard-caps xterm's character-cell measurement at 0.
FitAddon.fit() then proposes 0 columns/rows and `.xterm-screen` (plus the WebGL
canvas) collapses to 0x0 — the prompt streams in and is written into xterm's row DOM
but paints into a zero-size box, so the terminal is blank. Mobile-only, which is why
desktop always rendered fine.

Reproduced live via mobile emulation: `.xterm-char-measure-element` measured 0 while
an identical monospace span in the same container measured ~295px; `max-width: none`
on the measure element restored ~295px, and reopening the terminal with the exemption
active rendered the prompt with `.xterm-screen` sized 369x760. No amount of
remeasure/refit can fix this — the CSS re-caps the measurement to 0 every time — so
the FN-7692 CharSizeService guard is removed.

- Exempt `.xterm-helpers` / `.xterm-char-measure-element` from the mobile max-width
  reset in styles.css (covers both TerminalModal and SessionTerminal)
- Revert the ineffective FN-7692 remeasure guard and its tests
- Update changeset (patch) and the docs/solutions write-up to the real root cause

Note: root cause + fix validated in the automation browser via mobile emulation
(393px, iPhone UA, forced touch), not a physical device.

Fusion-Task-Id: FN-7693

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 15:09:26 -07:00
gsxdsm
b7b1b71cae fix(FN-7692): recover blank mobile terminal when xterm screen collapses to 0x0
The mobile terminal rendered blank even though the WebSocket was Connected and
the shell prompt had already streamed in. Root cause (reproduced live): on the
mobile fullscreen layout xterm's CharSizeService can measure a 0-width character
cell, so FitAddon.fit() proposes 0 columns/rows and .xterm-screen (plus the WebGL
canvas) collapses to 0x0 — prompt bytes arrive and are written into xterm's row
DOM but paint into a zero-size box. Renderer-independent and mobile-layout-
specific; not fixed by resize/font-size re-fits because prior guards only validate
the container width and font load, never the resulting measured screen/cell width.

Add guardAgainstCollapsedTerminalScreen (app/utils/terminalPreferences.ts) and arm
it from both terminal surfaces (TerminalModal + SessionTerminal) right after their
initial fit. While the container has a width but .xterm-screen does not, it forces
a genuine DOM-strategy remeasure (forceTerminalFontRemeasure) + fit, re-driven by a
ResizeObserver until the screen has a real width. It waits (does not give up) while
the container is not yet measurable, is bounded so it never spins, and is disposed
on every re-init/close path. Recurrence of FN-7620/FN-7686.

- Add isTerminalScreenCollapsed + guardAgainstCollapsedTerminalScreen with tests
- Wire + dispose the guard across all xterm (re)init/close paths in both surfaces
- Add changeset (patch) and a docs/solutions write-up

Note: reproduced via mobile emulation (393px, iPhone UA, forced touch), not a
physical device; the guard is the structural fix — confirm on a real device.

Fusion-Task-Id: FN-7692

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 13:22:10 -07:00
gsxdsm
5631c88d54 FN-7614: replace planning-mode banner with yellow nav badge for needs-input state
Planning Mode's "waiting for input" indicator moves from a top banner (whose button did not redirect correctly) to a yellow status-dot badge on the Planning nav destination, matching the existing chat unread-badge pattern.

- Add a `planningNeedsInput` flag in app lifecycle utils to detect awaiting_input planning sessions
- Exclude planning awaiting_input sessions from SessionNotificationBanner so the banner no longer shows for this case
- Add a status-dot--pending badge to the Planning entry in LeftSidebarNav and to the Planning item/tab in MobileNavBar
- Add/extend tests covering appLifecycle, LeftSidebarNav, MobileNavBar, and SessionNotificationBanner behavior
- Add changeset (patch) documenting the fix
- Update dashboard-guide.md docs

Files changed:
 .changeset/fn-7614-planning-badge.md               |  7 +++
 docs/dashboard-guide.md                            |  4 ++
 packages/dashboard/app/App.tsx                     | 13 +++-
 .../dashboard/app/components/LeftSidebarNav.tsx    | 10 +++
 packages/dashboard/app/components/MobileNavBar.css | 20 ++++++
 packages/dashboard/app/components/MobileNavBar.tsx | 19 +++++-
 .../components/__tests__/LeftSidebarNav.test.tsx   | 28 +++++++++
 .../app/components/__tests__/MobileNavBar.test.tsx | 41 ++++++++++++
 .../__tests__/SessionNotificationBanner.test.tsx   | 44 +++++++++++++
 .../app/utils/__tests__/appLifecycle.test.ts       | 73 +++++++++++++++++++++-
 packages/dashboard/app/utils/appLifecycle.ts       | 12 ++++
 packages/i18n/locales/en/app.json                  |  1 +
 packages/i18n/locales/es/app.json                  |  1 +
 packages/i18n/locales/fr/app.json                  |  1 +
 packages/i18n/locales/ko/app.json                  |  1 +
 packages/i18n/locales/zh-CN/app.json               |  1 +
 packages/i18n/locales/zh-TW/app.json               |  1 +
 packages/i18n/src/resources.d.ts                   |  1 +
 18 files changed, 275 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7614

Fusion-Task-Lineage: 249e6ee8-149c-4d51-85b6-561dfc30c769

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-06 19:03:06 -07:00
gsxdsm
9d4a45b0f9 FN-7561: fix mobile terminal excess inter-character spacing after font settle
Root-cause fix for xterm text rendering with wide inter-character gaps on mobile after fonts settle post-load.
- Added forceTerminalFontRemeasure() in terminalPreferences.ts to work around xterm's OptionsService setter being a no-op when reassigning an already-current fontFamily/fontSize
- Applied the remeasure helper at every post-waitForTerminalFontMetrics() settle site in TerminalModal.tsx and SessionTerminal.tsx
- Added regression tests covering the remeasure invariant across SessionTerminal, TerminalModal, and terminalPreferences
- Documented root cause and fix in docs/solutions/ui-bugs/xterm-options-noop-remeasure-after-font-settle.md
- Added changeset for @runfusion/fusion (patch)

Files changed:
 .changeset/fn-7561-mobile-terminal-spacing.md      |   7 +
 docs/solutions/ui-bugs/xterm-options-noop-remeasure-after-font-settle.md | 120 ++++++++++
 packages/dashboard/app/components/SessionTerminal.tsx   |  11 +-
 packages/dashboard/app/components/TerminalModal.tsx     |  11 +-
 packages/dashboard/app/components/__tests__/SessionTerminal.test.tsx  | 108 ++++++++-
 packages/dashboard/app/components/__tests__/TerminalModal.test.tsx    | 257 ++++++++++++++++++++-
 packages/dashboard/app/utils/__tests__/terminalPreferences.test.ts    |  55 +++++
 packages/dashboard/app/utils/terminalPreferences.ts     |  38 +++
 8 files changed, 601 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7561

Fusion-Task-Lineage: ad9da396-abf4-46ea-8c60-f2ed40fa4b01

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-05 11:31:44 -07:00
gsxdsm
f992e6aefa FN-7553: add dedicated keyboard shortcuts settings section
Adds a standalone Keyboard Shortcuts settings section with an easier-to-use capture input and support for more shortcut actions.
- Introduce a new KeyboardShortcutsSection with a dedicated ShortcutCaptureInput component for recording key combos
- Split keyboard-shortcut settings out of the general settings section into their own settings tab
- Extend the shortcut schema/types and useDashboardKeyboardShortcuts hook to support additional actions
- Update settings save-split, section-keys, and defaults/parity tests to cover the new section
- Update dashboard docs and add a changeset for the new settings section

Files changed:
 .changeset/fn-7553-keyboard-shortcuts-section.md   |   7 +
 docs/dashboard-guide.md                            |  22 ++-
 packages/core/src/__tests__/global-settings.test.ts     |   9 +-
 packages/core/src/__tests__/settings-defaults.test.ts   |   4 +
 packages/core/src/__tests__/settings-parity.test.ts     |   2 +-
 packages/core/src/settings-schema.ts               |   6 +-
 packages/core/src/types.ts                         |  12 ++
 packages/dashboard/app/App.tsx                     |  26 +++-
 packages/dashboard/app/__tests__/App.keyboard-shortcuts.test.tsx  |  47 ++++++-
 packages/dashboard/app/components/SettingsModal.css     |  56 ++++++--
 packages/dashboard/app/components/SettingsModal.tsx     |  30 +++-
 packages/dashboard/app/components/__tests__/SettingsModal.general.test.tsx |  63 ---------
 packages/dashboard/app/components/__tests__/SettingsModal.keyboardShortcuts.test.tsx |  156 +++++++++++++++++++++
 packages/dashboard/app/components/settings/__tests__/section-keys.test.ts |   1 +
 packages/dashboard/app/components/settings/save-split.ts |   6 +-
 packages/dashboard/app/components/settings/sections/GlobalGeneralSection.tsx |  38 -----
 packages/dashboard/app/components/settings/sections/KeyboardShortcutsSection.tsx |  78 +++++++++++
 packages/dashboard/app/components/settings/sections/ShortcutCaptureInput.tsx |  118 ++++++++++++++++
 packages/dashboard/app/components/settings/sections/__tests__/KeyboardShortcutsSection.test.tsx |  113 +++++++++++++++
 packages/dashboard/app/hooks/__tests__/useDashboardKeyboardShortcuts.test.tsx |  73 +++++++++-
 packages/dashboard/app/hooks/useDashboardKeyboardShortcuts.ts |  38 ++++-
 packages/dashboard/app/utils/__tests__/keyboardShortcuts.test.ts |  37 ++++-
 packages/dashboard/app/utils/keyboardShortcuts.ts  |  54 ++++++-
 23 files changed, 854 insertions(+), 142 deletions(-)

Fusion-Task-Id: FN-7553

Fusion-Task-Lineage: 51c1ad69-fbd3-45ce-8d2d-45d9962d7b76

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-04 21:28:19 -07:00
gsxdsm
3b52a4d2d9 FN-7527: fix desktop server switching redirects
Route desktop shell server switches through the live runtime/profile state.

- Replace separate local/remote redirect effects with a shared resolver that uses localRuntime/baseUrl and active remote profiles.
- Remove the dead localServer shell state field and document the local/remote switch navigation behavior.
- Add regression coverage for desktop shell redirect targets and include a patch changeset.

Files changed:
 .changeset/fn-7527-desktop-switch-server-navigation.md    |   7 +
 docs/native-shell.md                               |   2 +-
 packages/dashboard/app/App.tsx                     |  44 ++---
 packages/dashboard/app/components/__tests__/App.test.tsx          |   1 -
 packages/dashboard/app/types/native-shell.d.ts     |  13 +-
 packages/dashboard/app/utils/__tests__/appLifecycle.test.ts       | 180 +++++++++++++++++++++
 packages/dashboard/app/utils/appLifecycle.ts       |  70 ++++++++
 7 files changed, 280 insertions(+), 37 deletions(-)

Fusion-Task-Id: FN-7527

Fusion-Task-Lineage: a0fe5cbc-120b-4a56-b791-48306223a636

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-04 13:43:59 -07:00
gsxdsm
9f24b507fc FN-7507: prioritize topmost dashboard shortcut dismissal
Refine dashboard keyboard shortcut behavior and coverage for configurable popup handling.

- Factor App Escape dismissal into a pure helper that closes one topmost surface at a time.
- Prioritize popped-out tasks ahead of Quick Chat, Terminal, and fixed dashboard modals.
- Add regression coverage for configurable shortcut bindings, editable focus guards, default-prevented events, and Escape ordering.
- Update dashboard shortcut documentation and release-note wording.

Files changed:
 .changeset/fn-7494-keyboard-shortcuts.md           |   4 +-
 docs/dashboard-guide.md                            |   2 +-
 packages/dashboard/app/App.tsx                     | 110 +++++++++-----
 .../app/__tests__/App.keyboard-shortcuts.test.tsx  | 158 +++++++++++++++++++++
 .../app/utils/__tests__/keyboardShortcuts.test.ts  |   1 +
 5 files changed, 236 insertions(+), 39 deletions(-)

Fusion-Task-Id: FN-7507

Fusion-Task-Lineage: 804986ef-ec6c-4404-a168-6d154f75b118

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-04 12:08:38 -07:00
gsxdsm
2f23d2260d FN-7494: add configurable dashboard shortcuts
Add configurable dashboard keyboard shortcuts for opening Quick Chat and Terminal.

- Add global settings defaults, schemas, persistence, and Settings UI controls for dashboard shortcuts.
- Register safe document-level shortcut handling with editable-target guards and Escape popup dismissal.
- Normalize shortcut strings, detect disabled/conflicting bindings, and document operator behavior.
- Cover shortcut parsing, dashboard listener behavior, and settings persistence with tests.

Files changed:
 .changeset/fn-7494-keyboard-shortcuts.md           |   7 +
 docs/dashboard-guide.md                            |  14 ++
 .../core/src/__tests__/global-settings.test.ts     |  20 +++
 .../core/src/__tests__/settings-defaults.test.ts   |  10 ++
 .../core/src/__tests__/settings-parity.test.ts     |  10 ++
 packages/core/src/__tests__/store-settings.test.ts |  10 ++
 packages/core/src/settings-schema.ts               |   8 +
 packages/core/src/types.ts                         |  12 ++
 packages/dashboard/app/App.tsx                     |  52 ++++++
 .../dashboard/app/components/SettingsModal.css     |  21 +++
 .../dashboard/app/components/SettingsModal.tsx     |  11 ++
 .../__tests__/SettingsModal.general.test.tsx       |  63 ++++++++
 .../app/components/settings/save-split.ts          |   1 +
 .../settings/sections/GlobalGeneralSection.tsx     |  38 +++++
 .../useDashboardKeyboardShortcuts.test.tsx         | 101 ++++++++++++
 packages/dashboard/app/hooks/useAppSettings.ts     |   8 +-
 .../app/hooks/useDashboardKeyboardShortcuts.ts     |  66 ++++++++
 .../app/utils/__tests__/keyboardShortcuts.test.ts  |  76 +++++++++
 packages/dashboard/app/utils/keyboardShortcuts.ts  | 175 +++++++++++++++++++++
 19 files changed, 702 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7494
Fusion-Task-Lineage: 30445f4d-c0c5-4657-bd79-fc2acaf3c37d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-04 11:38:42 -07:00
gsxdsm
9df13c7ffa fix(dashboard): garbage-collect stale SWR caches and add Clear local data button
Stale SWR hydration entries (per-chat-session/per-room message caches up to
500KB each) were never garbage-collected — readCache returned null for stale
entries but left the bytes on disk, and nothing swept abandoned caches. This
caused localStorage quota exhaustion for users with many projects and chat
sessions.

Three fixes:
- readCache now lazily deletes stale entries (behavior-preserving; every
  reader already treats stale as a miss and re-fetches)
- Boot sweep pruneStaleCacheEntries() in DashboardLoader removes any
  kb-dashboard-* entry older than 24h before hydration hooks read caches
- Settings > General "Browser Data" panel with a Clear local data button
  that wipes all Fusion-owned browser data while preserving the auth token

Also completes the vitest localStorage mock (was missing length/key).
2026-07-02 23:53:26 -07:00
gsxdsm
869974cd5a FN-7383: refresh workflows after chat authoring
Chat-authored workflow changes now propagate immediately to workflow selectors and editors.

- Emit workflow lifecycle SSE events when chat, planner, or room workflow tools create, update, select, configure, or delete workflows.
- Force-refresh board workflow caches and the workflow editor list when workflow lifecycle events arrive.
- Add cross-surface tests for chat workflow creation visibility and room/chat workflow tool event behavior.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-7383-chat-workflow-authoring.md      |  7 +++
 .../workflow-selection-cross-surface.test.tsx      | 23 +++++++++
 packages/dashboard/app/api/legacy.ts               |  9 ++--
 .../app/components/WorkflowNodeEditor.tsx          | 23 ++++++++-
 .../app/hooks/__tests__/useBoardWorkflows.test.ts  | 27 +++++++---
 packages/dashboard/app/hooks/useBoardWorkflows.ts  | 22 +++++---
 .../utils/__tests__/boardWorkflowsCache.test.ts    | 12 ++++-
 .../dashboard/app/utils/boardWorkflowsCache.ts     | 14 +++++
 .../dashboard/src/__tests__/chat-manager.test.ts   | 44 ++++++++++++++--
 .../dashboard/src/__tests__/chat.rooms.test.ts     | 44 ++++++++++++++++
 packages/dashboard/src/chat.ts                     | 59 +++++++++++++++++++---
 11 files changed, 255 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-7383

Fusion-Task-Lineage: ebe4c982-214b-402f-b829-a58ace19ffe0

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-01 11:12:59 -07:00
gsxdsm
0915377a1c FN-7314: reuse shared planner question UI
Reuse the existing question-response modal UI inside task-detail planner Chat clarification flows.

- Render planner fn_ask_question tool calls with ChatQuestionResponse, including answered read-only and duplicate-pending states.
- Preserve steering-tool confirmations while sending submitted clarification answers back through planner Chat.
- Extend parser and modal tests for multi-question payloads, submitted answers, duplicate prompts, and empty dependency labels.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-7314-planner-question-ui.md          |  7 ++
 .../app/components/TaskPlannerChatTab.css          |  9 +++
 .../app/components/TaskPlannerChatTab.tsx          | 76 ++++++++++++++++--
 ...etailModal.responsive-and-dependencies.test.tsx |  3 +
 .../__tests__/TaskPlannerChatTab.test.tsx          | 89 ++++++++++++++++++----
 .../utils/__tests__/parseQuestionToolCall.test.ts  | 10 ++-
 .../dashboard/app/utils/parseQuestionToolCall.ts   |  6 +-
 7 files changed, 176 insertions(+), 24 deletions(-)

Fusion-Task-Id: FN-7314

Fusion-Task-Lineage: bd5da323-0ba1-4094-a965-cc2801a1c9b7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-30 19:21:53 -07:00
gsxdsm
082dd55967 FN-7280: persist all-workflows board view
Persist the Board aggregate workflow view so refreshes restore the operator's last board selection.

- Store the All workflows sentinel in project-scoped board view preferences while filtering it out for real workflow consumers.
- Restore all-workflows selection on remount/project changes and clear it when workflow mode is unavailable.
- Cover refresh persistence, project scoping, hooks, utilities, and cross-surface behavior with tests.
- Document the refresh-persistent All workflows behavior and add a patch changeset.

Files changed:
 .changeset/fn-7280-all-workflows-board-view.md     |  7 +++
 docs/dashboard-guide.md                            |  7 +--
 .../workflow-selection-cross-surface.test.tsx      | 15 ++++++
 packages/dashboard/app/components/Board.tsx        | 31 +++++++++---
 .../app/components/__tests__/Board.test.tsx        | 58 ++++++++++++++++++++--
 .../app/hooks/__tests__/useBoardWorkflows.test.ts  | 11 ++++
 .../utils/__tests__/boardWorkflowSelection.test.ts | 13 +++++
 .../dashboard/app/utils/boardWorkflowSelection.ts  | 13 ++++-
 8 files changed, 137 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-7280

Fusion-Task-Lineage: 12d83b05-5b2b-4435-9383-30b35c07c087

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-30 09:04:03 -07:00
gsxdsm
d05ca2154f FN-7258: restore mobile board scroll on return
Preserve the board lane position when mobile users return from full-panel task detail.

- Capture and restore board, column, project-content, and document scroll offsets for board detail navigation.
- Retry board scroll restoration across bounded animation frames after remount and hydration.
- Cover mobile and desktop Back to board behavior with focused tests and document the mobile scroll contract.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-7258-mobile-board-scroll.md          |   7 ++
 docs/dashboard-guide.md                            |   2 +
 .../__tests__/navigation-history.test.tsx          | 111 ++++++++++++++++++---
 .../hooks/__tests__/useBoardScrollRestore.test.ts  |  43 +++++++-
 .../dashboard/app/hooks/useBoardScrollRestore.ts   |  45 ++++++---
 .../utils/__tests__/boardScrollSnapshot.test.ts    |  91 +++++++++++++++--
 .../dashboard/app/utils/boardScrollSnapshot.ts     |  41 +++++++-
 7 files changed, 305 insertions(+), 35 deletions(-)

Fusion-Task-Id: FN-7258

Fusion-Task-Lineage: 97faf031-4244-4117-9948-45491c364134

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-29 21:02:34 -07:00
gsxdsm
3886e585dd fix(FN-7143): show compound workflow node progress
Record skill-backed workflow nodes into workflowStepResults and teach task progress surfaces to include those graph-node records without re-showing disabled optional workflow checks.
2026-06-29 14:59:16 -07:00
gsxdsm
b36327059a FN-7234: preserve board workflow selections
Persist workflow choices across dashboard board surfaces so operators return to their selected lane reliably.

- Add project-scoped durable storage helpers for board workflow selection with stale-id validation and cleanup.
- Share the workflow selection hook across Board, List, Header, and Graph surfaces while preserving cached payloads on transient refresh failures.
- Update List quick-create/planning handoffs, cross-surface tests, and dashboard documentation for durable workflow selection behavior.
- Add patch changesets for the published Fusion package.

Files changed:
 .changeset/fn-7234-durable-board-workflow-selection.md    |   7 ++
 .changeset/workflow-selection-board-list.md               |   7 ++
 docs/dashboard-guide.md                                   |   5 +-
 .../workflow-selection-cross-surface.test.tsx             |  66 ++++++++--
 packages/dashboard/app/components/ListView.tsx            | 111 ++++-------------
 .../app/components/__tests__/Board.test.tsx               |  45 +++++++
 .../__tests__/GraphWorkflowSwitcherSlot.test.tsx          |  57 +++++++++
 .../__tests__/HeaderWorkflowSwitcherSlot.test.tsx         |  42 ++++++-
 .../app/components/__tests__/ListView.test.tsx            | 122 +++++++++++++++++++
 .../app/hooks/__tests__/useBoardWorkflows.test.ts         |  29 +++++
 packages/dashboard/app/hooks/useBoardWorkflows.ts         |  64 ++++++++-
 .../utils/__tests__/boardWorkflowSelection.test.ts        | 135 +++++++++++++++++++++
 .../app/utils/__tests__/projectStorage.test.ts            |   3 +-
 .../dashboard/app/utils/boardWorkflowSelection.ts         |  49 ++++++++
 packages/dashboard/app/utils/projectStorage.ts            |   1 +
 15 files changed, 633 insertions(+), 110 deletions(-)

Fusion-Task-Id: FN-7234
Fusion-Task-Lineage: 6ebc000c-19c3-4a8e-9303-4e18a59902ed
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-29 14:41:52 -07:00
gsxdsm
b86ddf4d10 fix(FN-7225): route failed plan review to triage 2026-06-29 00:48:49 -07:00
gsxdsm
0a8a86cb05 FN-7217: map GLM models to Z.ai icons
Command Center token analytics now render standalone GLM model rows with Z.ai provider icons.

- Infer Z.ai provider icons for standalone glm-* model ids without matching unrelated text.
- Cover GLM icon rendering in Overview token bars and Tokens Area bars/table rows.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-7217-zai-glm-icons.md                |  7 +++
 .../__tests__/CommandCenter.test.tsx               | 39 ++++++++++++++++
 .../areas/__tests__/TokensArea.test.tsx            | 53 ++++++++++++++++++++++
 .../app/utils/__tests__/providerIconKey.test.ts    |  4 ++
 packages/dashboard/app/utils/providerIconKey.ts    |  7 ++-
 5 files changed, 109 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7217

Fusion-Task-Lineage: e784413e-2dcf-4b38-ba01-5f9d825e07b8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-28 21:00:00 -07:00
gsxdsm
fc958bc54b FN-7178: improve review comment rendering
Render task Review tab comments with cleaner content, author context, and filter controls.

- Reuse the sanitized mailbox markdown renderer and strip GitHub HTML comments in plain-text mode.
- Add human/bot author derivation, avatars, badges, and All/Human/Bot filtering for review items.
- Cover rendering, filtering, selection pruning, and author classification with dashboard tests.
- Document the Review tab behavior and add the release changeset.

Files changed:
 .../fn-7178-task-review-comment-rendering.md       |   7 +
 docs/dashboard-guide.md                            |   1 +
 .../dashboard/app/components/TaskReviewTab.css     | 117 ++++++++++++++++
 .../dashboard/app/components/TaskReviewTab.tsx     | 144 ++++++++++++-------
 .../components/__tests__/TaskReviewTab.test.tsx    | 153 +++++++++++++++++++++
 .../utils/__tests__/githubCommentAuthor.test.ts    |  46 +++++++
 .../dashboard/app/utils/githubCommentAuthor.ts     |  33 +++++
 packages/dashboard/vitest.config.ts                |   1 +
 8 files changed, 455 insertions(+), 47 deletions(-)

Fusion-Task-Id: FN-7178

Fusion-Task-Lineage: 98269a09-3c57-492d-b433-d6ccb81d5b17

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-27 23:53:51 -07:00
gsxdsm
5b71bdb284 FN-7177: color PR badges by GitHub status
Align dashboard PR badges with live GitHub PR state colors.

- Add a shared PR badge modifier helper for open, draft, merged, closed, and conflict states.\n- Apply the helper to single and multi-PR task card badges so live payload changes repaint correctly.\n- Add token-backed merged/conflict styling, regression coverage, and a patch changeset.

Files changed:\n .changeset/fn-7177-pr-badge-status-color.md        |  7 ++++\n packages/dashboard/app/components/GitHubBadge.tsx  |  8 +++--\n packages/dashboard/app/components/TaskCard.tsx     |  9 +++--\n .../app/components/__tests__/GitHubBadge.test.tsx  |  1 +\n .../app/components/__tests__/TaskCard.test.tsx     | 41 +++++++++++++++++++---\n packages/dashboard/app/styles.css                  | 15 ++++++--\n .../app/utils/__tests__/prBadgeClass.test.ts       | 22 ++++++++++++\n packages/dashboard/app/utils/prBadgeClass.ts       | 28 +++++++++++++++\n 8 files changed, 119 insertions(+), 12 deletions(-)

Fusion-Task-Id: FN-7177

Fusion-Task-Lineage: 23954f1b-d184-49a6-9635-7d9c1d0aea11

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-27 23:47:21 -07:00
gsxdsm
b570a834ba FN-7156: open Missions on overview by default
Ensure the Missions tab opens to the overview unless an explicit mission target is requested.

- Remove selected-mission cache restore and inline first-mission auto-selection.
- Treat hidden inline Missions as inactive so reopening resets to overview.
- Update SWR cache keys and dashboard tests for the overview-first behavior.
- Add a patch changeset documenting the operator-facing fix.

Files changed:
 .changeset/fn-7156-missions-overview-default.md    |   7 +
 .../dashboard/app/components/DashboardLoader.tsx   |   1 -
 .../dashboard/app/components/MissionManager.tsx    |  50 ++----
 .../components/__tests__/DashboardLoader.test.tsx  |   1 -
 .../MissionManager.overview-default.test.tsx       | 174 +++++++++++++++++++++
 .../dashboard/app/utils/__tests__/swrCache.test.ts |   1 -
 packages/dashboard/app/utils/swrCache.ts           |   1 -
 7 files changed, 191 insertions(+), 44 deletions(-)

Fusion-Task-Id: FN-7156

Fusion-Task-Lineage: 1be987d5-33c6-4a59-905f-14c8d22b75d1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-27 20:27:09 -07:00
gsxdsm
c468c161c2 FN-7141: add chat context token budget indicator
Add a desktop Direct-chat header indicator for estimated tokens used against the active model context window.

- Estimate chat token usage client-side, including streaming text, and format compact counts.
- Render the context-window badge only for non-mobile Direct-chat threads with known model context windows.
- Cover desktop, mobile, floating-narrow, rooms, unknown-context, and streaming surfaces with tests.
- Document the dashboard behavior and add a release changeset.

Files changed:
 .changeset/fn-7141-chat-context-window.md          |   7 +
 docs/dashboard-guide.md                            |   2 +
 packages/dashboard/app/components/ChatView.css     |  22 +++
 packages/dashboard/app/components/ChatView.tsx     |  35 +++-
 .../__tests__/ChatView.context-window.test.tsx     | 193 +++++++++++++++++++++
 .../app/utils/__tests__/estimateChatTokens.test.ts |  34 ++++
 packages/dashboard/app/utils/estimateChatTokens.ts |  29 ++++
 packages/i18n/locales/en/app.json                  |   1 +
 8 files changed, 322 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7141

Fusion-Task-Lineage: 3ede9af4-b8d6-4da6-996f-cd9277ef49ac

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-27 17:22:12 -07:00
gsxdsm
819c626466 fix(mobile-chat): hide executor footer and remove gap above keyboard (#1789)
## Problem

On mobile, when the soft keyboard is up in Chat, the executor footer
(task counts / **Running** indicator) stayed visible and there was a
dead band of empty space between the composer and the keyboard.

Root cause: `computeMobileBarKeyboardFlags` gated the footer-hide +
padding-strip to **iOS only**. On Android `footerHidden` stayed `false`,
so `ExecutorStatusBar` kept rendering **and** `.project-content` kept
reserving `footer-height + nav-height` (~80px) of `padding-bottom`. The
mobile nav bar is slid off-screen (`translateY(100%)`) when the keyboard
is up, so that reserved space rendered as the empty gap.

## Fix

Drop the `&& isIOS` gate on `footerHidden` so Android matches iOS. When
the keyboard is open on mobile:
- `ExecutorStatusBar` is hidden (no task-count/Running footer), and
- `.project-content` reserves no footer/nav padding, so the composer
sits flush above the keyboard.

`footerKeyboardOpen` (the iOS `bottom: 0` footer-collapse class) stays
iOS-only — it only matters when the footer is still rendered over a
modal. Modal / Quick-Chat-overlay keyboard cases are unchanged
(`boardLayoutSuppressed`).

## Before / After

| Before | After |
| --- | --- |
| Footer shown + empty gap above keyboard | Footer hidden, composer
flush above keyboard |

_(Rendered with the real component CSS at a mobile viewport with the
keyboard-open classes applied.)_

## Notes / verification

- File-scoped tests pass: `mobileBarKeyboardFlags`,
`mobile-bottom-bars-keyboard-layout`, App keyboard-layout cases,
`footer-safe-layout`, `dashboard-footer-mobile-layout`,
`ChatView.mobile-render` (46 tests).
- FN-5707 originally gated this to iOS over a concern that stripping nav
padding mid-focus could make Android Chrome dismiss the keyboard. The
strip is keyed off `keyboardOpen`, which only flips `true` after the
visual viewport settles into its keyboard-open size — but **please
confirm on a real Android device** that the keyboard stays up when
tapping the composer. If it dismisses, the fallback is a transform-based
hide that avoids the reflow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1789">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->
2026-06-26 10:17:37 -07:00
gsxdsm
e48c75ccc5 fix(mobile-chat): hide executor footer and remove gap above keyboard
On Android the keyboard-open footer (executor status bar) stayed visible
and the off-screen mobile nav bar's reserved padding rendered as an empty
band between the composer and the keyboard. computeMobileBarKeyboardFlags
no longer iOS-gates footerHidden, so both platforms now hide the footer
and drop the reserved footer+nav padding-bottom when the soft keyboard is
up, letting the composer sit flush above the keyboard. footerKeyboardOpen
(the iOS bottom:0 collapse class) stays iOS-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 09:32:53 -07:00
gsxdsm
fca2ff6efb fix(FN-7039): render workflow steps with proper casing in the progress UI
An enabled-but-not-yet-run workflow step has no recorded result, so the progress bar
previously showed the raw graph node id (e.g. 'code-review'). Humanize the id fallback to
Title Case ('Code Review', 'Browser Verification', 'Frontend UX Design'). Once the step
runs, the graph-recorded config.name still wins; humanization is only the pre-run fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 08:53:26 -07:00
gsxdsm
3ee47dec86 merge: integrate origin/main into feature/workflow-steps (FN-7039)
Resolve conflicts from 56 upstream commits:
- db.ts: renumber my migrations around main's new migration 130 (columnDwellMs) —
  enable-id normalization 130→131, drop-table 131→132, SCHEMA_VERSION→132.
- index.ts / routes.ts: take main's new MCP exports/imports; keep WORKFLOW_STEP_TEMPLATES
  array removed (kept the WorkflowStepTemplate type).
- merger.ts: keep the legacy post-merge execution path removed (U7c) over main's version.
- ci-workflow.test.ts (from main): add port-4040/process-supervisor allowlist markers to
  the gate-script assertions that reference the checker filenames (pre-existing self-match).

Gate green (engine-core 299, ci-shape 62); boot smoke PASS; migration tests + typecheck clean.
2026-06-26 08:50:22 -07:00
gsxdsm
005322eeaa fix(review): address PR #1788 review feedback
- workflow-graph-executor: wrap each post-merge walk() in try/catch so a malformed
  post-merge IR / traversal error is logged and skipped, never flipping an already-
  merged task to failed (non-blocking post-merge contract) [T9, real bug].
- Refresh stale FNXC comments now that graphNativePostMerge is default-ON and the
  legacy merger post-merge path was removed (experimental-features, workflow-graph-
  executor, workflow-graph-post-merge.test) [T6/T7/T8].
- Normalize FNXC timestamps to yyyy-MM-dd-hh:mm (TaskCard.test, taskProgress.test) [T2/T3].
- Changeset: category fix → feature to match the minor bump [T0].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 08:40:59 -07:00
gsxdsm
4dab2b6986 FN-7011: Exclude engine downtime from task timing
Exclude proven engine-process downtime from active task duration stats and badges.

- Persist a throttled engineLastActiveAt heartbeat while the scheduler is running and unpaused.
- Reconcile in-progress execution segment anchors on startup when downtime exceeds the poll threshold.
- Emit run-audit events for shifted and no-action downtime reconciliation outcomes.
- Cover core timing, dashboard badge behavior, scheduler heartbeat throttling, and self-healing audit metadata.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-7011-engine-downtime-timing.md       |  7 +++
 AGENTS.md                                          |  1 +
 .../src/__tests__/store-execution-timing.test.ts   | 51 ++++++++++++++++++++++
 packages/core/src/settings-schema.ts               |  1 +
 packages/core/src/store.ts                         | 28 ++++++++++++
 packages/core/src/types.ts                         |  5 +++
 .../app/utils/__tests__/taskTiming.test.ts         | 16 +++++++
 .../__tests__/scheduler-workflow-cutover.test.ts   | 29 +++++++++++-
 packages/engine/src/__tests__/self-healing.test.ts | 23 ++++++++++
 packages/engine/src/run-audit.ts                   |  4 ++
 packages/engine/src/scheduler.ts                   | 11 +++++
 packages/engine/src/self-healing.ts                | 21 +++++++++
 12 files changed, 196 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7011

Fusion-Task-Lineage: 44225b0a-0fa1-40be-812d-33fd5e446944
2026-06-25 23:35:31 -07:00
gsxdsm
9a2709dde9 FN-6969: show provider icons beside Command Center models
Show inferred provider icons beside model names across Command Center bar and table surfaces.

- Add dashboard-side provider-icon inference for model/provider strings.
- Render provider icons on Command Center model bar rows and token table rows while keeping pie chart labels text-only.
- Cover overview, token, and ecosystem model-icon surfaces with tests and add a changeset.

Files changed:
 .changeset/fn-6969-provider-icons.md               |   7 ++
 .../components/command-center/CommandCenter.tsx    |  15 ++-
 .../__tests__/CommandCenter.test.tsx               |  33 ++++++-
 .../command-center/areas/EcosystemArea.tsx         |  15 ++-
 .../components/command-center/areas/TokensArea.tsx |  37 +++++++-
 .../areas/__tests__/TokensArea.test.tsx            | 105 +++++++++++++++++++++
 .../command-center/areas/__tests__/areas.test.tsx  |  42 ++++++++-
 .../app/components/command-center/charts/Bar.tsx   |  25 ++++-
 .../components/command-center/charts/charts.css    |  42 +++++++++
 .../app/utils/__tests__/providerIconKey.test.ts    |  32 +++++++
 packages/dashboard/app/utils/providerIconKey.ts    |  45 +++++++++
 11 files changed, 377 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-6969

Fusion-Task-Lineage: 6caf8864-1ecc-46e3-b7fa-bfa8e9a70aaa
2026-06-25 23:34:07 -07:00
gsxdsm
7b358b74b5 feat(FN-7039): drive progress bar + Workflow tab from graph-written results
getUnifiedTaskProgress reads task.workflowStepResults (graph-written in U2) and
no longer needs workflowStepNameLookup — names come from result.workflowStepName.
Removed the lookup prop + fetchWorkflowSteps-name plumbing end-to-end (App,
MainContent, RightDock, Board, Column, Lane, WorktreeGroup, TaskCard). Added the
running state (pending + startedAt) and a distinct advisory_failure (amber, non-
blocking) vs failed (red) treatment; advisory_failure counts as complete.

Plan U3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:48:50 -07:00
gsxdsm
4cc9c2f3f1 FN-6972: add browser-native file previews
Files modal now renders common media and PDF files with browser-native previews while preserving editor flows for text and unknown binaries.

- Add shared extension-based preview classification for images, videos, audio, and PDFs.
- Render preview-only files from workspace-safe download URLs and skip binary editor loading/saving actions for those selections.
- Update preview styling, localized labels, documentation, tests, and release notes.

Files changed:
 .changeset/fn-6972-browser-file-previews.md        |   7 +
 docs/dashboard-guide.md                            |   1 +
 packages/dashboard/app/components/FileBrowser.css  |  39 ++-
 .../dashboard/app/components/FileBrowserModal.tsx  | 107 +++++---
 .../components/__tests__/FileBrowserModal.test.tsx | 302 ++++++++++-----------
 .../app/utils/__tests__/file-preview-kind.test.ts  |  40 +++
 packages/dashboard/app/utils/file-preview-kind.ts  |  70 +++++
 packages/i18n/locales/en/app.json                  |   4 +-
 packages/i18n/locales/es/app.json                  |   4 +-
 packages/i18n/locales/fr/app.json                  |   4 +-
 packages/i18n/locales/ko/app.json                  |   4 +-
 packages/i18n/locales/zh-CN/app.json               |   4 +-
 packages/i18n/locales/zh-TW/app.json               |   4 +-
 13 files changed, 381 insertions(+), 209 deletions(-)

Fusion-Task-Id: FN-6972

Fusion-Task-Lineage: 04b07def-e490-43f7-8b92-39ca704b20b6
2026-06-25 12:25:13 -07:00
gsxdsm
4fd8d444fb fix(dashboard): polish app chrome and workflow defaults 2026-06-22 18:21:06 -07:00
gsxdsm
03aeed291f feat(dashboard): Import Tasks list pane small + freely resizable, preview fills remainder
Default list width 256px (min 160, max min(480px,50%)), driven by an inline width var with flex:0 0 so the drag actually wins (the embedded wide layout previously forced a clamp via !important, so the handle did nothing). Preview pane is flex:1 1 auto;min-width:0 so freed space flows to it. Persisted per-project via kb-dashboard-github-import-list-width. Shared workspace covers both Issues and Pull Requests tabs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 10:09:32 -07:00
gsxdsm
a6f49b847c feat(dashboard): integrate stashed workflow-selection refactor; Dashboard rename; resolve CC conflicts
- Resolve the stash-pop conflicts in command-center CSS/test by keeping the current branch's newer FN-6784 responsive clamps, Team heartbeat docs, and recharts assertions (the stashed snapshot was older).
- Land the stashed workflow-selection refactor (Board/NewTaskModal/WorkflowSwitcher; remove lastSelectedWorkflow util).
- Rename Command Center -> Dashboard (i18n source) and move it to the top of the left sidebar; workflow switcher chevron sized to match the project selector.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 03:34:15 -07:00
gsxdsm
c0ab7f43b8 FN-6923: default new tasks to the selected workflow lane
New Task now inherits the project's current or last valid workflow lane.

- Persist explicit Board and List workflow switcher selections per project.
- Seed the New Task workflow selector from the cached valid lane without marking the pristine dialog dirty.
- Preserve default-workflow inheritance when no remembered lane exists or the remembered lane was deleted.
- Cover quick-add parity, workflow defaulting, stale-lane fallback, and storage helper behavior in tests.
- Document New Task workflow selector defaulting in the dashboard guide.

Files changed:
 docs/dashboard-guide.md                            |   2 +
 packages/dashboard/app/components/Board.tsx        |  12 +-
 packages/dashboard/app/components/ListView.tsx     |  12 +-
 packages/dashboard/app/components/NewTaskModal.tsx |  21 ++-
 .../app/components/__tests__/NewTaskModal.test.tsx | 142 ++++++++++++++++++++-
 .../utils/__tests__/lastSelectedWorkflow.test.ts   |  67 ++++++++++
 .../dashboard/app/utils/lastSelectedWorkflow.ts    |  31 +++++
 7 files changed, 279 insertions(+), 8 deletions(-)

Fusion-Task-Id: FN-6923
Fusion-Task-Lineage: 6e3c8efd-3865-4975-a754-2f0d5ff89ab0
2026-06-22 03:34:15 -07:00
gsxdsm
c808177979 FN-6776: prevent workflow board legacy flash
Prevent workflow-enabled board surfaces from flashing the legacy layout during first paint.

- Hydrate Board and ListView workflow metadata from a per-project session cache before async revalidation.
- Gate legacy board/list rendering behind settings and workflow-lane metadata readiness, with neutral skeleton states for cold or empty workflow loads.
- Add regression coverage for no-legacy-flash behavior and cache validation, plus docs and changeset notes.

Files changed:
 .changeset/fn-6776-board-flash.md                  |   5 +
 docs/dashboard-guide.md                            |   1 +
 packages/dashboard/app/App.tsx                     |   4 +
 packages/dashboard/app/components/Board.css        |  69 +++++
 packages/dashboard/app/components/Board.tsx        |  53 +++-
 packages/dashboard/app/components/ListView.css     |  53 ++++
 packages/dashboard/app/components/ListView.tsx     |  52 +++-
 .../__tests__/board-no-legacy-flash.test.tsx       | 326 +++++++++++++++++++++
 .../utils/__tests__/boardWorkflowsCache.test.ts    |  71 +++++
 .../dashboard/app/utils/boardWorkflowsCache.ts     |  49 ++++
 10 files changed, 676 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-6776

Fusion-Task-Lineage: caa8e53f-9b6d-49a6-94ca-b694550b43ef
2026-06-20 15:42:16 -07:00
gsxdsm
c4f34ceed1 FN-6767: make agents sidebar resizable
Make the Agents split view wider by default and persist user-adjusted sidebar widths.

- Add a desktop/tablet resize handle with pointer and keyboard controls, clamped accessible values, and per-project storage.\n- Update split-layout CSS so mobile remains stacked while non-mobile views reserve a resize affordance column.\n- Cover default, stored, clamped, pointer, keyboard, mobile, and org-chart sidebar behaviors in tests.\n- Add a patch changeset for the published Fusion package.\n\nFiles changed:\n .changeset/fn-6767-agents-sidebar.md               |   5 +\n packages/dashboard/app/components/AgentsView.css   |  47 ++++++--\n packages/dashboard/app/components/AgentsView.tsx   | 101 +++++++++++++++-\n .../app/components/__tests__/AgentsView.test.tsx   | 132 +++++++++++++++++++++\n .../app/utils/__tests__/projectStorage.test.ts     |   3 +-\n packages/dashboard/app/utils/projectStorage.ts     |   1 +\n 6 files changed, 280 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-6767

Fusion-Task-Lineage: 93605e16-7524-4577-bbcd-666c105a867b
2026-06-20 02:25:11 -07:00
gsxdsm
11c4120705 FN-6659: keep xterm font metrics symbols-free
Keep terminal wide-glyph fallback out of xterm's measured font path while preserving Nerd Font symbols in DOM rendering.

- Split terminal font resolution into symbols-free xterm font families and scoped glyph fallback families.
- Apply the glyph fallback CSS variable to both TerminalModal and SessionTerminal surfaces.
- Update regression coverage and the documented mobile xterm wide-glyph recurrence analysis.

Files changed:
 .changeset/fn-6659-terminal-render.md              |  5 +++
 .../xterm-symbols-nerd-font-unicode-range.md       | 22 +++++++-----
 .../dashboard/app/__tests__/terminal-input.test.ts | 42 +++++++++++++---------
 .../dashboard/app/components/SessionTerminal.css   |  8 +++++
 .../dashboard/app/components/SessionTerminal.tsx   | 21 +++++++++--
 .../dashboard/app/components/TerminalModal.css     |  8 +++++
 .../dashboard/app/components/TerminalModal.tsx     | 13 ++++++-
 .../__tests__/SessionTerminal.mobile.test.tsx      |  6 ++--
 .../components/__tests__/SessionTerminal.test.tsx  | 14 ++++----
 .../components/__tests__/TerminalModal.test.tsx    |  9 +++--
 .../utils/__tests__/terminalPreferences.test.ts    |  2 +-
 .../dashboard/app/utils/terminalPreferences.ts     | 16 +++++----
 12 files changed, 117 insertions(+), 49 deletions(-)

Fusion-Task-Id: FN-6659

Fusion-Task-Lineage: e29a709d-9d9d-4a90-9616-8f08c41b126d
2026-06-18 15:59:34 -07:00
gsxdsm
16b6e5decb FN-6638: stabilize mobile terminal font metrics
Stabilize terminal font metric remeasurement across mobile and attach surfaces.

- Add a shared terminal font metric wait helper that falls back from full font stacks to concrete individual font families before remeasurement.
- Reapply font options, refit, resize, and refresh SessionTerminal after font metrics settle to cover attached CLI terminals.
- Pin text-size adjustment on xterm measurement subtrees so mobile WebKit cannot inflate ASCII cell metrics.
- Extend terminal preference and rendering tests, documentation, and changeset coverage for the recurrence.

Files changed:
 .changeset/fn-6638-terminal-render.md              |   5 +
 .../xterm-async-font-remeasure-paste-dedupe.md     |  20 +++-
 .../dashboard/app/__tests__/terminal-input.test.ts |  26 +++++
 .../dashboard/app/components/SessionTerminal.css   |  10 ++
 .../dashboard/app/components/SessionTerminal.tsx   |  29 ++++++
 .../dashboard/app/components/TerminalModal.css     |  10 ++
 .../dashboard/app/components/TerminalModal.tsx     |  24 ++---
 .../components/__tests__/SessionTerminal.test.tsx  |  41 +++++++-
 .../components/__tests__/TerminalModal.test.tsx    |  38 ++++++++
 .../utils/__tests__/terminalPreferences.test.ts    |  29 +++++-
 .../dashboard/app/utils/terminalPreferences.ts     | 107 +++++++++++++++++++++
 11 files changed, 319 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-6638

Fusion-Task-Lineage: edbf071d-a0c1-4955-95ff-83e6996f4674
2026-06-18 13:19:43 -07:00
gsxdsm
ca14a12b94 FN-6601: consolidate relative-time bucket formatting
Consolidate dashboard relative-time calculations behind a shared bucket helper while preserving each surface's display behavior.

- Add getRelativeTimeBucket to centralize parsing, boundary math, and bucket metadata.
- Route ActivityFeed, AgentLogViewer, MissionManager, and PlanningModeModal timestamp labels through the shared helper.
- Extend unit coverage for bucket boundaries plus surface-specific just-now and future timestamp behavior.

Files changed:
 packages/dashboard/app/components/ActivityFeed.tsx | 36 ++++++----
 .../dashboard/app/components/AgentLogViewer.tsx    | 36 ++++++----
 .../dashboard/app/components/MissionManager.tsx    | 32 +++++----
 .../dashboard/app/components/PlanningModeModal.tsx | 35 ++++++----
 .../app/components/__tests__/ActivityFeed.test.tsx |  8 +++
 .../components/__tests__/AgentLogViewer.test.tsx   |  8 +++
 .../app/utils/__tests__/relativeTimeAgo.test.ts    | 77 +++++++++++++++++++++-
 packages/dashboard/app/utils/relativeTimeAgo.ts    | 66 +++++++++++++++----
 8 files changed, 236 insertions(+), 62 deletions(-)

Fusion-Task-Id: FN-6601

Fusion-Task-Lineage: 3521afa0-f3ce-49a4-8861-efd4f64f9a69
2026-06-17 17:57:19 -07:00
gsxdsm
01b80db603 FN-6589: add structured ask-question chat tool
Add a native chat-agent tool for presenting structured questions to dashboard users.

- Register `fn_ask_question` for dashboard chat sessions with prompt guidance to wait for user replies.
- Reuse the existing structured question card parser by recognizing the new tool name.
- Validate ask-question parameters in engine tooling and cover chat/parser behavior with tests.
- Document the dashboard chat question flow and add a patch changeset.

Files changed:
 .changeset/fn-6589-chat-ask-question.md            |  5 ++
 docs/dashboard-guide.md                            |  3 +-
 .../utils/__tests__/parseQuestionToolCall.test.ts  | 19 +++++
 .../dashboard/app/utils/parseQuestionToolCall.ts   |  3 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   | 10 ++-
 packages/dashboard/src/chat.ts                     | 10 ++-
 .../src/__tests__/agent-tools-ask-question.test.ts | 51 ++++++++++++
 packages/engine/src/agent-tools.ts                 | 94 ++++++++++++++++++++++
 packages/engine/src/index.ts                       |  2 +
 9 files changed, 190 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-6589
Fusion-Task-Lineage: 3f416010-ed2f-40b3-a899-7a9f4a6ed265
2026-06-17 16:53:29 -07:00
gsxdsm
c261217ac1 FN-6597: add task chat timestamps
Show compact relative timestamps in task chat without adding live polling.

- Add a shared relative-time formatter for chat timestamps.
- Render muted timestamps on user message headers and agent group metadata.
- Cover timestamp formatting and chat header rendering with dashboard tests.
- Document task chat timestamp behavior in the dashboard guide.

Files changed:
 docs/dashboard-guide.md                            |  2 +-
 packages/dashboard/app/components/TaskChatTab.css  | 19 +++++
 packages/dashboard/app/components/TaskChatTab.tsx  | 23 ++++-
 .../app/components/__tests__/TaskChatTab.test.tsx  | 97 +++++++++++++++++++++-
 .../app/utils/__tests__/relativeTimeAgo.test.ts    | 32 +++++++
 packages/dashboard/app/utils/relativeTimeAgo.ts    | 23 +++++
 6 files changed, 192 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-6597

Fusion-Task-Lineage: 52c54a9e-6d00-4df1-a454-2218a935ebda
2026-06-17 16:21:54 -07:00