Commit Graph

4036 Commits

Author SHA1 Message Date
gsxdsm
0e4c0c713e FN-8995: reconcile durable-write inventory drift
Keep the durable-write inventory synchronized while preserving reviewed lifecycle verdicts.

- Add fail-closed manifest regeneration and regression coverage.
- Reconcile current call-site structure while retaining equivalent verdicts through module moves.
- Clarify durable wedge-notification writer classification and regeneration guidance.

Files changed:
 .../merge-orphan-body-durable-write-fences.md      |    18 +-
 .../__tests__/_merge-durable-write-callsites.ts    |    84 +-
 .../merge-orphan-durable-write-inventory.json      | 15414 +++++++++----------
 ...ge-orphan-durable-write-inventory-drift.test.ts |    88 +-
 4 files changed, 7836 insertions(+), 7768 deletions(-)

Fusion-Task-Id: FN-8995
Fusion-Task-Lineage: df3d27ca-6614-418d-b09f-e1dd9f49f910
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 15:29:44 -07:00
gsxdsm
5134a55b77 FN-8958: fence orphaned merge-body writes
Prevent cancelled merge generations from writing stale task state.

- Add a signal-aware merge write fence with orphan audit reporting.
- Fence merge finalization, post-push metadata, and recovery-branch task logs.
- Cover durable write callsites and cancellation behavior with tests and guidance.

Files changed:
 .changeset/fn-8958-orphan-merge-write-fence.md     |   7 +
 AGENTS.md                                          |   1 +
 .../reliability/orphan-merge-body-write-fence.md   |  68 ++
 .../__tests__/_merge-durable-write-callsites.ts    |   4 +
 .../merge-orphan-durable-write-inventory.json      | 982 +++++++++++----------
 .../merge-orphan-body-durable-writes.test.ts       |  38 +-
 .../engine/src/__tests__/merge-write-fence.test.ts |  39 +
 .../engine/src/merge/auto-merge-finalization.ts    |   9 +
 packages/engine/src/merge/merge-write-fence.ts     |  92 ++
 packages/engine/src/merge/merger-ai.ts             | 173 ++--
 10 files changed, 875 insertions(+), 538 deletions(-)

Fusion-Task-Id: FN-8958
Fusion-Task-Lineage: 5f398c44-4320-4f0c-be15-707184f66aa8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 15:20:19 -07:00
gsxdsm
43141467fb FN-8955: harden reviewer verdict extraction
Recover structured reviewer verdicts from prose containing malformed brace or quote characters.

- Scan and recover JSON verdict candidates after parser desynchronization.
- Prevent unreadable structured verdicts from being treated as prose approvals.
- Cover malformed prose and multi-finding verdict recovery across review gates.

Files changed:
 .changeset/fn-8955-verdict-extractor.md            |  7 ++
 docs/workflow-steps.md                             |  4 +-
 packages/engine/src/__tests__/reviewer.test.ts     | 65 +++++++++++++++
 .../workflow-malformed-verdict-gate.test.ts        | 14 ++++
 .../workflow-step-verdict-parsing.test.ts          | 86 ++++++++++++++++++--
 packages/engine/src/execution/reviewer.ts          | 92 ++++++++++++++++++++--
 .../engine/src/executor/workflow-step-verdict.ts   | 16 ++--
 7 files changed, 267 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-8955

Fusion-Task-Lineage: 84107fd2-b7f3-4162-9e8c-2ec24600d9d5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 15:01:52 -07:00
gsxdsm
778292b484 refactor: package code organization wave 19 (self-healing pure peels) (#3403)
## Summary
Starts **U5** of the package code-organization program after wave 18
(executor peels) landed.

Peels pure free-function clusters out of `self-healing.ts` into
`packages/engine/src/self-healing/` without behavior changes. Public
imports from `./self-healing.js` remain stable via re-exports.

### Peels
| Symbol | New home |
|--------|----------|
| `autoRecoverWorktreeSessionStartFailure` |
`self-healing/auto-recover-worktree-session.ts` |
| `archiveAsGhostBug` | `self-healing/archive-ghost-bug.ts` |
| `hasStepProgress` / work-complete helpers |
`self-healing/step-progress.ts` |

### Line count
- `self-healing.ts`: ~15456 → ~15231 (baseline ratcheted to post-peel
live; main had already drifted past the prior grandfathered ceiling via
organic growth)
- New modules each well under 2,000 lines

## Test plan
- [x] `pnpm --filter @fusion/engine exec tsc --noEmit`
- [x] `self-healing-trait-rekey.test.ts` (autoRecover requeue)
- [x] `self-healing-paused-abort-recovery.test.ts`
- [x] `self-healing-model-unavailable-recovery.test.ts`
- [ ] CI gate

## Follow-ups
U5 Slice B: domain method clusters (startup, in-review, merge-status,
workspace, surfacing) into additional `self-healing/*.ts` modules.

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

* **Bug Fixes**
* Improved automatic recovery when worktree sessions fail to start,
including stale or incomplete session data.
* Tasks can be safely requeued while preserving progress, or escalated
after retry limits are reached.
* Improved handling of completed work and failures where task completion
was not recorded.
* Preserved valid task branches during recovery and provided more
reliable fallback requeue behavior.
* Ghost bugs are automatically archived with recovery details and
activity history.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-11 11:29:30 -10:00
gsxdsm
9622a62425 fix(engine): preserve manual handoff holds during recovery (#3422)
## Summary
Supersedes #3421 — fork head not writable for main-merge. Same change
rebased onto current main so lifecycle-column lint stays green.

## Test plan
- [x] merges cleanly onto main
- [ ] CI green

Co-authored-by: BESA-Franz <49682134+BESA-Franz@users.noreply.github.com>
2026-08-11 11:29:23 -10:00
Phil Larson
ca134c2554 test(engine): align failed notification fixture with recovery ownership (#3418)
## Summary
- make the already-merged recovery fixture explicit that no maintenance
sweep owns terminal-failure recovery
- preserve the fail-open `task-wedged` notification assertion when no
landed commit is found

## Test plan
- `corepack pnpm --filter @fusion/engine exec vitest run
--silent=passed-only --reporter=dot src/__tests__/self-healing.test.ts`
(460 passed)
- `corepack pnpm --filter @fusion/engine typecheck`
- `node scripts/run-static-gate-checks.mjs` (12 passed)
- `corepack pnpm --filter @fusion/engine test:core` (422 passed)
- `corepack pnpm --filter @fusion/core test:unit-gate` (184 passed)
- `corepack pnpm --filter @runfusion/fusion test:ci-shape` (71 passed)
- `corepack pnpm test:gate` reaches the PostgreSQL harness but cannot
authenticate locally (`empty password returned by client`) before
product assertions


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

* **Tests**
* Updated failure-notification test conditions to cover scenarios
without automatic maintenance processing.
* Added coverage confirming terminal-failure notifications fail open
when no maintenance sweep owns the task.
* Bypassed production debounce timing to make the test behavior
deterministic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-11 11:28:46 -10:00
gsxdsm
66c51038a5 fix(engine): bind self-owned worktree liveness probe (#3419)
## Summary
Supersedes #3416 — the fork head is not writable from maintainers, so
this branch carries the same fix merged onto current `main`.

## Changes
- Bind the self-owned worktree liveness probe in task-executor pure
facades (from #3416).
- Merge current main so the lifecycle-column census baseline stays
green.

## Test plan
- [x] `pnpm check:lifecycle-columns` clean after merge
- [ ] CI green

Closes context from #3416.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed cleanup for self-owned worktrees so it no longer crashes before
checking whether an active session is present.
* Improved safety during worktree reconciliation by correctly verifying
that the worktree is still active before removal.

* **Documentation**
  * Added a changeset documenting the worktree cleanup fix.

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

Co-authored-by: BESA-Franz <49682134+BESA-Franz@users.noreply.github.com>
2026-08-11 11:28:42 -10:00
gsxdsm
a6ce7f89ef FN-8987: expose release-gate verdicts for Promote visibility
Expose server-evaluated release-gate state so Promote controls accurately reflect approval readiness.

- Attach transient release-gate verdicts to task API responses.
- Preserve only fresh REST verdicts across task snapshots and render them in task cards.
- Align hold-release gating and document the Promote-state contract.

Files changed:
 .changeset/fn-8987-release-gate-verdict.md         |   7 +
 docs/dashboard-guide.md                            |   4 +
 docs/solutions/workflow-learnings/project-union-versus-per-task-lanes.md |   1 +
 docs/workflow-steps.md                             |   4 +
 packages/core/src/index.gate.ts                    |   2 +-
 packages/core/src/index.ts                         |   2 +-
 packages/core/src/types.ts                         |   2 +
 packages/core/src/types/task/task-core.ts          |  20 +++
 packages/dashboard/app/components/TaskCard.tsx     |   3 +-
 packages/dashboard/app/components/__tests__/TaskCard.test.tsx |  31 ++++
 packages/dashboard/app/hooks/__tests__/useTasks.test.ts |  26 ++++
 packages/dashboard/app/hooks/useTasks.ts           | 135 +++++++++++++++--
 packages/dashboard/app/utils/__tests__/releaseGate.contract.test.ts |  29 ++++
 packages/dashboard/app/utils/__tests__/releaseGate.test.ts |  49 ++++++
 packages/dashboard/app/utils/releaseGate.ts        |  26 ++++
 packages/dashboard/app/utils/reviewBudgetApproval.ts |   9 ++
 packages/dashboard/src/routes/register-task-workflow-routes.ts |  20 ++-
 packages/engine/src/__tests__/release-gate-verdict.test.ts |  40 +++++
 packages/engine/src/execution/hold-release.ts      | 166 +++++++++------------
 packages/engine/src/index.ts                       |   3 +
 20 files changed, 469 insertions(+), 110 deletions(-)

Fusion-Task-Id: FN-8987

Fusion-Task-Lineage: 6f1742bc-2b2b-4a32-9be5-92160335d90d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 14:22:14 -07:00
Phil Larson
6cc15fd73d fix(ci): restore clean-main CLI and lifecycle gates (#3420)
## Summary
- Complete the isolated `@fusion/core` mock used by the
experiment-finalize extension suite
- Classify three intentional physical/synthetic lifecycle literals
introduced on current main
- Re-record the strict lifecycle census baseline with zero unexamined
guards

## Test plan
- `pnpm --filter @runfusion/fusion exec vitest run
src/__tests__/extension-experiment-finalize.test.ts --silent=passed-only
--reporter=dot`
- `pnpm --filter @fusion/core exec vitest run
src/__tests__/task-intake-owner-resolver.test.ts --silent=passed-only
--reporter=dot`
- `pnpm --filter @fusion/engine exec vitest run --project engine-default
src/__tests__/mission-feature-sync-lanes.test.ts --silent=passed-only
--reporter=dot`
- `pnpm check:lifecycle-columns`
- `node scripts/check-mock-completeness.mjs`


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

- **Bug Fixes**
- Improved mission reconciliation previews for task links, specification
alignment, and lifecycle updates.
- Prevented stale or superseded validation runs from overwriting current
feature status or ownership.
- Improved blocked-feature diagnostics and archived-task handling across
workflow configurations.

- **Documentation**
- Clarified validation, assignment checks, and mission synchronization
behavior.

- **Tests**
- Expanded coverage for reconciliation previews and validator ownership
scenarios.

- **Chores**
  - Updated lifecycle baseline data for known archived-task cases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-11 10:57:36 -10:00
gsxdsm
9f24a517cf FN-8956: track resolved review findings
Add durable, scoped resolution states for workflow review findings.

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

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

Fusion-Task-Id: FN-8956

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

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 13:34:27 -07:00
gsxdsm
6ae9299576 FN-8953: defer terminal wedge alerts during recovery
Hold terminal wedge alerts until their recovery window has elapsed.

- Persist and settle pending wedge notifications across restarts.
- Clear pending alerts on task progress and reconcile expired holds during self-healing.
- Expose the settle window in notification settings with coverage for store and notification flows.

Files changed:
 .changeset/fn-8953-wedge-settle-window.md          |   7 +
 AGENTS.md                                          |   1 +
 docs/architecture.md                               |   3 +-
 docs/settings-reference.md                         |   1 +
 .../core/src/__tests__/store-wedge-pending.test.ts |  56 +++++
 packages/core/src/config/settings-schema.ts        |   1 +
 packages/core/src/store.ts                         |  46 ++++
 packages/core/src/types/settings/settings-scope.ts |   2 +
 packages/core/src/types/task/task-core.ts          |  15 ++
 .../app/components/settings/save-split.ts          |   1 +
 .../sections/NotificationsSection.search.ts        |   9 +
 .../settings/sections/NotificationsSection.tsx     |  15 ++
 .../settings-default-descriptions.test.tsx         |   1 +
 ...self-healing-pending-wedge-notification.test.ts | 148 ++++++++++++
 .../__tests__/notification-service.test.ts         |   7 +-
 .../__tests__/task-wedge-notification.test.ts      | 258 ++++++++++++++++++++-
 .../src/notification/notification-service.ts       | 260 +++++++++++++++++++++
 packages/engine/src/self-healing.ts                |  38 +++
 packages/i18n/locales/en/app.json                  |   2 +
 19 files changed, 850 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-8953

Fusion-Task-Lineage: fd5b5827-c69d-409f-86d5-01ff23405ee3

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 12:34:47 -07:00
gsxdsm
dfd88e7540 fix: resume capacity-parked workflow continuations
The planning-continuation drain skipped every due `kind: "task"` row whose
`waitReason` was not "planning", on the premise that such rows "belong to a
different drain". No such drain exists: `listDueWorkflowWorkItems` has exactly
two callers, this pass and the self-healing reclaim sweep, and the sweep
deliberately leaves `runnable`/`retrying` rows alone as "the dispatcher's own
queue". A capacity-parked continuation was therefore owned by nobody — skipped
here every poll with no state change and no audit row, and passed over there by
design.

Observed on the Fusion board: eight cards sat runnable for up to 8h with the
engine unpaused, 0 tasks in progress, and 4 of 10 worktrees used. Three carried
`waitReason: "capacity"` from the capacity-suspend path; five carried NULL. The
09:04 reclaim sweep had just moved them held -> runnable, handing them to this
drain and simultaneously putting them out of its own reach, so the auto-resume
fix tightened the strand it repaired.

Dispatch stays admission-gated by `admitPlanningContinuation`, so a
capacity-parked card resumes only when a slot is genuinely free.

Also repairs two stale path allowlists in planning-claim-single-writer.ts: the
mission stores and replan-target.ts moved into subdirectories, leaving that
ratchet red on main and accusing the two modules it exists to exclude.

Verified: the patched classifier returns `actionable` for all 8 live stranded
rows; gate + lint green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 10:36:26 -07:00
gsxdsm
eef68fe0b9 FN-8933: capture semantic memory from completed work
Add inferred graph relationships and detached recall capture across completed-work memory surfaces.

- Validate and persist deterministic inferred semantic edges with audit outcomes.
- Capture completed tasks, research findings, and insights as bounded recall entries.
- Wire memory semantics through engine, research APIs, and coverage tests.

Files changed:
 .changeset/fn-8933-memory-semantics-capture.md     |   7 +
 AGENTS.md                                          |   1 +
 docs/knowledge-graph.md                            |  10 +-
 .../src/__tests__/memory/recall-capture.test.ts    | 111 +++++++++++++
 .../__tests__/postgres/insight-store.pg.test.ts    |  25 +++
 .../postgres/research-execution.pg.test.ts         |  38 +++++
 .../__tests__/research-feature-promotion.test.ts   |  39 +++++
 .../core/src/async-stores/async-insight-store.ts   |  23 ++-
 packages/core/src/index.ts                         |   1 +
 .../__tests__/graph-builder-incremental.test.ts    |  28 ++++
 .../__tests__/inferred-edge-writer.test.ts         |  74 +++++++++
 packages/core/src/knowledge-graph/graph-builder.ts |  27 ++-
 .../src/knowledge-graph/graph-serialization.ts     |   2 +-
 packages/core/src/knowledge-graph/graph-store.ts   |  12 ++
 packages/core/src/knowledge-graph/graph-types.ts   |   2 +-
 packages/core/src/knowledge-graph/index.ts         |   1 +
 .../src/knowledge-graph/inferred-edge-writer.ts    |  96 +++++++++++
 packages/core/src/memory/index.ts                  |   1 +
 packages/core/src/memory/recall-capture.ts         | 184 +++++++++++++++++++++
 .../src/research/research-feature-promotion.ts     |  23 ++-
 packages/core/src/task-store/task-store-helpers.ts |  13 +-
 .../src/__tests__/research-routes.test.ts          |  80 ++++++++-
 packages/dashboard/src/research-routes.ts          |  27 ++-
 .../src/__tests__/agent-mission-tools.test.ts      |  60 ++++++-
 .../src/__tests__/in-process-runtime.pg.test.ts    |  28 +++-
 .../memory-consolidation-heartbeat-hook.test.ts    |   8 +-
 .../__tests__/memory-consolidation-ports.test.ts   |  17 +-
 .../src/__tests__/memory-semantics-pass.test.ts    | 115 +++++++++++++
 .../engine/src/__tests__/project-engine.test.ts    |  65 +++++++-
 packages/engine/src/agent-heartbeat.ts             |  14 +-
 packages/engine/src/agent-tools.ts                 |  12 +-
 packages/engine/src/agents/agent-reflection.ts     |   9 +-
 packages/engine/src/memory/index.ts                |   1 +
 .../src/memory/memory-consolidation-adapters.ts    |  18 +-
 packages/engine/src/memory/memory-consolidation.ts |  13 +-
 packages/engine/src/memory/memory-semantics.ts     |  67 ++++++++
 packages/engine/src/project-engine.ts              |   3 +
 .../engine/src/research/research-orchestrator.ts   |  20 ++-
 packages/engine/src/runtimes/in-process-runtime.ts |  12 ++
 packages/engine/src/util/run-audit.ts              |  11 ++
 40 files changed, 1250 insertions(+), 48 deletions(-)

Fusion-Task-Id: FN-8933

Fusion-Task-Lineage: b75a6b23-906f-4255-92f1-7684beb742b8

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

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

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

Fusion-Task-Id: FN-8934

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

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 04:57:14 -07:00
gsxdsm
637854ad36 FN-8932: add durable memory consolidation agent
Add a provisioned memory agent that consolidates durable recall material through idempotent heartbeat ticks.

- Provision and configure the durable memory agent with an enabled workflow setting.
- Add consolidation adapters, material collection, recall graph references, and run-audit metadata.
- Expose the setting in the dashboard and document the memory-agent behavior.
- Cover provisioning, heartbeat, consolidation, audit, and recall graph behavior with tests.

Files changed:
 .changeset/fn-8932-memory-agent.md                 |   7 ++
 AGENTS.md                                          |   1 +
 docs/agents.md                                     |  10 ++
 docs/settings-reference.md                         |   1 +
 docs/storage.md                                    |   2 +-
 .../memoryConsolidationEnabled-default.test.ts     |  22 ++++
 .../memory-recall-graph-cross-reference.pg.test.ts | 115 +++++++++++++++++++++
 .../__tests__/memory-agent-provisioning.test.ts    |  31 ++++++
 packages/core/src/agents/agent-store.ts            |  85 +++++++++++++++
 packages/core/src/agents/memory-agent-defaults.ts  |  30 ++++++
 packages/core/src/index.gate.ts                    |   2 +
 packages/core/src/index.ts                         |   9 ++
 packages/core/src/memory/recall/index.ts           |   1 +
 packages/core/src/memory/recall/recall-dedup.ts    |   3 +
 packages/core/src/memory/recall/recall-store.ts    |  35 ++++++-
 .../src/workflows/builtin-workflow-settings.ts     |  14 +++
 .../src/workflows/workflow-settings-resolver.ts    |  12 ++-
 .../__tests__/WorkflowSettingsPanel.test.tsx       |   8 ++
 .../__tests__/workflow-setting-display.test.ts     |   6 ++
 .../app/components/workflow-setting-display.ts     |   5 +
 .../memory-consolidation-heartbeat-hook.test.ts    |  92 +++++++++++++++++
 .../__tests__/memory-consolidation-ports.test.ts   |  34 ++++++
 ...memory-consolidation-run-audit-metadata.test.ts |  19 ++++
 .../__tests__/memory-consolidation-tick.test.ts    |  62 +++++++++++
 packages/engine/src/agent-heartbeat.ts             |  55 ++++++++++
 packages/engine/src/index.ts                       |   1 +
 packages/engine/src/memory/index.ts                |   3 +
 .../src/memory/memory-consolidation-adapters.ts    |  29 ++++++
 .../src/memory/memory-consolidation-material.ts    |  22 ++++
 packages/engine/src/memory/memory-consolidation.ts |  41 ++++++++
 packages/engine/src/util/run-audit.ts              |  10 ++
 31 files changed, 764 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-8932

Fusion-Task-Lineage: b4fdec50-1f42-4120-af17-0b6f3a94586e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 03:53:11 -07:00
gsxdsm
cb4d94104a docs(engine): correct the prune-before-remove rationale
The comment cited 89 registered worktrees against 20 on disk as evidence of stale
registrations. That comparison was against .worktrees/ alone; all 89 registrations
exist, spread across kb-worktrees, orca workspaces and .claude/worktrees. Prune
still belongs before removal on ordering grounds -- a dangling registration fails
the removal, and the throw skips the trailing prune so the retry never clears it --
but the false measurement should not stand as the justification.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 02:49:01 -07:00
gsxdsm
2b228383d5 test: cover model-target chat creation and non-conflict cleanup failures
Both suites are mutation-verified: reverting the corresponding fix fails 4 of the
chat tests and exactly the 3 new self-healing park tests.

The self-healing tests carry a positive control asserting the sweep actually
reached the tip-already-merged arm -- without it the park assertions passed
vacuously against a task shape the candidate filter rejected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 02:47:24 -07:00
gsxdsm
fd68bb1bea fix: model-target chats 404, and worktree rmdir races misreported as branch conflicts
Two unrelated production failures with a shared symptom of an opaque error.

Chat: FN-8869 hoisted the agent-existence check out of its else branch, so it ran
even when the client supplied an explicit model pair. Model-target chats send the
client-only sentinel `__fn_agent__`, which is never an agent row, so every one of
them 404'd behind the generic "Failed to create chat session" toast. The agent is
now required only when it is the source of model resolution.

Self-healing: a failed `tip-already-merged` cleanup was rethrown and classified
`branch-conflict-unrecoverable`, failing and pausing tasks whose branch was already
an ancestor of the integration ref. Every one of the 78 logged parks carried a
`git worktree remove --force` / `ENOTEMPTY rmdir node_modules` message -- a pnpm
race, not a conflict. Cleanup failure now retries on the next sweep, and prune runs
before removal so a stale registration stops causing the failure it would prevent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 02:39:56 -07:00
gsxdsm
06ea444339 fix: uncap workflow principals and auto-resume stranded continuations
Two independent wedges kept cards silently stuck on the board.

1. Workflow principals were capped. `WorkflowAgentCapacity.acquire` enforced
   `settings.maxConcurrent` as a project session budget plus an optional
   per-agent `maxWorkflowSessions`, and `routeWorkflowPrincipal`'s availability
   test applied the same per-agent ceiling. The workflow roles stand in for
   STAGES, not workers, and there is typically one agent per role - so the cap
   serialized the entire board behind a single Workflow Executor regardless of
   maxConcurrent/maxWorktrees. Admission now always succeeds; the lease survives
   as bookkeeping (it is what activeSessions counts and what the renewal timer
   keeps warm). `maxProjectSessions` is removed from the input rather than
   defaulted, so it cannot be reintroduced without deleting the contract, and
   the agent-capacity re-route loops in triage and graph admission are deleted
   with the refusal they existed to work around.

2. Continuations that stop in `running` or `held` were never re-polled. The
   scheduler's due-poll takes only `runnable`/`retrying`; a row claimed through
   a path that leaves `leaseExpiresAt` NULL keeps `state: "running"` forever
   after its process dies, and `acquireWorkflowWorkItemLease` can only re-take a
   `held` row whose blockedReason matches workflow-principal-%. Observed live:
   seven cards `running` behind leases from a process that exited ~9h earlier,
   two `held` with a NULL blockedReason for 46h, none emitting a single
   run-audit row while stranded. A further 33 active-state rows belonged to
   archived+soft-deleted tasks (the FK cascade only fires on hard delete).

   New sweep `reconcileStrandedWorkflowContinuations` (startup + periodic)
   re-queues both stranded shapes and retires dead tasks' rows, gated by the
   canonical liveness triple, a 10-minute grace matching the capacity lease
   duration, and a compare-and-set on the scanned state so a real claim wins.
   The decision is the pure `evaluateStrandedContinuationReclaim`, shared with
   its tests so coverage cannot drift from behavior - the drift that let the
   FN-8923 sweep ship covering one ninth of this problem.

Verified: pnpm lint, engine typecheck, pnpm test:gate (606 tests), verify:fast,
and the new suite under mutation (removing either guard fails 3 cases). The two
pre-existing failures in self-healing-orphaned-pending-step-results.test.ts
reproduce identically at HEAD without these changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 02:02:51 -07:00
gsxdsm
8f6190910d FN-8971: add mission blocked-status clearing tool
Add an operator-only CLI tool for repairing stale mission blocked badges.

- Register and document fn_mission_clear_blocked with PostgreSQL and status-error handling.
- Withhold the repair action from agent principals and deny it in readonly workflow steps.
- Classify the tool consistently across engine permission gates and add coverage.
- Add a minor CLI changeset for the new operator capability.

Files changed:
 .changeset/fn-8971-mission-clear-blocked-tool.md   |  7 +++
 docs/missions.md                                   |  7 ++-
 packages/cli/skill/fusion/SKILL.md                 |  2 +-
 .../cli/skill/fusion/references/extension-tools.md |  9 ++++
 .../skill/fusion/references/fusion-capabilities.md |  1 +
 .../__tests__/extension-permission-gates.test.ts   | 26 ++++++++++
 packages/cli/src/__tests__/extension.test.ts       | 56 +++++++++++++++++++++-
 packages/cli/src/extension.ts                      | 54 +++++++++++++++++++++
 .../src/__tests__/agent-mission-tools.test.ts      |  5 +-
 .../src/__tests__/gating-classifications.test.ts   |  8 ++++
 .../workflow-step-readonly-allowlist.test.ts       |  5 +-
 .../engine/src/execution/gating-classifications.ts |  7 +++
 12 files changed, 182 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-8971

Fusion-Task-Lineage: 650c13b3-c6c4-4dc5-a0b5-9c71d3b94fc5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 01:45:08 -07:00
gsxdsm
844512ed3e FN-8976: prevent concurrent automatic validator runs
Prevent automatic validation from running alongside a fresh manual or non-memoized validator.

- Serialize validator admission around a feature-scoped fresh-running check.

- Report feature-versus-fingerprint blocking scope and preserve memoization semantics.

- Add regression coverage, documentation, and a patch changeset.

Files changed:

 .changeset/fn-8976-validator-admission.md          |   7 ++
 docs/missions.md                                   |   4 +-
 .../__tests__/postgres/mission-store.pg.test.ts    | 110 +++++++++++++++++++--
 .../core/src/async-stores/async-mission-store.ts   |  61 ++++++++++--
 packages/core/src/missions/mission-types.ts        |   2 +
 .../src/__tests__/mission-execution-loop.test.ts   |  10 +-
 6 files changed, 171 insertions(+), 23 deletions(-)

Fusion-Task-Id: FN-8976
Fusion-Task-Lineage: 61b487e8-5542-4cce-94f7-58d5295fe177
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 22:57:21 -07:00
gsxdsm
90573e31b0 FN-8963: prevent concurrent mission validation runs
Prevent duplicate manual validation runs while preserving recovery from stale validator state.

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

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

Fusion-Task-Id: FN-8963
Fusion-Task-Lineage: 7e5d0ae4-98ac-4f79-99ca-45fd1450362d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 21:41:47 -07:00
gsxdsm
cef07527f6 FN-8948: reconcile mission state from task ground truth
Centralize mission and feature state repair around deterministic task lifecycle evidence.

- Add a reusable mission reconciliation authority with task-move, API, tool, and maintenance callers.
- Repair unambiguous title links while preserving terminal, validation, and audit safeguards.
- Route scheduler moves through the authority and reject duplicate feature-title ownership.
- Expose reconcile controls and document the operator workflow.

Files changed:
 .changeset/fn-8948-mission-auto-reconcile.md       |   7 +
 AGENTS.md                                          |   1 +
 docs/missions.md                                   |   8 +-
 packages/cli/skill/fusion/SKILL.md                 |   2 +-
 .../cli/skill/fusion/references/extension-tools.md |   9 +
 .../skill/fusion/references/fusion-capabilities.md |   1 +
 .../extension-experiment-finalize.test.ts          |   2 +
 .../__tests__/extension-gitlab-tracking.test.ts    |   2 +
 .../cli/src/__tests__/extension-web-fetch.test.ts  |   2 +
 packages/cli/src/extension.ts                      |  14 +
 packages/dashboard/src/mission-routes.ts           |  24 +-
 .../src/__tests__/agent-mission-tools.test.ts      |   2 +-
 .../engine/src/__tests__/mission-autopilot.test.ts |   8 +-
 .../src/__tests__/mission-state-reconcile.test.ts  |  67 +++++
 packages/engine/src/agent-tools.ts                 |   6 +
 .../engine/src/execution/gating-classifications.ts |   1 +
 packages/engine/src/index.ts                       |   6 +
 packages/engine/src/missions/index.ts              |   8 +-
 packages/engine/src/missions/mission-autopilot.ts  | 106 +------
 .../engine/src/missions/mission-feature-sync.ts    |   1 +
 .../engine/src/missions/mission-state-reconcile.ts | 169 +++++++++++
 packages/engine/src/runtimes/in-process-runtime.ts |   4 +-
 packages/engine/src/scheduler.ts                   | 331 +++++----------------
 packages/engine/src/util/run-audit.ts              |   2 +
 24 files changed, 426 insertions(+), 357 deletions(-)

Fusion-Task-Id: FN-8948
Fusion-Task-Lineage: 0fbccef3-eeac-46d2-b3d8-aca679b3657e
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 20:32:26 -07:00
gsxdsm
b82f1a41f3 FN-8947: add repairable mission validation controls
Add repairable mission-validation badges with clear and re-run flows.

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

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

Fusion-Task-Id: FN-8947

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

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 19:36:31 -07:00
ischindl
f775039f5b feat(engine): add typed delivery-pipeline run-audit catalogue (#3410)
## What
Adds a typed, queryable catalogue for engine run-audit events as the
first step of the delivery-pipeline reliability & observability effort.

- **New module** `packages/engine/src/run-audit/run-audit-catalogue.ts`
— a typed registry describing run-audit event kinds (scheduler,
self-healing, merger, worktree, symbol-lock, …) so pipeline
observability can ingest and reason about them consistently.
- **Parity test** `run-audit-catalogue.test.ts` — asserts the catalogue
matches the emitted run-audit event space.
- **Docs** `docs/run-audit.md` + index pointer.

## Why
Run-audit events are currently emitted ad-hoc without a typed contract.
A catalogue gives:
- a single source of truth for event kinds/names,
- a parity guard so any new or renamed event is caught,
- a foundation for delivery-pipeline reliability dashboards.

## Verification
- `@fusion/engine` `tsc` build → **PASS**
- `vitest run run-audit-catalogue.test.ts` → **3 tests passed**
- No production behavior change outside the new module.

## Scope
New isolated module + its test + docs. No changesets/release artifacts.

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

* **Documentation**
* Added a run-audit catalogue covering delivery-pipeline finalization,
self-healing reconciliation, and durable-agent error events.
* Documented recorded outcomes, emission conditions, audit-store
querying, and event catalogue maintenance.
  * Added a documentation index entry linking to the new catalogue.
* **Tests**
* Added validation to ensure documented audit events remain complete,
consistently formatted, and synchronized with the supported event
catalogue.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Fusion <noreply@runfusion.ai>
2026-08-10 15:19:43 -10:00
gsxdsm
8c055a6695 fix: keep self-healing sweeps alive across stale task links (#3417)
## Summary
Supersedes #3405 — the fork head is not writable from maintainers, so
this branch carries the same fix rebased/merged onto current `main`.

## Conflict resolution
- Main already landed the equivalent fail-open path as **FN-8919**
(`readLinkedTaskOrUndefined` + per-agent try/catch).
- Kept the additional `recoverAgentsRunningOnInactiveTasks` regression
that covers task-gone races plus transient lookup isolation.
- Dropped the duplicate changeset (main already has
`fn-8919-agent-link-sweep-fail-open`).

## Test plan
- [x] `git merge-tree` clean against `main`
- [ ] CI green

Closes context from #3405.

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

## Summary by CodeRabbit

* **Bug Fixes**
  * Improved recovery handling when task lookups fail.
* Agents linked to deleted or missing tasks are now unlinked, while
agents affected by temporary errors remain preserved.
* Recovery continues for other eligible agents instead of stopping after
an individual lookup failure.

* **Tests**
* Added regression coverage for deleted, missing, and temporarily
unavailable tasks.

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

Co-authored-by: Codex <codex@openai.com>
2026-08-10 15:19:08 -10:00
gsxdsm
d749a11a5b FN-8923: document orphan merge durable-write fences
Record the bounded cancellation frontier for orphaned AI merge bodies.

- Add AST-derived durable-writer inventory and drift guard for the pinned merge closure.
- Characterize orphan and successor merge-lane writes with production-path fixtures.
- Document unresolved follow-ups and link the fence from the architecture guide.

Files changed:
 docs/architecture.md                               |    2 +-
 .../merge-orphan-body-durable-write-fences.md      |   92 +
 .../__tests__/_merge-durable-write-callsites.ts    |  938 ++
 .../merge-orphan-durable-write-inventory.json      | 9965 ++++++++++++++++++++
 .../merge-orphan-body-durable-writes.test.ts       |  348 +
 ...ge-orphan-durable-write-inventory-drift.test.ts |   56 +
 packages/engine/src/merge/merger-ai.ts             |    6 +
 packages/engine/src/project-engine.ts              |    6 +
 8 files changed, 11412 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8923

Fusion-Task-Lineage: 5b2d278c-1626-439a-affd-077f2de2aef1

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 17:55:46 -07:00
gsxdsm
a839c61929 FN-8926: expose graph and recall through MCP
Expose Fusion knowledge graph and durable recall through a built-in MCP transport.

- Add the reserved fusion-memory server with graph and recall MCP tools.
- Resolve built-in availability and enable/disable tombstones across configuration and UI.
- Add CLI transport, documentation, release metadata, and lane coverage tests.

Files changed:
 .changeset/fn-8926-memory-mcp-server.md            |   7 +
 docs/cli-reference.md                              |   4 +
 docs/mcp.md                                        |  10 ++
 packages/cli/src/bin.ts                            |   6 +
 .../__tests__/mcp-memory-server-spawn.test.ts      |  79 ++++++++++
 .../commands/__tests__/mcp-memory-server.test.ts   |  83 +++++++++++
 packages/cli/src/commands/__tests__/mcp.test.ts    |  27 +++-
 packages/cli/src/commands/mcp-memory-server.ts     | 104 +++++++++++++
 packages/cli/src/commands/mcp.ts                   |  64 ++++++--
 packages/core/package.json                         |  10 ++
 .../core/src/__tests__/mcp-builtin-servers.test.ts |  17 +++
 packages/core/src/__tests__/mcp-config.test.ts     |  12 ++
 packages/core/src/config/mcp-builtin-descriptor.ts |  16 ++
 packages/core/src/config/mcp-builtin-servers.ts    |  18 +++
 packages/core/src/config/mcp-config.ts             |  40 +++--
 packages/core/src/config/mcp-discovery.ts          |   3 +-
 packages/core/src/index.ts                         |   6 +
 packages/core/src/memory/index.ts                  |   1 +
 .../mcp/__tests__/memory-mcp-handler.test.ts       |  36 +++++
 .../mcp/__tests__/memory-mcp-serialization.test.ts |  23 +++
 packages/core/src/memory/mcp/index.ts              |   4 +
 .../core/src/memory/mcp/memory-mcp-backends.ts     |  39 +++++
 packages/core/src/memory/mcp/memory-mcp-handler.ts |  54 +++++++
 .../src/memory/mcp/memory-mcp-serialization.ts     |  48 ++++++
 packages/core/src/memory/mcp/memory-mcp-tools.ts   |  64 ++++++++
 packages/core/src/types.ts                         |  10 ++
 .../settings/sections/GlobalMcpSection.tsx         |  14 +-
 .../settings/sections/McpServersCard.tsx           |  67 +++++++--
 .../settings/sections/ProjectMcpSection.tsx        |  15 +-
 .../__tests__/McpServersCard.builtin.test.tsx      |  45 ++++++
 .../dashboard/src/__tests__/chat-manager.test.ts   |  24 +++
 .../register-config-mcp-pi-settings-routes.ts      |  20 ++-
 packages/dashboard/vitest.config.ts                |   2 +
 .../__tests__/mcp-builtin-lane-coverage.test.ts    | 163 +++++++++++++++++++++
 packages/engine/src/mcp/mcp-resolution.ts          |  10 +-
 packages/engine/vitest.config.ts                   |   2 +
 36 files changed, 1097 insertions(+), 50 deletions(-)

Fusion-Task-Id: FN-8926
Fusion-Task-Lineage: b2861491-33da-4b05-b9f8-a7c1448c1c8c
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 17:50:27 -07:00
gsxdsm
3143f9536f FN-8908: auto-recover terminal task failures
Recover generic terminal task failures through a bounded, durable retry budget before escalating them to operators.

- add fenced task-store recovery claims, retries, budget resets, and audit events
- defer terminal-failure notifications until recovery is exhausted while preserving a single escalation
- expose operator retry budget reset and cover recovery lifecycle behavior

Files changed:
 .../fn-8908-terminal-failure-auto-recovery.md      |   7 +
 AGENTS.md                                          |   1 +
 docs/agents.md                                     |   2 +
 docs/architecture.md                               |   2 +
 packages/cli/src/commands/task.ts                  |   2 +
 packages/cli/src/extension.ts                      |   2 +
 ...terminal-failure-auto-recovery-store.pg.test.ts | 108 +++++++++
 .../terminal-failure-auto-recovery.test.ts         |  60 +++++
 packages/core/src/index.gate.ts                    |   1 +
 packages/core/src/index.ts                         |   1 +
 packages/core/src/store.ts                         | 179 ++++++++++++++-
 .../core/src/task-store/archive-lifecycle-2.ts     |  15 ++
 packages/core/src/task-store/moves.ts              |  48 +++-
 packages/core/src/task-store/persistence.ts        |  18 +-
 packages/core/src/task-store/project-store-ops.ts  |   4 +-
 .../src/task-store/workflow-task-create-ops.ts     |   4 +-
 packages/core/src/tasks/index.ts                   |   1 +
 .../src/tasks/terminal-failure-auto-recovery.ts    | 114 ++++++++++
 packages/core/src/types/task/task-core.ts          |  24 ++
 .../src/routes/register-task-workflow-routes.ts    |   2 +
 ...-healing-terminal-failure-auto-recovery.test.ts | 199 ++++++++++++++++
 .../__tests__/notification-service.test.ts         |  86 ++++++-
 .../__tests__/task-wedge-notification.test.ts      |   2 +-
 .../src/notification/notification-service.ts       | 103 +++++++--
 .../src/notification/task-wedge-notification.ts    |  30 ++-
 packages/engine/src/self-healing.ts                | 251 ++++++++++++++++++++-
 packages/engine/src/util/run-audit.ts              |   7 +
 27 files changed, 1240 insertions(+), 33 deletions(-)

Fusion-Task-Id: FN-8908

Fusion-Task-Lineage: 99e96b16-0306-41f1-87da-8623d69735f7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 16:53:51 -07:00
gsxdsm
55fd20e5f8 fix(engine): bound spec-drift reconciliation so boot cannot exhaust the connection pool
Fusion wedged on "starting" and never brought the engine up. The dashboard bound
the migration holding server on 4040, then every query behind it failed with
"sorry, too many clients already", so the card never progressed and the
supervisor crash-looped.

Root cause: each spec-drift reconcile costs a DEDICATED PostgreSQL connection.
persist -> appendSpecDriftReport -> withPlanningLifecycleLock opens its own
postgres(directUrl, { max: 1 }) session, because the planning advisory lock is
session-scoped and deliberately fences a stale report against a newer plan.

enqueue() released every id straight into its own microtask, and project-engine
enqueues every task at runtime-boundary setup (listTasks includeArchived). On a
1,082-task project that opened ~1,082 lock sessions simultaneously against
max_connections = 500. The cluster saturated ~25s into boot and stayed saturated.

The flat 1s retry then made it self-sustaining rather than transient: once
saturated, every task failed for the same shared reason and re-armed in lockstep
once per second, re-opening the whole fleet of sessions and pinning the very
resource it was waiting on. Measured 4,777 lock sessions in 17 seconds.

Fix, contained to the reconciler — the advisory lock and its fencing semantics
are load-bearing and unchanged:
- concurrency bound (maxConcurrent, default 4) drained by a fair
  insertion-ordered pump, so fan-out can no longer exceed a known connection cost
- per-task in-flight dedupe; two passes on one task would contend on that task's
  own advisory lock while holding two connections
- exponential backoff with jitter capped at 60s, and retries re-enter through
  enqueue so a retry storm is bounded by the same limit as a first pass

Verified against the real 1,082-task project: connections stay flat at 3-10
across a 70s boot that previously reached 1,109 and saturated, and the engine
boots through to executing tasks and shuts down cleanly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 16:44:19 -07:00
gsxdsm
7b3bd75268 fix(engine): wire the Plan Review replan cap and tombstone its dead predecessor
Investigating the "dead cap" turned up the opposite of what it looked like, plus a
worse problem next to it.

The Plan Review replan loop was NOT unbounded. U3 re-owned the cap-park in the
graph: requestPreMergeOptionalStepFix parks via parkPlanReviewReplanCapExhausted
at awaiting-approval with reason plan-review-replan-cap, on both an explicit
finite budget and the unbounded default. That capability has been live throughout.

What was actually dead:

1. PLAN_REVIEW_GATE_REPLAN_CAP = 8 — an unread constant belonging to the
out-of-graph triage gate (runPlanReviewBeforeExecution) that U10/R4 deleted. Its
companion column Task.planReviewReplanCount was persisted, serialized and reset
but never incremented or compared. A constant and a column that look like a live
safety ceiling while enforcing nothing are worse than no ceiling: they answer "is
this loop bounded?" with a confident yes. Deleted, ratcheted in
legacy-tombstones.test.ts, and the column documented as legacy/never-written with
the live owner named.

2. planReviewReplanCap — an operator-facing setting, declared, validated,
documented in settings-reference.md and editable in the Workflow Editor, that
NOTHING read. Lowering it changed nothing. The unbounded backstop was instead
hardcoded to PLAN_REVIEW_FEEDBACK_HISTORY_LIMIT — a bound on how much reviewer
PROSE is replayed into the next planning prompt, whose own comment says it is
"bounded independently of persistence and retry accounting". Two unrelated
concerns shared one number, so trimming prompt history would have silently
tightened a safety ceiling.

The backstop now resolves from the setting, defaulting to the new
DEFAULT_PLAN_REVIEW_REPLAN_CAP = 15 — the previously-effective value, so this is a
pure re-wiring rather than a silent behavior change. The existing 15-attempt
regression test passes unchanged, which is the evidence for that. 0 is honored as
park-on-first-REVISE. An explicit planReviewMaxRevisions / node maxRevisions
budget remains a stricter, earlier gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:39:55 -07:00
gsxdsm
c05d44d44a fix(engine): bound planning retries and cap the planning turn
Three changes to the triage planning path.

1. Unclassified planning failures are bounded. specifyTask's catch-all branch —
the one reached by every error the classifiers above do not recognize — restored
the card's claimable status and wrote nothing else: no counter, no
nextRecoveryAt, no park. Triage rediscovery re-admitted the card on the very next
poll, and replaceActiveTaskWorkflowContinuation replaced the terminal work item
with a fresh one carrying no attempt count, so nothing recorded that the task had
already failed N times. It now consumes the same recoveryRetryCount/nextRecoveryAt
budget the transient branch uses (MAX_RECOVERY_RETRIES = 3, 60s/120s/300s jittered
backoff) and parks status:"failed" with a PLANNING_FAILED_EXHAUSTED: error once
spent — status:"failed" is what suppresses rediscovery. Classifying one error
string fixes one symptom; this budget is what makes the NEXT unrecognized error
fail safely instead of looping for a day.

2. The planning turn has a ceiling. Fusion set no timeout on it at all:
workflowStepTimeoutMs covers pre-merge workflow steps only, and the provider SDK's
300s APIConnectionTimeoutError caps time-to-first-byte and is cleared once headers
arrive, after which the stream is uncapped. configureHttpDispatcher, which would
install undici idle timeouts, is only called from pi's CLI entrypoints and never
in the in-process engine. Observed consequence: single attempts ran to 126 minutes,
with failed-attempt durations spread smoothly from 1 to 126 min and no clustering —
the signature of nothing enforcing a bound. New workflow-native planningTimeoutMs
(default 90 min) aborts the session; the failure consumes one bounded attempt.

The default is deliberately generous rather than tight. Successful planning work
items measured over 7 days ran p50 12.7 / p90 39.5 / p99 105.7 minutes, so a
tighter bound would abort legitimate plans and pay for the restart — the churn
this work exists to remove. It bounds hung turns, not slow ones.

3. [event:task:moved] executor tracing dropped from log to debug. It fires on
every dispatch, rebound, requeue, archive and self-healing move across every task,
which made it the loudest line in engine output and buried operator-actionable
events. No test pins the level; the information remains at debug.

Also fixes a test break shipped in 963dba6f80: the review blocking-severity
settings landed inside BUILTIN_REVIEW_REVISION_SETTINGS, whose contents
builtin-workflow-settings-triage.test.ts asserts exactly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:27:10 -07:00
gsxdsm
81139dbbd0 fix(engine): classify provider request timeouts as transient
"Request timed out." is the literal default message of the Anthropic and OpenAI
SDKs' APIConnectionTimeoutError, surfaced to Fusion by checkSessionError after
pi-coding-agent exhausts its in-session retries. It matched none of the
connection-scoped timeout patterns, which deliberately excluded "general
timeouts", so it fell through to specifyTask's generic failure branch — the one
that restores status: null and writes no counter, no nextRecoveryAt, and no park.
Triage rediscovery then re-admitted the card on the very next poll, forever.

Measured before this change: 48 "Specification failed: Request timed out." events
across 10 tasks in 30 hours with zero backoff between attempts. FN-8950 alone
burned 8 consecutive attempts over ~8 hours and never reached implementation.
Across 2 days, 91 failed planning attempts averaged 33 minutes each — ~50 hours of
wall-clock producing nothing, 24% of all planning time.

Classifying these as transient routes them into the bounded recovery policy
(MAX_RECOVERY_RETRIES = 3, 60s/120s/300s jittered backoff) already used by the
connection-level patterns, so a provider blip costs three spaced retries instead
of an unbounded loop.

The pattern is anchored to "request timed out" rather than a bare timeout match:
agent log prose and verification output legitimately contain "timed out"
("BuildKit timed out", "stuck-kill unwind timeout"), and a broad pattern would
reclassify real permanent failures as retryable — the mistake the connection-only
rule was written to avoid. Regression tests pin both directions.

This does not affect model fallback, which pi decides internally and Fusion only
observes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 12:01:25 -07:00
gsxdsm
00ddafd5fe FN-8845: persist deterministic spec alignment
Persist approved-plan drift alignment on linked mission features.

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

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

Fusion-Task-Id: FN-8845

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

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 11:50:56 -07:00
gsxdsm
963dba6f80 feat: gate review verdicts on finding severity and preserve remediation sessions
Review remediation loops were the dominant cost of task wall-clock: over 14 days,
tasks with >=5 post-review fix rounds were 22% of tasks but consumed 78% of all
task active time, and 311 of 331 recorded findings were spec-internal-consistency
complaints that changed no delivered behavior.

Two causes compounded. Plan/Code Review remediation was unbounded by default, and
the review policy ordered a full re-derivation of the artifact after every edit
("distrust the edit ... fresh holistic pass"), so each round surfaced a fresh crop
of previously-acceptable observations as new blockers.

Make the already-persisted WorkflowReviewFinding.severity load-bearing instead of
decorative: a REVISE only blocks when it carries a finding at or above the review
kind's threshold (plan: P0+P1, code: P0). Non-blocking findings are still parsed,
persisted, and handed to the implementer as advisory notes in PROMPT.md. Fails
closed — a REVISE with no findings, or with any unclassified finding, still blocks,
so prose-only and custom reviewers keep full blocking power. The gate only ever
relaxes a verdict, never promotes one.

Reviewer prompts now request the structured findings schema (Plan Review emitted
none before), define severity by consequence as P0/P1/P2, omit nits entirely rather
than filing them as low-severity findings, and use an incremental re-review contract.
Remediation renders findings grouped by priority and sanctions an explicit decline
with rationale, so a disputed finding has a terminal state.

Also preserve the implementation session across a review bounce: sendTaskBackForFix
no longer nulls sessionFile when preserving resume state, and the executor's finally
no longer clears it on a review handoff. Remediation rounds continue the conversation
instead of re-reading the repo and re-deriving the change they just wrote. The resume
prompt now directs a PROMPT.md re-read, without which a resumed agent would never see
the new findings.

New per-workflow settings planReviewBlockingSeverity / codeReviewBlockingSeverity;
set either to "any" to restore the previous behavior.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 11:28:32 -07:00
gsxdsm
e6b6223d30 fix(engine): stop per-poll symbol-lock renewal log and activityLog spam
Renewal runs every poll for every implementation-column task with declared
symbols, and a lost lock never recovers by renewing — renewSymbolLocks reports
the same lost set on each pass, so the warning and its store.logEntry companion
repeated forever: log-pane spam plus unbounded activityLog growth for a stuck
task. The two error paths had the same shape on any persistent failure.

Extract the executor's suppression into a shared createRepeatSuppressedLog and
use it in both: first occurrence per task/signature logs at full level, repeats
drop to debug(), a changed lost set or error message logs again, and a clean
renewal clears the memo. The logEntry write is gated on the same decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 10:33:35 -07:00
gsxdsm
a2deae041a fix(engine): stop per-poll executor dispatch-blocked log spam
The unmet-dependency and ephemeral-disabled pre-dispatch gates re-run on every
dispatch attempt for a blocked task but only change state on the first, so every
later pass re-logged the same line at default level and drowned the log pane.

Route both through logDispatchBlockedOnce: first block per task/reason logs at
log(), identical repeats drop to debug() (FUSION_DEBUG=executor), a changed
reason logs again, and the marker clears when the gate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 10:11:11 -07:00
gsxdsm
936dd1ea96 FN-8924: retain safe age gate for merge recovery
Document why interrupted merge recovery retains its age-based admission gate.

- Record why merger logs cannot establish task ownership or orphan status.
- Pin non-owner recovery behavior when a merging task was recently updated.

Files changed:
 docs/self-healing-backward-move-audit.md           | 8 +++++++-
 packages/engine/src/__tests__/self-healing.test.ts | 9 ++++++++-
 2 files changed, 15 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-8924

Fusion-Task-Lineage: 19e7f803-21fe-43fb-8ca6-eecf8ff61df4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 09:09:04 -07:00
gsxdsm
0fc6f3d849 FN-8946: enable attributed agent mission status updates
Enable authorized agents to update feature and mission statuses with transactional, attributed audit events.

- Add mission and feature status tools to the Fusion extension and engine allowlists.
- Record bounded actor, reason, and hierarchy metadata for status transitions across every writer.
- Guard linked feature transitions and document the agent-facing workflow.

Files changed:
 .changeset/fn-8946-mission-status-writes.md        |   7 +
 docs/missions.md                                   |   7 +-
 packages/cli/skill/fusion/SKILL.md                 |   2 +-
 .../cli/skill/fusion/references/extension-tools.md |  20 +++
 .../skill/fusion/references/fusion-capabilities.md |   2 +
 packages/cli/src/__tests__/extension.test.ts       |  46 ++++++
 packages/cli/src/extension.ts                      |  27 +++
 .../mission-status-event-metadata.test.ts          |  50 ++++++
 .../__tests__/postgres/mission-store.pg.test.ts    | 160 +++++++++++++++++-
 .../core/src/async-stores/async-mission-store.ts   | 182 +++++++++++++++------
 packages/core/src/index.ts                         |   5 +
 packages/core/src/missions/mission-store.ts        |   7 +-
 packages/core/src/missions/mission-types.ts        |  99 +++++++++--
 .../src/__tests__/chat-toolset-permissions.test.ts |  24 +++
 packages/dashboard/src/mission-routes.ts           |   3 +-
 .../src/__tests__/agent-mission-tools.test.ts      |  42 ++++-
 .../src/__tests__/heartbeat-executor.test.ts       |   4 +-
 .../workflow-step-readonly-allowlist.test.ts       |   2 +
 packages/engine/src/agent-tools.ts                 |  18 ++
 .../engine/src/execution/gating-classifications.ts |   2 +
 20 files changed, 635 insertions(+), 74 deletions(-)

Fusion-Task-Id: FN-8946

Fusion-Task-Lineage: 473cc0e0-e632-48b3-ac84-adaaeb81db4b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 07:30:42 -07:00
gsxdsm
00e369711c FN-8949: add dead mock specifier guard
Prevent silent dead engine test mocks and restore renamed-lane coverage.

- Add a ratcheting test that detects unresolved relative vi.mock specifiers.
- Update self-healing test seams for moved modules and queue transitions.
- Document mock-specifier and store-fake failure patterns.

Files changed:
 .../dead-vi-mock-specifiers-fail-silently.md       |  57 ++++++
 ...e-defects-that-masquerade-as-production-bugs.md |  12 ++
 docs/testing.md                                    |   5 +
 .../self-healing-query-filter-blindness.test.ts    |  42 ++++-
 .../__tests__/vi-mock-specifiers-resolve.test.ts   | 199 +++++++++++++++++++++
 5 files changed, 306 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-8949

Fusion-Task-Lineage: a1079d1c-a2a9-4ac2-8245-1db434468405

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 04:54:55 -07:00
gsxdsm
0fbeba50d1 FN-8937: rescue project engine test quarantine
Rescue the project engine suite by making subprocess watchdog behavior deterministic.

- Capture real timer APIs for subprocess watchdogs and isolate failure ownership.
- Mock integration-branch resolution to prevent host git during lifecycle tests.
- Add watchdog regression coverage and remove the expired quarantine exclusion.

Files changed:
 docs/testing.md                                    |   3 +
 packages/core/src/__test-utils__/vitest-setup.ts   |  74 ++++++++++-
 .../__tests__/subprocess-guard-fake-timers.test.ts | 140 +++++++++++++++++++++
 .../engine/src/__tests__/project-engine.test.ts    |  63 +++++++---
 packages/engine/vitest.config.ts                   |  12 +-
 scripts/lib/test-quarantine.json                   |   8 +-
 6 files changed, 265 insertions(+), 35 deletions(-)

Fusion-Task-Id: FN-8937

Fusion-Task-Lineage: 9fe166b5-b101-4683-bb2b-4855ee73df10

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 03:50:58 -07:00
gsxdsm
08a3f2851b FN-8919: harden stale agent link recovery
Normalize missing task lookup errors so stale durable-agent links do not halt self-healing sweeps.

- Treat thrown not-found and deleted task lookups as stale links.
- Isolate transient task lookup failures to their affected agent.
- Add recovery regression coverage and a patch changeset.

Files changed:
 .changeset/fn-8919-agent-link-sweep-fail-open.md   |  7 ++
 .../self-healing-agent-link-drift.test.ts          | 58 +++++++++++++--
 .../self-healing-path-utils-task-miss.test.ts      | 51 +++++++++++++
 packages/engine/src/__tests__/self-healing.test.ts | 84 +++++++++++++++++++++-
 .../engine/src/healing/self-healing-path-utils.ts  | 34 ++++++++-
 packages/engine/src/self-healing.ts                | 57 +++++++++++----
 6 files changed, 272 insertions(+), 19 deletions(-)

Fusion-Task-Id: FN-8919

Fusion-Task-Lineage: 6dca2c1d-8ff9-47fb-b6c1-24f5af57b499

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

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

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

Fusion-Task-Id: FN-8943

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

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 02:56:58 -07:00
gsxdsm
5b9e6643d6 FN-8869: inherit project model overrides for role agents
Role-based permanent agents now consistently use their effective project model and thinking settings.

- Resolve permanent-agent model and thinking inheritance by workflow role in core.
- Apply inherited settings to Agent views, Chat sessions, routes, and heartbeat sessions.
- Cover role-specific inheritance and preserve the lifecycle-column ratchet classification.

Files changed:
 .changeset/fn-8869-role-agent-project-model-override.md   |   7 ++
 docs/agents.md                                     |   9 +-
 docs/settings-reference.md                         |   4 +-
 packages/core/src/__tests__/agent-effective-model.test.ts    |  97 +++++++++++++++++++
 packages/core/src/__tests__/no-hardcoded-lifecycle-columns.test.ts |   2 +
 packages/core/src/ai/agent-effective-model.ts      |  82 +++++++++++++++++
 packages/core/src/ai/model-resolution.ts           |  14 +++
 packages/core/src/index.gate.ts                    |   7 ++
 packages/core/src/index.ts                         |   7 ++
 packages/core/src/types.ts                         |   7 ++
 packages/dashboard/app/components/AgentDetailView.tsx |  49 ++++++---
 packages/dashboard/app/components/AgentsView.tsx   |  11 ++-
 packages/dashboard/app/components/__tests__/AgentDetailView.effective-model.test.tsx |  55 +++++++++++
 packages/dashboard/app/components/__tests__/AgentDetailView.settings.test.tsx |  22 +++++
 packages/dashboard/app/components/__tests__/AgentsView.test.tsx |  25 +++++
 packages/dashboard/src/__tests__/chat-manager.test.ts |  45 +++++++++
 packages/dashboard/src/__tests__/routes-chat-sessions-project-model.test.ts | 103 +++++++++++++++++++++
 packages/dashboard/src/chat.ts                     |  65 +++++--------
 packages/dashboard/src/routes/register-chat-routes.ts |  37 +++++---
 packages/engine/src/__tests__/agent-session-helpers-test-mode.test.ts |  13 +++
 packages/engine/src/__tests__/agent-session-helpers.test.ts |  54 +++++++++++
 packages/engine/src/agent-heartbeat.ts             |  10 +-
 packages/engine/src/agents/agent-session-helpers.ts |   6 +-
 23 files changed, 648 insertions(+), 83 deletions(-)

Fusion-Task-Id: FN-8869

Fusion-Task-Lineage: 00227aaf-b33b-43f1-bcbb-2203c9930dbc

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-10 02:25:03 -07:00
gsxdsm
51437558ac fix(workflow): give a stranded planning hold a retry owner, and stop status erasure
FN-8923 sat silent in Todo for 7+ hours with zero run-audit rows. Its plan node
held on principal routing, triage correctly recorded `needs-replan`, and then
dependency auto-unblock nulled that status when its blocker completed. From that
moment the card was invisible to both lanes: triage saw a fully-written spec with
no replan flag and skipped it, while the executor's `isUnplannedForExecution`
refused to dispatch because no capacity-boundary continuation existed. Not stuck
in a retry loop -- unowned.

- Dependency auto-unblock clears only the `queued` marker it owns, at all four
  sites (scheduler.ts plus three in self-healing.ts). `status` is a shared
  lifecycle channel and `needs-replan` is the only signal that re-admits a
  hold-column card whose PROMPT.md is already a real spec.
- New self-healing sweep `reconcilePrincipalHeldPlanningContinuations` re-queues
  planning for a card whose sole active continuation is a principal-routing hold.
  A planning hold otherwise has no retry owner at all. Gated on the planning
  lane, effective auto-merge, an owned (null) status, and the shared planning
  lifecycle lock, so it cannot clobber a triage claim or launder a `failed` /
  `stuck-killed` / `queued` card into a replan.
- Workflow node-instance-id materialization is idempotent across foreach, loop,
  and optional-group containers. It re-wrapped its own output on every dispatch,
  so FN-8869 grew a ~1.8 KB `run_id` of ~30 repeated segments on a hot indexed
  column and every retry read as a distinct run.
- An unresolvable node instance or absent IR now fails closed instead of being
  treated as an edited-away override -- the previous shape would have discarded a
  real reviewer fence and handed a named review to the pool.
- Mirror the routing exports into the gate-safe core barrel; the reduced barrel
  resolved them to `undefined`, a latent trap for any suite reaching the router.

Findings from a multi-reviewer pass; 9 of 11 confirmed by an independent
validator. Each fix carries a regression asserting the invariant across its
surfaces, not the single reported case -- the optional-group accretion test was
verified to fail without the fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:43:54 -07:00
gsxdsm
37d32357e9 fix(workflow): keep assigned tasks executing instead of holding on a dead principal
Workflow principal routing conflated two different questions: whether an agent
CAN run a node, and whether it can run it RIGHT NOW. Both produced a hold, and a
named principal never falls through to the role pool — so an agent that could
never satisfy the node wedged the task permanently.

FN-8869, FN-8928, and FN-8845 were each explicitly assigned to a permanent
engineer-role agent (which the assignment policy allows). Their `step-execute`
nodes took that owner as `task-assignee` authority, found no `executor` tag, and
held closed. Each card re-dispatched and re-held every ~15 minutes for hours
while two idle `Workflow Executor` pool agents were never consulted. The only
thing still touching them was the owner's hourly heartbeat, which logged
"progressing, no blockers" and exited: heartbeat observation had replaced
execution.

- Structural incapability (wrong role, agent deleted, authority edited away) is
  no longer authority for the node. Routing continues to the column binding and
  then the role pool.
- A resumed continuation whose fence proves stale discards it and re-routes,
  instead of re-asserting a dead principal on every dispatch.
- Availability is unchanged and still fail-closed: a role-capable principal that
  is paused, disabled, or at session capacity holds, and is never silently
  replaced by a pool member.
- An explicitly assigned engineer-role agent is now valid task-assignee
  authority for an executor node, so the assigned agent executes its own task
  continuously under graph dispatch. The role pool stays strict, since automatic
  backlog pickup by engineers is a separate opt-in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 00:58:43 -07:00
gsxdsm
d9a2d9dba3 FN-8925: clear orphaned paused merge stamps safely
Allow only engine-owned deadlock pauses to clear stale merge stamps without resuming work.

- Fail closed when merge ownership probing is unavailable.
- Clear stale stamps only for merge-deadlock-detected pauses and suppress their enqueue.
- Add race coverage, audit documentation, and a patch changeset.

Files changed:
 .changeset/fn-8925-paused-stale-merge.md           |   7 +
 docs/self-healing-backward-move-audit.md           |   2 +-
 docs/task-management.md                            |   4 +-
 .../self-healing-query-filter-blindness.test.ts    |   5 +-
 .../self-healing-stale-merge-fanout.test.ts        |   1 +
 packages/engine/src/__tests__/self-healing.test.ts | 203 +++++++++++++++++++--
 packages/engine/src/self-healing.ts                |  45 ++++-
 7 files changed, 241 insertions(+), 26 deletions(-)

Fusion-Task-Id: FN-8925

Fusion-Task-Lineage: e5491e1a-ca0a-4a82-b4e0-4002f30e869e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>,
2026-08-09 23:13:34 -07:00
Phil Larson
b30508c685 fix(executor): preserve external checkout ownership guards (#3404)
## Summary
- keep operator-routed external checkouts out of managed worktree
preflight, cleanup, and lost-work reconciliation paths
- mark injected custom graph worktree creation as native so workspace
mode accepts the managed backend
- add an extraction regression guard for the ownership fences

## Test plan
- `pnpm --filter @fusion/engine exec vitest run
src/executor/__tests__/external-checkout-extraction-guards.test.ts
--silent=passed-only --reporter=dot`
- `pnpm --filter @fusion/engine typecheck`
- `pnpm check:changesets`
- targeted ESLint on the changed TypeScript files


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

* **Bug Fixes**
* External execution checkouts are no longer treated as Fusion-managed
worktrees.
* Prevented unnecessary Git checks, cleanup, and reconciliation during
retries, pauses, recovery, and stuck-task handling.
* Invalid external checkout configurations now fail safely with an
error.
* Graph-injected worktrees now use the native worktree backend for
consistent setup.
* **Tests**
* Added coverage verifying external checkouts remain excluded from
managed worktree operations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-09 19:40:01 -10:00
Phil Larson
a5c3476cb2 fix: harden pinned worktree recovery cleanup (#3402)
## Summary
- serialize pinned-path classification, orphan preservation, quarantine
reconciliation, and recreation under one reservation
- preserve cross-filesystem orphans atomically beside the configured
worktree root and retain the newest 10 generated entries per recovery
root
- exclude recovery containers from pool and self-healing scans, with
fail-closed symlink and active-session guards
- document recovery location and retention behavior

## Test plan
- `pnpm --filter @fusion/engine exec vitest run
src/__tests__/worktree-acquisition.test.ts
src/__tests__/worktree-paths.test.ts src/__tests__/worktree-pool.test.ts
src/__tests__/self-healing-tempdir-sweep.test.ts --silent=passed-only
--reporter=dot`
- `pnpm --filter @fusion/engine typecheck`
- `pnpm --filter @fusion/engine build`
- `pnpm test:gate:static`
- `pnpm check:changesets --strict`
- `pnpm check:fnxc-future-dates`


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

* **New Features**
* Preserves orphaned pinned worktrees during recovery, including across
filesystems.
* Retains the 10 most recent recovery entries and safely skips active or
invalid entries.
* Keeps recovery data separate from normal worktree discovery, cleanup,
and capacity checks.
* Adds safeguards for path containment, active-session ownership, and
concurrent recovery.

* **Bug Fixes**
* Prevents pinned worktree data from being lost during recreation or
quarantine cleanup.
* Ensures recovery cleanup failures do not interrupt worktree
acquisition.

* **Documentation**
* Documented orphan recovery, retention, fallback behavior, and cleanup
safeguards.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-09 19:39:39 -10:00
gsxdsm
1474c617b5 FN-8918: suppress false parked-task alerts
Prevent stale self-healing observations from notifying operators about active or intentionally held tasks.

- Require ownerless self-healing proof before classifying a task as wedged.
- Revalidate live tasks and suppress notifications for progressing, held, deleted, archived, or complete-lane rows.
- Cover reviewing, typed not-found reads, and archived episode resolution; document the behavior.
- Add a patch changeset for the notification fix.

Files changed:
 .changeset/fn-8918-false-parked-task-alerts.md     |   7 ++
 docs/agents.md                                     |   2 +-
 docs/architecture.md                               |   2 +-
 packages/engine/src/notification/__tests__/task-wedge-notification.test.ts | 121 +++++++++++++++++++--
 packages/engine/src/notification/notification-service.ts | 34 ++++--
 packages/engine/src/notification/task-wedge-notification.ts | 21 +++-
 6 files changed, 166 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-8918

Fusion-Task-Lineage: 4da385aa-c625-40c5-a781-36becdf94fe5

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-09 21:57:01 -07:00