Unifies OAuth expiry detection so expired Claude subscription logins correctly show as disconnected with a re-login prompt, and adds a proactive engine-side scheduler that refreshes tokens before they expire.
- Share expiry-detection logic between OAuthExpiryMonitor and the /api/auth/status route so both agree on when a token is expired.
- Add engine-side oauth-refresh-scheduler that proactively refreshes OAuth tokens ahead of expiry, wired into project-engine (guarded by skipNotifier).
- Extend auth-storage with the helpers needed for expiry checks/refresh.
- Add tests covering routes-auth status detection, auth-storage expiry helpers, and the new refresh scheduler.
- Document the new behavior in dashboard-guide.md and settings-reference.md.
- Add changeset for the user-facing fix.
Files changed:
.../fn-7574-oauth-expiry-detection-refresh.md | 7 +
docs/dashboard-guide.md | 4 +
docs/settings-reference.md | 4 +
.../dashboard/src/__tests__/routes-auth.test.ts | 76 +++++++++++
.../dashboard/src/routes/register-auth-routes.ts | 25 +++-
packages/engine/src/__tests__/auth-storage.test.ts | 60 +++++++++
packages/engine/src/auth-storage.ts | 14 +-
.../__tests__/oauth-refresh-scheduler.test.ts | 141 ++++++++++++++++++++
packages/engine/src/notification/index.ts | 3 +
.../src/notification/oauth-refresh-scheduler.ts | 143 +++++++++++++++++++++
packages/engine/src/project-engine.ts | 14 +-
11 files changed, 488 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7574
Fusion-Task-Lineage: 59996eac-c070-4992-9727-d066c6934b69
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Relocates the FN-7519 Intervention Timeline out of the inline oversight cluster and into the task Activity view as a fourth selectable segment.
- Add `interventions` to the `ActivitySegment` union and gate its dropdown option on the same oversight-active expression previously used by the inline mount
- Render `PlannerInterventionTimeline` in a new Activity segment panel instead of inline next to the oversight controls
- Fall back to the Live segment automatically if oversight turns off (or was never resolved) while Interventions is selected, avoiding an orphaned selection
- Update oversight-controls and task-activity-chat tests to cover the new dropdown segment and removed inline mount
- Add changeset and update dashboard guide docs
Files changed:
...7571-intervention-timeline-activity-dropdown.md | 7 +
docs/dashboard-guide.md | 4 +-
.../dashboard/app/components/TaskDetailModal.tsx | 49 ++++---
.../TaskDetailModal.oversight-controls.test.tsx | 148 +++++++++++++++++++++
.../TaskDetailModal.task-activity-chat.test.tsx | 7 +-
5 files changed, 195 insertions(+), 20 deletions(-)
Fusion-Task-Id: FN-7571
Fusion-Task-Lineage: 331a1b32-5712-4583-9777-e36ff5cc3ffc
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the mobile oversight overflow menu rendering two overlapping menus by narrowing auto-focus to actionable button menuitems.
- Change the menu-open auto-focus effect to query `button.detail-oversight-menu-item` instead of matching any `.detail-oversight-menu-item` element, since the native level `<select>` also carried that class and was matched first.
- Programmatically focusing the native `<select>` triggered its OS option picker, which rendered as a second overlapping menu on top of the custom `role="menu"` popover.
- Add regression tests covering: auto-focus landing on the first button menuitem when nudge/stop/explain are available, no fallback focus on the select when oversight is off (level-only state), and confirming the desktop inline select is unaffected.
- Update dashboard-guide.md docs to describe the fixed auto-focus behavior.
Files changed:
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/TaskDetailModal.tsx | 3 +-
.../app/components/__tests__/TaskDetailModal.oversight-mobile.test.tsx | 96 ++++++++++++++++++++++
3 files changed, 99 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-7562
Fusion-Task-Lineage: f39068f1-811f-4663-ade1-ff020a389ae5
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Add a visible group label and an in-DOM disabled-reason helper to the task-detail oversight controls so the Nudge/Explain cluster is no longer confusing when greyed out, and make Explain always-openable since it is read-only.
- Add a `detail-oversight-controls-label` group label above the Nudge/Stop/Explain buttons, gated by the same visibility condition as the buttons (mobile and desktop clusters)
- Add a `detail-overseer-nudge-disabled-reason` in-DOM helper line explaining why Nudge is unavailable, instead of relying only on a hover title
- Remove the disabled gate from Explain (it's read-only/non-mutating) and update its title copy to reflect that it always opens and shows last-known state when inactive
- Add regression tests covering the new label/helper text and Explain's always-enabled behavior
- Add a patch changeset and a docs/dashboard-guide.md note
Files changed:
.changeset/FN-7546-oversight-controls-clarity.md | 7 +++
docs/dashboard-guide.md | 2 +
.../dashboard/app/components/TaskDetailModal.css | 42 +++++++++++++
.../dashboard/app/components/TaskDetailModal.tsx | 41 +++++++++++--
.../TaskDetailModal.oversight-controls.test.tsx | 69 ++++++++++++++++++++++
5 files changed, 157 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7546
Fusion-Task-Lineage: d1f342ea-2de0-4b54-9930-9b3d540c7af6
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a mobile-friendly overflow menu for the task-detail planner-overseer controls, keeping the desktop inline cluster unchanged.
- Below 768px, replace the inline oversight-level select/nudge/stop/explain controls with a single "Oversight" overflow-menu trigger (MoreVertical icon, aria-haspopup="menu") mirroring the existing move-action dropdown pattern
- Popover lists the same controls as full-width, tappable role="menuitem" entries with identical testids and enablement/visibility rules as desktop
- Trigger is withheld entirely when no controls would render (no empty-shell button)
- Desktop (>768px) inline cluster is unchanged
- Adds TaskDetailModal.oversight-mobile.test.tsx covering trigger visibility, menu contents, and parity with desktop controls
- Updates docs/dashboard-guide.md to document the mobile overflow-menu behavior
Files changed:
docs/dashboard-guide.md | 2 +
packages/dashboard/app/components/TaskDetailModal.css | 118 ++++++
packages/dashboard/app/components/TaskDetailModal.tsx | 383 ++++++++++++++-----
packages/dashboard/app/components/__tests__/TaskDetailModal.oversight-mobile.test.tsx | 413 +++++++++++++++++++++
packages/dashboard/app/components/__tests__/TaskDetailModal.test-helpers.ts | 2 +
5 files changed, 830 insertions(+), 88 deletions(-)
Fusion-Task-Id: FN-7545
Fusion-Task-Lineage: 63cb778e-f17d-43d3-a3de-864683d4e8f1
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Removes the recently-added executor/reviewer/merger overseer-state chip from TaskCard, which fired as noise on nearly every in-progress card, keeping the separate oversight-level badge untouched.
- Deletes deriveOverseerCardWatchedStage and its OVERSEER_STATE_LABEL/MODIFIER maps from TaskCard.tsx
- Removes showOverseerStateBadge gating and its contribution to hasCardMetaBadges/areTaskCardPropsEqual
- Strips the now-unused .task-card-overseer-state-badge CSS rules from TaskCard.css
- Rewrites TaskCard.oversight.test.tsx to drop overseer-state-badge coverage while keeping oversight-level badge tests
- Updates docs/dashboard-guide.md reference and adds a changeset documenting the removal
Files changed:
.changeset/fn-7542-remove-overseer-state-badge.md | 7 +
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/TaskCard.css | 63 +-------
packages/dashboard/app/components/TaskCard.tsx | 161 +++------------------
.../__tests__/TaskCard.oversight.test.tsx | 149 +++++++------------
5 files changed, 77 insertions(+), 305 deletions(-)
Fusion-Task-Id: FN-7542
Fusion-Task-Lineage: dabaf72a-a7b0-4054-8a72-7c3d99fa7bb1
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Prevent the Auto-recovery/oversight badge from rendering on virtually every task card when the effective planner oversight level is just the inherited schema default.
- TaskCard: track whether the effective oversight level was reached purely via inheritance (no per-task override, no explicit non-default workflow tier), and suppress the badge in that case
- Preserve badge visibility when a task explicitly overrides oversight to "autonomous" or a workflow tier explicitly resolves to a non-default level
- Update TaskCard oversight tests to cover inherited-default suppression vs explicit-override rendering
- Add changeset documenting the fix
- Update dashboard guide docs
Files changed:
.changeset/fn-7539-oversight-badge-default.md | 7 ++++
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/components/TaskCard.tsx | 21 +++++++++-
.../__tests__/TaskCard.oversight.test.tsx | 48 +++++++++++++++++++---
.../app/components/__tests__/TaskCard.test.tsx | 11 +++--
5 files changed, 76 insertions(+), 14 deletions(-)
Fusion-Task-Id: FN-7539
Fusion-Task-Lineage: 8ac9a60c-69c6-4095-b6b2-18c79718b62b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Introduces a persisted planner-overseer intervention timeline surfaced in the task-detail Planner Oversight cluster, recording stage, reason, action taken, outcome, attempt count/limit, and source links for each intervention.
- Add core `PlannerInterventionEntry` type plus `recordPlannerIntervention`/`getPlannerInterventionTimeline` helpers that persist entries via the run-audit store under the `overseer:intervention` mutation
- Add `PlannerInterventionTimeline` dashboard component rendering the timeline (stage/reason/action/outcome/attempts/links) with associated styles
- Wire the new API route/legacy handler and TaskDetailModal integration to expose and render the timeline
- Add unit tests for the core helpers and the new UI component
- Add changeset for the new minor feature and update architecture/dashboard-guide docs
Files changed:
$(cat /tmp/diffstat_7519.txt)
Fusion-Task-Id: FN-7519
Fusion-Task-Lineage: 3c4fcda3-9eb2-46d3-b142-b0c7d6334cd0
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Route window resize/orientationchange/scroll through the same opening-viewport guard used by visualViewport so a same-gesture echo repositions the Activity menu instead of closing it, fixing the dropdown not showing on mobile.
- Add handleGuardedViewportChange shared by resize/orientationchange/visualViewport listeners so an opening-gesture echo only repositions the menu instead of closing it
- Add handleScrollChange to treat scrolls originating inside the .detail-tabs horizontal tab strip as benign (reposition-only), since window scroll listens with capture and would otherwise see nested scroller scrolls as a close signal
- Add regression tests covering mobile Activity dropdown open/scroll/resize behavior
- Add changeset for the fix
- Update dashboard guide docs
Files changed:
.changeset/fn-7536-activity-dropdown-mobile.md | 7 +
docs/dashboard-guide.md | 1 +
.../dashboard/app/components/TaskDetailModal.tsx | 38 +++--
.../TaskDetailModal.task-activity-chat.test.tsx | 161 +++++++++++++++++++++
4 files changed, 196 insertions(+), 11 deletions(-)
Fusion-Task-Id: FN-7536
Fusion-Task-Lineage: c8a3b11e-9bd2-4a61-b49e-038c93cfe4d2
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Branch-group completion no longer silently drops archived-but-unlanded members, which previously let genuinely-incomplete groups be flagged complete and promoted.
- listTasksByBranchGroup now scans with includeArchived:true so archived members stay counted in the group's total instead of dropping out silently
- ArchivedTaskEntry gains a persisted mergeDetails snapshot so an archived member that had already landed is still distinguished from one that never landed
- store.ts archival paths (task->archive projection) now carry mergeDetails through so isBranchGroupMemberLanded keeps working post-archival
- Added regression coverage in branch-group-store.test.ts and group-merge-coordinator.test.ts for archived-landed and archived-unlanded gating
- Added changeset documenting the fix as a patch-level bug fix
Files changed:
.changeset/fn-7534-branch-group-archived-member.md | 7 +
docs/dashboard-guide.md | 2 +
packages/core/src/__tests__/branch-group-store.test.ts | 77 +++++++++++
packages/core/src/store.ts | 30 ++++-
packages/core/src/types.ts | 11 ++
packages/engine/src/__tests__/group-merge-coordinator.test.ts | 148 ++++++++++++++++++++-
6 files changed, 273 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-7534
Fusion-Task-Lineage: 510af857-ce08-49a0-a2a1-41b3ad473804
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds two display-only badges to TaskCard so operators can see planner oversight configuration and live overseer activity at a glance.
- Resolve and display the workflow's effective `plannerOversightLevel` (observe/steer/autonomous) per task, with a module-level cache keyed by (projectId, workflowId) and in-flight de-duplication to avoid redundant `/api/workflows/:id/setting-values` fetches across cards sharing a workflow.
- Gate oversight badge rendering until the workflow-effective value resolves (or a per-task override is known) so the very first render never shows a guessed schema-default badge.
- Derive a card-local "active overseer state" indicator (Executor/Reviewer/Merger/Pull request/Workflow gate) that mirrors the engine's `resolveWatchedStage` precedence using only fields already present on the Task payload (column, paused, pausedReason, prInfo, reviewState, workflowTransitionNotification), since the real in-memory monitor state has no persisted/API surface today.
- Add corresponding CSS badge modifiers and update dashboard-guide.md documentation.
- Add TaskCard.oversight.test.tsx covering the new badges and update existing TaskCard tests/badge-wrap test for the new markup.
Files changed:
docs/dashboard-guide.md | 4 +
packages/dashboard/app/components/TaskCard.css | 106 +++++-
packages/dashboard/app/components/TaskCard.tsx | 369 +++++++++++++++++++-
.../__tests__/TaskCard.badge-wrap.test.tsx | 1 +
.../__tests__/TaskCard.oversight.test.tsx | 383 +++++++++++++++++++++
.../app/components/__tests__/TaskCard.test.tsx | 32 +-
6 files changed, 889 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-7516
Fusion-Task-Lineage: ce909409-862b-4697-a19e-d6735a3b572d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Keep the task-detail Activity view picker usable during mobile iOS opening taps.
- Add a short visualViewport opening guard for the root-portaled Activity views menu while preserving normal close behavior afterward.
- Reset menu position and guard state consistently on outside click, Escape, selection, task changes, and tab toggles.
- Cover the iOS visualViewport echo, portal/CSS contract, and documentation plus a patch changeset.
Files changed:
.changeset/activity-menu-ios.md | 7 +
docs/dashboard-guide.md | 3 +-
.../dashboard/app/components/TaskDetailModal.tsx | 68 +++++++---
.../__tests__/TaskDetailModal.css.test.ts | 9 +-
.../TaskDetailModal.task-activity-chat.test.tsx | 141 ++++++++++++++++++++-
5 files changed, 210 insertions(+), 18 deletions(-)
Fusion-Task-Id: FN-7485
Fusion-Task-Lineage: 291331c4-453c-481b-b991-41f57db23e3b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Mobile direct-chat dropdowns now identify sessions by conversation title instead of model-name text.
- Render the mobile session trigger with the conversation title or Untitled while preserving the provider logo.
- Remove mobile trigger model-tag styling and assert the model badge stays out of the compact header.
- Document the mobile Chat dropdown behavior and add a patch changeset for the published CLI package.
Files changed:
.changeset/fn-7462-mobile-chat-dropdown-title.md | 7 ++++
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/ChatView.css | 8 -----
packages/dashboard/app/components/ChatView.tsx | 8 +++--
.../__tests__/ChatView.core-contracts.test.tsx | 25 +++++++++++---
.../components/__tests__/ChatView.mobile.test.tsx | 39 +++++++++++++++++++++-
6 files changed, 72 insertions(+), 17 deletions(-)
Fusion-Task-Id: FN-7462
Fusion-Task-Lineage: 6a6e2ac3-ecca-4076-81c5-b4e4a65eb286
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Keep the mobile direct-chat header on a single left-aligned row without losing accessible context.
- Hide the direct-chat ViewHeader title shell from layout while preserving the accessible Chat heading.
- Keep the back button first and the active session switcher beside it on a non-wrapping mobile row.
- Extend mobile chat coverage for long duplicate session titles, Bot fallback labels, and the CSS layout contract.
- Document the updated mobile Chat header behavior and add a patch changeset.
Files changed:
.changeset/fn-7455-mobile-chat-header-layout.md | 7 ++
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/ChatView.css | 17 +++--
packages/dashboard/app/components/ChatView.tsx | 4 +-
.../components/__tests__/ChatView.mobile.test.tsx | 80 ++++++++++++++++++++--
5 files changed, 98 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7455
Fusion-Task-Lineage: fe14b542-ff6a-437b-ad89-8011c2b3c299
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Collapse the mobile direct chat header into the shared top row.
- Move the mobile direct-thread back button and session switcher into ViewHeader actions.
- Hide the redundant mobile thread header while preserving desktop thread identity and context details.
- Update mobile chat styling, docs, changeset, and header contract tests for the single-row layout.
Files changed:
.changeset/fn-7450-mobile-chat-header.md | 7 +
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/components/ChatView.css | 53 +++++-
packages/dashboard/app/components/ChatView.tsx | 197 +++++++++++----------
.../__tests__/ChatView.core-contracts.test.tsx | 48 ++---
.../components/__tests__/ChatView.mobile.test.tsx | 76 ++++++--
6 files changed, 256 insertions(+), 128 deletions(-)
Fusion-Task-Id: FN-7450
Fusion-Task-Lineage: c266a9b8-7fb1-410e-9c35-adad4c6a2d47
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Return successful GitHub issue import and close flows to the issue list.
- Clear the selected GitHub issue and switch mobile preview back to the list after successful import or close actions.
- Preserve the selected preview on failures so users can retry with the existing error affordance.
- Add regression coverage for desktop and mobile import/close success and failure navigation states.
- Document the post-import list reset behavior and add a patch changeset.
Files changed:
.changeset/fn-7442-github-import-return-list.md | 7 +
docs/dashboard-guide.md | 2 +-
.../dashboard/app/components/GitHubImportModal.tsx | 20 +-
.../__tests__/GitHubImportModal.test.tsx | 210 +++++++++++++++++++--
4 files changed, 218 insertions(+), 21 deletions(-)
Fusion-Task-Id: FN-7442
Fusion-Task-Lineage: e334a7c1-68de-48f7-be31-b036ba741685
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>