Commit Graph

1848 Commits

Author SHA1 Message Date
gsxdsm
ae98ec37a6 FN-7005: close cached plugin store with TaskStore
TaskStore shutdown now tears down its cached plugin store to avoid leaking plugin database handles.

- Dispose the cached PluginStore during TaskStore.close(), clear the cache, and remove listeners before closing.
- Keep close idempotent when no plugin store was created or after a prior teardown.
- Add regression coverage for direct TaskStore.close() and disk-backed harness reopen lifecycle.

Files changed:
 .../src/__tests__/store-plugin-store-close.test.ts | 63 ++++++++++++++++++++++
 packages/core/src/store.ts                         | 15 ++++++
 2 files changed, 78 insertions(+)

Fusion-Task-Id: FN-7005
Fusion-Task-Lineage: fe2242d8-7004-4d29-904d-58ee77861d99
2026-06-25 08:35:44 -07:00
gsxdsm
e42e17023a FN-7003: stabilize core test fixture state
Stabilize @fusion/core tests by resetting stale plugin-store database handles and aligning fixture assertions.

- Add a PluginStore close method that disposes local and central database connections.
- Reset the lazy plugin store before the shared test harness clears global settings storage.
- Cover plugin-store reopening from the built-in workflow harness.
- Assert the runtime FN task-prefix fallback without requiring serialized defaults.

Files changed:
 packages/core/src/__tests__/builtin-workflows.test.ts |  6 ++++++
 packages/core/src/__tests__/store-test-helpers.ts     |  8 ++++++++
 packages/core/src/__tests__/test-project.test.ts      |  8 +++++++-
 packages/core/src/plugin-store.ts                     | 12 ++++++++++++
 4 files changed, 33 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7003

Fusion-Task-Lineage: ec4d6e45-61ea-4e6a-b296-3af3acf7ba4b
2026-06-25 08:35:44 -07:00
gsxdsm
f5e1b966ab FN-6943: add worktree file copy settings
Add configurable file-copy seeding for new task worktrees.

- Add the worktreeCopyFiles setting to project settings, schema validation, and dashboard settings UI.
- Copy selected files into acquired worktrees after checkout and record audit events for copied/skipped files.
- Document the new Worktrees setting and cover it with core, dashboard, and engine tests.

Files changed:
 .changeset/fn-6943-worktree-copy-files.md          |   7 +
 docs/dashboard-guide.md                            |   4 +
 docs/settings-reference.md                         |   1 +
 packages/core/src/__tests__/store-settings.test.ts |  24 ++++
 packages/core/src/settings-schema.ts               |   5 +
 packages/core/src/types.ts                         |   7 +
 .../app/__tests__/settings-sections.test.tsx       |  66 +++++++++
 .../dashboard/app/components/SettingsModal.tsx     | 146 ++++++++++++++++++++
 .../components/__tests__/SettingsModal.test.tsx    |  91 +++++++++++++
 .../settings/sections/WorktreesSection.tsx         |  51 ++++++-
 .../src/__tests__/worktree-acquisition.test.ts     |  69 +++++++++-
 .../src/__tests__/worktree-copy-files.test.ts      | 112 ++++++++++++++++
 packages/engine/src/run-audit.ts                   |   6 +
 packages/engine/src/worktree-acquisition.ts        |  32 ++++-
 packages/engine/src/worktree-copy-files.ts         | 147 +++++++++++++++++++++
 15 files changed, 765 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6943

Fusion-Task-Lineage: fd1ded06-25f9-4496-8f50-6416446d2f29
2026-06-25 08:34:44 -07:00
gsxdsm
2fb87c9c7a fix(FN-783): separate write-scope intent and repair stale overlap blockers (#1755)
## Summary
- Separates prompt-derived write intent from read-only/context paths for
file-scope classification.
- Preserves true shared/hot-family overlaps while avoiding poisoned
scheduler/near-duplicate signatures.
- Adds store/API/dashboard support to safely repair or reroute stale
`overlapBlockedBy` blockers instead of direct DB/JSON edits.

## Test Plan
- `corepack pnpm --filter @fusion/core exec vitest run
--silent=passed-only --reporter=dot src/__tests__/store-parsing.test.ts
src/__tests__/near-duplicate.test.ts`
- `corepack pnpm --filter @fusion/engine exec vitest run
--silent=passed-only --reporter=dot src/__tests__/triage.test.ts
src/__tests__/scheduler-overlap-starvation.test.ts
src/__tests__/self-healing.test.ts`
- `FUSION_DASHBOARD_DEEP=1 corepack pnpm --filter @fusion/dashboard exec
vitest run --project dashboard-api --silent=passed-only --reporter=dot
src/__tests__/routes-tasks-ops.test.ts`
- `FUSION_DASHBOARD_DEEP=1 corepack pnpm --filter @fusion/dashboard exec
vitest run --project dashboard-app --silent=passed-only --reporter=dot
--exclude "**/build-output.test.ts"
app/components/__tests__/TaskDetailModal.rendering.test.tsx`
- `corepack pnpm --filter @fusion/core typecheck`
- `corepack pnpm --filter @fusion/engine typecheck`
- `corepack pnpm --filter @runfusion/fusion build`

## Notes
- `corepack pnpm --filter @fusion/dashboard typecheck` was attempted
after a clean branch install but failed on dependency-resolution/type
baseline noise (`express`, `@earendil-works/pi-ai`, etc. reported
missing across existing files); targeted dashboard API/app tests passed.

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

---

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

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

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

* **New Features**
* Added an end-to-end “repair overlap blocker” action with a new backend
endpoint, dashboard clear-overlap-blocker flow, and legacy API client
support.
* Introduced shared prompt file-scope classification to derive effective
write scopes consistently.
* **Bug Fixes**
* Improved overlap-blocker liveness/recovery by using effective
file-scope overlap analysis with ignore paths.
* Refined overlap-lease eligibility and queued blocker/status clearing
behavior.
* Updated near-duplicate intent signature handling to honor file-scope
constraints.
* **Tests**
* Expanded coverage for file-scope parsing/deduping, overlap-repair
outcomes, and dashboard/modal behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 08:30:57 -07:00
gsxdsm
7b46d78c73 fix: align tests with recent source changes on main (#1754)
## Summary

Fixes 6 failing tests on `origin/main` caused by recent feature commits
that landed without updating dependent test assertions. No production
behavior is changed — every fix aligns a test (or build output) with an
intentional source change.

## Changes

| # | Test | Root Cause | Fix |
|---|------|-----------|-----|
| 1 | `packages/core` `test-project.test.ts` | Commit `800f845e1`
changed `DEFAULT_PROJECT_SETTINGS.taskPrefix` from `"FN"` to `undefined`
(prefix now derived from project name at runtime) | Updated assertion to
expect `undefined` |
| 2 | `packages/dashboard` `text-token-canonicalization.test.ts` |
`ScriptsModal.css` used banned `--text-primary` token | Replaced with
canonical `--text` token |
| 3 | `packages/cli` `package-config.test.ts` | Pi runtime deps bumped
from `^0.79.1` to `^0.79.9` | Updated expected version |
| 4 | `packages/cli` `skill-sync.test.ts` | 4 engine tools added but not
documented | Added to `engine-tools.md` |
| 5 | `packages/cli` `version.test.ts` | `release:version` script gained
`run-ci-distill.mjs` | Updated expected script |
| 6 | `packages/cli` `bundled-plugin-freshness.test.ts` | 3 plugins had
stale dist | Rebuilt via `pnpm build` |

## Verification

- `pnpm test:gate` passes (313 core + 58 ci-shape tests)
- `pnpm lint` clean
- All 6 previously-failing tests now pass individually
- Runtime invariant preserved: tasks in fresh projects still get
`FN-NNN` IDs (covered by existing test at `test-project.test.ts:89`)


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

---

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

<!-- stage-review-badge-end -->
2026-06-25 08:27:41 -07:00
Phil Larson
88ccd9081c fix(FN-783): harden overlap repair race handling 2026-06-25 07:57:32 -07:00
Phil Larson
6495875fb8 fix(FN-783): ignore inactive prior overlap blockers 2026-06-25 06:39:56 -07:00
Phil Larson
e8c6a4a36f fix(FN-783): clear missing overlap blocker references 2026-06-25 06:26:40 -07:00
Phil Larson
973e167a9e fix(FN-783): align overlap repair with paused lease state 2026-06-25 05:49:29 -07:00
Phil Larson
7cd660f558 fix(FN-783): address overlap repair review blockers 2026-06-25 05:08:04 -07:00
Phil Larson
8cc5fd895e feat(FN-783): add supported overlap blocker repair API 2026-06-25 03:44:23 -07:00
Phil Larson
53825ad0ab fix(core): prefer explicit file scope for duplicate signatures 2026-06-25 03:44:22 -07:00
Phil Larson
41d1d5b74b feat(FN-783): complete Step 3 — shared write-scope classification
Fusion-Task-Id: FN-783

Co-authored-by: Fusion <noreply@runfusion.ai>
2026-06-25 03:44:21 -07:00
Phil Larson
c8be19f9e6 test(FN-783): cover poisoned write-scope metadata
Fusion-Task-Id: FN-783

Co-authored-by: Fusion <noreply@runfusion.ai>
2026-06-25 03:44:21 -07:00
gsxdsm
bc56ab287e fix: align tests with recent source changes on main
Fix 6 failing tests caused by intentional source changes that landed
without updating dependent test assertions:

- Core test-project: taskPrefix default changed from "FN" to undefined
  (commit 800f845e1, derived from project name at runtime)
- Dashboard ScriptsModal.css: replace banned --text-primary with --text
- CLI package-config: update expected pi dep version ^0.79.1 -> ^0.79.9
- CLI skill-sync: document 4 new engine tools in engine-tools.md
- CLI version: update expected release:version script to include
  run-ci-distill.mjs
- CLI bundled-plugin-freshness: rebuild stale dist directories
2026-06-25 00:13:29 -07:00
gsxdsm
5cd795a3f2 fix(db): use rollback-journal mode for central DB to stop SIGBUS crashes (#1752)
## Summary

Running more than one fusion process on a host (multiple dashboards/CLIs
across worktrees, all attaching `~/.fusion/fusion-central.db`) could
crash a `node` process at random — instantly, with no JS stack and
nothing in the logs. This happened 3 times in 3 days on one machine.
After this change those processes coexist without crashing.

The crash was an OS-level `SIGBUS` (`EXC_BAD_ACCESS`, `FS pagein error`
/ kernel `cluster_pagein past EOF`) inside SQLite's `walIndexReadHdr`.
In WAL mode every connection coordinates through a memory-mapped `-shm`
wal-index; on macOS/APFS, when one process resizes/rebuilds that file
during a checkpoint while another has it mmap'd, the reader faults on
the now-out-of-bounds page. A hardware memory fault can't be caught by
`node:sqlite` or JS, so the whole process dies.

The fix switches the central DB to `journal_mode = DELETE` (rollback
journal), which uses no `-shm` memory map and coordinates cross-process
access via POSIX byte-range locks instead — removing the faulting
surface entirely while keeping multi-process access. The existing
`busy_timeout` absorbs the writer serialization that DELETE mode trades
for WAL's reader/writer concurrency. Per-project DBs (`db.ts`) are
intentionally left on WAL: they're single-process-per-project and don't
hit this cross-process fault. SQLite migrates the existing WAL database
on first open (checkpoints `-wal` into the main file and removes
`-wal`/`-shm`), so there is no data loss.

## Test plan

- New regression tests in `central-db.test.ts` assert the central DB
reports `journal_mode = delete` (not `wal`) and that **no `-shm`
wal-index file is ever created** even after write traffic — i.e. the
exact faulted surface is gone.
- All 6 central-DB suites pass (221 tests); `@fusion/core` typechecks
clean.

---

[![Compound
Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
![Claude
Code](https://img.shields.io/badge/Opus_4.8_%281M%29-D97757?logo=claude&logoColor=white)


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

---

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

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

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved stability when multiple dashboards or CLIs run on the same
machine.
* Switched the local database to a safer journaling mode to reduce rare
crash issues on macOS/APFS.
* Prevented creation of extra database side files during normal
operation, while keeping data durability and lock-based coordination in
place.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 00:04:43 -07:00
gsxdsm
e53f50eb38 Address PR review feedback (#1752)
- Verify the WAL->DELETE journal-mode switch instead of discarding exec()'s
  result. During a rolling upgrade a lingering WAL holder blocks the exclusive
  lock the switch needs, so SQLite either throws SQLITE_BUSY or no-ops and
  returns "wal". Capture both outcomes and warn loudly so the residual -shm
  SIGBUS surface is observable, rather than silently swallowed.
- Do not rethrow: the condition is transient and self-healing (the next start
  after the last WAL holder exits migrates cleanly); hard-failing would make the
  central DB unopenable during the very upgrade window it describes.
- Add a migration-path regression test (a WAL holder blocking the switch) that
  the prior fresh-DB-only tests did not cover.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:51:52 -07:00
gsxdsm
50a94714ec fix(db): use rollback-journal mode for central DB to stop SIGBUS crashes
The central DB (~/.fusion/fusion-central.db) is opened concurrently by every
fusion process on a host. In WAL mode those connections coordinate through a
memory-mapped `-shm` wal-index; on macOS/APFS a reader takes a SIGBUS
(walIndexReadHdr / `cluster_pagein past EOF`) when another process resizes it
mid-checkpoint, killing the node process with no JS stack or log. Observed 3x
in 3 days. Switch the central DB to journal_mode=DELETE, which uses no `-shm`
mmap and coordinates cross-process access via POSIX byte-range locks instead;
busy_timeout absorbs the added writer serialization. Per-project DBs keep WAL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:39:35 -07:00
gsxdsm
eb3833a542 FN-6971: retire dual-observe cutover gating
Remove stale dual-observe prerequisites from workflow-authoritative readiness while preserving parity-summary safeguards.

- Require the authoritative flag plus clean populated parity summaries for interpreter cutover readiness.
- Keep persisted workflowInterpreterDualObserve values inert in runtime tests and documentation.
- Update cutover, parity, and graph-executor tests to reflect retired shadow observation behavior.
- Add a formatted patch changeset for the operator-facing cutover readiness fix.

Files changed:
 .changeset/fn-6971-workflow-cutover-readiness.md   |  7 ++
 docs/architecture.md                               |  2 +-
 docs/settings-reference.md                         |  4 +-
 docs/workflow-steps.md                             | 19 +++--
 .../core/src/__tests__/workflow-cutover.test.ts    | 19 +++--
 packages/core/src/workflow-cutover.ts              |  9 +--
 .../workflow-interpreter-cutover.test.ts           | 87 +++++++++++++++++++---
 .../workflow-interpreter-dual-observe.test.ts      | 76 ++++++-------------
 .../src/__tests__/stepwise-workflow-parity.test.ts | 25 ++++---
 .../engine/src/workflow-authoritative-driver.ts    | 10 +--
 10 files changed, 152 insertions(+), 106 deletions(-)

Fusion-Task-Id: FN-6971
Fusion-Task-Lineage: 363a441d-62e5-403c-9389-75fcf788352a
2026-06-24 23:32:52 -07:00
gsxdsm
28ceca2cbd Address PR review feedback (#1747)
- core/store: include workspaceWorktrees in the slim and activity-log-limited
  SELECT lists (rowToTask reads it, but the explicit column lists omitted it, so
  slim/limited reads dropped the field and could misclassify workspace tasks);
  add regression tests for both read surfaces
- dashboard/register-git-github: validate caller-supplied repoPath in resolveGitDir
  via isPathWithin containment check (path-traversal hardening for all git
  endpoints); make loadWorkspaceConfig a static @fusion/core import per AGENTS.md
- dashboard/legacy: preserve repoPath in the string-form pullBranch overload
- dashboard/GitManagerModal: revalidate selectedRepo against the fetched repo list
  so a stale selection can't persist across project switches

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:43:12 -07:00
gsxdsm
f06281961e fix(workspace): persist workspaceWorktrees and isolate concurrent session leases
Multiworkspace tasks could not complete due to two independent bugs:

1. task.workspaceWorktrees had no SQLite column / rowToTask mapping, so
   fn_acquire_repo_worktree's updateTask write was dropped on every persist
   (applyTaskPatch writes the DB-round-tripped task back to task.json). Every
   later getTask returned undefined, so fn_task_done's scope verifier read {}
   and blocked with "acquired no sub-repo worktrees", and isWorkspaceTask()
   consumers misfired. Persist it mirroring mergeDetails (schema column + v129
   migration + db-migrate + defineTaskColumn + TaskRow + rowToTask).

2. In workspace mode every task ran rooted at the shared browse-only root, and
   setActiveSession registered that path keyed only by path — so a second
   concurrent workspace task was rejected by the foreign-task guard
   ("active-session path ... is held by ..."). Give each task a task-scoped
   synthetic session key (sessionRegistryPath), applied at all register and
   unregister sites; the in-memory worktree Set still holds the real root.

Regression tests assert the persistence invariant across getTask/listTasks/
store-reopen and concurrent session registration across all three session
surfaces; both verified to fail without the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:13:43 -07:00
gsxdsm
b680948d8c Address PR review feedback (#1746)
- Fix race condition: add request ID guard for stale workspace detection responses
- Guard workspaceMode:true: only persist when repos.length > 0
- Add server-side taskPrefix validation (/^[A-Z]{1,5}$/)
- Move store.init() inside try/finally in both CLI TaskStore lifecycles
- Accept 1-character prefixes in CLI prompt (was requiring >= 2)
- Fix workspaceMode passing: forward false explicitly (was coerced to undefined)
- Fix 3rd KB→FN fallback in distributed-task-id.ts catch block
- Add try/finally to dashboard TaskStore in register-project-routes
- Gate workspace detection on existing-directory mode only (skip clone mode)
2026-06-24 14:24:07 -07:00
gsxdsm
46d0c4a1f6 Address PR review feedback round 3 (#1741)
- Align dashboard prefix validation to 1-5 chars (was 1-10) matching CLI cap
- Fix distributed-task-id.ts fallback from KB to FN (3 occurrences)
- Move taskPrefix/defaultWorkflowId persistence outside interactive-only block
  so non-interactive CLI registration also gets defaults
- Wrap both TaskStore lifecycles in try/finally to guarantee close() on error
2026-06-24 14:08:32 -07:00
gsxdsm
aae76cecc3 Address PR review feedback (#1741)
- Close first TaskStore before creating second in interactive registration (P1)
- Revert defaultWorkflowId default to undefined; set explicitly in onboarding only (P1)
- Add alpha-only filter + 2-char min to interactive prefix input (P2)
- Move suggestTaskPrefix to @fusion/core, share between CLI and dashboard (P2)
- Fix suggestTaskPrefix JSDoc to match implementation (P2)
2026-06-24 10:45:21 -07:00
gsxdsm
9a7c0c6154 fix: fallback task prefix to FN (was KB) when unset
The hardcoded fallback prefix in store.ts was 'KB' (legacy name). Changed
to 'FN' to match the product name and dashboard placeholder.
2026-06-24 10:31:06 -07:00
gsxdsm
800f845e15 feat(workspace): fix auto-detection, derive prefix from name, default coding workflow
- Fix workspace detection: change workspaceMode default from false to
  undefined so isWorkspaceModeExplicitlyDisabled no longer blocks
  auto-detection on fresh projects (config.json was being written with
  workspaceMode:false during store.init(), causing the guard to skip
  detection before it ever ran)
- Derive task prefix from project name (first 2-4 chars) instead of
  hardcoded 'FN' as the suggested default
- Default workflow is now builtin:coding instead of undefined
- CLI registerProjectInteractive: onboarding prompt for task prefix
  confirmation after project name
- Dashboard POST /api/projects: auto-derive prefix and set default
  workflow for new registrations
2026-06-24 10:31:06 -07:00
gsxdsm
c1b5be7d69 fix(workspace): write config.json before workspace.json, validate settings object
Address PR #1739 review round 3:

- Major (coderabbit): Reorder writes so setWorkspaceModeInConfig runs
  before saveWorkspaceConfig. If the config write fails, no stale
  workspace.json is left behind.
- Major (coderabbit): setWorkspaceModeInConfig only treats ENOENT as
  empty config (not parse errors or permission errors). Validates
  settings is a plain object before merging to prevent clobbering.
2026-06-24 09:02:02 -07:00
gsxdsm
11ffca1611 fix(workspace): persist workspaceMode:true in config.json, let save errors propagate
Address PR #1739 review round 2:

- P1 (greptile): Auto-detection fallback now sets workspaceMode: true in
  config.json so the dashboard toggle reflects the actual state.
- Major (coderabbit): Let saveWorkspaceConfig errors propagate instead of
  silently returning 'existing' when the write fails. A failed write would
  leave the project with no git repo and no workspace config.
2026-06-24 08:36:55 -07:00
gsxdsm
42342eff03 fix(workspace): respect explicit workspaceMode:false, improve exclusion test
Address PR #1739 review feedback:

- P1 (greptile): When workspaceMode is explicitly false in config.json,
  skip the auto-detection fallback so toggling workspace mode off via the
  dashboard has a lasting effect (was being re-enabled on next registration).
- CodeRabbit: node_modules exclusion test now includes a real sibling
  sub-repo to prove the exclusion is the gate, not just absence of
  detection.
- Add test for workspaceMode:false config.json guard.
2026-06-24 08:16:36 -07:00
gsxdsm
9aaf911735 feat(workspace): add per-project workspaceMode setting with interactive confirmation
Add workspaceMode as a first-class ProjectSettings boolean that controls
whether the project root is treated as a workspace parent (multi-repo)
or a single git repo.

- ProjectSettings type + DEFAULT_PROJECT_SETTINGS: workspaceMode?: boolean
- CLI registerProjectInteractive: when sub-repos are detected, ask the
  user to confirm workspace mode instead of auto-applying
- TaskStore.updateSettings: when workspaceMode is toggled on, detect
  sub-repos and persist workspace.json; when toggled off, remove it
- Dashboard SettingsModal GeneralSection: workspace mode toggle checkbox

This lets users change workspace mode per-project at any time via the
dashboard Settings or PUT /settings API.
2026-06-24 00:45:24 -07:00
gsxdsm
ff155b9df7 fix(workspace): exclude node_modules from detection, best-effort save
Address PR #1739 review feedback:

- P1: Exclude node_modules, .fusion, .pi from detectWorkspaceRepos so
  packages installed from git sources don't produce false-positive
  workspace members.
- P2: Wrap saveWorkspaceConfig in try/catch so a write failure (permissions,
  disk full) doesn't fail the current registration.
- Nitpick: Thread runner/timeout through detectWorkspaceRepos so custom-runner
  callers are consistent across all code paths.
2026-06-24 00:26:31 -07:00
gsxdsm
cab375a6f8 fix(workspace): detect sub-repos when workspace.json is missing
The initial fix only checked loadWorkspaceConfig, but the dashboard
POST /api/projects and `fn project add` routes never create workspace.json
(only registerProjectInteractive does). So re-adding a workspace project
through the dashboard still triggered git init because the guard saw no
workspace.json.

Add detectWorkspaceRepos as a fallback: after loadWorkspaceConfig and
isInsideGitWorkTree both miss, probe for git sub-repos. If found, persist
workspace.json and return 'existing' without running git init. This covers
all registration surfaces.
2026-06-24 00:16:37 -07:00
gsxdsm
038ac3060b FN-6963: disable tool output log details by default
Agent logs now keep tool timeline rows while requiring an explicit opt-in to persist verbose tool payloads.

- Default persistAgentToolOutput to false in global settings and direct AgentLogger construction.
- Update the settings UI, API expectations, documentation, and changeset to describe opt-in tool payload persistence.
- Adjust engine and dashboard tests for the new default-off behavior while preserving explicit opt-in coverage.

Files changed:
 .changeset/FN-6963-tool-output-default-off.md      |  5 ++++
 docs/settings-reference.md                         |  2 +-
 packages/core/src/settings-schema.ts               |  6 ++++-
 .../components/__tests__/SettingsModal.test.tsx    | 22 +++++++++++++---
 .../settings/sections/GlobalGeneralSection.tsx     |  2 +-
 .../src/__tests__/routes-settings.test.ts          |  4 +--
 packages/engine/src/__tests__/agent-logger.test.ts | 30 ++++++++++++++++++----
 .../src/__tests__/heartbeat-executor.test.ts       |  4 +--
 .../src/__tests__/merger-merge-details.test.ts     |  2 +-
 .../src/__tests__/merger-verification.test.ts      |  2 +-
 .../src/__tests__/step-session-executor.test.ts    |  4 +--
 packages/engine/src/__tests__/triage.test.ts       |  2 +-
 packages/engine/src/agent-logger.ts                |  8 ++++--
 13 files changed, 71 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-6963

Fusion-Task-Lineage: 7db32871-f539-4a27-a324-02c55ce5bd04
2026-06-23 23:35:33 -07:00
gsxdsm
6745126e14 Merge branch 'main' into fix/workspace-git-init-skip 2026-06-23 23:21:35 -07:00
gsxdsm
a9ea1f6fe3 fix(workspace): skip git init for workspace-mode project roots
ensureGitRepositoryForProjectPath unconditionally ran `git init` on
non-git paths, including workspace roots. This created a stray empty
repo with unborn HEAD at the workspace root, poisoning every downstream
git command (executor session cwd: `fatal: ambiguous argument 'HEAD'`).

Add an early-return guard that checks loadWorkspaceConfig before any git
operation, keeping the workspace root non-git as intended by the
workspace execution contract.
2026-06-23 23:14:05 -07:00
gsxdsm
9fbc93c8b1 Merge remote-tracking branch 'origin/main' into latest-1717
# Conflicts:
#	packages/engine/src/executor.ts
2026-06-23 17:40:35 -07:00
gsxdsm
37b2cb38ac Merge branch 'main' into feature/workflow-branch-group 2026-06-23 17:16:16 -07:00
gsxdsm
0dea25061d Merge remote-tracking branch 'origin/main' into conflict-resolution-1717
# Conflicts:
#	packages/engine/src/__tests__/executor-recovery.test.ts
#	packages/engine/src/agent-tools.ts
#	packages/engine/src/executor.ts
#	packages/engine/src/merger-ai.ts
#	packages/engine/src/project-engine.ts
#	packages/engine/src/worktree-acquisition.ts
2026-06-23 16:12:10 -07:00
gsxdsm
4faadd4f75 Merge remote-tracking branch 'origin/main' into conflict-resolution-1712
# Conflicts:
#	packages/dashboard/app/components/WorkflowNodeEditor.tsx
#	packages/engine/src/__tests__/executor-fast-mode-workflows.test.ts
2026-06-23 15:44:52 -07:00
gsxdsm
a8abecd043 Merge remote-tracking branch 'origin/main' into conflict-resolution-1711
# Conflicts:
#	packages/engine/src/executor.ts
2026-06-23 15:37:29 -07:00
gsxdsm
905a877954 Merge pull request #1710 from MichaelHoughtonDeBox/feat/workspace-multi-repo
Workspace mode: open a folder of git repos as one project (foundation + design Q)
2026-06-23 15:08:15 -07:00
gsxdsm
81f43e0e89 Merge pull request #1730 from Runfusion/feature/memory-fix
[codex] Dispose completed spawned child sessions
2026-06-23 10:29:30 -07:00
gsxdsm
a46800128a Address PR review feedback (#1730)
- Await async spawned child session disposal

- Use own-key iteration for structured tool result previews

- Add FNXC requirement comments for new regression assertions
2026-06-23 09:57:49 -07:00
gsxdsm
b02fb62c04 fix(core): avoid loading artifact content in registry lists 2026-06-23 09:16:57 -07:00
gsxdsm
a670f5ce98 FN-6952: repair workflow-column lifecycle regressions
Restores core lifecycle compatibility while keeping workflow-column scheduling on the graduated runtime.\n\n- Split raw compatibility-flag checks from public workflow-column runtime enablement.\n- Keep scheduler and hold-release sweeps on workflow columns despite stale persisted false flags.\n- Preserve legacy moveTask guard bypass and invalid-transition behavior for compatibility paths.\n- Isolate the startup watch recovery fixture and add a patch changeset.\n\nFiles changed:\n .changeset/fn-6952-core-lifecycle-regressions.md |  5 ++++\n packages/core/src/__tests__/store-create.test.ts |  6 +++++\n packages/core/src/store.ts                       | 32 +++++++++++++++++-------\n packages/core/src/workflow-columns-settings.ts   |  8 ++----\n packages/engine/src/hold-release.ts              |  6 +++--\n packages/engine/src/scheduler.ts                 | 10 +++++++-\n 6 files changed, 49 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-6952

Fusion-Task-Lineage: cfd7ad99-db00-4454-b3d7-a07a72a7bbe7
2026-06-23 08:21:10 -07:00
gsxdsm
efb94c8623 FN-6876: add editable model pricing refresh
Add editable model pricing overrides and a LiteLLM refresh path for usage cost analytics.

- Add persisted model pricing override settings and apply them to token and team analytics cost calculations.
- Add a Command Center pricing fetch endpoint that imports chat pricing from LiteLLM and invalidates settings caches.
- Add a Global Models pricing editor with manual rows, removal, and one-click fetch support.
- Cover override lookup, settings parity, analytics, route behavior, and UI editing with tests and docs.

Files changed:
 .changeset/model-pricing-overrides.md              |   5 +
 docs/architecture.md                               |   3 +-
 docs/dashboard-guide.md                            |   5 +-
 docs/settings-reference.md                         |   3 +
 packages/core/src/__tests__/model-pricing.test.ts  | 101 +++++++++++
 .../core/src/__tests__/settings-parity.test.ts     |   4 +
 packages/core/src/__tests__/store-settings.test.ts |  25 +++
 .../core/src/__tests__/token-analytics.test.ts     |  39 +++++
 packages/core/src/index.ts                         |   4 +
 packages/core/src/model-pricing.ts                 | 118 +++++++++++--
 packages/core/src/settings-schema.ts               |   3 +
 packages/core/src/team-analytics.ts                |  17 +-
 packages/core/src/token-analytics.ts               |  19 +-
 packages/core/src/types.ts                         |  12 ++
 .../dashboard/app/components/SettingsModal.tsx     |   2 +
 .../settings/sections/GlobalModelsSection.tsx      |   8 +-
 .../settings/sections/ModelPricingSection.css      |  82 +++++++++
 .../settings/sections/ModelPricingSection.test.tsx | 126 ++++++++++++++
 .../settings/sections/ModelPricingSection.tsx      | 193 +++++++++++++++++++++
 .../register-command-center-routes.test.ts         | 172 +++++++++++++++++-
 .../src/routes/register-command-center-routes.ts   |  58 +++++++
 21 files changed, 967 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-6876

Fusion-Task-Lineage: 4d4e3b9d-bec4-4e14-b7bc-88f846465566
2026-06-23 01:14:11 -07:00
gsxdsm
a147a983d5 fix(FN-6950): protect global settings and task chat icons 2026-06-23 00:31:58 -07:00
gsxdsm
849b40d220 FN-6947: tolerate workflow project identity failures
Keep workflow IR resolution usable when project identity lookup is unavailable.

- Treat workflow settings project identity errors as an absent project scope.
- Preserve project-scoped cache and prompt override behavior when identity resolves.
- Add resolver regression coverage and a patch changeset for the fallback behavior.

Files changed:
 .changeset/fn-6947-workflow-ir-project-identity.md |  5 ++
 .../src/__tests__/workflow-ir-resolver.test.ts     | 62 +++++++++++++++++++++-
 packages/core/src/workflow-ir-resolver.ts          | 12 ++++-
 3 files changed, 76 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6947

Fusion-Task-Lineage: f63b985f-6c43-4163-8391-8ca5efb83079
2026-06-22 23:56:34 -07:00
gsxdsm
32986f6b50 fix(core): tolerate missing done task mirrors on startup 2026-06-22 21:51:28 -07:00
gsxdsm
65c4dc5438 fix(engine): harden workflow runtime cutover 2026-06-22 21:45:05 -07:00