Commit Graph

389 Commits

Author SHA1 Message Date
gsxdsm
2eae0b2507 feat: remove stuck-task tagging from the dashboard; fix liveness-ratchet scan path
Removes the dashboard's stuck-task tagging per operator request: the Stuck
card/status badges, stuck row styling, the footer Stuck segment and
stuckTaskCount stat, utils/taskStuck.ts, the isStuck agent-activity gate,
and the taskStuckTimeoutMs prop plumbing (App -> Board/Lane/Column/
WorktreeGroup/MainContent -> TaskCard/ListView/ExecutorStatusBar). Stuck-task
tests are deleted or reconciled. The taskStuckTimeoutMs setting and the
engine's recovery sweeps (including the stuck-killed status) are unchanged —
the setting is engine-side only now.

Also repoints the FN-6756 liveness-gate ratchet's facade scans at
executor/task-executor-session-facades.ts, where the wave20 extraction moved
hasLiveSessionSurface/clearPhantomExecutorBinding (the two pre-existing red
tests on main).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 15:47:43 -07:00
gsxdsm
59dc5df5f4 fix(dashboard): show a retryable message when Planning Retry hits a down server
Gateway 502/503/504 non-JSON bodies (for example Traefik "no available server")
were dumped as content-type diagnostics into the Planning error banner.
2026-08-15 21:42:34 -07:00
gsxdsm
ba643fc384 FN-9042: fix dashboard update installation feedback
Make dashboard update actions report clear terminal outcomes and avoid unsupported installs.

- Distinguish update checks, no-op responses, installation failures, and unsupported installation methods.
- Block source-checkout, Homebrew, and missing-npm global installation attempts with actionable guidance.
- Surface update results in dashboard controls and cover API, updater, and UI behavior with tests.

Files changed:
 .changeset/fn-9042-update-now-outcomes.md          |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 docs/settings-reference.md                         |   2 +-
 packages/dashboard/app/api/settings/settings.ts    |   2 +
 .../dashboard/app/components/SettingsModal.tsx     |  18 +--
 .../app/components/UpdateAvailableBanner.tsx       |  11 +-
 .../__tests__/SettingsModal.general.test.tsx       |  20 ++++
 .../__tests__/UpdateAvailableBanner.test.tsx       |  19 ++++
 .../dashboard/src/__tests__/auto-update.test.ts    |  38 ++++++-
 .../dashboard/src/__tests__/update-check.test.ts   |  19 +++-
 packages/dashboard/src/auto-update.ts              |  33 +++++-
 .../__tests__/register-update-check-routes.test.ts | 104 ++++++++++++++++++
 .../src/routes/register-update-check-routes.ts     |  28 +++--
 packages/dashboard/src/server.ts                   |   9 +-
 packages/dashboard/src/update-check.ts             | 122 ++++++++++-----------
 15 files changed, 338 insertions(+), 96 deletions(-)

Fusion-Task-Id: FN-9042

Fusion-Task-Lineage: 22ae5540-e5b5-43cf-ad16-c7aa05782593

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-14 12:59:23 -07:00
gsxdsm
873f339ddd FN-9040: show backup status and preserve schedules
Expose database backup inventory and schedule execution evidence while keeping scheduled backups due after unchanged settings saves.

- Display backup files, empty and error states, and automatic schedule details in Settings.
- Reconcile the shared backup routine at engine startup and retain its next run when settings are unchanged.
- Add API, localization, documentation, and regression coverage for backup status and scheduling.

Files changed:
 .changeset/fn-9040-database-backups-visibility.md  |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 docs/settings-reference.md                         |   4 +
 .../src/__tests__/backup-schedule-status.test.ts   | 124 +++++++++++++++++++++
 .../core/src/automation/global-routine-store.ts    |  31 +++++-
 packages/core/src/backup/backup.ts                 |  95 ++++++++++++++--
 packages/core/src/index.gate.ts                    |   4 +-
 packages/core/src/index.ts                         |   4 +-
 .../app/api/agents/agent-import-generation.ts      |  14 +++
 packages/dashboard/app/api/legacy.ts               |   1 +
 .../dashboard/app/components/SettingsModal.tsx     |  12 +-
 .../__tests__/SettingsModal.test-harness.tsx       |   7 +-
 .../__tests__/SettingsModalNodeRouting.test.tsx    |   2 +-
 .../components/__tests__/settings-mobile.test.tsx  |   2 +-
 .../settings/sections/DatabaseBackupsSection.css   |  24 ++++
 .../settings/sections/DatabaseBackupsSection.tsx   |  67 ++++++-----
 .../__tests__/DatabaseBackupsSection.test.tsx      |  45 ++++++++
 .../register-system-maintenance-routes.test.ts     |  47 +++++++-
 .../routes/register-system-maintenance-routes.ts   |  46 ++++++--
 .../src/__tests__/in-process-runtime.pg.test.ts    |  15 ++-
 packages/engine/src/runtimes/in-process-runtime.ts |  13 +++
 packages/i18n/locales/en/app.json                  |  17 ++-
 packages/i18n/locales/es/app.json                  |  17 ++-
 packages/i18n/locales/fr/app.json                  |  17 ++-
 packages/i18n/locales/ko/app.json                  |  17 ++-
 packages/i18n/locales/pt-BR/app.json               |  17 ++-
 packages/i18n/locales/zh-CN/app.json               |  17 ++-
 packages/i18n/locales/zh-TW/app.json               |  17 ++-
 packages/i18n/src/resources.d.ts                   |  28 ++++-
 29 files changed, 623 insertions(+), 90 deletions(-)

Fusion-Task-Id: FN-9040

Fusion-Task-Lineage: 29a803a2-0784-4a99-b7cb-2f67d105254b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-13 17:22:46 -07:00
gsxdsm
dad726c777 FN-9038: add Knowledge Graph tab to Memory view
Expose knowledge graph data in the Memory view through a localized, resilient dashboard panel.

- Add protected knowledge graph API routes and access helpers.
- Add a Memory view tab, graph panel, loading/error states, and localized labels.
- Document graph navigation and cover access, route, hook, and component behavior.

Files changed:
 .changeset/fn-9038-knowledge-graph-tab.md          |   7 +
 docs/dashboard-guide.md                            |   2 +
 docs/knowledge-graph.md                            |  10 ++
 packages/dashboard/app/api/legacy.ts               |  17 ++-
 packages/dashboard/app/api/system/index.ts         |   1 +
 .../dashboard/app/api/system/knowledge-graph.ts    |  23 +++
 .../app/components/KnowledgeGraphPanel.css         |  35 +++++
 .../app/components/KnowledgeGraphPanel.tsx         |  68 +++++++++
 packages/dashboard/app/components/MemoryView.tsx   |  15 +-
 .../__tests__/KnowledgeGraphPanel.test.tsx         |  49 +++++++
 .../app/components/__tests__/MemoryView.test.tsx   |  13 ++
 .../app/hooks/__tests__/useKnowledgeGraph.test.ts  |  66 +++++++++
 packages/dashboard/app/hooks/useKnowledgeGraph.ts  |  94 ++++++++++++
 .../src/__tests__/knowledge-graph-access.test.ts   |  88 ++++++++++++
 packages/dashboard/src/knowledge-graph-access.ts   | 160 +++++++++++++++++++++
 .../register-knowledge-graph-routes.test.ts        |  75 ++++++++++
 .../src/routes/register-knowledge-routes.ts        | 120 ++++++++++++++++
 packages/i18n/locales/en/app.json                  |  15 +-
 packages/i18n/locales/es/app.json                  |  15 +-
 packages/i18n/locales/fr/app.json                  |  15 +-
 packages/i18n/locales/ko/app.json                  |  15 +-
 packages/i18n/locales/pt-BR/app.json               |  15 +-
 packages/i18n/locales/zh-CN/app.json               |  15 +-
 packages/i18n/locales/zh-TW/app.json               |  15 +-
 24 files changed, 939 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-9038

Fusion-Task-Lineage: 4200e214-ad22-4f92-b980-c9bcb8ffd3b9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-13 16:48:01 -07:00
gsxdsm
f7bf3f91d1 FN-9022: add task recommendations to Insights
Expose actionable task recommendations in the Insights view.

- Add recommendation list API, client hook, and Insights rendering states.
- Localize recommendation content and document the Insights workflow.
- Cover recommendation retrieval, routes, hooks, API, and view behavior.

Files changed:
 .changeset/fn-9022-insights-recommendations.md     |   7 ++
 docs/architecture.md                               |   1 +
 docs/dashboard-guide.md                            |   3 +-
 .../__tests__/task-recommendations-list.test.ts    | 136 +++++++++++++++++++++
 packages/core/src/index.ts                         |   2 +-
 packages/core/src/store.ts                         |   5 +-
 packages/core/src/task-store/reads.ts              |  48 +++++++-
 packages/core/src/types.ts                         |   4 +
 packages/core/src/types/task/task-core.ts          |  19 +++
 packages/dashboard/app/__tests__/api-tasks.test.ts |  24 ++++
 packages/dashboard/app/api/legacy.ts               |   3 +
 packages/dashboard/app/api/tasks/tasks.ts          |  22 ++++
 packages/dashboard/app/components/InsightsView.css |  27 ++++
 packages/dashboard/app/components/InsightsView.tsx |  47 +++++--
 .../app/components/__tests__/InsightsView.test.tsx | 117 ++++++++++++++++++
 .../hooks/__tests__/useTaskRecommendations.test.ts | 130 ++++++++++++++++++++
 .../dashboard/app/hooks/useTaskRecommendations.ts  | 116 ++++++++++++++++++
 .../__tests__/task-recommendation-routes.test.ts   |  26 ++++
 .../src/routes/register-task-workflow-routes.ts    |  33 +++++
 packages/i18n/locales/en/app.json                  |  11 +-
 packages/i18n/locales/es/app.json                  |  11 +-
 packages/i18n/locales/fr/app.json                  |  11 +-
 packages/i18n/locales/ko/app.json                  |  11 +-
 packages/i18n/locales/pt-BR/app.json               |  11 +-
 packages/i18n/locales/zh-CN/app.json               |  11 +-
 packages/i18n/locales/zh-TW/app.json               |  11 +-
 packages/i18n/src/resources.d.ts                   |   9 ++
 27 files changed, 835 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-9022

Fusion-Task-Lineage: b83f1074-37af-4f87-9ec0-2bd9bb9bf64d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-12 22:18:18 -07:00
gsxdsm
fc56161c9d FN-9014: add chat and mailbox message archiving
Add archived-message lifecycle support across chat and mailbox views.

- Persist archive state with a PostgreSQL migration and message-store APIs.
- Expose archive, restore, and permanent-delete messaging endpoints.
- Add archived-message views and archive-by-default actions with regression coverage.
- Document storage behavior and add a release changeset.

Files changed:
 .changeset/fn-9014-message-archive.md              |   7 ++
 docs/dashboard-guide.md                            |   7 +-
 docs/storage.md                                    |   2 +-
 .../__tests__/postgres/message-store.pg.test.ts    |  34 +++++++
 .../src/__tests__/postgres/schema-applier.test.ts  |   9 +-
 .../core/src/async-stores/async-message-store.ts   |  73 +++++++++++---
 .../migrations/0058_fn_9014_message_archive.sql    |  13 +++
 packages/core/src/postgres/schema-applier.ts       |  14 ++-
 packages/core/src/postgres/schema/project.ts       |   2 +
 packages/core/src/stores/message-store.ts          |  68 ++++++++++---
 packages/core/src/types/messaging/messages.ts      |   9 ++
 packages/dashboard/app/api/chat/messaging.ts       |  37 +++++--
 packages/dashboard/app/api/legacy.ts               |   2 +
 packages/dashboard/app/components/ChatView.tsx     |  21 +++-
 packages/dashboard/app/components/MailboxModal.tsx |  74 ++++++++++++--
 packages/dashboard/app/components/MailboxView.tsx  | 108 +++++++++++++++++++--
 .../__tests__/ChatView.core-contracts.test.tsx     |  24 +++++
 .../components/__tests__/ChatView.test-harness.tsx |   3 +
 .../app/components/__tests__/MailboxModal.test.tsx |   6 +-
 .../app/components/__tests__/MailboxView.test.tsx  |  10 +-
 .../dashboard/app/hooks/__tests__/useChat.test.ts  |  35 ++++++-
 packages/dashboard/app/hooks/useChat.ts            |  38 +++++++-
 .../__tests__/messaging-archive-routes.test.ts     |  86 ++++++++++++++++
 .../src/routes/register-messaging-scripts.ts       |  33 ++++++-
 24 files changed, 635 insertions(+), 80 deletions(-)

Fusion-Task-Id: FN-9014

Fusion-Task-Lineage: 1dbd02c3-1180-4d72-8cbc-9594e5f355dc

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-12 16:03:30 -07:00
gsxdsm
9f24a517cf FN-8956: track resolved review findings
Add durable, scoped resolution states for workflow review findings.

- Persist reviewer-applied and superseded finding receipts without making them actionable.
- Scope supersession claims to a named prior workflow result, preserving duplicate IDs in other review lanes.
- Render informational resolution badges and reject resolved items from revision requests.

Files changed: .changeset/fn-8956-review-finding-resolution.md    |   7 +
 docs/dashboard-guide.md                            |   2 +-
 docs/workflow-steps.md                             |   8 +-
 .../src/__tests__/review-severity-gate.test.ts     |  25 ++++
 .../src/__tests__/workflow-step-results.test.ts    |  45 +++++-
 packages/core/src/index.gate.ts                    |   6 +
 packages/core/src/index.ts                         |   6 +
 packages/core/src/types.ts                         |   2 +
 packages/core/src/types/task/task-review.ts        |   4 +
 packages/core/src/types/workflow/workflow-steps.ts |  15 +-
 .../src/workflows/builtin-code-review-group.ts     |   2 +-
 .../src/workflows/builtin-plan-review-group.ts     |   2 +-
 .../core/src/workflows/review-severity-gate.ts     |  37 ++++-
 .../core/src/workflows/workflow-step-results.ts    |  54 ++++++-
 packages/dashboard/app/api/agents/run-audit.ts     |   1 +
 .../dashboard/app/components/TaskReviewTab.css     |  22 +++
 .../dashboard/app/components/TaskReviewTab.tsx     |  36 +++--
 .../components/__tests__/TaskReviewTab.test.tsx    |  46 ++++++
 .../dashboard/src/__tests__/routes-tasks.test.ts   |  48 ++++++
 .../src/routes/register-task-workflow-routes.ts    |  14 +-
 .../__tests__/review-finding-supersession.test.ts  | 163 +++++++++++++++++++++
 .../__tests__/review-findings-injection.test.ts    |  22 +++
 .../workflow-step-verdict-parsing.test.ts          |  16 +-
 .../engine/src/executor/execute-workflow-graph.ts  | 129 ++++++++--------
 .../engine/src/executor/execute-workflow-step.ts   |  25 +++-
 .../engine/src/executor/run-graph-custom-node.ts   |   7 +
 .../executor/workflow-step-failure-injection.ts    |   8 +-
 .../engine/src/executor/workflow-step-verdict.ts   |  17 ++-
 .../src/workflows/workflow-graph-executor.ts       |  15 ++
 packages/i18n/locales/en/app.json                  |   4 +-
 packages/i18n/locales/es/app.json                  |   4 +-
 packages/i18n/locales/fr/app.json                  |   4 +-
 packages/i18n/locales/ko/app.json                  |   4 +-
 packages/i18n/locales/pt-BR/app.json               |   4 +-
 packages/i18n/locales/zh-CN/app.json               |   4 +-
 packages/i18n/locales/zh-TW/app.json               |   4 +-
 36 files changed, 703 insertions(+), 109 deletions(-)

Fusion-Task-Id: FN-8956

Fusion-Task-Lineage: 80568280-85aa-4a49-a60a-99b75f88f486

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 13:34:27 -07:00
gsxdsm
5a1853cac6 FN-8934: add memory pre-steering across agent prompts
Add bounded memory-first guidance and consolidation observability across agent workflows.

- Apply mode-aware memory pre-steering to execution, triage, reviewer, heartbeat, and merger prompts.
- Export and test shared memory nudges while documenting memory inclusion settings.
- Expose agent memory consolidation history through dashboard API and detail UI.

Files changed:
 .changeset/fn-8934-memory-pre-steering.md          |  7 ++
 docs/agents.md                                     |  4 +
 docs/settings-reference.md                         |  2 +
 .../core/src/__tests__/memory-pre-steering.test.ts | 28 +++++++
 packages/core/src/__tests__/project-memory.test.ts | 22 ++++++
 packages/core/src/index.gate.ts                    |  7 ++
 packages/core/src/index.ts                         |  7 ++
 packages/core/src/memory/index.ts                  |  1 +
 packages/core/src/memory/memory-pre-steering.ts    | 41 ++++++++++
 packages/core/src/memory/project-memory.ts         | 19 +++++
 packages/dashboard/app/api/agents/agents.ts        | 12 +++
 packages/dashboard/app/api/legacy.ts               |  2 +
 .../dashboard/app/components/AgentDetailView.css   | 41 ++++++++++
 .../dashboard/app/components/AgentDetailView.tsx   | 56 +++++++++++++-
 ...etailView.memory-consolidation-history.test.tsx | 58 +++++++++++++++
 .../__tests__/AgentDetailView.test-helpers.ts      |  3 +
 .../register-agent-memory-consolidations.test.ts   | 87 ++++++++++++++++++++++
 .../register-agent-reflection-rating-routes.ts     | 36 +++++++++
 .../memory-pre-steering-injection.test.ts          | 50 +++++++++++++
 packages/engine/src/__tests__/reviewer.test.ts     | 18 +++++
 packages/engine/src/__tests__/triage.test.ts       | 18 ++++-
 packages/engine/src/agent-heartbeat.ts             | 14 +++-
 .../engine/src/agents/agent-heartbeat-prompts.ts   |  2 +
 packages/engine/src/agents/agent-instructions.ts   | 16 ++--
 packages/engine/src/execution/reviewer.ts          | 31 +++++---
 packages/engine/src/executor/execution-prompt.ts   |  6 +-
 packages/engine/src/merger.ts                      |  9 ++-
 packages/engine/src/triage.ts                      | 12 ++-
 28 files changed, 577 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-8934

Fusion-Task-Lineage: a062cc6b-1277-4d36-9926-b3ecba4945eb

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 04:57:14 -07:00
gsxdsm
7ddcf7e2a6 FN-8979: remove legacy mission resume blockers
Retire the deprecated v0 mission-resume blocker payload in favor of canonical descriptors.

- Remove legacy blocker types, conversions, exports, and HTTP payload mirrors.
- Deduplicate canonical blocker descriptors and update clients, tests, and documentation.
- Add a major changeset for the breaking API removal.

Files changed:
 .changeset/fn-8979-removal.md                      |  7 +++++
 docs/missions.md                                   |  4 +--
 .../suite-only-flakes-observed-register.md         | 14 +++++++++
 .../src/__tests__/mission-blocked-clear.test.ts    | 23 ++++++++++++++-
 .../core/src/__tests__/mission-blockers.test.ts    | 26 +++++++++++------
 .../__tests__/postgres/mission-store.pg.test.ts    |  5 +---
 .../core/src/async-stores/async-mission-store.ts   |  7 +----
 packages/core/src/index.gate.ts                    |  3 +-
 packages/core/src/index.ts                         |  3 +-
 packages/core/src/missions/mission-blockers.ts     | 34 +++++++++++++---------
 packages/core/src/missions/mission-types.ts        |  9 ++----
 packages/core/src/types.ts                         |  2 +-
 packages/dashboard/app/api/missions/missions.ts    | 25 +++++-----------
 .../MissionManager.blocked-repair.test.tsx         | 17 +++++++----
 .../MissionManager.resume-conflict.test.tsx        |  9 ++++--
 .../src/__tests__/mission-resume-conflict.test.ts  | 11 ++++---
 packages/dashboard/src/mission-routes.ts           | 10 +++----
 17 files changed, 127 insertions(+), 82 deletions(-)

Fusion-Task-Id: FN-8979
Fusion-Task-Lineage: 2a0dd0b6-43ca-44ad-b992-79f4ef8eda67
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 01:30:04 -07:00
gsxdsm
3eec1338c5 FN-8970: add mission reconcile controls
Add a dry-run mission reconciliation control with explicit apply feedback.

- Add the dashboard reconcile API client and exported result type.
- Present preview, apply, empty, and archived reconciliation states in Mission Manager.
- Guard reconcile requests across direct selection and target-mission deep-link changes.
- Cover reconcile interactions, stale requests, and deep-link intent updates.

Files changed:
 .changeset/fn-8970-mission-reconcile-control.md    |   7 +
 docs/missions.md                                   |   6 +
 packages/dashboard/app/api/legacy.ts               |   2 +
 packages/dashboard/app/api/missions/missions.ts    |  31 +++
 packages/dashboard/app/components/MissionManager.css    |  48 +++++
 packages/dashboard/app/components/MissionManager.tsx    | 184 +++++++++++++-
 packages/dashboard/app/components/__tests__/MissionManager.mobile-css.test.ts    |   8 +
 packages/dashboard/app/components/__tests__/MissionManager.reconcile.test.tsx    | 277 +++++++++++++++++++++
 8 files changed, 557 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8970

Fusion-Task-Lineage: 62802129-a7ea-43cb-8068-5ce2c2c21b77

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 00:23:10 -07:00
gsxdsm
918a4c4bfa FN-8973: add versioned mission resume blockers
Expose versioned mission resume blockers across API and UI.

- Add versioned blocker descriptors with fail-closed legacy normalization and v0 compatibility projections.
- Return typed resume-conflict envelopes and render root stop details in Mission Manager.
- Cover descriptor behavior, route conflicts, UI handling, and PostgreSQL persistence.

Files changed:
 .changeset/fn-8973-mission-blocker-descriptor.md   |  7 ++
 docs/missions.md                                   |  2 +-
 .../src/__tests__/mission-blocked-clear.test.ts    | 18 ++---
 .../core/src/__tests__/mission-blockers.test.ts    | 43 ++++++++++++
 .../__tests__/postgres/mission-store.pg.test.ts    | 22 ++++--
 .../core/src/async-stores/async-mission-store.ts   | 23 +++---
 packages/core/src/index.gate.ts                    |  4 ++
 packages/core/src/index.ts                         |  4 ++
 packages/core/src/missions/mission-blockers.ts     | 43 ++++++++++++
 packages/core/src/missions/mission-types.ts        | 81 ++++++++++------------
 packages/core/src/types.ts                         |  4 +-
 packages/dashboard/app/api/legacy.ts               |  1 +
 packages/dashboard/app/api/missions/missions.ts    | 46 +++++++-----
 .../dashboard/app/components/MissionManager.tsx    | 11 +--
 .../MissionManager.blocked-repair.test.tsx         | 10 +--
 .../MissionManager.resume-conflict.test.tsx        | 24 +++++++
 .../__tests__/mission-blocked-clear-routes.test.ts |  2 +-
 .../src/__tests__/mission-resume-conflict.test.ts  | 42 +++++++++++
 packages/dashboard/src/mission-routes.ts           | 12 +++-
 19 files changed, 297 insertions(+), 102 deletions(-)

Fusion-Task-Id: FN-8973
Fusion-Task-Lineage: 5d36c9c9-dc0f-4cb0-bd0c-ad41c8dde5c0
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 22:36:01 -07:00
gsxdsm
90573e31b0 FN-8963: prevent concurrent mission validation runs
Prevent duplicate manual validation runs while preserving recovery from stale validator state.

- Add atomic mission-store claims and release handling for manual validator runs.
- Return a conflict response and disable the validation action while a run is active.
- Cover concurrent claims, API behavior, UI state, and stale-window parity.

Files changed:
 .changeset/fn-8963-validate-inflight-guard.md      |   7 ++
 docs/missions.md                                   |   2 +
 .../__tests__/postgres/mission-store.pg.test.ts    | 129 +++++++++++++++++++++
 .../core/src/async-stores/async-mission-store.ts   |  87 ++++++++++++--
 packages/core/src/index.ts                         |   2 +
 packages/core/src/missions/mission-store.ts        |  69 ++++++++++-
 packages/core/src/missions/mission-types.ts        |  13 +++
 packages/dashboard/app/api/legacy.ts               |   2 +
 packages/dashboard/app/api/missions/missions.ts    |  11 +-
 .../dashboard/app/components/MissionManager.tsx    |  15 ++-
 .../MissionManager.validate-inflight.test.tsx      |  77 ++++++++++++
 .../mission-validate-inflight-guard.test.ts        |  55 +++++++++
 packages/dashboard/src/mission-routes.ts           |  32 +---
 .../src/__tests__/mission-execution-loop.test.ts   |  61 +++++++++-
 .../validator-run-stale-window-parity.test.ts      |   9 ++
 15 files changed, 549 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-8963
Fusion-Task-Lineage: 7e5d0ae4-98ac-4f79-99ca-45fd1450362d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 21:41:47 -07:00
gsxdsm
5dd3031e34 FN-8962: add mission blocked status repair controls
Add explicit diagnostics and repair paths for stale mission blocked badges.

- Expose audited core and REST APIs that recompute and clear stale mission blocked status without resuming automation.
- Add mission-manager controls, blocker diagnostics, responsive styling, and operator documentation.
- Cover clear conflicts, persistence, routes, and desktop/mobile UI behavior.

Files changed: .changeset/fn-8962-mission-blocked-clear.md        |   7 ++
 docs/missions.md                                   |  12 ++-
 .../src/__tests__/mission-blocked-clear.test.ts    |  40 ++++++++
 .../__tests__/postgres/mission-store.pg.test.ts    |  71 ++++++++++++++
 .../core/src/async-stores/async-mission-store.ts   |  90 +++++++++++++++--
 packages/core/src/index.gate.ts                    |   4 +
 packages/core/src/index.ts                         |   5 +-
 packages/core/src/missions/mission-types.ts        |  62 ++++++++++++
 packages/dashboard/app/api/legacy.ts               |   3 +
 packages/dashboard/app/api/missions/missions.ts    |  29 ++++++
 .../dashboard/app/components/MissionManager.css    |   6 ++
 .../dashboard/app/components/MissionManager.tsx    |  90 ++++++++++++++++-
 .../MissionManager.blocked-repair.test.tsx         | 106 +++++++++++++++++++++
 .../__tests__/MissionManager.mobile-css.test.ts    |   8 ++
 .../__tests__/mission-blocked-clear-routes.test.ts |  71 ++++++++++++++
 packages/dashboard/src/mission-routes.ts           |  49 ++++++++++
 16 files changed, 638 insertions(+), 15 deletions(-)

Fusion-Task-Id: FN-8962

Fusion-Task-Lineage: 38cab277-a0c3-4c60-af3e-dd25d2f88dea

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 20:41:11 -07:00
gsxdsm
b82f1a41f3 FN-8947: add repairable mission validation controls
Add repairable mission-validation badges with clear and re-run flows.

- Persist repair metadata and audit events for mission validation state changes.
- Expose validation repair through dashboard routes, UI controls, engine tools, and CLI capabilities.
- Add database, API, UI, engine, and extension coverage plus operator documentation.

Files changed: .changeset/fn-8947-mission-validation-repair.md    |   7 +
 docs/missions.md                                   |  15 +-
 packages/cli/skill/fusion/SKILL.md                 |   2 +-
 .../cli/skill/fusion/references/extension-tools.md |  10 +
 .../skill/fusion/references/fusion-capabilities.md |   1 +
 .../extension-experiment-finalize.test.ts          |   2 +
 .../__tests__/extension-gitlab-tracking.test.ts    |   2 +
 .../cli/src/__tests__/extension-web-fetch.test.ts  |   2 +
 packages/cli/src/__tests__/extension.test.ts       |  24 +++
 packages/cli/src/extension.ts                      |  40 ++++
 .../mission-status-event-metadata.test.ts          |  23 +++
 .../postgres/mission-validation-repair.pg.test.ts  | 187 ++++++++++++++++++
 .../core/src/async-stores/async-mission-store.ts   | 216 ++++++++++++++++++---
 packages/core/src/index.gate.ts                    |   5 +
 packages/core/src/index.ts                         |   5 +-
 packages/core/src/missions/mission-types.ts        |  49 +++++
 packages/core/src/types.ts                         |   7 +
 packages/dashboard/app/api/legacy.ts               |   1 +
 packages/dashboard/app/api/missions/missions.ts    |  13 ++
 .../dashboard/app/components/MissionManager.css    |  26 ++-
 .../dashboard/app/components/MissionManager.tsx    | 207 +++++++++++++++++---
 .../__tests__/MissionManager.mobile-css.test.ts    |   8 +
 .../MissionManager.validation-repair.test.tsx      |  83 ++++++++
 .../__tests__/mission-task-prefix-routes.test.ts   | 162 +++++++++++++++-
 packages/dashboard/src/mission-routes.ts           | 104 +++++++++-
 .../src/__tests__/agent-mission-tools.test.ts      | 119 +++++++++++-
 .../__tests__/mission-feature-sync-lanes.test.ts   |  59 +++++-
 .../workflow-step-readonly-allowlist.test.ts       |   1 +
 packages/engine/src/agent-tools.ts                 |  36 ++++
 .../engine/src/execution/gating-classifications.ts |   1 +
 packages/engine/src/index.ts                       |   1 +
 .../engine/src/missions/mission-feature-sync.ts    |  79 ++++++++
 32 files changed, 1430 insertions(+), 67 deletions(-)

Fusion-Task-Id: FN-8947

Fusion-Task-Lineage: b93e5ab6-021c-4d32-bffb-f89f4c3894bc

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 19:36:31 -07:00
gsxdsm
00ddafd5fe FN-8845: persist deterministic spec alignment
Persist approved-plan drift alignment on linked mission features.

- Store spec alignment across PostgreSQL and SQLite mission feature projections
- Reconcile and render durable alignment instead of browser-side task joins
- Preserve migration identities and cover drift persistence regressions

Files changed:
 docs/architecture.md                               |  2 +
 docs/missions.md                                   |  2 +-
 .../core/src/__tests__/planner/spec-lock.test.ts   |  1 +
 .../src/__tests__/postgres/schema-applier.test.ts  |  9 ++++-
 .../async-stores/async-mission-store-queries.ts    |  5 +++
 packages/core/src/missions/mission-store.ts        |  9 ++++-
 packages/core/src/missions/mission-types.ts        | 10 +++++
 packages/core/src/planner/spec-lock.ts             |  7 +++-
 .../0053_mission_feature_spec_alignment.sql        |  3 ++
 packages/core/src/postgres/schema-applier.ts       | 13 +++++-
 packages/core/src/postgres/schema/project.ts       |  2 +
 packages/dashboard/app/api/missions/missions.ts    |  2 +
 .../dashboard/app/components/MissionManager.tsx    | 40 ++++++------------
 packages/dashboard/app/components/mission-types.ts |  2 +
 .../src/__tests__/plan-approval-status.pg.test.ts  |  4 +-
 .../src/__tests__/mission-feature-sync.test.ts     | 37 ++++++++++++++++-
 .../src/__tests__/spec-drift-reconciler.test.ts    | 14 +++++++
 packages/engine/src/missions/mission-autopilot.ts  | 17 +++++---
 .../engine/src/missions/mission-feature-sync.ts    | 47 +++++++++++++++++++++-
 packages/engine/src/project-engine.ts              |  3 +-
 packages/engine/src/scheduler.ts                   | 40 +++++++++++-------
 packages/engine/src/spec-drift-reconciler.ts       |  5 +++
 22 files changed, 215 insertions(+), 59 deletions(-)

Fusion-Task-Id: FN-8845

Fusion-Task-Lineage: d4a30472-f1c3-41ba-a61b-3f2be1ad32ab

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 11:50:56 -07:00
gsxdsm
e610c72034 FN-8943: reconcile spec-lock divergence history
Preserve prior divergence when a task is re-locked after plan changes.

- Persist immutable spec locks, current-plan evidence, and drift reports.
- Reconcile retained divergence into re-approved alignment state across engine, API, and dashboard views.
- Fence Plan Review acceptance and schema upgrades while retaining migration identity parity.

Files changed:
 .changeset/fn-8845-spec-lock-drift-report.md       |   7 +
 .changeset/fn-8943-spec-lock-divergence.md         |   7 +
 docs/architecture.md                               |  17 +-
 docs/dashboard-guide.md                            |   3 +
 docs/missions.md                                   |   4 +
 .../core/src/__tests__/planner/spec-lock.test.ts   | 158 ++++++++++++++
 .../src/__tests__/postgres/schema-applier.test.ts  |  30 ++-
 .../postgres/task-dependency-mutation.pg.test.ts   |  74 +++++++
 packages/core/src/index.gate.ts                    |   4 +
 packages/core/src/index.ts                         |   4 +
 packages/core/src/planner/drift-report.ts          | 152 +++++++++++++
 packages/core/src/planner/spec-lock.ts             | 182 ++++++++++++++++
 .../migrations/0050_spec_lock_drift_report.sql     |  29 +++
 .../0051_spec_lock_source_revision_bigint.sql      |   3 +
 packages/core/src/postgres/schema-applier.ts       |  25 ++-
 packages/core/src/postgres/schema/project.ts       |  13 ++
 packages/core/src/store.ts                         | 242 ++++++++++++++++++++-
 .../core/src/task-store/branch-and-pr-entities.ts  |  32 ++-
 packages/core/src/task-store/project-store-ops.ts  |  34 ++-
 packages/core/src/task-store/task-update.ts        |  66 +++++-
 packages/core/src/task-store/update-task-deps.ts   |  31 ++-
 packages/dashboard/app/api.ts                      |   3 +
 packages/dashboard/app/api/tasks/tasks.ts          |  22 ++
 .../dashboard/app/components/MissionManager.css    |  21 ++
 .../dashboard/app/components/MissionManager.tsx    |  41 +++-
 .../dashboard/app/components/TaskDetailModal.css   |  26 +++
 .../dashboard/app/components/TaskDetailModal.tsx   |  62 +++++-
 .../__tests__/TaskDetailModal.spec-lock.test.tsx   |  80 +++++++
 .../__tests__/TaskDetailModal.test-helpers.ts      |   2 +
 .../src/__tests__/plan-approval-status.pg.test.ts  |  81 ++++++-
 .../src/routes/register-task-workflow-routes.ts    |  59 ++++-
 .../src/__tests__/mission-feature-sync.test.ts     |  15 +-
 .../src/__tests__/spec-drift-reconciler.test.ts    | 108 +++++++++
 .../engine/src/executor/execute-workflow-graph.ts  |  49 ++++-
 .../engine/src/missions/mission-feature-sync.ts    |  55 ++++-
 packages/engine/src/project-engine.ts              |  33 +++
 packages/engine/src/spec-drift-reconciler.ts       | 105 +++++++++
 packages/engine/src/triage.ts                      |  29 +++
 38 files changed, 1842 insertions(+), 66 deletions(-)

Fusion-Task-Id: FN-8943

Fusion-Task-Lineage: 2a7f8a38-99aa-4c4b-8c36-41d14c466d21

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 02:56:58 -07:00
gsxdsm
a48594f128 FN-8929: dismiss accepted chat attachments
Clear staged chat attachments immediately when the server accepts a direct or room message.

- Add stream and room delivery acceptance callbacks for attachment cleanup.
- Preserve staged files on pre-acceptance failures and block destructive clear commands.
- Cover direct, room, mobile, and stream acceptance behavior with tests.

Files changed:
 .changeset/fn-8929-chat-attachment-dismiss.md      |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 .../app/api/__tests__/legacy-chat-stream.test.ts   |  34 ++++++
 packages/dashboard/app/api/chat/chat.ts            |   7 ++
 packages/dashboard/app/components/ChatView.tsx     |  86 +++++++++------
 .../__tests__/ChatView.core-interactions.test.tsx  | 117 ++++++++++++++++++++-
 .../components/__tests__/ChatView.core.test.tsx    |   6 +-
 .../__tests__/ChatView.mobile-render.test.tsx      |  21 ++++
 .../components/__tests__/ChatView.mobile.test.tsx  |   2 +-
 .../components/__tests__/ChatView.rooms.test.tsx   |  64 ++++++++---
 .../dashboard/app/hooks/__tests__/useChat.test.ts  |  54 ++++++++++
 .../app/hooks/__tests__/useChatRooms.test.ts       |  33 +++++-
 packages/dashboard/app/hooks/useChat.ts            |  11 +-
 packages/dashboard/app/hooks/useChatRooms.ts       |  13 ++-
 14 files changed, 393 insertions(+), 64 deletions(-)

Fusion-Task-Id: FN-8929

Fusion-Task-Lineage: 3f39d1aa-a4f9-4a71-a7a8-3522d7c3c83e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-09 23:21:02 -07:00
gsxdsm
d09e3e5554 FN-8861: preserve GitHub issue context in planning
Preserve imported GitHub issue provenance through Planning Mode and source tracking.

- Pass structured GitHub issue context from import through planning task creation.
- Append source-issue metadata to planned tasks and safely link each source issue once.
- Cover provenance persistence, duplicate suppression, and planning UI handoff.

Files changed:
 .changeset/fn-8861-planning-source-issue.md        |   7 ++
 docs/dashboard-guide.md                            |   8 +-
 docs/settings-reference.md                         |   2 +-
 packages/dashboard/app/App.tsx                     |   4 +-
 packages/dashboard/app/api/planning/planning.ts    |   3 +-
 packages/dashboard/app/components/AppModals.tsx    |   2 +-
 .../dashboard/app/components/GitHubImportModal.tsx |  13 +--
 .../dashboard/app/components/PlanningModeModal.tsx |   5 +-
 .../__tests__/GitHubImportModal.test.tsx           |  34 ++++++
 .../app/components/dashboard/PlanningKeepAlive.tsx |   1 +
 .../dashboard/app/components/dashboard/types.ts    |   2 +-
 .../app/hooks/__tests__/useModalManager.test.ts    |  26 ++++-
 packages/dashboard/app/hooks/useModalManager.ts    |  17 ++-
 .../src/__tests__/github-tracking.test.ts          | 125 ++++++++++++++++++++-
 packages/dashboard/src/__tests__/github.test.ts    |  78 ++++++++++++-
 .../__tests__/planning-e2e-plan-creation.test.ts   |  49 +++++++-
 .../src/__tests__/planning-source-issue.test.ts    |  61 ++++++++++
 .../src/__tests__/routes-planning-tracking.test.ts | 118 ++++++++++++++++++-
 packages/dashboard/src/github-tracking.ts          | 112 ++++++++++++++++--
 packages/dashboard/src/github.ts                   |  50 +++++++++
 packages/dashboard/src/planning.ts                 |  48 +++++++-
 .../dashboard/src/routes/register-git-github.ts    |  31 +----
 .../src/routes/register-planning-subtask-routes.ts |  69 +++++++++++-
 23 files changed, 785 insertions(+), 80 deletions(-)

Fusion-Task-Id: FN-8861
Fusion-Task-Lineage: b2433f70-9c1b-47ef-bafa-0434861cd0a8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-09 07:06:06 -07:00
gsxdsm
a61ab834f8 FN-8846: show workflow agents' active tasks
Expose active workflow-linked tasks alongside explicit agent assignments.

- Return a deduplicated, project-scoped union of assigned and active agent tasks.
- Clarify agent task loading, failure, and empty-state copy.
- Cover task visibility across workflow, assignment, project, and viewport states.

Files changed:
 packages/dashboard/app/api/agents/run-audit.ts     |   9 +-
 .../dashboard/app/components/AgentDetailView.tsx   |   6 +-
 .../AgentDetailView.logs-tasks-runs.test.tsx       |  86 ++++++++----
 .../register-agent-runtime-routes.tasks.test.ts    | 154 +++++++++++++++++++++
 .../src/routes/register-agent-runtime-routes.ts    |  17 ++-
 5 files changed, 239 insertions(+), 33 deletions(-)

Fusion-Task-Id: FN-8846

Fusion-Task-Lineage: 38c00c21-711a-4792-87fd-8aa2aff4f07a

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-08 18:35:19 -07:00
gsxdsm
d450dbe971 FN-8829: add task recommendations
Add persistent task recommendations that agents can create, resolve, and display in task details.

- Persist recommendation state and expose task recommendation API routes.
- Generate recommendations from executor task completions with duplicate suppression.
- Add localized dashboard recommendation tab and settings control with coverage.

Files changed:
 .changeset/fn-8829-recommendations.md              |   7 +
 docs/dashboard-guide.md                            |   1 +
 docs/settings-reference.md                         |   1 +
 .../postgres/settings-persistence.pg.test.ts       |  10 +
 .../postgres/task-recommendations.pg.test.ts       | 191 +++++++++
 .../core/src/__tests__/settings-parity.test.ts     |   2 +
 packages/core/src/config/settings-schema.ts        |   2 +
 packages/core/src/index.ts                         |   2 +-
 .../0047_fn_8829_task_recommendations.sql          |   3 +
 packages/core/src/postgres/schema-applier.ts       |  32 +-
 packages/core/src/postgres/schema/project.ts       |   2 +
 packages/core/src/store.ts                         |  12 +-
 packages/core/src/task-store/persistence.ts        |   4 +-
 packages/core/src/task-store/serialization.ts      |   1 +
 packages/core/src/task-store/settings-ops.ts       |  22 +
 packages/core/src/task-store/task-mutation-ops.ts  |  78 +++-
 packages/core/src/task-store/task-row-mappers.ts   |   2 +-
 packages/core/src/task-store/task-update.ts        |  51 ++-
 packages/core/src/types.ts                         |   4 +
 packages/core/src/types/settings/settings-scope.ts |   6 +
 packages/core/src/types/task/task-core.ts          |  18 +
 .../__tests__/App.openTasksInRightSidebar.test.ts  |   3 +-
 packages/dashboard/app/__tests__/api-tasks.test.ts |  31 ++
 packages/dashboard/app/api/legacy.ts               |   1 +
 packages/dashboard/app/api/tasks/tasks.ts          |  24 ++
 .../dashboard/app/components/TaskDetailModal.tsx   |  43 +-
 .../app/components/TaskRecommendationsTab.css      |  71 ++++
 .../app/components/TaskRecommendationsTab.tsx      | 127 ++++++
 .../__tests__/SettingsModal.general.test.tsx       |  11 +
 .../TaskDetailModal.recommendations.test.tsx       | 111 +++++
 .../app/components/settings/section-keys.ts        |   1 +
 .../settings/sections/GeneralSection.tsx           |  14 +
 .../settings-default-descriptions.test.tsx         |   1 +
 packages/dashboard/app/hooks/useModalManager.ts    |   6 +
 packages/dashboard/app/plugins/types.ts            |   7 +-
 .../__tests__/task-recommendation-routes.test.ts   | 472 +++++++++++++++++++++
 .../src/routes/register-task-workflow-routes.ts    | 263 +++++++++++-
 .../executor-task-recommendations.test.ts          | 128 ++++++
 packages/engine/src/executor.ts                    |  66 ++-
 packages/i18n/locales/en/app.json                  |  15 +-
 packages/i18n/locales/es/app.json                  |  16 +-
 packages/i18n/locales/fr/app.json                  |  16 +-
 packages/i18n/locales/ko/app.json                  |  16 +-
 packages/i18n/locales/zh-CN/app.json               |  16 +-
 packages/i18n/locales/zh-TW/app.json               |  16 +-
 packages/i18n/src/resources.d.ts                   |  12 +
 46 files changed, 1908 insertions(+), 30 deletions(-)

Fusion-Task-Id: FN-8829
Fusion-Task-Lineage: 5f60a1fb-9cf8-4577-9bfd-c20a2d402333
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-08 01:59:38 -07:00
gsxdsm
3dd824d04e FN-8823: respect shared member auto-merge holds
Honor project and member auto-merge consent consistently throughout shared-branch integration.

- Apply project autoMerge settings and explicit member overrides to shared-member hold decisions.
- Expose shared-member integration hold state and controls in branch-group dashboard and lifecycle APIs.
- Add regression coverage, operator documentation, and a patch changeset.

Files changed:
 .changeset/fn-8823-shared-member-consent.md        |  7 ++
 docs/dashboard-guide.md                            |  4 +-
 packages/core/src/__tests__/task-merge.test.ts     | 57 +++++++++++++++
 packages/core/src/index.gate.ts                    |  3 +
 packages/core/src/index.ts                         |  3 +
 packages/core/src/merge/task-merge.ts              | 81 ++++++++++++++++++---
 .../dashboard/app/api/tasks/tasks-lifecycle.ts     | 11 +++
 .../dashboard/app/components/BranchGroupCard.css   | 84 ++++++++++++++++++++++
 .../dashboard/app/components/BranchGroupCard.tsx   | 58 ++++++++++++++-
 packages/dashboard/app/components/ListView.tsx     | 14 +++-
 .../dashboard/app/components/TaskDetailModal.tsx   | 20 +++++-
 .../components/__tests__/BranchGroupCard.test.tsx  | 44 +++++++++++-
 .../components/__tests__/TaskDetailModal.test.tsx  | 24 ++++++-
 .../app/components/dashboard/MainContent.tsx       |  2 +-
 .../app/components/useRightDockController.tsx      |  2 +-
 packages/dashboard/app/hooks/useModalManager.ts    |  6 ++
 .../src/__tests__/routes-branch-groups.test.ts     | 42 ++++++-----
 .../src/routes/register-branch-groups-routes.ts    |  9 ++-
 ...cutor-live-branch-group-auto-merge-hold.test.ts | 21 +++---
 .../src/__tests__/group-merge-coordinator.test.ts  |  7 +-
 .../workflow-graph-executor-handlers.test.ts       | 33 ++++++---
 packages/engine/src/executor.ts                    | 27 ++++---
 packages/engine/src/project-engine.ts              |  9 ++-
 packages/engine/src/self-healing.ts                | 16 ++---
 .../src/workflow-node-runners/merge-runner.ts      | 13 ++--
 25 files changed, 503 insertions(+), 94 deletions(-)

Fusion-Task-Id: FN-8823

Fusion-Task-Lineage: 19a8ed3f-26e1-4c8e-8782-ca366718a3f2

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-07 20:27:04 -07:00
gsxdsm
35810666be FN-8797: stabilize task detail refreshes
Keep task-detail state and controls mounted while Definition content refreshes.

- Add a prompt-only task endpoint and client request path.
- Preserve task lifecycle, workflow badges, and actions during prompt refreshes and workflow updates.
- Cover prompt refresh stability, late responses, and route behavior.

Files changed:
 packages/dashboard/app/__tests__/api-tasks.test.ts |  14 ++
 packages/dashboard/app/api/legacy.ts               |   3 +
 packages/dashboard/app/api/tasks/tasks.ts          |  15 ++
 .../dashboard/app/components/TaskDetailModal.tsx   | 102 ++++++----
 .../__tests__/TaskDetailModal.rendering.test.tsx   | 211 ++++++++++++++++++---
 .../__tests__/TaskDetailModal.test-helpers.ts      |   1 +
 ...gister-task-workflow-routes.task-prompt.test.ts |  93 +++++++++
 .../src/routes/register-task-workflow-routes.ts    |  17 ++
 8 files changed, 388 insertions(+), 68 deletions(-)

Fusion-Task-Id: FN-8797

Fusion-Task-Lineage: 57d571b4-4a02-4c96-9986-444c525d8405

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-04 22:22:41 -07:00
gsxdsm
0658795181 FN-8793: restore workflow review feedback selection
Restore canonical workflow review feedback so revisions can select server-owned reviewer items.

- Normalize current Code Review and Plan Review workflow results into stable review items.
- Preserve verdict and reviewer type through review API mappings and reject forged client feedback.
- Add regression coverage and a patch changeset.

Files changed:
 .changeset/fn-8793-workflow-review-items.md        |   7 +
 packages/core/src/index.gate.ts                    |   2 +-
 packages/core/src/index.ts                         |   2 +-
 packages/core/src/types/task/task-review.ts        |   6 +-
 packages/dashboard/app/api/agents/run-audit.ts     |   2 +
 .../dashboard/src/__tests__/routes-tasks.test.ts   | 121 +++++++++++++++++
 .../src/routes/register-task-workflow-routes.ts    | 148 ++++++++++++++++++---
 7 files changed, 264 insertions(+), 24 deletions(-)

Fusion-Task-Id: FN-8793

Fusion-Task-Lineage: 25da04f9-5c30-4ad8-9f82-e1ac91ec481f

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-04 19:23:20 -07:00
gsxdsm
78543233aa fix(planning): allow repeated task creation
Advance the durable creation epoch for each explicit Planning Mode action while preserving idempotency for transport retries. Recover soft-deleted task links with a fresh claim key and cover live, deleted, and retry paths.
2026-08-03 12:15:19 -07:00
gsxdsm
5b2b31d2c9 FN-8762: extract Todo Lists into bundled plugin
Move Todo Lists into a bundled, project-enabled plugin package.

- Move Todo UI, client API, and server routes into the plugin package.
- Register and bundle Todo as an enabled plugin dashboard view rather than a static host feature.
- Preserve Todo route validation and server-error semantics, including task assignment agent lookup.
- Keep disabled and legacy Todo views out of project navigation and main content.

Files changed:
 .changeset/fn-8762-todos-plugin.md                 |   7 +
 AGENTS.md                                          |   3 +-
 docs/PLUGIN_AUTHORING.md                           |   4 +
 docs/dashboard-guide.md                            |   4 +
 docs/todo-view.md                                  | 151 +----
 .../cli/src/plugins/staged-bundled-plugin-ids.ts   |   1 +
 packages/cli/tsup.config.ts                        |   8 +
 .../core/src/board/mobile-nav-primary-items.ts     |   2 -
 .../__tests__/bundled-plugin-install.test.ts       |   2 +
 .../core/src/plugins/bundled-plugin-install.ts     |   1 +
 packages/dashboard/app/App.tsx                     |  18 +-
 .../app/__tests__/lazy-loaded-views-docs.test.ts   |   9 +-
 packages/dashboard/app/api/legacy.ts               |  15 -
 packages/dashboard/app/api/system/index.ts         |   1 -
 packages/dashboard/app/api/system/todo.ts          |  85 ---
 packages/dashboard/app/components/Header.tsx       |  23 +-
 .../dashboard/app/components/LeftSidebarNav.tsx    |   1 -
 packages/dashboard/app/components/MobileNavBar.tsx |   4 -
 .../dashboard/app/components/SettingsModal.tsx     |   2 -
 .../app/components/__tests__/App.test.tsx          |   7 -
 .../app/components/__tests__/Header.test.tsx       |  42 --
 .../app/components/__tests__/RightDock.test.tsx    |  18 +-
 ...skDetail.mobile-transition.board-panel.test.tsx |   1 -
 .../__tests__/TaskDetail.swipe-back.test.tsx       |   1 -
 .../__tests__/TodoView.mobile-css.test.ts          |  66 ---
 .../app/components/__tests__/TodoView.test.tsx     | 649 ---------------------
 .../__tests__/navigation-history.test.tsx          |   3 -
 .../__tests__/overflowViewRegistry.test.tsx        | 118 +---
 .../app/components/dashboard/MainContent.tsx       |  27 +-
 .../dashboard/app/components/dashboard/types.ts    |   6 +-
 .../app/components/overflowViewRegistry.tsx        |  21 +-
 .../app/hooks/__tests__/useTodoLists.test.ts       | 291 ---------
 .../app/hooks/__tests__/useViewState.test.ts       |  11 +
 packages/dashboard/app/hooks/useAppSettings.ts     |   5 -
 packages/dashboard/app/hooks/useViewState.ts       |   5 +
 .../__tests__/registerBundledPluginViews.test.tsx  |  14 +
 packages/dashboard/app/plugins/bundled-todos.d.ts  |   5 +
 .../app/plugins/registerBundledPluginViews.ts      |  18 +
 packages/dashboard/app/plugins/types.ts            |   4 +
 .../src/__tests__/todo-documentation.test.ts       |  68 ---
 .../dashboard/src/__tests__/todo-routes.test.ts    | 577 ------------------
 packages/dashboard/src/registry-manifest.json      | 101 +++-
 packages/dashboard/src/routes.ts                   |   1 -
 .../src/routes/plugin-bundled-runtimes.ts          |   1 +
 .../src/routes/register-integrated-routers.ts      |   2 -
 packages/dashboard/src/shared/dashboard-views.ts   |   6 -
 packages/dashboard/src/todo-routes.ts              | 342 -----------
 packages/dashboard/vite.config.ts                  |   8 +
 packages/dashboard/vitest.config.ts                |   8 +
 packages/desktop/scripts/workspace-tools.ts        |   1 +
 plugins/fusion-plugin-todos/README.md              |  20 +
 plugins/fusion-plugin-todos/manifest.json          |   6 +
 plugins/fusion-plugin-todos/package.json           |  38 ++
 .../fusion-plugin-todos/src/dashboard-interop.d.ts |  12 +
 plugins/fusion-plugin-todos/src/dashboard-view.tsx |   4 +
 .../src/dashboard/LoadingSpinner.tsx               |   1 +
 .../src/dashboard}/TodoView.css                    |   0
 .../src/dashboard}/TodoView.tsx                    |  16 +-
 plugins/fusion-plugin-todos/src/dashboard/api.ts   |  15 +
 .../src/dashboard/projectStorage.ts                |   3 +
 .../fusion-plugin-todos/src/dashboard/swrCache.ts  |   6 +
 .../src/dashboard/useConfirm.ts                    |   1 +
 .../src/dashboard}/useTodoLists.ts                 |   4 +-
 plugins/fusion-plugin-todos/src/index.ts           |   4 +
 .../fusion-plugin-todos/src/todo-routes.test.ts    |  46 ++
 plugins/fusion-plugin-todos/src/todo-routes.ts     | 156 +++++
 plugins/fusion-plugin-todos/tsconfig.json          |  28 +
 plugins/fusion-plugin-todos/vitest.config.ts       |   9 +
 pnpm-lock.yaml                                     |  64 +-
 pnpm-workspace.yaml                                |   1 +
 70 files changed, 671 insertions(+), 2531 deletions(-)

Fusion-Task-Id: FN-8762
Fusion-Task-Lineage: 3beb502c-3793-451b-b357-50c243395410
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-03 09:04:45 -07:00
gsxdsm
cb57093d03 refactor: domain folder layout (types, API, core, engine) (#2398)
## Summary

Wave 17 organizes Fusion into **domain folders** (stacks on #2397).

### Layout
- **core/types/** — board, task, agents, settings, merge, workflow,
mesh, …
- **core/src/** — agents, ai, async-stores, workflows, tasks, config,
db, …
- **dashboard/app/api/** — client, tasks, agents, git, missions,
planning, …
- **engine/src/** — agents, auth, execution, merge, missions, overseer,
worktree, …

Root keepers retained for large entrypoints (`store.ts`, `executor.ts`,
`merger.ts`, …).

Public barrels (`@fusion/core`, `@fusion/engine`, `app/api.ts` → legacy)
stay stable.

## Test plan
- [x] `@fusion/core` typecheck
- [x] `@fusion/engine` typecheck (pre-existing playwright-core noise
only)
- [ ] CI merge gate

**Stack:** #2394 → #2397 → **this PR**
2026-08-03 00:20:53 -07:00
gsxdsm
0e8f6769ba FN-8666: add credential instance pickers
Add credential-instance selection across dashboard model configuration surfaces.

- Expose provider credential instances in custom model dropdowns and task, workflow, and settings forms.
- Persist per-role credential-instance overrides through dashboard APIs and effective model resolution.
- Document credential-instance precedence and cover dropdown/settings behavior, including task state synchronization.

Files changed:
 .changeset/fn-8666-credential-instance-picker.md   |   7 ++
 docs/settings-reference.md                         |   2 +
 docs/workflow-steps.md                             |   2 +-
 packages/dashboard/app/api.ts                      |   1 +
 packages/dashboard/app/api/models-usage.ts         |  27 ++++-
 packages/dashboard/app/api/tasks.ts                |   8 ++
 .../app/components/CustomModelDropdown.css         |  12 ++-
 .../app/components/CustomModelDropdown.tsx         |  71 ++++++++++++-
 .../dashboard/app/components/InlineCreateCard.tsx  |  23 +++-
 packages/dashboard/app/components/ListView.tsx     |  29 +++++-
 .../app/components/ModelSelectionModal.tsx         |  25 ++++-
 .../dashboard/app/components/ModelSelectorTab.tsx  |  29 +++++-
 packages/dashboard/app/components/NewTaskModal.tsx |  23 +++-
 .../dashboard/app/components/QuickEntryBox.tsx     |  28 +++++
 .../dashboard/app/components/SettingsModal.tsx     |   2 +
 .../dashboard/app/components/TaskDetailModal.tsx   |  32 +++++-
 packages/dashboard/app/components/TaskForm.tsx     |  18 ++++
 .../app/components/WorkflowNodeEditor.tsx          |  13 ++-
 .../app/components/WorkflowSettingsPanel.tsx       |  38 ++++++-
 ...ustomModelDropdown.credential-instance.test.tsx | 111 ++++++++++++++++++++
 .../__tests__/WorkflowSettingsPanel.test.tsx       |   9 +-
 .../app/components/effective-model-resolution.ts   |   8 +-
 .../settings/sections/GlobalModelsSection.tsx      |  31 +++++-
 .../settings/sections/ProjectModelsSection.tsx     | 116 ++++++++++++++++-----
 .../ProjectModelsSection.chatDefault.test.tsx      |  33 +++++-
 packages/dashboard/app/hooks/useFavorites.ts       |   6 +-
 packages/dashboard/app/hooks/useModelsCache.ts     |   5 +-
 .../src/routes/register-task-workflow-routes.ts    |  17 ++-
 28 files changed, 655 insertions(+), 71 deletions(-)

Fusion-Task-Id: FN-8666

Fusion-Task-Lineage: 6c3711b3-68b8-47a0-ac36-4b64846adf39

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-01 04:03:26 -07:00
gsxdsm
5f12044168 FN-8652: add multiple provider credential instances
Enable operators to create, select, and remove named credentials for each supported provider.

- Add provider-auth instance discovery and credential mutation endpoints.
- Add dashboard authentication controls, status handling, and instance coverage.
- Document instance behavior and add a release changeset.

Files changed:
 .changeset/fn-8652-provider-credential-instances.md       |   7 +
 docs/secrets.md                                    |   2 +
 docs/settings-reference.md                         |   4 +
 packages/dashboard/app/api.ts                      |   1 +
 packages/dashboard/app/api/provider-status.ts      |  94 +++++-
 .../dashboard/app/components/SettingsModal.tsx     | 138 ++++-----
 .../AuthenticationSection.instances.test.tsx       |  75 +++++
 .../settings/sections/AuthenticationSection.css    |  13 +
 .../settings/sections/AuthenticationSection.tsx    | 199 +++++++-----
 .../dashboard/src/__tests__/routes-auth.test.ts    |  27 +-
 packages/dashboard/src/routes.ts                   |  12 +-
 .../dashboard/src/routes/register-auth-routes.ts   | 334 ++++++++++++++++++---
 .../src/__tests__/provider-auth-instances.test.ts  |  65 ++++
 packages/engine/src/provider-auth.ts               |  89 ++++++
 14 files changed, 845 insertions(+), 215 deletions(-)

Fusion-Task-Id: FN-8652

Fusion-Task-Lineage: 39568d58-7f57-4d17-97cb-1837323b3a94

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-01 01:07:59 -07:00
gsxdsm
189f237a07 fix(security): make the approval and permission gates actually enforce (#2457)
## Why

An AI agent autonomously deleted a live task (FN-8609) via
`fn_task_delete`. Investigating that led to two audits, which found the
gate machinery is well-built and its *enforcement* well-tested — but the
*decision boundary* was unguarded and the tools that matter never
reached the gate at all.

The headline defect: all ~76 tools in `packages/cli/src/extension.ts`
are delivered through `hostExtensionPaths` → `DefaultResourceLoader`,
which never passes through `wrapToolsWithActionGate`. `fn_task_delete`
*was* classified as gated in `gating-classifications.ts` — that
classification was dead code. Roughly 15 destructive tools were ungated
even for an operator who had locked their policy all the way down.

Second: `POST /api/approvals/:id/decision` took the approver identity
from the request body, validated for shape only, with no check that the
decider was human or differed from the requester. Combined with a bash
tool whose command string was never inspected (only `params.cwd`), an
agent could read the daemon token from `~/.fusion/settings.json`, find
its own pending request, and approve it.

## Scope

This does **not** tighten defaults. The `unrestricted` preset is
byte-for-byte unchanged — `git diff` on `agent-permission-policy.ts` is
empty — and regression tests assert that an out-of-the-box install
behaves exactly as before. The bug was never "the default is too
permissive"; it was "strict policy doesn't enforce." This makes turning
security up actually work.

The one deliberate exception: the containment that stops an agent
escalating its *own* privileges (reading the daemon token / credentials,
calling the approvals API to self-approve) applies at every preset
including `unrestricted`. That is a privilege-escalation boundary rather
than a permission preference — if it only engaged under strict policy it
would not have prevented the incident that prompted this.

## What changed

8 bisectable commits:

- **Approval lifecycle** — self-approval blocked via server-derived
deciders; same-verdict replay 409s; decide re-reads and re-validates
inside the transaction; expiry TTLs; `markCompleted` ownership check;
session identity registry in core.
- **Engine gates enforce for real** — unclassified tools resolve to a
policy-governed category instead of hardcoded `allow`; missing-policy
fail-open closed; bash containment floor + exact-command approval
binding.
- **Dashboard decision routes** — stop trusting client-supplied actors
(decision, bypass-review, worktrunk → 403 on forged actors).
- **`fn serve` authenticated by default** — auto-mints a token following
the existing `fn dashboard` precedent; `--no-auth` opts out.
- **Sibling entry points closed** — user-sourced hard-cancel moves, ACP
execute-once approvals, plugin task-store gating.
- **pi-extension principal resolution** — the extension resolves the
acting principal and can withhold or policy-gate the previously ungated
destructive tools.
- **Root-cause bonus fix** — `findLatestByDedupeKey` was broken in
PostgreSQL backend mode (already-parsed jsonb fed through a string-only
parser), so approved-grant redemption **never matched in production**,
minting duplicate requests. This explains the live DB state of 17
approved / 0 completed. *(Also cherry-picked to `main` as `a9b30013bb`,
since it is an active production defect on its own.)*
- **Review follow-ups** (`627f1b1fa8`) — operator-configured
provisioning privilege and a configurable grant TTL; see below.

## Review follow-ups

**Provisioning privilege is operator-configured, not role-derived.**
`isCallerPrivileged` had gone from `caller.reportsTo == null` (every
top-level agent privileged — permanent escalation by creating a
manager-less agent) to `caller.role === "ceo"`, which swapped an
implicit rule for a magic string: any agent config can claim that role,
while an operator who genuinely wants a privileged agent had no
supported way to say so. Privilege now derives solely from
`agentProvisioning.trustedAgentIds` / `trustedRoles` and fails closed
when settings are unresolvable.

It is also no longer forwarded to `resolveAgentProvisioningPolicy` as
`isPrivileged`, because that flag short-circuits ahead of
`alwaysApproveDelete` — a trusted caller was bypassing delete approval
entirely. The policy applies the same trusted rules itself, in the right
order. The function now governs only the org-chart escape hatch (acting
outside your own direct reports).

**Grant TTL defaults to 1 hour and is configurable.** Approval →
redemption is not instantaneous: an operator approving from their phone,
an engine restart, a queued lane, or a task waiting on a worktree all
routinely exceeded 15 minutes, after which the grant expired and the
agent silently re-requested. One hour remains far short of the
"redeemable forever" hazard the TTL exists to bound. Override via
`FUSION_APPROVAL_GRANT_TTL_MS` or `configureApprovalRequestTtls()`;
invalid overrides are ignored rather than widening the window to
infinity or collapsing it to zero.

## Behavior changes requiring operator review before rollout

1. `fn serve` requires a bearer token by default (`--no-auth` opts out);
unauthenticated clients get 401.
2. Agents can no longer run withheld destructive tools
(`fn_task_delete`, `fn_task_bypass_review`,
mission/milestone/slice/feature/workflow deletes, `experiment_finalize`,
`skills_install`). Operators keep them via CLI/dashboard. **This is the
incident fix.**
3. Agents get provisioning privilege only when the operator lists them
in `agentProvisioning.trustedAgentIds` / `trustedRoles`; the
provisioning gate is now live in production. Previously-implicit
privilege (top-level position, or a `ceo` role) no longer grants
anything on its own.
4. Decision replay 409s (was 200); pending approvals expire after 24h,
approved grants after 1h (configurable); bash approvals bind per exact
command.
5. Forged/body actors on decision, bypass-review, worktrunk routes →
403; `archive-all-done` requires `{confirm:true}` (external scripts
affected).
6. `fn_secret_get` approvals grant exactly one reveal (previously
granted nothing and looped forever); ACP approvals are execute-once
(previously infinite reuse).
7. Bash containment denies token/credential/approvals-API commands in
all agent sessions at every preset.

## Verification

Independently re-run against the branch, not just self-reported:

- 5 typechecks (core, engine, cli, dashboard `tsconfig.json` +
`tsconfig.app.json`) — clean
- `pnpm lint` — clean
- `pnpm test:gate` — 379 passed
- `pnpm build --force` — green (a plain `pnpm build` skips packages as
unchanged and does **not** compile the branch)
- `pnpm check:changesets` — clean
- ~650 file-scoped tests including new negative-path suites for the
decision boundary, which previously had **zero** test coverage

`packages/engine/src/__tests__/plugin-runner.test.ts` fails 56/80 —
**verified pre-existing**, reproducing identically at base commit
`93a403af67` on `main`. Not in the merge gate.

### A mutation check that failed to fail

Worth recording, because it nearly shipped an untested security fix. The
first mutation check on the provisioning change reintroduced the `ceo`
hardcode and **all 17 tests still passed** — the tests asserted through
the policy path, which can no longer observe `isCallerPrivileged` at
all, precisely because `isPrivileged` is no longer forwarded there.
Org-chart cases that do exercise the function were added; the hardcode
now fails exactly 1 of 19, and restoring is green. A green mutation run
is only meaningful if the test can actually see the code under test.

## Known limitations (stated, not papered over)

- The bash containment floor is string-matching: a cost-raiser, not a
sandbox. Quoting, encoding, `$HOME`, symlinks, or an interpreter
one-liner can evade it. The durable protection is the decision route
refusing agent-originated deciders — the filter is the belt, not the
braces.
- Approval expiry is lazy (evaluated at decide/complete/redeem), not
swept, so an expired pending row stays visible in lists until touched.
- The extension's require-approval path returns a pending message but
cannot suspend a pi session mid-turn; engine-side pause hooks cover
engine lanes only.

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

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

## Summary by CodeRabbit

* **Security**
* Hardened approval and permission gating with server-side decider
attribution, self-approval blocking, ownership checks, replay/race
protection, and status/TTL enforcement.
* Added fail-closed behavior for sensitive/unclassified tools and
sandbox provisioning approvals.
* Blocked credential/approval access via bash containment; plugin
destructive task operations now require explicit permission.
* **New Features**
* `fn serve` now defaults to bearer-token auth, with `--no-auth` as the
explicit opt-out.
* **Bug Fixes**
* Improved task move-source attribution (`moveSource: "user"`) and
tightened dashboard archive/bypass confirmation and operator attribution
behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 21:50:37 -07:00
gsxdsm
fd795883c5 feat(missions): per-mission taskPrefix override for triaged task ids (#2347)
## Summary
Maintainer re-land of
[#2334](https://github.com/Runfusion/Fusion/pull/2334) (fork
`flexi767:feat/per-mission-task-prefix`) after resolving merge conflicts
with current `main`.

Fork push was unavailable despite `maintainerCanModify`, so this branch
carries the conflict resolution.

### Feature
- Optional per-mission `taskPrefix` for triaged task ids (inherits
project prefix when unset)
- Dashboard MissionManager + routes + store/triage plumbing
- Postgres migration for `project.missions.task_prefix`

### Conflict resolution
- Main claimed migration **0026** (bigint counters) and **0027**
(workflow IR pin)
- Mission task-prefix migration renumbered **0026 → 0028**
- Baseline `0000_initial.sql` includes `task_prefix` on missions
- `legacy.ts` keeps code-org re-exports; `missions.ts` carries
`taskPrefix` on create/update types

## Test plan
- [ ] CI green (lint/typecheck/build/gate)
- [ ] Create mission with custom prefix; triage feature → task ids use
that prefix
- [ ] Clear mission prefix via PATCH null; new tasks inherit project
prefix

Closes / supersedes #2334 once this lands (or re-point the fork PR).

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

* **New Features**
* Missions can now set an optional per-mission task ID prefix
(overriding the project default).
* Added task prefix support to mission create/edit UI and dashboard
APIs, including normalized uppercase values and validation.
* **Bug Fixes**
* Improved commit hook generation for custom prefixes and special
characters, with safer shell handling to prevent unsafe interpretation.
* **Chores**
* Added PostgreSQL migration and schema-applier support to persist and
propagate mission task prefixes, including upgrade/backfill coverage.
* **Tests**
* Added backend and UI/API test coverage for task-prefix creation,
clearing, and ID minting behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 21:35:23 -07:00
gsxdsm
647bac5b21 test(dashboard): lowercase header keys + the client stamp (1 red → 0) — and 88 dashboard failures CI never runs (#2732)
## The fix

`app/api/client.ts` builds request headers through a `Headers` object —
which lower-cases every key — and stamps `x-fusion-client: dashboard-ui`
on every dashboard-originated request so the server can attribute the
caller (the FN-8609 delete-attribution surface).

This test asserted `"Content-Type"`, and `expect.objectContaining`
compares keys **case-sensitively**, so it failed on casing alone.

Rather than only lower-casing the key, it now pins the **client stamp**
too — that header is the point of the feature and nothing else in this
file covered it.

| Check | Result |
|---|---|
| `plugin-setup-api.test.ts` | 1 failed → **3 passed** |
| client stamp neutered in `client.ts` | **1 failed** / 2 passed —
load-bearing |
| `pnpm lint`, dashboard app `tsc` | clean |

## Method correction — I nearly filed 40 phantom failures

Measuring this package with a raw `vitest run` reports **~40 failing
files**. That number is worthless: `@fusion/dashboard`'s own `test`
script is `node scripts/run-quality-tests.mjs`, which runs the quality
projects as **separate invocations** with per-group heap sizes and
exclusions. Running every project in one process fails en masse for
reasons unrelated to the code.

Correct command — `pnpm --filter @fusion/dashboard test` — gives **9
failing files / 88 failing tests**, exit 1.

## The finding: those 88 failures are never executed in CI

I first concluded "CI shows no dashboard failures, so these are
local-only." **That was wrong, and the reason matters.**

CI does schedule the dashboard quality groups — they are distributed
across all four shards as individual `test:quality:*` invocations. Shard
2's plan, for example:

```
[ci-test-shard] shard 2/4: @fusion/core [2/2], @fusion/dashboard run test:quality:app:components-b,
                @fusion/dashboard run test:quality:app:backfill-1, ...
```

But only two invocations ever get a `(watchdog budget 1500s)` start
line: the plugins group and `@fusion/core [2/2]`. `components-b` never
starts, because the shard aborts on the first failing package —
`ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL`, present in shards 1, 2 and 4.

**So the dashboard quality groups are not passing — they are unrun**,
behind a package that fails first. Consequences:

1. **Fixing core/engine/CLI will unmask 88 dashboard failures.** My
merged PRs move shards 1/2/4 toward green; as each earlier package stops
failing, these groups begin executing for the first time. Expect the
shard counts to *rise* before they fall — that is progress, not
regression.
2. **Reading shard conclusions is misleading.** A shard says "core
failed"; it does not say "and everything scheduled after core never
ran."

Where the 88 live (all files currently unowned):

| File | Failures | Lane / shard |
|---|---:|---|
| `TaskDetailModal.inline-editing-and-integrations` | 50 |
`components-b` / shard 2 |
| `auto-merge-toggle-blank.mobile-integration` | 13 | `components-a` /
shard 3 |
| `auto-merge-toggle-blank.mobile` | 8 | `components-a` / shard 3 |
| `TaskDetailModal` | 6 | `components-b` / shard 2 |
| `SecretsView` | 4 | `components-b` / shard 2 |
| `WorkflowNodeEditor` | 3 | `components-b` / shard 2 |
| `TaskCard` + `TaskCard.badge-wrap` | 3 | `components-b` / shard 2 |
| `board-mobile` | 1 | `components-a` / shard 3 |

Dominant symptoms: `Unable to fire a "click" event - please provide a
DOM element` (29), `Unable to find an accessible element with the role
"checkbox" and name "Auto-merge"` (13), `expected null to be truthy` (7)
— consistent with a small number of shared render/affordance causes
rather than 88 independent bugs, but I have not isolated them.

**I am not starting that repair in this PR.** It is a 9-file, 88-test
area needing per-cluster diagnosis, and bundling it behind a one-line
header fix would produce exactly the shallow work this program keeps
rejecting. Filed here with the correct measurement command, the
lane/shard mapping, and the reason CI has been silent about it.
2026-07-30 05:33:00 -07:00
gsxdsm
e9e63d8e0f consolidate/capacity: --strict was red on main (my #2621), 14 stale baselines, routines seeding a deleted column, worktrees-off audit (#2652)
Capacity unit consolidation. Three coherent themes, small commits
inside.

## Census before/after (`node scripts/lifecycle-column-census.mjs`)

| | before | after |
|---|---:|---:|
| triage column guards (the bar) | 10 | **10** |
| `--strict` on main | ❌ **RED** | ✅ green |
| baseline staleness | 14 files stale | **0** |

This branch does **not** move the triage bar — its remaining 10 are
moves.ts (dies with the flag), the dashboard cluster, and one deliberate
site. It fixes the instrument that measures the bar, plus a live defect
the comparison count cannot see.

---

## 1. `--strict` was RED on clean `origin/main`, and it was my fault

```
packages/dashboard/src/routes/register-task-workflow-routes.ts: 22 -> 23
```

My merged #2621 added a v1-IR pre-WIP fallback answering a greptile P1
and shipped no marker or baseline update, so the program's measuring
instrument has been failing on main since it landed.

Fixed **at the site** with a `DELIBERATE-LITERAL` marker, not by bumping
the baseline. That branch runs only when the IR declares no columns and
no nodes, so there is no role to resolve — `resolveLifecycleColumns`
returns nothing and the legacy pre-implementation ids are the only
pre-WIP signal that exists there. It is *unconvertible*, not unfinished;
the sibling `else` two lines down is the trait path for every IR that
can answer. A rise that is genuinely correct belongs where a reader will
see it.

## 2. The baseline was stale for 14 files — a hole, not cosmetics

A stale allowance lets converted guards return while the check stays
green. Measured gaps:

```
self-healing.ts          allows 126, tree has 111
executor.ts              allows 112, tree has 104
moves.ts                 allows  44, tree has  39
default-workflow-hooks   allows  25, tree has   7
mission-feature-sync     allows   5, tree has   0
MissionControlPanel      allows   4, tree has   0        (+8 more)
```

**Only two of the fourteen are mine.** The other twelve are
already-merged conversions by other workers where nobody re-recorded.
Re-recorded all fourteen here rather than waiting for twelve PRs,
because until it happens the ratchet is not holding the 779 it exists to
hold. Flagging it plainly: those drops are other people's work being
locked in, not mine being claimed.

## 3. Routines created tasks into the column U11 deleted

The routine editor's "Target Column" defaulted to `triage`. That value
is submitted as the create step's `taskColumn`, and an **explicit**
column bypasses the workflow entry-column resolution added for
column-less creates (#2589) — so every routine saved with the untouched
default seeded its tasks into a column the board does not declare.

Defaulting to `todo` would be the same mistake one column over: a custom
workflow declaring no `todo` is seeded into an undeclared column just as
surely, because an explicit column overrides entry resolution whatever
its value. So the default sends **nothing** and each workflow's own
intake resolution decides.

The `triage` **option** is removed too, not merely un-defaulted — fixing
the initializer alone left the operator able to pick the deleted column
one click away, and it was the option labelled "Planning", the name the
merged `todo` column now displays. Removing it retires that label
inversion as well.

Found by scanning **membership** forms rather than comparisons: the
comparison census cannot see a `?? "triage"` default, so no count showed
this and nobody was looking. Revert-proof — restoring the default fails
with *"the default must not name a column at all"*.

## 4. "Worktrees off is INERT" had one unaudited reader

The constraint was that `maxWorktrees` become genuinely inert, "not set
very high and not skipped by convention". `resolveWorktreeCapacityLimit`
returns `null` for that, and its unit tests can only prove the
**resolver** is right — they cannot see a second reader, which is the
only way the constraint breaks.

Audited every `maxWorktrees` read that bounds anything. **Exactly two:**
`scheduler.ts` (the admission gate, via the resolver, single call site,
optional gate snapshot) and `self-healing.ts`'s `enforceWorktreeCap` —
`(settings.maxWorktrees ?? 4) * 2`, a **raw** read.

The second is **not a bug** and is left alone: it bounds worktree
*directories on disk* and only removes *idle* ones. Worktrees still
exist in OFF mode, so that bound must keep applying or idle directories
accumulate unbounded. Recorded consequence: in OFF mode the number still
governs disk retention while gating no admission — an edge you scoped
out. The note says explicitly **not** to unify the two readers: routing
hygiene through the resolver returns `null` in OFF mode and silently
removes the disk bound, which is a leak dressed as a simplification.

New ratchet requires every file bounding on `maxWorktrees` to be named
with a reason, and rejects a **stale** allowlist entry. Proven by
injecting `active >= (settings.maxWorktrees ?? 4)` into
`hybrid-executor.ts`.

---

## Deliberately NOT included

- **My own census script.** #2633 landed the canonical one, and it is
better than mine — an AST classifier *plus* an independent text
classifier with `--compare`, and a baseline that fails on unrecorded
**drops** as well as rises. Mine only caught rises. I deleted mine
rather than ship a second measuring instrument; three copies of "strip
comments" is the drift shape this program keeps paying for, so the
worktree ratchet now imports #2633's `stripComments`.
- **My TaskContextMenu fix.** Superseded, and by a better answer: main's
`isPureIntakeColumn` (intake *without* hold) keeps the merged Planning
column shown and suppresses only a bare Ideas capture, which resolves
the exact hold-lane objection coderabbit raised against my version. I
briefly clobbered that merged work by checking my old file out
wholesale, caught it in the diff, and reverted.

## Verification

`pnpm lint` clean · core + dashboard `tsc` clean · census suite 23/23 ·
worktree ratchet 8/8 · RoutineEditor 49/49 ·
`routes-task-retry-planning-column` 16/16 · `lifecycle-column-census
--strict` exits 0.

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

---

## Added after review (all four greptile threads were real, and two of
them mattered)

**The routine fix was half a fix.** `routine-runner.ts:515` *and*
`cron-runner.ts:982` both did `column: (step.taskColumn as Column) ||
"triage"` **after** the step is read, so every routine — including ones
saved through the fixed editor — still created tasks into the deleted
column. Both now omit it.

**The advanced steps editor MANUFACTURED the defect.**
`ScheduleStepsEditor.tsx` had three `triage` defaults: the new-step
template (`:64`), the per-step initializer (`:95`), and the select still
offering it (`:344`). So the path I had *not* fixed produced the bug by
default, on fresh data. Template names no column; initializer coerces a
persisted `triage`; `triage` removed from the options; empty submits
`undefined`.

**Four pre-existing tests pinned the defect** and are rewritten to the
corrected invariant rather than appeased:

| test | asserted |
|---|---|
| `cron-runner`: "defaults column to triage when taskColumn is not set"
| `column: "triage"` |
| `ScheduleStepsEditor`: "adds a create-task step..." | `taskColumn`
toBe `"triage"` |
| `ScheduleStepsEditor`: "allows saving create-task step..." | the
legacy column is **resubmitted** |
| plus the explicit-column case added beside each, so the fix cannot
swallow a deliberate choice |

**The allowlist hole was the worst finding.** `AUDITED_BOUNDS` was keyed
by FILE, so every bounding expression in an allowlisted file was exempt
— a second raw bound in `scheduler.ts` stayed green, the one case that
ratchet exists for. Per-expression now, and making it so **immediately
surfaced a real second bound the file-level version was hiding**
(`maxWorktreesGate.used >= maxWorktreesGate.limit`, safe by construction
since the snapshot is `undefined` in OFF mode). Proven by injection.

## Found while re-reading my own deletion, not reported

A **rendered tooltip** still named a deleted cap. The "Queued to plan"
badge read *"planning starts when a concurrency slot frees up
(maxConcurrent / globalMaxConcurrent)"*. The cross-project cap is gone —
capacity is two numbers per project — so it told operators their
planning waited on a limiter they can no longer find a setting for.
Names the surviving dimension only now.

## Coding (Ideas): enforcing #2651 rather than repeating it

I took the unowned coding-ideas IR merge, concluded it must not be done,
then found **#2651 had already implemented, reverted and documented
exactly that** — with better grounding than my own argument. It added no
test, so nothing stops the next person reaching the same dead end.

So this ships their reasoning as a ratchet, not a second opinion: triage
discovery keys on the column's `autoTriage`, so a merged column is
either never scanned (cards sit on a bootstrap stub until the **capacity
hold** releases them, sending **unplanned** work into in-progress —
worse than stalling) or scanning wins and the manual gate is gone. Their
scope caveat is kept: `autoTriage` is a general trait field, so only
*this preset's* collapse is dead, not manual intake as a concept. The
registry does not reject the merged shape, which is why prose was not
enough.

## Verification (re-run)

`pnpm lint` clean · core + engine + dashboard-app `tsc` clean ·
`lifecycle-column-census --strict` exits 0 ("every file matches its
baseline exactly") · routine-runner 24/24 · cron-runner 156/156 ·
ScheduleStepsEditor 41/41 · RoutineEditor 49/49 · worktree +
coding-ideas 12/12. TaskCard has 2 failures **pre-existing on main** —
confirmed identical with my changes stashed.

---

## Bears directly on the closing bar: this PR already removes the
67-guard ratchet slack

Measured on current `origin/main` with the census itself:

```
tree total: 787   baseline total: 854   SLACK: 67

FILES ABOVE BASELINE (1):
   +1  packages/dashboard/src/routes/register-task-workflow-routes.ts  (22 -> 23)

FILES BELOW BASELINE: 13, totalling 68 unrecorded conversions
   -18  core/default-workflow-hooks.ts (25->7)   -15  engine/self-healing.ts (126->111)
    -8  engine/executor.ts (112->104)             -5  core/task-store/moves.ts (44->39)
    -5  engine/mission-feature-sync.ts (5->0)     -4  core/live-agent-count.ts (10->6)
```

**The slack is not regression — it is 13 files of merged conversions
nobody re-recorded**, against exactly **one** rise. This PR re-records
the baseline **854 → 782 across 140 files**, which closes it.

**And the "+3 that slipped in" is +1, and it is mine.**
`register-task-workflow-routes.ts 22 → 23` is the v1-IR pre-WIP fallback
my #2621 added; it is justified (that branch runs only when the IR
declares no columns or nodes, so there is no role to resolve) but it
shipped with no marker and no baseline update — which is why `--strict`
has been **red on main since it merged**. Fixed here at the site with a
`DELIBERATE-LITERAL` marker rather than by bumping the baseline, because
a rise that is genuinely correct belongs where a reader will see it.

Sequencing note for the auto-lowering change: if this lands first, that
work is purely the mechanism (auto-lower, or fail with tighten
instructions) rather than a cleanup, and the two re-records will not
collide in the same file.

Also worth carrying into that mechanism, from building the same guard
here: **`--update` must refuse to RAISE.** An earlier version of mine
wrote current counts verbatim, so a developer who added a literal and
ran the documented update command locked the regression in as the new
ceiling — the mirror of the high-water problem. Lowering can be
unattended; raising should be a hand edit with the reason recorded.

## Third piece of residue from my own deletion

`updateGlobalConcurrency` in the dashboard API client PUT to
`/api/global-concurrency`, a route removed when the machine-wide cap
went. Zero callers; the only reference was the `legacy.ts` barrel
re-export. Deleted both. `fetchGlobalConcurrency` **survives on
purpose** — the GET route remains and serves live utilization telemetry
to the footer and Command Center; nothing gates on it.

That is the third: after the second raw `maxWorktrees` reader and the
"Queued to plan" tooltip. A deletion is not finished when the
enforcement goes — the client, the label and the tooltip outlive it.

---

## Re-greened the dashboard API tests: 117 failures on main, ONE root
cause

These would have polluted the closing verification pass, and nobody
owned them.

`api()` builds headers via `new Headers(...)` and returns
`Object.fromEntries(headers.entries())` — and `Headers.entries()`
**lowercases every key**, so the object reaching `fetch` is
`content-type`, not `Content-Type`. `ab87d0d80` then added
`x-fusion-client: dashboard-ui` for run-audit attribution. Both changes
are correct; neither is visible at a call site, so **114 assertions
across 7 files** kept asserting the old shape and went red together.

Fixed by naming the shape **once** in `app/test/apiRequestHeaders.ts`
rather than patching 114 literals — restating a shared fact 114 times is
what made a two-line client change look like 117 failures. Deliberately
not a loose `objectContaining`: these tests are the only thing pinning
that the attribution header is sent *at all*.

**117 → 4.** The remaining 4 are unrelated pre-existing CSS failures
(`task-detail-modal-tablet-width` ×3, `space-token-defined` ×1) —
confirmed identical on clean main with my changes stashed.

### A gap this surfaced, recorded not papered over

Three routes failed in the *opposite* direction — they send the old
shape because they call `fetch()` **directly**, bypassing `api()`, so
they never get the attribution header. `client.ts` claims the opposite:

> "Applied once here rather than per-call so no future mutation route
has to remember it."

That does not hold for a route that bypasses the helper it is applied
in. **Measured in `app/api/`: 8 files make direct `fetch()` calls and 7
include mutations (POST/DELETE)** — among them `ai-sessions.ts`'s
DELETE, which is the same class as the four-delete incident the header
was added for. So the attribution fix has a hole in exactly its
motivating case.

Not fixed here: routing those onto `api()` is a behaviour change across
the API layer and belongs to its owner, not to a test re-green. Those
assertions use a separate `API_JSON_HEADERS_NO_ATTRIBUTION` constant so
the gap stays **visible** — if a route is later moved onto `api()`, its
test fails and points at the note explaining why.

---

## This branch takes the triage bar 10 → 5, and makes `--strict` green

`node scripts/lifecycle-column-census.mjs` on this branch reports
**triage 5**, against **10** on `origin/main`. The five removed are the
ScheduleStepsEditor template/initializer/option and the RoutineEditor
default/option — the automation paths that were creating tasks into the
deleted column.

**`--strict` was also RED on clean main, twice over, and both causes
were the same mistake:** a thorough written rationale the tool cannot
read, because the marker was not where the census looks. The census
reads a comparison node's **leading comments**; a `DELIBERATE-LITERAL`
in the JSDoc above the enclosing function or declaration does not reach
the comparison inside it.

| site | why it is legitimate | why the tool could not see it |
|---|---|---|
| `columnRoles.ts:80` `isHoldColumnRole` | degrades to `columnId ===
"todo"` only when a column has **no resolved traits** — identical in
kind to `LEGACY_PRE_IMPLEMENTATION_COLUMN_IDS` directly above, which
escapes counting only because a Set is a membership form | rationale
written, **no marker token** |
| `MissionControlPanel.tsx` ×3 | the SDLC funnel **alias table** — maps
`to-do`/`ready`/`review`/`shipped` onto one display stage with an
explicit `other` bucket, and nothing branches on it | marker in the
JSDoc; the comparisons are arrow bodies **inside the array literal**,
which it does not reach |

The second only surfaced because converting the `triage` stage to a Set
removed its count and exposed the siblings — red gate, justification
sitting three lines above, unreachable.

Both are markers, no behaviour change. Neither is a conversion
candidate: resolving the funnel table to traits would **drop the
non-column aliases it exists to accept**.

**For the auto-lowering work:** the marker-placement rule is now the
recurring trap — three instances, three different authors, including me.
A marker that does not register is indistinguishable from no marker, and
the failure mode is a red gate with a written explanation nobody can act
on. If the census accepted a marker anywhere in the enclosing
declaration's comments, none of the three would have happened.

Baseline re-recorded per the tool's own instruction ("Re-record the
baseline in the SAME PR that lowered the count").


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

- **Bug Fixes**
- Task “Actions” menus no longer appear on bare cards in the Planning
column.
- Routines, scheduled tasks, and create-task steps now respect each
board’s configured workflow intake column instead of using a retired
default.
- Legacy tasks saved with the retired intake column are migrated to
automatic workflow resolution.
- Target-column selection now offers only “Automatic (workflow intake)”
and “Planning,” removing the obsolete option.
- Capacity/planning messaging and related UI tooltip text were
clarified; concurrency cap updates are managed per project.

- **Tests**
- Added/updated coverage for workflow intake resolution, create-task
target column behavior (including legacy coercion), capacity safeguards,
and API request consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 03:10:35 -07:00
gsxdsm
3cef9c226e Drift 1/4: TaskCard planning affordances from traits, not "triage" (8→3 measured; one site needed a new wire fact, one conversion was wrong and the tests caught it) (#2558)
## Drift conversion 1 of 4 — TaskCard.tsx

Taking the dashboard surfaces from the drift review. This is the
board-card one; ListView, TaskDetailModal and
register-task-workflow-routes follow separately so each stays
revertable.

### Convergence number

`task.column === / !== "todo" | "triage"` in `TaskCard.tsx`: **8 → 3**

The three survivors are **one documented fallback**, not scattered
checks. `getTaskColumnFlags` (Column.tsx) returns `undefined` when a
card's column is absent from the resolved metadata and is not the
rendering column — the pre-load window, and a card stranded in a lane
its workflow dropped. Converting to bare trait reads would have removed
every planning affordance in exactly those states, so the legacy ids
survive **once**, at the role helpers, plus the move prompt resolving
its own target. They retire with the load window, not with this change.

I'd rather report 8 → 3 with the reason than 8 → 0 with a regression
behind it.

### Why this file was urgent

Every planning affordance was gated on `task.column === "triage"`. Land
U11 — merged column keeps id `todo`, `triage` deleted — and each
comparison silently becomes false: **delete button, awaiting-approval
controls, planner badge, step list all vanish from planning cards.**

### One site needed a new fact on the wire, not a renamed comparison

`showStartAction` was `intake === true && column !== "triage"`. That
hardcoded id was standing in for *"an intake column that does not
auto-triage"* — a distinction that lives in trait **config** (`intake`
with `autoTriage: false`) and was invisible to every client.

It also **inverts** under U11: with `triage` deleted, `column !==
"triage"` is vacuously true, so a Start button would appear on **every
planning card**. `describeColumns` now derives `manualIntake`
server-side and the gate reads it. Renaming the comparison would have
shipped the inversion.

### One conversion was wrong, and the tests caught it

I first converted the move-progress prompt to the card's *own* column
role. The original tests the move **destination** — moving a card *back*
into a pre-implementation lane is what risks discarding step progress.
`confirms preserving progress before moving` failed immediately on an
`in-progress → todo` move. It now resolves the target column's flags.

That is the argument for red-green per site rather than pattern-matching
the comparison: the regex looks identical at both sites and means
different things.

### Revert-proof

New `TaskCard.u11-merged-column.test.tsx` renders cards in the
**post-U11 shape** — id `todo`, traits `intake + hold`, no `triage`
anywhere — and asserts Delete, the planner badge and the step list still
appear; that Start does **not** (auto-triaging); and that a
manual-intake lane does get it. Revert any converted site and the
matching case fails, because these cards are not in `triage` and never
will be again.

### Fixture updates, and why they are not weakening

- Start-affordance cases now pass `manualIntake`, which the server
supplies for a manual intake lane.
- "omits the Start button for the triage column even when intake is
flagged" → "for an **AUTO-triaging** intake column". The rule was never
about the id; the title said it was.

### Verification

`pnpm test:gate` (414 + 10 + 71), `pnpm lint`, both dashboard typechecks
green. **No new failures**: `TaskCard.test.tsx` reports the same 2
pre-existing failures with and without the change, verified by diffing
failing test *names* against a stashed clean tree rather than comparing
counts.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 09:54:16 -07:00
gsxdsm
da0351857e U12 part 5: put real workflow adjacency on the wire — custom-workflow move menus were guessing (measured), and the VALID_TRANSITIONS shortcut is gone (#2525)
## U12 part 5 — the move menu was guessing; now it asks the graph

**Stacks on #2521** (same file). Merge that first.

The context menu had **no adjacency data at all**, so it did two wrong
things at once: it approximated move targets from a column's
**neighbours in declared order**, and — because that approximation is
strictly weaker than the real graph — it kept a `VALID_TRANSITIONS`
shortcut for any workflow whose column-id set matched the six built-ins.

Measured, the approximation loses real operator moves:

| current | workflow graph | neighbour approximation |
|---|---|---|
| `in-progress` | in-review, todo, triage, done | todo, in-review |
| `todo` | in-progress, triage, archived | triage, in-progress |
| `done` | todo, triage, archived | in-review, archived |

So **every custom workflow has been offering a guess**: menu entries the
store would reject, and legal moves it never offered. The built-ins were
fine only because the shortcut bypassed the guess entirely.

### The fix

`BoardWorkflowColumn` gains `moveTargets`, resolved by
`resolveAllowedColumns` — *the same resolver `moveTaskInternal`
validates against*. The menu now offers exactly what the store will
accept, for any workflow. Threaded through all four metadata builders
(Board, Lane, ListView, TaskDetailModal).

Optional on the wire, deliberately: a client older than this field keeps
the neighbour fallback rather than losing its move menu mid-upgrade.

### Why deleting the legacy shortcut is safe

Not an assertion — a measurement, then a pin.
`resolveAllowedColumns(BUILTIN_CODING_WORKFLOW_IR, c)` is **identical to
`VALID_TRANSITIONS[c]` for all six columns, order included**:

```
triage       ["todo","archived"]                     == VALID  SAME
todo         ["in-progress","triage","archived"]     == VALID  SAME
in-progress  ["in-review","todo","triage","done"]    == VALID  SAME
in-review    ["done","in-progress","todo","triage"]  == VALID  SAME
done         ["todo","triage","archived"]            == VALID  SAME
archived     ["done"]                                == VALID  SAME
```

`builtin-adjacency-matches-legacy-transitions.test.ts` pins it so the
equivalence cannot drift silently — if the built-in workflow's edges
change without `VALID_TRANSITIONS` following, default menus change shape
and that test fails first. It compares **order** too, since the menu
renders targets in the order it receives them, so a reorder is
operator-visible.

Default-workflow menus are therefore byte-identical. Custom ones stop
guessing.

### What's left of the legacy vocabulary here

`COLUMNS` is gone from `TaskContextMenu` — deleting the shortcut removed
its last use. `VALID_TRANSITIONS` survives for exactly one thing: the
**no-metadata load window**, documented at the site. I measured removing
that in #2521 and it left Task Detail with no move options during load,
which is a regression rather than a cleanup. It retires when the load
window does.

### Revert-proof, two ways

- Drop the `declaredTargets` branch → the custom-workflow case fails:
the neighbour fallback returns `["backlog","building"]`, missing the
legal `shipped` jump **and** offering `backlog`, which that graph
forbids. That is exactly the defect class shipped to every custom
workflow today.
- A second case pins that an adjacency edge into a column the board
cannot show is **dropped**, not rendered as a dead menu entry.

### Verification

`pnpm test:gate` (309 + 10 + 71), `pnpm lint`, `pnpm verify:fast`, core
+ dashboard typechecks green.

**No new test failures**: five suites report 31 failures with and
without the change — an identical, pre-existing set, verified by diffing
failing test *names* against a stashed clean tree, not by comparing
counts.


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

* **Bug Fixes**
* Move menus for custom workflows now show only the destinations
permitted by that workflow.
* Task-specific workflow rules are applied consistently across boards,
lists, lanes, and task details.
  * Invalid or unavailable destinations are excluded from move options.
* Existing clients remain supported when workflow destination data is
unavailable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 23:23:00 -07:00
gsxdsm
3f33cb000f feat: per-origin workflow selection + feedback-derived refinement titles
Two task origins had no workflow picker in front of the operator and always
inherited the project default: `fn task create` (CLI + the `fn_task_create`
agent tool) and refinement tasks. Add a Project General setting for each, where
blank/unset means "Selected workflow" (the operator's current Board lane,
falling back to the project default) and a concrete id pins that origin.

Because the Board lane lives in browser localStorage, non-browser callers could
not resolve "Selected workflow" at all. `boardSelectedWorkflowId` mirrors the
lane into project settings so they can. Note this makes the mirrored lane
project-scoped: two operators on one project share it, last switch wins. The
Board never reads it back, so the only effect is which workflow a newly created
task inherits.

Resolution is `TaskStore.resolveOriginWorkflowOverrideId(origin)`: pinned
setting -> mirrored lane -> `undefined` to inherit each caller's existing
default-workflow path unchanged. A deleted or fragment id degrades to inherit
rather than throwing, so a stale settings value can never break task creation.
An explicit `workflow_id` argument to `fn_task_create` still wins.

Separately, a refinement is now titled by the operator's own feedback via the
shared `deriveFallbackTaskTitle`, not `Refinement: <parent title>`. Ten
refinements of one task previously rendered ten identical titles, so the board
could not tell them apart while the text saying what each one asked for sat in
the description. Provenance moves to a `Refines <id>` card chip alongside the
existing detail-view parent link and dependency edge.

Verified: merge gate (299 tests), lint, full build, and typecheck for core, CLI,
and dashboard all pass. New coverage: origin resolution across both origins and
the full precedence ladder, the two settings pickers, the board-lane mirror,
refinement titling (including sibling distinctness), and the card chip.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 20:33:25 -07:00
gsxdsm
93a403af67 fix(dashboard): import delete-attribution constants via browser-safe subpath
The client bundle aliases `@fusion/core` to the leaf `core/src/types.ts` to
keep Node-only dependencies out of the browser, so a package-root import of
`FUSION_CLIENT_HEADER`/`FUSION_DASHBOARD_UI_CLIENT` typechecked but failed
`vite build`:

  "FUSION_CLIENT_HEADER" is not exported by "../core/src/types.ts"

Follow the documented pattern instead of widening the root alias: declare a
`./task-delete-attribution` subpath export, add the matching Vite alias ahead
of the broader `@fusion/core` key (Vite matches in order), register the module
in the browser-safe-core allowlist, and import the subpath from the client.
`task-delete-attribution.ts` has no imports at all, so it is a safe leaf.

`app/utils/detectContentLanguage.ts` already warned about exactly this trap;
the miss was mine for verifying with typecheck, lint and test:gate but not
`pnpm build`, which is one of the four checks CI blocks on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 13:22:18 -07:00
gsxdsm
ab87d0d803 fix(api): return 404 for missing tasks, and make task deletions attributable
Three related fixes, all originating from a `[api:error] Request failed`
log line showing a 500 on `GET /api/tasks/FN-8610/runtime-fallback`.

1. Missing/deleted tasks now return 404 instead of 500.
   `getTaskImpl` signalled a miss with a bare `Error`, and route catches
   only mapped errno `ENOENT` to 404 — a leftover from the file-backed
   storage era. In Postgres mode nothing sets an errno code, so every
   unknown/missing/soft-deleted/wrong-project read returned 500. Adds a
   typed `TaskNotFoundError` (message byte-identical) plus a shared
   `task-lookup-error` mapper applied across the task, session-diff,
   git/GitHub, workflow and file-workspace route registrars. The same
   bare throw existed on both archive-lifecycle delete paths, so
   `DELETE /tasks/:id` was affected too.

2. 5xx logs now carry the origin stack.
   `rethrowAsApiError` constructed a fresh `ApiError` from the message
   and discarded the original, so the `FNXC:ApiErrorDiagnostics`
   contract logged the rethrow site rather than the throw site — the
   reported log entry had no stack at all. Threads `cause` through the
   error factories and walks the chain (bounded, cycle-guarded).

3. Task deletions are attributable, and non-operator deletes notify.
   `task:deleted` audit rows recorded `agentId: "system"` for every HTTP
   delete, making an operator click indistinguishable from a script or
   an agent; the calling agent's task id was accepted by the store and
   then never persisted. Adds a `callerKind` union recorded in audit
   metadata, tags every delete call site, and stamps a self-reported
   `x-fusion-client` header from the dashboard client. When the caller
   is `agent-tool` or `api-unattributed`, a best-effort notice is sent
   to the operator mailbox; operator and engine deletes stay silent.

`x-fusion-client` is attribution, not authentication — anything can send
it. No delete-blocking, gating or permission logic is added here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 13:15:36 -07:00
gsxdsm
827b145fa1 FN-8611: persist manual import translations
Persist manual GitHub and GitLab import translations across preview sessions.

- Add durable translation cache reads and identity-aware translation requests.
- Route manual translations through the translation budget with actionable API errors.
- Restore cached previews automatically and cover API/UI behavior with tests.

Files changed:
 .changeset/fn-8611-manual-import-translations.md   |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 packages/dashboard/app/api/ai-text.ts              |  52 ++++++--
 packages/dashboard/app/api/legacy.ts               |   2 +
 .../dashboard/app/components/GitHubImportModal.tsx |  14 ++-
 .../components/GitHubImportTranslateControls.tsx   |  39 +++++-
 .../__tests__/GitHubImportModal.test.tsx           |  42 +++++++
 packages/dashboard/src/ai-translate.ts             |  23 ++++
 .../register-ai-text-assistant-routes.test.ts      | 135 +++++++++++++++++----
 .../routes/register-ai-text-assistant-routes.ts    | 131 ++++++++++++++------
 10 files changed, 370 insertions(+), 77 deletions(-)

Fusion-Task-Id: FN-8611

Fusion-Task-Lineage: 00a84f43-4469-4bc5-bbb6-8245d8d79781

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-26 13:05:23 -07:00
gsxdsm
f157bf7460 fix(dashboard): harden visibility suspension, log caps, and mobile board UX
Suspend poll/SSE work when the tab is hidden, cap log buffers, restore board scroll more reliably, and improve list windowing/live tickers with related tests and a mobile-tab retention changeset.
2026-07-26 09:50:44 -07:00
gsxdsm
41d60f0355 feat(board): explain the unplanned promote rejection and let operators force past it
Promote on a held card printed the raw i18n key `board.rejection.unplannedForExecution`:
FN-8471 added the server-side code without a client case or catalog entry, so
translateRejection fell through to `t(messageKey, messageKey)`.

- Add the explicit rejection case (both translate helpers) plus the en catalog
  entry and secondary-locale stubs.
- promoteHeldTask(..., { force }) waives ONLY the unplanned-for-execution gate;
  hold membership, capacity and slot reservation still arbitrate. It clears a
  needs-replan/plan-review-unavailable status so triage rediscovery cannot pull
  the card back into the waived replan, and emits task:promote-forced-unplanned.
- POST /tasks/:id/promote accepts { force: true }; the board asks for explicit
  confirmation first and only offers the override for this rejection.

Force stays operator-only — the sweep, the webhook release and fn_task_promote
never set it, so FN-7648 still holds for every automatic surface.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 19:56:54 -07:00
gsxdsm
749167cbed fix(engine-controls): surface a paused engine instead of showing it as idle
A paused engine with nothing running derived executorState "idle", so the
footer badge was indistinguishable from a healthy engine waiting for work.
That is exactly the state a pause settles into once in-flight tasks drain:
triage and planning stall while the board keeps moving, with the pause only
visible by opening the Engine Control menu. Pause state now dominates run
state; the adjacent counters still report throughput.

In the CLI TUI, the global `t` (Git view) branch returned before the Utilities
dispatch in the same key handler, so the advertised "[t] Toggle Engine Pause"
was unreachable dead UI. It now yields when Utilities owns input, and because
the shortcut can stop the board, pausing takes a second `t` within 5s while
resuming stays single-press.

Tests assert the invariant across the whole state matrix (both pause flags x
0/1/5 running), not just the zero-running repro, plus the TUI routing, the
two-press pause, single-press resume, and re-arm behavior.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 18:49:19 -07:00
gsxdsm
a9d5b06013 FN-8562: add tags to chat conversations
Enable project-scoped reusable tags for Direct chat sessions.

- Add tag storage, migrations, and scoped assignment APIs.
- Add chat sidebar tag creation, assignment, and filtering controls.
- Document tag behavior and cover schema and chat interactions.
- Establish the session project/id candidate key before creating scoped tag foreign keys.

Files changed:
 .changeset/fn-8562-chat-conversation-tags.md       |   7 ++
 docs/dashboard-guide.md                            |   4 +
 docs/storage.md                                    |   2 +
 .../src/__tests__/postgres/schema-applier.test.ts  |   8 +-
 packages/core/src/async-chat-store.ts              | 117 ++++++++++++++++++++-
 packages/core/src/chat-store.ts                    |  32 ++++++
 packages/core/src/chat-types.ts                    |  14 +++
 packages/core/src/index.gate.ts                    |   3 +
 packages/core/src/index.ts                         |   3 +
 .../postgres/migrations/0036_chat_session_tags.sql |  64 +++++++++++
 packages/core/src/postgres/schema-applier.ts       |  16 ++-
 packages/core/src/postgres/schema/project.ts       |  34 ++++++
 packages/dashboard/app/api.ts                      |   1 +
 packages/dashboard/app/api/chat.ts                 |  18 ++++
 packages/dashboard/app/components/ChatView.css     |  17 +++
 packages/dashboard/app/components/ChatView.tsx     |  70 +++++++++++-
 .../__tests__/ChatView.core-interactions.test.tsx  |  27 +++++
 .../dashboard/app/hooks/__tests__/useChat.test.ts  |   1 +
 packages/dashboard/app/hooks/useChat.ts            |  52 ++++++++-
 .../dashboard/src/routes/register-chat-routes.ts   |  70 ++++++++++++
 20 files changed, 550 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-8562

Fusion-Task-Lineage: 4efe798c-0865-451a-adbd-6b85f9f8b149

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-24 18:09:32 -07:00
gsxdsm
2978ec4973 FN-8551: add accessible agent heartbeat controls
Add per-agent and project-wide heartbeat enablement controls.

- Add preserved runtime configuration helpers and heartbeat controls across agent list, board, and org-chart views.
- Add bulk enable/disable actions, accessible labels, localized copy, documentation, and release metadata.
- Cover heartbeat mutations through dashboard, route, scheduler, and layout smoke tests.

Files changed:
 .changeset/fn-8551-agent-heartbeat-controls.md     |   7 +
 docs/dashboard-guide.md                            |   2 +
 packages/dashboard/app/api/agents.ts               |  12 ++
 packages/dashboard/app/api/legacy.ts               |   2 +
 .../dashboard/app/components/AgentDetailView.tsx   |  14 +-
 packages/dashboard/app/components/AgentsView.css   |  11 ++
 packages/dashboard/app/components/AgentsView.tsx   | 186 ++++++++++++++++-----
 .../AgentDetailView.advanced-settings.test.tsx     |  29 ++++
 .../__tests__/AgentDetailView.test-helpers.ts      |   2 +
 .../app/components/__tests__/AgentsView.test.tsx   |  68 ++++++++
 .../dashboard/scripts/browser-layout-smoke.mjs     |  54 ++++++
 .../src/routes/__tests__/agent-core-routes.test.ts |  69 ++++++++
 .../src/__tests__/heartbeat-scheduler.test.ts      |  21 +++
 packages/i18n/locales/en/app.json                  |  19 ++-
 packages/i18n/locales/es/app.json                  |  19 ++-
 packages/i18n/locales/fr/app.json                  |  19 ++-
 16 files changed, 484 insertions(+), 50 deletions(-)

Fusion-Task-Id: FN-8551

Fusion-Task-Lineage: 2d4c8a15-a444-47b6-b57c-f41fc4163155

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-23 14:32:58 -07:00
gsxdsm
ebbb5948ab FN-8529: add contextual plan review comments
Enable operators to submit selected-plan suggestions through the existing Planning Mode revision flow.

- Capture text selections, batch suggestions, and retain retryable comment submissions in the Planning Mode UI.
- Validate bounded comment payloads and format them for the existing planning session update path.
- Document the workflow and add coverage for ordering, retry behavior, and selection boundaries.

Files changed:
 .changeset/fn-8529-planning-comments.md            |   7 +
 docs/dashboard-guide.md                            |   4 +
 packages/dashboard/app/api/legacy.ts               |   1 +
 packages/dashboard/app/api/planning.ts             |   9 +-
 .../dashboard/app/components/PlanningModeModal.css |  86 ++++++++++++
 .../dashboard/app/components/PlanningModeModal.tsx | 144 ++++++++++++++++++++-
 .../PlanningModeModal.planning-flow.test.tsx       |  39 ++++++
 .../PlanningModeModal.ui-interactions.test.tsx     |  10 ++
 .../__tests__/planning-infinite-interview.test.ts  |  62 +++++++++
 packages/dashboard/src/planning.ts                 |  76 ++++++++++-
 .../src/routes/register-planning-subtask-routes.ts |  27 +++-
 11 files changed, 455 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-8529

Fusion-Task-Lineage: c7064d76-effd-4597-a2b4-03f344dd59b9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-23 00:56:47 -07:00
gsxdsm
de5d446b5c FN-8526: add custom workflow column descriptions
Enable custom workflow authors to define and display descriptions for board columns.

- Persist optional descriptions in workflow column definitions and API responses.
- Add editor controls and board tooltips for column descriptions.
- Cover validation, API, and dashboard behavior with tests and documentation.

Files changed:
 .changeset/fn-8526-workflow-column-descriptions.md |  7 +++
 docs/dashboard-guide.md                            |  4 ++
 .../src/__tests__/workflow-ir-validation.test.ts   | 30 +++++++++++
 packages/core/src/workflow-ir-types.ts             |  4 ++
 packages/core/src/workflow-ir.ts                   |  9 ++++
 packages/dashboard/app/api/board-workflows.ts      |  2 +
 packages/dashboard/app/components/Board.tsx        |  3 ++
 packages/dashboard/app/components/Column.tsx       | 14 +++--
 .../app/components/WorkflowColumnPanel.tsx         | 31 ++++++++++++
 .../app/components/WorkflowNodeEditor.css          | 41 +++++++++++++++
 .../app/components/__tests__/Column.test.tsx       | 19 +++++++
 .../__tests__/WorkflowColumnPanel.test.tsx         | 38 ++++++++++++++-
 .../app/components/__tests__/WorkflowNodeEditor.test.tsx | 19 +++++++
 .../app/components/workflow-flow-mapping.ts        |  1 +
 packages/dashboard/app/styles.css                  |  8 +++
 .../src/__tests__/board-workflows.test.ts          | 59 ++++++++++++++++++++++
 packages/dashboard/src/routes/board-workflows.ts   |  3 ++
 17 files changed, 288 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-8526

Fusion-Task-Lineage: df26b7c0-301c-4875-b100-d63d0cfecf85

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-22 22:37:51 -07:00
flexi767
f21d3ce132 feat(core): support additive archived task documents (#2375)
## Summary

Re-lands the completed Fusion board task FX-005 on current upstream
`main`, stacked on #2374 (FX-004).

- adds a narrowly authorized additive publication path for archived task
documents
- preserves archived task and mission state and keeps ordinary
replacement/deletion writes rejected
- exposes retained archived current/revision reads
- requires project-scoped revision/hash CAS for publication
- maps malformed, unauthorized, missing, inconsistent, and stale states
safely
- rebases preserved dashboard drafts explicitly after CAS conflicts

## Why

Operators need to append a correction or evidence revision to an
archived task without unarchiving it or weakening ordinary archived-task
immutability.

## Dependency

This branch contains #2374 plus the eight FX-005 commits because
cross-fork PRs cannot target a fork-only base branch. After #2374 lands,
this PR should be rebased or refreshed so its diff collapses to FX-005
only.

## Validation

- PostgreSQL task-store and archived-default suites: 33/33
- dashboard route and editor suites: 321/321
- agent document tools: 22/22
- core, dashboard, and engine typechecks pass

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

## Summary by CodeRabbit

* **New Features**
* Added optimistic concurrency controls for task document creation and
editing using revisions and content hashes.
* Added safe, authenticated append-only corrections for documents
retained on archived tasks.
* Archived documents and revision history remain available for direct
reading.
* Agent and dashboard tools now report conflicts clearly and support
explicit draft rebasing.
* **Bug Fixes**
  * Prevented stale updates from overwriting newer document content.
* Preserved archived-task immutability while allowing controlled
corrections.
* **Documentation**
* Updated CLI, dashboard, storage, task-management, and agent guidance
for these workflows.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: fusion-merge-train <merge-train@topkoli.local>
Co-authored-by: Fusion <noreply@runfusion.ai>
Co-authored-by: v <v@v.speedport.ip>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 08:30:12 -07:00
gsxdsm
3a7684b90e refactor: package code organization wave 12 (#2362)
## Summary

Behavior-preserving package code organization (wave 12), continuing
after wave 11 (#2333).

- **Dashboard client API peels** from `app/api/legacy.ts` into focused
modules with stable re-exports:
- `git.ts` — remotes, PR management, terminal sessions, git management
(`withRepoPath` preserved)
  - `workspace-files.ts` — file browser + workspace file ops
  - `provider-status.ts` — auth/CLI and runtime provider status
  - `github-import.ts` / `gitlab-import.ts` — issue/PR import clients
  - `run-audit.ts` — run-audit, timeline, org tree, task review
  - `task-diff.ts` — task diffs and commit associations
  - `agent-import-generation.ts` — agent import catalog + generation
- **Core types peels** from `types.ts`:
  - `types/run-audit.ts`
  - `types/planner-intervention.ts`
- **Domain rename**: `task-store/remaining-ops-5.ts` →
`task-store/task-id-integrity.ts` (call sites updated)
- **Line-count ratchet**: `legacy.ts` ceiling ~5665 → ~3339; baseline
refreshed

No intentional behavior changes; public import paths via `app/api` /
`@fusion/core` remain stable.

## Test plan

- [x] `@fusion/core` typecheck
- [x] Dashboard `tsconfig.app` typecheck (wave12-related errors cleared;
pre-existing playwright/plugin env noise unchanged vs main)
- [x] ESLint on peeled API modules
- [x] `pnpm check:line-count` (baseline updated)
- [ ] CI: Lint / Typecheck / Build / Gate

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

- **New Features**
- Added dashboard client support for Git remotes/PR workflows,
GitHub/GitLab importing, terminals (HTTP/SSE) and PTY sessions,
workspace file browsing/editing/search, and task diff viewing with
file/ZIP download helpers.
- Added new dashboard APIs for planning/onboarding streaming, mission
interview flows, provider/auth status, dev server sessions,
run-audit/timelines & task review, agent import/generation, and AI title
summarization.
- Added backup and settings export/import helpers, plus model
discovery/usage reporting and task steering actions.
- **Refactor**
- Modularized dashboard API clients into focused modules while
preserving the existing integration style.
- **Tests**
- Updated a backend-mode SQLite guidance regression test to exercise the
intended implementations.
- **Chores**
  - Refreshed internal line-count baselines.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 23:10:08 -07:00
gsxdsm
d1c3b63cff fix(dashboard): honor beta channel on Settings check for updates
Settings "Check for updates" called a legacy endpoint that only queried npm
latest and ignored prerelease ordering, so beta users never saw newer
X.Y.Z-beta.N releases. Route the check through channel-aware force refresh
and add a beta.0 → beta.1 regression test.
2026-07-21 20:40:55 -07:00
gsxdsm
eef5eb751e FN-8453: unify concurrency accounting and indicators
Unify live-agent capacity accounting across engine and dashboard.

- Derive Running and Waiting from workflow traits and durable agent liveness.
- Apply unified limits to planner, executor, and merge admission while updating dashboard indicators.
- Remove duplicate concurrency controls and document the unified operator model.

Files changed:
 .changeset/fn-8453-unified-concurrency.md          |   7 +
 docs/agent-tool-surface-full-loop.md               |   4 +-
 docs/architecture.md                               |   2 +-
 docs/dashboard-guide.md                            |   4 +-
 docs/settings-reference.md                         |   4 +-
 .../skill/fusion/references/fusion-capabilities.md |   4 +-
 .../core/src/__tests__/live-agent-count.test.ts    |  91 ++++----
 packages/core/src/index.gate.ts                    |   6 +
 packages/core/src/index.ts                         |   6 +
 packages/core/src/live-agent-count.ts              | 107 ++++++---
 packages/dashboard/app/App.tsx                     |  28 ++-
 packages/dashboard/app/api/board-workflows.ts      |   2 +
 packages/dashboard/app/components/Column.tsx       |   6 +-
 .../dashboard/app/components/EngineControlMenu.tsx |  26 ---
 .../dashboard/app/components/ExecutorStatusBar.tsx |  38 ++-
 .../dashboard/app/components/SettingsModal.tsx     |   1 -
 .../app/components/__tests__/Column.test.tsx       |   6 +-
 .../__tests__/EngineControlMenu.test.tsx           |  10 +-
 .../__tests__/ExecutorStatusBar.test.tsx           |  32 ++-
 .../command-center/CommandCenterControls.tsx       |  26 ---
 .../settings/sections/SchedulingSection.search.ts  |   9 -
 .../settings/sections/SchedulingSection.tsx        |  13 --
 .../app/hooks/__tests__/useExecutorStats.test.ts   |  12 +-
 packages/dashboard/app/hooks/useExecutorStats.ts   |  50 ++--
 .../src/__tests__/project-store-resolver.test.ts   |  11 +-
 packages/dashboard/src/project-store-resolver.ts   |  14 +-
 .../register-config-mcp-pi-settings-routes.ts      |   3 +-
 packages/engine/src/__tests__/concurrency.test.ts  | 123 +++++++++-
 .../engine/src/__tests__/project-engine.test.ts    |  34 +++
 packages/engine/src/__tests__/triage.test.ts       |   7 +-
 packages/engine/src/concurrency.ts                 | 207 ++++++++++++++++-
 packages/engine/src/project-engine.ts              | 151 ++++++++++--
 packages/engine/src/scheduler.ts                   |  82 ++++++-
 packages/engine/src/triage.ts                      | 254 +++++++++++++--------
 .../lib/dashboard-browser-safe-core-modules.json   |   5 +
 35 files changed, 991 insertions(+), 394 deletions(-)

Fusion-Task-Id: FN-8453

Fusion-Task-Lineage: 12cfa5df-675d-4fce-b17e-932376544239

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-21 15:30:31 -07:00