2cbb80c5019b773627f257640324ae7fadbc97d1
802 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
227281dc32 |
FN-8503: preserve unbounded Code Review retries
Keep Code Review remediation retry policies accurate across graph execution and recovery. - Preserve unlimited retry presentation when Code Review has no configured cap - Enforce finite Code Review caps during failed-step recovery - Validate non-negative revision settings and document the active retry policy Files changed: .../fn-8503-unbounded-code-review-retries.md | 7 ++ docs/workflow-steps.md | 2 +- .../core/src/__tests__/builtin-workflows.test.ts | 8 +- packages/core/src/builtin-workflow-settings.ts | 4 + .../workflow-graph-optional-step-fix.test.ts | 135 +++++++++++++++++++++ packages/engine/src/executor.ts | 51 ++++++-- 6 files changed, 193 insertions(+), 14 deletions(-) Fusion-Task-Id: FN-8503 Fusion-Task-Lineage: 7bd555d1-23e5-42ea-b6f5-0b9fe4da7f94 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
53e3063e9f |
FN-8490: load skills for foreach step-execute sessions
Honor skill-executor configuration for implementation sessions created by foreach templates. - Propagate validated step-execute skill names through workflow seam context. - Load namespaced and bare skills with configured discovery paths for pinned step sessions. - Add regression coverage, workflow documentation, and a minor changeset. Files changed: .changeset/fn-8490-step-execute-skill.md | 7 ++ docs/workflow-steps.md | 4 +- .../__tests__/step-execute-skill-loading.test.ts | 128 +++++++++++++++++++++ packages/engine/src/executor.ts | 62 +++++++++- packages/engine/src/workflow-node-handlers.ts | 21 ++++ 5 files changed, 219 insertions(+), 3 deletions(-) Fusion-Task-Id: FN-8490 Fusion-Task-Lineage: aa1ff02d-3139-45f2-8853-f53c0aef0f2f Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
56efd7488e |
fix(engine): stop false-positive stuck loop kills on iterative work (#2404)
## Summary - Fix a false-positive in `StuckTaskDetector` where legitimate long single-step work (E2E debugging, iterative fix/test cycles) was classified as a loop and kill/requeued. - Root cause: loop meant “no step status transition for `taskStuckTimeoutMs` + high activity volume,” conflating **step progress** with **actual activity**. Agents can stay productively busy on one step for 10+ minutes with zero repetition. - Loop now requires thrash evidence on top of volume + no step progress: - **repetitive tool fingerprints** (`toolName` + primary-arg detail in a sliding window), or - **elevated ignored step-update rebuffs** (≥ 10) - Wire tool name/detail from `AgentLogger` → executor / step-session into `recordActivity(...)` so novelty is measurable. - Document the thrash-evidence rule in `docs/architecture.md`. ## Test plan - [x] `pnpm --filter @fusion/engine exec vitest run src/__tests__/stuck-task-detector.test.ts src/__tests__/reliability-interactions/non-progress-churn.test.ts` - [x] Regression: high-volume **diverse** iterative activity (174 events) does **not** classify as loop - [x] High bare text/heartbeat volume without tools does **not** classify as loop - [x] Repetitive identical tool fingerprint + timeout **does** classify as loop - [x] Ignored step-update thrash (≥10) with volume **does** classify as loop - [x] Existing FN-5168 no-progress-churn + FN-6598 verification suppression paths still pass - [ ] CI gate green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved stuck/loop classification by requiring explicit “thrash evidence” (repetitive tool fingerprints and/or elevated ignored progress rebuffs), reducing false positives for busy but diverse work. * Updated loop evidence tracking to incorporate tool name plus summarized tool-argument detail. * Cleared loop evidence appropriately after verification, progress updates, and task resumption. * Extended tool-start telemetry/callbacks to include optional tool detail. * **Documentation** * Refined loop-classification criteria to match the new evidence gates. * **Tests** * Updated/expanded stuck/loop and churn scenarios to validate the evidence-based behavior and callback ordering. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d194290a75 |
fix(engine): reject out-of-order step starts (#2403)
## Summary Ordered task steps can no longer appear active ahead of unfinished predecessors. Step starts now use the same dependency-aware ordering guard as completions, while steps explicitly declared independent remain parallelizable. Rejected executor updates explain that the lifecycle transition was suppressed instead of implying completed work was overwritten. ## Validation - Reproduced the FN-8490 concurrent update sequence and verified later steps remain pending. - Passed 15 PostgreSQL step-order tests, the focused executor response test, core and engine typechecks, changeset validation, and `pnpm verify:fast` including boot smoke. - The full `executor-prompt.test.ts` run retains five pause-behavior expectation failures that reproduce unchanged on `origin/main`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced the step start hook to support an awaited “pre-start projection” that can reject startup via `false` (sync or async), preventing step-session creation/completion. * Added a step-start “verdict” so steps can be started or blocked deterministically (including “resumed” behavior). * **Bug Fixes** * Prevented ordered/dependency steps from transitioning out-of-order by enforcing guards for both in-progress and done transitions, including concurrent update attempts. * Improved integrity/out-of-order warning behavior and suppression details when persisted status doesn’t match expectations. * **Tests** * Added/updated PostgreSQL and engine regression coverage for blocked/resumed start and start-rejection control flow. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
6422cb93a4 |
fix(engine): stop overseer hard-cancel thrash on live step sessions (#2393)
## Summary
Prevents the FN-8471 failure mode where planner overseer `retry_step`
bounced `in-progress → todo` while a live step-execute session was still
coding, hard-cancelling the agent up to three times until recovery
budget exhausted.
Also closes concurrent resume races after plan-review release that
parked `status=failed` on a losing graph while a peer session still
owned work.
### Changes
- **Overseer live gate:** `retryStep` skips the hard-cancel bounce when
`isTaskLiveForOverseerRetry` is true; returns `false` so attempt budget
is not burned; durable skip log is deduped per task/stage.
- **Single-flight graph dispatch:** `executeCore` claims `graphRouting`
before any await; `executeWorkflowGraph({ alreadyClaimed })` owns
release.
- **Single-flight unpause resume:** claim `resumingUnpaused` before
await; treat existing graph claim as already-owned; clear claim before
completed-work recovery.
- **No false park:** execute-family graph endings with a peer live
session no longer stamp `status=failed` (merge-region failures still
park).
### Tests
- `executor-live-overseer-retry-gate.test.ts` — live probe matrix,
execute-family preserve, merge still parks
- `planner-overseer-intervention-wiring.test.ts` — live skip keeps
column in-progress and `getAttemptCount === 0`
## Test plan
- [x] `vitest run` scoped to the two new/updated test files (16 passed)
- [ ] CI gate (lint/typecheck/build/test:gate)
- [ ] Optional manual: fail a raced graph with a live step session and
confirm overseer does not bounce to todo
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Improved overseer-retry “live session” gating to avoid interrupting
active work, covering more live surfaces and preventing multi-resume
races.
- Updated failure handling so execute-family failures can be preserved
when another live session is still running, while merge-attempt failures
are still marked failed.
- Added deduping for “retry skipped due to live session” logs so they’re
emitted only once per task stage, and ensured the recovery attempt
budget isn’t consumed when intentionally skipped.
- **Tests**
- Added coverage for live-gating, retry-skip/budget behavior, and the
revised failure-parking rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
1e05793876 |
fix(ci): green full-suite bookkeeping after origin/main cutover (#2392)
## Summary Restores green merge-gate and package-default suites after repeated `origin/main` merges brought workflow-graph ownership cutover drift into CI. - Align engine/dashboard/core tests with post-cutover contracts (`moveTaskIf`/`deleteTaskIf`, graph handoff, worktree-pool reclaim via `removeWorktree` + `RemovalReason`, multi-step RESUMING parse, soft-pause merge requester, graph-terminal failure surfaces). - Small product fixes needed for real regressions uncovered by the suite: soft-delete refuse before graph routing, skip DUPLICATE step-heading withhold when an explicit marker is present, PG schema applier guards, and related bookkeeping (research promote tool inventory / migration seed, stop shell `psql` in PG admin DDL). - Quarantine/ledger hygiene only where required by standing rules; no timeout/worker appeasement. ## Verification - `pnpm test:gate` ×2 green - `@fusion/engine` full package suite green (~9083 tests) - Targeted core/dashboard clusters green (schema applier, agent-runs UI, settings descriptions, mobile close) ## Test plan - [x] `pnpm test:gate` (twice) - [x] `pnpm --filter @fusion/engine test` - [ ] CI full suite / PR checks on this branch - [ ] Confirm no unrelated product behavior changes beyond the listed regression fixes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for `roadmap-item` native structure kinds, including native structure embeds and metadata validation. * Added Stable and Beta release channel options in General settings. * Added per-action reporting target configuration with clearer “unset” guidance. * **Bug Fixes** * Improved heartbeat/prompt behavior when patrol is disabled. * Prevented deleted tasks from continuing through execution. * Made recovery for explicit duplicate redirects more permissive. * Hardened database migration and test database cleanup to reduce flaky failures. * **Documentation** * Updated settings text for release channels, reporting targets, and inheritance/unset behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
080a8e7134 |
FN-8464: guard baseline capture against invalid worktrees
Prevent baseline Git probes from using stale or non-directory task worktrees. - Gate baseline capture on an existing worktree directory - Defer graph step projection until worktree acquisition completes - Cover missing, non-directory, and filesystem-race worktree paths - Add a patch changeset for the operator-facing fix Files changed: .changeset/fn-8464-baseline-cwd.md | 7 ++ .../__tests__/executor-fast-mode-workflows.test.ts | 100 ++++++++++++++++++++- .../engine/src/__tests__/executor-test-helpers.ts | 6 +- packages/engine/src/__tests__/step-runner.test.ts | 62 +++++++++++++ packages/engine/src/executor.ts | 16 +++- packages/engine/src/step-runner.ts | 24 +++++ 6 files changed, 210 insertions(+), 5 deletions(-) Fusion-Task-Id: FN-8464 Fusion-Task-Lineage: e4116dd0-decd-4f9d-87f0-e695cc7f182b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
648971634a |
FN-8461: suppress spurious workflow skill-load warnings
Prevent optional CE configuration from producing warnings when a requested plugin skill is discoverable. - Merge plugin skill body directories with the optional CE discovery root - Warn only when the named workflow skill lacks every viable discovery source - Cover plugin, CE-namespaced, and unrelated-skill discovery cases Files changed: .changeset/fn-8461-skill-load-warning.md | 7 + docs/workflow-steps.md | 8 +- .../__tests__/ce-workflow-step-executor.test.ts | 149 ++++++++++++++++++++- .../engine/src/__tests__/executor-test-helpers.ts | 1 + packages/engine/src/executor.ts | 53 ++++++-- 5 files changed, 200 insertions(+), 18 deletions(-) Fusion-Task-Id: FN-8461 Fusion-Task-Lineage: ef743df4-8bd2-44e6-9498-f6448738d6dc Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c71a9545b0 |
fix(engine): isolate provider rate-limit pauses (#2339)
## What changed
- Construct one `UsageLimitPauser` per project runtime and wire it into
both executor and triage.
- Replace the project-wide emergency stop for 429/quota failures with
provider-scoped task parking.
- Resolve execution, planning, validator, and merger providers for
active tasks; park only tasks routed through the unavailable provider.
- Preserve the actual reviewer provider on `ReviewerProviderError`, so a
Claude Plan Review 429 does not stop Codex work.
- Record `provider-rate-limit:<provider>` pause provenance without
storing provider response bodies in pause metadata.
- Run one daemon-owned provider-health monitor that probes only
providers with persisted rate-limit parks.
- Resume exact matching provider parks across every project only after
the existing authenticated usage probe succeeds and all reported
capacity windows are usable.
- Probe at five-minute intervals for the first five checks, then back
off independently per provider to 10/20/40/60 minutes with a one-hour
cap.
## Root cause and impact
The runtime refactor left `usageLimitPauser` undefined for
`TriageProcessor`. In the observed FN-922 incident, Claude Plan Review
returned four explicit 429 responses; Fusion backed off for roughly
60/120/240 seconds and then failed the task, but never invoked its pause
coordinator. The older coordinator also used `globalPause`, which would
terminate healthy sessions on every other provider.
After this change, active tasks using the unavailable provider are
parked while work routed exclusively through healthy providers
continues. Recovery is a provider-health state transition: the daemon
checks Claude/Codex authentication and metered capacity independently of
task execution, including after restart, and clears only exact
`provider-rate-limit:<provider>` parks. Logged-out, errored, exhausted,
manually paused, user-paused, and other-provider tasks remain parked.
Explicit global/engine pause controls remain unchanged.
## Surface enumeration
- executor usage-limit catches
- triage planner and Plan Review catches
- reviewer provider-error propagation
- merger usage-limit catches
- per-project runtime construction and wiring
- task model overrides plus project/global execution, planning,
validator, and merger resolution
- daemon startup/listen and shutdown lifecycle
- multi-project provider-probe deduplication
- Claude and Codex authenticated usage/capacity probes
- done/archived/already-paused task exclusions
- manual, user, generic, and other-provider pause provenance
## Symptom verification
**Original symptom:** Anthropic/Claude 429s retried and failed FN-922
without pausing Claude-routed work; a functioning global pauser would
also have stopped Codex, and provider parks had no positive-health
recovery path.
**Exact reproduction:** Raise `ReviewerProviderError("429
overloaded_error", "usage-limit", { provider: "anthropic" })` during
Plan Review with Anthropic and Codex tasks present, then return
logged-out/error/exhausted and finally healthy Claude usage responses
from the daemon probe.
**Assertion it is gone:** Anthropic-routed active tasks receive
`provider-rate-limit:anthropic`; Codex-only tasks are not paused and
`globalPause` is never changed. Unhealthy probes leave the Anthropic
tasks parked; a positive authenticated response with remaining capacity
resumes only exact Anthropic provider parks without executing a model
call as a probe.
## Validation
- `packages/engine/src/__tests__/usage-limit-detector.test.ts`: 49
passed
- `packages/dashboard/src/__tests__/provider-health-monitor.test.ts`: 8
passed
- Engine TypeScript check passed
- Dashboard server and app TypeScript checks passed
- Scoped ESLint passed
- Changeset strict format check passed
- Reapply script passed `bash -n`, two consecutive fixture applications,
and `node --check`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Tasks paused due to a provider’s rate limits can now automatically
resume when capacity returns.
- Provider health is monitored in the background, including retry
backoff for unavailable providers.
- **Bug Fixes**
- Rate-limit issues now pause only affected provider-routed tasks
instead of stopping unrelated work.
- Provider failures are handled separately from invalid review results,
improving recovery behavior.
- Healthy providers remain available while another provider is
rate-limited.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: v <v@v.speedport.ip>
|
||
|
|
de2cad7535 |
fix(workflows): reject missing plan review artifacts (#2390)
## Summary Workflows could reach Plan Review without an authoritative PROMPT.md, producing misleading approvals or stranding the task. Planning now verifies durable prompt persistence before releasing the card, and every workflow entry/review surface fails closed when its required plan is absent. Confirmed absence triggers bounded automatic replanning; TaskStore read outages retry in place; exhausted recovery parks visibly without consuming review-fix budget or overriding pause, manual-review, terminal, or merge-confirmed state. Related: FN-8455 ## Validation - Focused workflow-artifact, graph-recovery, review, writer, and triage regression suites pass. - @fusion/engine typecheck passes. - Repository lint, changeset validation, and diff checks pass. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Plan Review now fails closed when `PROMPT.md` is missing or blank, returning a revision request with a typed `failureValue`. * Required workflow artifacts are treated as missing unless they exist with non-empty content; read failures are handled separately. * Recovery now deterministically chooses replan vs “park-failed” with bounded retries, and records a `task:required-artifact-missing` audit event. * **Workflow Improvements** * Triage and approval now persist `PROMPT.md` through the dedicated prompt-write flow and verify it was stored exactly. * Optional-group remediation preserves typed required-artifact missing failures for pre-merge fixes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dc834e582e |
fix(workflows): address lifecycle review follow-ups (#2380)
## Summary - preserve workflow IR hashes in production column-transition audit metadata - centralize active workflow-continuation states across release, runtime, and executor paths - extract and test actionable planning-continuation selection - expand Coding (Ideas) remapping/removal coverage and add required lifecycle decision records Follow-up to the review body on #2378 after that PR was merged. ## Validation - `pnpm lint` - 123 focused core/engine tests - `pnpm verify:fast` - `pnpm test:gate` (487 tests) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved workflow continuation handling by centralizing “active/continuation-eligible” state selection across executor, hold/release logic, and in-process runtime. - Persisted richer task column-transition metadata (including `irHash`) to preserve workflow provenance. - Ensured planning continuations exclude paused/missing/invalid tasks and that task resolution failures surface instead of being ignored. - Corrected fresh-worktree step execution ordering to return expected `baselineSha`/`checkpointId` behavior. - **New Features** - Added and exposed `ACTIVE_WORKFLOW_WORK_ITEM_STATES` for consistent work-item “active” semantics. - Introduced a shared planning-continuation candidate selector to standardize dispatchable planning work filtering. - **Documentation** - Clarified the small coding-ideas workflow preset omits verification while preserving a continuous executable path. - **Tests** - Added coverage for planning continuation filtering and fresh-worktree ordering behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
83209e64dc |
fix(workflows): align stages with board columns (#2378)
## Summary The Coding (Ideas) workflow now behaves like the board it presents: Ideas stays inert, Todo owns planning and plan review, In progress owns implementation, and In review owns code review and merge. The restored preset is intentionally limited to that five-stage path, while the existing Coding workflow remains unchanged. Workflow execution now suspends at Todo→In progress instead of running the implementation node early. A durable, single-owner continuation records the exact resume node and survives process restarts; the scheduler remains the only component allowed to admit the task into WIP. Disabled optional review groups traverse the same boundary without invoking a reviewer, avoiding the prior stuck-task behavior. Workflow validation also rejects capacity holds with no reachable WIP destination, so deterministic lifecycle deadlocks fail at authoring time rather than after a task is running. Session-settled decisions carried from planning: columns are execution invariants, scheduler-owned WIP admission is preserved, the existing Coding (Ideas) preset is restored and simplified, and invalid release topology is rejected (user-approved). ## Validation - `pnpm lint` - `pnpm verify:fast` - `pnpm test:gate` (296 engine, 128 PostgreSQL core, and 63 CI-shape tests) - Focused workflow lifecycle tests (106 assertions) - PostgreSQL regression coverage proves atomic continuation replacement and database rejection of a second active owner <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added durable, resumable workflow execution across capacity boundaries (including explicit suspend/resume at the correct node). * Introduced Todo “plan review” workflow continuations and automated planning/capacity draining. * Restored Coding (Ideas) as a selectable built-in and updated its lane placement; improved optional-step group enablement support. * **Bug Fixes** * User moves back to Todo now cancels active workflow continuations. * Rejected workflow boundary transitions now surface as errors (instead of silently continuing). * Workflows with undriveable capacity-hold configurations are now rejected. * **Tests / Data** * Expanded coverage for workflow suspension, continuations, and continuation replacement; updated database schema to persist continuation metadata and enforce single active continuation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4c0dfbcfd6 |
fix(engine): preserve workflow completion summaries
Keep approved-contract retry instructions scoped to review nodes so advisory and completion-summary agents can produce their intended output. |
||
|
|
1d4e8afa7b |
FN-8444: include planning time in task metrics
Track active planning time alongside execution time for costs, analytics, and task displays. - Persist planning timing state across task lifecycle transitions and recovery - Include planning activity in token cost, analytics, and dashboard timing displays - Add PostgreSQL migration support using the configured migration directory Files changed: .changeset/fn-8444-planning-time-cost.md | 7 +++ docs/dashboard-guide.md | 3 ++ docs/task-management.md | 5 ++ packages/core/src/index.ts | 1 + .../migrations/0029_planning_active_timing.sql | 3 ++ packages/core/src/postgres/schema-applier.ts | 14 ++++- packages/core/src/postgres/schema/project.ts | 2 + packages/core/src/productivity-analytics.ts | 29 +++++----- packages/core/src/store.ts | 2 +- .../core/src/task-store/archive-lifecycle-2.ts | 2 + packages/core/src/task-store/moves.ts | 7 +++ packages/core/src/task-store/persistence.ts | 4 ++ packages/core/src/task-store/remaining-ops-2.ts | 2 +- packages/core/src/task-store/serialization.ts | 7 +++ packages/core/src/task-store/task-row-mappers.ts | 2 +- packages/core/src/task-store/task-update.ts | 10 ++++ packages/core/src/task-timing.ts | 35 ++++++++++++ packages/core/src/types.ts | 12 +++++ packages/dashboard/app/components/TaskCard.tsx | 13 ++--- .../app/components/TaskTokenStatsPanel.tsx | 6 ++- .../app/components/__tests__/TaskCard.test.tsx | 17 ++++++ .../app/utils/__tests__/taskTiming.test.ts | 9 +++- packages/dashboard/app/utils/taskTiming.ts | 14 +++++ packages/dashboard/app/utils/taskTokenCost.ts | 2 + .../dashboard/src/task-planner-chat-metrics.ts | 14 ++++- packages/engine/src/__tests__/self-healing.test.ts | 61 +++++++++++++++++++++ packages/engine/src/executor.ts | 50 +++++++++++++++++ packages/engine/src/runtimes/in-process-runtime.ts | 3 ++ packages/engine/src/self-healing.ts | 62 ++++++++++++++++++++++ packages/engine/src/triage.ts | 10 ++++ packages/i18n/locales/en/app.json | 2 +- packages/i18n/locales/es/app.json | 2 +- packages/i18n/locales/fr/app.json | 2 +- packages/i18n/locales/ko/app.json | 2 +- packages/i18n/locales/zh-CN/app.json | 2 +- packages/i18n/locales/zh-TW/app.json | 2 +- 36 files changed, 384 insertions(+), 36 deletions(-) Fusion-Task-Id: FN-8444 Fusion-Task-Lineage: 0178e0a7-3018-4ef4-be9b-6de5f964fb58 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
1b8b7f617e |
fix(FN-8426): wait for answers to agent questions
Convert supported runtime question-tool calls into Fusion's durable awaiting-user-input contract so workflow execution cannot continue while the operator question is unanswered. Fusion-Task-Id: FN-8426 |
||
|
|
71c0d0a970 |
fix(engine): recover completed triage tasks
Preserve workflow ownership across Plan Review replan moves and route advanced completed triage rows through legal lifecycle transitions before review. Clear only stale same-task session claims after live executor, planner, and merger ownership checks. |
||
|
|
876a278afd |
fix(engine): prevent workflow boundary restart loops (#2360)
## Summary Workflow tasks no longer restart or become stranded in Planning when the graph moves through replan and review boundaries. The executor now distinguishes its own synchronous column transition from an external cancellation, while preserving the existing hard-cancel behavior for user and unrelated engine moves. Existing advanced tasks left in Planning are recovered from durable worktree and graph-pin evidence: completed work advances through the normal review handoff, and incomplete remediation resumes at its pinned execution column. A shared synchronous reservation keeps Planning and recovery mutually exclusive, and Planning excludes advanced rows so they cannot consume capacity in a repeated claim/skip loop. ## Validation - 238 affected engine tests passed, including graph-boundary cancellation, planner eligibility, ownership races, and advanced-task recovery coverage. - `pnpm --filter @fusion/engine typecheck` - `pnpm verify:fast` — workspace build, CLI bundle, and real `/api/health` boot smoke passed. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Workflow graph tasks now continue running correctly when crossing workflow column boundaries. * Improved recovery of interrupted advanced-triage tasks, including completed and in-progress work. * Prevented duplicate triage dispatches and protected tasks from competing recovery and planning actions. * Added safeguards for task state changes during recovery and maintenance operations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7cf030ddca |
fix(FN-8400): normalize preserved worktree recovery
Relocate idle native checkouts into the configured root across executor and self-healing recovery while preserving live, Worktrunk-managed, and task-pinned paths. Cover the invariant with real Git and focused recovery tests. Fusion-Task-Id: FN-8400 |
||
|
|
3b8220113f |
fix(FN-8400): recover preserved worktrees in configured root
Relocate same-task worktrees before returning them from branch-conflict recovery so executor liveness validation cannot reject the recovered path in a retry loop. Fusion-Task-Id: FN-8400 |
||
|
|
1f77935358 |
FN-8307: guard heartbeat task creation with mission lineage
Require autonomous heartbeat work to prove and retain approved mission lineage. - Validate and persist mission lineage for created and delegated tasks - Block off-mission heartbeat actions and reconcile roadmap failures without completion - Renew and release mission symbol locks across workflow lifecycle transitions Files changed: .changeset/fn-8307-heartbeat-mission-guard.md | 7 ++ docs/missions.md | 4 + packages/core/src/__tests__/symbol-locks.test.ts | 12 +++ packages/core/src/task-store/task-update.ts | 17 +++- .../engine/src/__tests__/agent-action-gate.test.ts | 9 +- .../src/__tests__/agent-tools-delegation.test.ts | 41 +++++++- .../src/__tests__/gating-classifications.test.ts | 7 +- .../src/__tests__/mission-feature-sync.test.ts | 10 +- .../src/__tests__/mission-symbol-admission.test.ts | 25 +++++ .../src/__tests__/permanent-agent-gating.test.ts | 3 +- packages/engine/src/agent-action-gate.ts | 28 +++++- packages/engine/src/agent-heartbeat-prompts.ts | 14 +-- packages/engine/src/agent-heartbeat.ts | 34 +++++-- packages/engine/src/agent-tools.ts | 103 +++++++++++++++++++-- packages/engine/src/executor.ts | 2 +- packages/engine/src/gating-classifications.ts | 11 ++- packages/engine/src/mission-feature-sync.ts | 39 +++----- packages/engine/src/mission-symbol-admission.ts | 35 ++++++- packages/engine/src/permanent-agent-gating.ts | 22 +++++ packages/engine/src/scheduler.ts | 21 +++-- packages/engine/src/step-session-executor.ts | 2 +- packages/engine/src/triage.ts | 2 +- 22 files changed, 369 insertions(+), 79 deletions(-) Fusion-Task-Id: FN-8307 Fusion-Task-Lineage: 4ca2ccac-db6e-4e5c-9cc6-d62a40d4f30a Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
fc24e66f63 |
fix(engine): trust explicit task completion summaries
Stop inferring incomplete work from summary wording so scoped future-work notes cannot requeue completed tasks. Keep structural review and bulk-step completion guards intact. |
||
|
|
c77488e0fa |
FN-8370: enforce isolated task worktrees
Keep branch-scoped task work in registered worktrees while the primary checkout stays on its current branch. - Document the executor and acquisition isolation invariant. - Add real-Git coverage for fresh, unregistered, and reused task worktrees. - Guard task worktree creation paths against root checkout switches. Files changed: .../worktree-primary-checkout-invariant.test.ts | 133 +++++++++++++++++++++ packages/engine/src/executor.ts | 7 ++ packages/engine/src/worktree-acquisition.ts | 5 + 3 files changed, 145 insertions(+) Fusion-Task-Id: FN-8370 Fusion-Task-Lineage: 5153b764-c474-4a52-823e-40b06b43d47c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
41f387b219 |
FN-8364: track task token usage from session deltas
Track only task-local deltas from cumulative session usage. - Capture and reset baselines for reused, resumed, and heartbeat sessions - Route executor prompt accounting through the shared per-session delta seam - Cover token accounting behavior and document the analytics correction Files changed: .changeset/fn-8364-session-token-deltas.md | 7 +++ docs/storage.md | 2 +- .../src/__tests__/executor-token-usage.test.ts | 48 +++++++++++++++++++- .../src/__tests__/heartbeat-executor.test.ts | 42 +++++++++++++++++ .../src/__tests__/session-token-usage.test.ts | 53 +++++++++++++++++++++- packages/engine/src/agent-heartbeat.ts | 10 +++- packages/engine/src/executor.ts | 44 +++++++++++------- packages/engine/src/session-token-usage.ts | 20 ++++++++ 8 files changed, 205 insertions(+), 21 deletions(-) Fusion-Task-Id: FN-8364 Fusion-Task-Lineage: 2b16a581-0d58-4c91-8903-6ce368b30a7c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
50454d8a59 |
fix(FN-7996): release Plan Review fallback lease
Unregister the exact workflow-step path after a repository-root fallback so later Plan Review tasks are not blocked by a stale active-session owner. |
||
|
|
3f7c32c95c |
refactor(cutover 2/3): engine — graph-owned lifecycle, legacy execution deleted (#2342)
Part **2 of 3** of the IR-driven lifecycle cutover (stacked on #2341; top is #2335). **Scope (80 files, packages/engine + cli/pi skill docs + AGENTS/architecture):** graph-driven column moves via the column-boundary controller (R1), single-mover scheduler/hold-release trait cutover (KTD-2/KTD-9), trait re-keyed self-healing + merger with the R7b confirmed-merge-must-finalize guarantee, graph-exclusive Plan Review with leased dedup (R4/R5), the executeCore body-lift — zero legacy re-entry — with fn_review_step + interceptor machinery deleted and tombstone-ratcheted (R9), builtin workflow runtime fixes (missing hold handler, unseamed-node column inheritance, no-merge completion mover), the 6-column benchmark acceptance suite (11 tests) + 12-builtin lifecycle sweep (94 assertions), and the executor test-harness modernization. Also retires core's interpreter-cutover scaffolding whose last consumer (the authoritative driver) dies here. **Merge order:** #2341 → this → #2335. After #2341 merges, retarget this to main. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b4c1a1ac77 |
fix(FN-8350): keep tasks running through MCP outages
Retry MCP bootstrap with bounded backoff and request deadlines, then continue with healthy servers when an integration remains unavailable. Exclude definitions with unresolved secrets so graceful degradation never connects a partially authenticated server. |
||
|
|
38891bfd81 |
FN-8296: add chat-requested task verification
Enable chat agents to queue and monitor executor-owned verification runs. - Persist task verification requests through a new PostgreSQL migration. - Expose action-gated chat request and status tools with executor processing. - Show verification status in task and Command Center views. - Advance the schema baseline to migration 0024 and keep chat mocks complete. Files changed: .changeset/fn-8296-feature.md | 7 ++ docs/agent-tool-surface-full-loop.md | 10 +-- docs/dashboard-guide.md | 4 + packages/core/src/index.ts | 2 + .../core/src/postgres/migrations/0000_initial.sql | 20 +++++ .../migrations/0024_task_verification_request.sql | 20 +++++ packages/core/src/postgres/schema-applier.ts | 13 ++- packages/core/src/postgres/schema/project.ts | 25 ++++++ packages/core/src/store.ts | 16 +++- packages/core/src/task-store/reads.ts | 14 +++- packages/core/src/task-store/remaining-ops-6.ts | 49 ++++++++++- packages/core/src/types.ts | 30 +++++++ packages/dashboard/app/api/legacy.ts | 1 + packages/dashboard/app/api/task-content.ts | 10 +++ .../dashboard/app/components/TaskDetailModal.tsx | 17 +++- .../app/components/TaskVerificationStatus.css | 94 ++++++++++++++++++++++ .../app/components/TaskVerificationStatus.tsx | 39 +++++++++ .../__tests__/TaskVerificationStatus.test.tsx | 28 +++++++ .../components/command-center/CommandCenter.css | 33 ++++++++ .../components/command-center/CommandCenter.tsx | 37 ++++++++- packages/dashboard/src/__tests__/chat.test.ts | 1 + packages/dashboard/src/chat.ts | 55 +++++++++++++ .../src/routes/register-command-center-routes.ts | 20 +++++ .../src/routes/register-task-workflow-routes.ts | 17 ++++ packages/engine/src/executor.ts | 51 +++++++++++- packages/engine/src/gating-classifications.ts | 5 ++ packages/engine/src/index.ts | 2 +- 27 files changed, 605 insertions(+), 15 deletions(-) Fusion-Task-Id: FN-8296 Fusion-Task-Lineage: f94647cf-c89f-4f0e-b25f-cbf5b56683bc Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
059a71f5e9 |
fix(FN-8288): fail closed when review contract is unavailable
Fusion-Task-Id: FN-8288 |
||
|
|
358b628b8d |
fix(FN-8288): preserve approved review and recovery state
Fusion-Task-Id: FN-8288 |
||
|
|
cf1a5991aa |
fix: stop processing before returning tasks to Todo (#2322)
## Summary Moving an active task back to Todo could update the board before its agent and subprocesses had stopped, leaving a Todo card that was still processing. User-initiated in-progress-to-Todo moves now wait for every executor cancellation surface before the new column is persisted or returned to the dashboard. Cancellation is fail-closed and bounded: a wedged shutdown leaves the task in Progress, releases its lock for recovery, and fences late cleanup from replacement execution generations. Engine-driven recovery moves and other transitions retain their existing behavior. ## Validation - Confirmed with PostgreSQL-backed symptom tests that the durable row stays in Progress while cancellation is pending and that a timeout releases the task lock without publishing Todo. - Verified multi-executor ownership and replacement-generation fencing across focused core and engine tests: 18 tests passed. - Core build, engine typecheck, targeted lint, and strict changeset validation passed. --- [](https://github.com/EveryInc/compound-engineering-plugin) |
||
|
|
bcdad279d7 |
FN-8289: add feature-video review artifacts
Add gated local feature-video capture to completed user-facing deliverables. - Capture loopback scenario WebM recordings through the existing artifact registry. - Keep recording failures non-blocking and cover gated, unsafe, and failed capture paths. - Document the scenario contract and package the Playwright runtime dependency. Files changed: .changeset/fn-8289-feature-video.md | 7 + docs/workflow-steps.md | 8 + packages/cli/package.json | 3 +- packages/cli/tsup.config.ts | 7 + packages/engine/package.json | 3 +- .../__tests__/executor-review-artifacts.test.ts | 44 ++++ packages/engine/src/executor.ts | 33 +++ .../src/review-artifacts/feature-video.test.ts | 75 +++++++ .../engine/src/review-artifacts/feature-video.ts | 226 +++++++++++++++++++++ packages/engine/src/review-artifacts/index.ts | 10 + pnpm-lock.yaml | 6 + 11 files changed, 420 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-8289 Fusion-Task-Lineage: 8a34675a-2417-4669-a14a-b74c4aa99331 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d51ce46db5 |
FN-8295: add persisted ideation mission handoffs
Persist bounded ideation sessions through agent tools, the Command Center, and atomic Mission convergence. - Store ideation sessions and divergent candidates in PostgreSQL with async APIs and migration support. - Expose gated ideation tools, chat routes, and agent lifecycle integration. - Add the Ideation panel, documentation, release metadata, and regression coverage. Files changed: .changeset/fn-8295-ideation-diverge-converge.md | 7 ++ docs/ideation/persisted-diverge-converge.md | 22 ++++ docs/missions.md | 4 + .../__tests__/postgres/ideation-store.pg.test.ts | 57 +++++++++ packages/core/src/async-ideation-store-queries.ts | 117 +++++++++++++++++ packages/core/src/async-ideation-store.ts | 138 +++++++++++++++++++++ packages/core/src/async-mission-store.ts | 27 ++-- packages/core/src/ideation-types.ts | 69 +++++++++++ packages/core/src/index.ts | 3 + .../core/src/postgres/migrations/0022_ideation.sql | 67 ++++++++++ packages/core/src/postgres/schema-applier.ts | 18 ++- packages/core/src/postgres/schema/project.ts | 49 +++++++- packages/core/src/store.ts | 8 +- packages/core/src/task-store/remaining-ops-8.ts | 14 +++ .../components/command-center/CommandCenter.tsx | 7 +- .../components/command-center/IdeationPanel.css | 18 +++ .../components/command-center/IdeationPanel.tsx | 58 +++++++++ .../__tests__/CommandCenter.test.tsx | 6 +- .../dashboard/src/__tests__/chat-manager.test.ts | 1 + packages/dashboard/src/__tests__/chat.test.ts | 1 + .../__tests__/ideation-tool-route-parity.test.ts | 29 +++++ packages/dashboard/src/chat.ts | 4 + packages/dashboard/src/ideation-routes.ts | 50 ++++++++ .../src/routes/register-integrated-routers.ts | 2 + .../src/__tests__/agent-ideation-tools.test.ts | 40 ++++++ .../src/__tests__/gating-classifications.test.ts | 16 +++ .../src/__tests__/permanent-agent-gating.test.ts | 2 + packages/engine/src/agent-heartbeat.ts | 4 +- packages/engine/src/agent-tools.ts | 67 ++++++++++ packages/engine/src/executor.ts | 2 + packages/engine/src/gating-classifications.ts | 8 ++ packages/engine/src/index.ts | 1 + packages/engine/src/triage.ts | 2 + 33 files changed, 897 insertions(+), 21 deletions(-) Fusion-Task-Id: FN-8295 Fusion-Task-Lineage: 1b8b0752-22bd-4b2f-aebd-4305c63abcf9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b533b918fe |
fix(FN-8064): narrate all task step transitions
Fusion-Task-Id: FN-8064 |
||
|
|
8d1620ea23 |
FN-8294: expose action-gated Mission hierarchy tools
Expose project-scoped Mission hierarchy operations to engine agents and eligible dashboard chat sessions. - Add Mission, milestone, slice, and feature tool definitions backed by MissionStore - Classify hierarchy mutations for action and permanent-agent approval gates - Wire gated tool access through triage, executor, heartbeat, CLI, and chat lanes - Cover tool availability, mutation gating, and chat integration with tests and documentation Files changed: .changeset/fn-8294-mission-engine-tools.md | 7 ++ docs/missions.md | 8 ++ packages/cli/src/extension.ts | 2 +- .../dashboard/src/__tests__/chat-manager.test.ts | 48 +++++++++ packages/dashboard/src/__tests__/chat.test.ts | 1 + packages/dashboard/src/chat.ts | 113 ++++++++++++++++++++- .../src/__tests__/agent-mission-tools.test.ts | 43 ++++++++ packages/engine/src/__tests__/triage.test.ts | 34 ++++++- packages/engine/src/agent-heartbeat.ts | 4 +- packages/engine/src/agent-tools.ts | 64 ++++++++++++ packages/engine/src/executor.ts | 2 + packages/engine/src/gating-classifications.ts | 11 ++ packages/engine/src/index.ts | 17 ++++ packages/engine/src/triage.ts | 111 ++++++++++++++++++++ 14 files changed, 457 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-8294 Fusion-Task-Lineage: ab0f248b-8a38-40e3-b297-79f9dbe18075 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7c23771433 |
FN-8265: add task follow-up proposal creation
Enable configured ephemeral workers to propose and create follow-up tasks from mailbox messages. - Add persisted task-proposal claim state, migrations, and async messaging APIs. - Register task-proposal creation routes, SSE events, agent tool support, and CLI integration. - Add mailbox creation controls, settings, documentation, localization, and regression coverage. Files changed: .changeset/fn-8265-task-follow-up-policy.md | 7 ++ docs/dashboard-guide.md | 2 +- docs/settings-reference.md | 12 ++- packages/cli/src/extension.ts | 34 ++++--- .../src/__tests__/postgres/sqlite-migrator.test.ts | 14 ++- .../postgres/task-proposal-claim.pg.test.ts | 51 +++++++++++ packages/core/src/async-message-store.ts | 39 ++++++++ packages/core/src/index.gate.ts | 4 +- packages/core/src/index.ts | 4 +- packages/core/src/message-store.ts | 46 ++++++++++ .../core/src/postgres/migrations/0000_initial.sql | 2 + .../migrations/0020_task_proposal_claim.sql | 4 + packages/core/src/postgres/schema-applier.ts | 13 ++- packages/core/src/postgres/schema/project.ts | 3 + packages/core/src/settings-schema.ts | 19 +++- packages/core/src/task-store/async-persistence.ts | 2 +- packages/core/src/task-store/persistence.ts | 4 +- packages/core/src/task-store/serialization.ts | 1 + packages/core/src/task-store/task-creation.ts | 51 +++++++++++ packages/core/src/task-store/task-row-mappers.ts | 2 +- packages/core/src/types.ts | 56 +++++++++++- packages/dashboard/app/api/legacy.ts | 5 + packages/dashboard/app/components/MailboxModal.tsx | 4 + .../app/components/MailboxTaskProposal.css | 3 + .../app/components/MailboxTaskProposal.tsx | 33 +++++++ packages/dashboard/app/components/MailboxView.tsx | 4 + .../__tests__/MailboxTaskProposal.test.tsx | 43 +++++++++ .../app/components/settings/section-keys.ts | 2 +- .../settings/sections/GeneralSection.search.ts | 13 ++- .../settings/sections/GeneralSection.tsx | 22 +++-- .../settings-default-descriptions.test.tsx | 4 +- .../routes/__tests__/task-proposal-routes.test.ts | 99 ++++++++++++++++++++ .../src/routes/register-messaging-scripts.ts | 101 +++++++++++++++++++++ packages/dashboard/src/sse.ts | 7 ++ packages/engine/src/agent-tools.ts | 30 ++++-- packages/engine/src/executor.ts | 9 +- packages/engine/src/step-session-executor.ts | 8 +- packages/i18n/locales/en/app.json | 5 + 38 files changed, 696 insertions(+), 66 deletions(-) Fusion-Task-Id: FN-8265 Fusion-Task-Lineage: 4e864a2f-3485-4a54-8be7-1699b5479a94 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
5acea6c0cf |
fix(pg): route residual SQLite-stub store paths through the async data layer (#2273)
## Summary An audit of the SQLite→PostgreSQL store migration found data-store paths still reaching the removed SQLite stub in backend (PG) mode. In backend mode `store.db`/`getDatabase()` throw the removed-SQLite error, so each of these either threw on every run or — worse — had the throw swallowed into a silent wrong result. This PR routes all of them through the `AsyncDataLayer` (and removes one dead primitive). ## The 6 live bugs fixed | Fix | Was | |-----|-----| | `executor.ts` authoritative assigned-agent fallback now inherits the TaskStore `asyncLayer` | silently returned `null` → model drift to the pi built-in (the exact thing its comment guards) | | `pruneAgentLogFilesAsync` replaces the sync self-healing prune call | threw `SQLite Database is not available` every maintenance sweep → agent-log pruning never ran | | `cleanupOrphanedMaterializedSteps` deletes PG `workflow_steps` rows on a failed create | swallowed the throw → leaked rows | | `deleteTaskBackendImpl` now runs the async mission feature/task-link unlink | PG hard delete left orphaned mission links | | `getWorkflowSettingsProjectId` returns `rootDir` in backend mode without touching the stub | swallowed throw for unscoped backend stores | | `fn plugin` unregistered-project fallback bootstraps a `CentralCore` `AsyncDataLayer` | layerless `PluginStore` threw in PG | ## The 4 latent traps, fixed properly - **`cleanupArchivedTasks`** — real async port (enumerate archived soft-deleted rows, guarantee cold snapshot, hard-delete project row + purge selection rows + rm dir). - **`deleteWorkflowStep`** — real async port (delete `workflow_steps` via the layer with `.returning()` to preserve the not-found contract). - **`applyTaskPatch`** — **removed** (zero-caller SQLite column-patch primitive with no backend analogue; impl + facade + import deleted). - **`AgentStore.importLegacyFileRuns`** — clean backend no-op (no legacy SQLite run-files exist in a PG deployment; its only `init()` caller early-returns in backend mode). ## Symptom Verification New PG regression suite `packages/core/src/__tests__/postgres/store-sqlite-residue-fixes.pg.test.ts` reproduces the original failures against real embedded Postgres and asserts they're gone: - orphaned `workflow_steps` are actually deleted (no swallowed throw) - `pruneAgentLogFilesAsync` resolves and prunes inactive-task log files - hard delete unlinks the mission feature from the task - `deleteWorkflowStep` removes the row / reports not-found - `cleanupArchivedTasks` hard-deletes the project row while retaining the cold snapshot ## Verification - `@fusion/core`, `@fusion/engine`, `@runfusion/fusion` typecheck clean - ~50 existing + 5 new PG tests pass; lint clean; changeset validates 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Prevented PostgreSQL backend maintenance from hitting removed legacy SQLite code paths, avoiding datastore failures and residue cleanup issues. * Fixed workflow-step deletion and “not found” behavior in backend mode. * Ensured backend hard-deletes correctly unlink related mission feature/task links and clean orphaned materialized steps. * Prevented legacy file-run imports from incorrectly reporting success in backend mode. * **New Features** * Added async agent-log pruning for inactive tasks and updated maintenance to use it. * **Tests** * Added PostgreSQL regression coverage for residue fixes and archive/workflow cleanup. * **Refactor** * Removed an unused task patch operation and updated task-store cleanup methods to be async where needed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
eb7d223a03 |
FN-8207: add task reassignment for delegated work
Correct delegation routing for duplicate tasks and enable explicit task owner reassignment. - Preserve requested assignee and todo routing on duplicate canonical tasks - Add governed fn_task_assign to engine, heartbeat, triage, workflow, and chat sessions - Cover assignment validation, truthful delegation responses, and tool availability Files changed: .changeset/fn-8207-delegate-assign.md | 7 ++ docs/agents.md | 6 ++ packages/core/src/types.ts | 1 + packages/core/src/usage-events.ts | 2 +- .../dashboard/src/__tests__/chat-manager.test.ts | 2 + packages/dashboard/src/__tests__/chat.test.ts | 2 + packages/dashboard/src/chat.ts | 2 + .../engine/src/__tests__/agent-action-gate.test.ts | 2 + .../src/__tests__/agent-tools-delegation.test.ts | 99 ++++++++++++++++++- .../src/__tests__/agent-tools-task-assign.test.ts | 75 +++++++++++++++ .../src/__tests__/gating-classifications.test.ts | 1 + .../src/__tests__/heartbeat-executor.test.ts | 8 +- .../src/__tests__/permanent-agent-gating.test.ts | 2 + .../src/__tests__/step-session-executor.test.ts | 4 +- packages/engine/src/__tests__/triage.test.ts | 5 +- packages/engine/src/agent-heartbeat.ts | 4 +- packages/engine/src/agent-tools.ts | 105 ++++++++++++++++++++- packages/engine/src/executor.ts | 3 + packages/engine/src/gating-classifications.ts | 1 + packages/engine/src/index.ts | 2 + packages/engine/src/step-session-executor.ts | 2 + packages/engine/src/triage.ts | 2 + 22 files changed, 324 insertions(+), 13 deletions(-) Fusion-Task-Id: FN-8207 Fusion-Task-Lineage: db6f3876-bdc8-4279-b726-29344d9acdb9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7a50232916 |
FN-8208: validate agent message recipients before delivery
Prevent false-success agent messages by validating recipients before delivery. - Wire AgentStore into every send-message tool registration. - Reject missing or unvalidated agent recipients before persistence or wake-up. - Add recipient validation coverage and a patch changeset. Files changed: .../fn-8208-send-message-recipient-validation.md | 7 ++ .../chat-send-message-agentstore-wiring.test.ts | 11 ++ packages/dashboard/src/chat.ts | 2 +- ...tools-send-message-recipient-validation.test.ts | 116 +++++++++++++++++++++ packages/engine/src/agent-heartbeat.ts | 4 +- packages/engine/src/agent-tools.ts | 24 ++++- packages/engine/src/executor.ts | 2 +- packages/engine/src/step-session-executor.ts | 2 +- 8 files changed, 162 insertions(+), 6 deletions(-) Fusion-Task-Id: FN-8208 Fusion-Task-Lineage: 84752bb8-c9f7-42bd-87c1-9681ac442789 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7760d783bd |
fix: green full-suite after getAgentLogCount and inventory drift (#2266)
## Summary - Follow-up after #2229: full suite on main still failed on dashboard curated inventory (21 ungated files) and mass engine failures (`this.store.getAgentLogCount is not a function`). - Harden executor tool-failure cursor capture for minimal/test `TaskStore` adapters (same optional-API pattern as `project-engine`), keep mock fixtures in lockstep, and quarantine inventory-only dashboard files with ledger + vitest exclude. ## Changes - **Executor**: optional `getAgentLogCount` / `getAgentLogs` / `updateTask` at graph entry and trailing-failure detection. - **Mocks**: `createMockStore`, soft-delete guard, post-done continuation, cron `getGlobalSettingsDir`, executor-prompt `bulkCompletionRefusalAt` (FN-8141). - **i18n** (prior commit): es/fr/ko/zh-CN/zh-TW triage-duplicate keys. - **Inventory**: 21 dashboard files → `test-quarantine.json` + `vitest.config.ts` lockstep (VAL-REMOVAL SQLite / load flakes / build-only dist assert). ## Test plan - [x] `node scripts/check-test-inventory.mjs --dashboard-curated` - [x] `pnpm test:gate` - [x] engine: soft-delete, prompt, cron, post-done, tool-failure-retry, and related samples - [x] `@fusion/core` schema-applier + `@fusion/i18n` parity - [ ] Full Suite (non-blocking) on this PR / main after merge <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added localized text for triage duplicate-resolution settings and near-duplicate task actions in Spanish, French, Korean, Simplified Chinese, and Traditional Chinese. - Users can now see translated options and confirmations to keep or delete detected duplicate tasks. - **Bug Fixes** - Improved resilience during task execution and recovery when optional activity-log services are unavailable, preventing avoidable failures during error handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
daa34fbc38 |
fix: refineTask/duplicateTask fail in backend (PostgreSQL) mode (#2253)
## Summary Eliminates the remaining backend/PostgreSQL-mode sync-SQLite (`store.db`) call sites — both the crashing ones and the try/catch-masked ones that silently degraded features. Found via a full audit of `store.db`/`archiveDb` residue after the PG cutover's per-site routing missed them. **Crashes fixed:** 1. **refineTask / duplicateTask** threw `TaskStore.db: SQLite Database is not available in backend mode`. Both create rows through `createTaskWithId` callbacks calling `store.atomicCreateTaskJson()` directly, bypassing `_createTaskInternal`'s backend routing. The shared helper now routes itself (soft-delete conflict check + non-destructive insert in one AsyncDataLayer transaction). 2. **Merger verification cache**: `getVerificationCacheHit` ran sync SQLite unguarded *outside* any try/catch in `runDeterministicVerification`; `recordVerificationCachePass` was swallowed so the cache never warmed. Both are now async with a PG branch. **Silent degradations fixed (features that were dead on PG):** - Workflow run-branch + foreach step-instance persistence (`saveWorkflowRunBranch`, `loadWorkflowRunBranches`, `clearWorkflowRunBranches`, `saveWorkflowRunStepInstance`, `loadWorkflowRunStepInstances`, `clearWorkflowRunStepInstances`) — executor crash-resume checkpoints were silently never persisted. - `getBranchProgressByTask` — returned an empty map, dropping `branchProgress` from task payloads. - `runPluginColumnTransitionHooks` — plugin `onEnter`/`onExit` column-transition hooks never fired (marker bookkeeping + non-locking task read now async). - `getTaskColumns` — dashboard treated all agent-linked tasks as non-terminal. - `getWorkflowStep` / `listWorkflowSteps` — stored workflow-step rows now read from `project.workflow_steps` (listing previously returned plugin steps only); `getLegacyWorkflowStepSnapshot` returns `undefined` on PG (legacy snapshot exists only in pre-migration SQLite). - `readRawProjectSettings` / `listWorkflowPromptOverridesForProject` — now read via the async layer. These store methods became **async**; engine/dashboard callers await them (the workflow persistence interfaces already accepted `Promise`-returning impls). **PG gotcha encoded in the fixes:** migration `0006_project_ownership` rebuilds every project-schema PK to lead with `project_id`, so column-list `ON CONFLICT` inference fails (42P10) — upserts target the PK by constraint name. ## Surface Enumeration - Creators through `atomicCreateTaskJson`: `refineTaskImpl`, `duplicateTaskImpl` (fixed); `_createTaskInternalImpl` unaffected (already routed). - Verification-cache callers (all merger, all 3 sites now awaited). - Run-branch/step-instance callers: executor persistence adapters, parse-steps foreach probe, integration-queue flip, crash-resume reconcile, graph-reset cleanup; triage replan cleanup; dashboard spec-rebuild pin clears; agent-reflection rework summing — all awaited. - Audit classified everything else as guarded or sync-mode-only (dead in production — every entry point constructs stores via `createTaskStoreForBackend`). ## Symptom Verification - **Original symptoms:** refinement/duplicate creation threw; merge verification threw; workflow checkpoints/branch progress/plugin hooks/task-column lookups silently no-oped on PostgreSQL. - **Exact reproduction:** `refine-duplicate-task.pg.test.ts`, `verification-cache.pg.test.ts`, and `sync-db-residue-backend.pg.test.ts` exercise each surface against embedded-PostgreSQL backend-mode TaskStores. - **Assertion it is gone:** all suites pass (14 + 5 tests), plus `transition-pending-and-status-clear.pg.test.ts`, `create-task-reserved-id.pg.test.ts`, dashboard `routes-github.test.ts` (123), engine `triage.test.ts` (221) and `agent-reflection.test.ts` (31). Core/engine/dashboard typecheck fully clean: the 13 errors from the FN-8142 pi SDK migration are fixed by bumping @earendil-works/pi-ai/pi-coding-agent to ^0.80.10 (FN-8142 used APIs absent from the previously locked 0.80.6). Locally green: `pnpm verify:fast` (scoped typecheck + build + CLI build + boot smoke), `pnpm test:gate`, and `pnpm lint`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed refinement/duplication task creation in PostgreSQL-backed backend mode. * Improved backend-mode persistence for workflow checkpoints, foreach-step instances, branch progress, and cleanup flows (including retries/resets/transitions), so stored data reliably round-trips. * Hardened backend-mode reads for workflow steps, task columns, project settings, and prompt overrides. * Made verification-cache reads/writes complete reliably, including command-specific cache behavior. * **Tests** * Added PostgreSQL integration/regression coverage for refinement/duplication, sync residue, and verification caching. * **Chores** * Bumped `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` to `^0.80.10`. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f116d05c41 |
fix(engine): honest BLOCKED park survives pause-abort and workflow-graph teardown (#2264)
## What Follow-up 1 to the FN-8141 guard series (#2254–#2260). Makes the honest `fn_task_done(outcome="blocked")` park (`status:"failed"`, `error:"BLOCKED: <reason>"`, blockedBy → dependencies, added in #2256) **survive the graph-teardown machinery** that bounced FN-8141's failed park back to `todo`. ## Why In the original FN-8141 incident, the executor's parked-failed state did not stick: the pause-abort classifier and the workflow-graph failure handler either rehomed the task to `todo` (clearing `status`/`error`) or overwrote the distinctive `BLOCKED:` error with a generic "Workflow graph terminated with failure" string. #2256 added the blocked exit but nobody proved the park survives that bounce. Any path that clears/overwrites the marker re-opens the laundering hole, because self-healing (#2257/#2260) and dependency-gated scheduling key off exactly that `BLOCKED:` error plus the recorded `blockedBy` dependencies. `handleGraphFailure` now detects a live blocked park (`status === "failed" && error.startsWith("BLOCKED:")`) **before every other classifier** and honors it, following the existing non-graph honor-park precedent (executor `~12163`): - no requeue to `todo`, no engine-internal auto-continue, no `BLOCKED:` error overwrite; - clears the in-memory pause-abort marker so `recoverPausedAbortFailures` has nothing to chase; - **releases the worktree / `maxWorktrees` slot** (FN-6782 leaked-holder precedent — the graph `finally` does not delete `activeWorktrees`); - leaves `status`/`error`/`column`/`dependencies`/steps untouched. Unblocking still works: the operator requeue (`moveTask` in-progress→todo, `moves.ts ~628`) and `buildManualRetryResetPatch` clear the `BLOCKED:` error; the guard keys off the **live** error, so a cleared row is never re-wedged, and dependency-gated scheduling leaves the parked row untouched while `blockedBy` deps are unmet. ## Surfaces covered Pause-abort classifier (hard-cancel), engine-internal auto-continue, and the plain terminal graph-failure sink — all routed through `handleGraphFailure`, so a single top-of-method guard composes across them. ## Test evidence Extended `executor-task-done-blocked.test.ts` (drives `handleGraphFailure` against a live blocked park): - honors the park under a hard-cancel pause-abort bounce (no requeue / clear / auto-continue); - honors it under a plain terminal graph failure (sink never overwrites `BLOCKED:`); - releases the worktree/concurrency slot + clears the pause-abort marker; - NON-blocked failed park keeps existing behavior (guard scoped to `BLOCKED:`); - a cleared (unblocked) row is NOT re-honor-parked. ``` pnpm --filter @fusion/engine exec vitest run src/__tests__/executor-task-done-blocked.test.ts → 13 passed pnpm --filter @fusion/engine exec vitest run executor-paused-abort-todo-benign + executor-graph-requeue-gate → 53 passed pnpm --filter @fusion/engine exec tsc --noEmit → clean pnpm verify:fast → PASS (3 steps green) ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus <noreply@anthropic.com> |
||
|
|
a136535f15 |
fix(engine): taint steps skipped after a bulk-completion refusal so they cannot auto-promote (#2260)
## What & why
**FN-8141 laundered a failed task into `done` with zero net changes and
no sign-off.** After the executor's
`bulk-step-completion-without-review` refusal fired (steps had no
APPROVE verdicts), the agent used the sanctioned skip affordance
(`fn_task_update status="skipped"`) on the remaining unreviewed steps.
Because every completion check counts `skipped` as complete, the task
then satisfied the exact condition the refusal was protecting, and
downstream **automatic** promotion (implicit `fn_task_done`,
self-healing `recoverStrandedCompletedTodoTasks`) moved it to in-review
— where the AI merger found an empty diff and finalized it as a no-op
`done`.
This PR restores the invariant: **steps skipped while a
bulk-step-completion refusal marker is active on the task are "tainted"
and cannot carry the task to review through any automatic path.** The
taint clears on an honest exit — an accepted `fn_task_done` (explicit or
non-tainted implicit) or an operator manual retry — so the legitimate
`PREMISE STALE` skip-then-done flow is unaffected.
## Design
- **Persisted marker**: new nullable `Task.bulkCompletionRefusalAt` (ISO
timestamp), stamped when the `bulk-step-completion-without-review`
refusal fires (explicit `fn_task_done` handler + implicit
`handleImplicitTaskDoneRefusal`). Survives requeue so a refusal on
attempt N taints attempt N+1's promotion. Full store plumbing (types,
descriptors, serialization, SQLite/PG schema + health self-heal).
- **Pure evaluator** `evaluateSkipBypassTaint(task)` in `@fusion/core`
(next to `evaluateNoCommitsNoOpFinalize`): `blocked` iff the marker is
set AND ≥1 step is `skipped`. Single rule every AUTO-promotion check
calls.
- **Clearing**: accepted explicit `fn_task_done`, accepted
implicit/retry completion (the success-reset `updateTask`s), and
`buildManualRetryResetPatch` (operator retry). A fresh lifecycle that
genuinely re-does the work leaves zero skipped steps, so it is never
blocked even if a marker lingers.
## Surface enumeration (every consumer of "all steps done/skipped" that
gates AUTO-promotion)
- **executor.ts**: `getCompletedTaskFinalizationDecision` (gated on the
`isTaskWorkComplete` branch only, never on an accepted `taskDone`);
`recoverCompletedTask` (shared chokepoint for unpause resume,
completed-task watchdog, orphan resume);
`evaluateImplicitCompletionRefusal` (both implicit-completion loops);
`isTaskAlreadyCompleteForNonContinuableSession`; graph merge-boundary
`getWorkflowMergeImplementationProofFailure`.
- **self-healing.ts**: `recoverCompletedTasks` (stuck in-progress) and
`recoverStrandedCompletedTodoTasks` (the exact FN-8141 promoter).
- **Verified-safe, left as-is**: per-step graph node projections
(executor ~6274/6298) and progress-render checks — they don't gate
whole-task auto-promotion.
## Test evidence
Scoped runs (all green):
```
CORE: pnpm --filter @fusion/core exec vitest run \
src/__tests__/skip-bypass-taint-guard.test.ts \
src/__tests__/skip-bypass-taint-persistence.test.ts \
src/__tests__/manual-retry-reset.test.ts
→ 17 passed
ENGINE: pnpm --filter @fusion/engine exec vitest run \
src/__tests__/executor-skip-bypass-taint.test.ts \
src/__tests__/self-healing.test.ts
→ 401 passed
```
Coverage: pure-evaluator (skip-before-refusal counts, skip-after-refusal
doesn't, taint-clearing, empty-marker/empty-steps edges); store
round-trip of the marker (set→read→clear); executor white-box (implicit
completion refused when tainted, allowed when clean or fully re-done,
graph merge-boundary reports missing proof, and the **explicit
`fn_task_done` PREMISE-STALE honest exit stays accepted**); self-healing
(FN-8141 sequence does not promote from either recovery path; a clean
legitimately-skipped task still promotes); manual-retry clears the
marker.
## Note on `pnpm verify:fast`
`verify:fast` currently fails at the workspace-artifact bootstrap on
**pre-existing** pi-SDK type errors in
`packages/engine/src/{auth-storage,pi,provider-registration}.ts` — the
FN-8145 upstream migration breakage (pi 0.80.x removed
`AuthStorage`/`ModelRegistry.create`). **None of those files are in this
diff.** `@fusion/core` builds clean (`packages/core build: Done`), and
`@fusion/engine` `tsc` reports **no errors in the files this PR
touches** (`executor.ts`, `self-healing.ts`); the only engine build
errors are the FN-8145 files. This base failure is the same condition
FN-8141 describes and is out of scope for this task.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus <noreply@anthropic.com>
|
||
|
|
29543a0aac |
FN-8157: add PostgreSQL workflow step-instance persistence
Persist workflow foreach step-instance state through async PostgreSQL store APIs. - Add async save, load, and stale-run pruning operations backed by Drizzle. - Route executor persistence, recovery, and integration projection through async APIs. - Cover PostgreSQL persistence and migrate foreach wiring coverage to the PG harness. - Quarantine unrelated flaky route and triage tests per the test ledger. Files changed: .../workflow-run-step-instances.pg.test.ts | 100 +++++++++++++++++++ packages/core/src/store.ts | 14 ++- packages/core/src/task-store/remaining-ops-6.ts | 109 ++++++++++++++++++++- .../dashboard/src/__tests__/routes-github.test.ts | 14 +-- .../src/routes/register-task-workflow-routes.ts | 18 ++-- packages/engine/src/__tests__/triage.test.ts | 6 +- .../src/__tests__/workflow-foreach-wiring.test.ts | 59 +++++------ packages/engine/src/executor.ts | 57 ++++++++--- packages/engine/src/triage.ts | 4 +- packages/engine/vitest.config.ts | 2 +- scripts/lib/test-quarantine.json | 7 +- 11 files changed, 315 insertions(+), 75 deletions(-) Fusion-Task-Id: FN-8157 Fusion-Task-Lineage: c359f0d3-9191-4d27-aaed-9912419c5c27 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
136958fc60 |
fix(engine): stranded-completed promoters withhold tasks whose last execution ended in a failure park (#2257)
## What & why
FN-8141 laundered a failed task into `done`. The executor correctly
parked the task `failed` ("task parked failed during no-fn_task_done
retry" / "fn_task_done refusal retry budget exhausted"), the pause-abort
machinery bounced it to `todo`, and ~12 minutes later
`recoverStrandedCompletedTodoTasks` promoted it to `in-review` because
every step was done/skipped — overriding the honest failure park. From
there the AI merger found an empty diff and finalized it as a no-op
`done`, with no reviewer ever seeing it.
Existing exclusions (`task.error`,
`evaluateNoCommitsNoOpFinalize().blocked`, active statuses, refreshing
review state) all missed it because the failure provenance lived **only
in the durable task log** by the time the promoter ran — status/error
had been cleared by the pause-abort bounce.
This PR restores the invariant: **a stranded-completed promoter must not
promote a task whose most recent execution lifecycle ended in a
failure/refusal park.**
## Change
- New pure, unit-testable evaluator
`evaluateCompletedPromotionFailureProvenance(task)` in `@fusion/core`
(next to `no-commits-finalize-guard.ts`). It scans the task-log **tail**
(bounded to 250 entries) and lets the **most-recent execution-outcome
marker** decide: a failure/refusal park → `{ blocked: true, reason:
"failure-provenance" }`; a fresh clean completion (`Task marked done by
agent` / `All steps complete — implicit fn_task_done`) that appears more
recently supersedes an earlier park; zero failure markers → not blocked.
Recency is by construction, so a failure that predates a newer clean
execution is never reached.
- Both self-healing sweeps (`recoverCompletedTasks` stuck-in-progress
**and** `recoverStrandedCompletedTodoTasks` stranded-todo) fetch the
full task for candidates that already cleared the cheap slim filters
(slim listings strip `log`) and skip when blocked, emitting a
**deduped** `task:reconcile-stranded-completed-no-action` run-audit
event (ids/outcomes-only: `taskId`, `reason`, `sweep`, `marker?`).
- Defense-in-depth: the shared executor `recoverCompletedTask`
chokepoint — which the sweeps AND the executor's own
unpause/`resumeOrphaned` fast-paths all funnel through — also refuses a
provenance-blocked promotion, so no route can launder a failed park.
**Escape hatch (documented in FNXC comments):** an operator
retrying/moving the task starts a fresh execution whose clean-completion
marker supersedes the failure park, clearing the block with no code
change.
## Surface enumeration
- `recoverCompletedTasks` (stuck-in-progress sweep, self-healing.ts) —
guarded + audited.
- `recoverStrandedCompletedTodoTasks` (stranded-todo sweep,
self-healing.ts) — guarded + audited. FN-8141 shows both columns can
launder.
- `recoverCompletedTask` executor callback (the route both sweeps +
unpause + `resumeOrphaned` share) — verified it did **not** check
log-based provenance; added the guard there as the final chokepoint.
## Test evidence
Pure-evaluator unit tests (`@fusion/core`) — marker detection,
most-recent-outcome recency, supersede-by-clean-completion,
empty/missing log, tail-scan bound:
```
pnpm --filter @fusion/core exec vitest run src/__tests__/completed-promotion-failure-provenance.test.ts
Test Files 1 passed (1) Tests 9 passed (9)
```
Self-healing integration tests (`@fusion/engine`) — FN-8141-shaped todo
(3 done + 2 skipped + refusal-exhaust/park marker) is NOT promoted and
emits the no-action event exactly once (deduped across a second cycle);
same task after a fresh clean execution IS promoted; stuck-in-progress
variant covered:
```
pnpm --filter @fusion/engine exec vitest run src/__tests__/self-healing.test.ts -t "recoverCompletedTasks|recoverStrandedCompletedTodoTasks|FN-8141"
Test Files 1 passed (1) Tests 14 passed | 382 skipped (396)
```
`@fusion/core` builds clean. My engine changes add **zero** new type
errors (verified: all 13 engine build errors are the pre-existing pi-SDK
cluster in `auth-storage.ts`/`pi.ts`/`provider-registration.ts`, none in
`self-healing.ts`/`run-audit.ts`/`executor.ts`/the new file).
## Known environmental blocker
`pnpm verify:fast` cannot go green on this branch: the `@fusion/engine`
build is **already broken at baseline** (confirmed by stashing all my
changes) by the pi 0.80.x SDK migration errors
(`ModelRegistry`/`AuthStorage`/`ModelRuntime`) — the exact FN-8145
upstream breakage described in the FN-8141 incident. That is out of
scope for this task and independent of this diff. Likewise, the 22
pre-existing
`restart.integration.test.ts`/`executor-fast-mode-workflows.test.ts`
failures are identical with and without my changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus <noreply@anthropic.com>
|
||
|
|
9a37415887 |
fix(engine): add honest blocked exit to fn_task_done so impossible tasks park failed instead of laundering to done (#2256)
## What & why
FN-8141 ("Update pi SDK to latest and verify Kimi K3 end to end") was
impossible as specced — pi 0.80.x removed `AuthStorage`/`ModelRegistry`
APIs, so every SDK bump broke the build. The executor correctly reverted
its work and filed follow-up FN-8145 — but had **no sanctioned way to
end the task in a blocked state**. `fn_task_done` only expressed
success: the bulk-completion gate refused it, the requeue budget re-ran
the doomed task 5 times, and the only remaining affordance (mark every
step `skipped`, then complete) made `isTaskComplete()` return true.
Self-healing then promoted the "complete" todo to in-review and the AI
merger finalized the empty diff as `done`. **The honest path must be
cheaper than the laundering path.**
This adds a first-class **blocked** outcome to the executor's
`fn_task_done` tool.
## Change
- `fn_task_done` gains `outcome: "completed" | "blocked"` (default
`"completed"`), optional `blockedBy: string[]`, and `reason` (required
when blocked).
- `outcome="blocked"` runs **before** every completion gate (completion
blocker, verdict providers, worktree invariants, bulk-completion
refusal) — blocked is not a completion claim, so none of those gates
apply.
- Parks the task `failed` with `error = "BLOCKED: <reason>"`, following
the FN-7863 `EXECUTION_DISPATCH_LOOP_EXHAUSTED` park convention: **steps
keep their true statuses** (no auto-done, no auto-skip), worktree/branch
preserved. It does **not** call `onDone()`, so the executor's existing
`status === "failed"` post-loop branch honors the park instead of
handing off to review.
- `blockedBy` is recorded as real `task.dependencies` edges (unioned
with existing) so the task requeues behind the blocker.
- Emits run-audit `task:execution-blocked-parked` with ids/outcomes-only
metadata (`taskId`, `blockedBy` ids, `hasReason` boolean — **never** the
reason prose).
- Executor + core prompt guidance and the
`bulk-step-completion-without-review` refusal message now name the
blocked exit as **the** correct action when work cannot proceed,
replacing skip-and-done. `PREMISE STALE:` skip guidance is preserved for
genuinely-stale premises.
## Surface enumeration
- **fn_task_done tool schema + handler**
(`packages/engine/src/executor.ts`): blocked branch added at the top of
`execute`, before all gates.
- **Refusal/requeue machinery**: `formatTaskDoneRefusal` for
`bulk-step-completion-without-review` now points at the blocked exit;
the requeue-budget path is untouched (blocked never enters it).
- **Executor prompt text**: turn-ending rules, the "Cannot proceed"
section, the preflight/stale-premise escape hatch (now explicitly
distinguishes stale-premise skip from blocked).
- **Core prompt mirror** (`packages/core/src/agent-prompts.ts`): same
turn-ending + cannot-proceed guidance.
- **Tool reference doc**
(`packages/cli/skill/fusion/references/engine-tools.md`): `fn_task_done`
params updated. (grep for `fn_task_done` confirmed the only executable
tool schema is in executor.ts; CLI/pi surfaces re-export it, no separate
schema copy.)
- **Self-healing**: verified a blocked-parked row is NOT auto-recovered
by `recoverStrandedCompletedTodoTasks` — its steps are not all
done/skipped and `task.error` is set (both are hard filters in the
sweep).
- **Run Audit inventory** (`AGENTS.md`): documented the new event.
## Test evidence
New `packages/engine/src/__tests__/executor-task-done-blocked.test.ts`
(8 tests) asserts the invariant across surfaces:
```
pnpm --filter @fusion/engine exec vitest run \
src/__tests__/executor-task-done-blocked.test.ts \
src/__tests__/executor-task-done-invariant.test.ts \
src/__tests__/gating-classifications.test.ts \
src/__tests__/reliability-interactions/execute-requeue-loop-guard.test.ts --reporter=dot
→ Test Files 3 passed | Tests 138 passed (0 failed)
```
Coverage: blocked parks failed with `BLOCKED:` error and does **not**
trip the bulk-completion refusal or requeue to todo; `blockedBy` unioned
into `dependencies`; `task:execution-blocked-parked` emitted with
metadata that excludes the reason prose; steps left untouched; empty
`reason` rejected without parking; `completed` outcome unchanged (still
marks steps done, no blocked audit); and
`recoverStrandedCompletedTodoTasks` never promotes a blocked-parked row.
### Note on `pnpm verify:fast`
`verify:fast` currently fails at the workspace build step due to
**pre-existing** type errors in `packages/engine/src/auth-storage.ts`,
`pi.ts`, and `provider-registration.ts` — the exact FN-8142 pi SDK API
break that FN-8145 will fix. These are present on the base branch and
untouched by this PR. Verified instead that this change introduces
**zero** new type errors (`tsc` diff before/after, engine and core both
clean) and that all scoped tests are green.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus <noreply@anthropic.com>
|
||
|
|
5a60643c0a |
FN-8142: migrate auth storage and model runtime to pi SDK
Migrate Fusion's credential and model integrations to pi SDK 0.80.8+. - Replace legacy AuthStorage initialization with a locked Fusion credential store and ModelRuntime-backed registry. - Wire asynchronous model initialization and refresh through CLI, desktop, dashboard, executor, and provider paths. - Update provider, routing, and registry tests for the new SDK contracts. Files changed: packages/cli/src/commands/__tests__/daemon.test.ts | 2 +- .../cli/src/commands/__tests__/dashboard.test.ts | 9 +- .../cli/src/commands/__tests__/onboard.test.ts | 1 + packages/cli/src/commands/__tests__/serve.test.ts | 2 +- packages/cli/src/commands/daemon.ts | 19 +- packages/cli/src/commands/dashboard.ts | 20 +- packages/cli/src/commands/onboard.ts | 6 +- packages/cli/src/commands/serve.ts | 19 +- packages/cli/src/commands/startup-model-sync.ts | 4 +- packages/core/src/__tests__/openai-models.test.ts | 17 +- ...-model-routes-openai-codex-supplemental.test.ts | 17 +- ...register-model-routes-zai-real-registry.test.ts | 15 +- packages/dashboard/src/routes.ts | 12 +- .../dashboard/src/routes/register-model-routes.ts | 2 +- packages/desktop/src/local-runtime.ts | 2 +- packages/desktop/src/local-server.ts | 2 +- .../custom-providers-openai-completions.test.ts | 16 +- .../custom-providers-openai-responses.test.ts | 16 +- .../engine/src/__tests__/executor-test-helpers.ts | 2 +- .../src/__tests__/pi-create-fn-agent.test.ts | 8 +- .../engine/src/__tests__/pi-layers-wiring.test.ts | 2 +- packages/engine/src/__tests__/pi.test.ts | 47 ++--- .../src/__tests__/provider-registration.test.ts | 17 +- packages/engine/src/auth-storage.ts | 218 ++++++++++++++++++--- packages/engine/src/custom-provider-registry.ts | 14 +- packages/engine/src/executor.ts | 15 +- packages/engine/src/pi.ts | 50 +++-- packages/engine/src/provider-auth.ts | 58 +++--- packages/engine/src/provider-registration.ts | 16 +- 29 files changed, 421 insertions(+), 207 deletions(-) Fusion-Task-Id: FN-8142 Fusion-Task-Lineage: 8ae79064-7820-4976-9645-9431b5a3129e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ca7a5a7106 |
FN-8144: remove workspace worktrees on archive
Archive workspace task worktrees synchronously and safely across archive entry points. - Add store-scoped workspace disposal planning, reservations, and quarantine handling. - Install baseline and executor disposers that remove per-repository worktrees and branches without shell interpolation. - Cover disposal-plan deduplication and document the archive cleanup behavior. Files changed: .../fn-8144-archive-removes-workspace-worktrees.md | 7 ++ AGENTS.md | 1 + docs/task-management.md | 4 + .../archive-removes-workspace-worktrees.test.ts | 59 +++++++++++ packages/core/src/archive-worktree-disposer.ts | 52 ++++++++++ packages/core/src/index.gate.ts | 8 ++ packages/core/src/index.ts | 8 ++ .../core/src/task-store/archive-lifecycle-2.ts | 29 ++++-- packages/core/src/task-store/archive-lifecycle.ts | 114 ++++++++++++++++++++- .../src/archive-worktree-disposer-install.ts | 27 ++++- packages/engine/src/executor.ts | 25 ++++- 11 files changed, 319 insertions(+), 15 deletions(-) Fusion-Task-Id: FN-8144 Fusion-Task-Lineage: 1c4b65f3-a1d2-4a5c-a4b6-c263f9e6f61d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f57dfc03b6 |
FN-8105: remove archived task worktrees safely
Archive task worktrees through a store-scoped, race-safe disposal lifecycle. - Reserve pinned worktree paths during archive cleanup and successor creation. - Reconcile quarantined removals before reusing a pinned path. - Gate PostgreSQL archival before destructive worktree disposal and wire CLI cleanup. Files changed: .changeset/fn-8105-archive-removes-worktree.md | 7 + docs/task-management.md | 4 + .../extension-experiment-finalize.test.ts | 1 + .../src/__tests__/extension-fn-secret-get.test.ts | 1 + .../extension-gitlab-tracking.test.ts | 1 + .../cli/src/__tests__/extension-web-fetch.test.ts | 1 + .../task-command-github-import-tracking.test.ts | 1 + packages/cli/src/commands/__tests__/task.test.ts | 1 + packages/cli/src/commands/task.ts | 8 +- packages/cli/src/extension.ts | 4 + .../__tests__/worktree-path-reservation.test.ts | 58 ++++++++ packages/core/src/archive-worktree-disposer.ts | 21 +++ packages/core/src/index.gate.ts | 13 ++ packages/core/src/index.ts | 13 ++ .../core/src/task-store/archive-lifecycle-2.ts | 8 ++ packages/core/src/task-store/archive-lifecycle.ts | 37 +++++ packages/core/src/worktree-path-reservation.ts | 149 +++++++++++++++++++++ .../src/archive-worktree-disposer-install.ts | 18 +++ packages/engine/src/executor.ts | 16 +++ packages/engine/src/index.ts | 2 + packages/engine/src/runtimes/in-process-runtime.ts | 1 + packages/engine/src/worktree-acquisition.ts | 27 +++- 22 files changed, 388 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-8105 Fusion-Task-Lineage: cabb8f52-093f-4986-bfda-2c7601a72579 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d870878a23 |
FN-7998: add executor alternate model escalation
Add opt-in executor escalation after same-model tool-failure retries are exhausted. - Persist escalation settings and one-shot task state across SQLite and PostgreSQL stores. - Retry once on a configured alternate model or scheduler node and audit escalation outcomes. - Expose escalation controls, documentation, translations, migration, and regression coverage. Files changed: .changeset/fn-7998-executor-escalation.md | 7 ++ AGENTS.md | 1 + docs/settings-reference.md | 13 ++- .../core/src/__tests__/settings-defaults.test.ts | 23 ++++- packages/core/src/in-review-stall.ts | 29 ++++++ packages/core/src/index.gate.ts | 3 +- packages/core/src/index.ts | 3 +- packages/core/src/manual-retry-reset.ts | 1 + .../0014_executor_escalation_attempt.sql | 2 + packages/core/src/postgres/schema-applier.ts | 17 ++++ packages/core/src/postgres/schema/project.ts | 1 + packages/core/src/settings-schema.ts | 4 + packages/core/src/store.ts | 2 +- packages/core/src/task-store/persistence.ts | 2 + packages/core/src/task-store/remaining-ops-2.ts | 2 +- packages/core/src/task-store/remaining-ops-3.ts | 2 +- packages/core/src/task-store/remaining-ops-6.ts | 2 +- packages/core/src/task-store/serialization.ts | 1 + packages/core/src/task-store/task-update.ts | 2 + packages/core/src/types.ts | 13 +++ .../dashboard/app/components/SettingsModal.tsx | 12 +++ .../app/components/settings/section-keys.ts | 4 + .../settings/sections/SchedulingSection.search.ts | 36 +++++++ .../settings/sections/SchedulingSection.tsx | 6 ++ .../settings-default-descriptions.test.tsx | 4 + .../__tests__/executor-tool-failure-retry.test.ts | 91 +++++++++++++++++- packages/engine/src/executor.ts | 104 +++++++++++++++++++-- packages/i18n/locales/en/app.json | 8 ++ 28 files changed, 376 insertions(+), 19 deletions(-) Fusion-Task-Id: FN-7998 Fusion-Task-Lineage: bbce767d-c61a-4667-be62-abc0cc54d8be Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
60b6e3e048 |
FN-7996: add configurable executor tool-failure retries
Add bounded, durable same-model retry handling for qualifying consecutive executor tool errors. - Persist retry claims, cursors, and audit markers with PostgreSQL migrations. - Expose project retry count, backoff, and failure threshold settings in the dashboard. - Cover retry, exhaustion, reset, and stale-run safety behavior with tests. Files changed: .changeset/fn-7996-executor-tool-failure-retry.md | 7 + AGENTS.md | 1 + docs/architecture.md | 1 + docs/settings-reference.md | 10 ++ .../executor-tool-failure-retry-claim.test.ts | 17 +++ .../core/src/__tests__/manual-retry-reset.test.ts | 3 + .../core/src/__tests__/settings-defaults.test.ts | 15 +- packages/core/src/in-review-stall.ts | 20 +++ packages/core/src/index.gate.ts | 6 + packages/core/src/index.ts | 6 + packages/core/src/manual-retry-reset.ts | 3 + .../0013_executor_tool_failure_retry.sql | 4 + packages/core/src/postgres/schema-applier.ts | 17 +++ packages/core/src/postgres/schema/project.ts | 3 + packages/core/src/settings-schema.ts | 3 + packages/core/src/store.ts | 10 +- packages/core/src/task-store/persistence.ts | 7 + packages/core/src/task-store/remaining-ops-2.ts | 2 +- packages/core/src/task-store/remaining-ops-3.ts | 2 +- packages/core/src/task-store/remaining-ops-6.ts | 65 ++++++++- packages/core/src/task-store/serialization.ts | 3 + packages/core/src/task-store/task-update.ts | 6 + packages/core/src/types.ts | 16 +++ .../dashboard/app/components/SettingsModal.tsx | 15 ++ .../app/components/settings/section-keys.ts | 3 + .../settings/sections/SchedulingSection.search.ts | 27 ++++ .../settings/sections/SchedulingSection.tsx | 4 + .../settings-default-descriptions.test.tsx | 3 + .../__tests__/executor-tool-failure-retry.test.ts | 160 +++++++++++++++++++++ packages/engine/src/executor.ts | 87 ++++++++++- packages/i18n/locales/en/app.json | 6 + 31 files changed, 523 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-7996 Fusion-Task-Lineage: d1682ef8-534c-410e-b74c-1f2cf176eac2 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |