Commit Graph

2627 Commits

Author SHA1 Message Date
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
fe536b2af8 FN-6954: reconcile stale parked task assignments
Reconcile agent/task drift when durable agents remain linked to queued tasks without live execution proof.

- clear stale Agent.taskId links for parked todo/triage tasks while preserving task leases and queue state
- report stale parked assignments as active/no-live-run in Reports Health Check before reconciliation completes
- add scheduler and self-healing coverage for queued lease drift, overlap starvation, and audit events
- document the reconciliation behavior and add a published package patch changeset

Files changed:
 .changeset/fn-6954-agent-task-state-drift.md       |   5 +
 docs/architecture.md                               |   2 +
 .../src/__tests__/heartbeat-executor.test.ts       |  68 ++++++++++++
 .../__tests__/scheduler-overlap-starvation.test.ts |  68 +++++++++++-
 .../self-healing-agent-link-drift.test.ts          |  97 ++++++++++++++++-
 .../engine/src/__tests__/task-agent-sync.test.ts   |  33 +++++-
 packages/engine/src/agent-heartbeat.ts             | 121 +++++++++++++++++++--
 packages/engine/src/run-audit.ts                   |   5 +
 packages/engine/src/runtimes/in-process-runtime.ts |   1 +
 packages/engine/src/scheduler.ts                   |  24 +++-
 packages/engine/src/self-healing.ts                | 102 ++++++++++++++---
 packages/engine/src/task-agent-sync.ts             |  65 ++++++++++-
 12 files changed, 555 insertions(+), 36 deletions(-)

Fusion-Task-Id: FN-6954
Fusion-Task-Lineage: 24b8a2eb-5a33-4539-ab64-ae2bbfc2d195
2026-06-23 10:30:50 -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
e59b1fa07d Merge pull request #1726 from plarson/fix/triage-spec-review-fallback
fix(triage): pass fallback model settings to spec review
2026-06-23 09:52:58 -07:00
gsxdsm
36b7ad90fd fix(engine): bound structured tool result log previews 2026-06-23 09:19:32 -07:00
gsxdsm
466cf9ca8d fix(engine): dispose completed spawned child sessions 2026-06-23 09:12:28 -07:00
Phil Larson
823623e1c6 fix(triage): address spec review fallback PR comments 2026-06-23 08:51:58 -07:00
Phil Larson
40bef6dfce fix(triage): pass fallback model settings to spec review 2026-06-23 08:39:27 -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
9218613552 FN-6949: fix auto-merge lifecycle finalization
Make auto-merge completion idempotent when landed tasks are left outside done.

- Add shared auto-merge finalization logic that refreshes task rows, clears stale queue/blocker state, and recovery-rehomes proven landed tasks to done.
- Route direct AI merge, merge-confirmed fast paths, and self-healing recovery through the shared finalizer with run-audit events for reconciled or blocked column mismatches.
- Extend lifecycle and recovery tests to cover todo/in-review mismatches, finalization failures, stale blockers, and cleanup idempotency.
- Add the required patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-6949-auto-merge-lifecycle.md         |   5 +
 .../src/__tests__/merge-error-recovery.test.ts     |  50 ++++-
 packages/engine/src/__tests__/merger-ai.test.ts    |   8 +-
 .../src/__tests__/merger-merge-lifecycle.test.ts   | 155 +++++++++++++++
 .../ai-merge-cleanup-enoent-idempotent.test.ts     |   2 +-
 packages/engine/src/__tests__/self-healing.test.ts | 194 +++++++++++--------
 packages/engine/src/auto-merge-finalization.ts     | 208 +++++++++++++++++++++
 packages/engine/src/merger-ai.ts                   |  47 +++--
 packages/engine/src/project-engine.ts              |  87 +++++----
 packages/engine/src/run-audit.ts                   |   4 +
 packages/engine/src/self-healing.ts                |  92 ++++-----
 11 files changed, 663 insertions(+), 189 deletions(-)

Fusion-Task-Id: FN-6949

Fusion-Task-Lineage: db784ec0-68e9-4a37-9728-daa6f133e294
2026-06-22 23:18:28 -07:00
gsxdsm
acf0fff413 test(engine): cover workflow cutover recovery guards 2026-06-22 22:22:37 -07:00
gsxdsm
e60b1378b8 fix(engine): address workflow cutover review feedback 2026-06-22 22:17:30 -07:00
gsxdsm
65c4dc5438 fix(engine): harden workflow runtime cutover 2026-06-22 21:45:05 -07:00
gsxdsm
bf3276295c fix(engine): complete workflow runtime cutover 2026-06-22 20:45:29 -07:00
gsxdsm
f9043d733e fix(dashboard): polish workflow and chrome defaults 2026-06-22 19:48:50 -07:00
gsxdsm
ec1d29e818 FN-6922: guard worktree acquisition returns from repo root
Prevent task worktree acquisition from handing the project root back to executors.

- Add a repo-root return guard across resume, pool, and fresh acquisition paths.
- Clear invalid repo-root task assignments and create a fresh worktree fallback when safe.
- Share repo-root canonicalization and expand regression coverage for acquisition liveness.
- Document the acquisition guard and add a patch changeset.

Files changed:
 .changeset/fn-6922-repo-root-acquisition-guard.md  |   5 +
 .../repo-root-task-worktree-requeue-loop.md        |   9 +-
 .../__tests__/executor-worktree-liveness.test.ts   |  35 +++
 .../worktree-acquisition-secrets-env.test.ts       |   9 +-
 .../src/__tests__/worktree-acquisition.test.ts     |  91 ++++++-
 packages/engine/src/worktree-acquisition.ts        | 272 +++++++++++++--------
 packages/engine/src/worktree-pool.ts               |   8 +-
 7 files changed, 304 insertions(+), 125 deletions(-)

Fusion-Task-Id: FN-6922

Fusion-Task-Lineage: c16cee1b-de16-4d5f-90e0-132f94fa8377
2026-06-22 19:11:08 -07:00
gsxdsm
4fd8d444fb fix(dashboard): polish app chrome and workflow defaults 2026-06-22 18:21:06 -07:00
gsxdsm
c229a15e20 FN-6934: restrict agent workflow reassignment
Clarify agent workflow-routing prompts so agents do not reassign tasks they did not create unless directed.

- Add executor guardrails against changing the current task workflow without explicit user instruction.
- Update triage workflow-routing guidance to distinguish existing tasks from agent-created tasks.
- Cover workflow ownership policy in prompt and engine tests, docs, and a patch changeset.

Files changed:
 .changeset/fn-6934-workflow-movement-policy.md     |  5 +++++
 docs/agents.md                                     |  6 ++++++
 docs/custom-workflow-reliability-acceptance-map.md |  7 +++++--
 docs/settings-reference.md                         |  9 +++++++--
 docs/workflow-steps.md                             |  9 +++++++--
 packages/core/src/__tests__/agent-prompts.test.ts  | 15 ++++++++++++++
 packages/core/src/agent-prompts.ts                 | 23 ++++++++++++++++------
 .../src/__tests__/executor-review-verdicts.test.ts |  3 +++
 .../__tests__/triage-threshold-settings.test.ts    |  3 +++
 packages/engine/src/__tests__/triage.test.ts       |  2 +-
 packages/engine/src/executor.ts                    |  5 +++++
 11 files changed, 74 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-6934

Fusion-Task-Lineage: cc583806-b160-4a08-b1a7-e798a575dbd5
2026-06-22 17:58:27 -07:00
gsxdsm
0b410d54e1 FN-6915: surface user comments in agent prompts
User task chat and steering comments now flow into planning, review, and merge agent context.

- Add a shared user-comment formatter and selector for prompt context.
- Inject latest user comments into planner-triggered review, reviewer, merger, and clean-room AI merge prompts.
- Cover comment selection, prompt formatting, review/merge propagation, and docs updates with targeted tests.

Files changed:
 docs/architecture.md                               |  1 +
 docs/dashboard-guide.md                            |  1 +
 .../src/__tests__/agent-user-comments.test.ts      | 81 ++++++++++++++++++++++
 .../executor-review-step-indexing.test.ts          | 28 +++++++-
 packages/engine/src/__tests__/merger-ai.test.ts    | 54 +++++++++++++++
 .../src/__tests__/merger-prompt-and-utils.test.ts  | 29 ++++++++
 packages/engine/src/__tests__/reviewer.test.ts     | 37 ++++++++--
 packages/engine/src/__tests__/triage.test.ts       | 23 ++++++
 packages/engine/src/agent-user-comments.ts         | 60 ++++++++++++++++
 packages/engine/src/executor.ts                    | 14 ++--
 packages/engine/src/merger-ai.ts                   | 23 +++++-
 packages/engine/src/merger.ts                      | 22 +++++-
 packages/engine/src/reviewer.ts                    | 13 ++++
 13 files changed, 372 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-6915

Fusion-Task-Lineage: 02de0c12-481a-4489-b495-70c9c00619bc
2026-06-22 03:34:15 -07:00
gsxdsm
af06170a51 FN-6778: add agent artifact registry tools
Adds engine and chat tools for registering, discovering, and viewing artifacts with inbox notifications.

- Add fn_artifact_register, fn_artifact_list, and fn_artifact_view tools for heartbeat, executor, and chat sessions.
- Send best-effort dashboard system inbox notifications when artifacts are registered.
- Classify artifact tools for action gating and coordination exemptions, with coverage for executor, heartbeat, permanent agent, and chat flows.
- Document the artifact registry behavior and update package metadata, quarantine ledger, and line-count baseline.

Files changed:
 .changeset/fn-6778-artifact-agent-tools.md         |   5 +
 CONCEPTS.md                                        |   3 +
 docs/agents.md                                     |   1 +
 packages/core/src/db.ts                            |   1 +
 .../src/__tests__/session-error-recovery.test.ts   |   1 +
 .../session-persistence-roundtrip.test.ts          |   1 +
 .../src/__tests__/session-reconnect.test.ts        |   1 +
 .../src/__tests__/session-resume-history.test.ts   |   1 +
 packages/dashboard/src/chat.ts                     |   6 +-
 packages/dashboard/src/planning.ts                 |   4 +
 packages/dashboard/src/test/mockCoreEngine.ts      |   1 +
 .../engine/src/__tests__/agent-action-gate.test.ts |   3 +
 .../src/__tests__/agent-artifact-tools.test.ts     | 458 +++++++++++++++++++++
 .../src/__tests__/executor-step-session.test.ts    |  48 +++
 .../src/__tests__/gating-classifications.test.ts   |   3 +
 .../src/__tests__/heartbeat-executor.test.ts       |  40 +-
 .../src/__tests__/heartbeat-session-prompt.test.ts |  25 +-
 .../src/__tests__/permanent-agent-gating.test.ts   |   6 +
 packages/engine/src/agent-heartbeat.ts             |   6 +-
 packages/engine/src/agent-tools.ts                 | 288 ++++++++++++-
 packages/engine/src/executor.ts                    |  25 ++
 packages/engine/src/gating-classifications.ts      |   7 +
 packages/engine/src/index.ts                       |   9 +
 scripts/lib/test-quarantine.json                   |   8 +-
 scripts/line-count-baseline.json                   |  54 +--
 25 files changed, 945 insertions(+), 60 deletions(-)

Fusion-Task-Id: FN-6778
Fusion-Task-Lineage: 7eb4afcb-8140-4f86-9540-eb3b83e64148
2026-06-22 03:34:14 -07:00
gsxdsm
f2c1a28eab fix(workspace): re-read task before workspaceWorktrees merge; FNXC format
Addresses the follow-up review on the foundation fixes:
- Re-read the task via store.getTask immediately before merging the per-repo
  entry, so a concurrent sibling-repo acquisition that landed since the initial
  read isn't clobbered by updateTask's wholesale map replace (narrows the
  read-modify-write window to the store lock; a fully atomic per-repo store-level
  merge remains a follow-up).
- Normalize the inline FNXC comment to the FNXC:Area yyyy-MM-dd-hh:mm: convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 00:26:40 -07:00
gsxdsm
accb32e9b6 fix(review): address PR #1711 review findings
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 00:19:15 -07:00
gsxdsm
429258354d fix(workspace): address CodeRabbit review findings on the foundation
Resolves the actionable CodeRabbit threads on the workspace-mode foundation:

- project-resolver: defer saveWorkspaceConfig until after the user confirms init
  and store.init() succeeds (no partial .fusion/ on a declined/non-interactive run).
- git-repository: validate each candidate with a real `git rev-parse` work-tree
  probe before counting it (no false-positive repos from stray .git markers);
  loadWorkspaceConfig now rejects absolute paths, `..` escapes, and non-string
  entries so a corrupt/malicious config can't resolve outside the workspace root.
- executor: gate workspace mode on repos.length > 0 at all three sites so an
  empty { repos: [] } can't bypass the git-repo guard or enable an empty workspace.
- worktree-acquisition: thread the configured-command runner through the workspace
  acquire path (sub-repos run their init setup); validate repoRelPath as an in-root
  relative path before joining; liveness-check a remembered worktree before
  reporting it ready (pruned paths fall through to re-acquire); clear the singular
  task.worktree/branch after persisting per-repo state (per-repo state lives only
  in workspaceWorktrees).
- agent-tools: forward runContext into acquireWorkspaceRepoWorktree for log attribution.

The executor-workspace test's mock-the-subject pattern is left for the
session-scoping follow-up that rewrites it with a real two-repo fixture (FN-5048).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 00:09:59 -07:00
gsxdsm
79e53e8d97 fix(workspace): remove unused acquireWorkspaceRepoWorktree import
The foundation imports acquireWorkspaceRepoWorktree in executor.ts but
deliberately stops before wiring it into the executor lifecycle, so the import
is unused and fails @typescript-eslint/no-unused-vars (the sole Lint failure on
this PR). Remove the dead import; it is reintroduced with real usage in the
session-scoping follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 23:37:12 -07:00
gsxdsm
26c8d960a2 FN-6893: add editable built-in workflow prompts
Enable project-scoped prompt overrides for built-in workflows without allowing structural edits.

- Add workflow prompt override storage, normalization, and IR overlay support for prompt and gate nodes.
- Expose dashboard API routes and Workflow Node Editor controls to edit or reset built-in prompts.
- Cover override persistence, route behavior, editor flows, and engine workflow resolution with tests.
- Document editable built-in prompts and reset-to-default behavior.

Files changed:
 docs/dashboard-guide.md                            |   2 +-
 docs/settings-reference.md                         |   2 +
 docs/workflow-steps.md                             |  20 ++-
 .../__tests__/workflow-definition-store.test.ts    |  25 +++
 .../workflow-prompt-overrides-store.test.ts        | 190 ++++++++++++++++++++
 .../__tests__/workflow-prompt-overrides.test.ts    |  58 +++++++
 packages/core/src/db.ts                            |  35 +++-
 packages/core/src/index.ts                         |   7 +
 packages/core/src/store.ts                         |  97 ++++++++++-
 packages/core/src/workflow-ir-resolver.ts          |  21 ++-
 packages/core/src/workflow-prompt-overrides.ts     |  65 +++++++
 packages/dashboard/app/api/legacy.ts               |  34 ++++
 .../app/components/WorkflowNodeEditor.css          |  35 ++++
 .../app/components/WorkflowNodeEditor.tsx          | 191 ++++++++++++++++++++-
 .../__tests__/WorkflowNodeEditor.test.tsx          | 136 ++++++++++++++-
 .../src/__tests__/workflow-routes.test.ts          |  59 +++++++
 .../src/routes/register-workflow-routes.ts         |  86 +++++++++-
 .../workflow-prompt-overrides-resolution.test.ts   |  61 +++++++
 packages/i18n/locales/en/app.json                  |  14 +-
 packages/i18n/locales/es/app.json                  |  14 +-
 packages/i18n/locales/fr/app.json                  |  14 +-
 packages/i18n/locales/ko/app.json                  |  14 +-
 packages/i18n/locales/zh-CN/app.json               |  14 +-
 packages/i18n/locales/zh-TW/app.json               |  14 +-
 24 files changed, 1168 insertions(+), 40 deletions(-)

Fusion-Task-Id: FN-6893

Fusion-Task-Lineage: 961eb119-32e1-44c3-9b51-6edd982fa565
2026-06-21 21:23:41 -07:00
gsxdsm
316d2659b8 fix(review): workspace-merge park must use status:'failed' to avoid re-enqueue loop (U0)
Post-fix verification review (correctness + adversarial + reliability, unanimous
P0) found that the earlier retry-burn fix introduced an infinite loop: parking a
WorkspaceTaskMergeError task with status:null + mergeRetries:0 passes every
auto-merge eligibility gate (canMergeTask short-circuits only on status==='failed'),
so the cooldown sweep re-enqueues it every tick → guard re-throws → re-park, forever.

- Park with status:'failed' (keep mergeRetries:0). canMergeTask now blocks the
  auto-sweep; a human's manual merge still works because it flows through the
  manual-resolver branch (rejectMergeResolvers), which bypasses canMergeTask — so
  'failed' does not block manual retry (the original comment's worry was wrong).
- Detect the error via `err instanceof Error && err.name === "WorkspaceTaskMergeError"`,
  matching the VerificationError/MergeAbortedError convention and bundle-safe across
  the @fusion/core→@fusion/engine boundary (drops the now-unused class import).
- Document that the dispatch door guard is a fast-fail only; the unconditional
  chokepoint guard inside runAiMerge is the authoritative enforcement.
- Add a regression test asserting the auto-merge park sets status:'failed' (not null).

Gate green: lint, typecheck, build, test:gate (649+58), project-engine (81).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 20:29:46 -07:00
gsxdsm
7240b77c67 fix(review): harden R7 workspace merge guard + deprecation warning (U0)
Applies ce-code-review (autofix) feedback — 5 reviewers, P1s corroborated.

F1 [P1, ×4 reviewers] Guard the merge chokepoint, not just the 4 doors. The
per-caller `getTask().catch(()=>null); if(t) assert` pattern failed open on a
transient read, and runAiMerge re-read the task unguarded — so a workspace
task could reach git work against the non-git root. Added a named
WorkspaceTaskMergeError and call assertNotWorkspaceTaskMerge inside runAiMerge
(the sole merge path) and the deprecated aiMergeTask body; door guards remain
as fast-fail defense-in-depth.

F2 [P1] The dispatch catch treated the guard throw as a merge failure and set
mergeRetries=MAX, permanently blocking manual retry. It now recognizes
WorkspaceTaskMergeError and parks without burning retries.

F3 [P2] Deprecation-warning test asserted toBeLessThanOrEqual(1) — vacuously
true on zero emissions. Now resets the per-project flag and asserts the
warning fires exactly once and not again on a second deterministic merge.

F6 [P2] The once-per-process warning flag suppressed the notice for all other
projects in a multi-project host; now keyed per project (Set by cwd).

F5/F7/F8 [P3] @deprecated propagated to the aiMergeTask barrel re-export; CLI
runTaskMerge guard moved inside the formatted try/catch; FNXC placeholder
timestamps corrected; test .at(-1) -> length index.

Documented as residual (deferred to master-plan U8, not bugs in U0's window):
self-healing auto-finalize + store.mergeTask are additional merge-completing
paths not hardened here — workspace tasks are not end-to-end runnable until
master-plan Phase A, and U8 makes self-healing workspace-aware.

Gate green: typecheck (29 projects), lint, build, test:gate (649+58),
affected tests (206+4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 19:19:55 -07:00
gsxdsm
a6252e518d refactor(merger): unify on runAiMerge as the sole merge path (U0)
Make runAiMerge (the FN-5633 clean-room AI merge path, already the default)
the sole merge path; soft-deprecate the legacy aiMergeTask pipeline. Phase 0
of the workspace-mode master plan — a standalone merge-consolidation refactor
that lands first so downstream workspace work targets one merge function.

U1 — collapse the dispatch: project-engine.ts now calls runAiMerge
unconditionally; the two direct callers that bypassed the dispatch
(dashboard.ts onMergeImpl in --no-engine mode, task.ts runTaskMerge /
`fn task merge`) now route to runAiMerge too. Export runAiMerge from
@fusion/engine.

U2 — soft-deprecate: aiMergeTask is @deprecated (body retained for a later
deletion pass; shared helpers runAiMerge imports, e.g.
captureSingleCommitLandedMetadata, left intact). merger.mode "deterministic"
is annotated deprecated and made inert (type + field kept — published
@runfusion/fusion surface); the dispatch logs a one-time deprecation warning
and routes to runAiMerge. Changeset added (minor).

U3 — R7 workspace merge-boundary guard: shared @fusion/core predicate
assertNotWorkspaceTaskMerge(task) rejects tasks with populated
workspaceWorktrees at all four merge entry points (dispatch, store.mergeTask,
onMergeImpl, runTaskMerge) with an error naming master-plan U6. Covers the
window until per-repo merge support lands; U6 removes it.

U4 — deterministic-mode blast-radius audit: no production project, CI config,
or seeded setting pins merger.mode "deterministic"; only four engine tests
used it to drive the dispatch to aiMergeTask as a mockable seam — migrated to
mock runAiMerge instead. Other module-level aiMergeTask mocks were dead under
the default "ai" mode or test aiMergeTask directly (body retained), so they
are unaffected.

Also removes an unused acquireWorkspaceRepoWorktree import inherited from the
foundation branch (executor.ts) that was failing lint; master-plan U1 re-adds
it with its per-repo usage.

Merge gate green: lint, typecheck (29 projects), build, test:gate
(649 + 58), plus the migrated (114) and new predicate (4) tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 18:58:06 -07:00
gsxdsm
d5ea17d8ab FN-6873: exclude archived tasks from auto-claim scans
Auto-claim now revalidates cached candidates so archived tasks cannot be surfaced or claimed.

- Restrict auto-claim candidate runnability to live todo rows while still allowing archived dependencies to satisfy blockers.
- Rebuild fresh auto-claim candidates from canonical task fields before heartbeat prompt rendering and claim selection.
- Cover archived-while-cached snapshots and executor/engineer heartbeat behavior with regression tests.

Files changed:
 .../src/__tests__/auto-claim-snapshot.test.ts      | 52 ++++++++++++++++--
 .../src/__tests__/heartbeat-executor.test.ts       | 63 ++++++++++++++++++++++
 packages/engine/src/auto-claim-snapshot.ts         |  6 +++
 3 files changed, 118 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6873

Fusion-Task-Lineage: 3bd438f8-bbf8-428e-a7e2-56aebbbc6522
2026-06-21 16:23:42 -07:00
gsxdsm
7ee1fec22c FN-6861: reject repo-root task worktrees
Prevent stale task metadata from treating the project repository root as a reusable task worktree.

- Classify root-equal task worktree paths as repo-root before registered-worktree checks.
- Clear stale resumed repo-root assignments so acquisition creates a fresh configured task worktree.
- Add structured executor audit metadata and regression coverage for repo-root liveness collisions.
- Document the repo-root requeue-loop invariant and recovery behavior.

Files changed:
 docs/architecture.md                               |  2 +-
 .../repo-root-task-worktree-requeue-loop.md        | 49 ++++++++++++++++
 .../__tests__/executor-worktree-liveness.test.ts   | 23 +++++++-
 .../src/__tests__/worktree-acquisition.test.ts     | 67 +++++++++++++++++++++-
 .../src/__tests__/worktree-pool-liveness.test.ts   | 25 ++++++++
 packages/engine/src/executor.ts                    | 22 ++++++-
 packages/engine/src/worktree-acquisition.ts        |  4 ++
 packages/engine/src/worktree-pool.ts               | 13 ++++-
 8 files changed, 198 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-6861

Fusion-Task-Lineage: d6a4922e-5a21-4037-b2c2-86ff53d8e9e3
2026-06-21 14:28:58 -07:00
MichaelHoughtonDeBox
8f4098e5b1 feat: add workspace mode foundation (multi-repo projects)
Allow registering a non-git parent directory that contains multiple git
repositories as a single Fusion project. The agent acquires per-repo
worktrees on demand via a new `fn_acquire_repo_worktree` tool as it
discovers it needs to work in each sub-repo.

This commit lays the foundation:
- detectWorkspaceRepos / loadWorkspaceConfig / saveWorkspaceConfig in
  @fusion/core (config persisted to .fusion/workspace.json)
- Task.workspaceWorktrees data model + store plumbing (per-repo
  worktree/branch map, distinct from the singular task.worktree)
- acquireWorkspaceRepoWorktree wraps acquireTaskWorktree per sub-repo,
  clearing the singular worktree/branch fields so each sub-repo gets a
  fresh worktree instead of resuming a sibling repo's worktree
- fn_acquire_repo_worktree agent tool + workspace prompt injection
- executor git-repository validation bypassed when a workspace config
  is present
- CLI `fn init` detects a non-git dir containing sub-repos and writes a
  workspace config

Known gap (intentionally left for design discussion, see PR): the
executor's main worktree-acquisition path still assumes a single git
root and is not yet workspace-aware. End-to-end execution (skipping the
root acquisition, per-repo merge, per-repo session scoping) is a
follow-on once the execution model is agreed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 22:04:37 +01:00
gsxdsm
d99246cb74 FN-6834: use OS-available memory for system metrics
Use shared OS-available memory readings so macOS cache/inactive pages are not counted as used.

- Add a core available-memory helper that prefers `process.availableMemory()` and flags `freemem` fallback reliability.
- Route core metrics, dashboard system stats, and the dashboard TUI through the shared helper.
- Move and expand memory tests across core, dashboard routes, and verification coverage while documenting the telemetry behavior.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fix-macos-memory-used.md                |  5 ++
 docs/architecture.md                               |  2 +-
 docs/dashboard-guide.md                            |  2 +-
 .../__tests__/available-memory.test.ts             | 54 --------------
 .../cli/src/commands/dashboard-tui/controller.ts   | 37 +---------
 .../core/src/__tests__/available-memory.test.ts    | 83 ++++++++++++++++++++++
 packages/core/src/__tests__/system-metrics.test.ts | 36 +++++++++-
 packages/core/src/available-memory.ts              | 32 +++++++++
 packages/core/src/index.ts                         |  1 +
 packages/core/src/system-metrics.ts                |  9 ++-
 .../dashboard/src/__tests__/routes-system.test.ts  | 27 +++++++
 packages/dashboard/src/routes.ts                   |  7 +-
 .../src/__tests__/run-verification-command.test.ts | 18 +++++
 13 files changed, 218 insertions(+), 95 deletions(-)

Fusion-Task-Id: FN-6834

Fusion-Task-Lineage: 2e651551-6c35-46d1-b517-535758c7ace2
2026-06-21 13:32:19 -07:00
gsxdsm
9620a50756 FN-6850: refresh auto-claim candidates before heartbeat claims
Auto-claim heartbeats now validate cached todo candidates against current task rows before displaying or claiming them.

- Share the auto-claim runnability predicate between snapshot generation and canonical freshness checks.
- Rebuild cached candidates from fresh slim task rows before role filtering, prompt rendering, and claim selection.
- Cover stale triage, assigned, checked-out, deleted, dependency-blocked, and retitled candidate cases in snapshot and heartbeat tests.

Files changed:
 .../src/__tests__/auto-claim-snapshot.test.ts      | 65 +++++++++++++++-
 .../src/__tests__/heartbeat-executor.test.ts       | 85 +++++++++++++++++++-
 packages/engine/src/agent-heartbeat.ts             | 15 ++--
 packages/engine/src/auto-claim-snapshot.ts         | 91 +++++++++++++++-------
 4 files changed, 220 insertions(+), 36 deletions(-)

Fusion-Task-Id: FN-6850

Fusion-Task-Lineage: 5af79319-46f4-4ee7-b6dc-d846f45abaa4
2026-06-21 13:25:41 -07:00
gsxdsm
bbac132d71 Merge pull request #1708 from Runfusion/gsxdsm/slow-tests
fix: keep Fusion test verification bounded
2026-06-21 11:08:02 -07:00
gsxdsm
21df96cfbb fix(FN-5048): address PR feedback on test verification
Fusion-Task-Id: FN-5048
2026-06-21 10:53:08 -07:00
gsxdsm
03af93eb3a fix(FN-5048): direct agent + tool verification away from full workspace suite
Tighten the executor agent guidance and the fn_run_verification tool guidance so
verification stays scoped to changed files instead of running the full workspace
test suite, which (for a foundational-package edit) reverse-expands across the
whole workspace and stalls the task.

- agent-prompts.ts: remove the "during final integration" blanket permission to
  run workspace-wide suites; name the forbidden full-run commands explicitly.
- run-verification-tool.ts: strengthen BOUNDED_VERIFICATION_GUIDANCE to forbid
  `pnpm test:full` / `pnpm verify:workspace` / whole-package runs as verification.

Engine + core typecheck pass; run-verification-command and executor-review-verdicts
prompt-assertion suites stay green (93 tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 10:50:48 -07:00
gsxdsm
bc1c7db4bc Merge pull request #1707 from Runfusion/gsxdsm/engine-worklow
fix(engine): preserve task progress when a single-session run is hard-cancelled (FN-6722)
2026-06-21 10:42:55 -07:00
gsxdsm
ce90cc9b62 fix(FN-5048): keep Fusion test verification bounded 2026-06-21 10:05:12 -07:00
gsxdsm
e6503ca872 Address PR review feedback (#1707)
- Read hasResumableProgress from latestTask (the store snapshot fetched
  at ~9226), not the frozen dispatch-time task param, so a freshly
  dispatched task that commits step progress mid-session is preserved on
  a hard-cancel teardown — not just the re-dispatch case (greptile P1)
- Add companion regression test for the fresh-task-with-in-session-progress
  case, which fails against the stale-task snapshot (greptile P1)
- Reformat the requirement comment block to the canonical FNXC heading
  (FNXC:WorkflowLifecycle yyyy-MM-dd-hh:mm:) convention (CodeRabbit)

Fusion-Task-Id: FN-6722

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 09:59:26 -07:00
gsxdsm
93017a3c4a fix(engine): preserve task progress when a single-session run is hard-cancelled
When the engine aborted in-flight work mid-execution and bounced the task
back to `todo`, the single-session teardown cleared the task `branch` and
re-queued without `preserveResumeState` — resetting every step to `pending`
(store.moveTaskInternal resetAllStepsToPending) and dropping the pointer to
the commits already on the task branch. The next dispatch then re-planned
from Step 0 and the committed work was stranded, observed as FN-6722 losing
all its progress and getting stuck in todo.

The teardown now keeps the branch and moves with `preserveResumeState`
whenever the task has resumable step progress, matching the sibling
step-session (executor ~8065) and pause-park (executor ~1826) paths, so
execute() resumes onto the existing branch from the first incomplete step.
The worktree is still removed to free its concurrency slot (FN-6782) — only
the durable pointers (branch + step state) are kept.

Adds a regression test driving the exact single-session catch teardown.

Fusion-Task-Id: FN-6722

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 09:41:51 -07:00
gsxdsm
7e478fb473 Merge pull request #1703 from Runfusion/gsxdsm/workflow-optional-steps
feat(dashboard): workflow optional steps — authoring, full-modal parity, stepwise seam
2026-06-21 09:04:39 -07:00
gsxdsm
c7b56a5ab7 FN-6832: preserve default workflow routing
Preserve the default workflow unless users explicitly request workflow routing changes.

- Update triage and fast-planning prompt guidance to stop inferring alternate workflows from task type or no-commit markers.
- Refresh workflow docs and prompt tests to assert explicit-request-only workflow selection.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-6832-workflow-routing.md               |  5 +++++
 docs/workflow-steps.md                               |  5 ++++-
 packages/core/src/agent-prompts.ts                   | 20 +++++++++++++-------
 .../src/__tests__/triage-threshold-settings.test.ts  |  7 +++++--
 packages/engine/src/__tests__/triage.test.ts         | 13 +++++--------
 5 files changed, 32 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-6832

Fusion-Task-Lineage: 5a7ad103-2081-4c4c-ac32-fd5e4f6adfda
2026-06-21 09:00:40 -07:00
gsxdsm
fbce59b707 FN-6777: add artifact registry storage
Add a core artifact registry for storing metadata and task-scoped artifact payloads.\n\n- Add artifact types, schema, migrations, store APIs, and exports for registering/listing artifact metadata.\n- Persist binary artifact payloads under task or project artifact directories and hydrate artifacts during worktree acquisition.\n- Cover registry behavior, DB schema, and worktree hydration with tests and document storage semantics.\n\nFiles changed:\n .changeset/fn-6777-artifact-registry.md            |   5 +\n docs/storage.md                                    |   8 +\n packages/core/src/__tests__/artifacts.test.ts      | 257 +++++++++++++++++++++\n packages/core/src/__tests__/db.test.ts             |   5 +\n packages/core/src/db.ts                            |  59 ++++-\n packages/core/src/index.ts                         |   2 +-\n packages/core/src/store.ts                         | 220 +++++++++++++++++-\n packages/core/src/types.ts                         |  75 ++++++\n .../engine/src/__tests__/executor-test-helpers.ts  |   1 +\n .../engine/src/__tests__/executor-worktree.test.ts |   2 +\n .../__tests__/worktree-acquisition-backend.test.ts |   2 +-\n .../worktree-acquisition-secrets-env.test.ts       |   2 +-\n .../worktree-acquisition-worktrunk.test.ts         |   2 +-\n .../src/__tests__/worktree-acquisition.test.ts     |   2 +-\n .../src/__tests__/worktree-db-hydrate.test.ts      |  59 +++++\n packages/engine/src/worktree-acquisition.ts        |   2 +-\n packages/engine/src/worktree-db-hydrate.ts         |  42 +++-\n 17 files changed, 732 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-6777

Fusion-Task-Lineage: 42cdcdcf-6388-42fe-8de1-6857ef20839d
2026-06-21 09:00:40 -07:00
gsxdsm
cc26b333ce FN-6856: restrict executor full-suite testing
Clarify executor verification guidance so agents default to targeted tests and reserve full workspace suites for explicit opt-in.

- Update canonical executor prompts to prohibit full/workspace-wide test suites as the normal verification path.
- Preserve workspace lint/build/typecheck gates while requiring targeted test verification unless task or workflow instructions opt in.
- Extend executor prompt coverage to assert the full-suite restriction and allowFullSuite opt-in language.

Files changed:
 packages/core/src/agent-prompts.ts                            | 11 ++++++++---
 .../engine/src/__tests__/executor-review-verdicts.test.ts     |  5 ++++-
 packages/engine/src/executor.ts                               | 11 ++++++++---
 3 files changed, 20 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-6856
Fusion-Task-Lineage: 78d698df-9e85-4371-bf59-af27e64e3069
2026-06-21 09:00:40 -07:00
gsxdsm
fa9a3cc52f Address PR review feedback (#1704): clear stale external marker on acquire
Move externalEngines.delete(projectId) to immediately after acquiring the
singleton lock instead of after engine.start() succeeds. If a project was
marked external, the holder exits, acquire succeeds, but start() then throws,
the success-path delete never ran and hasRunningEngine() reported a phantom
engine forever. Added a regression test for the failed-takeover path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:32:53 -07:00
gsxdsm
0a49023f0b Address PR review feedback (#1704)
- Stop reconciliation/startAll/onProjectAccessed from warning every tick for
  externally-owned engines: swallow EngineAlreadyRunningError in the outer
  catches (it's expected and already logged once in createAndStart)
- Add FNXC:DashboardHealth requirement-trace comments on the externalEngines
  field and the dashboard hasRunningEngine health check
- Add regression test: reconciliation stays quiet across ticks for an
  externally-owned engine (inner refusal logged once, outer failure suppressed)
- Add regression test: hasDashboardEngine legacy fallback to getAllEngines when
  hasRunningEngine is unavailable on the manager

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:29:47 -07:00
gsxdsm
7635ba8682 fix: report engine available when another fusion process owns it
The dashboard's engine-availability health check only counted engines
this process started. A second launch (e.g. `pnpm dev dashboard`
alongside an already-running `fusion`) is correctly refused the
per-machine engine singleton lock, so its engine map stays empty and
the dashboard showed a false "engine not running" banner even though an
engine was live on the machine.

ProjectEngineManager now records projects whose singleton lock is held
by another process (via EngineAlreadyRunningError) and exposes
hasRunningEngine(), which the health endpoint consults so the banner
reflects machine-level truth. Reconciliation still retries so this
process takes over if the other exits, and the "refusing to start" log
fires once per project instead of on every 30s reconciliation tick.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:09:35 -07:00
gsxdsm
222e781dc0 Merge pull request #1702 from vamsi-ship-it/fix/anthropic-compatible-custom-provider-api-key
fix(engine): map anthropic-compatible custom providers to anthropic-messages api
2026-06-21 02:23:11 -07:00