Commit Graph

8768 Commits

Author SHA1 Message Date
gsxdsm
3ee47dec86 merge: integrate origin/main into feature/workflow-steps (FN-7039)
Resolve conflicts from 56 upstream commits:
- db.ts: renumber my migrations around main's new migration 130 (columnDwellMs) —
  enable-id normalization 130→131, drop-table 131→132, SCHEMA_VERSION→132.
- index.ts / routes.ts: take main's new MCP exports/imports; keep WORKFLOW_STEP_TEMPLATES
  array removed (kept the WorkflowStepTemplate type).
- merger.ts: keep the legacy post-merge execution path removed (U7c) over main's version.
- ci-workflow.test.ts (from main): add port-4040/process-supervisor allowlist markers to
  the gate-script assertions that reference the checker filenames (pre-existing self-match).

Gate green (engine-core 299, ci-shape 62); boot smoke PASS; migration tests + typecheck clean.
2026-06-26 08:50:22 -07:00
gsxdsm
005322eeaa fix(review): address PR #1788 review feedback
- workflow-graph-executor: wrap each post-merge walk() in try/catch so a malformed
  post-merge IR / traversal error is logged and skipped, never flipping an already-
  merged task to failed (non-blocking post-merge contract) [T9, real bug].
- Refresh stale FNXC comments now that graphNativePostMerge is default-ON and the
  legacy merger post-merge path was removed (experimental-features, workflow-graph-
  executor, workflow-graph-post-merge.test) [T6/T7/T8].
- Normalize FNXC timestamps to yyyy-MM-dd-hh:mm (TaskCard.test, taskProgress.test) [T2/T3].
- Changeset: category fix → feature to match the minor bump [T0].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 08:40:59 -07:00
gsxdsm
7d13f880ba FN-7059: pin merge gate composition
Add CI-shape coverage that guards the trusted merge gate composition.\n\n- Load root and engine package scripts plus the engine vitest config in the CI workflow test.\n- Assert test:gate includes the audited guard scripts, engine core suite, and CLI CI-shape suite.\n- Assert engine test:core continues targeting the engine-core vitest project.\n\nFiles changed:\n packages/cli/src/__tests__/ci-workflow.test.ts | 26 ++++++++++++++++++++++++++\n 1 file changed, 26 insertions(+)

Fusion-Task-Id: FN-7059

Fusion-Task-Lineage: 47af7fdd-a812-4d03-960a-a6300d86b59e
2026-06-26 06:47:27 -07:00
gsxdsm
2b554142f5 FN-7056: guard configured commands against execSync
Add a focused engine regression guard for user-configured command paths.

- Add a static Vitest registry that slices protected configured-command helpers and fails on execSync usage.
- Assert each protected command path keeps bounded async safeguards such as timeout, maxBuffer, or maxLifetimeMs.
- Document the guard and its deliberate git-plumbing exclusions in the testing guide.

Files changed:
 docs/testing.md                                    |   5 +
 .../user-configured-command-no-execsync.test.ts    | 288 +++++++++++++++++++++
 2 files changed, 293 insertions(+)

Fusion-Task-Id: FN-7056

Fusion-Task-Lineage: b92f19cf-526e-4345-b18e-869a278e0e10
2026-06-26 04:11:04 -07:00
gsxdsm
d03d6c23d6 FN-7057: preserve workflow selections across dashboard surfaces
Add regression coverage and stale-workflow fallback for workflow-aware dashboard selection.

- Cover cached board-workflow hydration across remounted Header and Graph switchers.
- Verify Header and Graph selections remain isolated while Graph task filtering follows the Graph selection.
- Treat deleted workflow assignments as default-workflow tasks so they remain visible.
- Add hook coverage for cache hydration, project changes, selection fallbacks, disabled workflow mode, and consumer isolation.
- Add a patch changeset for the stale Graph workflow filtering fix.

Files changed:
 .changeset/fn-7057-graph-workflow-filter.md        |   7 +
 .../workflow-selection-cross-surface.test.tsx      | 184 +++++++++++++++++++++
 .../app/components/GraphWorkflowSwitcherSlot.tsx   |  11 +-
 .../__tests__/GraphWorkflowSwitcherSlot.test.tsx   |   1 +
 .../app/hooks/__tests__/useBoardWorkflows.test.ts  | 133 ++++++++++++++-
 5 files changed, 330 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7057

Fusion-Task-Lineage: 52e6682a-576e-4ed6-92d5-03e0e9b5896c
2026-06-26 04:06:32 -07:00
gsxdsm
3bfdb16650 FN-7033: document MCP operator workflows
Add a canonical MCP guide with operator workflows and contract coverage.

- Add docs/mcp.md covering MCP settings resolution, transports, secret references, validation, dashboard management, CLI commands, import/export, and AI lane forwarding.
- Link the MCP guide from the docs index, CLI reference, settings reference, secrets docs, and dashboard guide.
- Add a documentation contract test that checks required guide sections and source-aligned MCP surfaces.

Files changed:
 docs/README.md                                     |   1 +
 docs/cli-reference.md                              |   2 +-
 docs/dashboard-guide.md                            |   2 +-
 docs/mcp.md                                        | 221 +++++++++++++++++++++
 docs/secrets.md                                    |   2 +-
 docs/settings-reference.md                         |   2 +
 .../src/__tests__/mcp-documentation.test.ts        |  65 ++++++
 7 files changed, 292 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7033

Fusion-Task-Lineage: 530abc69-0247-49ee-9487-54d8e2a1b988
2026-06-26 02:52:51 -07:00
gsxdsm
8131d541ca FN-7038: add live automation run output
Add configurable automation tool access with live manual-run streaming for schedules and routines.

- Add an automation tool allowlist model and dashboard selectors for AI prompt steps.
- Stream manual automation and routine run progress, output, step updates, and tool events over SSE.
- Surface live run transcripts in automation/routine cards and document the operator workflow.
- Cover validation, runner callbacks, API streaming, and UI behavior with targeted tests.

Files changed:
 .changeset/fn-7038-automation-tools-live-output.md |   7 +
 docs/dashboard-guide.md                            |   9 +
 packages/core/src/__tests__/automation.test.ts     |  27 +-
 packages/core/src/automation.ts                    |  18 +
 packages/core/src/index.ts                         |   4 +-
 packages/core/src/types.ts                         |   6 +
 packages/dashboard/app/api/legacy.ts               |  48 +++
 packages/dashboard/app/components/RoutineCard.tsx  |  16 +-
 packages/dashboard/app/components/ScheduleForm.tsx |  53 ++-
 .../app/components/ScheduleStepsEditor.tsx         |  49 ++-
 .../app/components/ScheduledTasksModal.tsx         |  72 +++-
 packages/dashboard/app/components/ScriptsModal.css |  79 ++++
 .../app/components/__tests__/RoutineCard.test.tsx  |  45 +++
 .../app/components/__tests__/ScheduleForm.test.tsx | 100 +++++-
 .../__tests__/ScheduleStepsEditor.test.tsx         |  67 +++-
 .../__tests__/ScheduledTasksModal.test.tsx         |  36 +-
 .../src/__tests__/routes-automation.test.ts        | 151 +++++++-
 packages/dashboard/src/routes.ts                   | 400 ++++++++++++++++++++-
 packages/dashboard/src/server.ts                   |   7 +-
 packages/engine/src/__tests__/cron-runner.test.ts  |  56 ++-
 .../src/__tests__/pi-create-fn-agent.test.ts       |  44 +++
 .../engine/src/__tests__/routine-runner.test.ts    |  28 ++
 packages/engine/src/cron-runner.ts                 |  20 +-
 packages/engine/src/pi.ts                          |  32 +-
 packages/engine/src/routine-runner.ts              |  39 +-
 packages/i18n/locales/en/app.json                  |   9 +
 packages/i18n/src/resources.d.ts                   |  21 ++
 27 files changed, 1374 insertions(+), 69 deletions(-)

Fusion-Task-Id: FN-7038

Fusion-Task-Lineage: 7f5871d0-1de0-4d22-a9c9-ee9418658677
2026-06-26 02:45:29 -07:00
gsxdsm
301f25da06 FN-7025: add MCP server management settings UI
Adds dashboard controls for managing MCP server configuration across global and project scopes.

- Add global and project MCP settings sections with server cards, validation, inheritance status, and import/export controls.
- Wire MCP settings into split-save behavior, browser-safe core exports, localization, and dashboard documentation.
- Cover MCP settings interactions and save routing with dashboard tests.

Files changed:
 .changeset/fn-7025-mcp-dashboard-ui.md             |   7 +
 docs/dashboard-guide.md                            |  14 +
 packages/core/src/types.ts                         |   4 +
 .../app/__tests__/settings-save-split.test.ts      |  25 +
 .../dashboard/app/components/SettingsModal.tsx     |  25 +
 .../__tests__/SettingsModal.mcp.test.tsx           | 228 +++++++++
 .../app/components/settings/save-split.ts          |   5 +
 .../settings/sections/GlobalMcpSection.tsx         |  26 ++
 .../settings/sections/McpServersCard.css           | 177 +++++++
 .../settings/sections/McpServersCard.tsx           | 515 +++++++++++++++++++++
 .../settings/sections/ProjectMcpSection.tsx        |  27 ++
 packages/i18n/locales/en/app.json                  |  10 +-
 packages/i18n/locales/es/app.json                  |  10 +-
 packages/i18n/locales/fr/app.json                  |  10 +-
 packages/i18n/locales/ko/app.json                  |  10 +-
 packages/i18n/locales/zh-CN/app.json               |  10 +-
 packages/i18n/locales/zh-TW/app.json               |  10 +-
 17 files changed, 1107 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7025

Fusion-Task-Lineage: e4e59431-c819-464b-a04b-e470ac51c460
2026-06-26 02:30:34 -07:00
gsxdsm
347842faca refactor(FN-7039): drop the legacy workflow_steps table; remove all table readers
Final cutover — nothing reads workflow_steps at runtime, so migration 131 drops it.

- Removed the merger post-merge execution path entirely (runPostMergeWorkflowSteps,
  hasEnabledPostMergeWorkflowSteps, executePostMerge{Prompt,Script}Step, post-merge
  worktree helpers + call site). Graph owns post-merge.
- Executor recovery no longer reads getWorkflowStep().gateMode; gate-ness comes from the
  recorded WorkflowStepResult.status.
- Removed store CRUD (create/update/deleteWorkflowStep), materializeWorkflowSteps, and
  migrateLegacyWorkflowSteps; selectTaskWorkflow now seeds default-on optional-group node
  ids (consistent with create-time). KEPT the plugin step-template palette (getWorkflowStep
  plugin-only resolver / listWorkflowSteps plugin-only) — never touches the table.
  Removed the dashboard migrate-legacy-steps route + editor migration UI.
- SCHEMA_VERSION 130→131; migration 131 DROP TABLE IF EXISTS workflow_steps; SCHEMA_SQL
  table def removed; historical migrations 77/105/109/130 guarded with tableExists().

Proof nothing stranded: the graph executes IR nodes resolved from workflowId (never
stepIds/compiled rows) — materializeWorkflowSteps writes were vestigial. Full @fusion/core
suite (6290), reliability backstop (154), boot smoke, and a seed-at-130 drop test all pass
with the table gone.

Plan U7c.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 02:29:32 -07:00
gsxdsm
afa33b76d3 FN-7055: fix task workflow detail rendering
Fix task-detail workflow rendering so inherited workflow data and live results refresh reliably.

- Clear stale workflow selections and result rows while switching between tasks.
- Load inherited/default workflow graphs and avoid empty graph previews during loading.
- Alias optional template IDs to materialized workflow steps so configured details populate.
- Cover task switching, inherited workflows, and optional step detail rendering with dashboard tests.

Files changed:
 .changeset/fn-7055-workflow-tab-graph-step-details.md     |  7 +++
 docs/dashboard-guide.md                                    |  1 +
 packages/dashboard/app/components/TaskDetailModal.tsx      |  5 ++
 packages/dashboard/app/components/WorkflowResultsTab.tsx   | 35 +++++++++--
 packages/dashboard/app/components/__tests__/TaskDetailModal.models-progress-workflow.test.tsx | 56 +++++++++++++++++
 packages/dashboard/app/components/__tests__/WorkflowResultsTab.test.tsx | 72 ++++++++++++++++++++++
 6 files changed, 171 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7055

Fusion-Task-Lineage: a28dd138-3c2f-43bc-81f9-fb47799f5251
2026-06-26 02:04:53 -07:00
gsxdsm
59fc94bc0f FN-7054: fix slash skill request matching
Normalize requested skill identifiers so slash/catalog forms load the discovered bare skill across chat and agent sessions.

- Add requested-name matching keys for slash paths, SKILL.md paths, and source-qualified skill identifiers.
- Preserve execution-skill disable/exclude behavior and not-found diagnostics while applying the new matching only to requested names.
- Cover chat/agent requested skill paths with resolver and full flow tests and document supported /skill forms.

Files changed:
 .changeset/fn-7054-skill-slash-names.md            |   7 ++
 docs/agents.md                                     |   2 +-
 docs/dashboard-guide.md                            |   2 +-
 .../engine/src/__tests__/agent-skills-flow.test.ts |  42 +++++++++
 .../engine/src/__tests__/skill-resolver.test.ts    | 101 +++++++++++++++++++++
 packages/engine/src/skill-resolver.ts              |  23 ++++-
 6 files changed, 170 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7054
Fusion-Task-Lineage: 8d0f5c7d-9d8b-4b16-b24e-db6d2f6a464b
2026-06-26 01:38:57 -07:00
gsxdsm
9a2e8a7260 feat(FN-7039): graph is sole post-merge owner + migration 130 normalizes enable ids
Makes graph-native post-merge the default and cuts the merger's legacy post-merge
path over so post-merge runs exactly once (via the graph), with migration data prep.

- experimentalFeatures.graphNativePostMerge → default ON; merger
  hasEnabledPostMergeWorkflowSteps/runPostMergeWorkflowSteps become inert when on
  (no double-run; proven by a new no-double-run test). Merger code kept (U7c removes it).
- Migration 130 (SCHEMA_VERSION 129→130) rewrites each task's enabledWorkflowSteps
  entries that are legacy built-in pre-merge workflow_steps row ids → the optional-group
  node id (browser-verification/code-review); dedupes; idempotent; identity-stable;
  leaves node-ids/compiled/custom entries untouched. Table KEPT (U7c drops it).
- Investigation (real DBs): NO custom/plugin post-merge steps exist; the only post-merge
  step is compound-engineering's 'document' graph node — so the merger no-op strands
  nothing. Custom-step re-pointing was verified unnecessary and skipped.

Safe-to-drop in U7c still blocked by live readers: merger post-merge fns, store CRUD,
migrateLegacyWorkflowSteps/readConfig materialization (executor recovery reader is
already null-safe→advisory).

Plan U7b.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 01:30:24 -07:00
gsxdsm
dbd613a529 FN-7053: catch up tasks on SSE re-entry
Reconcile task list catch-up behavior when re-entering live Board/List views.

- Move Board/List SSE re-entry refetch ownership from App into useTasks.
- Trigger exactly one catch-up fetch for each sseEnabled false-to-true transition without duplicating initial mount.
- Cover disabled, search-query, and repeated toggle cases in useTasks tests.

Files changed:
 packages/dashboard/app/App.tsx                     |  22 +----
 .../dashboard/app/hooks/__tests__/useTasks.test.ts | 110 +++++++++++++++++----
 packages/dashboard/app/hooks/useTasks.ts           |  12 +++
 3 files changed, 105 insertions(+), 39 deletions(-)

Fusion-Task-Id: FN-7053

Fusion-Task-Lineage: 7fd7a05e-deb5-4c0d-9585-288089cb9945
2026-06-26 01:24:47 -07:00
gsxdsm
c0d53530cf FN-7052: restore Agent Detail tab touch panning
Restore mobile horizontal panning from direct touches on Agent Detail tab buttons.

- Apply pan-x touch-action to Agent Detail tab buttons alongside the tab strip.
- Cover both base and mobile tab styles so the global mobile pan-y lock does not block button-origin swipes.
- Extend the mobile scroll regression test to assert tab buttons expose horizontal touch panning.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-7052-agent-detail-mobile-tab-touch-action.md        | 7 +++++++
 packages/dashboard/app/components/AgentDetailView.css             | 5 +++++
 .../components/__tests__/AgentDetailView.mobile-scroll.test.tsx   | 8 ++++++--
 3 files changed, 18 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-7052

Fusion-Task-Lineage: 42921948-f940-46d6-8c86-c159e94603b5
2026-06-26 01:19:55 -07:00
gsxdsm
3f66e55505 FN-7016: keep workflow container edges connected
Keep workflow container fallback layouts connected in the editor.

- Space fallback and auto-layout columns by each node's rendered width so wide containers do not overlap adjacent handles.
- Treat incomplete top-level saved layouts as stale and fall back to a coherent graph layout.
- Cover optional-group, foreach, and mobile graph mapping with regression tests.

Files changed:
 .changeset/fn-7016-optional-group-edges.md         |   7 +
 .../__tests__/workflow-auto-layout.test.ts         |  18 +++
 .../__tests__/workflow-flow-mapping.test.ts        | 154 ++++++++++++++++++++-
 .../__tests__/workflow-mobile-graph.test.ts        |  37 ++++-
 .../app/components/workflow-auto-layout.ts         |  28 +++-
 .../app/components/workflow-flow-mapping.ts        |  40 +++++-
 6 files changed, 271 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-7016

Fusion-Task-Lineage: a009fc2d-05cb-41cc-8be1-c5522f7398ff
2026-06-26 01:15:14 -07:00
gsxdsm
194878dac9 feat(FN-7039): post-merge workflow steps run graph-native (flag-gated)
Adds graph-native post-merge step execution behind experimentalFeatures.graphNativePostMerge
(default OFF — byte-identical behavior until enabled). After a successful merge-attempt
(the merge seam awaits the merge Promise), the graph runs post-merge optional-group nodes
and records phase:"post-merge" results, non-blocking. The merge-region traversal hop is
inert when the flag is off, and empty for builtin:coding even flag-on (its merge exits only
reach merge-region nodes or end), so the parity oracle holds. Optional-group recording now
derives phase + log prefix from config.phase (defaults pre-merge). Adds postMergeOptionalGroupNode
factory for migration/custom workflows. Legacy merger post-merge path untouched (U7b cutover).

Plan U7a.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 01:09:45 -07:00
gsxdsm
d739223de2 FN-7049: collapse model pricing behind modal editor
Collapse the Global Models pricing editor into a compact summary with a modal table for detailed edits.

- Add a View pricing table modal with escape, overlay, and close-button dismissal.
- Keep add, edit, delete, and LiteLLM fetch workflows available while showing override counts in the collapsed settings view.
- Update model pricing tests, styling, and documentation for the collapsed summary and modal editor.

Files changed:
 docs/dashboard-guide.md                            |   2 +-
 docs/settings-reference.md                         |   4 +-
 .../settings/sections/ModelPricingSection.css      |  36 +++++-
 .../settings/sections/ModelPricingSection.test.tsx |  62 ++++++++-
 .../settings/sections/ModelPricingSection.tsx      | 144 +++++++++++++++------
 5 files changed, 198 insertions(+), 50 deletions(-)

Fusion-Task-Id: FN-7049
Fusion-Task-Lineage: 9ba63354-28e7-4717-81e6-805f1f05fd97
2026-06-26 01:04:03 -07:00
gsxdsm
6c94ee069c FN-7023: forward MCP runtime config to AI lanes
Forward enabled MCP server configuration through AI session creation and validation paths.

- Resolve and materialize effective MCP servers with secret values at runtime for triage, execution, review, merge, evaluation, reflection, mission validation, and dashboard chat/planning lanes.
- Add runtime support guards, Claude CLI MCP config generation, and a dashboard validation route for MCP server reachability probes.
- Cover MCP forwarding, provider support behavior, settings resolution, validation, and pi extension config generation with targeted tests and docs.

Files changed:
 .changeset/fn-7023-mcp-runtime-forwarding.md       |   7 +
 docs/agents.md                                     |   2 +
 docs/secrets.md                                    |   1 +
 docs/settings-reference.md                         |   6 +-
 .../src/__tests__/mcp-lane-forwarding.test.ts      |  79 +++++++++++
 .../src/__tests__/mcp-validate-route.test.ts       | 111 ++++++++++++++++
 packages/dashboard/src/chat.ts                     |   3 +
 packages/dashboard/src/planning.ts                 |   5 +
 packages/dashboard/src/routes.ts                   |  90 ++++++++++++-
 .../src/__tests__/mcp-lane-forwarding.test.ts      |  95 ++++++++++++++
 .../engine/src/__tests__/mcp-resolution.test.ts    | 104 +++++++++++++++
 .../src/__tests__/mcp-runtime-support.test.ts      |  44 +++++++
 .../src/__tests__/mcp-validation-service.test.ts   |  69 ++++++++++
 packages/engine/src/__tests__/pi.test.ts           |  65 +++++++++
 packages/engine/src/agent-reflection.ts            |   3 +
 packages/engine/src/agent-runtime.ts               |  36 ++++-
 packages/engine/src/agent-session-helpers.ts       |   2 +
 packages/engine/src/evaluator.ts                   |   3 +
 packages/engine/src/executor.ts                    |  14 ++
 packages/engine/src/index.ts                       |   3 +
 packages/engine/src/mcp-resolution.ts              |  81 ++++++++++++
 packages/engine/src/mcp-runtime-support.ts         |  41 ++++++
 packages/engine/src/mcp-validation-service.ts      | 146 +++++++++++++++++++++
 packages/engine/src/merger-ai.ts                   |   5 +
 packages/engine/src/merger.ts                      |  14 ++
 packages/engine/src/mission-execution-loop.ts      |   3 +
 packages/engine/src/pi.ts                          |  44 +++++--
 packages/engine/src/reviewer.ts                    |   3 +
 packages/engine/src/runtime-resolution.ts          |   8 +-
 packages/engine/src/step-session-executor.ts       |   6 +-
 packages/engine/src/triage.ts                      |   5 +
 packages/pi-claude-cli/index.ts                    |  20 ++-
 packages/pi-claude-cli/src/mcp-config.ts           |  65 ++++++++-
 33 files changed, 1150 insertions(+), 33 deletions(-)

Fusion-Task-Id: FN-7023
Fusion-Task-Lineage: ea09c6c7-b3c3-4af6-9ca6-0ebbfec17139
2026-06-26 00:57:32 -07:00
gsxdsm
93da87dc5d FN-7048: enable mobile detail tab swiping
Allow task detail tabs to keep horizontal touch scrolling on mobile surfaces.

- Add pan-x touch-action overrides on detail tab buttons for modal, embedded, mobile, and tablet contexts.
- Extend responsive CSS coverage to assert each task-detail tab target allows horizontal panning.
- Add a patch changeset documenting the mobile task-detail tab scroll fix.

Files changed:
 .changeset/fn-7048-task-detail-mobile-tab-touch-action.md  |  7 +++++++
 packages/dashboard/app/components/TaskDetailModal.css      | 14 ++++++++++++++
 .../TaskDetailModal.responsive-and-dependencies.test.tsx   | 14 +++++++++++++-
 3 files changed, 34 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7048

Fusion-Task-Lineage: bb07b72f-8843-4ed4-a45b-ea8172bc4957
2026-06-26 00:48:51 -07:00
gsxdsm
f3f20accbb FN-7031: preview binary media files in dock Files viewer
Render browser-native previews for right-dock file selections while preserving text editing behavior.

- Add image, video, audio, and PDF preview rendering through the workspace download URL.
- Keep previewable and known binary files out of the text editor, with a read-only fallback for unsupported binaries.
- Cover compact and two-pane dock preview behavior with tests, docs, and a patch changeset.

Files changed:
 .changeset/fn-7031-dock-files-binary-preview.md    |   7 +
 docs/dashboard-guide.md                            |   2 +-
 .../dashboard/app/components/DockFilesView.css     |  45 ++++++
 .../dashboard/app/components/DockFilesView.tsx     |  85 ++++++++++-
 .../components/__tests__/DockFilesView.test.tsx    | 170 ++++++++++++++++++++-
 5 files changed, 303 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7031

Fusion-Task-Lineage: a52bdd57-bb3e-494e-85a8-81326a1548e2
2026-06-26 00:43:55 -07:00
gsxdsm
2ce208e36d FN-7036: make Automations popup movable and resizable
Render the Automations modal in the shared floating-window shell while preserving embedded and mobile behavior.

- Wrap the modal presentation in FloatingWindow with persisted geometry, drag handle, and resize sizing.
- Update Automations modal CSS so desktop fills the floating shell and mobile remains full-screen with resize handles hidden.
- Cover floating-window rendering, dragging, resizing, mobile CSS contract, and embedded mode in ScheduledTasksModal tests.
- Add a minor changeset for the published Fusion package.

Files changed:
 .changeset/fn-7036-automation-modal-floating.md    |   7 ++
 .../app/components/ScheduledTasksModal.tsx         |  43 +++++----
 packages/dashboard/app/components/ScriptsModal.css |  78 +++++++++-------
 .../__tests__/ScheduledTasksModal.test.tsx         | 103 +++++++++++++++++++--
 4 files changed, 172 insertions(+), 59 deletions(-)

Fusion-Task-Id: FN-7036

Fusion-Task-Lineage: 3d6926b7-ec6d-4179-ad17-573bcfef297f
2026-06-26 00:35:41 -07:00
gsxdsm
98a5052b65 FN-6706: add signal connector incident ingestion
Connect external signal ingestion routes to Command Center incident analytics.\n\n- Add connector status reporting and incident upsert/resolution support for webhook, Sentry, Datadog, and PagerDuty sources.\n- Move signal aggregation through shared activity analytics and expose connector-aware empty states in Command Center.\n- Document connector setup, settings, and dashboard behavior with a published changeset.\n- Extend route, analytics, and Command Center UI tests for scoped signal data and configured-but-quiet connectors.\n\nFiles changed:\n .changeset/fn-6706-signal-connectors.md            |   7 +\n AGENTS.md                                          |   1 +\n docs/dashboard-guide.md                            |   4 +-\n docs/settings-reference.md                         |  16 +\n docs/signals-connectors.md                         | 140 ++++++++\n .../core/src/__tests__/signals-analytics.test.ts   |  37 ++-\n packages/core/src/activity-analytics.ts            | 185 ++++++++++-\n packages/core/src/index.ts                         |  11 +-\n packages/core/src/signals-analytics.ts             | 209 +-----------\n .../command-center/areas/SignalsArea.tsx           |  47 ++-\n .../areas/__tests__/areas.github-signals.test.tsx  | 120 +++++--\n .../command-center/areas/__tests__/areas.test.tsx  |   3 +-\n .../register-command-center-routes.test.ts         |  72 +++-\n .../src/__tests__/register-signal-routes.test.ts   | 369 ++++++++++++++++++++-\n .../src/routes/register-command-center-routes.ts   |  29 +-\n .../dashboard/src/routes/register-signal-routes.ts |  55 +++\n packages/dashboard/src/signal-source.ts            |   8 +\n packages/dashboard/src/signal-sources/datadog.ts   |   8 +\n packages/dashboard/src/signal-sources/pagerduty.ts |  14 +-\n packages/dashboard/src/signal-sources/sentry.ts    |  19 +-\n packages/dashboard/src/signal-sources/webhook.ts   |   8 +\n 21 files changed, 1094 insertions(+), 268 deletions(-)

Fusion-Task-Id: FN-6706

Fusion-Task-Lineage: 09003e9b-481b-4393-926b-44907d13bcf9
2026-06-26 00:28:31 -07:00
gsxdsm
142bce0b93 fix(review): apply code-review fixes — dead code, step output/notes, seam-contract sync
From the U1-U6 code review (correctness/adversarial/reliability/maintainability):
- Delete dead code left by the runWorkflowSteps removal: parkTaskAfterWorkflowStepPause,
  handleWorkflowRevisionRequest (+ createWorkflowRevisionFollowUpTask,
  injectWorkflowRevisionInstructions), handleWorkflowStepFailure, the dead
  partitionWorkflowRevisionFeedback export + its test, and 2 orphaned jsdocs;
  reword 2 stale comments (executor.ts FN-6722, self-healing.ts jsdoc).
- Record step output/notes on graph workflow-step results: runGraphCustomNode now
  emits contextPatch:{output,notes} so the Workflow tab shows real review feedback
  and [pre-merge] revision logs carry detail (was always the fallback before).
- Sync the workflow-step seam contract: core (workflow-compiler SEAM_NAMES/order,
  workflow-ir column map, builtin-workflow-prompts) now rejects the workflow-step
  seam to match the engine's resolveSeamName, preventing a latent run-time crash on
  a persisted/cloned def that core would otherwise parse.

Residual (tracked in the PR): re-introduce the FN-4343 per-step scope gate on the
graph path; the parked-failed recovery log wording; malformed-advisory->passed edge
case; recording for non-optional-group/split-branch step realizations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 00:26:03 -07:00
gsxdsm
a7eb3c4dd8 refactor(FN-7039): delete WORKFLOW_STEP_TEMPLATES + legacy workflow-step management surface
U6: delete the built-in WORKFLOW_STEP_TEMPLATES catalog + its materializer
(getBuiltInWorkflowTemplate/ensureWorkflowStepForTemplate/toBuiltInWorkflowStep);
inline the browser-verification + code-review name/prompt/toolMode/gateMode into
their optional-group IR builders (node bytes unchanged); simplify
resolveEnabledWorkflowSteps to an identity-stable pass-through (no materialization,
so the optionalGroupIdSet collision guard is no longer needed). Plugin-contributed
step templates are kept as the editor palette.

U5: remove the legacy /api/workflow-steps REST surface (GET/POST/PATCH/DELETE +
/refine + /workflow-step-templates/:id/create), the dead client fns, and the
Settings management UI; GET /api/workflow-step-templates now serves plugin
templates only. The create-time optional-step toggles remain.

Scope: the workflow_steps store CRUD + table are intentionally KEPT — still consumed
by the engine (merger/recovery) and needed by U7's migration; their removal + the
table drop land in U7.

Plan U5 + U6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 00:06:31 -07:00
gsxdsm
4dab2b6986 FN-7011: Exclude engine downtime from task timing
Exclude proven engine-process downtime from active task duration stats and badges.

- Persist a throttled engineLastActiveAt heartbeat while the scheduler is running and unpaused.
- Reconcile in-progress execution segment anchors on startup when downtime exceeds the poll threshold.
- Emit run-audit events for shifted and no-action downtime reconciliation outcomes.
- Cover core timing, dashboard badge behavior, scheduler heartbeat throttling, and self-healing audit metadata.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-7011-engine-downtime-timing.md       |  7 +++
 AGENTS.md                                          |  1 +
 .../src/__tests__/store-execution-timing.test.ts   | 51 ++++++++++++++++++++++
 packages/core/src/settings-schema.ts               |  1 +
 packages/core/src/store.ts                         | 28 ++++++++++++
 packages/core/src/types.ts                         |  5 +++
 .../app/utils/__tests__/taskTiming.test.ts         | 16 +++++++
 .../__tests__/scheduler-workflow-cutover.test.ts   | 29 +++++++++++-
 packages/engine/src/__tests__/self-healing.test.ts | 23 ++++++++++
 packages/engine/src/run-audit.ts                   |  4 ++
 packages/engine/src/scheduler.ts                   | 11 +++++
 packages/engine/src/self-healing.ts                | 21 +++++++++
 12 files changed, 196 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7011

Fusion-Task-Lineage: 44225b0a-0fa1-40be-812d-33fd5e446944
2026-06-25 23:35:31 -07:00
gsxdsm
da69e03d29 FN-7047: remove quick-entry keyboard hint
Remove the retired quick-entry keyboard hint and its empty UI shell from task creation.

- Drop the quick-entry hint element and associated responsive styles.
- Remove the retired quickEntryHint locale key from all app locales and generated resources.
- Add coverage asserting the hint and shell stay absent across expanded and collapsed quick-entry modes.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-7047-quick-entry-hint-removal.md         |  7 +++++++
 packages/dashboard/app/components/QuickEntryBox.css    | 18 ------------------
 packages/dashboard/app/components/QuickEntryBox.tsx    |  4 +---
 .../app/components/__tests__/QuickEntryBox.test.tsx    | 18 ++++++++++++++++++
 packages/i18n/locales/en/app.json                      |  1 -
 packages/i18n/locales/es/app.json                      |  1 -
 packages/i18n/locales/fr/app.json                      |  1 -
 packages/i18n/locales/ko/app.json                      |  1 -
 packages/i18n/locales/zh-CN/app.json                   |  1 -
 packages/i18n/locales/zh-TW/app.json                   |  1 -
 packages/i18n/src/resources.d.ts                       |  1 -
 11 files changed, 26 insertions(+), 28 deletions(-)

Fusion-Task-Id: FN-7047

Fusion-Task-Lineage: c838f25b-a3cf-4c2c-b214-511df12dd423
2026-06-25 23:34:08 -07:00
gsxdsm
ea5e12e8eb FN-7042: stop refocusing quick task input after submit
Prevent successful quick task creation from stealing focus back to the quick-entry textarea.

- Remove the post-submit focus restoration request/effect from QuickEntryBox.\n- Update desktop, mobile, duplicate-confirm, and image-upload tests to assert no automatic refocus.\n- Add a patch changeset documenting the quick-entry focus fix.\n\nFiles changed:\n .changeset/fn-7042-quick-entry-no-refocus.md       |  7 +++\n .../dashboard/app/components/QuickEntryBox.tsx     | 46 +------------------\n .../components/__tests__/QuickEntryBox.test.tsx    | 53 ++++++++++++----------\n 3 files changed, 39 insertions(+), 67 deletions(-)

Fusion-Task-Id: FN-7042

Fusion-Task-Lineage: 7c8e26a6-3a6b-463f-bfb7-8310682584f8
2026-06-25 23:34:08 -07:00
gsxdsm
9bd0853667 FN-7044: split Command Center area tests
Split the oversized Command Center area test suite into focused files while preserving shared fixtures and coverage.

- Extract shared date ranges, fixtures, and helpers into areas.test-harness.tsx.
- Move GitHub and Signals area assertions into a dedicated sibling suite.
- Keep the remaining areas.test.tsx below the 2000-line cap with existing coverage intact.

Files changed:
 .../areas/__tests__/areas.github-signals.test.tsx  | 406 +++++++++++++
 .../areas/__tests__/areas.test-harness.tsx         | 302 ++++++++++
 .../command-center/areas/__tests__/areas.test.tsx  | 648 +--------------------
 3 files changed, 730 insertions(+), 626 deletions(-)

Fusion-Task-Id: FN-7044

Fusion-Task-Lineage: 63886ec9-e9c3-410e-bbc6-c5116cddb168
2026-06-25 23:34:08 -07:00
gsxdsm
07209a4732 FN-7045: capitalize Code Review step name
Normalize the built-in Code Review workflow label and cover the display-name invariant.

- Rename the compound-engineering built-in code-review node to "Code Review".
- Add regression coverage that rejects lowercase built-in Code review node names.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-7045-code-review-step-name.md           | 7 +++++++
 packages/core/src/__tests__/builtin-workflows.test.ts | 9 +++++++++
 packages/core/src/builtin-workflows.ts                | 6 +++++-
 3 files changed, 21 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7045

Fusion-Task-Lineage: 4608df38-dc5f-4d16-b33e-9f4ce00fe96d
2026-06-25 23:34:07 -07:00
gsxdsm
429143ecf0 FN-7024: add MCP server management CLI
Add CLI support for managing MCP server configuration without exposing secret values.

- Add fn mcp list/add/edit/remove/enable/disable/import/export/validate subcommands.
- Store MCP env and header values as Fusion secret references, including Claude Desktop import conversion.
- Document MCP CLI usage and add command coverage for scoped configuration, import, export, and validation.
- Add a minor changeset for the published CLI feature.

Files changed:
 .changeset/fn-7024-mcp-cli.md                   |   7 +
 docs/cli-reference.md                           |  49 +++
 packages/cli/src/bin.ts                         | 124 +++++++
 packages/cli/src/commands/__tests__/mcp.test.ts | 182 ++++++++++
 packages/cli/src/commands/mcp.ts                | 455 ++++++++++++++++++++++++
 5 files changed, 817 insertions(+)

Fusion-Task-Id: FN-7024

Fusion-Task-Lineage: e3d98bfa-b883-4b9e-86d5-f0416808d6f2
2026-06-25 23:34:07 -07:00
gsxdsm
2c46cdc1e2 FN-7041: fix optional workflow step descriptions
Fix the workflow results settings display for configured optional steps.

- Treat workflow step definitions as missing only when the lookup has no entry.
- Preserve empty descriptions for found optional-group steps such as Code Review.
- Add regression coverage for configured, checkbox, and ordering displays.
- Add a patch changeset for the published Fusion package.

Files changed:
 .../fn-7041-workflow-step-definition-not-found.md  |  7 +++++
 .../app/components/WorkflowResultsTab.tsx          |  9 +++++-
 .../__tests__/WorkflowResultsTab.test.tsx          | 36 ++++++++++++++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7041

Fusion-Task-Lineage: 84698437-d4d3-4b68-9c5f-c8b15f513230
2026-06-25 23:34:07 -07:00
gsxdsm
c7cbae147c FN-7040: align task-detail model displays
Unify task-detail model resolution so Chat, Agent Log, and Workflow settings display the same effective model.

- Add a shared dashboard resolver for executor, validator, and planning model display precedence.
- Reuse the resolver in TaskDetailModal and WorkflowResultsTab instead of duplicating fallback logic.
- Cover log marker, assigned runtime model, task override, and settings fallback cases with focused tests.
- Add a patch changeset for the published Fusion package.

Files changed:
 .../FN-7040-align-task-detail-model-display.md     |   7 +
 .../dashboard/app/components/TaskDetailModal.tsx   | 158 +--------------------
 .../app/components/WorkflowResultsTab.tsx          |  15 +-
 .../__tests__/WorkflowResultsTab.test.tsx          |  74 +++++++++-
 .../__tests__/effective-model-resolution.test.ts   | 111 +++++++++++++++
 .../app/components/effective-model-resolution.ts   | 149 +++++++++++++++++++
 6 files changed, 354 insertions(+), 160 deletions(-)

Fusion-Task-Id: FN-7040

Fusion-Task-Lineage: 05ec3ae7-5063-4219-a515-da16168e9a19
2026-06-25 23:34:07 -07:00
gsxdsm
9a2709dde9 FN-6969: show provider icons beside Command Center models
Show inferred provider icons beside model names across Command Center bar and table surfaces.

- Add dashboard-side provider-icon inference for model/provider strings.
- Render provider icons on Command Center model bar rows and token table rows while keeping pie chart labels text-only.
- Cover overview, token, and ecosystem model-icon surfaces with tests and add a changeset.

Files changed:
 .changeset/fn-6969-provider-icons.md               |   7 ++
 .../components/command-center/CommandCenter.tsx    |  15 ++-
 .../__tests__/CommandCenter.test.tsx               |  33 ++++++-
 .../command-center/areas/EcosystemArea.tsx         |  15 ++-
 .../components/command-center/areas/TokensArea.tsx |  37 +++++++-
 .../areas/__tests__/TokensArea.test.tsx            | 105 +++++++++++++++++++++
 .../command-center/areas/__tests__/areas.test.tsx  |  42 ++++++++-
 .../app/components/command-center/charts/Bar.tsx   |  25 ++++-
 .../components/command-center/charts/charts.css    |  42 +++++++++
 .../app/utils/__tests__/providerIconKey.test.ts    |  32 +++++++
 packages/dashboard/app/utils/providerIconKey.ts    |  45 +++++++++
 11 files changed, 377 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-6969

Fusion-Task-Lineage: 6caf8864-1ecc-46e3-b7fa-bfa8e9a70aaa
2026-06-25 23:34:07 -07:00
gsxdsm
433ccce0b5 fix: stop global settings resetting via project-local central DBs (#1787)
## Problem

Operators intermittently saw **"all my global settings reset"** —
including the global concurrency cap surfacing as `gate=semaphore` with
a low value in scheduler queue logs.

## Root cause

`CentralCore` is supposed to live at `~/.fusion/fusion-central.db`, but
`resolveGlobalDir(dir)` returns an explicit dir **verbatim**, and
several production call sites passed the **project** `.fusion/` dir:

- `store.getSecretsStore()` → `new CentralCore(store.getFusionDir())`
- dashboard secrets/proxy/node/secrets-sync/settings-sync routes → `new
CentralCore(store.getFusionDir())`

Each spawned a **stray per-project central DB**
(`<project>/.fusion/fusion-central.db`) seeded with **default** global
state (`globalMaxConcurrent=4`, empty secrets, default
`centralSettings`) that shadowed the real global DB whenever a
read/write hit one of those paths. Confirmed on disk: 14+ stray DBs at
default `4` vs the real `~/.fusion` at the operator's actual value.

## Fix

- Add `TaskStore.getGlobalSettingsDir()` returning the **resolved global
dir** (`string`); route the secrets store + all the affected dashboard
routes through it instead of `getFusionDir()`.
- `getSecretsStore()` also passes the global dir to `MasterKeyManager`
(co-locates the master key; makes the path test-exercisable).
- Add a `resolveGlobalDir()` **guard** that throws on a project-local
`.fusion/` dir (basename `.fusion` with a `.git` parent), with an
explicit `FUSION_ALLOW_PROJECT_LOCAL_GLOBAL_DIR` opt-out for
legitimately version-controlled custom global dirs. Inert under VITEST.

## Tests

- `global-settings-guard.test.ts` — guard rejects project/worktree
`.fusion` dirs, allows home + custom non-repo dirs.
- `store-secrets-store-global-dir.test.ts` — **symptom-based**:
`getSecretsStore()` creates the central DB in the global dir and
**never** spawns a stray project-local `fusion-central.db`.
- Added `getGlobalSettingsDir()` to route-test mock stores (the new
getter is now called by the routes).

## Operator note

Existing stray project-local `fusion-central.db` files (all
default/empty in practice) should be removed; on the affected machine
they were quarantined to `.legacy-central-db-backup-*` folders.

## Verification

- `pnpm --filter @fusion/core run typecheck` / `@fusion/dashboard`
typecheck — clean
- core guard + regression tests pass; previously-affected route suites
(proxy, nodes-sync, browse-directory, secrets-sync) pass (313/313)
- `pnpm check:changesets` — clean; eslint on changed files — clean

Companion to #1786 (global concurrency slider UI), which is independent.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1787">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed intermittent resets of global settings (including the global
concurrency cap).
* Ensured global settings/secrets are read from and written to the
correct global storage location rather than a project-local one.
* Added a safeguard to prevent using a project-local settings directory
when running inside a repository.

* **Tests**
* Added regression coverage for global directory resolution/guard
behavior.
* Updated route and secrets sync tests to validate the global directory
selection used for proxying and sync.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 23:33:43 -07:00
gsxdsm
e335acc235 feat: global concurrency slider (footer + dashboard) and scoped settings (#1786)
## What

Adds a **Global Max Concurrent** slider to two operator surfaces and
groups the Scheduling settings by scope.

- **Footer engine menu** (`EngineControlMenu`) and **Command Center →
Concurrency card** (`CommandCenterControls`) each get a global-cap
slider.
- **Settings → Scheduling** (`SchedulingSection`) now groups fields
under labeled **"Global — applies to all projects"** and **"This
project"** subheadings with scope badges (clearer on mobile, and
surfaces the existing `globalMaxConcurrent` field that was easy to
miss).

## How

Both sliders are backed by a single shared `useGlobalConcurrency` hook
(module-level store + subscribers), so they read/write **one source of
truth** and **revalidate after every `PUT /api/global-concurrency`**.
This avoids the last-writer-wins / stale-clobber races that two
independent per-component caches would cause (which would ironically
re-create a "global cap resets" symptom). The hook also:

- treats a fetch error as **non-interactive** (slider disabled, not
stuck showing `1` and persistable),
- surfaces a **save-state** indicator (Saving…/Saved/Save failed)
mirroring the project sliders,
- **flushes a pending edit on menu close / unmount** so a quick
drag-then-dismiss isn't silently dropped.

## Review

These race/feedback behaviors were hardened in response to a multi-agent
`/code-review` (correctness, adversarial, reliability, frontend-races
all flagged the per-component-cache approach). Independent of the
companion fix PR (global-settings reset).

## Verification

- `pnpm --filter @fusion/dashboard run typecheck` — clean
- eslint on changed files — clean
- Not yet browser-verified (next step).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1786">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added a global concurrency slider that applies across all projects.
* Global and per-project scheduling controls are now clearly separated
with scope labels and badges.
* The concurrency setting now stays in sync across different dashboard
views and saves automatically after brief pauses.

* **Bug Fixes**
  * Improved feedback for loading, saving, and error states.
* Prevented confusion between global settings and project-specific
settings, especially on smaller screens.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 23:27:23 -07:00
gsxdsm
f987470e6d refactor(FN-7039): delete legacy runWorkflowSteps execution path; graph is sole executor
Removes the legacy workflow-step EXECUTION path now that the graph records results
(U2): delete runWorkflowSteps(), the workflow-step seam + runWorkflowStep primitive
(runtime-primitives, workflow-node-handlers, authoritative-driver), and the legacy
execute() step blocks. Keeps task.workflowStepResults + its store write path (the
graph's sink) and executeWorkflowStep/executeScriptWorkflowStep (reused by the graph).

- Watchdog recoverCompletedTask now re-enters via maybeExecuteWorkflowGraph so the
  graph re-runs pending gates, records results, and owns the in-review/back-for-fix
  transition (KTD-2).
- maybeExecuteWorkflowGraph fails CLOSED (parks) when a store lacks
  getTaskWorkflowSelection AND the task has enabled pre-merge steps — closing the
  FN-7039 silent-skip class without changing minimal-store implementation runs (KTD-5).

KNOWN GAP (follow-up): the FN-4343 per-step workflowStepScopeEnforcement leak check
lived only in runWorkflowSteps and is NOT yet replicated on the graph path. Merge-time
File Scope enforcement (FileScopeViolationError, squash overlap) is unaffected.

Plan U4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 23:25:23 -07:00
gsxdsm
9fd4dedcae fix(review): resolve PR feedback on resolveGlobalDir guard
- Avoid the legacy-migration side effect on the hot path: run the cheap,
  read-only checks (basename === ".fusion" && parent has .git) FIRST, and
  only call resolveGlobalDirForHome() (which can perform a one-time rename)
  when a dir actually looks project-local.
- Normalize paths before the home-dir comparison (realpathSync when present,
  else resolve) so a trailing slash, doubled separator, or symlinked home
  doesn't make the legitimate home global dir trip the guard.
- Harden the browse-directory regression test: the mock returns a global dir
  DISTINCT from getFusionDir() and asserts CentralCore is constructed with the
  global dir, so a revert to getFusionDir() now fails the test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 23:17:02 -07:00
gsxdsm
1ebb518698 fix(review): resolve PR feedback on global concurrency hook
- Double-commit race: null pendingValueRef synchronously at commit() start
  so the close-flush + unmount-cleanup guards can't both fire and send a
  duplicate PUT for the same value.
- Clamp ceiling: clamp setValue against max(SLIDER_BASE_MAX, currentValue)
  instead of Number(raw) (which had no effective upper bound for
  programmatic callers).
- Out-of-band staleness: force-revalidate on each activate so a Settings-modal
  save (which writes globalMaxConcurrent directly, bypassing this store) is
  reflected when a slider surface reopens.
- Load-error label: add an explicit error branch in both EngineControlMenu
  and CommandCenterControls so a failed initial load shows "Load failed"
  instead of "Ready" while the slider is disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 23:05:56 -07:00
gsxdsm
7b358b74b5 feat(FN-7039): drive progress bar + Workflow tab from graph-written results
getUnifiedTaskProgress reads task.workflowStepResults (graph-written in U2) and
no longer needs workflowStepNameLookup — names come from result.workflowStepName.
Removed the lookup prop + fetchWorkflowSteps-name plumbing end-to-end (App,
MainContent, RightDock, Board, Column, Lane, WorktreeGroup, TaskCard). Added the
running state (pending + startedAt) and a distinct advisory_failure (amber, non-
blocking) vs failed (red) treatment; advisory_failure counts as complete.

Plan U3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:48:50 -07:00
gsxdsm
c61164853c test(FN-7039): update stale visitedNodeIds fixtures for code-review optional-group
Prior WIP added a default-on code-review optional-group to builtin:coding on the
success path (execute -> browser-verification -> code-review -> review). 9 exact
visitedNodeIds expectations across 3 suites predated that node and were failing.
Updated expectations to match the real traversal (insert code-review in position).
No product code touched; no assertions weakened.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:38:12 -07:00
gsxdsm
7b19f9796c test: remove real-time waits from the slowest test files (FN-5048) (#1784)
Removes real wall-clock waits and per-test rebuilds from the slowest
test files, replacing them with deterministic seams. **No assertions
weakened, no timeouts widened, no retries added** — this is anti-pattern
removal per FN-5048, verified by re-running each file.

## Changes

| File | What | Result |
|---|---|---|
| `dashboard/.../insights-routes.test.ts` | Boot server+store **once**
in `beforeAll` (was `createServer` + `TaskStore.init` per test ×24);
reset insight tables per test for isolation; drive sweeper via fake
timers | test-exec **~3.7s → ~0.8s** |
| `core/.../db.test.ts` | Fixed 150ms write-lock hold → manual stdin
signal-release (keeps the real OS-lock contention under test); fixed a
real EPIPE on redundant release | 152 pass, non-flaky / 8 runs; −300ms
dead wait |
| `core/.../mission-store.test.ts` | 4 real `setTimeout` sleeps (only
there to force distinct timestamps) → `vi.setSystemTime` controlled
clock | anti-pattern removed |
| `core/.../agent-store.test.ts` | 1 real ordering-sleep → injected
`renewedAt` clock; **assertions strengthened** to pin exact timestamp
values | anti-pattern removed |
| `engine/.../in-process-runtime.test.ts` | Fake the one real 25ms
sleep; drop its inflated 30s per-test timeout | anti-pattern removed |

## Honest accounting
- The **real wins** are `insights-routes` (per-test server boot
eliminated, ~75% execution-time cut) and `db` (dead lock-hold removed).
- The **timestamp-sleep removals** (mission-store, agent-store,
in-process-runtime) are small absolute wins — the headline per-file
durations (16–25s) were **full-suite shard contention, not in-file dead
time** (each runs in 3–10s isolated). But they eliminate the FN-5048
real-wait anti-pattern, so a hub edit no longer drags real sleeps into
every `--changed` selection.
- **`workflow-routes.test.ts` was evaluated for splitting and
deliberately NOT split.** A measured A/B showed the 4-way split
*regressed* wall-clock (6s → 11s): the file is import/transform-bound
(per-file esbuild + `@fusion/core`/express import ≈ 5s > the ~4.3s test
runtime), and per-test store migration was already amortized by
`installInMemoryDbSnapshot`. Splitting only multiplies the dominant
fixed cost. Left intact.

## Verification
- `core` 612/612, `dashboard` 24/24, `engine` 78/78 (file-scoped).
- `tsc --noEmit` clean on all 3 packages; eslint clean.

Follow-up (not in this PR): `scripts/test-timings.json` is stale (its
former #1 file no longer exists) — refresh via `pnpm test:velocity --
--measure --write-report` so the watchdog budgets and velocity report
reflect reality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1784">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Made several test suites more deterministic by replacing real-time
delays with controlled timers and fixed timestamps.
* Improved lock and task checkout tests to use manual release signals,
reducing timing-related flakiness.
* Streamlined route test setup/teardown for faster, more reliable runs.
* Added safer cleanup around timer-based tests to avoid intermittent
failures.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 22:35:53 -07:00
gsxdsm
cb1691f473 feat(FN-7039): record graph workflow-step results into task.workflowStepResults
Enabled optional-group nodes now upsert their outcome into the existing
task.workflowStepResults field keyed by node id, and emit [pre-merge] logs at
parity with the legacy runWorkflowSteps path. Disabled groups stay byte-inert.
Reuses the existing WorkflowStepResult type + store.updateTask path (no new
table/type/store method). Unblocks the unified progress bar for graph-run steps.

Plan U2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:33:08 -07:00
gsxdsm
50f5c36660 feat(core): per-stage column dwell instrumentation (#1781)
## Why

Diagnosing "tasks take too long" showed the dominant end-to-end
wall-clock is **waiting**, not work: tasks sit in `todo` (queue) and
`in-review` (merge wait) far longer than the agent actually runs. Today
only `cumulativeActiveMs` exists, which measures **in-progress time
only** — every other stage's dwell had to be reconstructed by hand from
agent logs.

## What

Adds `columnDwellMs?: Record<string, number>` to `Task` — a per-column
accumulator (column name → cumulative ms), recorded at the **same store
column-transition seam** as `cumulativeActiveMs` (`moveTaskInternal`).
On each move it adds `columnMovedAt(new) − columnMovedAt(prev)` to the
bucket for the column being left:

- clamped `>= 0` (clock skew safe);
- unparseable/missing prior timestamp and zero-dwell moves are skipped
(no spurious buckets);
- second visits **add** to the existing bucket (multi-visit churn is
captured);
- flag-independent — keys off the generic `columnMovedAt` delta, so it
runs for both the workflow-hook and legacy-inline move paths.

This makes per-stage dwell directly queryable, the same way
`productivity-analytics.ts` already consumes `cumulativeActiveMs`.

## Persistence

JSON-text task column, following the v129 `workspaceWorktrees` precedent
exactly: `SCHEMA_SQL` column + `SCHEMA_VERSION` 129→130 + a versioned
`addColumnIfMissing` migration. Additive and behavior-preserving —
pre-existing rows start NULL and accumulate from their next transition.
Survives archive/restore (added to the archive-entry mapping).

## Tests

`src/__tests__/store-execution-timing.test.ts` — new regression asserts
dwell across
`todo→in-progress→in-review→done→todo→in-progress→in-review` accumulates
the right per-column ms (second visits add) and survives a `getTask` DB
round-trip.

```
pnpm --filter @fusion/core exec vitest run src/__tests__/store-execution-timing.test.ts ... --reporter=dot
→ store-execution-timing 5/5, schema suites (goals/secrets) green, 17/17 total
```

Migration chain verified end-to-end (secrets-schema test climbs v11/v82
→ v130). No hardcoded literal version assertions in the suite; schema
tests assert against the `SCHEMA_VERSION` constant.

`@fusion/core` is private — no changeset.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1781">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
  </picture>
</a>

<!-- stage-review-badge-end -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added per-column dwell timing to tasks, showing how long work spent in
each column across multiple visits.
  * Preserved this timing data when tasks are archived and restored.

* **Bug Fixes**
* Task timing now updates correctly during column moves, including
repeated returns to the same column.
* Existing data can be upgraded to the new timing format without
breaking stored tasks.

* **Tests**
* Added coverage for multi-step task movement and data reloading to
verify timing totals stay accurate.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 22:23:48 -07:00
gsxdsm
1d860ec310 feat: global concurrency slider (footer + dashboard) and scoped settings
Add a "Global Max Concurrent" slider to the footer engine menu and the
Command Center Concurrency card, and group the Scheduling settings by
Global vs Project scope so the global cap isn't mistaken for a per-project
setting (clearer on mobile).

Both sliders are backed by a single shared `useGlobalConcurrency` hook
(module-level store) so they read/write one source of truth and revalidate
after every PUT /api/global-concurrency — fixing the last-writer-wins and
stale-clobber races a per-component cache would cause. The hook treats a
fetch error as non-interactive (slider disabled, not stuck at 1), surfaces
a save-state indicator, and flushes a pending edit on menu close / unmount
so a quick drag-then-dismiss is never silently dropped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:19:24 -07:00
gsxdsm
84ec10d1a7 fix(review): harden global-dir fix per code review
Addresses code-review findings on the global-settings reset fix:
- getGlobalSettingsDir() now returns a resolved `string` (was `string |
  undefined`), so the project-local `.fusion` guard fires at the getter
  call site instead of leaking CentralCore's undefined-default semantics.
- getSecretsStore() passes the resolved global dir to MasterKeyManager so
  the master key co-locates with the global central DB and the path is
  exercisable under tests (a bare new MasterKeyManager() throws in VITEST).
- resolveGlobalDir() guard gains an explicit FUSION_ALLOW_PROJECT_LOCAL_GLOBAL_DIR
  opt-out so a legitimately version-controlled custom global dir (dotfiles
  repo with a .git parent) is not hard-rejected.
- Add a symptom-based regression test (store-secrets-store-global-dir) proving
  the secrets central DB lands in the global dir and never spawns a stray
  project-local fusion-central.db.
- Add getGlobalSettingsDir() to route-test mock stores (CentralCore is mocked,
  so it mirrors getFusionDir()) and FNXC comments to the remaining route sites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:18:56 -07:00
gsxdsm
207d2b899a test: remove real-time waits from slow test files (FN-5048)
Replace real wall-clock waits and per-test rebuilds in the slowest test files
with deterministic seams. No assertions weakened, no timeouts widened, no
retries added — anti-pattern removal only.

- insights-routes.test.ts: boot the server + store ONCE in beforeAll (was a full
  createServer + TaskStore.init per test x24), reset insight tables per test for
  isolation, drive the sweeper via fake timers. Test-execution time ~3.7s -> ~0.8s.
- db.test.ts: convert the fixed 150ms write-lock hold to manual stdin signal-
  release; keeps the real OS-lock contention under test, removes 2x150ms dead
  wait. Fixed a real EPIPE on redundant release. 152 pass, non-flaky over 8 runs.
- mission-store.test.ts / agent-store.test.ts: replace real setTimeout sleeps
  used only to force distinct timestamps with a controlled clock (vi.setSystemTime
  / injected renewedAt). agent-store assertions strengthened to pin exact values.
- in-process-runtime.test.ts: fake the one real 25ms sleep, drop its inflated
  30s per-test timeout.

Honest note: the timestamp-sleep removals are small absolute wins (the headline
per-file durations were full-suite shard contention, not in-file dead time) but
eliminate the FN-5048 real-wait anti-pattern. workflow-routes.test.ts was
evaluated for splitting and deliberately NOT split — measured A/B showed the
split regressed wall-clock (the file is import/transform-bound, already amortized
by installInMemoryDbSnapshot), so splitting only multiplies fixed import cost.

Verified: core 612/612, dashboard 24/24, engine 78/78; typecheck + eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:08:41 -07:00
gsxdsm
c20c4b7294 fix: stop global settings resetting via project-local central DBs
Production code constructed `new CentralCore(store.getFusionDir())`, pointing
the central/global DB at the project's `.fusion/` instead of `~/.fusion/`.
`resolveGlobalDir()` returns an explicit dir verbatim, so this spawned stray
per-project `fusion-central.db` files seeded with default global settings
(globalMaxConcurrent=4, empty secrets) that shadowed the real global DB
whenever a read/write hit one of those paths — surfacing as intermittent
"all my global settings reset".

- Add TaskStore.getGlobalSettingsDir() (resolved global dir; undefined→~/.fusion)
- Route the secrets store + secrets/proxy/node/secrets-sync/settings-sync
  dashboard routes through it instead of getFusionDir()
- Add a resolveGlobalDir() guard that throws on a project-local `.fusion/`
  dir (basename `.fusion` with a `.git` parent); inert under VITEST
- Regression tests in global-settings-guard.test.ts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:56:27 -07:00
gsxdsm
dd1b9603bc fix(FN-7039): run enabled optional workflow steps via builtin:coding resolution
optionalGroupIdSet falls back to builtin:coding (mirroring the executor's
unselected-task resolution) so a toggled built-in group id like
browser-verification is no longer downgraded to a legacy WS-xxx step row the
graph executor never matches. Create-time optional-step controls resolve
builtin:coding when no project default workflow is set so the toggles render.

First unit of the graph-native workflow-step refactor (see
docs/plans/2026-06-25-001-refactor-workflow-steps-graph-native-plan.md).

Fusion-Task-Id: FN-7039

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:47:03 -07:00
gsxdsm
b6b5583f01 FN-7039: apply execution-lane models to workflow steps
Route workflow and automation prompt steps through the execution-lane model hierarchy.

- Use executor session model resolution for task workflow prompt steps while preserving per-step overrides.
- Use execution settings model resolution for scheduled and manual AI-prompt automation runs.
- Document the model precedence and add regression coverage plus a patch changeset.

Files changed:
 .changeset/fn-7039-workflow-execution-model.md     |   7 +
 docs/settings-reference.md                         |   2 +
 .../core/src/__tests__/model-resolution.test.ts    |  12 ++
 packages/dashboard/src/routes.ts                   |   6 +-
 .../engine/src/__tests__/executor-test-helpers.ts  |  11 +-
 .../__tests__/executor-workflow-step-model.test.ts | 234 +++++++++++++++++++++
 packages/engine/src/cron-runner.ts                 |   7 +-
 packages/engine/src/executor.ts                    |  23 +-
 8 files changed, 285 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-7039

Fusion-Task-Lineage: f27c4be8-7793-4212-b9ee-679f50193406
2026-06-25 21:05:33 -07:00
gsxdsm
79c602d9d4 FN-7022: add MCP server configuration foundation
Add core MCP configuration primitives for secure server declarations and resolution.

- Add MCP server setting types, schema entries, validation, and project-over-global resolution.
- Add secret-reference materialization seams plus Claude Desktop import/export helpers.
- Cover MCP config behavior with core unit tests and document settings and secret handling.
- Add a changeset for the published CLI package.

Files changed:
 .changeset/fn-7022-mcp-core-foundation.md      |   7 +
 docs/secrets.md                                |   3 +-
 docs/settings-reference.md                     |  23 ++
 packages/core/src/__tests__/mcp-config.test.ts | 199 ++++++++++++++
 packages/core/src/index.ts                     |  30 +-
 packages/core/src/mcp-config.ts                | 366 +++++++++++++++++++++++++
 packages/core/src/settings-schema.ts           |  90 +++++-
 packages/core/src/settings-validation.ts       | 172 +++++++++++-
 packages/core/src/types.ts                     |  62 +++++
 9 files changed, 947 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7022

Fusion-Task-Lineage: 7bafd0b8-e4a5-4bc2-9a2a-43bfb934845c
2026-06-25 21:01:15 -07:00