- Add CLI support for task node routing with create --node, task set-node, and task clear-node commands
- Extend settings command validation/output for defaultNodeId and unavailableNodePolicy and document new keys
- Surface task routing details in CLI task show plus dashboard Routing tab status/binding reason indicators
- Enhance Settings modal node routing UX with selected-node health status and add/refresh tests and changeset
- Add list view node status indicator styles for bulk edit controls
- Remove duplicated memory dream trigger test blocks introduced during conflict resolution
- Keep dashboard test suite deterministic by retaining a single canonical memory dream trigger describe
- Replace split move control with a single move button that supports primary action plus arrow-zone menu toggling
- Add keyboard support for move options via ArrowDown to open and Escape to close and refocus the trigger
- Update task detail styling for the unified move button and arrow affordance states
- Refresh TaskDetailModal and TaskForm tests to cover the new move control behavior and preset selection query
- Extend batch task update APIs and route handlers to accept nodeId overrides alongside model settings
- Update ListView bulk edit UX to load nodes and apply node overrides through batch updates
- Add node routing visibility improvements in task detail/settings UI and align related labels/styles
- Expand dashboard/API test coverage for node override batch updates and bulk edit behavior
- Redesign the task Routing tab with effective-node summary rows, unhealthy node signaling, and direct per-task override selection
- Add robust override update handling (loading/saving states, stale-task guards, clear override action, and in-progress lock messaging)
- Extend TaskCard execution time indicator behavior to in-review cards and add focused regression coverage
- Refresh dashboard tests and styling for routing and node-status presentation, and remove an unused remote settings API import
- Add a reusable ProjectNodeSelector component and hook RoutingTab to it for per-task node overrides
- Move default node and unavailable-node policy controls into the dedicated Node Routing settings section
- Add descriptive routing guidance text and project-level note in SettingsModal
- Expand dashboard tests for routing tab behavior and node routing settings UX
- Remove the separate "Activate Provider" action from SettingsModal and rely on save-only provider configuration
- Ensure saving remote settings enables the selected active provider and keeps provider flags consistent
- Seed remoteAccess defaults in remote settings routes when project settings are missing instead of returning conflicts
- Expand dashboard tests to cover first-use/default remote settings behavior and updated provider lifecycle expectations
- Move the check-for-updates refresh button into the settings header actions group for consistent placement
- Keep update check behavior unchanged, including loading state, disabled state, and aria labeling
- Set the refresh icon size explicitly to match surrounding header controls
- Simplify mobile CSS by removing obsolete settings-update-check wrap overrides
- Add formatElapsedDurationDone to render done task elapsed time with ceiling-based minute/hour/day rounding
- Keep in-progress time indicator logic on existing floor-based formatElapsedDuration behavior
- Route done-card time indicator rendering through the new done-specific formatter
- Expand TaskCard tests to cover done rounding semantics and preserve in-progress rounding expectations
- Reset merge metadata, verification counters, and workflow results when tasks move from in-review/done back to in-progress
- Reopen verification-related steps (or the last step fallback) so re-verification runs from a pending state
- Add execute-time guard to clear stale mergeDetails on in-progress tasks before continuing
- Prevent resumeOrphaned fast-path recovery when completed in-progress tasks still carry merge metadata
- Add targeted executor and TaskForm tests covering FN-2883 regression paths
- Add planning-module documentation explaining current ntfy helper flow and future NotificationService migration
- Detect NotificationService export availability during helper initialization and emit diagnostic info logging
- Add regression test coverage that verifies planning notifications still use ntfy helper functions when NotificationService is present
- Preserve planning awaiting-input notification behavior and click URL/event gating expectations
- Wire onRetryTask from App through Board/Column/WorktreeGroup/ListView into TaskCard
- Add a Retry button with loading/disabled state to failed task error boxes in TaskCard
- Update failed-card styles to use design tokens and add retry button visual states
- Add TaskCard tests covering retry visibility, callback invocation, loading, and error toast behavior
- Add a patch changeset for @runfusion/fusion documenting the dashboard retry shortcut
- Assert default-model auto-selection initializes a model session with project-scoped context
- Verify quick chat input stays disabled until default-model session bootstrap completes
- Add parity coverage for default-model initialization when agents are present
- Allow session initialization to retry when the same target key is selected but no active session exists
- Gate duplicate-init short-circuit behind activeSession/sessionsLoading so model-mode startup can recover
- Expand the effect dependency list to track session readiness inputs used by the retry guard
- Add node status indicators and labels to task creation, quick entry, task form, and settings node selectors
- Surface selected node health in list bulk-edit controls with status dot styling for online/connecting/offline/error states
- Update dashboard component CSS and shared styles for consistent node status presentation
- Include changeset documenting unavailable-node routing policy and default node behavior
Subtask, mission-interview, and milestone/slice-interview sessions could pin
their `generating` state forever when the underlying provider stream stalled
silently or a tool call hung. Wrap each `agent.session.prompt()` in a new
GenerationGuard helper (per-session AbortController + timer) so a stuck turn
becomes a bounded error users can retry. Adds matching `stop*Generation`
exports and threads abort through cleanup so dismissing a modal cancels the
in-flight call instead of leaking it.
Also closes the gh-cli tool hang vector: `runGhAsync` / `runGhJsonAsync` now
accept `{ signal, timeoutMs }` (default 30s). Github-touching extension tools
forward the AI tool's signal so an aborted agent kills the `gh` child instead
of orphaning it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a dependency task merges and its branch is deleted, self-healing nulls
the dependent task's baseBranch. Both resolveDiffBase (dashboard) and
resolveTaskDiffBaseRef (merger) defaulted to "main" in that case, widening
the diff range to merge-base(HEAD, main) and surfacing unrelated history —
e.g. FN-2855 reported 108 changed files instead of 16. Skip the merge-base
step when baseBranch is unset and a baseCommitSha is recorded; fall back to
"main" only for legacy tasks lacking both hints.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add an effective node resolver with task override, project default, and local fallback precedence.
- Wire scheduler dispatch to persist effectiveNodeId/effectiveNodeSource and log resolved node routing.
- Add coverage for effective node resolution and scheduler node routing integration behavior.
- Stabilize workspace test resolution by adding @fusion/core and @fusion/plugin-sdk aliases across Vitest configs.
- Tighten background task indicator pill padding to reduce vertical footprint
- Lower line-height to keep icon/text alignment after the size reduction
- Reduce mobile min-height so the footer pill no longer appears oversized
- Add ProjectEngine memory dreams wiring tests for startup ordering, settings-change resync, and unrelated-setting no-op behavior
- Cover degraded-mode startup and settings-update failure paths to ensure sync errors are logged without stopping the engine
- Extend MemoryView Dream Now tests for success, failure toast handling, and disabled loading-state behavior
- Add POST /api/memory/dream route that runs project and agent dream processing with AI prompt execution
- Expose triggerMemoryDreams() in dashboard legacy API client for direct dream invocation
- Switch SettingsModal and useMemoryData Dream Now actions from automation lookup to the new endpoint
- Update dashboard route, hook, and settings modal tests to cover success and error handling
- Add a patch changeset for @runfusion/fusion documenting the new endpoint and client helper
- Extend /models API responses to include optional defaultProvider/defaultModelId from global settings, including empty and error paths
- Update QuickChatFAB to prefer the configured default model on load and fall back to first-model selection only when no agents exist
- Move quick chat model tag/title-wrap inline styles into QuickChatFAB.css using dashboard design tokens
- Add QuickChatFAB tests covering default-model auto-selection with and without agents and legacy behavior when no default is configured
- Add a Learn more link to the update-available banner alongside release notes
- Refactor SettingsModal update-result rendering into a shared helper and include the infusion.ai link when updates exist
- Add dedicated SettingsModal link styling with hover and focus-visible states using dashboard tokens
- Update banner and settings tests to assert the new Learn more link behavior
- Add a patch changeset for @runfusion/fusion documenting the update notice link addition
- Add dedicated styles for the workflow result expand icon button with token-based sizing and alignment
- Add hover and focus-visible states for clearer interaction feedback and keyboard accessibility
- Increase mobile touch target sizing for both workflow edit and expand toggles using design tokens
- Add global `touch-action: manipulation` on html/body to reduce gesture-triggered zoom
- Set mobile input font-size to 16px for terminal, nodes, and scripts modal form fields
- Extend mobile CSS regression tests to assert the global touch-action rule
- Extend useMemoryData with triggerDreamNow and dreamRunning state by locating and invoking the Memory Dreams automation
- Add Dream Now actions to MemoryView and SettingsModal memory settings with loading UI, success/error toasts, and file refresh in MemoryView
- Expand hook and component tests to cover dream-trigger visibility and execution flows in both views
- Update terminal mobile keyboard layout CSS contract expectations for the current mobile modal width and min-height rules
- Add a core node-override-guard module, export it from @fusion/core, and enforce conflicts in store updates
- Add API route and CLI extension safeguards so nodeId override updates are blocked when ownership would conflict
- Wire node override routing and validation through dashboard quick-create, list, modal, settings, and task form/detail surfaces
- Add focused unit and integration tests for core guard logic, workflow routes, and dashboard node override UX
- WorkflowStepManager: fix React error #310 ("Rendered more hooks than during
the previous render") that broke the workflow steps panel from loading.
`useOverlayDismiss` was being called after `if (!isOpen) return null`, so
the hook count differed between open/closed renders. Move the hook above
the early return.
- ModelOnboardingModal: API-key input + Save button now span the full card
width on mobile via negative inline margins that bleed past the card's
horizontal padding, so the form sits flush to the card edges instead of
picking up a chunky left indent from the icon-row's flex start position.
- TerminalModal: same desktop-min-width-pinning bug as the onboarding modal.
Reset min-width/min-height to 0 on mobile with `!important` so persisted
desktop sizes from useModalResizePersist cannot re-pin the modal at 480×320
on smaller phones. Also add `!important` to the keyboard-overlap height/
max-height so the visual-viewport adjustment wins against the new
fullscreen rule — without this the terminal stayed at 100dvh while the
mobile keyboard covered the bottom of the screen.
- Add 0.7.1 changeset covering the full mobile polish + paperclip CLI parity
+ plugin runtime registry fallback + SCHEMA_VERSION bump series.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On mobile the dialog was rendering with its top hidden behind the in-page
\"Agents\" header. The dialog wasn't actually positioned wrong — its overlay
is `position: fixed; inset: 0`. The problem was that NewAgentDialog
rendered as a child of `.agents-view` (which has `overflow: hidden` and
`position: relative`), and an ancestor stacking context combined with the
relative+overflow parent prevented the fixed overlay from escaping above
the page header in the painter's order.
Render the dialog through `createPortal(..., document.body)` so the
overlay attaches at the document root, escaping every parent stacking
context. This is the standard React modal pattern.
All 9639 dashboard tests still pass — React Testing Library queries
traverse portals transparently.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ModelOnboardingModal:
- API-key row was forced to flex-direction: column on mobile, stacking the
input above the Save button and doubling the vertical space inside the
already-cramped provider card. Switch to flex-direction: row with the
input growing (flex: 1, left-aligned) and Save shrunk to its label
(right-aligned). Tighten input/button min-height to 32px and shrink the
button's inline padding.
- Tighten surrounding form: gap → --space-xs, label font-size → 11px with
no margin-bottom, helper paragraphs → 11px / line-height 1.35.
NewAgentDialog:
- Top of the dialog was cut off under the iOS notch / status bar. Added
env(safe-area-inset-top) to the mobile header padding-top, and
env(safe-area-inset-bottom) to the footer padding-bottom so the home
indicator doesn't cover the action buttons.
- Body wasn't scrolling because the flex child kept its default
min-height: auto, making the dialog grow past the viewport and never
trigger overflow-y: auto. Added min-height: 0 + flex: 1 1 auto on the
body, and flex-shrink: 0 on the header/footer/steps so only the body
gives up height.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous mobile rule forced .onboarding-provider-card to flex-direction:
column with --space-lg padding, so the icon, body, and actions each took
their own full-width row and every card rendered ~140px tall on a phone.
Keep the icon inline beside the name + description (the row layout the
desktop already uses, just tighter), shrink the icon container to
list-item-bullet size, drop name/description font sizes a notch, and rely
on the existing flex-wrap so the API-key form / action buttons still drop
to their own row underneath. Also evenly split simple action rows (Connect
/ Skip) across the full width for easier tap targets.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ModelOnboardingModal: the desktop base set min-width: 640px / min-height:
480px and the mobile media query only reset max-width — but min-width
always wins over max-width in size resolution, so the modal stayed pinned
at 640px and overflowed any phone narrower than that. Compounding it,
useModalResizePersist writes inline width/height from saved desktop
sessions (e.g. 1100px), and inline styles beat the media query. Reset
min-width/min-height to 0 in the mobile rule and force fullscreen
(100vw/100dvh) with !important so the persisted desktop size cannot
re-pin the modal off-screen. Also disable resize on mobile.
- NewAgentDialog: had no mobile media query at all. Added a max-width: 768px
block that drops the overlay padding, fills 100vw/100dvh, removes the
border-radius, tightens header/footer/steps padding, locks body scroll
with overscroll-behavior: contain + -webkit-overflow-scrolling: touch
(so iOS doesn't bubble the scroll up and trap users above the footer),
and stacks the footer buttons full-width. Also switched the desktop
max-height from 100vh to 100dvh so iOS Safari's collapsing URL bar
doesn't push the footer under the address bar.
- SettingsModal auth panel: reduced .auth-panel-body padding-inline from
--space-xl (24px) to --space-md (12px) so each provider card gets more
horizontal room — the cards are dense enough that the wider gutter
wasted visible width without any visual benefit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Use bundled Nous Research SVG (inverted) on the Hermes runtime card
instead of the generic ProviderIcon.
- Lock GitHub-star and Help buttons in the settings header to a uniform
26px height so the differing icon sizes don't misalign them.
- Drop the inline Delete button from the idle/terminated agent-card
states — deletion stays available from the agent detail view.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace process.env.HOME fallbacks with os.homedir() in dashboard usage
probes and the hermes plugin profile resolver so unset HOME no longer
yields literal "~" paths. Skip POSIX process-group semantics on Windows
in engine/merger and dashboard-tui's pgrep-based vitest killer. Add
shell: true to npx spawns in CLI skills/extension so .cmd shims resolve
on Windows, and route test:build-exe through cross-env.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- packages/dashboard/src/routes.ts: hermes/openclaw runtime metadata declares
`version` as `string | undefined`, but BUNDLED_PLUGIN_RUNTIMES requires
`string`. Coalesce to "0.0.0" so the bundled fallback list type-checks.
- packages/dashboard/app/components/__tests__/NodeStatusIndicator.test.tsx:
the file had been reduced to a stub ("placeholder") which the test runner
parsed as an undefined identifier. Restore the original 155-line suite from
c4a48491e; the underlying NodeStatusIndicator component is unchanged.
All 9639 dashboard tests pass; pnpm typecheck is clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merge metadata for the three example runtime plugins bundled as workspace
dependencies of @fusion/dashboard with pluginLoader.getPluginRuntimes(), so
the NewAgentDialog "Plugin Runtime" dropdown populates without requiring
an explicit `fn plugin install`. Installed plugins override the bundled
fallback by runtimeId.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Paperclip runtime card's Local CLI tab previously only derived an apiUrl
from the local config and then made HTTP calls itself, so the Test action and
the company/agent pickers ignored the user's onboarded CLI auth context.
Add CLI-backed variants for every Paperclip call that has a `paperclipai`
counterpart, and route through them when transport=cli — both from the
settings card and from the runtime adapter's prompt path.
- New plugin functions spawning `paperclipai … --json`:
* probePaperclipViaCli, listCompaniesViaCli, listCompanyAgentsViaCli
(settings card test + pickers)
* createIssueViaCli, getIssueViaCli, agentsMeViaCli (runtime hot path)
- New dashboard routes: /providers/paperclip/cli-status, /cli-companies,
/cli-agents (read-only façades over the plugin's CLI helpers)
- PaperclipRuntimeCard: branches on transport=cli to use the cli-* fetchers
- PaperclipRuntimeAdapter: stores transport on the session and routes
createIssue/getIssue + identity derivation through CLI variants in CLI mode;
raises a clear error when agentId is unset in CLI mode (paperclipai has no
/agents/me equivalent)
- getIssueComments / wakeAgent / getRunEvents stay on HTTP (no matching
paperclipai subcommands) and continue to use the apiKey discovered from
the local paperclipai config, so CLI mode still works end-to-end
- Tests: 9 new paperclip-client tests covering each CLI variant + 5 new
adapter tests for the Local-CLI transport branch (64/64 plugin tests pass)
- Update routes.test for the existing BUNDLED_PLUGIN_RUNTIMES fallback so
the bundled hermes/openclaw/paperclip entries are expected alongside
installed plugins
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Define and export unavailable node policy types in core settings interfaces
- Add project-level unavailable node policy default and runtime validation helper
- Add core unit coverage for unavailable node policy parsing and acceptance cases
- Guard Paperclip mint requests to include companyId only when available for type-safe payloads
- Document unavailable node policy in the settings reference
- Hermes / OpenClaw plugin index.ts now re-export `probeHermesBinary` /
`probeOpenClawBinary` and their status types so the dashboard's
`runtime-provider-probes.ts` façade can import them via the public
package entry instead of deep paths.
- Dashboard `package.json` adds `@fusion-plugin-examples/hermes-runtime`,
`…/openclaw-runtime`, `…/paperclip-runtime` as workspace deps so
pnpm symlinks them into `packages/dashboard/node_modules/`. Without
these, the new probe imports failed with "Cannot find module" during
`pnpm typecheck`.
This clears 6 of the 9 outstanding typecheck errors. The remaining 3 are
in the in-flight Hermes plugin rewrite (runtime-adapter still imports
from a deleted `./pi-module.js`; the new `index.ts` calls a factory
with the wrong arg type) and should be resolved by the same change set
that landed the rewrite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>