Commit Graph

11648 Commits

Author SHA1 Message Date
gsxdsm
54565a092d docs: add Claude Agent SDK bridge provider plan
Capture the implementation-ready plan for a conditional, experimental
pi-claude-bridge / Agent SDK provider behind policy and isolation gates.
2026-07-17 12:15:09 -07:00
gsxdsm
adb3eb3a37 FN-8224: add Claude ACP runtime support
Add a bundled Claude Code ACP runtime with model discovery and CLI distribution integration.

- Add the Claude ACP runtime plugin, bridge, tool forwarding, and tests.
- Register Claude model discovery and cached picker support in the dashboard.
- Stage the plugin in CLI and desktop packaging with its pinned dependency.
- Add workspace, lockfile, and release metadata.

Files changed:
 .changeset/fn-8224-claude-acp-runtime.md           |   7 +
 packages/cli/package.json                          |   1 +
 packages/cli/src/__tests__/bundle-output.test.ts   |  32 +-
 .../cli/src/plugins/staged-bundled-plugin-ids.ts   |   1 +
 packages/cli/tsup.config.ts                        |  40 +-
 .../core/src/plugins/bundled-plugin-install.ts     |   2 +
 packages/dashboard/package.json                    |   3 +-
 packages/dashboard/src/claude-model-cache.ts       | 185 +++++++
 packages/dashboard/src/routes.ts                   |   1 +
 .../dashboard/src/routes/register-model-routes.ts  |  11 +
 packages/dashboard/src/runtime-provider-probes.ts  |  15 +
 packages/dashboard/vitest.config.ts                |   4 +
 packages/desktop/scripts/workspace-tools.ts        |   1 +
 plugins/fusion-plugin-claude-runtime/README.md     |   7 +
 plugins/fusion-plugin-claude-runtime/manifest.json |   1 +
 plugins/fusion-plugin-claude-runtime/package.json  |   1 +
 .../src/__tests__/cli-spawn.test.ts                |   3 +
 .../src/__tests__/index.test.ts                    |   3 +
 .../src/__tests__/provider.test.ts                 |   8 +
 .../src/__tests__/runtime-adapter.test.ts          |   7 +
 .../src/__tests__/tool-bridge.test.ts              |  79 +++
 .../src/acp-settings.ts                            |  21 +
 .../src/acp/VENDORED.md                            |  30 ++
 .../src/acp/cli-spawn.ts                           | 188 +++++++
 .../src/acp/control-handler.ts                     | 302 ++++++++++++
 .../src/acp/event-bridge.ts                        | 308 ++++++++++++
 .../src/acp/fs-capabilities.ts                     | 263 ++++++++++
 .../fusion-plugin-claude-runtime/src/acp/index.ts  |  16 +
 .../src/acp/path-jail.ts                           | 229 +++++++++
 .../src/acp/process-manager.ts                     | 177 +++++++
 .../src/acp/prompt-builder.ts                      |  87 ++++
 .../src/acp/provider.ts                            | 542 +++++++++++++++++++++
 .../src/acp/runtime-adapter.ts                     | 190 ++++++++
 .../src/acp/sanitize.ts                            |  81 +++
 .../src/acp/tool-mapping.ts                        |  47 ++
 .../fusion-plugin-claude-runtime/src/acp/types.ts  | 189 +++++++
 .../fusion-plugin-claude-runtime/src/cli-spawn.ts  |  31 ++
 plugins/fusion-plugin-claude-runtime/src/index.ts  |  95 ++++
 .../src/mcp-forwarding.ts                          | 114 +++++
 .../src/mcp-schema-server.cjs                      | 155 ++++++
 plugins/fusion-plugin-claude-runtime/src/probe.ts  |   8 +
 .../fusion-plugin-claude-runtime/src/provider.ts   |   8 +
 .../src/runtime-adapter.ts                         | 424 ++++++++++++++++
 .../src/skill-loader.ts                            | 290 +++++++++++
 .../src/tool-bridge.ts                             | 264 ++++++++++
 plugins/fusion-plugin-claude-runtime/src/types.ts  | 142 ++++++
 plugins/fusion-plugin-claude-runtime/tsconfig.json |  10 +
 .../fusion-plugin-claude-runtime/vitest.config.ts  |  22 +
 pnpm-lock.yaml                                     | 131 ++++-
 pnpm-workspace.yaml                                |   1 +
 50 files changed, 4753 insertions(+), 24 deletions(-)

Fusion-Task-Id: FN-8224

Fusion-Task-Lineage: 4e626913-32bb-4baa-a142-816c7f4ee7c4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 12:00:26 -07:00
gsxdsm
7f1b7e21c1 FN-8223: enforce full CLI quarantine ledger lockstep
Extend CLI quarantine validation across the entire ledger.

- Normalize package-relative Vitest exclusions to repository paths.
- Require each CLI configuration exclusion and ledger entry exactly once.
- Validate ISO 8601 quarantine timestamps.

Files changed:
 .../src/__tests__/lockstep-cli-quarantine.test.ts  | 52 +++++++++++-----------
 packages/cli/vitest.config.ts                      |  4 +-
 2 files changed, 27 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-8223

Fusion-Task-Lineage: 7abe719b-63bf-4dfa-8db6-e3dd7547c7fe

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:43:46 -07:00
gsxdsm
065890ca01 FN-8222: align CLI tests with current store APIs
Repair CLI test mocks and retry-reset expectations for the current store contracts.

- Add the backend store factory to the experiment-finalize mock.
- Provide global settings directory access in backup test stores.
- Assert all manual retry reset fields in task command tests.

Files changed:
 .../extension-experiment-finalize.test.ts          | 13 ++++++++++
 .../commands/__tests__/backup-lock-retry.test.ts   |  2 ++
 packages/cli/src/commands/__tests__/backup.test.ts | 17 ++++++++++++-
 packages/cli/src/commands/__tests__/task.test.ts   | 28 +++++++++++++++++-----
 4 files changed, 53 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-8222

Fusion-Task-Lineage: 033ce6a6-c699-409c-a59e-2d1f5e041cfc

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:37:32 -07:00
gsxdsm
5d2c3be6a0 FN-8221: clear inactive planner overseer state
Clear retained planner overseer state when effective oversight is disabled.

- Remove monitor, recovery, advisor, and dedup runtime for oversight-off tasks.
- Suppress stale oversight-off Eye badges in task cards.
- Cover cleanup and badge behavior with regression tests.
- Document the runtime snapshot invariant and add a patch changeset.

Files changed:
 .changeset/fn-8221-overseer-badge-oversight-off.md |   7 ++
 docs/architecture.md                               |   4 +
 packages/dashboard/app/components/TaskCard.tsx     |   9 +-
 .../app/components/__tests__/TaskCard.test.tsx     |  20 ++++
 .../__tests__/planner-overseer-off-cleanup.test.ts | 119 +++++++++++++++++++++
 packages/engine/src/project-engine.ts              |  12 +++
 6 files changed, 170 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8221

Fusion-Task-Lineage: 01c9d838-fbe4-4d34-8eb5-d735cf35e581

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:27:44 -07:00
gsxdsm
b686fbd61d FN-8220: mock daemon model runtime setup
Align daemon startup mocks with the model runtime initialization path.

- Add the auth-storage setModelRuntime mock.
- Stub the Fusion model registry factory to use the shared test registry.

Files changed:
 packages/cli/src/commands/__tests__/daemon.test.ts | 9 +++++++++
 1 file changed, 9 insertions(+)

Fusion-Task-Id: FN-8220

Fusion-Task-Lineage: 6e00980f-2e24-4502-a4d8-e91849df33b9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:24:02 -07:00
gsxdsm
5acea6c0cf fix(pg): route residual SQLite-stub store paths through the async data layer (#2273)
## Summary

An audit of the SQLite→PostgreSQL store migration found data-store paths
still reaching the removed SQLite stub in backend (PG) mode. In backend
mode `store.db`/`getDatabase()` throw the removed-SQLite error, so each
of these either threw on every run or — worse — had the throw swallowed
into a silent wrong result. This PR routes all of them through the
`AsyncDataLayer` (and removes one dead primitive).

## The 6 live bugs fixed

| Fix | Was |
|-----|-----|
| `executor.ts` authoritative assigned-agent fallback now inherits the
TaskStore `asyncLayer` | silently returned `null` → model drift to the
pi built-in (the exact thing its comment guards) |
| `pruneAgentLogFilesAsync` replaces the sync self-healing prune call |
threw `SQLite Database is not available` every maintenance sweep →
agent-log pruning never ran |
| `cleanupOrphanedMaterializedSteps` deletes PG `workflow_steps` rows on
a failed create | swallowed the throw → leaked rows |
| `deleteTaskBackendImpl` now runs the async mission feature/task-link
unlink | PG hard delete left orphaned mission links |
| `getWorkflowSettingsProjectId` returns `rootDir` in backend mode
without touching the stub | swallowed throw for unscoped backend stores
|
| `fn plugin` unregistered-project fallback bootstraps a `CentralCore`
`AsyncDataLayer` | layerless `PluginStore` threw in PG |

## The 4 latent traps, fixed properly

- **`cleanupArchivedTasks`** — real async port (enumerate archived
soft-deleted rows, guarantee cold snapshot, hard-delete project row +
purge selection rows + rm dir).
- **`deleteWorkflowStep`** — real async port (delete `workflow_steps`
via the layer with `.returning()` to preserve the not-found contract).
- **`applyTaskPatch`** — **removed** (zero-caller SQLite column-patch
primitive with no backend analogue; impl + facade + import deleted).
- **`AgentStore.importLegacyFileRuns`** — clean backend no-op (no legacy
SQLite run-files exist in a PG deployment; its only `init()` caller
early-returns in backend mode).

## Symptom Verification

New PG regression suite
`packages/core/src/__tests__/postgres/store-sqlite-residue-fixes.pg.test.ts`
reproduces the original failures against real embedded Postgres and
asserts they're gone:
- orphaned `workflow_steps` are actually deleted (no swallowed throw)
- `pruneAgentLogFilesAsync` resolves and prunes inactive-task log files
- hard delete unlinks the mission feature from the task
- `deleteWorkflowStep` removes the row / reports not-found
- `cleanupArchivedTasks` hard-deletes the project row while retaining
the cold snapshot

## Verification

- `@fusion/core`, `@fusion/engine`, `@runfusion/fusion` typecheck clean
- ~50 existing + 5 new PG tests pass; lint clean; changeset validates

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

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

* **Bug Fixes**
* Prevented PostgreSQL backend maintenance from hitting removed legacy
SQLite code paths, avoiding datastore failures and residue cleanup
issues.
* Fixed workflow-step deletion and “not found” behavior in backend mode.
* Ensured backend hard-deletes correctly unlink related mission
feature/task links and clean orphaned materialized steps.
* Prevented legacy file-run imports from incorrectly reporting success
in backend mode.
* **New Features**
* Added async agent-log pruning for inactive tasks and updated
maintenance to use it.
* **Tests**
* Added PostgreSQL regression coverage for residue fixes and
archive/workflow cleanup.
* **Refactor**
* Removed an unused task patch operation and updated task-store cleanup
methods to be async where needed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:22:21 -07:00
gsxdsm
cdcc3261f1 FN-8225: migrate goal-tool tests to shared PostgreSQL harness
Migrate goal-tool extension tests to the injected shared PostgreSQL harness.

- Replace temporary embedded PostgreSQL roots with shared harness lifecycle hooks
- Reuse harness API registration and tool helpers across goal retrieval and audit suites
- Preserve retrieval audit assertions while avoiding concurrent database startup locks

Files changed:
 .../__tests__/extension-goal-tools-audit.test.ts   |  72 ++++++-------
 .../cli/src/__tests__/extension-goal-tools.test.ts | 113 ++++++++-------------
 2 files changed, 76 insertions(+), 109 deletions(-)

Fusion-Task-Id: FN-8225

Fusion-Task-Lineage: 424c1bb2-5cb7-4e81-b3fd-8f6a6f29b433

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:18:50 -07:00
gsxdsm
a7ab3ccb49 fix(heartbeat): stop zombie-timer audit churning live-but-skipping timers (#2271)
## Problem

Permanent (durable) agent heartbeats went silent while the rest of the
engine kept running. Investigation of the live DB showed **every**
permanent agent's `heartbeatTimerRepair` metadata carrying
`nonAdvancingEscalated: true` with **3–63 consecutive** zombie re-arms —
the audit re-arming a timer every 60s for hours while emitting
`heartbeat-rearm-nonadvancing-escalated` warnings that never recovered
anything.

## Root cause

The heartbeat trigger audit classified a "zombie" (dead) timer **solely
from a stale `lastHeartbeatAt`**. But that column advances *only* on a
successful `"ok"` delivery (`agent-store.ts` `recordHeartbeat`). It
stays frozen whenever a heartbeat is intentionally skipped or no-op'd:

- agent over budget / over budget threshold
- `globalPause` / `enginePaused`
- `skipHeartbeatWhenIdle` on an idle agent
- idle "org" agents whose runs complete as `no_assignment_identity_run`

In all of these the interval keeps firing perfectly — the timer is
alive, delivery is just (correctly) skipped. Keying zombie detection off
`lastHeartbeatAt` misread those healthy timers as dead, re-armed them
every 60s, and escalated forever. Re-arming a live timer is a no-op, so
the loop could never recover — it only produced churn and phantom
warnings.

## Fix (the invariant)

Key zombie detection off **whether the interval physically fired**, not
whether delivery advanced.

- New `lastTimerFireAtMs` map, stamped at the top of `onTimerTick`
**before any gate** — a fired-but-skipped tick still counts as proof of
liveness.
- In the audit: a present + stale timer that fired within its stale
window is **left untouched** (no re-arm, no escalation, non-advancing
counter reset). Only a timer with **no recent fire** (a genuinely dead
interval) falls through to the existing re-arm/escalation path.
- Map cleaned up in `unregisterAgent()` / `stop()`.

This preserves the FN-7645 zombie repair (a timer that stops firing goes
stale in lockstep on both clocks and is still re-armed) and the FN-7939
watchdog, while eliminating the phantom churn for live-but-skipping
timers.

Why not "force a heartbeat" or "park the agent": forcing delivery would
bypass budget/pause governance, and parking a healthy idle agent would
be wrong. The correct action for a live-but-skipping timer is to leave
it alone — its next real tick delivers once the skip condition clears.

## Tests

- Rewrote the old `skipHeartbeatWhenIdle` test that codified the buggy
escalation → now asserts a **live** idle-skipping timer is left
untouched (no zombie re-arm, no escalation).
- Added a budget/no-assignment surface: a live timer that dispatches but
leaves `lastHeartbeatAt` frozen must not be misclassified.

`heartbeat-scheduler.test.ts` 120/120; broader heartbeat + concurrency
suites 349/349; `@fusion/engine` typecheck 0 errors.

## Review

Self-reviewed at medium effort. Two acknowledged, bounded trade-offs
(kept intentionally): a genuinely-dead-but-recently-fired timer's repair
latency is bounded at ~2× interval (same as the original FN-7645
latency), and the escalation warning is suppressed for live timers (it
only ever fired because of the churn this removes; per-tick error logs +
a new "left live-but-skipping timer" log retain visibility). One trivial
cleanup applied (single `Date.now()` sample).

## Notes

- Engine is a private package → no changeset.
- Complementary to a separate in-flight fix for the
agentStore/scheduler-not-constructed bug (why heartbeats stopped
*entirely*); this PR ensures that once the scheduler runs again, the
audit stops the phantom churn/escalation.

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


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved heartbeat timer monitoring to distinguish healthy timers from
genuinely stopped timers.
* Prevented unnecessary timer re-registration and warning escalation
when heartbeats are intentionally skipped due to idle, paused,
budget-limited, or unassigned states.
* Improved recovery when a replacement timer stops firing, ensuring it
is detected and repaired reliably.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:15:41 -07:00
gsxdsm
01b1c694d1 FN-8219: remove expired CLI quarantined tests
Remove expired CLI test quarantines and preserve evidence of their resolution.

- Delete five expired quarantined CLI test files
- Remove their Vitest exclusions
- Add a lockstep regression guard for the retired quarantine scope

Files changed:
 .../src/__tests__/extension-fn-secret-get.test.ts  |  164 -
 .../src/__tests__/lockstep-cli-quarantine.test.ts  |   64 +
 packages/cli/src/__tests__/skill-sync.test.ts      |  562 ---
 packages/cli/src/__tests__/version.test.ts         |   62 -
 .../cli/src/commands/__tests__/dashboard.test.ts   | 3736 --------------------
 .../__tests__/bundled-plugin-freshness.test.ts     |   75 -
 packages/cli/vitest.config.ts                      |   21 +-
 7 files changed, 78 insertions(+), 4606 deletions(-)

Fusion-Task-Id: FN-8219

Fusion-Task-Lineage: cac0b4c5-3255-4733-ba24-2156979d60f3

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:11:07 -07:00
gsxdsm
526aaf8d65 FN-8218: stub model registry runtime initialization in serve tests
Keep serve command tests compatible with async ModelRuntime initialization.

- Add setModelRuntime to the auth storage mock
- Mock createFusionModelRegistry with the shared registry fixture

Files changed:
 packages/cli/src/commands/__tests__/serve.test.ts | 10 ++++++++++
 1 file changed, 10 insertions(+)

Fusion-Task-Id: FN-8218

Fusion-Task-Lineage: dcbba740-e363-4b17-8eba-00c399343d16

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 11:05:02 -07:00
gsxdsm
abc2550cc6 FN-8216: fix settings description test guard
Keep the Settings default-description coverage aligned with surfaced and global-only settings.

- Add missing Notifications and Scheduling description keys to the coverage map
- Allowlist the global-only LAN discovery setting so the guard does not require a UI description

Files changed:
 .../sections/__tests__/settings-default-descriptions.test.tsx    | 9 +++++++++
 1 file changed, 9 insertions(+)

Fusion-Task-Id: FN-8216

Fusion-Task-Lineage: a5449429-c5b2-4d88-915b-26baba3fb60b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:59:11 -07:00
gsxdsm
eb7d223a03 FN-8207: add task reassignment for delegated work
Correct delegation routing for duplicate tasks and enable explicit task owner reassignment.

- Preserve requested assignee and todo routing on duplicate canonical tasks
- Add governed fn_task_assign to engine, heartbeat, triage, workflow, and chat sessions
- Cover assignment validation, truthful delegation responses, and tool availability

Files changed:
 .changeset/fn-8207-delegate-assign.md              |   7 ++
 docs/agents.md                                     |   6 ++
 packages/core/src/types.ts                         |   1 +
 packages/core/src/usage-events.ts                  |   2 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   |   2 +
 packages/dashboard/src/__tests__/chat.test.ts      |   2 +
 packages/dashboard/src/chat.ts                     |   2 +
 .../engine/src/__tests__/agent-action-gate.test.ts |   2 +
 .../src/__tests__/agent-tools-delegation.test.ts   |  99 ++++++++++++++++++-
 .../src/__tests__/agent-tools-task-assign.test.ts  |  75 +++++++++++++++
 .../src/__tests__/gating-classifications.test.ts   |   1 +
 .../src/__tests__/heartbeat-executor.test.ts       |   8 +-
 .../src/__tests__/permanent-agent-gating.test.ts   |   2 +
 .../src/__tests__/step-session-executor.test.ts    |   4 +-
 packages/engine/src/__tests__/triage.test.ts       |   5 +-
 packages/engine/src/agent-heartbeat.ts             |   4 +-
 packages/engine/src/agent-tools.ts                 | 105 ++++++++++++++++++++-
 packages/engine/src/executor.ts                    |   3 +
 packages/engine/src/gating-classifications.ts      |   1 +
 packages/engine/src/index.ts                       |   2 +
 packages/engine/src/step-session-executor.ts       |   2 +
 packages/engine/src/triage.ts                      |   2 +
 22 files changed, 324 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-8207

Fusion-Task-Lineage: db6f3876-bdc8-4279-b726-29344d9acdb9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:53:19 -07:00
gsxdsm
86c281bc38 FN-8215: add GitHub issue comment posting
Enable operators to post upstream GitHub issue comments from the Import Tasks preview.

- Add authenticated GitHub CLI and REST fallback support for creating issue comments.
- Expose a validated API route and inline issue-comment composer with optimistic preview updates.
- Add localized UI copy, documentation, release metadata, and coverage for client, route, and modal behavior.

Files changed:
 .changeset/fn-8215-github-issue-add-comment.md     |  7 ++
 docs/dashboard-guide.md                            |  9 ++-
 packages/dashboard/app/api/legacy.ts               | 13 ++++
 .../dashboard/app/components/GitHubImportModal.css | 34 +++++++++
 .../dashboard/app/components/GitHubImportModal.tsx | 68 +++++++++++++++++-
 .../__tests__/GitHubImportModal.test.tsx           | 62 +++++++++++++++++
 packages/dashboard/src/__tests__/github.test.ts    | 48 +++++++++++++
 .../dashboard/src/__tests__/routes-github.test.ts  | 80 ++++++++++++++++++++++
 packages/dashboard/src/github.ts                   | 49 +++++++++++++
 .../dashboard/src/routes/register-git-github.ts    | 56 +++++++++++++++
 packages/i18n/locales/en/app.json                  |  5 ++
 packages/i18n/locales/es/app.json                  |  5 ++
 packages/i18n/locales/fr/app.json                  |  5 ++
 packages/i18n/locales/ko/app.json                  |  5 ++
 packages/i18n/locales/zh-CN/app.json               |  5 ++
 packages/i18n/locales/zh-TW/app.json               |  5 ++
 packages/i18n/src/resources.d.ts                   |  5 ++
 17 files changed, 459 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-8215

Fusion-Task-Lineage: 0fe6acca-e86d-484f-a97f-5746d32717a1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:37:00 -07:00
gsxdsm
3b0b9a5661 FN-8214: show runtime model providers in chat
Ensure task chat role icons reflect each agent's actual runtime model.

- Parse runtime model markers from status and text log entries.
- Prefer runtime and effective models over stale task provider overrides.
- Cover provider icon precedence and fallback behavior for all chat roles.

Files changed:
 packages/dashboard/app/components/TaskChatTab.tsx        |  8 +-
 packages/dashboard/app/components/__tests__/TaskChatTab.test.tsx | 88 ++++++++++++++++++----
 2 files changed, 76 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-8214

Fusion-Task-Lineage: 1eb02ca5-469f-4a9d-932c-5cf02383b7fe

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:30:46 -07:00
gsxdsm
26807c8bf4 FN-8211: restore intrinsic mobile option icons
Restore intrinsic mobile sizing for Quick Add option icons.

- Limit enlarged mobile glyphs to primary Quick Add controls.
- Preserve compact options, touch targets, and desktop styling.
- Add regression coverage and a patch changeset.

Files changed:
 .changeset/fn-8211-quick-add-icon-revert.md        |  7 +++++
 .../quick-entry-action-row-height-parity.test.tsx  | 27 ++++++++++---------
 .../dashboard/app/components/QuickEntryBox.css     | 30 +++++++++++++---------
 3 files changed, 38 insertions(+), 26 deletions(-)

Fusion-Task-Id: FN-8211

Fusion-Task-Lineage: 85399053-2d6e-4bb7-8741-e7c3b1aa437d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:25:01 -07:00
gsxdsm
0d339f4803 FN-8210: repair CLI package configuration test contract
Restore the CLI package configuration test to the active test lane with current build expectations.

- Allowlist WhatsApp plugin-only tsup externals as non-runtime CLI dependencies.
- Assert the full workspace build command in the verification contract.
- Remove the stale package-config test quarantine.

Files changed:
 packages/cli/src/__tests__/package-config.test.ts | 12 +++++++++++-
 packages/cli/vitest.config.ts                     |  9 ++++-----
 2 files changed, 15 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8210

Fusion-Task-Lineage: aa29d866-430f-4097-affa-a89d107474b2

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:19:34 -07:00
gsxdsm
611e51d2a8 FN-8209: align task detail toolbar icons on mobile
Make Task Detail inline controls use the compact, accessible Quick Add icon pattern.

- Replace labeled priority and execution controls with icon-only buttons and a priority picker.
- Apply shared icon sizing to oversight, attachment, priority, and fast-mode controls.
- Update responsive and interaction coverage and add a patch changeset.

Files changed:
 .changeset/fn-8209-task-detail-toolbar-icons.md    |   7 +
 .../dashboard/app/components/TaskDetailModal.css   | 160 ++++++---------------
 .../dashboard/app/components/TaskDetailModal.tsx   | 109 ++++++++++----
 ...lModal.inline-editing-and-integrations.test.tsx |  31 ++--
 .../TaskDetailModal.oversight-controls.test.tsx    |   5 +-
 .../TaskDetailModal.oversight-mobile.test.tsx      |   4 +
 .../__tests__/TaskDetailModal.rendering.test.tsx   |  95 +++---------
 ...etailModal.responsive-and-dependencies.test.tsx |  20 ++-
 8 files changed, 182 insertions(+), 249 deletions(-)

Fusion-Task-Id: FN-8209
Fusion-Task-Lineage: 3c079a7b-245a-4c4d-b058-6e1cf4b5a69d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:13:23 -07:00
gsxdsm
7a50232916 FN-8208: validate agent message recipients before delivery
Prevent false-success agent messages by validating recipients before delivery.

- Wire AgentStore into every send-message tool registration.
- Reject missing or unvalidated agent recipients before persistence or wake-up.
- Add recipient validation coverage and a patch changeset.

Files changed:
 .../fn-8208-send-message-recipient-validation.md   |   7 ++
 .../chat-send-message-agentstore-wiring.test.ts    |  11 ++
 packages/dashboard/src/chat.ts                     |   2 +-
 ...tools-send-message-recipient-validation.test.ts | 116 +++++++++++++++++++++
 packages/engine/src/agent-heartbeat.ts             |   4 +-
 packages/engine/src/agent-tools.ts                 |  24 ++++-
 packages/engine/src/executor.ts                    |   2 +-
 packages/engine/src/step-session-executor.ts       |   2 +-
 8 files changed, 162 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8208
Fusion-Task-Lineage: 84752bb8-c9f7-42bd-87c1-9681ac442789
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:07:24 -07:00
gsxdsm
28878d8125 FN-8206: validate landed merge checkout
Validate mission assertions against the delivered merge revision rather than an ambient working branch.

- Materialize and dispose a detached checkout at mergeDetails.commitSha for validator sessions.
- Defer failed validation when landed-code ancestry cannot be proven, preventing spurious fix features.
- Link validator runs to their board tasks and document the inspection behavior.

Files changed:
 .changeset/fn-8206-mission-validator-inspection-root.md   |   7 +
 docs/missions.md                                          |   2 +
 packages/engine/src/__tests__/mission-execution-loop.test.ts | 278 +++++++++++++--------
 packages/engine/src/mission-execution-loop.ts             | 160 ++++++++----
 4 files changed, 298 insertions(+), 149 deletions(-)

Fusion-Task-Id: FN-8206

Fusion-Task-Lineage: dfd1eb21-fcdf-4722-acb8-416750f4f40b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 10:00:18 -07:00
gsxdsm
67fac31f5c FN-8202: prevent mDNS hostname conflicts
Prevent self-conflicting mDNS advertisements and allow automatic LAN discovery to be disabled.

- Advertise a Fusion-owned DNS-SD hostname derived from the node ID.
- Add a global automatic LAN discovery opt-out for dashboard and serve.
- Cover hostname isolation and discovery startup behavior with tests and documentation.

Files changed:
 .changeset/fn-8202-mdns-hostname-fix.md            |  7 +++++
 docs/settings-reference.md                         |  1 +
 docs/shared-mesh-protocol.md                       |  2 +-
 .../cli/src/commands/__tests__/dashboard.test.ts   | 24 ++++++++++++++++
 packages/cli/src/commands/__tests__/serve.test.ts  | 12 ++++++++
 packages/cli/src/commands/dashboard.ts             | 24 +++++++++++-----
 packages/cli/src/commands/serve.ts                 | 24 +++++++++++-----
 packages/core/src/__tests__/node-discovery.test.ts | 32 +++++++++++++++++++++-
 .../core/src/__tests__/settings-defaults.test.ts   |  8 ++++++
 packages/core/src/node-discovery.ts                | 31 +++++++++++++++++++++
 packages/core/src/settings-schema.ts               |  5 ++++
 packages/core/src/types.ts                         |  2 ++
 12 files changed, 156 insertions(+), 16 deletions(-)

Fusion-Task-Id: FN-8202

Fusion-Task-Lineage: c1d6e36b-bda7-4968-b40c-c14e16ebda28

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:54:44 -07:00
gsxdsm
7fc4b439ee FN-8205: fix shared auth credential lock retries
Serialize shared auth credential writes and await durable persistence under contention.

- Replace synchronous auth-file locking with queued asynchronous retries.
- Propagate asynchronous credential mutations through CLI, dashboard, and provider wrappers.
- Cover held-lock persistence, queue recovery, and awaited caller behavior.

Files changed:
 .changeset/fn-8205-auth-lock-retry.md              |   7 ++
 .../cli/src/commands/__tests__/onboard.test.ts     |  17 +++
 .../src/commands/__tests__/provider-auth.test.ts   |  78 ++++++------
 packages/cli/src/commands/onboard.ts               |   2 +-
 packages/dashboard/src/routes.ts                   |   6 +-
 .../dashboard/src/routes/register-auth-routes.ts   |  10 +-
 .../dashboard/src/routes/register-mesh-routes.ts   |   4 +-
 .../register-settings-sync-inbound-routes.ts       |   4 +-
 .../src/routes/register-settings-sync-routes.ts    |   4 +-
 .../src/__tests__/auth-storage-concurrency.test.ts |  84 ++++++++++---
 packages/engine/src/__tests__/auth-storage.test.ts |  48 ++++----
 packages/engine/src/auth-storage.ts                | 137 +++++++++++++--------
 packages/engine/src/provider-auth.ts               |  56 ++++-----
 13 files changed, 284 insertions(+), 173 deletions(-)

Fusion-Task-Id: FN-8205

Fusion-Task-Lineage: b932b9ce-9aee-4f0a-9155-63b026c6bde4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:47:40 -07:00
gsxdsm
4293826b5a FN-8212: remove model dropdown sticky-header gap
Make pinned model provider headers sit flush against the fixed dropdown header stack.

- Remove top padding that exposed scrolling rows above sticky provider headers.
- Cover the no-seam invariant across desktop and mobile layouts with and without thinking controls.
- Add a patch changeset for the dropdown scrolling fix.

Files changed:
 .changeset/fn-8212-model-dropdown-sticky-gap.md    |  7 ++++
 .../app/components/CustomModelDropdown.css         |  5 ++-
 .../__tests__/CustomModelDropdown.test.tsx         | 46 ++++++++++++++++++++++
 3 files changed, 57 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8212

Fusion-Task-Lineage: d7ce42d1-bcbe-4000-8107-794ec8e05307

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:35:14 -07:00
gsxdsm
d6860b5b76 FN-8204: add configurable mobile footer quick actions
Add an ordered project setting for mobile footer quick-action destinations.

- Render selected destinations as primary mobile tabs and retain omitted choices in More.
- Provide settings controls, validation, translations, documentation, and regression coverage.
- Add a minor changeset for the published CLI package.

Files changed:
 .changeset/fn-8204-mobile-nav-primary-items.md     |   7 +
 docs/dashboard-guide.md                            |   4 +
 docs/settings-reference.md                         |   4 +
 .../src/__tests__/mobile-nav-primary-items.test.ts |  23 +++
 packages/core/src/index.ts                         |   9 ++
 packages/core/src/mobile-nav-primary-items.ts      |  55 +++++++
 packages/core/src/settings-schema.ts               |   1 +
 packages/core/src/types.ts                         |   7 +
 packages/dashboard/app/App.tsx                     |   2 +
 .../mobile-feature-access-regression.test.tsx      |  19 +++
 packages/dashboard/app/components/MobileNavBar.tsx | 159 +++++----------------
 .../app/components/__tests__/MobileNavBar.test.tsx |  16 +++
 .../app/components/settings/section-keys.ts        |   1 +
 .../settings/sections/GeneralSection.search.ts     |   9 ++
 .../settings/sections/GeneralSection.tsx           |  45 ++++++
 .../settings-default-descriptions.test.tsx         |   1 +
 packages/dashboard/app/hooks/useAppSettings.ts     |   5 +
 packages/i18n/locales/en/app.json                  |   4 +
 18 files changed, 244 insertions(+), 127 deletions(-)

Fusion-Task-Id: FN-8204

Fusion-Task-Lineage: 077de4c4-d281-401d-bddd-e5ce8e91d4ab

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:27:33 -07:00
gsxdsm
c0d610d9d7 fix(whatsapp-plugin): connect with current WA Web version and load as bundled plugin
WhatsApp rejects handshakes advertising Baileys' baked-in stale protocol
version with a 405 close, so the plugin cycled starting->disconnected and
never issued a QR. connect() now fetches the current WA Web version per
socket build. /status also exposes lastError so this failure mode is
diagnosable from the documented troubleshooting surface.

The published bundled.js also failed to load entirely ("Dynamic require
of 'crypto' is not supported"): plugin bundles are ESM but Baileys is
CJS. bundlePluginEntry now injects the same createRequire banner as
dist/bin.js.

Verified end-to-end against an isolated fn serve: bundled.js loads,
status reaches awaiting-qr, /qr serves a scannable QR data URL,
/pair-code validates input, /logout clears auth state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 09:13:55 -07:00
gsxdsm
e445b3e367 FN-8201: pin pi dependency versions
Pin the pi runtime packages to a single exact version so global npm installs resolve a compatible set.

- Pin pi-ai and pi-coding-agent declarations across workspace manifests
- Add a guard and tests that reject ranged or mismatched pi versions
- Document the source-install fallback and add a patch changeset

Files changed:
 .changeset/fn-8201-pin-pi-versions.md              |   7 ++
 docs/getting-started.md                            |   3 +
 package.json                                       |   6 +-
 packages/cli/package.json                          |   4 +-
 packages/cli/src/__tests__/package-config.test.ts  |  18 +++-
 packages/core/package.json                         |   2 +-
 packages/dashboard/package.json                    |   2 +-
 packages/engine/package.json                       |   4 +-
 packages/pi-claude-cli/package.json                |   8 +-
 .../__tests__/check-pi-versions-pinned.test.mjs    |  45 ++++++++
 scripts/check-pi-versions-pinned.mjs               | 120 +++++++++++++++++++++
 11 files changed, 205 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-8201

Fusion-Task-Lineage: bf0ac363-df5f-4445-835b-cfd2d4909659

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 09:12:01 -07:00
gsxdsm
6ca7e48f87 fix(FN-7965): surface duplicate decisions
Show a clear operator-decision badge and deliver an idempotent mailbox prompt for triage duplicate markers.

Fusion-Task-Id: FN-7965
2026-07-17 08:53:44 -07:00
gsxdsm
c6adac6e7c fix(dashboard): stop mobile task-detail panel shifting left
The full-screen mobile task-detail sheet hides all resize handles, so
FN-8015's `margin-inline-end: var(--space-lg)` gutter on the shared
`.floating-window__body` (added to keep the scrollbar clear of desktop
resize hot zones) only added dead space on the right and shifted the
entire panel left. Zero it for `.floating-window--task-detail` inside
the mobile breakpoint so `.detail-body`'s own padding defines both
insets equally; desktop resize-handle clearance is untouched.

Refined the FN-8015 invariant test to enforce the desktop hot-zone gutter
media-aware (strips @media blocks) and added a regression guard for the
mobile zeroing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 08:35:44 -07:00
gsxdsm
f27965d711 FN-8200: add Settings theme selector spacing
Add tokenized spacing below the Settings current-theme selector before Font Size.

- Scope the spacing to the Settings current-theme row without affecting compact dropdowns.
- Add a regression test for the established spacing token.
- Add a patch changeset for the Settings layout fix.

Files changed:
 .changeset/fn-8200-theme-selector-spacing.md                      | 6 ++++++
 packages/dashboard/app/components/ThemeDropdown.css               | 8 ++++++++
 .../dashboard/app/components/__tests__/ThemeDropdown.test.tsx     | 6 ++++++
 3 files changed, 20 insertions(+)

Fusion-Task-Id: FN-8200

Fusion-Task-Lineage: 6b72d0f7-759f-49aa-a8f9-f788cc9ec5c5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 08:17:09 -07:00
gsxdsm
f866e68c6a FN-8199: sync translated README updates
Bring localized README feature and storage descriptions in line with the English documentation.

- Add PostgreSQL storage and documentation references across translations.
- Refresh model, task chat, theme, GitHub, dashboard, and model override descriptions.
- Align package storage terminology with the PostgreSQL migration.

Files changed:
 README.es.md    | 16 +++++++++-------
 README.fr.md    | 16 +++++++++-------
 README.ko.md    | 16 +++++++++-------
 README.zh-CN.md | 16 +++++++++-------
 README.zh-TW.md | 16 +++++++++-------
 5 files changed, 45 insertions(+), 35 deletions(-)

Fusion-Task-Id: FN-8199

Fusion-Task-Lineage: ba617549-e43e-4531-bdfe-4e79f94ffdae

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 01:29:30 -07:00
gsxdsm
7b540959c5 FN-8198: add Todo item task creation API
Add API endpoints that turn Todo lists and items into executable board tasks.

- Expose Todo list and item read endpoints with async store parity.
- Create tasks from Todo items with validation, project scoping, provenance, and workflow-default placement.
- Document the scripting flow and cover dashboard and PostgreSQL behavior.

Files changed:
 .changeset/fn-8198-todo-api.md                     |   7 +
 docs/todo-view.md                                  |  18 ++-
 .../src/__tests__/postgres/todo-store.pg.test.ts   |  13 ++
 packages/core/src/async-todo-store.ts              |  17 +++
 .../dashboard/src/__tests__/todo-routes.test.ts    | 157 ++++++++++++++++++++-
 packages/dashboard/src/todo-routes.ts              | 128 ++++++++++++++++-
 6 files changed, 335 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-8198

Fusion-Task-Lineage: f8d5032b-4844-43c9-97d1-3cc7d13d0ce1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 01:23:32 -07:00
gsxdsm
a51cba0d69 FN-8197: move merge details to summary tab
Keep completed task merge metadata with its completion summary.

- Relocate the Merge Details card from Definition to the done-only Summary tab.
- Cover merge-detail states and Definition/mobile containment with dashboard tests.
- Document the Summary tab behavior and add a patch changeset.

Files changed:
 .changeset/fn-8197-merge-details-summary-tab.md    |  7 +++
 docs/dashboard-guide.md                            |  2 +-
 packages/dashboard/app/components/TaskDetailModal.tsx   |  4 +-
 packages/dashboard/app/components/TaskSummaryTab.tsx    |  9 +++
 packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx | 49 ++++++++++------
 packages/dashboard/app/components/__tests__/TaskDetailModal.summary-tab.test.tsx | 65 ++++++++++++++++++++++
 6 files changed, 115 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-8197

Fusion-Task-Lineage: f4aac014-1e8d-4b8f-91f1-ba40ae879508

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 01:17:22 -07:00
gsxdsm
6183621ca3 FN-8196: add mobile footer stat tooltips
Make compact mobile executor footer statistics identifiable on tap.

- Add accessible tap targets and portaled tooltips for mobile footer statistics.
- Dismiss stat tooltips on repeat tap, outside interaction, Escape, scrolling, and viewport changes.
- Cover mobile behavior while preserving desktop and tablet inline labels.
- Document the interaction and add a patch changeset.

Files changed:
 .changeset/fn-8196-mobile-footer-stat-tooltips.md  |   7 +
 docs/dashboard-guide.md                            |   2 +
 .../dashboard/app/components/ExecutorStatusBar.css |  47 +++++-
 .../dashboard/app/components/ExecutorStatusBar.tsx | 166 +++++++++++++++++++--
 .../__tests__/ExecutorStatusBar.test.tsx           | 132 +++++++++++++++-
 5 files changed, 333 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-8196

Fusion-Task-Lineage: c566b614-739d-4538-85c5-a8ff62720f4d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 01:12:08 -07:00
gsxdsm
7f175b036b FN-8195: label replan task status
Display the needs-replan task state with a clear localized operator-facing label.

- Map needs-replan status badges to Replan centrally.
- Add English i18n resources and generated resource typings.
- Cover the status-label mapping and add a patch changeset.

Files changed:
 .changeset/fn-8195-replan-badge.md                                | 7 +++++++
 .../dashboard/app/utils/__tests__/taskStatusBadgeLabel.test.ts    | 4 ++++
 packages/dashboard/app/utils/taskStatusBadgeLabel.ts              | 8 ++++++++
 packages/i18n/locales/en/app.json                                 | 2 ++
 packages/i18n/src/resources.d.ts                                  | 2 ++
 5 files changed, 23 insertions(+)

Fusion-Task-Id: FN-8195

Fusion-Task-Lineage: 7ad115b8-6405-426e-9201-bfa1258fff5e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 01:07:52 -07:00
gsxdsm
79b05c62ea FN-8190: apply heartbeat multipliers to agent health
Align dashboard health labels with project-resolved heartbeat cadence.

- Load the project heartbeat multiplier in agent list and detail views.
- Apply the effective cadence once when determining stale agents.
- Cover long-cadence and multiplier boundary health states.

Files changed:
 .../dashboard/app/components/AgentDetailView.tsx   | 19 ++++++++++++--
 .../dashboard/app/components/AgentListModal.tsx    | 19 ++++++++++++--
 packages/dashboard/app/components/AgentsView.tsx   |  2 +-
 .../__tests__/AgentDetailView.test-helpers.ts      |  3 +++
 .../components/__tests__/AgentListModal.test.tsx   | 27 ++++++++++++++++++++
 .../app/utils/__tests__/agentHealth.test.tsx       | 29 ++++++++++++++++++++++
 packages/dashboard/app/utils/agentHealth.tsx       | 25 ++++++++++++++++---
 7 files changed, 115 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-8190

Fusion-Task-Lineage: 1efcdc19-503a-4893-b277-f65e900a399b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 01:01:53 -07:00
gsxdsm
87ffb24fca FN-8194: align task detail inline controls
Align task-detail actions with Quick Add while preserving existing integrations.

- Add inline attachment and eligible GitHub tracking controls
- Replace the Oversight menu dots with an Eye icon and reorder metadata actions
- Cover action order, integration behavior, icon rendering, and mobile wrapping

Files changed:
 .changeset/fn-8194-task-detail-inline-controls.md  |  7 ++
 docs/dashboard-guide.md                            |  6 +-
 .../dashboard/app/components/TaskDetailModal.tsx   | 99 +++++++++++++++-------
 ...lModal.inline-editing-and-integrations.test.tsx | 80 ++++++++++++++++-
 .../TaskDetailModal.mock-coverage.test.ts          |  1 +
 .../TaskDetailModal.oversight-controls.test.tsx    | 19 +++++
 ...etailModal.responsive-and-dependencies.test.tsx |  5 +-
 .../__tests__/TaskDetailModal.test-helpers.ts      | 10 +--
 8 files changed, 187 insertions(+), 40 deletions(-)

Fusion-Task-Id: FN-8194

Fusion-Task-Lineage: 8de0e36f-b428-401c-98aa-35964c556a39

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:55:57 -07:00
gsxdsm
3fdc2c1fb7 FN-8193: add collapsible sticky provider lists
Keep model-provider headers visible and let users collapse provider model rows with persisted local preferences.

- Add sticky provider headers and accessible collapse toggles to CustomModelDropdown
- Persist collapsed provider groups locally while keeping filtered matches visible
- Cover collapse, keyboard navigation, storage recovery, and empty-state behavior
- Document the dashboard behavior and add a minor changeset

Files changed:
 .changeset/fn-8193-collapsible-provider-lists.md   |   7 ++
 docs/dashboard-guide.md                            |   1 +
 .../app/components/CustomModelDropdown.css         |  48 +++++++-
 .../app/components/CustomModelDropdown.tsx         | 110 ++++++++++++++----
 .../__tests__/CustomModelDropdown.test.tsx         | 129 +++++++++++++++++++++
 5 files changed, 266 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-8193

Fusion-Task-Lineage: 4fbc43a8-ef81-463c-b4d0-5f00a57ab27b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:48:36 -07:00
gsxdsm
c3e98d193f FN-8188: inherit default workflow steps for refinements
Make refinement tasks inherit configured default workflow steps and persist their selection.

- Seed refinement tasks with enabled default workflow steps
- Persist inherited workflow selections after task creation
- Cover populated, empty, and absent default workflows in PostgreSQL tests
- Add a patch changeset for the refinement workflow fix

Files changed:
 .changeset/fn-8188-refinement-workflow-steps.md    |  7 +++
 packages/core/src/__tests__/postgres/refine-duplicate-task.pg.test.ts | 68 ++++++++++++++++++++++
 packages/core/src/task-store/update-task-deps.ts   | 42 ++++++++++++-
 3 files changed, 116 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8188

Fusion-Task-Lineage: aed1e63a-f828-426c-9d3d-3a4ba17443c1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:42:00 -07:00
gsxdsm
b779785286 FN-8187: update README feature overview
Refresh the README to describe current Fusion capabilities and storage guidance.

- Highlight embedded PostgreSQL, Kimi K3, and richer task-chat progress reporting
- Document updated GitHub import, dashboard, and per-task override capabilities
- Add storage documentation to the resource directory

Files changed:
 README.md | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8187

Fusion-Task-Lineage: 696c1f1f-91fe-4256-b6b8-98a6d6b2f2e5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:36:21 -07:00
gsxdsm
ac52438554 FN-8192: prevent mobile confirmation ghost-click dismissal
Keep mobile task-delete confirmations open through delayed compatibility clicks.

- Gate backdrop dismissal until the opening gesture settles.
- Cover deliberate backdrop dismissal and mobile ghost-click behavior.
- Document the regression and add a patch changeset.

Files changed:
 .changeset/fn-8192-mobile-confirm-ghost-click.md   |  7 +++
 .../confirm-dialog-mobile-ghost-click-dismiss.md   | 53 ++++++++++++++++++++++
 .../dashboard/app/components/ConfirmDialog.tsx     | 23 +++++++++-
 .../components/__tests__/ConfirmDialog.test.tsx    | 34 ++++++++++++--
 .../app/hooks/__tests__/useConfirm.test.ts         | 32 ++++++++++++-
 5 files changed, 143 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-8192

Fusion-Task-Lineage: ea08a6c0-0f2e-4ec3-8ad7-23cdc4a5d7f1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:29:48 -07:00
gsxdsm
39887f5c87 FN-8186: refine mobile Quick Add action sizing
Refine mobile Quick Add controls so every action glyph is readable without compromising compact layout.

- Size option and primary action glyphs consistently with spacing tokens.
- Tighten mobile control padding while preserving touch-target and desktop behavior.
- Extend CSS contract coverage and add a patch changeset.

Files changed:
 .changeset/fn-8186-quick-add-mobile-icon-sizing.md |  7 +++++
 .../quick-entry-action-row-height-parity.test.tsx  | 35 ++++++++++++++--------
 .../dashboard/app/components/QuickEntryBox.css     | 31 +++++++++++--------
 3 files changed, 48 insertions(+), 25 deletions(-)

Fusion-Task-Id: FN-8186

Fusion-Task-Lineage: 9433521c-6c06-4f89-a486-b8073f2a2961

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:23:19 -07:00
gsxdsm
f0c32dc1bf FN-8191: clamp conversation action menus to viewport
Keep conversation overflow menus aligned with their triggers and contained in the visible viewport.

- Measure rendered menu dimensions so theme-specific widths remain aligned
- Clamp horizontal and vertical menu positions for trigger and context-menu entry points
- Cover desktop alignment and mobile alternate-theme viewport containment

Files changed:
 packages/dashboard/app/components/ChatView.css     |  6 ++
 packages/dashboard/app/components/ChatView.tsx     | 72 +++++++++++++++++++++-
 .../__tests__/ChatView.core-interactions.test.tsx  | 32 ++++++++++
 .../components/__tests__/ChatView.mobile.test.tsx  | 41 +++++++++++-
 4 files changed, 147 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-8191

Fusion-Task-Lineage: 1a52140b-9450-421d-844b-9fff302d8ea4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:17:59 -07:00
gsxdsm
0d2dcb3a40 FN-8189: fix mobile task-detail scrollbar gutter
Hide the mobile task-detail scrollbar to keep content insets visually symmetric.

- Preserve touch scrolling while removing the mobile non-overlay scrollbar track
- Add responsive regression coverage for scrollbar and inset behavior
- Add a patch changeset for the mobile layout fix

Files changed:
 .../fn-8189-task-detail-mobile-scrollbar-gutter.md |  7 +++
 .../dashboard/app/components/TaskDetailModal.css   | 12 +++++
 ...etailModal.responsive-and-dependencies.test.tsx | 55 ++++++++++++++++++++++
 3 files changed, 74 insertions(+)

Fusion-Task-Id: FN-8189

Fusion-Task-Lineage: 3a9300f7-9732-417b-95b0-b65a79efaaf6

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:04:41 -07:00
gsxdsm
6206af8ce9 FN-8146: restore persistent theme selection
Restore the full Settings theme picker while preserving Shadcn Mono selections across reloads.

- Merge the Settings selector into the current-theme row with shared dropdown controls.
- Restore Shadcn Mono across theme metadata, token styles, and dashboard/desktop bootstrap validation.
- Scope Mono light swatches correctly and cover restored options and persistence with tests.

Files changed:
 .changeset/FN-8146-theme-dropdown-current-row.md   |  7 +++
 docs/dashboard-guide.md                            |  5 ++-
 packages/core/src/types/execution-and-ui.ts        |  1 +
 .../dashboard/app/components/ThemeDropdown.css     | 52 ++++++++++++++++++++++
 .../dashboard/app/components/ThemeDropdown.tsx     | 42 ++++++++++++++---
 .../dashboard/app/components/ThemeSelector.css     | 42 +----------------
 .../dashboard/app/components/ThemeSelector.tsx     | 45 +++++--------------
 .../components/__tests__/ThemeDropdown.test.tsx    | 46 ++++++++++++++++---
 .../components/__tests__/ThemeSelector.test.tsx    | 29 ++++++++----
 .../__tests__/CommandCenterControls.test.tsx       | 15 ++++++-
 packages/dashboard/app/components/themeOptions.ts  |  2 +
 .../dashboard/app/hooks/__tests__/useTheme.test.ts |  8 ++--
 packages/dashboard/app/hooks/useTheme.ts           |  8 ++--
 packages/dashboard/app/index.html                  |  5 +--
 packages/dashboard/app/public/theme-data.css       | 16 ++++++-
 packages/desktop/src/renderer/index.html           |  1 +
 16 files changed, 213 insertions(+), 111 deletions(-)

Fusion-Task-Id: FN-8146

Fusion-Task-Lineage: 32ec7f21-ee6b-4459-8e7b-f5a5435c4994

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 00:00:46 -07:00
TrinaryCompute
bf6a974b58 fix(postgres): scope the cross-process merge guard to the project (#2267)
## fix(postgres): scope the cross-process merge guard to the project

The guard's own comment (`project-engine.ts`) says it checks whether
another process is merging a task **"for this project"** — and in SQLite
mode the per-project DB file made that scoping implicit.
`getActiveMergingTaskImpl`'s `backendMode` branch queries the shared PG
`tasks` table with **no `project_id` filter**, so one merging task
anywhere serializes merges across **all** projects.

### Production evidence
6-project embedded-PG deployment: **697 cross-project `Merge deferred …
is already merging (cross-process guard)` retries in 10 minutes** — six
independent repos waiting on each other's serialized merger, collapsing
merge throughput ~6x and letting `in-review` pile up to 95 tasks.

### Fix
Add the existing `taskProjectScope(layer)` filter to the query's
conditions (one line + import). It is a no-op when the layer carries no
`projectId`, so single-project deployments and the SQLite path are
unchanged. Same pattern as the other project-scoped task queries.

Deployed on the affected instance: cross-project merges now proceed in
parallel; per-project serialization (the guard's documented intent) is
preserved.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved merge task handling so activity in one project no longer
unnecessarily blocks merge operations in other projects.

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

Co-authored-by: TrinaryCompute <fusion-merge@trinarycompute.dev>
2026-07-16 23:46:41 -07:00
gsxdsm
7760d783bd fix: green full-suite after getAgentLogCount and inventory drift (#2266)
## Summary
- Follow-up after #2229: full suite on main still failed on dashboard
curated inventory (21 ungated files) and mass engine failures
(`this.store.getAgentLogCount is not a function`).
- Harden executor tool-failure cursor capture for minimal/test
`TaskStore` adapters (same optional-API pattern as `project-engine`),
keep mock fixtures in lockstep, and quarantine inventory-only dashboard
files with ledger + vitest exclude.

## Changes
- **Executor**: optional `getAgentLogCount` / `getAgentLogs` /
`updateTask` at graph entry and trailing-failure detection.
- **Mocks**: `createMockStore`, soft-delete guard, post-done
continuation, cron `getGlobalSettingsDir`, executor-prompt
`bulkCompletionRefusalAt` (FN-8141).
- **i18n** (prior commit): es/fr/ko/zh-CN/zh-TW triage-duplicate keys.
- **Inventory**: 21 dashboard files → `test-quarantine.json` +
`vitest.config.ts` lockstep (VAL-REMOVAL SQLite / load flakes /
build-only dist assert).

## Test plan
- [x] `node scripts/check-test-inventory.mjs --dashboard-curated`
- [x] `pnpm test:gate`
- [x] engine: soft-delete, prompt, cron, post-done, tool-failure-retry,
and related samples
- [x] `@fusion/core` schema-applier + `@fusion/i18n` parity
- [ ] Full Suite (non-blocking) on this PR / main after merge

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

## Summary by CodeRabbit

- **New Features**
- Added localized text for triage duplicate-resolution settings and
near-duplicate task actions in Spanish, French, Korean, Simplified
Chinese, and Traditional Chinese.
- Users can now see translated options and confirmations to keep or
delete detected duplicate tasks.

- **Bug Fixes**
- Improved resilience during task execution and recovery when optional
activity-log services are unavailable, preventing avoidable failures
during error handling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-16 23:44:35 -07:00
gsxdsm
13bdf63bfc fix: resolve Anthropic subscription auth through getApiKey for pi ModelRuntime.getAuth
pi >=0.80.8 moved session request auth to ModelRuntime.getAuth -> pi-ai
resolveProviderAuth, which reads credentials.read("anthropic") and refreshes an
OAuth credential via credentials.modify("anthropic"). Fusion stores the
subscription login under `anthropic-subscription` with no raw `anthropic` row,
so the refresh callback saw current===undefined, bailed, and auth resolved to
undefined -> "Provider is not configured: anthropic" (then fell back).

Resolve read("anthropic") through fusion's getApiKey (refresh + raw/legacy/
subscription/fallback precedence) and hand pi-ai a ready api_key credential;
pi-ai routes it as OAuth by the sk-ant-oat token prefix. Supersedes the prior
read-alias, which fixed lookup but not the broken OAuth refresh-via-modify path.

Verified end-to-end: ModelRuntime.getAuth(anthropic/opus) now resolves the
subscription token instead of returning undefined.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:24:45 -07:00
gsxdsm
4b150e2280 fix: resolve Anthropic subscription auth under pi-ai >=0.80 read() contract
pi-ai >=0.80 resolves provider auth via credentials.read(provider.id) and
performs OAuth refresh/derivation itself, bypassing fusion's getApiKey()
where the anthropic-subscription -> anthropic alias lived. A subscription-only
login surfaced as "Provider is not configured: anthropic" at prompt time even
though the status card showed connected.

- Alias the subscription OAuth credential into read("anthropic") at the
  credential-store layer (createFusionCredentialStore); raw/legacy rows still win.
- Match "not configured" in isRetryableModelSelectionError so an unresolved
  provider triggers the configured fallback model instead of hard-failing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:09:12 -07:00
TrinaryCompute
00cca460fc fix(engine): reclaim leaked semaphore slots when the system is busy, not only at total idle (#2265)
## fix(engine): reclaim leaked semaphore slots when the system is busy,
not only at total idle

### The bug

`recoverIdleSemaphoreLeakCandidate` only reclaims stale `AgentSemaphore`
slots when the system is **completely** idle (`persistedActive === 0 &&
inFlightCount === 0` → reconcile to 0). If even one in-progress row
persists — e.g. a zombie task whose agent session died without its
`finally` release — the valve never opens, and slots leaked by abnormal
teardown accumulate monotonically until `activeCount` pins the limit.

At that point the engine deadlocks in a distinctive way:
- every hold/release sweep logs `Hold release for <task> deferred — no
reservable slot for in-progress`
- triage/plan report `planning=0 … processing=0, semaphore
active=<limit>/<limit>, available=0`
- the merge queue grows unboundedly (merges also need a slot)
- only a process restart recovers

`reapLeakedConcurrencySlots` (FN-6782) doesn't help — it reconciles
**worktree** slots, not the shared semaphore.

### Production evidence

Observed twice on a 6-project embedded-PG deployment driving a local
model:

- After ~5 days of continuous operation: `semaphore active=24/24`,
`planning=0/24, processing=0`, 5 persisted in-progress rows (dead
sessions), merge queue at 88, **zero merges for >24h**. Restart
immediately restored merging.
- Same signature earlier at `active=40/40` with both LLM backends idle
(`kvcache≈0`).

The handful of zombie in-progress rows kept `persistedActive` nonzero
indefinitely, so the idle-only valve could never fire.

### The fix

Generalize the valve: clamp `activeCount` down to the **persisted +
in-flight bound** whenever the semaphore over-holds **continuously** for
a repair window.

- The strict-idle case (`bound === 0`) keeps its existing fast 5s window
— behavior unchanged, existing tests pass as-is.
- The non-idle case uses a deliberately conservative new window
(`STALE_SEMAPHORE_EXCESS_REPAIR_MS = 600_000`, 10 min): nested helper
agents (`runNested`) legitimately push `activeCount` above the persisted
top-level count for the duration of a nested run, so the excess must
outlive any plausible nested session before it is treated as leaked. The
candidate timestamp resets the moment the excess clears.
- `reconcileActiveCount` only ever lowers the count, so the clamp cannot
inflate capacity; a late release from a genuinely live agent after a
(worst-case, mis-timed) clamp is absorbed by the existing excess-release
guard (FN-6423).

Call-site changes are limited to the two log messages (the old
parenthetical claimed "no persisted … agent work", which is no longer
the only repair case).

### Tests

- existing idle-valve tests pass unchanged (same window, same
reconcile-to-0)
- new: stale excess above a nonzero persisted bound is repaired only
after the long window, and clamps exactly to the bound
- new: candidate resets when the excess clears (nested overshoot ending)
- new: caller in-flight sessions count into the bound (no false
candidate)

### Files

- `packages/engine/src/concurrency.ts` — generalized valve +
`STALE_SEMAPHORE_EXCESS_REPAIR_MS`
- `packages/engine/src/scheduler.ts`, `packages/engine/src/triage.ts` —
log message accuracy
- `packages/engine/src/__tests__/concurrency.test.ts` — 3 new tests


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

* **Bug Fixes**
* Improved stale “semaphore excess” recovery by using a configurable
repair window when excess persists.
* Prevented premature capacity corrections by accounting for in-flight
top-level work during reconciliation.
* Correctly handles nested helper activity so only leaked excess is
reclaimed, preserving legitimate nested runs.
* Updated reconciliation to clamp excess to the appropriate reclaim
floor instead of waiting indefinitely.
* **Improvements**
* Refreshed diagnostic warning text to clarify the over-held vs
persisted+in-flight work comparison.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: TrinaryCompute <fusion-merge@trinarycompute.dev>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:08:42 -07:00
gsxdsm
d1e9b563f7 fix(FN-8141): add forward migration for tasks.bulk_completion_refusal_at
PR #2260 added project.tasks.bulk_completion_refusal_at to the Drizzle model
and the 0000 baseline but shipped no forward migration. Databases created
before #2260 already carry the 0000 marker, so the applier skips the baseline
and they never gained the column — every such cluster crashed on the first
TaskStore SELECT ("column bulk_completion_refusal_at does not exist"), taking
down dashboard/app boot.

Adds forward migration 0018 (wired via BULK_COMPLETION_REFUSAL_AT_VERSION;
SCHEMA_BASELINE_VERSION -> "0018") so existing clusters heal on next startup.

Prevention:
- Per-column upgrade regression test reproducing the exact existing-DB failure.
- Migration-wiring-integrity guard (no PostgreSQL): SCHEMA_BASELINE_VERSION must
  equal the highest migration file, and every .sql must be registered in the
  applier so none silently never runs.
- Repairs 6 pre-existing schema-applier tests left stale by the 0017 addition
  (baseline-marker identity + version-list enumerations).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:47:33 -07:00