70330bcffbf8179a715021434e8e070e0bd2b892
3007 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
587bdfd394 |
FN-7764: add cross-type artifact create/list/view test coverage
Extend artifact test coverage to pin creation, listing, and viewing across every artifact type and payload variant on both the agent/dashboard-chat tool surface and the dashboard artifacts route. - Add a route-level integration test covering list/serve for all artifact types (document, image, video, audio, other) across inline content, uri reference, and binary data payloads, including task-scoped filtering, registry-level (task-less) artifacts, and 404 behavior for uri-only artifacts requested via /media. - Add an engine-level real-TaskStore test exercising fn_artifact_register/list/view (agent tools) and the dashboard-chat artifact tool for every artifact type and content/uri/dataBase64 variant, asserting list and view output correctness. - Factor out shared PNG_IMAGE_BYTES fixture and per-type MIME/binary fixtures to keep new assertions concise. Files changed: .../__tests__/artifacts-route-integration.test.ts | 150 ++++++++++++++++++++- .../src/__tests__/agent-artifact-tools.test.ts | 142 ++++++++++++++++++- 2 files changed, 287 insertions(+), 5 deletions(-) Fusion-Task-Id: FN-7764 Fusion-Task-Lineage: 187b3f0f-d1b4-42fe-9658-1ee67870b524 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
18841d76a0 |
FN-7761: fix Grok CLI auth to use logged-in CLI instead of requiring API key
Packaged fn serve/daemon/dashboard hosts previously failed with a misleading missing-API-key error for grok-cli agents even though the operator was already logged in via the Grok CLI. This fixes routing so those hosts eagerly ensure the bundled Grok Runtime plugin is installed/loaded before session creation, and no longer silently falls back to the key-requiring direct endpoint when no key is visible. - Eagerly ensure the bundled fusion-plugin-grok-runtime in serve, daemon, and dashboard commands before loadAllPlugins() so runtime id "grok" is available on fresh installs without manual plugin-settings setup. - agent-session-helpers.ts: deriveGrokRuntimeHintForNoVisibleKey now throws an actionable error (naming both remediations: install/enable the Grok CLI runtime plugin, or set GROK_API_KEY) instead of silently falling through to the key-requiring pi/openai-completions path when the runtime can't be loaded. - Update docs/grok-cli-contract.md to document the FN-7761 packaged-host wiring and new no-silent-fallback behavior. - Add regression tests for the packaged bootstrap behavior and bundled-plugin install path. - Add changeset for @runfusion/fusion (patch, category: fix). Files changed: .changeset/fn-7761-grok-cli-packaged-routing.md | 7 +++++ docs/grok-cli-contract.md | 19 +++++++++---- .../__tests__/grok-runtime-bootstrap.test.ts | 31 ++++++++++++++++++++++ packages/cli/src/commands/daemon.ts | 17 +++++++++++- packages/cli/src/commands/dashboard.ts | 20 +++++++++++++- packages/cli/src/commands/serve.ts | 19 +++++++++++-- .../__tests__/bundled-plugin-install.test.ts | 17 ++++++++++++ .../src/__tests__/grok-runtime-routing.test.ts | 17 ++++++------ packages/engine/src/agent-session-helpers.ts | 15 +++++++++-- 9 files changed, 142 insertions(+), 20 deletions(-) Fusion-Task-Id: FN-7761 Fusion-Task-Lineage: 3be5f054-965c-4e8a-ad91-6e61d4dc4a42 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2be6040b02 |
FN-7758: route Grok CLI fallback models through the CLI runtime when no API key is visible
Fix Grok CLI 'missing API key' false-positive by extending the no-visible-key routing invariant to configured fallback models, not just the default provider. - deriveGrokRuntimeHintForNoVisibleKey now also triggers when the fallback provider is grok-cli - new applyGrokCliNoKeyRuntimeOptions promotes a grok-cli fallback model into the primary session (stripping the provider-qualified model prefix) instead of leaving it as an unused fallback - docs/grok-cli-contract.md updated to describe the fallback-routing contract - added regression tests in grok-runtime-routing.test.ts, chat-manager.test.ts, and chat-manager-room-hybrid.test.ts - added changeset fn-7758-grok-cli-no-key-routing.md (patch) Files changed: .changeset/fn-7758-grok-cli-no-key-routing.md | 7 ++ docs/grok-cli-contract.md | 29 +++-- .../src/__tests__/chat-manager-room-hybrid.test.ts | 36 +++++++ .../dashboard/src/__tests__/chat-manager.test.ts | 41 +++++++ packages/dashboard/src/chat.ts | 16 ++- .../src/__tests__/grok-runtime-routing.test.ts | 118 +++++++++++++++++++++ packages/engine/src/agent-session-helpers.ts | 36 ++++++- 7 files changed, 266 insertions(+), 17 deletions(-) Fusion-Task-Id: FN-7758 Fusion-Task-Lineage: 6b564b21-50ab-4c3e-b0d7-7fded2091d90 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f7c6f560c0 |
FN-7753: route grok-cli execution through the grok CLI when no Fusion-visible GROK_API_KEY resolves
Route grok-cli model selections through the grok CLI runtime when no Fusion-visible GROK_API_KEY is available. - Add read-only isGrokApiKeyFusionVisible() in packages/core/src/grok-provider.ts, refactored to share user-settings-file reading with hydrateGrokApiKeyFromUserSettings without mutating process.env or logging key material. - In packages/engine/src/agent-session-helpers.ts, auto-derive the existing "grok" runtimeHint when defaultProvider is grok-cli, no key is Fusion-visible, and the grok plugin runtime is registered; explicit runtime hints and mock/test-mode routing remain unchanged, and the provider-qualified model prefix is stripped before handoff. - Normalize provider-qualified model ids (grok-cli/<id>, grok/<id>) in the grok-runtime plugin's runtime-adapter and CLI stream spawn so the concrete model reaches `grok --model`, with the historical grok/default fallback preserved for the no-model path. - Update docs (grok-cli-contract.md, settings-reference.md, plugin README) and add/extend tests covering the new fallback behavior, model normalization, and CLI streaming. - Add changeset fn-7753-grok-cli-no-key-fallback.md (patch, fix). Files changed: .changeset/fn-7753-grok-cli-no-key-fallback.md | 7 ++ docs/grok-cli-contract.md | 83 ++++++++++------ docs/settings-reference.md | 6 +- .../__tests__/grok-provider-user-settings.test.ts | 46 +++++++++ packages/core/src/grok-provider.ts | 39 +++++++- packages/core/src/index.gate.ts | 1 + packages/core/src/index.ts | 1 + .../src/__tests__/grok-runtime-routing.test.ts | 107 +++++++++++++++++++-- packages/engine/src/agent-session-helpers.ts | 52 +++++++++- plugins/fusion-plugin-grok-runtime/README.md | 46 +++++---- .../src/__tests__/cli-stream.test.ts | 70 ++++++++++++++ .../src/__tests__/runtime-adapter.test.ts | 28 ++++++ .../fusion-plugin-grok-runtime/src/cli-stream.ts | 6 ++ .../src/runtime-adapter.ts | 24 ++++- 14 files changed, 443 insertions(+), 73 deletions(-) Fusion-Task-Id: FN-7753 Fusion-Task-Lineage: 30ef7265-1ba9-47fd-8c4e-87b02f6a1d78 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d2c2a4cab1 |
FN-7754: seed OpenAI GPT-5.6 Codex models into pi createFnAgent registry
Wires the GPT-5.6 codenamed OpenAI Codex models (gpt-5.6-luna/sol/terra) into the engine pi model-registry seeding surface, mirroring the dashboard's /api/models supplemental merge so the models are no longer missing from pi. - Call mergeSupplementalOpenAiCodexModels() in createFnAgent (packages/engine/src/pi.ts) alongside the existing Anthropic supplemental merge - Add regression tests covering synthesis of missing GPT-5.6 rows and dedupe against pinned catalog entries - Update docs/settings-reference.md to describe the additive surfacing on both /api/models and the engine/pi registry-seeding path - Add a patch changeset for @runfusion/fusion Files changed: .changeset/fn-7754-openai-gpt-5-6-pi-surface.md | 7 +++ docs/settings-reference.md | 2 +- .../src/__tests__/pi-create-fn-agent.test.ts | 63 ++++++++++++++++++++++ packages/engine/src/pi.ts | 6 +++ 4 files changed, 77 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7754 Fusion-Task-Lineage: b61b6812-c94b-46d8-b187-445ccdd6e4e9 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> |
||
|
|
0e90578122 |
FN-7737: Add file_scope agent permission category with default allow disposition
Introduces a new file_scope sensitive-action category to the agent permission policy model so file-scope-related FN tools are classified and gated distinctly from other categories, defaulting to allowed under the grant-all preset. - Add file_scope to AGENT_PERMISSION_POLICY_ACTION_CATEGORIES in @fusion/core types - Classify FILE_SCOPE_FN_TOOLS in both agent-action-gate and permanent-agent-gating with a uniform preset disposition (no review_gate_bypass-style override) - Update AgentDetailView and AgentPermissionPolicyEditor to surface the new category in the dashboard UI - Add/extend unit tests across core, engine, and dashboard packages covering the new category's resolution, gating, and UI rendering - Update docs/agents.md and docs/settings-reference.md to document the new permission category - Regenerate i18n locale strings (en/es/fr/ko/zh-CN/zh-TW) and resources.d.ts for the new category labels - Add changeset for @runfusion/fusion (minor) describing the new File Scope permission category Files changed: .../fn-7737-file-scope-permission-category.md | 7 + docs/agents.md | 10 +- docs/settings-reference.md | 8 +- .../agent-permission-policy-resolution.test.ts | 13 + .../src/__tests__/agent-permission-policy.test.ts | 45 +++ packages/core/src/types.ts | 7 + .../dashboard/app/components/AgentDetailView.tsx | 2 + .../app/components/AgentPermissionPolicyEditor.tsx | 8 + .../__tests__/AgentPermissionPolicyEditor.test.tsx | 37 +++ .../engine/src/__tests__/agent-action-gate.test.ts | 46 +++ .../src/__tests__/gating-classifications.test.ts | 67 +++++ .../src/__tests__/permanent-agent-gating.test.ts | 41 +++ packages/engine/src/agent-action-gate.ts | 7 + packages/engine/src/gating-classifications.ts | 6 + packages/engine/src/permanent-agent-gating.ts | 6 + packages/i18n/locales/en/app.json | 4 + packages/i18n/locales/es/app.json | 4 + packages/i18n/locales/fr/app.json | 4 + packages/i18n/locales/ko/app.json | 4 + packages/i18n/locales/zh-CN/app.json | 4 + packages/i18n/locales/zh-TW/app.json | 4 + packages/i18n/src/resources.d.ts | 310 +++++++++++++++------ 22 files changed, 550 insertions(+), 94 deletions(-) Fusion-Task-Id: FN-7737 Fusion-Task-Lineage: 7b161fb3-7dd9-4860-aa4d-0cb35f38ea5b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
1fa4a69dde |
FN-7747: derive dashboard authStorage fallback from engine.getAuthStorage()
Fixes desktop provider API keys not persisting when a host wires an engine into createServer() but forgets to pass its own authStorage, which previously caused register-auth-routes.ts to throw "Authentication is not configured". - Add ProjectEngine.getAuthStorage() exposing the OAuth subsystem's raw createFusionAuthStorage() instance - In createServer(), derive options.authStorage from engine.getAuthStorage() when not explicitly provided (mirrors existing engine-derivation pattern for onMerge/automationStore/etc.); explicit authStorage still overrides - Add regression tests covering the fallback-derivation and explicit-override behavior - Add changeset (patch) documenting the fix for @runfusion/fusion Files changed: .changeset/fn-7747-derive-authstorage-from-engine.md | 7 ++ packages/dashboard/src/__tests__/server.test.ts | 119 +++++++++++++++++++++ packages/dashboard/src/server.ts | 28 ++++- packages/engine/src/project-engine.ts | 25 +++++ 4 files changed, 178 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7747 Fusion-Task-Lineage: f8e72b15-d084-4e8d-89db-47453d57b41b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2ff8e2e13e |
FN-7743: detect and recover stalled in-progress executor tasks in overseer
Fix the planner overseer's executor-stage stall detection so hung in-progress tasks get unstuck instead of being reported as progressing forever. - Add configurable stuck-detection: the executor-stage overseer observation now emits signal: "stuck" once an in-progress task has been inactive past a new plannerOverseerExecutorStuckAfterMs threshold, feeding the existing decidePlannerRecovery -> bounded inject_guidance recovery path. - Register the new plannerOverseerExecutorStuckAfterMs setting in builtin-workflow-settings.ts and export it via core index.ts/index.gate.ts. - Preserve human-control withholds (user-paused / approval-blocked / autoMerge-off) taking precedence over stuck detection. - Add/extend tests covering planner-overseer, planner-recovery-controller, planner-recovery, and builtin-workflow-settings-triage. - Document the new setting in docs/architecture.md and docs/settings-reference.md. - Add changeset fn-7743-overseer-executor-stall.md (patch). Files changed: .changeset/fn-7743-overseer-executor-stall.md | 7 + docs/architecture.md | 31 +++++ docs/settings-reference.md | 3 +- .../builtin-workflow-settings-triage.test.ts | 22 ++++ .../core/src/__tests__/planner-recovery.test.ts | 12 ++ packages/core/src/builtin-workflow-settings.ts | 26 ++++ packages/core/src/index.gate.ts | 1 + packages/core/src/index.ts | 1 + .../engine/src/__tests__/planner-overseer.test.ts | 146 +++++++++++++++++++++ .../__tests__/planner-recovery-controller.test.ts | 52 +++++++- packages/engine/src/planner-overseer.ts | 88 ++++++++++++- packages/engine/src/project-engine.ts | 11 +- 12 files changed, 391 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-7743 Fusion-Task-Lineage: 791852a2-5b77-48de-955a-1b3916616dfa 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> |
||
|
|
e4a59f7269 |
fix: remove over-firing triage release-authorization gate
The triage release-authorization gate (FN-6481/FN-6469) false-flagged any spec that merely mentioned release tooling (scripts/release.mjs, pnpm release) and, because non-user sources made the in-band authorization marker inert, stranded ordinary tasks in awaiting-approval with no exit. - Delete triage-release-authorization.ts + its test and the finalizeApprovedTask parking block; release-class specs now flow through triage normally. - Remove the dashboard approve/reject-plan API guards and UI gating so tasks still carrying the legacy awaitingApprovalReason="release-authorization" hold render as ordinary manual plan-approval holds and can be resolved. - Keep the awaitingApprovalReason field + activity label for backward-compat. - Replace the engine gate with agent instruction (AGENTS.md -> Releasing): agents must never run a release from inside a Fusion task. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
d44dbaab15 |
FN-7728: add review_gate_bypass RBAC category for fn_task_bypass_review
Introduces a dedicated review_gate_bypass permission-policy category so operators can govern who may bypass a failed pre-merge review gate independently of ordinary task-mutation permissions. - Add review_gate_bypass as a new sensitive-action category in packages/core/src/types.ts, distinct from task_agent_mutation, with fn_task_bypass_review as its sole example tool - Default review_gate_bypass to require-approval even under the unrestricted preset (stricter than the preset's uniform disposition) in packages/core/src/agent-permission-policy.ts, while approval-required/locked-down already cover it uniformly - Classify fn_task_bypass_review into the new category via a shared REVIEW_GATE_BYPASS_FN_TOOLS set in packages/engine/src/gating-classifications.ts, consumed identically by both evaluateAgentActionGate and the permanent-agent gate to prevent path drift - Render the new category as its own row in the dashboard's project-default and per-agent AgentPermissionPolicyEditor, surfaced in AgentDetailView - Update docs/settings-reference.md and add unit tests across core/engine/dashboard covering the new category, its stricter default, and gate-classification alignment - Add changeset (@runfusion/fusion: minor) documenting the new operator-facing permission category Files changed: .changeset/fn-7728-review-gate-bypass-rbac.md | 7 +++ docs/settings-reference.md | 8 +-- .../src/__tests__/agent-permission-policy.test.ts | 54 ++++++++++++++++++- packages/core/src/agent-permission-policy.ts | 12 ++++- packages/core/src/types.ts | 8 +++ .../dashboard/app/components/AgentDetailView.tsx | 2 + .../app/components/AgentPermissionPolicyEditor.tsx | 8 +++ .../__tests__/AgentPermissionPolicyEditor.test.tsx | 5 ++ .../engine/src/__tests__/agent-action-gate.test.ts | 45 ++++++++++++++++ .../src/__tests__/gating-classifications.test.ts | 63 ++++++++++++++++++++++ .../src/__tests__/permanent-agent-gating.test.ts | 41 ++++++++++++++ packages/engine/src/agent-action-gate.ts | 7 +++ packages/engine/src/gating-classifications.ts | 8 ++- packages/engine/src/permanent-agent-gating.ts | 6 +++ 14 files changed, 266 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-7728 Fusion-Task-Lineage: 100c8563-2897-4d53-9546-5c2faa6ab7d8 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
e5c3ffbb39 |
FN-7725: wire Grok CLI runtime adapter routing end-to-end with tests and docs
Formalizes and tests the existing agent Runtime-mode picker path as the decided Grok CLI routing wiring. - Add FNXC decision note at the extractRuntimeHint seam documenting the Grok CLI routing chain (agent-session-helpers.ts) - Add routing test verifying runtimeHint="grok" resolves through resolveRuntime/resolvePluginRuntime to GrokRuntimeAdapter (grok-runtime-routing.test.ts) - Update docs/grok-cli-contract.md with the wiring decision and documented limitations - Update plugins/fusion-plugin-grok-runtime/README.md with routing guidance - Add changeset for the new opt-in Grok CLI streaming runtime routing feature Files changed: .changeset/fn-7725-grok-cli-routing.md | 7 + docs/grok-cli-contract.md | 106 ++++++-- .../src/__tests__/grok-runtime-routing.test.ts | 275 +++++++++++++++++++++ packages/engine/src/agent-session-helpers.ts | 12 + plugins/fusion-plugin-grok-runtime/README.md | 38 ++- 5 files changed, 414 insertions(+), 24 deletions(-) Fusion-Task-Id: FN-7725 Fusion-Task-Lineage: f5210793-59d0-4a0c-8152-4c5ef61ca737 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
626e00288c |
FN-7720: add operator review-lane bypass for stranded pre-merge review failures
Add a policy-gated review-lane bypass primitive so operators can unstick cards stranded by a failed pre-merge review step (e.g. the no-feedback review-engine defect), without exposing it to agent-driven lanes.
- Add `store.bypassFailedPreMergeReviewStep(id, { reason, actor })` in @fusion/core plus `getLatestFailedPreMergeReviewStep` in task-merge.ts, and new `bypassedBy`/`bypassedAt`/`bypassReason`/`bypassedFromStatus`/`bypassedFromVerdict` fields on `WorkflowStepResult`
- Add operator-only `fn_task_bypass_review` CLI/pi-extension tool; explicitly withheld from executor/reviewer/triage agent tool lists
- Add `POST /tasks/:id/bypass-review` dashboard API route and wire it through `register-task-workflow-routes.ts` and legacy API compatibility layer
- Add dashboard UI affordance (context menu action + task detail modal + right-dock controller wiring) to trigger the bypass with a reason
- Add i18n strings for the bypass action/labels across en/es/fr/ko/zh-CN/zh-TW locales
- Update `gating-classifications.ts` to recognize the bypassed state
- Add unit tests: `store-bypass-review.test.ts`, `task-merge-bypass.test.ts`, extension test coverage, and `useTasks` hook test coverage
- Update docs (`docs/workflow-steps.md`, `docs/dashboard-guide.md`, AGENTS.md, fusion skill references) to describe the new bypass tool/route
- Add changeset `.changeset/fn-7720-review-lane-bypass-primitive.md` (minor)
Files changed:
$(git diff --cached --stat)
Fusion-Task-Id: FN-7720
Fusion-Task-Lineage: 590b020a-ae02-4b51-8189-df8f54bf3044
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
|
||
|
|
e657d3b965 |
FN-7723: add cross-process agent state change notification bus
Adds opt-in cross-process change detection to AgentStore so the engine reacts to CLI-driven agent stop/start mutations promptly instead of waiting for the periodic audit sweep. - AgentStore gains fs.watch-based (with poll fallback) cross-process notification, modeled on TaskStore's existing mechanism - Re-emits existing agent:updated/agent:stateChanged events in the engine process when another process (the fn CLI) mutates an agent row - HeartbeatTriggerScheduler listeners now fire immediately instead of waiting up to 60s for the auditTimerRegistrations sweep; the sweep remains as durable backstop - in-process-runtime.ts wires up the new notification bus - Adds unit tests for agent-store cross-process notifications and heartbeat-scheduler reaction behavior - Updates docs/agents.md and docs/architecture.md - Adds changeset (patch) for @runfusion/fusion Files changed: .changeset/fn-7723-cross-process-agent-notify.md | 7 + docs/agents.md | 1 + docs/architecture.md | 1 + packages/core/src/__tests__/agent-store.test.ts | 177 +++++++++++++++++ packages/core/src/agent-store.ts | 210 ++++++++++++++++++++- .../src/__tests__/heartbeat-scheduler.test.ts | 162 ++++++++++++++++ packages/engine/src/runtimes/in-process-runtime.ts | 30 +++ 7 files changed, 587 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7723 Fusion-Task-Lineage: d3a7fa05-b40d-4388-8e98-140f9d8861c9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
a24b0fac1a |
FN-7721: cap heartbeat worktree-acquisition retries and record exhaustion failures
Bounds durable-agent heartbeat worktree acquisition to a fixed retry count instead of requeuing to todo indefinitely across heartbeat cycles. - Add MAX_HEARTBEAT_WORKTREE_ACQUISITION_RETRIES (3) in agent-heartbeat.ts, reusing Task.recoveryRetryCount as a cross-heartbeat counter (no schema migration) - On cap exhaustion, terminally mark the task status:"failed" with an explanatory error, log the entry, and reopen to todo with preserveStatus so the failed status isn't wiped by reopen-to-todo semantics - Add onTaskAcquisitionExhausted callback wired in in-process-runtime.ts to CentralCore.recordTaskCompletion(taskId, false) so exhausted acquisitions count toward totalTasksFailed - Add regression tests in agent-heartbeat-worktree.test.ts and in-process-runtime.test.ts covering the retry cap and completion recording - Add changeset (patch) and a docs/solutions/logic-errors writeup documenting the investigation and other worktree-collision sub-gaps found not to reproduce on HEAD Files changed: .changeset/fn-7721-worktree-heartbeat-retry-cap.md | 7 ++ docs/solutions/logic-errors/heartbeat-worktree-acquisition-unbounded-requeue.md | 84 ++++++++++++++++++++++ packages/engine/src/__tests__/agent-heartbeat-worktree.test.ts | 58 +++++++++++++++ packages/engine/src/__tests__/in-process-runtime.test.ts | 11 +++ packages/engine/src/agent-heartbeat.ts | 72 ++++++++++++++++++- packages/engine/src/runtimes/in-process-runtime.ts | 12 ++++ 6 files changed, 242 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7721 Fusion-Task-Lineage: caad671c-f360-4c1c-8aaa-5b48fca5a55b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
cda9532c3b |
FN-7718: fix zombie heartbeat timers surviving agent stop/start
Ensures stopping and restarting an agent durably clears its heartbeat timer instead of relying on the later FN-7645 watchdog repair. - HeartbeatTriggerScheduler.auditTimerRegistrations now unregisters lingering timers for non-eligible (stopped/paused/disabled) agents - syncTimerForAgent force-re-arms a stale present timer on a start transition so no orphaned timer entry lingers - Added 308 lines of new heartbeat-scheduler regression tests covering the stop/start zombie-timer scenarios - Added changeset (patch) documenting the fix - Updated docs/agents.md and docs/architecture.md to describe the new invariant Files changed: .changeset/fn-7718-zombie-timer-invalidate.md | 7 + docs/agents.md | 2 + docs/architecture.md | 1 + .../src/__tests__/heartbeat-scheduler.test.ts | 308 +++++++++++++++++++++ packages/engine/src/agent-heartbeat.ts | 49 +++- 5 files changed, 364 insertions(+), 3 deletions(-) Fusion-Task-Id: FN-7718 Fusion-Task-Lineage: fc834ccd-495e-4294-805d-325b4cb536a2 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
a4931a4731 |
FN-7719: derive implicit planning fallback model when no fallback configured
Triage planning-model retries no longer dead-end on "no fallback configured" when a provider primary-model call fails (e.g. a 404 wrapped in a 429 for nvidia/moonshotai/kimi-k2.6). - Add resolveImplicitPlanningFallbackModel() to agent-session-helpers.ts: derives a fallback from the resolved project/global default (execution) model when neither planningFallback*/global fallback* is set, guarding against self-swap and skipping in test mode. - Wire the implicit fallback into TriageProcessor.specifyTask() in triage.ts so a retryable primary planner-model failure swaps once via the derived fallback instead of failing triage outright. - Add unit test coverage in agent-session-helpers.test.ts and triage.test.ts for the new implicit-fallback resolution and its triage integration. - Document the new implicit-fallback behavior in docs/settings-reference.md. - Add a patch changeset for @runfusion/fusion describing the fix. Files changed: .changeset/fn-7719-triage-planning-implicit-fallback.md | 7 + docs/settings-reference.md | 2 + packages/engine/src/__tests__/agent-session-helpers.test.ts | 75 +++++++ packages/engine/src/__tests__/triage.test.ts | 237 +++++++++++++++++++++ packages/engine/src/agent-session-helpers.ts | 41 ++++ packages/engine/src/triage.ts | 31 ++- 6 files changed, 389 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-7719 Fusion-Task-Lineage: 69e797e1-5bac-47f3-8dce-505b9d64d83c 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> |
||
|
|
7dc271027f |
FN-7711: add built-in Grok CLI provider to fix pi model registry lookup
Registers a built-in grok-cli provider so Grok CLI model executions no longer hard-fail with "not found in the pi model registry". - Add packages/core/src/grok-provider.ts: built-in grok-cli provider config (xAI OpenAI-compatible endpoint https://api.x.ai/v1, api openai-completions, apiKey $GROK_API_KEY), mirroring the existing Z.ai provider - Register the provider in packages/engine/src/pi.ts (registerExtensionProviders) and packages/engine/src/provider-registration.ts (seedDashboardProviders) - Wire the provider into CLI entrypoints: packages/cli/src/commands/daemon.ts, dashboard.ts, serve.ts - Export grok-provider from packages/core/src/index.ts and packages/core/src/index.gate.ts - Add unit tests: packages/core/src/__tests__/grok-provider.test.ts, and extend packages/engine/src/__tests__/pi-create-fn-agent.test.ts and provider-registration.test.ts - Document the new provider in docs/settings-reference.md - Add changeset .changeset/fn-7711-grok-cli-model-registry.md (patch, category: fix) Note: Grok CLI binary remains discovery/probe only; GrokRuntimeAdapter streaming is a stub (tracked follow-up). Files changed: .changeset/fn-7711-grok-cli-model-registry.md | 7 + docs/settings-reference.md | 2 + packages/cli/src/commands/daemon.ts | 4 + packages/cli/src/commands/dashboard.ts | 4 + packages/cli/src/commands/serve.ts | 4 + packages/core/src/__tests__/grok-provider.test.ts | 130 ++++++++++++ packages/core/src/grok-provider.ts | 224 +++++++++++++++++++++ packages/core/src/index.gate.ts | 7 + packages/core/src/index.ts | 7 + .../src/__tests__/pi-create-fn-agent.test.ts | 78 ++++++- .../src/__tests__/provider-registration.test.ts | 4 +- packages/engine/src/pi.ts | 4 + packages/engine/src/provider-registration.ts | 4 + 13 files changed, 476 insertions(+), 3 deletions(-) Fusion-Task-Id: FN-7711 Fusion-Task-Lineage: ae90b54f-206e-46fd-8365-b0a4488ceb84 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>
|
||
|
|
7f2e34f5b3 |
test(FN-7690): reconcile anthropic-compatible apiType assertions + de-slow retry test
FN-7690 changed resolveApiType() to return the registered pi-ai key "anthropic-messages" for anthropic-compatible providers (the bare "anthropic" key is never registered and throws at stream time), but left behind a stale JSDoc and a stale test expectation: - custom-provider-registry.ts: update the FN-7689 buildCustomProviderModels comment that still described the anthropic/anthropic-messages drift as unresolved. - provider-registration.test.ts: assert config.api === "anthropic-messages" (was still asserting the pre-fix "anthropic"). Also de-slow a retry-exhaustion test: the describe uses fake timers with shouldAdvanceTime, so awaiting a 3-retry backoff (1s+5s+15s) burned ~21s of real wall time. Drive the backoff with advanceTimersByTimeAsync instead (Standing Rule: prefer fake timers over real time waits). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
409de31e57 |
fix: stop false Anthropic OAuth expiry notifications when token is valid
The OAuth expiry monitor and validity logger iterated the un-aliased
getOAuthProviders() id `anthropic` and evaluated get("anthropic"), which
can resolve to a stale legacy/supplemental row (e.g. ~/.pi/agent/auth.json)
even when the fresh, actually-used token lives under `anthropic-subscription`.
That fired a false "Anthropic OAuth expired" notification while the real
subscription token had refreshed successfully.
Both surfaces now resolve the freshest of the two aliased ids via a shared
resolveEffectiveOAuthCredential helper (mirroring the refresh scheduler's
getRefreshCandidateIds alias handling), so a live subscription token
suppresses the false alert. Notification throttle/cadence unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
053e34b370 |
FN-7693: add real-store integration test for image artifact register/list/view pipeline
Adds an end-to-end integration test proving the artifact pipeline works against a real TaskStore, not just a mocked one. - New test file exercises createArtifactRegisterTool/createArtifactListTool/createArtifactViewTool bound to a real TaskStore (inMemoryDb, real filesystem writes) instead of a mocked store - Pins the register -> list -> view invariant for a real base64 PNG image artifact, verifying disk persistence, SQLite row fields (type, mimeType, sizeBytes, uri, taskId), and the list/view text surfaces - Pins the invalid-base64-payload rejection path (non-image bytes for an image-typed artifact) to confirm no artifact row is persisted - Pins the empty-state list text for a task with no registered artifacts Files changed: packages/engine/src/__tests__/agent-artifact-tools-real-store-integration.test.ts | 131 +++++++++++++++++++++ 1 file changed, 131 insertions(+) Fusion-Task-Id: FN-7693 Fusion-Task-Lineage: fd3493aa-6fb2-4e18-a735-c4a9d87c9c6c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c74c5f6d67 |
perf(test): fast-forward fake timers in step-session terminal-activity test (was 22.6s real-time wait)
The 'publishes failed terminal workflow step activity' test awaited executeAll()
directly while the executor retried a failing step 3x with sleep() delays. Under
useFakeTimers({ shouldAdvanceTime: true }) those sleeps consumed REAL wall-clock
time (~22.6s locally, ballooning under CI load and busting the shard-2 watchdog).
Fast-forward the retry sleeps via vi.advanceTimersByTimeAsync like sibling retry
tests; the loop now completes in milliseconds.
|
||
|
|
0bfe7e811b | test(engine): opt into FN-7658 auto-archive in verification-followup-dedup additive test | ||
|
|
67cc02750c |
FN-7692: fix misleading merger confirmation copy under active auto-merge
Correct the planner-oversight confirmation messaging so it no longer claims a hard block when the active auto-merge policy will actually advance the merge/pull-request stage unattended. - decidePlannerRecovery accepts an additive, messaging-only `autoMergeWillProceed` flag and picks accurate reason wording (advisory vs. genuine human-approval block vs. neutral/unknown) for merger/pull-request await_confirmation decisions - PlannerRecoveryController.tick threads `allowsAutoMergeProcessing(task, settings)` into decidePlannerRecovery as `autoMergeWillProceed` - project-engine's requestConfirmation steering comment prefix changed from "confirmation required" to neutral "merge checkpoint" so it doesn't contradict the now-accurate reason text - added regression tests in planner-recovery.test.ts and planner-overseer-intervention-wiring.test.ts - added changeset and doc note Files changed: .changeset/fn-7692-merger-confirmation-copy.md | 7 +++ docs/architecture.md | 10 +++- packages/core/src/__tests__/planner-recovery.test.ts | 66 ++++++++++++++++++++++ packages/core/src/planner-recovery.ts | 36 +++++++++++- packages/engine/src/__tests__/planner-overseer-intervention-wiring.test.ts | 37 ++++++++++++ packages/engine/src/planner-recovery-controller.ts | 14 ++++- packages/engine/src/project-engine.ts | 11 +++- 7 files changed, 176 insertions(+), 5 deletions(-) Fusion-Task-Id: FN-7692 Fusion-Task-Lineage: 187684b8-1d24-425d-85d4-627587469908 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7cb76669db |
fix: resolve 3 staff-engineer review findings from #1957 (init_error mislabel, unbounded off-screen polling, duplicate toasts) (#1960)
## Summary A Staff Engineer pre-landing review (Greptile/CodeRabbit) on #1957 (merged) flagged four structural issues. This PR fixes the three that were confirmed still present on `main`; the fourth (an unregistered-rule `eslint-disable-next-line react-hooks/exhaustive-deps` comment) was already fixed in #1957's second commit before merge and needed no further change. 1. **`resolvePluginRuntime()` mislabeled "found but failed to init" as `not_found`.** When a `runtimeHint` plugin registration is found but `pluginContext`/`createRuntimeContext(...)` comes back falsy, the resolver returned `reason: "not_found"` — indistinguishable from "never registered" — defeating the point of a distinct `FallbackReason`. Now returns `reason: "init_error"`. Updated the existing test that wrongly asserted `"not_found"` for this path, and added a new test asserting all three reachable `FallbackReason` values (`not_found`, `init_error`, `factory_error`) are pairwise distinct. 2. **`ActiveAgentsPanel.tsx`/`AgentsView.tsx` hardcoded `isInViewport={true}`.** Every agent card (live-agent header, board card, list card) polled the runtime-fallback endpoint every 30s forever, even scrolled off-screen — unlike `TaskCard.tsx`'s correct `IntersectionObserver`-gated pattern. Both files now thread a real `IntersectionObserver`-backed viewport signal into `RuntimeFallbackBadge`. Added regression tests proving polling stops once a badge instance's `isInViewport` transitions to `false` and resumes once it goes back to `true` (desktop + a mobile-breakpoint variant), plus verified via `tsc --noEmit` for `@fusion/dashboard`. 3. **Toast dedupe was per-hook-instance, not shared.** `useRuntimeFallbackStatus`'s `lastToastedEventIdRef` was a local `useRef`, so the same task rendered simultaneously in two card surfaces (e.g. `ActiveAgentsPanel` + `AgentsView`) fired two separate toasts for one fallback event. Dedupe now lives in module-level shared state (a bounded `Map` keyed by `taskId:eventId`, FIFO-evicted past 500 entries) so a fallback event toasts exactly once across every simultaneously-mounted badge instance for the same task. Added a cross-instance regression test mounting two badges for the same `taskId`/`eventId` and asserting exactly one toast fires. ## Test evidence - `pnpm --filter @fusion/engine exec vitest run src/__tests__/runtime-resolution.test.ts --reporter=dot` — 25/25 pass - `pnpm --filter @fusion/dashboard exec vitest run app/components/__tests__/RuntimeFallbackBadge.test.tsx --reporter=dot` — 11/11 pass - `pnpm --filter @fusion/dashboard run typecheck` — clean - `pnpm --filter @fusion/engine run typecheck` — clean ## Scope Isolated 6-file diff on top of current `main` (`packages/engine/src/runtime-resolution.ts`, `packages/engine/src/__tests__/runtime-resolution.test.ts`, `packages/dashboard/app/hooks/useRuntimeFallbackStatus.ts`, `packages/dashboard/app/components/ActiveAgentsPanel.tsx`, `packages/dashboard/app/components/AgentsView.tsx`, `packages/dashboard/app/components/__tests__/RuntimeFallbackBadge.test.tsx`). No behavior outside the three findings above was touched. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - The desktop dashboard now supports plugin-backed runtime features, improving how plugin-enabled workflows are loaded and run. - Agent cards now pause background fallback polling when they’re off-screen, helping the dashboard feel smoother and more responsive. - **Bug Fixes** - Improved runtime fallback handling so missing runtimes and initialization failures are reported more accurately. - Toast notifications are now better deduplicated, reducing repeated alerts when multiple views show the same fallback state. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
461a4a2711 |
FN-7689: add opt-in Anthropic-style prompt caching for custom providers
Custom providers previously never enabled prompt-cache control, so agent turns re-billed the full context every request even on cache-capable backends. - Add `CustomProvider.anthropicPromptCaching` opt-in flag in @fusion/core types - Set pi-ai `compat.cacheControlFormat="anthropic"` on opted-in models in both registration paths: custom-provider-registry `toProviderConfig` and pi.ts `createFnAgent` - Expose the new toggle in the dashboard CustomProvidersSection UI (with supporting CSS) and thread it through the legacy API + custom-provider routes - Update docs (dashboard-guide, settings-reference) to document the new setting - Add engine test coverage for the caching flag across provider registration and pi-create-fn-agent paths - Add changeset for the fix Files changed: .changeset/fn-7689-custom-provider-prompt-caching.md | 7 + docs/dashboard-guide.md | 1 + docs/settings-reference.md | 2 +- packages/core/src/types.ts | 15 ++ packages/dashboard/app/api/legacy.ts | 12 ++ packages/dashboard/app/components/CustomProvidersSection.css | 24 +++ packages/dashboard/app/components/CustomProvidersSection.tsx | 58 +++++- packages/dashboard/src/routes/register-custom-provider-routes.ts | 16 ++ packages/engine/src/__tests__/pi-create-fn-agent.test.ts | 71 +++++++ packages/engine/src/__tests__/provider-registration.test.ts | 204 ++++++++++++++++++++- packages/engine/src/custom-provider-registry.ts | 71 +++++-- packages/engine/src/pi.ts | 27 ++- 12 files changed, 473 insertions(+), 35 deletions(-) Fusion-Task-Id: FN-7689 Fusion-Task-Lineage: b4f88f32-50da-4651-a546-432a95a1ab1c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
64d4bb753a |
FN-7690: fix custom-provider anthropic-compatible apiType resolution
Reconciles a naming drift where resolveApiType() mapped anthropic-compatible custom providers to an unregistered pi-ai api key, causing streaming failures. - resolveApiType() now maps anthropic-compatible to "anthropic-messages" (was "anthropic"), matching pi.ts's resolveCustomProviderApiType and the built-in Anthropic provider config - Added FNXC:CustomProviders comment documenting why anthropic-messages is the only key pi-ai's ModelRegistry actually registers - Added/updated regression tests in custom-provider-registry.test.ts and provider-registration.test.ts - Added changeset (patch) documenting the fix Files changed: .changeset/fn-7690-apitype-resolver-reconcile.md | 7 +++++++ packages/cli/src/commands/__tests__/custom-provider-registry.test.ts | 21 ++++++++++++++++++--- packages/engine/src/__tests__/provider-registration.test.ts | 20 ++++++++++++++++++++ packages/engine/src/custom-provider-registry.ts | 15 ++++++++++++++- 4 files changed, 59 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-7690 Fusion-Task-Lineage: 461c340f-bc29-44a2-b8ec-19f0b03224d7 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c3c726cff4 |
fix(FUX-039): return init_error for found-but-uninitialized plugin runtime
Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
a8c018f7d4 |
fix: prevent false "OAuth token expired" push on startup
Start OAuthRefreshScheduler before the refresh-blind OAuthExpiryMonitor so a stale-but-refreshable access token is renewed before the monitor's first awaited check() reads `expires`. Previously the monitor fired a false "OAuth token expired" ntfy push on startup, moments before the refresher silently renewed the token. Ordering locked by an invocationCallOrder assertion in project-engine.test.ts. 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> |
||
|
|
be94f630ea |
Surface runtime-resolution fallback in dashboard; thread real FallbackReason (#1957)
Closes/relates to Runfusion/Fusion#1956. ## Summary Surfaces silent runtime-resolution fallback in the dashboard, and threads the real `FallbackReason` ("not_found" vs "factory_error") through instead of hardcoding `"not_found"` for every fallback. ## Changes - `packages/engine/src/runtime-resolution.ts`: `resolvePluginRuntime()` now returns a tagged miss result (`{ ok: false, reason }`) distinguishing "not found" from "factory/instantiation error" instead of collapsing both to `null`. `resolveRuntime()` threads the real reason through to `logRuntimeFallback(...)` and returns it via `ResolvedRuntime.fallbackReason`. - `packages/engine/src/agent-session-helpers.ts`: `createResolvedAgentSession()` includes `fallbackReason` in the `session:runtime-resolved` audit event metadata when present. - `packages/dashboard/src/routes/register-task-workflow-routes.ts`: new `GET /api/tasks/:id/runtime-fallback` endpoint, returning the most recent `session:runtime-resolved` event normalized for UI consumption (`wasConfigured`, `runtimeHint`, `reason`, `showFallbackBadge`). - `packages/dashboard/app/hooks/useRuntimeFallbackStatus.ts` (new): polls the endpoint, dedupes toast firing per audit-event-id. - `packages/dashboard/app/components/RuntimeFallbackBadge.tsx` (new): renders the badge + fires the toast; wired into `TaskCard.tsx`, `ActiveAgentsPanel.tsx`, and `AgentsView.tsx` (board and list variants). ## Test plan - `pnpm --filter @fusion/engine exec vitest run src/__tests__/runtime-resolution.test.ts` — 24/24 pass (21 pre-existing + 3 new, none weakened) - `pnpm --filter @fusion/dashboard exec vitest run src/routes/__tests__/register-task-workflow-routes.runtime-fallback.test.ts` — 5/5 pass (empty/configured-ok/fallback-with-hint/fallback-blank-hint/stale-superseded states) - `pnpm --filter @fusion/dashboard exec vitest run app/components/__tests__/RuntimeFallbackBadge.test.tsx` — 8/8 pass (all data states + mobile breakpoint + toast-fires-once) - `pnpm --filter @fusion/dashboard run typecheck` and `pnpm --filter @fusion/engine run typecheck` — both clean <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added runtime-fallback warning badges across task and agent views (including board and “working on” sections) with automatic toast notifications. * Introduced a new backend API to surface the latest runtime-fallback state for a task. * Added runtime-fallback status polling and UI messaging to reflect the most recent state. * **Bug Fixes** * Prevented repeated toasts by deduplicating notifications across polling updates. * Improved fallback reporting so the UI reflects the latest runtime-resolved audit event. * Enhanced diagnostics by distinguishing fallback reasons (e.g., missing runtime vs factory failure) for clearer user guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
aa534c19af |
FN-7672: recover durable agents stuck in error state despite active manager
Root-causes 4 correlated CTO-report agent failures where durable non-ephemeral agents got stuck in `error` state indefinitely because the heartbeat scheduler stops ticking error-state agents entirely, and self-healing's recovery sweep previously only considered them when their manager row was missing. - SelfHealingManager: scope the `managerMissing` gate to the "running" orphan-detection path only, so "error"-state durable agents with a present/active manager now fall through to the existing transient/operator-actionable/active-execution/cooldown/retry-budget recovery guards instead of being skipped outright - Add FNXC:AgentHeartbeat comment documenting the FN-7672 incident and rationale for the scoping change - Extend self-healing.test.ts with coverage for manager-present durable agents in error state - Add changeset (patch) describing the fix for release notes - Update docs/agents.md accordingly Files changed: .changeset/fn-7672-durable-agent-recovery.md | 7 ++ docs/agents.md | 2 + packages/engine/src/__tests__/self-healing.test.ts | 129 ++++++++++++++++++++- packages/engine/src/self-healing.ts | 24 +++- 4 files changed, 160 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7672 Fusion-Task-Lineage: 6676dc9e-66e7-4f70-804a-cccf77e8d337 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f7d9509294 |
FN-7658: gate same-agent duplicate auto-archiving behind opt-in setting
Duplicate tasks created by the same agent are no longer auto-archived by default; they are flagged for review instead, controlled by a new opt-in project setting. - Add project setting `autoArchiveDuplicateTasksEnabled` (default false) gating the FN-4892 same-agent duplicate intake path - Add `flagSameAgentDuplicate` path and `nearDuplicateOf` metadata used when auto-archive is disabled; tombstone-resurrection blocking is unchanged - Wire the setting through core settings schema/types/store, dashboard SchedulingSection UI, and i18n strings - Update docs (settings-reference.md, task-management.md) to describe the new default-off behavior - Add a changeset for the @runfusion/fusion minor release - Extend duplicate-intake, tombstone-window, store-parent-task-dedup, and reliability-interaction tests to cover both flag states Files changed: $(cat /tmp/fn7658_stat.txt) Fusion-Task-Id: FN-7658 Fusion-Task-Lineage: 7d0d1074-1020-48a8-b96f-186154c2c408 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
0bed997af8 |
feat: surface runtime-resolution fallback in dashboard, thread real FallbackReason
Fixes silent runtime fallback visibility (dashboard never read wasConfigured or session:runtime-resolved) and threads the real FallbackReason (not_found vs factory_error) through resolveRuntime()/logRuntimeFallback instead of hardcoding "not_found" for every fallback. - packages/engine/src/runtime-resolution.ts: resolvePluginRuntime() now returns a tagged miss result distinguishing not_found from factory_error; resolveRuntime() threads the real reason through and returns it as ResolvedRuntime.fallbackReason - packages/engine/src/agent-session-helpers.ts: includes fallbackReason in the session:runtime-resolved audit event metadata - packages/dashboard/src/routes/register-task-workflow-routes.ts: new GET /api/tasks/:id/runtime-fallback endpoint - packages/dashboard/app/hooks/useRuntimeFallbackStatus.ts + packages/dashboard/app/components/RuntimeFallbackBadge.tsx: new polling hook + badge/toast component wired into TaskCard, ActiveAgentsPanel, and AgentsView Ref: Fusion task FUX-022, investigations/FUX-017-hermes-runtime-fallback.md recommendation #1 |
||
|
|
bec8987ce9 |
FN-7648: gate hold-release on trait-based unplanned-card check, not literal todo column
Blocks planning/intake column cards from entering processing columns regardless of literal column id, so renamed custom intake/planning columns are covered by the same guard as the legacy todo column. - Add isUnplannedForExecution() in hold-release.ts: true when task.status==="planning", or when the card sits in the legacy todo column or a column carrying the intake trait AND its PROMPT.md still equals the bootstrap stub. - Route issueRelease() (used by the sweep, promoteHeldTask, and releaseHeldTaskByEvent) through this guard before releasing into any countsTowardWip processing column. - Update scheduler.ts's reserveSlot guard to use the same trait-based predicate instead of a hardcoded "todo" column id check. - Add regression tests in hold-release.test.ts and scheduler-workflow-cutover.test.ts covering renamed intake/planning columns. - Document the invariant in docs/architecture.md and docs/workflow-steps.md. - Add changeset (patch) describing the fix. Files changed: .changeset/fn-7648-unplanned-intake-cards-never-execute.md | 7 + docs/architecture.md | 2 + docs/workflow-steps.md | 2 + packages/engine/src/__tests__/hold-release.test.ts | 238 +++++++++++++++++++++ packages/engine/src/__tests__/scheduler-workflow-cutover.test.ts | 60 +++++- packages/engine/src/hold-release.ts | 60 ++++++ packages/engine/src/scheduler.ts | 26 +-- 7 files changed, 378 insertions(+), 17 deletions(-) Fusion-Task-Id: FN-7648 Fusion-Task-Lineage: a4b54d30-f86d-4eb9-9cf2-6ac55b6dbe58 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
009ce26fd0 |
FN-7646: prevent OAuth credential clobbering across concurrent Fusion processes
Fix API keys/OAuth credentials in ~/.fusion/agent/auth.json being clobbered when the desktop app and CLI-served web app run concurrently on one machine. - Reload primary auth storage from disk (primary.reload()) before persisting a refreshed OAuth credential, so a concurrent process's newer login/refresh for the same provider isn't overwritten by this process's stale in-flight refresh. - Re-check credential identity against the freshly reloaded disk state before writing the refreshed token back. - Add cross-process regression coverage exercising concurrent auth.json read-modify-write scenarios. - Add changeset documenting the fix and its dependency on the pi-coding-agent locked per-provider merge (>=0.80.x). Files changed: .changeset/fn-7646-auth-storage-coordination.md | 7 + .../src/__tests__/auth-storage-concurrency.test.ts | 234 +++++++++++++++++++++ packages/engine/src/auth-storage.ts | 27 +++ 3 files changed, 268 insertions(+) Fusion-Task-Id: FN-7646 Fusion-Task-Lineage: de39f08d-2d9f-46ff-b293-c603e3268ecf Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
4e8c621e9c |
FN-7641: fix cards stranded after out-of-band/workspace merges by allowing proven-merge rehome
Fixes a state-machine bug family where cards got stranded after out-of-band or workspace merges landed: store.moveTask now allows a proven-merge recoveryRehome to cross legacy columns (e.g. todo→done), and nodeId='end' finalize no longer silently no-ops — it finalizes on durable merge proof or returns an explicit error, consistently across the dashboard route, the CLI task-update tool, and store.updateTask. - packages/core/src/store.ts: allow proven-merge recoveryRehome moves across legacy columns (e.g. todo→done) instead of rejecting them - packages/core/src/node-override-guard.ts: nodeId='end' finalize now checks for durable merge proof and returns an explicit error instead of silently no-op'ing - packages/dashboard/src/routes/register-task-workflow-routes.ts: dashboard workflow route surfaces the new explicit finalize error/behavior - packages/cli/src/extension.ts: CLI task-update tool surfaces the same explicit finalize error/behavior - docs/task-management.md: documented the updated finalize/rehome behavior - Added regression tests across core (node-override-guard, store-movement, task-node-override), dashboard (register-task-workflow-routes.nodeid-finalize), engine (merger-merge-lifecycle), and CLI (extension) covering the stranded-card invariant - Added changeset for @runfusion/fusion (patch) Files changed: .changeset/fn-7641-stranded-cards-after-merge.md | 7 ++ docs/task-management.md | 2 + packages/cli/src/__tests__/extension.test.ts | 59 ++++++++++++++ packages/cli/src/extension.ts | 10 +++ .../core/src/__tests__/node-override-guard.test.ts | 93 +++++++++++++++++++++ packages/core/src/__tests__/store-movement.test.ts | 94 ++++++++++++++++++++++ .../core/src/__tests__/task-node-override.test.ts | 73 +++++++++++++++++ packages/core/src/node-override-guard.ts | 69 +++++++++++++++- packages/core/src/store.ts | 69 +++++++++++++++- ...er-task-workflow-routes.nodeid-finalize.test.ts | 90 +++++++++++++++++++++ .../src/routes/register-task-workflow-routes.ts | 10 +++ .../src/__tests__/merger-merge-lifecycle.test.ts | 58 +++++++++++++ 12 files changed, 631 insertions(+), 3 deletions(-) Fusion-Task-Id: FN-7641 Fusion-Task-Lineage: 48ea7851-ee68-48f1-92f9-302d0da5acff Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
923bba7082 |
FN-7645: force re-arm zombie heartbeat timers detected as stale during audit
Fixes the heartbeat timer audit so it repairs not just missing timer registrations but also 'zombie' ones — timer entries that remain present in memory after their underlying interval silently stopped firing. Long-interval (~1h) agents were most affected since a single lost tick compounded into hours of staleness before self-healing noticed. - HeartbeatTriggerScheduler audit now computes staleness (elapsed vs repair-stale threshold) up front for every timer-eligible agent, not only for agents missing a timer entry - Present-but-stale timer entries are now treated as non-advancing and force cleared/re-registered via registerAgent() (which already clears any existing timer before re-arming) - Fresh (non-stale) present timers are left alone so healthy short-interval agents are never force-re-armed or double-ticked - Repair reason/log messages now distinguish zombie-timer-rearmed repairs from missing-registration repairs, and the summary log reports counts for each - Added heartbeat-scheduler tests covering the zombie-timer repair path - Added changeset and a docs/architecture.md note Files changed: .changeset/fn-7645-heartbeat-rearm.md | 7 + docs/architecture.md | 1 + .../src/__tests__/heartbeat-scheduler.test.ts | 223 +++++++++++++++++++++ packages/engine/src/agent-heartbeat.ts | 42 +++- 4 files changed, 266 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-7645 Fusion-Task-Lineage: 652bc2eb-a660-4306-9f85-d2d5f9ca7e38 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f1db31374a |
FN-7642: emit diagnostic output for dispatch/infra failures in optional-group and CE gate nodes
Fixes the code-review/plan-review/CE gate workflow node failing with a blank "(no feedback captured)" message when a dispatch or infra exception (not a reviewer verdict) causes the step to fail. - WorkflowGraphExecutor now synthesizes a non-blank WorkflowStepResult.output when an enabled optional-group (code-review, plan-review, browser-verification) or CE source:"node" skill-gate template node fails via dispatch/infra exception - Diagnostic output is derived from the node:<id>:error context-patch key, falling back to the failure value, then a stable sentinel - status, verdict extraction, edge routing, and self-healing's latestFailedPreMergeStep selection are unchanged - Added regression test coverage: workflow-graph-optional-group-no-feedback.test.ts - Added changeset (patch) documenting the fix for Runfusion/Fusion#1946 Files changed: .changeset/fn-7642-code-review-no-feedback-diagnostic.md | 7 + packages/engine/src/__tests__/workflow-graph-optional-group-no-feedback.test.ts | 246 +++++++++++++++++++++ packages/engine/src/workflow-graph-executor.ts | 104 ++++++++- 3 files changed, 355 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7642 Fusion-Task-Lineage: 1329e907-652f-4230-a945-5a9d7040ae69 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
fe5a595984 |
FN-7622: unify desktop and CLI provider seeding to fix truncated provider list
The Electron desktop app's in-process dashboard server skipped the CLI's provider seeding sequence, so /api/providers and /api/models returned a truncated catalog (missing built-in API-key providers and user customProviders[]) compared to the identical config on the web build. - Move provider-auth.ts and custom-provider-registry.ts from @fusion/cli into @fusion/engine as the single shared implementation - Add engine/src/provider-registration.ts exposing seedDashboardProviders(), mirroring the CLI's exact startup order (built-in Zai provider registration -> wrapAuthStorageWithApiKeyProviders -> model merge/refresh -> registerCustomProviders -> settings:updated resubscription) - Update desktop/src/local-runtime.ts and local-server.ts to call the shared seedDashboardProviders() helper instead of constructing a raw authStorage/modelRegistry - Convert packages/cli/src/commands/provider-auth.ts and custom-provider-registry.ts into re-export shims preserving unchanged observable behavior - Add engine/src/__tests__/provider-registration.test.ts and expand desktop local-runtime/local-server tests to cover the shared seeding path - Add changeset for @runfusion/fusion (patch) Files changed: .changeset/fn-7622-desktop-provider-parity.md | 7 + .../cli/src/commands/custom-provider-registry.ts | 122 +---- packages/cli/src/commands/provider-auth.ts | 517 +-------------------- .../desktop/src/__tests__/local-runtime.test.ts | 93 ++++ .../desktop/src/__tests__/local-server.test.ts | 62 ++- packages/desktop/src/local-runtime.ts | 33 +- packages/desktop/src/local-server.ts | 21 +- .../src/__tests__/provider-registration.test.ts | 192 ++++++++ packages/engine/src/custom-provider-registry.ts | 117 +++++ packages/engine/src/index.ts | 18 + packages/engine/src/provider-auth.ts | 513 ++++++++++++++++++++ packages/engine/src/provider-registration.ts | 105 +++++ 12 files changed, 1172 insertions(+), 628 deletions(-) Fusion-Task-Id: FN-7622 Fusion-Task-Lineage: fb6fbbf3-745e-4623-b7af-11471e13f138 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
1add12d703 |
fix: resolve full-suite CI failures across engine + dashboard (shards 1-4) (#1947)
## Summary Fixes the failing **full-suite** CI run on `main` ([run 28874651861](https://github.com/Runfusion/Fusion/actions/runs/28874651861)) — all 4 test shards were red. ~32 test files failing across engine + dashboard (src + app), rooted in ~13 distinct causes from recent main commits. All resolved; the merge gate and full engine/dashboard suites are green locally. ## Root causes & fixes ### Engine (shards 1 & 2) - **`appendAgentLog` 6th timing arg (FN-7503, `2797803c0`)** — `agent-logger.ts` now passes an optional `{durationMs,timeToFirstTokenMs}` 6th arg; many executor/heartbeat/merger tests asserted the old 5-arg form. Added a shared timing-tolerant helper `agent-log-assertions.ts` (asserts `taskId/text/type`, tolerant of the timing object) and applied it across affected files — so future timing fields won't re-break every executor test. - **`reconcileSupersededGeneratedFixFeatures` (mission)** — `mission-execution-loop.ts` calls a method the test's missionStore mock lacked; added a no-op stub (the real `MissionStore` already implements it). - **`ModelFallbackExhaustedError` / `proseSignalsClearApproval` / `extractJsonObjectCandidates` missing from `vi.mock`** — converted stale hand-written mocks (`../pi.js`, `../reviewer.js` in `executor-test-helpers.ts`) to `importOriginal`-spread so real exports carry through. - **Workspace product fixes (2):** - `merger-ai.ts` — `landWorkspaceTask` now recovers the integration-tip sha as `landedSha` when the A1 trailer-fallback proved a sub-repo landed but its sha was never persisted, so `finalizeWorkspaceTask` can build merge proof (was stranding partial-land retries in-review). - `worktree-acquisition.ts` — `acquireWorkspaceRepoWorktree` strips the shared project `integrationBranch/baseBranch` overrides before forwarding to `acquireTaskWorktree` (FN-7360's `freshStartPoint` was resolving an absent shared branch). - **FN-7360 extra `git symbolic-ref` exec** — updated worktree exec-count assertions for the new `resolveIntegrationBranch` call. - **Planner-overseer / stepwise-workflow / workflow-graph / workflow-prompt / executor-step-session / liveness-gate / checkout / ce-workflow / triage-split** — test-alignments for intentional behavior changes (FN-7229 retry-cap, FN-7265 review-node removal, FN-7335 pause-abort logging, FN-7577 recovery-budget, FN-7577 overseer denial loop, specifyTask single promptWithFallback call, FN-4944 already-on-main noop log, FN-7486 ownership short-circuit). ### Dashboard API (shard 3) - **`store.on('task:moved')` (FN-7337)** — `createServer` now registers the listener; backed the 4 affected MockStores with EventEmitter (shared root cause across chat-routes.rooms, register-git-github, routes-run-cited-goals, routes-sandbox-audit). - **`routes-agent-import`** — core mock converted to `importOriginal`-spread (was missing FN-7444 planning-deepening constants). - **`session-resume-history`** — engine mock missing `resolveMcpServersForStore`. - **`task-create-workflow-route`** — `builtin:legacy-coding` defaultSteps now include `plan-review` (FN-7224/7226). - **GitLab parity** — added the missing `[GitLab Parity Inventory]` cross-link in `docs/signals-connectors.md`. ### Dashboard app (shard 4) - Test-alignments for intentional product changes: FN-7057 (workflow selection preservation), FN-7340 (footer concurrency geometry), FN-7156 (Missions overview default), FN-7342/FN-6825 (board scroll + workflow switcher), FN-7352 (openDetailTask 3rd arg), FN-7261 (backdrop dismiss default-off), FN-7234 (non-authoritative fetch failures), plus a missing `fetchWorkflowOptionalSteps` mock. ### MCP coverage - `mcp-surface-coverage` forwarding needle updated for FN-7446's `resolvePlanningMcpServers` helper. ## Approach notes - Each fix is the **minimal** change at the correct source (test-update where a recent commit intentionally changed behavior; product-fix for the 2 real regressions). No assertion was loosened/deleted to force a pass; no timeout appeasement. - Coordination: work was partitioned by package across parallel subagents (engine / dashboard-src / dashboard-app) with Main as the sole git committer (path-scoped commits) after an early shared-index reset wiped in-progress edits — process was tightened mid-flight. ## Verification - **Full engine suite**: green (9231 passed; the lone local-only `custom-providers-openai-completions` import error is stale local `pi-ai@0.79.9` vs the lockfile's `0.80.3` — CI's fresh install resolves `/compat`; it passed in the original CI run). - **Dashboard API** (`dashboard-api-quality-backfill`): 242 files / 3185 tests / 0 failures. - **Dashboard app** (`dashboard-app-quality-backfill`): all targeted files green (37 + 95 tests). - **Merge gate** (`pnpm test:gate`): engine-core 326 + ci-shape 63, plus nohup/4040/appeasement/changeset-format checks — all pass. - 2 changesets added for the published-`@runfusion/fusion` behavior fixes (workspace landedSha, sub-repo worktree branch-strip). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved reliability for partial workspace land retries by recovering the exact proven landed commit so durable merge proofs can complete. * Fixed per-sub-repo worktree creation by removing invalid branch override settings, preventing worktree-add failures. * Dashboard stability updates: preserve mobile board scroll during stabilization/restore, correct task filtering when workflows are missing, ensure the Chat tab appears for done tasks, and refine modal-dismiss and responsive popover behavior. * **Documentation** * Expanded the GitLab connector section with GitLab parity context and a GitLab Parity Inventory reference. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
203c734340 |
fix(engine): require exact trailer line, not substring, for proven landed commit (Greptile P1)
findProvenLandedCommit now keeps --grep as a prefilter but verifies each candidate carries an actual 'Fusion-Task-Id: <taskId>' trailer line via git show -s --format=%B, so a later commit that merely mentions the trailer text in its body cannot be selected. Regression covers a body-mention intervening commit. |