feat(FN-3154): add plugin schema hooks, nav placement, and progress preserv

This merge introduces three major features: task reset now preserves existing progress with explicit user confirmation (FN-3185), the engine's soft-pause/unpause behavior is restored and documented (FN-3201), and the plugin system gains schema hook aggregation with new navigation placement and icons

Fusion-Task-Id: FN-3154
This commit is contained in:
Fusion
2026-05-02 10:41:22 -07:00
committed by gsxdsm
parent 44cc899eb9
commit bed7f3d325
12 changed files with 269 additions and 16 deletions

View File

@@ -274,12 +274,32 @@ const plugin: FusionPlugin = {
| `onTaskMoved` | `(task: Task, fromColumn: string, toColumn: string, ctx: PluginContext) => Promise<void> \| void` | Task moved between columns |
| `onTaskCompleted` | `(task: Task, ctx: PluginContext) => Promise<void> \| void` | Task reached "done" |
| `onError` | `(error: Error, ctx: PluginContext) => Promise<void> \| void` | Error occurred in plugin execution |
| `onSchemaInit` | `(db: Database) => Promise<void> \| void` | During DB schema initialization (before core migrations complete) |
### Hook Behavior
- **Timeout**: 5 seconds per invocation (logged and skipped if exceeded)
- **Error Isolation**: Hook failures never block the host system
- **Optional**: Only define the hooks you need
- **Schema hook constraints**: `onSchemaInit` is intended for idempotent DDL only (`CREATE TABLE IF NOT EXISTS`, `CREATE INDEX IF NOT EXISTS`). Avoid data backfills or long-running logic.
### Example: Schema initialization hook
```typescript
hooks: {
onSchemaInit: async (db) => {
db.exec(`
CREATE TABLE IF NOT EXISTS plugin_roadmaps (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_plugin_roadmaps_created_at
ON plugin_roadmaps(created_at);
`);
},
},
```
### Example: Notification on Task Completion
@@ -505,11 +525,24 @@ const dashboardViews: PluginDashboardViewDefinition[] = [
componentPath: "./src/DependencyGraphView.tsx",
icon: "Network",
order: 40,
placement: "more",
placement: "overflow",
description: "Explore task dependency links",
},
];
```
### PluginDashboardViewDefinition fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `viewId` | `string` | Yes | Unique slug-like ID within your plugin namespace |
| `label` | `string` | Yes | Human-readable nav label |
| `componentPath` | `string` | Yes | Module path for the view component, relative to plugin root |
| `icon` | `string` | No | Lucide icon name |
| `order` | `number` | No | Lower values appear earlier in nav |
| `placement` | `"primary" \| "overflow" \| "more"` | No | Navigation placement hint (default is host-defined overflow behavior) |
| `description` | `string` | No | Short summary for nav/help surfaces |
Current host constraints:
- Discovery API: `GET /api/plugins/dashboard-views`
- The dashboard **does not eval or filesystem-load plugin code in-browser**