- Remove the stale infusion-link changeset entry that conflicts with the FN-2837 correction already on main.
- Preserve the current runfusion.ai update-notice baseline instead of reintroducing reverted release-note metadata.
- Add a patch changeset entry for @runfusion/fusion describing the update-notice learn-more link adjustment.
- Record release-note metadata in .changeset/fn-2837-add-infusion-link.md for the upcoming publish.
The single "smart" strategy is now two flavors with the new default flipped
to prefer-main. Both share a pre-cascade `git fetch origin <currentBranch>`
+ best-effort fast-forward so a freshly-pushed sibling commit doesn't get
clobbered when the fallback resolves a conflict against a stale base.
- "smart-prefer-main" (new default): -X ours fallback. Protects just-merged
sibling work from being regressed by a concurrent task branch.
- "smart-prefer-branch": -X theirs fallback. Equivalent to legacy "smart".
Legacy "smart" / "prefer-main" enum values are accepted and normalized via
`normalizeMergeConflictStrategy()` so existing settings.json files migrate
seamlessly. The fast-forward step gracefully degrades on fetch failure or
divergent local main (logs and continues).
Updates settings UI dropdown, test helpers, and adds 5 fetch+ff regression
tests + 7 normalize-helper tests. Lint cleanup of two empty catch blocks
in scripts/release.mjs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The engine's merger imports MergeConflictStrategy from @fusion/core, but it
was defined in core/src/types.ts without being re-exported from index.ts,
breaking dashboard typecheck against a clean checkout (no engine dist).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The dry-run gate was at the bottom of the script, after version bump,
lockfile update, CHANGELOG sync, build, and the chore(release) commit
had already run — so a dry-run left the local repo with a stray version
commit that had to be reset. Move the gate to right after the version
selection so dry-run shows the full preview (changesets, proposed
version, override prompt) and exits before mutating anything. Drop the
now-dead late check and the redundant DRY_RUN short-circuit in confirm().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dry-run was previously bundled with --yes for the version prompt, so
it silently accepted the proposed version and skipped the interactive
flow it's meant to exercise. Only --yes should auto-accept.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inadvertent infusion.ai links slipped into the dashboard update-available
banner and settings modal (plus matching tests and changeset). Point them
at the actual marketing domain, runfusion.ai.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- docs(FN-2869): pluggable notification providers reference + architecture
- chore: changeset for pluggable notification providers
- ui(merge): clarify mergeConflictStrategy option labels — both "smart" and "prefer-main" run the full smart cascade; differ only in the final fallback (-X theirs vs -X ours)
- TaskDetailModal: keep Node Routing summary block removed
Conflicts in executor.ts, core/index.ts, and RoutingTab.* resolved by
keeping HEAD — fn-2869 branched from a stale main and was dragging in
older versions of files that have since been updated by sibling tasks
(including the FN-2887 rebase fix on executor.ts itself).
Show pending changeset summaries, compute the proposed semver via
`pnpm changeset status --output`, and prompt for an override before
applying. If the user picks a different version, post-process every
fixed-group package's package.json + CHANGELOG.md heading so the
commit, npm publish, and tag all use the chosen version. --yes and
--dry-run skip the prompt and accept the proposed version.
Adds a changeset for the recent SetupWizard scroll + model onboarding
handoff fixes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace notifications UI with reusable provider cards for ntfy and webhook settings
- Add event option metadata rendering and provider-specific test notification actions
- Align notification card gutters with existing settings layout and mobile behavior
- Expand SettingsModal and mobile tests to cover provider card visibility and interactions
On a fresh install useAuthOnboarding's effect ran at mount before the
setup wizard's 500ms auto-open timer fired. The one-shot ref locked,
and the resolved fetch could either stack model onboarding on top of
the wizard or never re-trigger after the wizard closed.
- Gate the trigger on projectId being set so the wizard owns the
bootstrap phase; the auth check only fires once a project exists.
- Re-check setupWizardOpen via a ref when the auth fetch resolves to
avoid stacking onboarding on top of a wizard opened mid-fetch.
- Release the one-shot in that suppressed branch so the effect retries
when the wizard closes.
Adds two regression tests: fresh-install handoff and mid-fetch wizard
suppression.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On a fresh install useAuthOnboarding's effect ran at mount before the
setup wizard's 500ms auto-open timer fired. The one-shot ref locked,
and the resolved fetch could either stack model onboarding on top of
the wizard or never re-trigger after the wizard closed.
- Gate the trigger on projectId being set so the wizard owns the
bootstrap phase; the auth check only fires once a project exists.
- Re-check setupWizardOpen via a ref when the auth fetch resolves to
avoid stacking onboarding on top of a wizard opened mid-fetch.
- Release the one-shot in that suppressed branch so the effect retries
when the wizard closes.
Adds two regression tests: fresh-install handoff and mid-fetch wizard
suppression.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Modal could clip its footer on older laptops / browsers without
dvh support: the height calc fell back to invalid, max-height was
dropped, and the parent overlay had no overflow rule. Added a vh
fallback before the dvh line and made .setup-wizard-overlay
scrollable as a safety net.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related executor fixes:
1. Spawned child agents previously bypassed the executor model lane hierarchy
and used settings.defaultProvider/defaultModelId directly, ignoring
project-level executionProvider/executionModelId from .fusion/config.json.
Resolve via resolveExecutorModelPair() so children honor the same
precedence as the parent executor.
2. Pre-merge workflow step AI calls now have a wall-clock timeout
(settings.workflowStepTimeoutMs, default 6 min) and fall back to the
configured validatorFallback / fallback model on timeout. The 20-min
stuck-detector kill loop was the only escape hatch when a provider's
streaming API hung mid-response, and the kill triggered a same-provider
retry — guaranteeing repeat hangs. The runner now races the prompt against
a timeout; on timeout it disposes the session, logs a clear entry, and
re-runs the step once with a distinct fallback provider/model. If neither
completes (or no fallback is configured), the step returns a normal
failure that flows into the existing handleWorkflowStepFailure retry path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 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
The prior commit re-enqueued tasks after stale-merge recovery but didn't
account for the engine's in-memory `mergeActive` set, which still held the
wedged task. `internalEnqueueMerge` silently no-ops when the entry is
present, so the re-enqueue had no effect.
The recovery callback now also aborts the active merge's signal and
disposes its session if the wedged attempt was the currently-active one.
This is what unsticks tasks where an AI provider call is hung mid-await
and the surrounding `try/finally` never gets a chance to run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stale-merge recovery now calls back into ProjectEngine's auto-merge queue
directly instead of waiting on the 15s polling sweep — wired via a new
InProcessRuntime.setMergeEnqueuer hook so SelfHealingManager can re-enqueue
without leaking engine internals.
createWorktree mirrors the merge-time rebase: when worktreeRebaseBeforeMerge
is enabled, the new task branch is rebased onto <remote>/<defaultBranch>
right after creation, so executors start from origin's tip with local main
replayed on top. Best-effort — fetch/rebase failures abort cleanly and
leave the merge-time rebase as the backstop.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 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 webhook settings fields and defaults for enablement, URL, format, and event filtering
- Implement WebhookNotificationProvider with payload formatting support for generic, Slack, and Discord endpoints
- Extend NotificationService to manage both ntfy and webhook providers with live settings sync
- Export webhook notification types/providers through engine notification entry points
- 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
- Resolve squash conflicts across dashboard and TUI files by preserving current mainline behavior
- Keep node-routing status UI and quick-chat default-model flows intact during conflict resolution
- Confirm no net code changes were required from fusion/fn-2868 after replay
- Run mandatory verification commands: pnpm test and pnpm build
- Add notification service module with provider abstractions and ntfy provider implementation
- Refactor NtfyNotifier into a compatibility wrapper that delegates task-event delivery to NotificationService
- Initialize and stop NotificationService from ProjectEngine while preserving gridlock notifications via NtfyNotifier
- Export notification APIs from engine index and add focused unit coverage for provider, service, and project-engine wiring
- 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
The live number-key handler hard-coded [3]→utilities, [4]→stats and
returned early, masking a parallel NUMBER_KEY_ORDER table. Update the
live mapping and remove the dead duplicate handler + constant.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 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
- Remove stdout header overlay patching and related frame recovery hooks from the dashboard TUI controller
- Keep panel switching logic lightweight by relying on normal state updates without forced recover cycles
- Adjust status footer and utility/system panel rendering to maintain a single-line, truncation-friendly layout
- Add explicit number-key panel mapping while preserving existing tab/cycle panel order
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>
Replace lazy `await import("./pi.js")` and `require("./pi.js")` calls in
runtime-resolution, agent-session-helpers, agent-heartbeat, and
cron-runner with top-level static imports. These dynamic imports were
documented as plugin-decoupling, but pi.js is already eagerly loaded
through index.ts re-exports and static imports in executor/merger/
reviewer/triage/mission-execution-loop, so the deferral never paid off
in practice.
The deferral did, however, introduce a TOCTOU race: a tsc rebuild that
momentarily emptied dist/pi.js would let the engine load fine and only
fail minutes later when the first session was created (e.g. FN-2860
errored two minutes into execution while pi.js was being rewritten).
With static imports, a missing/half-built dist now fails immediately at
process startup with a clear stack — verified by `mv dist/pi.js
dist/pi.js.bak` reproducing ERR_MODULE_NOT_FOUND on the first import of
runtime-resolution.js.
Also drops the DefaultPiRuntime.describeModelFn cache, which only
existed to paper over the require-on-first-call latency.
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.