feat(FN-2869): merge fusion/fn-2869

- Add pluggable notification provider system with changeset and docs (`@runfusion/fusion` patch)
- Strengthen node routing and task diff visibility (FN-2840): merge-base resolution, routing guards, and unavailable-node policy tests in dashboard
- Overhaul `QuickChatFAB` component: redesigned FAB with modal, chat thread UI, CSS expansion (140 lines added), and comprehensive test coverage
- Rewrite `useQuickChat` hook: switch to polling-based state, expose dismiss/reset, improve retry and error handling
- Fix executor/merger concurrency races and reviewer pause TOCTOU in `packages/engine`
- Add `AgentSemaphore` defensive guards for invalid limits (NaN, Infinity)
- Expand `agent-runtime`, `agent-session-helpers`, `self-healing`, and `triage` engine modules
- Improve TUI: stack utilities/settings under stats in wide layout, add log entry copy feedback
- Add routing and file-diffs test coverage (`routes.test.ts`, `routes-file-diffs.test.ts`)

Commits merged:
- docs(FN-2869): complete Step 2 — document notification provider settings
- chore(FN-2869): add changeset for pluggable notification providers
- feat(FN-2849): merge fusion/fn-2849-2
- feat(tui): stack utilities/settings under stats in wide layout
- fix(engine): close executor/merger concurrency races and reviewer pause TOCTOU
- fix(dashboard): prefer merge-base over outdated baseCommitSha
- fix(tui): surface visible feedback when copying a log entry
- feat(FN-2840): strengthen node routing and task diff visibility
- feat(FN-2910): merge fusion/fn-2910

Files changed:
.changeset/pluggable-notification-providers.md     |   4 +
 docs/settings-reference.md                         |  17 +-
 packages/cli/src/commands/dashboard-tui/app.tsx    |  71 +++++--
 .../cli/src/commands/dashboard-tui/controller.ts   |  18 ++
 packages/cli/src/commands/dashboard-tui/state.ts   |   5 +
 .../core/src/__tests__/node-override-guard.test.ts |  24 +++
 packages/core/src/__tests__/store.test.ts          |  27 +++
 .../core/src/__tests__/task-node-override.test.ts  |  25 +++
 .../src/__tests__/unavailable-node-policy.test.ts  |  42 ++++
 packages/dashboard/app/api/legacy.ts               |   3 +-
 packages/dashboard/app/components/QuickChatFAB.css | 140 ++++++++++++-
 packages/dashboard/app/components/QuickChatFAB.tsx | 226 ++++++++++++++++++++-
 .../app/components/__tests__/QuickChatFAB.test.tsx | 133 +++++++++++-
 .../app/hooks/__tests__/useQuickChat.test.ts       |  12 +-
 packages/dashboard/app/hooks/useQuickChat.ts       | 149 ++++++++------
 .../src/__tests__/routes-file-diffs.test.ts        |  52 +++++
 packages/dashboard/src/__tests__/routes.test.ts    | 177 ++++++++++++++++
 packages/dashboard/src/routes/resolve-diff-base.ts |  76 ++++---
 .../engine/src/__tests__/project-engine.test.ts    |   8 +-
 packages/engine/src/agent-runtime.ts               |  15 ++
 packages/engine/src/agent-session-helpers.ts       |  14 +-
 packages/engine/src/concurrency.ts                 |  37 +++-
 packages/engine/src/executor.ts                    | 183 ++++++++++++-----
 packages/engine/src/pi.ts                          |  11 +
 packages/engine/src/project-engine.ts              |  47 ++++-
 packages/engine/src/reviewer.ts                    |  95 +++++++--
 packages/engine/src/self-healing.ts                |   8 +
 packages/engine/src/triage.ts                      |  10 +-
 28 files changed, 1412 insertions(+), 217 deletions(-)

Fusion-Task-Id: FN-2869
This commit is contained in:
Fusion
2026-04-29 11:40:22 -07:00
committed by gsxdsm
parent 736baf3805
commit d6e8915418
2 changed files with 20 additions and 1 deletions

View File

@@ -43,6 +43,10 @@ Defaults from `DEFAULT_GLOBAL_SETTINGS`; key scope from `GLOBAL_SETTINGS_KEYS`.
| `ntfyBaseUrl` | `string` | `undefined` | Optional custom ntfy server base URL (must use `http://` or `https://`). If blank/unset, Fusion uses `https://ntfy.sh` for both runtime and test notifications. |
| `ntfyEvents` | `("in-review" \| "merged" \| "failed" \| "awaiting-approval" \| "awaiting-user-review" \| "planning-awaiting-input" \| "gridlock")[]` | `["in-review","merged","failed","awaiting-approval","awaiting-user-review","planning-awaiting-input","gridlock"]` | Event types that trigger ntfy notifications. `planning-awaiting-input` fires when planning mode is waiting on user input. `gridlock` fires when all schedulable todo tasks are blocked. |
| `ntfyDashboardHost` | `string` | `undefined` | Dashboard host used to build deep links in notifications. |
| `webhookEnabled` | `boolean` | `false` | Enable webhook notifications for task lifecycle events. Part of the legacy flat settings; prefer `notificationProviders` for new setups. |
| `webhookUrl` | `string` | `undefined` | Webhook endpoint URL. Must be `http://` or `https://`. Part of legacy flat settings. |
| `webhookFormat` | `"slack" \| "discord" \| "generic"` | `"generic"` | Webhook payload format. Part of legacy flat settings. |
| `webhookEvents` | `string[]` | `[]` | Event filter for webhook notifications. Empty/omitted means all events. Part of legacy flat settings. |
| `notificationProviders` | `NotificationProviderConfig[]` | `[]` | Array of pluggable notification provider configurations. Each entry uses `{ id, name, enabled, config }` and is dispatched by provider ID (for example `ntfy` or `webhook`). |
| `defaultProjectId` | `string` | `undefined` | Default project for multi-project CLI operations when `--project` is omitted. |
| `setupComplete` | `boolean` | `undefined` | Tracks completion of first-run setup. |
@@ -74,7 +78,7 @@ Defaults from `DEFAULT_GLOBAL_SETTINGS`; key scope from `GLOBAL_SETTINGS_KEYS`.
Fusion now supports a provider-list notification model via `notificationProviders` while keeping legacy flat ntfy/webhook settings intact.
- **Recommended for new setups:** configure providers in `notificationProviders`.
- **Backward compatible:** existing `ntfyEnabled`, `ntfyTopic`, `ntfyBaseUrl`, `ntfyEvents`, and `ntfyDashboardHost` still work unchanged.
- **Backward compatible:** existing flat settings continue to work unchanged, including `ntfyEnabled`, `ntfyTopic`, `ntfyBaseUrl`, `ntfyEvents`, `ntfyDashboardHost`, `webhookEnabled`, `webhookUrl`, `webhookFormat`, and `webhookEvents`.
- This is additive/non-breaking; no migration is required for existing ntfy users.
`notificationProviders` entry shape (`NotificationProviderConfig`):
@@ -102,6 +106,17 @@ When `id` is `"webhook"`, the provider `config` supports:
| `webhookFormat` | `"slack" \| "discord" \| "generic"` | `"generic"` | Invalid/omitted values fall back to `"generic"`. |
| `events` | `string[]` | `[]` | Event filter list. Empty/omitted means all events are sent. |
#### ntfy provider config
When `id` is `"ntfy"` in `notificationProviders`, the provider `config` supports:
| Field | Type | Default | Notes |
|---|---|---:|---|
| `topic` | `string` | _required_ | ntfy topic name (164 chars, alphanumeric + `-_`). |
| `ntfyBaseUrl` | `string` | `"https://ntfy.sh"` | Optional custom ntfy server URL. |
| `events` | `("in-review" \| "merged" \| "failed" \| "awaiting-approval" \| "awaiting-user-review" \| "planning-awaiting-input" \| "gridlock")[]` | `DEFAULT_NTFY_EVENTS` | Event filter list used by the provider. |
| `dashboardHost` | `string` | `undefined` | Dashboard host for deep links in notifications. |
Disable daily update checks globally:
```bash