feat(FN-3008): notify when model settings fall back to defaults

Merges FN-3008 to add a "fallback-used" notification system: the engine now emits events when AI model fallbacks are triggered, dispatches notifications via ntfy/webhook providers, surfaces a session banner in the dashboard, and exposes a settings toggle to enable or disable these alerts.

Fusion-Task-Id: FN-3008
This commit is contained in:
Fusion
2026-05-02 19:51:05 -07:00
committed by gsxdsm
parent 44a996e769
commit 68f34dd0f7
26 changed files with 357 additions and 41 deletions

View File

@@ -317,7 +317,16 @@ describe("GlobalSettingsStore", () => {
// After clear, reading back gives the default value
// (either undefined on disk with default applied, or default written directly)
const settings = await store.getSettings();
expect(settings.ntfyEvents).toEqual(["in-review", "merged", "failed", "awaiting-approval", "awaiting-user-review", "planning-awaiting-input", "gridlock"]);
expect(settings.ntfyEvents).toEqual([
"in-review",
"merged",
"failed",
"awaiting-approval",
"awaiting-user-review",
"planning-awaiting-input",
"gridlock",
"fallback-used",
]);
});
it("handles concurrent updates safely via locking", async () => {

View File

@@ -153,6 +153,7 @@ describe("NotificationDispatcher", () => {
"awaiting-user-review",
"planning-awaiting-input",
"gridlock",
"fallback-used",
]);
expect(DEFAULT_GLOBAL_SETTINGS.notificationProviders).toEqual([]);
});

View File

@@ -23,7 +23,16 @@ export const DEFAULT_GLOBAL_SETTINGS = {
ntfyEnabled: false,
ntfyTopic: undefined,
ntfyBaseUrl: undefined,
ntfyEvents: ["in-review", "merged", "failed", "awaiting-approval", "awaiting-user-review", "planning-awaiting-input", "gridlock"],
ntfyEvents: [
"in-review",
"merged",
"failed",
"awaiting-approval",
"awaiting-user-review",
"planning-awaiting-input",
"gridlock",
"fallback-used",
],
ntfyDashboardHost: undefined,
webhookEnabled: false,
webhookUrl: undefined,

View File

@@ -208,7 +208,15 @@ export interface WorkflowStep {
/** Input for creating a new workflow step. */
/** Event types that can trigger ntfy notifications */
export type NtfyNotificationEvent = "in-review" | "merged" | "failed" | "awaiting-approval" | "awaiting-user-review" | "planning-awaiting-input" | "gridlock";
export type NtfyNotificationEvent =
| "in-review"
| "merged"
| "failed"
| "awaiting-approval"
| "awaiting-user-review"
| "planning-awaiting-input"
| "gridlock"
| "fallback-used";
/** Known notification event types. Providers may support additional custom events. */
export const NOTIFICATION_EVENTS = [
@@ -219,6 +227,7 @@ export const NOTIFICATION_EVENTS = [
"awaiting-user-review",
"planning-awaiting-input",
"gridlock",
"fallback-used",
] as const;
/** Notification event type. Known events plus provider-specific custom events. */
@@ -226,7 +235,7 @@ export type NotificationEvent = (typeof NOTIFICATION_EVENTS)[number] | (string &
/** Standard payload shape shared across notification providers. */
export interface NotificationPayload {
taskId: string;
taskId?: string;
taskTitle?: string;
taskDescription?: string;
event: NotificationEvent;