4f037679ad788136301ac52901afbd4266ff027e
737 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4f037679ad |
feat: planner overseer session advisor (OMP advisor parity) (#2082)
## Summary Adds a **session advisor** to the planner overseer so Fusion can review live executor transcripts the way [oh-my-pi’s advisor](https://github.com/can1357/oh-my-pi/tree/main/packages/coding-agent/src/advisor) does — without replacing the existing lifecycle supervisor (stage watch, retry, merge confirmation, human-control withhold). ### What ships - **Emission guard** (`OverseerEmissionGuard`) — content-free phrase filter, session dedupe with severity-rank escalation, one accept per advisor update - **Session delta runtime** — queues agent-log deltas, drains through an advisor agent, drops backlog after 3 failures - **Session advisor service** — model gate, level matrix (`observe` / `steer` / `autonomous`), human-control re-check at inject, `[session-advisor]` steering comments - **OVERSEER.md / WATCHDOG.md** discovery for project review priorities - **AgentLogger `onEntriesFlushed`** + poll-backed agent-log cursor for durable deltas - Workflow settings: `plannerOverseerAdvisorProvider` + `plannerOverseerAdvisorModelId` (both required; empty = soft-disabled for cost safety) - Docs + changeset ### What does not ship (deferred) - Multi-advisor YAML roster, mutating advisor tools, reviewer/merger shadowing, true tool-abort interrupt ### Plan `docs/plans/2026-07-13-001-feat-overseer-advisor-parity-plan.md` ## Enablement 1. Set workflow **Session advisor model provider** + **Session advisor model id** 2. Oversight level `observe` (log only), `steer`, or `autonomous` (inject) 3. Optional: add `OVERSEER.md` or `WATCHDOG.md` in the project ## Test plan - [x] `pnpm --filter @fusion/core exec vitest run src/__tests__/overseer-emission-guard.test.ts` - [x] `pnpm --filter @fusion/engine exec vitest run` overseer-* unit tests (21 tests) - [x] Related planner-overseer / intervention regression tests - [x] `@fusion/engine` + `@fusion/core` typecheck - [ ] Manual: configure advisor model, run an executor task, confirm `[session-advisor]` inject + timeline metadata when concern is raised ## Residual Review Findings None from autofix pass (log-cursor ordering fix already committed). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an off-by-default “session advisor” that can review live execution activity and provide severity-based guidance. * Added project and per-task controls to enable it, including a default enable switch and Quick Add / Task Detail toggles. * Enhanced advisor prompting by discovering and incorporating `OVERSEER.md`/`WATCHDOG.md` review files. * **Documentation** * Added architecture and settings documentation for the new session-advisor parity behavior. * **Bug Fixes** * Improved fail-soft handling so advisor behavior won’t disrupt execution. * Fixed concurrent PostgreSQL migration startup failures. * **Tests** * Added coverage for advice parsing, emission guarding, runtime behavior, and watchdog discovery. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
6aff4958ad |
fix(FN-7952): finish async workflow selection cutover
Use PostgreSQL workflow selections in the dashboard TUI, authoritative driver, and graph-runner adapter so migrated tasks cannot silently fall back to the coding workflow. |
||
|
|
2d61976df0 |
fix(FN-7952): restore runtime state after PostgreSQL migration
Route workflow selections, model lanes, goals, skills, and reliability reads through project-scoped async stores. Recover heartbeat agents parked against an unrelated project model and preserve workflow JSONB patches atomically. |
||
|
|
278ede9dfa |
fix(FN-7952): recover provider failures without retry loops
Preserve authenticated CLI usage after migration, surface OAuth remediation, and use a single distinct model fallback before parking permanent failures. Keep transient credential errors retryable and confirm each OAuth expiry notification independently. Fusion-Task-Id: FN-7952 |
||
|
|
30a83f21fc |
fix(engine): requeue stale assistant continuations (#2095)
## Summary - detect persisted executor sessions that cannot continue from an assistant message - clear the stale session pointer after the executor lock is released - requeue the task with workflow progress preserved instead of marking it failed ## Test plan - `pnpm --filter @fusion/engine exec vitest run src/__tests__/executor-step-session.test.ts -t "clears a stale assistant-continuation resume session and requeues without marking the task failed" --project=engine-default --silent=passed-only --reporter=dot` - `pnpm --filter @fusion/engine typecheck` - `pnpm build` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved recovery when an assistant continuation session becomes stale by restarting a fresh session with bounded retries, preserving overall task progress. * Clears invalid persisted session/continuation state and defers requeue until coordination cleanup is safe. * When retries are exhausted, tasks are marked failed and the error callback runs (without routing to review). * **Tests** * Added coverage for stale-session recovery, repeated-stale behavior, correct (or skipped) requeue decisions, and progress/error handling paths. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c15c78feeb |
feat: migrate storage from SQLite to PostgreSQL (#1793)
# Migrate storage from SQLite to PostgreSQL — full dashboard cutover Migrates Fusion's storage layer to the embedded PostgreSQL `AsyncDataLayer` (the default backend) and **completes the satellite-store + feature cutover** so every dashboard and Command Center surface works in PG mode. ## Status — every surface works in embedded-PG mode Verified live against a running embedded-Postgres dashboard (all **200**, zero 5xx) and gate-tested (**23 files / 99 tests** on embedded PG, plus engine-core 294 and ci-shape 63 in the blocking merge gate; core/engine/cli/dashboard typecheck clean). | Area | Surfaces | State | |---|---|---| | Satellite stores | workflows, todos, insights, research, missions, goals, mailbox | ✅ | | Views | artifacts, documents, evals | ✅ | | Command Center | activity, productivity, team, tokens, tools, **workflows**, **github**, **signals**, **plugin-activations**, **live** (all 10) | ✅ | | Run execution | insight generation, research run execution | ✅ (store-path; AI step needs a provider) | | Live updates | SSE push for mission/research/insight events | ✅ | | Workflow editing | create / update / delete / select (+ id counter) | ✅ | | Engine | mission autopilot, incident-signal ingestion, regression storm-guard, agent wake-on-message | ✅ | | Core | tasks, agents, secrets, automations, memory, chat, usage, PRs, git | ✅ | ## Approach Each satellite store gets an `Async<Store>` wrapper exposing the sync store's method names over the existing `async-*-store.ts` helpers; `get<Store>Store()` returns a `Sync | Async` union; consumers `await` (harmless on sync), and engine/CLI paths that can't convert use `instanceof Sync` graceful fallback. Analytics aggregators branch on `"ping" in dbOrLayer` to run schema-qualified raw SQL over `project.*` (snake_case) in PG. Executors/orchestrators/autopilot are await-converted to drive the union store; the async store wrappers extend `EventEmitter` so SSE live-push fires in both backends. Not-yet-ported capabilities degrade gracefully (never 500) and are individually called out in commits. ## Sync with main The branch is kept continuously merged with `main` (currently through FN-7845, 2026-07-12); the earlier "final rebase deferred" note no longer applies. Use **Create a merge commit** (or squash) to land it — GitHub's rebase-merge cannot replay a merge-maintained branch. ## Residual Review Findings Multi-agent code review of the PostgreSQL satellite-store ports (U1–U5) applied 3 safe fixes (see `fix(review): apply autofix feedback`). The following are **real but gated** — recorded here as follow-up work rather than auto-applied. All are SQLite→PostgreSQL **concurrency/atomicity regressions**: the sync stores were immune only by SQLite's single-writer, single-threaded-handler execution; the async ports open multi-await read-modify-write windows. **Reachability is low today** because the execution engines that generate concurrent same-run mutations (insight run executor, research orchestrator/dispatcher) are `instanceof`-gated to sync mode in PG. No process-crash class survived (all engine fallbacks correctly guard the sync store). - **[P1] Research `appendResearchEvent` dual-write is non-atomic** (`packages/core/src/async-research-store.ts`, corroborated: adversarial + reliability). The `research_run_events` insert (own transaction) and the `run.events` jsonb update are separate writes — a crash between them, or two concurrent appends, splits the table count from the jsonb array. **Fix:** perform the seq-insert and the jsonb update in one `layer.transactionImmediate`. - **[P1] Research run terminal-reversion via stale full-row persist** (`async-research-store.ts` `persistResearchRun`/`updateResearchStatus`). Concurrent `PATCH /runs/:id/status` + `POST /runs/:id/events` can revert a terminal run to `running` by overwriting the whole row, bypassing the transition guard. **Fix:** scoped column `UPDATE`s with a `WHERE status …` guard, or optimistic version column. - **[P2] `updateResearchRun`/`updateInsightRun` read-then-write TOCTOU** — concurrent PATCHes last-writer-wins on the lifecycle merge. **Fix:** `SELECT … FOR UPDATE` / enclosing transaction. - **[P2] `upsertRun`/`createRunOrThrowConflict` check-then-create race** (`async-insight-store.ts`) — two callers can each create an "active" run. **Fix:** partial unique index on `(projectId, trigger) WHERE status IN ('pending','running')`. - **[P3] `createResearchRetryRun` return-value divergence** — sync returns the pre-update `queued` snapshot; async returns the reloaded `retry_waiting` run (persisted state is identical). Pick one side for cross-backend parity. - **[P2/perf] Mission `getMissionWithHierarchy`/`getMissionHealth` N+1 fan-out** — O(milestones×slices) sequential round-trips hold one pool slot per request; can starve the pool for large hierarchies. **Fix:** batched/joined reads. - **Testing gaps:** no PG-mode concurrency tests (interleaved status/event mutations), no sync↔async parity assertion for the lifecycle-error codes, and no mission status/health rollup parity test vs the sync `MissionStore`. ~~Out of scope (deferred): AI run *execution* (insight/research) + mission autopilot + live SSE mission events remain sync-gated/degraded in PG mode.~~ **Since ported** — insight/research run execution, mission autopilot, and SSE live push all run on the async layer now, which also makes the concurrency findings above genuinely reachable; they remain open follow-ups. --- ## Update — 2026-07-12: production-readiness hardening & live acceptance Everything below landed on this branch since the description above was written: **Production blockers from review — fixed** - `recoverStaleTransitionPending` ported to the async layer (backend moves write + clear the crash-safe marker; startup/maintenance sweeps no longer throw). - Lost-update class fixed: `atomicWriteTaskJson`/`WithAudit` write changed columns only (full-row upserts silently resurrected stale fields across concurrent store instances — the "task stuck unplanned forever" bug). - First-boot **auto-migration**: booting the PG backend over a project with a legacy `fusion.db` migrates it automatically (loud failure, SQLite kept as backup), and the dashboard shows a one-time **"your data was migrated" banner** with the backup paths and a Need-help Discord link. - `pg_dump`/`pg_restore` discovered from common install locations for embedded-mode backups. - The PG suite is part of the blocking merge gate (`test:pg-gate`). **Multi-project isolation (PR #2007, merged into this branch)** - `project_id` partition key on tasks / archived tasks / config, `taskProjectScope` threaded through every scan/claim/count, per-project config rows, layer bound to the project at startup. - Review P1 follow-up: the shared cold-storage `archive.archived_tasks` table is also partitioned and all archived-board reads/counts/searches are scoped. - Schema drift self-heal generalized to schema-qualified columns so existing databases upgrade in place. **Other changes** - Node settings sync **removed** in PG mode (409 `settings-sync-disabled-postgres`) — nodes share state by connecting to the same database; auth sync kept (per-machine file). - Perf (review findings): `listTasks` pushes column filter + ORDER BY + LIMIT/OFFSET into SQL; `getConversation` capped to the most recent 200 messages. - Fixed a false "operator action required" pause-abort log fired on every successfully auto-merged task. **Live acceptance — PASSED (2026-07-12)** A sandboxed instance (isolated HOME, embedded PG, real Opus executor) ran a task through the complete cycle: create → triage (AI spec) → execute → in-review → AI squash-merge landed on the project's `main` → done. A write+read sweep of every data surface (settings, comments, documents, attachments + artifact bridge + artifact edit, chat with real generation, goals, missions, agent mail, secrets, workflows, memory, CC analytics) was green on embedded PG. **Known remaining work** - The per-project `config` PK re-key has no upgrade path for pre-isolation embedded-PG databases (needs a real `DROP CONSTRAINT`/re-key migration; fresh databases are fine). - `pg_dump`/`pg_restore` binaries are not yet bundled in release artifacts (PATH/common-location discovery only). - The satellite-store concurrency findings listed above. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Phil Larson <hello@phillarson.xyz> Co-authored-by: fusion-merge <fusion-merge@local> |
||
|
|
316d4fa034 |
FN-7941: anchor execute-requeue loop guard to monotonic terminal-step progress
Hardens the FN-7863 execute-node self-requeue loop guard so residual execute_loop_stall cases (#2043/#2045/#2046/#2047) can no longer reset the loop counter forever via non-terminal signature drift. - Change buildExecuteRequeueLoopSignature to track terminal step count (done/skipped) plus total step count instead of raw currentStep + every step status, so pending/in-progress oscillation no longer produces a "new" signature each cycle. - Add buildExecuteRequeueLoopHighWaterSignature, which derives current terminal-step progress via the shared signature parser (parseExecuteRequeueLoopProgressSignature) and only resets the streak on monotonic forward progress, keeping a high-water mark across cycles so decreases/oscillation below the high-water still count toward exhaustion. - Update executor.ts's execute self-requeue dispatch path to use the new high-water helper when deciding whether to reset (1) or increment executeRequeueLoopCount, replacing the previous raw signature-equality check. - Extend execute-requeue-loop-guard.test.ts with regression coverage: a drifting-signature case that oscillates step order/status with no terminal progress (still terminalizes at MAX_EXECUTE_REQUEUE_LOOP_CYCLES), a done/in-progress oscillation case bounded after the high-water stops increasing, and an updated "real progress never terminalizes" case driven by genuine monotonic done-step advancement. - Update docs/architecture.md's FN-7863/FN-7926 self-healing notes to describe the new terminal-step high-water signature and cross-reference FN-7941. Files changed: docs/architecture.md | 4 +- .../execute-requeue-loop-guard.test.ts | 83 +++++++++++++++++++++- packages/engine/src/executor.ts | 54 ++++++++++++-- 3 files changed, 130 insertions(+), 11 deletions(-) Fusion-Task-Id: FN-7941 Fusion-Task-Lineage: cbf1e536-d29b-40da-bdd8-8c34d8d6b1ca Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
9ba8a2e575 |
FN-7932: add per-lane Reviewer and Planning thinking-level overrides
Adds validatorThinkingLevel and planningThinkingLevel task fields so the Reviewer and Planning AI lanes can override reasoning effort independently of the shared task thinkingLevel, with dashboard UI, storage, and runtime fallback wiring. - Add validatorThinkingLevel and planningThinkingLevel to Task/TaskCreateInput types (packages/core/src/types.ts) - Persist the new fields in the SQLite schema and store read/write/replication paths (packages/core/src/db.ts, store.ts, mesh-task-replication.ts) - Wire executor and triage lanes to fall back per-lane thinking level -> task.thinkingLevel -> existing settings/lane fallback (packages/engine/src/executor.ts, triage.ts) - Add per-lane thinking-level selectors to the ModelSelectorTab UI, alongside the existing thinking-level control (packages/dashboard/app/components/ModelSelectorTab.tsx) - Expose the new fields through the legacy task API and task-workflow routes (packages/dashboard/app/api/legacy.ts, packages/dashboard/src/routes/register-task-workflow-routes.ts) - Document the new settings in dashboard-guide.md and settings-reference.md - Add a minor changeset and unit/integration test coverage for store persistence, routes, UI, and agent-session helpers Files changed: .changeset/per-lane-task-thinking.md | 7 ++ docs/dashboard-guide.md | 2 + docs/settings-reference.md | 2 +- .../src/__tests__/store-thinking-levels.test.ts | 43 +++++++ packages/core/src/db.ts | 15 ++- packages/core/src/mesh-task-replication.ts | 4 + packages/core/src/store.ts | 24 +++- packages/core/src/types.ts | 12 ++ packages/dashboard/app/api/legacy.ts | 2 + .../dashboard/app/components/ModelSelectorTab.tsx | 126 ++++++++++++++++++++- .../components/__tests__/ModelSelectorTab.test.tsx | 50 +++++++- .../src/__tests__/routes-tasks-ops.test.ts | 74 ++++++++++++ .../src/routes/register-task-workflow-routes.ts | 19 +++- .../src/__tests__/agent-session-helpers.test.ts | 15 +++ packages/engine/src/executor.ts | 16 ++- packages/engine/src/triage.ts | 8 +- 16 files changed, 395 insertions(+), 24 deletions(-) Fusion-Task-Id: FN-7932 Fusion-Task-Lineage: 4202f774-aab9-41d2-86a0-f5277dd0f848 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
6dcecb0c34 |
FN-7926: park completed-but-blocked tasks instead of looping execute-requeue
Stops the execute → pause-abort → re-queue-to-todo infinite loop for tasks whose implementation work is done but a dependency/blockedBy blocker is still live, by diverting them into a dedicated parked state instead of feeding the FN-7863 no-progress backstop or looping forever. - Add TaskExecutor.parkCompletedBlockedTask(): when work is complete but getTaskCompletionBlocker() still reports a blocker, park the task in todo with pausedReason:"completed-work-blocked", status:"queued", preserved worktree/branch/steps, and a cleared execute-requeue signature. - Replace shouldFinalizeCompletedTask's boolean with getCompletedTaskFinalizationDecision() returning "finalize" | "blocked" | "incomplete" so both the paused-after-completion and finalization call sites can react to the new "blocked" outcome without re-entering execution. - Divert completed-but-blocked tasks before the FN-7863 execute-requeue-loop counter increments, so waiting-on-dependency states are no longer misclassified as EXECUTION_DISPATCH_LOOP_EXHAUSTED. - Add SelfHealingManager.reconcileCompletedBlockedTasks(): a bounded sweep (wired into both startup/maintenance and periodic self-healing passes) that clears the park and advances the task to review once getTaskCompletionBlockerForStore() resolves, guarded by auto-merge eligibility, user-pause, and live-execution checks; failed advances re-park rather than strand the row. - Add run-audit mutation types task:completed-blocked-parked and task:completed-blocked-advanced (ids/counts/outcomes-only metadata) plus AGENTS.md/docs/architecture.md entries documenting the new lifecycle. - Extend execute-requeue-loop-guard.test.ts with coverage for the park/advance flow, including the zero-step task edge case. Files changed: AGENTS.md | 1 + docs/architecture.md | 2 + .../execute-requeue-loop-guard.test.ts | 256 ++++++++++++++++++++- packages/engine/src/executor.ts | 85 ++++++- packages/engine/src/run-audit.ts | 4 + packages/engine/src/self-healing.ts | 95 ++++++++ 6 files changed, 432 insertions(+), 11 deletions(-) Fusion-Task-Id: FN-7926 Fusion-Task-Lineage: e47945f4-a816-447e-9ea1-7c13105d0ba9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
1ea185daa5 |
FN-7911: add workflow validate dry-run command, tool, and API route
Adds a non-mutating `fn workflow validate` dry-run path across CLI, agent tools, and dashboard API so custom workflow IR can be checked before create/update. - Add `packages/cli/src/commands/workflow.ts` implementing `fn workflow validate <id> | --file <path>` with JSON/text output, wired into `bin.ts`. - Add `fn_workflow_validate` agent tool (`agent-tools.ts`, `index.ts`) reusing the existing parseWorkflowIr/trait/code-node/column-agent validation used by create/update, performing no persistence. - Add `POST /api/workflows/validate` route in `register-workflow-routes.ts` plus dashboard route test coverage. - Extend heartbeat tool-gating/exposure tests and gating classifications to include `fn_workflow_validate` alongside the other workflow tools. - Update CLI/agent extension docs (`docs/cli-reference.md`, `docs/agents.md`, `docs/workflow-steps.md`, fusion skill references) to document the new command/tool. - Add changeset `.changeset/fn-7911-workflow-validate.md` (minor) describing the new capability. Files changed: .changeset/fn-7911-workflow-validate.md | 7 ++ docs/agents.md | 5 +- docs/cli-reference.md | 13 ++ docs/workflow-steps.md | 3 +- packages/cli/skill/fusion/SKILL.md | 2 +- .../cli/skill/fusion/references/extension-tools.md | 10 ++ .../skill/fusion/references/fusion-capabilities.md | 1 + .../src/__tests__/extension-workflow-tools.test.ts | 1 + packages/cli/src/__tests__/extension.test.ts | 1 + .../src/__tests__/workflow-docs-current.test.ts | 1 + packages/cli/src/bin.ts | 22 ++++ packages/cli/src/commands/workflow.ts | 80 ++++++++++++ packages/cli/src/extension.ts | 10 ++ .../dashboard/src/__tests__/chat-manager.test.ts | 1 + .../dashboard/src/__tests__/chat.rooms.test.ts | 1 + .../planning-document-tools-exposure.test.ts | 1 + .../__tests__/workflow-validate-route.test.ts | 101 +++++++++++++++ .../src/routes/register-workflow-routes.ts | 27 +++- .../engine/src/__tests__/agent-action-gate.test.ts | 2 +- .../agent-workflow-tools-exposure.test.ts | 70 ++++++++++- .../src/__tests__/gating-classifications.test.ts | 3 +- .../src/__tests__/heartbeat-executor.test.ts | 37 +++--- .../src/__tests__/heartbeat-session-prompt.test.ts | 5 +- .../src/__tests__/permanent-agent-gating.test.ts | 2 +- packages/engine/src/agent-heartbeat.ts | 5 +- packages/engine/src/agent-tools.ts | 140 ++++++++++++++++++++- packages/engine/src/executor.ts | 6 + packages/engine/src/gating-classifications.ts | 2 + packages/engine/src/index.ts | 4 + 29 files changed, 532 insertions(+), 31 deletions(-) Fusion-Task-Id: FN-7911 Fusion-Task-Lineage: 903d15fe-a7ec-458f-aa34-8f2e895a9603 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d4bbbcccc6 |
fix: stop Ideas-intake cards from auto-processing and keep replans in the workflow's own planner column
Root cause of the reported incident: store init ran the retired flag-off evacuation on every open, dumping Coding (Ideas) intake cards into triage where they were auto-planned and executed. Init now always runs the workflow-aware integrity pass (with a stale-selection mis-mapping guard and per-pass IR memoization) and evacuation remains toggle-only. Engine rebounds (Plan Review REVISE, stale-spec, fs-validation) resolve a workflow-aware replan column instead of hardcoding triage; needs-replan now counts as unplanned for hold-release dispatch so rejected plans cannot re-execute; triage rediscovers needs-replan todo cards and refinement seed prompts (shared buildRefinementSeedPrompt/isUnplannedSeedPrompt); the fs-validation rebound sets needs-replan so unreadable-prompt tasks re-spec instead of livelocking. Dashboard: the All-workflows board renders column-orphaned tasks instead of silently dropping them (hidden columns stay hidden), and the FN-7591 refetch also fires for present-but-unrepresentable workflow mappings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ee7af2513f |
fix(MAIN-008): address PR review feedback (#2020)
- Label namespaced mcp__* tools as resourceType "mcp" (not "research") so approvals/audit/dedupe keys describe external MCP actions - Guard getTask in resumeApprovalAfterUnwindIfNeeded so deferred resume cannot mask execute() finally outcomes |
||
|
|
555f916ebb |
fix(MAIN-008): complete Step 3 — resume approved MCP calls once
Agent: engineer Fusion-Task-Id: MAIN-008 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
e977fadda9 |
fix(MAIN-008): complete Step 2 — stabilize MCP executor bootstrap
Agent: engineer Fusion-Task-Id: MAIN-008 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
bc30ce8aa1 |
FN-7857: deliver plugin skill bodies to agent sessions and the Skills view
Plugin-contributed skills previously registered only a name for sessions and the dashboard, so their SKILL.md bodies were never actually loaded — fix threads real body paths through to both session creation and the Skills UI. - Resolve each enabled plugin skill's body path via @fusion/core's resolvePluginSkillBodyPath and thread its body dir (plus parent dir) into every session-creating lane (executor primary/retry/verification-fix/step/child-agent, triage, reviewer, merger, agent-heartbeat, cron-runner) as additionalSkillPaths, unioned with existing CE skill dirs. - Add collectPluginSkillNames/mergePluginSkills additionalSkillPaths plumbing in session-skill-context.ts so plugin skill discovery paths flow the same way as native/role-fallback skills. - Update dashboard skills-adapter.ts to read plugin skill SKILL.md and reference files from disk (via the traversal-guarded reader) instead of returning a runtime-placeholder/"not found" response for plugin-sourced skills. - Document the plugin skill body delivery mechanism in docs/PLUGIN_AUTHORING.md. - Add regression coverage: plugin-skill-body-delivery.test.ts, expanded session-skill-context.test.ts and skills-adapter.test.ts. - Add changeset fn-7857-plugin-skill-body-delivery.md (minor, fix). Files changed: .changeset/fn-7857-plugin-skill-body-delivery.md | 7 ++ docs/PLUGIN_AUTHORING.md | 3 + .../dashboard/src/__tests__/skills-adapter.test.ts | 92 ++++++++++++++++------ packages/dashboard/src/skills-adapter.ts | 33 ++------ .../__tests__/plugin-skill-body-delivery.test.ts | 75 ++++++++++++++++++ .../src/__tests__/session-skill-context.test.ts | 84 +++++++++++++++++++- packages/engine/src/agent-heartbeat.ts | 3 +- packages/engine/src/cron-runner.ts | 2 + packages/engine/src/executor.ts | 25 ++++-- packages/engine/src/merger.ts | 10 ++- packages/engine/src/reviewer.ts | 2 + packages/engine/src/session-skill-context.ts | 43 ++++++++-- packages/engine/src/step-session-executor.ts | 5 +- packages/engine/src/triage.ts | 3 +- 14 files changed, 318 insertions(+), 69 deletions(-) Fusion-Task-Id: FN-7857 Fusion-Task-Lineage: 9ba4c305-8b38-4ae8-85b3-4c87205ef767 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
9cfb40e137 |
FN-7863: add bounded execute-node self-requeue loop guard
Bounds the execute->pause-abort->todo dispatch loop so a task can no longer requeue forever with no visible signal or terminal state. - Track a progress-anchored `executeRequeueLoopCount`/`executeRequeueLoopSignature` pair on the task row (current step + step statuses) so slow no-progress requeue cycles are counted independently of the scheduler's wall-clock `dispatchStormCount` guard. - Warn visibly in the task log at `EXECUTE_REQUEUE_LOOP_VISIBLE_THRESHOLD` (3) and terminalize non-paused, non-terminal tasks at `MAX_EXECUTE_REQUEUE_LOOP_CYCLES` (6) with `status:"failed"` and an `EXECUTION_DISPATCH_LOOP_EXHAUSTED:` error, preserving worktree/branch/step progress. - Emit a new `task:execution-dispatch-loop-terminalized` run-audit mutation type with ids/counts/outcomes-only metadata. - Reset the loop counters on real progress, manual retry, forward moves (in-review/done/archived), and unpause, in both the executor and scheduler. - Add DB migration 142 (`executeRequeueLoopCount`, `executeRequeueLoopSignature` columns) plus store read/write/reset plumbing. - Add reliability-interactions coverage for the new loop guard and extend store-persistence tests for the new columns. - Document the new behavior in AGENTS.md and docs/architecture.md. Files changed: AGENTS.md | 1 + docs/architecture.md | 2 + packages/core/src/__tests__/store-persistence.test.ts | 45 +++++ packages/core/src/db.ts | 17 +- packages/core/src/manual-retry-reset.ts | 1 + packages/core/src/store.ts | 22 ++- packages/core/src/types.ts | 11 ++ .../execute-requeue-loop-guard.test.ts | 188 +++++++++++++++ packages/engine/src/executor.ts | 67 +++++++- packages/engine/src/run-audit.ts | 2 + packages/engine/src/scheduler.ts | 8 +- 11 files changed, 355 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-7863 Fusion-Task-Lineage: db40507f-5851-435e-8854-c1ed695b4154 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f23619c2d4 |
fix: preserve user pause across executor pause teardown (FN-7851 pause-bounce loop)
Pausing an in-progress task never stuck: the pause teardown re-queued the row to todo with a plain engine move, and the reopen block wiped paused/pausedByAgentId/pausedReason. The graph-failure classifier then saw an unpaused row, misread the hard-cancel as an engine-internal abort, and auto-continued the session (graphResumeRetryCount 1/2, 2/2); once the budget was exhausted the benign re-queue left the row dispatchable and the scheduler re-dispatched it seconds later — an indefinite pause/resume bounce, burning a fresh worktree + pnpm install per cycle. - store: new moveTask option `preservePause` keeps the pause park across a reopen-to-todo/triage move (flag-ON trait hook + flag-OFF legacy inline, kept in sync). It never SETS a pause, only prevents clearing one. - executor teardown: when the pause that caused the abort is still in force, move with preservePause so the row lands in todo still parked (scheduler skips paused/userPaused rows until explicit unpause). - classifier: a live task pause is labeled operator intent, never "engine abort during pause/resume"; the benign log now says "parked … awaiting explicit unpause" instead of the contradictory "cleared for normal scheduling" for parked rows. Surfaces covered by tests: flag-ON hook (preserve + never-set + default clear), classifier no-auto-continue for task-pause/user-pause/global-pause rows in todo, provenance labels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a8eafbbb14 |
feat: video, HTML mockup, and PDF artifact support end-to-end
Video was registrable but effectively unusable, and HTML/PDF deliverables had no first-class path from agents to the gallery. - media route now serves HTTP byte ranges (Accept-Ranges, 206 + Content-Range, 416 on unsatisfiable) so <video>/<audio> seeking works and Safari plays media at all - video attachments (mp4/webm/mov, 100MB cap vs 5MB for other types) bridge into the artifact registry like images; multer transport ceiling raised to 100MB with per-type caps enforced in the store - fn_artifact_register path payloads are signature-validated for video (ftyp box / EBML header) and PDF (%PDF- prefix), mirroring images - HTML doc artifacts (mimeType text/html) render as live sandboxed iframe previews by default in the doc viewer, with a Preview/Source toggle and the same FileEditor edit mode - executor/heartbeat/planning prompts and tool descriptions now cover the full type matrix: images, videos, audio, HTML mockups, PDFs, and markdown docs, each with the registration recipe Verified live: range requests (200/206/416) via curl, an ffmpeg-generated mp4 playing to completion in the gallery lightbox, and an interactive HTML mockup rendering in the sandboxed preview. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9024f3a639 |
feat: agent-created visual artifacts end-to-end + redesigned category gallery with doc editing
Agents could never get screenshots/wireframes/mocks into the Artifacts view:
fn_artifact_register was gated on assignedAgentId (never set in default
ephemeral mode), the only image payload source was inline base64, and no
prompt ever told agents to register visual deliverables.
- always expose fn_artifact_register to executor sessions ("executor" author
fallback), resolve relative paths against the task worktree, and default
taskId to the executing task (heartbeat task lane too)
- add a `path` payload source: file read with 50MB cap, extension MIME
inference, PNG/JPEG/GIF/WebP signature + SVG sniff validation, persisted
through managed artifact storage
- executor/heartbeat/planning prompts + engine-tools reference now instruct
agents to register screenshots, wireframes, mockups, and recordings
- new ArtifactsGallery: Images/Docs/PDFs/Videos/Audio/Other category sections
and filter chips, visual tile grid + lightbox, embedded PDF viewer, audio
player rows, download rows; mobile-responsive down to the 768px breakpoint
- doc artifacts open a full viewer rendered as markdown by default with an
in-place edit mode using the shared CodeMirror FileEditor; persisted via new
GET/PATCH /api/artifacts/:id + TaskStore.updateArtifact and live-refreshed
through the new artifact:updated SSE event
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
725ce45c5d |
FN-7799: fix false-negative Git repository detection blocking task execution
Replace the boolean isGitRepository() check with a tri-state Git detection so environmental git failures (dubious ownership, missing git binary, timeouts) are no longer misreported as "not a Git repository", which previously blocked all task execution in valid repos and survived engine restarts. - Add detectGitRepository() in worktree-pool.ts returning repo / not-repo / error (with reason: dubious-ownership, git-missing, timeout, unknown), classified from git's stderr; bound the git rev-parse call with a 10s timeout and maxBuffer; keep isGitRepository() as a backward-compatible wrapper - Route the executor dispatch preflight guard through detectGitRepository(): only emit the original "not a Git repository / run git init" fatal on a positive not-repo verdict; on error, throw a distinct accurate error naming the real git failure, including the safe.directory remedy for dubious ownership - Route the in-process runtime startup warning through the same tri-state detection so it only warns "not a Git repository" on a positive not-repo verdict - Add a regression test locking extractWorktreeConflictInfo() to NOT misclassify a dubious-ownership git worktree add failure as not-git-repo - Add targeted tests across worktree-pool, executor-worktree, and in-process-runtime test suites covering repo/not-repo/dubious-ownership/git-missing/timeout classifications on Windows OneDrive-style and POSIX paths - Add changeset and a docs/solutions/logic-errors write-up of the false-negative root cause and fix Files changed: .changeset/fn-7799-git-detection-false-negative.md | 7 +++ .../logic-errors/git-detection-false-not-repo.md | 54 ++++++++++++++++ .../engine/src/__tests__/executor-worktree.test.ts | 61 +++++++++++++++++++ .../engine/src/__tests__/worktree-pool.test.ts | 71 +++++++++++++++++++--- packages/engine/src/executor.ts | 38 +++++++++--- .../runtimes/__tests__/in-process-runtime.test.ts | 53 ++++++++++++++-- packages/engine/src/runtimes/in-process-runtime.ts | 16 ++++- packages/engine/src/worktree-pool.ts | 66 ++++++++++++++++++-- 8 files changed, 334 insertions(+), 32 deletions(-) Fusion-Task-Id: FN-7799 Fusion-Task-Lineage: 25a84283-bf47-472b-8a98-a10bf7e494de Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
fc4acd4d66 |
FN-7794: apply fallback model's own thinking level when swapping in at runtime
Adds fallbackThinkingLevel plumbing so, when Fusion swaps from a primary model to a configured fallback model (executor, validator/reviewer, merger, planning, title-summarizer, heartbeat, and workflow-step lanes), the fallback's own configured thinking level is applied instead of silently reusing the primary lane's level. - Add fallbackThinkingLevel option to AgentRuntimeOptions (agent-runtime.ts), AgentOptions (pi.ts), and ReviewOptions (reviewer.ts) - Add per-lane resolvers: resolveExecutorFallbackThinkingLevel, resolvePlanningFallbackThinkingLevel, resolveValidatorFallbackThinkingLevel, resolveTitleSummarizerFallbackThinkingLevel, resolveMergerFallbackThinkingLevel (agent-session-helpers.ts), each following fallback-provider precedence and falling back to the primary lane/default thinking level when unset - Export new resolvers from packages/engine/src/index.ts - Apply the resolved fallback thinking level in createFnAgent's applyThinkingLevelIfSupported once a session has swapped to the fallback model (pi.ts) - Wire fallbackThinkingLevel through executor session creation (workflow-step, task validator, child-agent, and main executor session paths), merger session creation, and heartbeat session creation - Promote the fallback thinking level alongside the fallback model/provider when the no-visible-key Grok CLI fallback is promoted to primary, so the cleared fallback pair doesn't leave the session on the superseded primary's thinking level - Route workflow-step fallback thinking level by which fallback candidate (validatorFallback vs globalFallback) actually matched - Document fallbackThinkingLevel runtime-swap behavior in docs/settings-reference.md - Add minor changeset for @runfusion/fusion - Add regression tests covering fallback thinking-level resolution and application (agent-session-helpers.test.ts, pi.test.ts) and a shared test helper (executor-test-helpers.ts) Files changed: .changeset/fn-7794-fallback-thinking-level.md | 7 ++ docs/settings-reference.md | 3 + .../src/__tests__/agent-session-helpers.test.ts | 38 ++++++ .../engine/src/__tests__/executor-test-helpers.ts | 23 ++++ packages/engine/src/__tests__/pi.test.ts | 136 +++++++++++++++++++++ packages/engine/src/agent-heartbeat.ts | 3 +- packages/engine/src/agent-runtime.ts | 5 + packages/engine/src/agent-session-helpers.ts | 54 ++++++++ packages/engine/src/executor.ts | 31 ++++- packages/engine/src/index.ts | 5 + packages/engine/src/merger.ts | 7 +- packages/engine/src/pi.ts | 16 ++- packages/engine/src/reviewer.ts | 6 + 13 files changed, 327 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-7794 Fusion-Task-Lineage: c94d621a-ccbd-42b2-9fe6-cb619418ad90 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d80cdd2b3b |
FN-7787: honor assigned agent's runtimeConfig model in task execution sessions
Task execution sessions previously ignored the assigned permanent agent's runtimeConfig model whenever the executor was handed an agents-less worktree AgentStore, silently drifting to the pi runtime's built-in default model instead of the configured one. - Add TaskExecutor.getAuthoritativeAssignedAgent(): falls back to the authoritative project `.fusion` AgentStore when the live executor's worktree AgentStore has no record of the assigned agent, so runtimeConfig resolution matches chat-session behavior. - Replace direct `this.options.agentStore.getAgent(...)` lookups across step-session, workflow-graph, and legacy execution paths with the new authoritative lookup helper. - Warn and audit (`noModelResolved` / `runtimeBuiltInFallbackModel`) when a non-mock, non-test-mode session resolves no provider/model pair and falls back to the runtime's built-in default, so the drift is visible instead of silent. - Add regression tests covering assigned-agent runtime-config resolution and the new runtime-resolved audit fields. - Add changeset (patch) and update docs/settings-reference.md and AGENTS.md. Files changed: .changeset/fuzzy-fable-fallback.md | 7 +++ AGENTS.md | 1 + docs/settings-reference.md | 2 +- .../executor-assigned-agent-runtime-config.test.ts | 68 ++++++++++++++++++++++ .../run-audit-session-runtime-resolved.test.ts | 44 ++++++++++++++ packages/engine/src/agent-session-helpers.ts | 31 +++++++--- packages/engine/src/executor.ts | 43 +++++++++----- 7 files changed, 174 insertions(+), 22 deletions(-) Fusion-Task-Id: FN-7787 Fusion-Task-Lineage: 40fccad5-2e67-4ee2-8199-4548ce9025c6 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
57c3d7ceb8 |
FN-7776: evaluate promptContribution.condition against effective plugin settings
Plugin prompt contributions declared a `condition` field in the SDK, but the host never evaluated it, so gated prompt content always rendered unconditionally. - Add packages/core/src/plugin-prompt-condition.ts implementing a minimal, non-eval `settings["key"] === "value"` / `!==` condition grammar - Wire condition evaluation into plugin-runner.ts / agent-instructions.ts / executor.ts / reviewer.ts / triage.ts / agent-heartbeat.ts so prompt contributions are filtered by effective plugin settings at each call site - Extend plugin-types.ts and core index.ts/index.gate.ts to expose the new evaluator and condition typing - Document the condition grammar in docs/PLUGIN_AUTHORING.md - Add regression tests covering the evaluator and its wiring through plugin-runner and agent-instructions - Add changeset (@runfusion/fusion minor, feature) describing the new gating behavior Files changed: .changeset/fn-7776-prompt-condition.md | 7 ++ docs/PLUGIN_AUTHORING.md | 13 ++- .../src/__tests__/plugin-prompt-condition.test.ts | 90 ++++++++++++++++++++ packages/core/src/index.gate.ts | 6 ++ packages/core/src/index.ts | 6 ++ packages/core/src/plugin-prompt-condition.ts | 51 +++++++++++ packages/core/src/plugin-types.ts | 10 ++- .../src/__tests__/agent-instructions.test.ts | 33 ++++++-- .../engine/src/__tests__/plugin-runner.test.ts | 98 +++++++++++++++++++++- packages/engine/src/agent-heartbeat.ts | 2 +- packages/engine/src/agent-instructions.ts | 6 +- packages/engine/src/executor.ts | 28 +++++-- packages/engine/src/plugin-runner.ts | 64 ++++++++++++-- packages/engine/src/reviewer.ts | 2 +- packages/engine/src/triage.ts | 2 +- packages/plugin-sdk/src/index.ts | 4 + 16 files changed, 385 insertions(+), 37 deletions(-) Fusion-Task-Id: FN-7776 Fusion-Task-Lineage: ba8dcd52-260a-4166-a712-f3dd39b81b15 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
df8ad460af |
FN-7772: add per-lane thinking level for workflow model lanes
Adds a per-workflow-lane thinking-level setting so execution, planning, and review model lanes can each specify their own reasoning-effort/thinking level, threaded through engine phase precedence so lane-specific settings override the workflow default. - Add workflow lane thinking-level settings to builtin workflow settings and settings schema, with new types in core. - Thread lane thinking-level precedence through model-resolution and engine phase execution (executor, step-session-executor, triage, agent-session-helpers). - Surface per-lane thinking-level controls in the dashboard WorkflowSettingsPanel and ProjectModelsSection. - Add/adjust tests for workflow settings, agent-session-helpers, and the dashboard settings panels. - Update settings-reference.md and workflow-steps.md docs. - Add changeset for the new feature (minor). Files changed: .changeset/fn-7772-workflow-lane-thinking.md | 7 ++++ docs/settings-reference.md | 10 ++--- docs/workflow-steps.md | 4 +- .../core/src/__tests__/workflow-settings.test.ts | 41 ++++++++++++++++++++ packages/core/src/builtin-workflow-settings.ts | 27 ++++++++++++- packages/core/src/index.ts | 4 +- packages/core/src/model-resolution.ts | 45 +++++++++++++++++++++- packages/core/src/settings-schema.ts | 3 ++ packages/core/src/types.ts | 6 +++ .../app/components/WorkflowSettingsPanel.tsx | 35 ++++++++++++++--- .../__tests__/SettingsModal.models-auth.test.tsx | 7 +++- .../__tests__/WorkflowSettingsPanel.test.tsx | 31 +++++++++++++++ .../settings/sections/ProjectModelsSection.tsx | 39 ++++++++++++++++--- .../src/__tests__/agent-session-helpers.test.ts | 13 ++++--- .../engine/src/__tests__/executor-test-helpers.ts | 1 + packages/engine/src/agent-session-helpers.ts | 19 +++++---- packages/engine/src/executor.ts | 4 +- packages/engine/src/step-session-executor.ts | 2 +- packages/engine/src/triage.ts | 8 +++- 19 files changed, 264 insertions(+), 42 deletions(-) Fusion-Task-Id: FN-7772 Fusion-Task-Lineage: 70aba3a9-66c2-4bb0-aff9-acabc7b98818 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
235ff4c65e |
FN-7771: add per-node thinking level for workflow model bindings
Adds a per-node thinking-level override (config.thinkingLevel) for workflow IR model bindings so individual workflow nodes can set reasoning effort independently of the global default. - Extend workflow-ir types/schema and workflow-steps-to-ir conversion to carry config.thinkingLevel per node - Wire thinkingLevel through executor and step-session-executor so the engine applies the per-node override during model calls - Add a thinking-level control to WorkflowNodeEditor for authoring per-node overrides in the dashboard - Add/extend tests covering IR round-trip, steps-to-ir conversion, executor model binding, and the WorkflowNodeEditor UI - Document the new setting in docs/workflow-steps.md - Add changeset for @runfusion/fusion (minor) Files changed: .changeset/fn-7771-workflow-node-thinking.md | 7 +++ docs/workflow-steps.md | 10 ++- packages/core/src/__tests__/workflow-ir.test.ts | 42 +++++++++++++ .../src/__tests__/workflow-steps-to-ir.test.ts | 15 +++++ packages/core/src/store.ts | 1 + packages/core/src/types.ts | 9 +++ packages/core/src/workflow-ir.ts | 21 +++++++ packages/core/src/workflow-steps-to-ir.ts | 5 ++ .../app/components/WorkflowNodeEditor.tsx | 42 ++++++++++++- .../__tests__/WorkflowNodeEditor.test.tsx | 73 ++++++++++++++++++++++ .../engine/src/__tests__/executor-test-helpers.ts | 5 ++ .../__tests__/executor-workflow-step-model.test.ts | 31 +++++++++ .../src/__tests__/workflow-step-review.test.ts | 53 ++++++++++++++++ packages/engine/src/executor.ts | 61 ++++++++++++++++-- packages/engine/src/step-session-executor.ts | 12 +++- packages/engine/src/workflow-node-handlers.ts | 29 ++++++++- 16 files changed, 404 insertions(+), 12 deletions(-) Fusion-Task-Id: FN-7771 Fusion-Task-Lineage: 5dbe3efb-773d-47db-9412-b740eb1d7745 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
5f14a58d3b |
FN-7770: add per-lane thinking-level overrides for project & global model settings
Adds an optional thinking-effort/reasoning override per model lane in Settings (project and global), resolved with precedence task > lane > global default, and reconciles this work with the already-landed FN-7768 inline thinking-level control on CustomModelDropdown (kept the shared shouldShowThinking/thinkingBadgeLabel implementation to avoid duplicating the selector/badge UI). - Add lane thinking-level settings schema fields and runtime precedence (task > lane > global default) in @fusion/core - Wire per-lane thinking selectors into GlobalModelsSection and ProjectModelsSection via CustomModelDropdown's existing showThinkingLevel/thinkingLevel/onThinkingLevelChange/defaultThinkingLevel props - Resolve merger thinking level from the default lane rather than the title-summarizer lane in engine session helpers/executor/merger/triage - Update settings-reference docs and add a minor changeset for the new lane thinking overrides - Add/expand test coverage: settings-parity, store-settings, settings-sections, agent-session-helpers - Add new i18n key models.options.defaultWithLevel across locales Files changed: .changeset/fn-7770-lane-thinking.md | 7 ++ docs/settings-reference.md | 8 ++ .../core/src/__tests__/settings-parity.test.ts | 17 ++++ packages/core/src/__tests__/store-settings.test.ts | 42 +++++++++ packages/core/src/settings-schema.ts | 14 +++ packages/core/src/types.ts | 16 ++++ .../app/__tests__/settings-sections.test.tsx | 100 ++++++++++++++++++--- .../app/components/CustomModelDropdown.css | 1 + .../dashboard/app/components/SettingsModal.tsx | 37 ++++++++ .../settings/sections/GlobalModelsSection.tsx | 9 +- .../settings/sections/ProjectModelsSection.tsx | 12 ++- .../app/components/settings/sections/context.ts | 2 + .../src/__tests__/agent-session-helpers.test.ts | 36 ++++++++ packages/engine/src/agent-session-helpers.ts | 60 +++++++++++++ packages/engine/src/executor.ts | 14 +-- packages/engine/src/merger-ai.ts | 12 ++- packages/engine/src/merger.ts | 12 +-- packages/engine/src/pr-response-run-ops.ts | 4 +- packages/engine/src/step-session-executor.ts | 3 +- packages/engine/src/triage.ts | 5 +- packages/i18n/locales/en/app.json | 3 +- packages/i18n/locales/es/app.json | 3 +- packages/i18n/locales/fr/app.json | 3 +- packages/i18n/locales/ko/app.json | 3 +- packages/i18n/locales/zh-CN/app.json | 3 +- packages/i18n/locales/zh-TW/app.json | 3 +- packages/i18n/src/resources.d.ts | 3 + 27 files changed, 390 insertions(+), 42 deletions(-) Fusion-Task-Id: FN-7770 Fusion-Task-Lineage: 3418c621-ac99-4cd4-a435-9348da03972f Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
eb377ba831 |
FN-7750: gate shared-branch-group auto-merge exemption on live groups
Fixes autoMerge=false being bypassed for engine-created branch-group member tasks whose branch group had already dissolved/finalized. - Add isLiveSharedBranchGroupMemberIntegration(task, group) in @fusion/core, requiring the branch group's status be "open" before the shared-branch-member exemption bypasses the global/task autoMerge:false hold. - Export the new helper from packages/core/src/index.ts and index.gate.ts. - Thread the live-group check through packages/engine/src/project-engine.ts (allowInReviewMergeProcessing, enqueueEligibleInReviewTasks, merge-confirmed fast-path branch routing, and merge handoff paths). - Add TaskExecutor.isLiveSharedBranchGroupMember helper in packages/engine/src/executor.ts and use it in retryable pre-merge remediation, no-op finalize, benign pause-abort classification, and merge-processing gates. - Keep self-healing.ts's solo no-op finalize predicate on the pure branchContext-shape check (isSharedBranchGroupMemberIntegration) intentionally, so stale shared-group members stay excluded from solo finalize regardless of group liveness. - Add regression tests covering the executor and project-engine auto-merge-hold behavior for stale/dissolved branch groups. - Add a patch changeset documenting the fix. Files changed: .../fn-7750-automerge-hold-stale-branch-group.md | 7 ++ packages/core/src/__tests__/task-merge.test.ts | 42 +++++++++-- packages/core/src/index.gate.ts | 1 + packages/core/src/index.ts | 1 + packages/core/src/task-merge.ts | 13 +++- ...cutor-live-branch-group-auto-merge-hold.test.ts | 85 ++++++++++++++++++++++ .../engine/src/__tests__/project-engine.test.ts | 37 +++++++++- packages/engine/src/executor.ts | 22 ++++-- packages/engine/src/project-engine.ts | 32 +++++--- packages/engine/src/self-healing.ts | 1 + 10 files changed, 214 insertions(+), 27 deletions(-) Fusion-Task-Id: FN-7750 Fusion-Task-Lineage: d61f8847-0b09-49b5-b66a-00018c8738bb Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
786a274ae6 |
FN-7749: fix benign pause/resume abort marking manual merge holds as failed
Fixes tasks in auto-merge-off manual merge hold getting incorrectly marked failed by a benign pause/resume abort, which blocked Merge & Close. - Add isBenignManualMergeHoldPauseAbort classifier in executor.ts: recognizes a hard-cancel pause-abort at a merge-region node while auto-merge is off (or processing is disallowed) as benign, and preserves the in-review row instead of failing/re-enqueueing it. - Clear stale pause-abort status/error and suppress the failure notification when this benign manual-hold case is detected, per FN-5147's no-backward-move/no-reenqueue contract. - Extend self-healing.ts recovery to handle this manual-hold case alongside existing paused-abort recovery paths. - Add/extend tests in merge-node-paused-abort-retryable.test.ts and self-healing-paused-abort-recovery.test.ts covering the new benign classification. - Document the fix in docs/architecture.md. - Add changeset (patch) describing the user-facing fix. Files changed: .changeset/fn-7749-manual-merge-hold-false-failure.md | 7 +++ docs/architecture.md | 4 +- packages/engine/src/__tests__/reliability-interactions/merge-node-paused-abort-retryable.test.ts | 50 +++++++++++++++++---- packages/engine/src/__tests__/self-healing-paused-abort-recovery.test.ts | 49 ++++++++++++++++++++- packages/engine/src/executor.ts | 51 +++++++++++++++++++++- packages/engine/src/self-healing.ts | 23 ++++++++-- 6 files changed, 168 insertions(+), 16 deletions(-) Fusion-Task-Id: FN-7749 Fusion-Task-Lineage: 6d90adc3-6cd9-463d-b9d0-7a5c3069c1a5 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
bab42b40dd |
FN-7736: prevent recovery/oversight from resuming approval-blocked tasks
Introduces a canonical awaiting-approval pause reason and predicate so recovery and oversight paths treat approval-blocked tasks as terminal-until-approved instead of eligible for early rebound. - Add isTaskBlockedOnApproval predicate and canonical "awaiting-approval" pause reason in @fusion/core (store.ts, task-merge.ts, index.ts/index.gate.ts) - Exclude approval-blocked tasks from paused-scope-decay rebound in self-healing.ts - Keep the planner overseer withholding oversight for approval-blocked tasks (overseer-human-control-policy.ts) - Executor and agent-heartbeat now recognize the approval-blocked state and avoid resuming it - Add regression tests across store-persistence, task-merge, overseer-human-control-policy, paused-scope-decay, and self-healing-paused-abort-recovery - Update docs/architecture.md with the new approval-hold invariant - Add changeset fn-7736-approval-hold.md (patch) Files changed: .changeset/fn-7736-approval-hold.md | 7 +++ docs/architecture.md | 64 ++++++++++++++++++++-- .../core/src/__tests__/store-persistence.test.ts | 18 ++++++ packages/core/src/__tests__/task-merge.test.ts | 34 ++++++++++++ packages/core/src/index.gate.ts | 2 + packages/core/src/index.ts | 2 + packages/core/src/store.ts | 18 +++++- packages/core/src/task-merge.ts | 34 ++++++++++++ .../executor-approval-gate-suspend.test.ts | 5 +- .../src/__tests__/heartbeat-executor.test.ts | 5 +- .../overseer-human-control-policy.test.ts | 44 +++++++++++++++ .../paused-scope-decay.test.ts | 44 +++++++++++++++ .../self-healing-paused-abort-recovery.test.ts | 21 +++++++ packages/engine/src/agent-heartbeat.ts | 8 ++- packages/engine/src/executor.ts | 13 ++++- .../engine/src/overseer-human-control-policy.ts | 45 +++++++++++---- packages/engine/src/self-healing.ts | 12 +++- 17 files changed, 351 insertions(+), 25 deletions(-) Fusion-Task-Id: FN-7736 Fusion-Task-Lineage: 67e05b7f-f621-4f9b-bc01-721ff05d715b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
927741a8cf |
FN-7727: persist failed workflow step history across self-healing retries
Preserves prior failed pre-merge review attempts instead of overwriting them when self-healing re-runs a failed workflow step. - Add optional bounded `priorAttempts?: WorkflowStepResult[]` field to `WorkflowStepResult` (capped at `MAX_WORKFLOW_STEP_PRIOR_ATTEMPTS`) - Add shared pure `upsertWorkflowStepResult(existing, incoming, opts?)` helper in `@fusion/core` (packages/core/src/workflow-step-results.ts) - Route the executor graph adapter's `recordWorkflowStepResult` and triage's `recordPlanReviewWorkflowResult` through the new helper so a self-healing recovery re-run snapshots the prior failed/advisory_failure attempt into `priorAttempts` instead of dropping it - Selection logic (self-healing, merge-blocker, progress/timing) is unchanged and still reads only the current entry - Surface prior failed attempts in the TaskDetailModal Summary tab's Workflow results list as a collapsed "previous failed attempts" disclosure - Add core/engine/dashboard tests covering the upsert helper, self-healing recovery snapshotting, and the UI disclosure - Document the behavior in docs/workflow-steps.md - Add changeset for @runfusion/fusion (patch) Files changed: .changeset/fn-7727-persist-failed-step-history.md | 7 ++ docs/workflow-steps.md | 15 +++ .../src/__tests__/workflow-step-results.test.ts | 138 +++++++++++++++++++++ packages/core/src/index.gate.ts | 4 + packages/core/src/index.ts | 4 + packages/core/src/types.ts | 19 +++ packages/core/src/workflow-step-results.ts | 99 +++++++++++++++ .../dashboard/app/components/TaskDetailModal.css | 55 ++++++++ .../dashboard/app/components/TaskSummaryTab.tsx | 42 ++++++- .../TaskSummaryTab.prior-attempts.test.tsx | 89 +++++++++++++ .../clear-terminal-workflow-step-failures.test.ts | 27 ++++ packages/engine/src/__tests__/self-healing.test.ts | 50 ++++++++ ...flow-step-results-self-healing-recovery.test.ts | 115 +++++++++++++++++ packages/engine/src/executor.ts | 29 +++-- packages/engine/src/triage.ts | 14 ++- 15 files changed, 688 insertions(+), 19 deletions(-) Fusion-Task-Id: FN-7727 Fusion-Task-Lineage: 7316fb18-bc92-426d-91f4-b1a4ad41c9b1 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c8fcbec94f |
FN-7717: release active-session locks when a task is archived
Archiving a task from triage/planning/todo (not just in-progress) previously left leaked active-session-registry entries, so a successor task could hit ActiveSessionPathHeldByForeignTaskError and get blocked from Plan Review. - Add an explicit `to === "archived"` branch in the task-move handler that awaits abort of in-flight task work and sweeps any leftover activeSessionRegistry paths for the task, checked before the narrower `from === "in-progress"` branch so direct in-progress→archived transitions are covered too. - Deliberately exclude `to === "done"` / `to === "in-review"` from this sweep since those columns legitimately hold ai-merge / workspace-repo-land merge leases that must survive the transition. - Add regression test coverage for archive releasing active sessions across originating columns. - Add changeset and architecture doc note. Files changed: .../fn-7717-archive-active-session-release.md | 7 + docs/architecture.md | 1 + ...xecutor-archive-releases-active-session.test.ts | 167 +++++++++++++++++++++ packages/engine/src/executor.ts | 35 +++++ 4 files changed, 210 insertions(+) Fusion-Task-Id: FN-7717 Fusion-Task-Lineage: 7cff6821-7bb3-4b75-b502-a26467ca7f51 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f10c39fa0b |
feat: add fn_task_file_scope_add tool so agents can widen their File Scope
Agents that must edit files beyond a task's declared ## File Scope had no
way to keep the scope in sync, so those edits were stranded at merge (the
squash merge is scoped to ## File Scope, and cross-task overlap blocking +
the merge file-scope invariant both read it).
New executor tool fn_task_file_scope_add validates repo-relative
paths/globs with isValidFileScopeEntry, de-dupes against existing scope,
appends them to the ## File Scope section of PROMPT.md, and persists via
store.updateTask({ prompt }) (same validation + task.json/PROMPT.md sync as
fn_task_prompt_write). Registered in the main coding-agent tool list; the
base executor prompt now instructs the agent to call it when editing beyond
the declared scope. Merge-time peer-claim refusal is unchanged and remains
the cross-task backstop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
8ee8f15dc6 |
FN-7675: add agent runtime self-awareness to system prompts
Agents were composing plans (e.g. reboot/wait-and-retry loops) that assumed they could keep acting even after the Fusion platform itself shut down, since prompts never told them they run inside Fusion. This adds a shared, docs-grounded self-awareness preamble prepended to chat, heartbeat, and executor base prompts so agents know their own runtime constraints. - Added FUSION_RUNTIME_SELF_AWARENESS shared preamble in packages/core/src/agent-prompts.ts, exported via packages/core/src/index.ts - Prepended the preamble to the chat system prompt (packages/dashboard/src/chat.ts) - Prepended the preamble to the heartbeat session prompt (packages/engine/src/agent-heartbeat.ts) - Prepended the preamble to the executor base prompt (packages/engine/src/executor.ts) - Updated docs/agents.md and CONCEPTS.md to document the new self-awareness/capability-grounding behavior - Added regression tests across core, dashboard, and engine covering the new prompt content - Added changeset for @runfusion/fusion (minor, fix category) Files changed: .changeset/fn-7675-agent-runtime-self-awareness.md | 7 ++++ CONCEPTS.md | 4 +- docs/agents.md | 17 ++++++++ packages/core/src/__tests__/agent-prompts.test.ts | 41 ++++++++++++++++++++ packages/core/src/agent-prompts.ts | 32 ++++++++++++++- packages/core/src/index.ts | 1 + packages/dashboard/src/__tests__/chat-system-prompt.test.ts | 17 ++++++++ packages/dashboard/src/chat.ts | 6 ++- packages/engine/src/__tests__/executor-prompt.test.ts | 45 ++++++++++++++++++++++ packages/engine/src/__tests__/heartbeat-session-prompt.test.ts | 35 +++++++++++++++++ packages/engine/src/agent-heartbeat.ts | 10 +++-- packages/engine/src/executor.ts | 7 +++- 12 files changed, 213 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-7675 Fusion-Task-Lineage: 126d04a6-2c68-4347-9789-591b274277bf Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
9e5c025113 |
FN-7608: block executors on pending approvals instead of allowing workarounds
Executors could previously treat a pending approval as a normal turn end and go hunt for ungated workarounds instead of stopping. This change makes wait-for-approval a hard suspend point. - wait-for-approval now suspends the in-flight executor session via awaitAbortInFlightTaskWork - Dedupe identical pending approvals so repeated waits don't pile up - Executor prompts now carve out awaiting-approval as a legitimate turn end (agent-prompts.ts) - Extend provisioning-gate and agent-action-gate coverage for the new suspend/carveout behavior - Add changeset (patch) documenting the fix for release notes - Update docs/agents.md and docs/architecture.md to describe the new blocking behavior Files changed: .changeset/fn-7608-awaiting-approval-blocking.md | 7 ++ docs/agents.md | 1 + docs/architecture.md | 1 + packages/core/src/agent-prompts.ts | 5 + .../engine/src/__tests__/agent-action-gate.test.ts | 82 +++++++++++++ .../executor-approval-gate-suspend.test.ts | 128 +++++++++++++++++++++ .../executor-approval-prompt-carveout.test.ts | 61 ++++++++++ packages/engine/src/agent-heartbeat.ts | 13 +++ packages/engine/src/executor.ts | 28 +++++ packages/engine/src/pi.ts | 22 +++- .../sandbox/__tests__/provisioning-gate.test.ts | 29 +++++ packages/engine/src/sandbox/provisioning-gate.ts | 11 ++ 12 files changed, 384 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-7608 Fusion-Task-Lineage: 9e42d8ee-bda7-4ef1-b159-46c2100bbc48 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
44442622c5 |
FN-7609: show gated action payload details on approval requests
Approval cards previously showed only a generic gating message with no visibility into the underlying command/arguments being approved, and repeated pending requests for the same action could pile up as duplicates. - Add GatedActionApprovalDetails component to render the gated command/arguments payload on agent-gating approval cards in MailboxView - Persist approvalDedupeKey in targetAction.context and a payload-bearing summary via buildAgentGatedActionSummary in permanent-agent-gating - Wire agent-heartbeat, executor, and pi to pass through the richer gated-action context/summary - Add changeset (patch) documenting the fix - Update docs/dashboard-guide.md - Add/extend tests: GatedActionApprovalDetails, MailboxView, permanent-agent-gating, pi-create-fn-agent Files changed: .changeset/FN-7609-gated-action-approval-payload.md | 7 ++ docs/dashboard-guide.md | 1 + packages/core/src/types.ts | 8 +++ .../app/components/GatedActionApprovalDetails.css | 50 ++++++++++++++ .../app/components/GatedActionApprovalDetails.tsx | 72 +++++++++++++++++++ packages/dashboard/app/components/MailboxView.tsx | 12 ++++ .../__tests__/GatedActionApprovalDetails.test.tsx | 66 ++++++++++++++++++ .../app/components/__tests__/MailboxView.test.tsx | 41 +++++++++++ .../src/__tests__/permanent-agent-gating.test.ts | 31 +++++++++ .../src/__tests__/pi-create-fn-agent.test.ts | 80 ++++++++++++++++++++++ packages/engine/src/agent-heartbeat.ts | 19 ++++- packages/engine/src/executor.ts | 19 ++++- packages/engine/src/permanent-agent-gating.ts | 53 ++++++++++++++ packages/engine/src/pi.ts | 6 ++ 14 files changed, 461 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-7609 Fusion-Task-Lineage: 80a6bb5b-79f7-4b78-9204-402c2dea6171 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
72b77bf621 |
fix(FN-7561): stop Plan Review replan loop and fix "can't find the plan" reviews
The Plan Review pre-merge gate could loop a task through triage↔plan-review indefinitely (FN-7525 ran 13+ replans overnight with no operator visibility), and its reviewer frequently produced "no PROMPT.md found / data lives in a DB" non-verdicts that fed the loop. Root cause of the non-verdicts: the reviewer runs readonly with cwd set to the task worktree, but the spec lives at project-root .fusion/tasks/<id>/PROMPT.md — outside the worktree — so telling it to "Read PROMPT.md" had it search the wrong tree and give up. Four fixes: 1. Inject the PROMPT.md content (via readTaskArtifact, store-backed) directly into the Plan Review reviewer prompt so the verdict never depends on the agent locating the file. 2. Self-retry a malformed reviewer response once on the primary model when no fallback model is configured, so a single fumbled response gets a second chance instead of feeding the replan loop. 3. A malformed (advisory_failure, no parsed verdict) plan-review result can never trigger a triage replan — it is an infra failure, not a plan defect. 4. Cap the unbounded plan-review replan default at 15 attempts; past the cap it emits a loud halting log entry and leaves the task for a human instead of looping forever. Explicit numeric operator budgets are unchanged. Tests: cap halts at 15 / still replans at 14 / malformed never replans. Existing Plan Review replan and malformed-verdict-gate tests still pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
42bbe58c03 |
FN-7579: add ask-user and exit-gate workflow nodes
Add workflow nodes for mid-flow user reach-out and early exit from a workflow run. - Add `ask-user` IR node kind that reuses the await-input park/resume mechanism and surfaces the question in the task chat for brainstorming/clarification. - Add `exit-gate` IR node kind that terminates the workflow early, with an optional condition. - Wire both node kinds through the engine executor and workflow-node-handlers, including a new exit-gate-runner. - Update the WorkflowNodeEditor palette, node summaries, and node help text for the two new node types. - Extend workflow-flow-mapping to support the new node kinds. - Keep `prompt`+`awaitInput` as a back-compat alias. - Add core/engine/dashboard tests covering the new node kinds. - Document the new nodes in docs/workflow-steps.md. - Add changeset for the new minor feature. Files changed: .changeset/fn-7579-ask-user-exit-gate-nodes.md | 7 + docs/workflow-steps.md | 28 ++++ packages/core/src/__tests__/workflow-ir.test.ts | 120 ++++++++++++++ packages/core/src/workflow-ir-types.ts | 12 +- packages/core/src/workflow-ir.ts | 47 ++++++ .../app/components/WorkflowNodeEditor.tsx | 181 ++++++++++++++++++++- .../app/components/__tests__/node-summary.test.ts | 43 +++++ .../__tests__/workflow-flow-mapping.test.ts | 49 ++++++ .../app/components/nodes/WorkflowNodeTypes.tsx | 14 +- .../dashboard/app/components/nodes/node-help.ts | 24 +++ .../dashboard/app/components/nodes/node-summary.ts | 28 ++++ .../app/components/workflow-flow-mapping.ts | 4 + .../workflow-graph-executor-handlers.test.ts | 115 +++++++++++++ .../src/__tests__/workflow-node-handlers.test.ts | 66 ++++++++ packages/engine/src/executor.ts | 23 ++- packages/engine/src/workflow-node-handlers.ts | 18 +- .../src/workflow-node-runners/exit-gate-runner.ts | 81 +++++++++ 17 files changed, 849 insertions(+), 11 deletions(-) Fusion-Task-Id: FN-7579 Fusion-Task-Lineage: 9a89ff49-200d-4a6c-b97c-15d219349ee5 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
5ad8ec8cb6 |
FN-7528: capture post-task agent performance reflections
Capture deterministic post-task reflection metrics for completed agent tasks. - Add non-LLM task performance capture with duration, touched files/packages, verification scope, and retry/rework metrics. - Wire executor completion paths to fire best-effort reflection capture once per completed task when reflections are enabled. - Extend reflection/run-audit types, docs, changeset, and regression coverage for capture behavior. Files changed: .changeset/fn-7528-task-performance-capture.md | 7 + AGENTS.md | 1 + docs/diagnostics.md | 12 +- .../core/src/__tests__/reflection-store.test.ts | 96 +++++++++ packages/core/src/types.ts | 28 ++- .../engine/src/__tests__/agent-reflection.test.ts | 202 +++++++++++++++++++ .../executor-post-task-reflection-capture.test.ts | 135 +++++++++++++ packages/engine/src/agent-reflection.ts | 215 ++++++++++++++++++++- packages/engine/src/executor.ts | 63 +++++- packages/engine/src/run-audit.ts | 29 +++ 10 files changed, 776 insertions(+), 12 deletions(-) Fusion-Task-Id: FN-7528 Fusion-Task-Lineage: 153090e1-681b-4445-83e8-097bc70dcdb4 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
82493e0f62 |
FN-7488: allow source-free task artifacts to complete
Teach fn_task_done to honor explicit source-free task-artifact contracts without weakening ordinary commit requirements. - Detect PROMPT-declared gitignored .fusion/tasks-only delivery contracts after completed steps. - Keep zero-commit refusals for mixed tracked source, docs, config, test, or changeset scope. - Document the completion contract in executor guidance and architecture notes. - Add regression coverage for allowed source-free artifacts and refused mixed-scope deliveries. - Add a patch changeset for the published CLI package. Files changed: .changeset/fn-7488-source-free-completion.md | 7 ++ docs/architecture.md | 2 +- packages/core/src/agent-prompts.ts | 6 ++ .../__tests__/executor-task-done-invariant.test.ts | 120 +++++++++++++++++++++ packages/engine/src/executor.ts | 61 ++++++++--- 5 files changed, 183 insertions(+), 13 deletions(-) Fusion-Task-Id: FN-7488 Fusion-Task-Lineage: adbf1146-4513-4531-bdd8-ccecbeb42a63 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
0f05156cb7 |
FN-7482: recover retryable review remediation failures
Recover retryable Code Review remediation failures so review tasks do not remain stranded after graph restarts. - Route retryable pre-merge remediation graph failures back through the existing fix-pass handoff when durable failed gate evidence remains. - Let self-healing revive parked Code Review and browser-verification remediation failures while excluding Plan Review replan failures and exhausted numeric caps. - Document the remediation recovery behavior and add targeted executor/self-healing regression coverage. - Add a patch changeset for the published Fusion package. Files changed: .changeset/fn-7482-code-review-remediation.md | 7 ++ docs/workflow-steps.md | 7 +- .../__tests__/executor-graph-requeue-gate.test.ts | 129 ++++++++++++++++++++- packages/engine/src/__tests__/self-healing.test.ts | 129 +++++++++++++++++++++ packages/engine/src/executor.ts | 101 ++++++++++++++++ packages/engine/src/self-healing.ts | 24 +++- 6 files changed, 387 insertions(+), 10 deletions(-) Fusion-Task-Id: FN-7482 Fusion-Task-Lineage: 0f178ab6-308e-4587-b5f3-be4e621799a0 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
85809103cd |
FN-7413: configure agent permissions across lifetimes
Enable explicit capability grants and runtime permission policies for both durable and ephemeral agents. - Persist normalized agent capability grants and leave missing permission policies to inherit project defaults at runtime. - Apply action and tool approval gates to permanent agents, ephemeral agents, and fallback task workers. - Add Agent Detail controls, translations, docs, tests, and a changeset for cross-lifetime agent permissions. Files changed: .changeset/fn-7413-agent-permissions.md | 7 ++ docs/agents.md | 12 ++-- docs/settings-reference.md | 11 ++- packages/core/src/__tests__/agent-store.test.ts | 65 +++++++++++++---- packages/core/src/agent-store.ts | 31 ++++++--- packages/core/src/types.ts | 10 +-- .../dashboard/app/components/AgentDetailView.css | 48 +++++++++++++ .../dashboard/app/components/AgentDetailView.tsx | 81 +++++++++++++++++++++- .../settings/sections/AgentPermissionsSection.tsx | 2 +- .../dashboard/src/__tests__/routes-agents.test.ts | 8 +-- .../src/routes/register-agent-core-routes.ts | 32 ++++++--- .../src/__tests__/heartbeat-executor.test.ts | 14 +++- packages/engine/src/agent-heartbeat.ts | 17 ++--- packages/engine/src/executor.ts | 57 +++++++-------- packages/i18n/locales/en/app.json | 12 +++- packages/i18n/locales/es/app.json | 12 +++- packages/i18n/locales/fr/app.json | 12 +++- packages/i18n/locales/ko/app.json | 12 +++- packages/i18n/locales/zh-CN/app.json | 12 +++- packages/i18n/locales/zh-TW/app.json | 12 +++- 20 files changed, 363 insertions(+), 104 deletions(-) Fusion-Task-Id: FN-7413 Fusion-Task-Lineage: bc004572-bde8-4d33-bb27-e941a5bc8884 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
855061db5f |
fix: harden workflow graph cutover paths and migrate cutover-era tests
Production fixes: - executor.ts: add safeLogEntry() wrapper so synchronous throws from store.logEntry don't abort pause/abort/finalize control flow. - workflow-authoritative-driver.ts: pass built-in auxiliary custom nodes (task-summary nodes, bypassable optional-groups) through as success instead of throwing. Test migrations for graph-native runtime (cherry-picked from closed PR #1869): - executor-prompt: two-party barrier for global-pause disposal test. - executor-task-done-invariant: assert merge-node boundary moveTask. - workflow-graph-merge-region-collapse: updated for merge-region node shapes. - executor-worktree/worktree-liveness/implicit-task-done-budget: graph-aware. - CLI extension tests: shared engine-workflow-authoring-mock helper. - Dashboard/desktop/reliability tests: cutover-aware assertion updates. |
||
|
|
3167dbc839 |
fix: lenient review-verdict parsing + clear stale gate failures on retry
Reviews no longer fail on formatting. Three changes to how reviewer/gate
verdicts are parsed and how retries reset state:
- Approval leniency: a review that clearly approves in prose passes even
without a structured verdict (proseSignalsClearApproval, with a
revise/reject/negated-approval guard so a rejection is never flipped). Any
APPROVE*/APPROVAL verdict token classifies as approved. Shared by the
reviewer/plan-review parser and the code-review/browser-verification gate.
- Prose + trailing JSON: extractJsonObjectCandidates does a string-aware
balanced-brace scan and prefers the last object, so a model that emits
reasoning prose then a trailing {"verdict":...} payload parses correctly.
An explicit "Verdict:" heading/line still takes precedence over an
incidental/example JSON object.
- Malformed handling: executeWorkflowStep retries the fallback model on
malformed output (not just timeout); malformed gate output becomes a
non-blocking advisory (a genuine parsed REVISE still blocks).
- Retry clears prior terminal step failures (incl. optional gate nodes like
code-review) after the task leaves the mergeable in-review column, so a
retry starts clean without an auto-merge race.
Fail-closed merge / PR-review / mission-verification gates are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
40b44e40b9 |
fix: enforce ephemeralAgentsEnabled across the workflow engine
Add TaskExecutor.blockOuterDispatchWhenEphemeralDisabled, gating all three workflow dispatch paths (graph / authoritative / work-engine) on ephemeralAgentsEnabled at the top of execute(). Previously the toggle was enforced only on the legacy scheduler/EphemeralWorkerManager path — whose onTaskStart spawn refusal is a fire-and-forget callback that runs after execution begins — so unassigned tasks reaching execute() off a non-scheduler path still ran. Unassigned tasks are now re-queued for permanent-agent assignment; permanent-agent-bound tasks still run. Adds regression coverage across all three entry points. Also includes the ephemeralAgentsCanCreateTasks project setting (default on) gating fn_task_create for ephemeral callers in both the pi extension and the executor task-worker tool. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
ca88a6c6a2 |
fix: don't flag a task failed while its code-review remediation is still executing
A pre-merge-remediation/plan-replan node (e.g. code-review-remediation) is a fire-and-forget async scheduler with no failure out-edge. When its schedule call can't re-arm (missing rehydrated failureContext after restart, remediation-not-scheduled, or an exhausted rework budget), the failure bubbled out as the terminal graph outcome and handleGraphFailure stamped status:"failed" — surfacing a spurious "Task Failed" even while the previously-scheduled fix/reviewer session was still live. Guard the terminal sink: skip the failed park when the failed node is a remediation node AND a live agent session surface is still registered for the task. Scoped via isRemediationGraphNode (IR workflowAction + built-in node-id fallback) and hasLiveTaskSessionSurface; genuine execute/merge failures and remediation failures with no live session still park failed unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
704e891f57 |
Merge origin/main into feature/fix-triage
Resolves the pnpm-lock.yaml conflict. Main's #1865 (review-checkout routing)
auto-merged cleanly with the completion-summary backstop in executor.ts.
Main independently pinned pi-claude-cli's pi-ai/pi-coding-agent to ^0.80.3
(
|
||
|
|
38841695c8 |
fix: stop triage loop at completion-summary node and i18n object-key crashes (#1863)
Two distinct v0.52.0 regressions reported in issue #1863. 1. Triage loop (engine): the best-effort completion-summary graph node is wired into every built-in workflow with a success-only edge. A thrown handler exception or a failed summary projection write bypassed the advisory `!blocking -> success` coercion, terminated the graph at 'completion-summary', and routeGraphFailureToExecutionResume bounced the in-review task back to todo forever (token usage 0, execution NOT STARTED). The graph executor now degrades a completion-summary node failure to success (ensureWorkflowCompletionSummary still backfills task.summary), with a routeGraphFailureToExecutionResume backstop. Shared isCompletionSummaryNode predicate exported from @fusion/core. 2. i18n object-key crashes (dashboard): three views called t() with keys that resolve to nested objects (taskDetail.executionMode, routing.source, nodes.dockerHost), so i18next returned "returned an object instead of string" and crashed the render. Added leaf label keys across all locales and switched the callers. Tests: engine non-fatal completion-summary regression (fails without the fix), dashboard invariant guard scanning t("literal") callers against real en/app.json, and a Stats-panel reproduction against the real bundle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
87ce37831c | fix(engine): address review checkout routing feedback | ||
|
|
f76d2f3609 | fix(engine): route review via explicit external checkout metadata | ||
|
|
af6e671e72 |
FN-7385: preserve live worktrees with fresh fallback
Preserve active worktree owners by retrying acquisition on a fresh sibling checkout. - Add executor fallback that detects active cleanup refusals and creates bounded sibling branches in fresh generated worktrees.\n- Cover DB-only, same-task workflow-step, existing-branch, and exhausted-suffix conflict paths with regression tests.\n- Document the live worktree conflict fallback and add a patch changeset for the published CLI package.\n\nFiles changed:\n .../fn-7385-active-worktree-fresh-fallback.md | 7 +\n docs/architecture.md | 1 +\n .../__tests__/executor-worktree-conflict.test.ts | 103 +++++++++++++-\n .../engine/src/__tests__/executor-worktree.test.ts | 153 ++++++++++++++++++---\n packages/engine/src/executor.ts | 90 ++++++++----\n 5 files changed, 312 insertions(+), 42 deletions(-) Fusion-Task-Id: FN-7385 Fusion-Task-Lineage: 02c31656-1248-49c0-9063-0750cc8e41c6 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |