- Add JSDoc to resolveCustomProviderApiType (docstring coverage + AGENTS.md
jsdoc convention) and convert the inline rationale to FNXC format.
- FNXC-format the test rationale comment.
- Strengthen the regression test per FN-5893 (fix the invariant, not the repro):
- negative assertion that no provider is ever registered with the bare
"anthropic" api key;
- assert every api key passed to registerProvider is one pi-ai's registry
actually registers, so a typo in any arm (not just anthropic) fails here.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
resolveCustomProviderApiType mapped the `anthropic-compatible` provider type
to the api key "anthropic", but pi-ai (@earendil-works/pi-ai) registers the
Anthropic Messages API under "anthropic-messages". Any custom provider
configured as anthropic-compatible selected a model whose `api` did not match
a registered provider, throwing "No API provider registered for api: anthropic"
at stream time (the model registered fine, but failed when a task tried to
stream).
The openai-responses and default (openai-completions) arms already map to real
registry keys and work; only the anthropic arm pointed at an unregistered key.
Extend the existing custom-provider registration test (which covered
openai-compatible and openai-responses but not anthropic-compatible) with a
regression assertion that anthropic-compatible maps to "anthropic-messages".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the manual FUSION_CLAUDE_ACP env enable with an experimental feature
switch. `experimentalFeatures.claudeCliAcp` is ON by default (off only when
explicitly set false); the engine translates it into the FUSION_CLAUDE_ACP
dispatch the pi-claude-cli provider reads, at registerExtensionProviders time.
- Still fail-closed: with no bridge path published (acp-runtime plugin absent),
the provider falls back to `claude -p`.
- Explicit FUSION_CLAUDE_ACP env always wins (operator / test override).
- New testable helper claude-acp-enable.ts (6/6 tests); flag documented in the
core experimentalFeatures doc.
So with the acp-runtime plugin installed, Claude CLI now routes through the ACP
bridge by default; set experimentalFeatures.claudeCliAcp=false to force `-p`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restore Pi-upgraded workspaces to keep Fusion resources accessible and recover title generation when configured models go stale.
- Mark read-only Fusion/Pi provider settings views as project-trusted so extension loading keeps working after Pi upgrades.
- Retry task title summarization with automatic model resolution when the configured provider model is missing from the Pi registry.
- Cover provider settings trust behavior and stale summarizer fallback paths with regression tests.
- Document the read-only settings trust contract and add a patch changeset.
Files changed:
.changeset/fn-6218-pi-upgrade-regressions.md | 5 +
docs/settings-reference.md | 2 +
docs/task-management.md | 2 +
.../commands/__tests__/provider-settings.test.ts | 16 ++++
packages/cli/src/commands/provider-settings.ts | 5 +
packages/core/src/__tests__/ai-summarize.test.ts | 102 +++++++++++++++++++++
packages/core/src/ai-summarize.ts | 85 ++++++++++++-----
.../src/__tests__/pi-create-fn-agent.test.ts | 32 +++++++
packages/engine/src/pi.ts | 7 +-
9 files changed, 233 insertions(+), 23 deletions(-)
Fusion-Task-Id: FN-6218
Fusion-Task-Lineage: 3d6aca32-a56a-43a0-a57b-8e6abc839ce9
Importing a catalog ("company") agent assigns role "custom", which the
scheduler never auto-assigns mission/queue work to. Combined with a
model/provider that rejects the "developer" system role, this surfaced as
an invisible, repeating failure loop (GitHub #1261).
- pi.ts: treat an unsupported message-role rejection as a model-selection
error so a configured fallback model is tried once (single-swap guarded)
before the task is marked failed.
- mission-autopilot.ts: block a mission feature immediately on an
operator-actionable failure instead of burning the retry budget
re-running the same cryptic error.
- mission-routes.ts: preflight mission start — when ephemeral agents are
disabled and no eligible executor exists, fail fast with an actionable
message instead of queueing tasks forever.
- agent import route + AgentImportModal: warn when only custom-role agents
are imported and no executor exists.
- agent-assignment.ts: extract shared listEligibleExecutorAgents helper.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes the U2/U5 skill-discovery carry-forward so the plugin's interactive ce-*
sessions actually load the stage's bundled skill in a live agent (not just in
scripted-fake tests).
Root cause: createFnAgent built its DefaultResourceLoader without forwarding any
skill-discovery path, and the interactive seam options couldn't carry one. The
loader's skillsOverride only *filters* skills already discovered from cwd's
standard roots, so the plugin-local .fusion-ce-skills/<id>/SKILL.md was never
discoverable.
Fix (end-to-end):
- AgentOptions.additionalSkillPaths forwarded into DefaultResourceLoader
- CreateInteractiveAiSessionOptions gains requestedSkillNames + additionalSkillPaths
- the interactive engine adapter forwards them to createFnAgent (skills +
additionalSkillPaths)
- the orchestrator runs the session with cwd on the real project root and hands
it [stage.skillId] + the install root
Proven: a real DefaultResourceLoader with additionalSkillPaths discovers ce-plan
and filters out ce-work; the orchestrator passes the right id/path/cwd. Plugin 96,
engine 136, core 99 tests green.
Added OpenAI Responses API as a new custom provider type, wiring `apiType: "responses"` through the core registry, engine routes, and dashboard UI with a dropdown selector; includes test coverage across the registry, routes, and component layers.
Fusion-Task-Id: FN-5601
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fusion-Task-Id: FN-5601
The top-level promptWithFallback bypassed the session-attached rich fallback
path that runs isRetryableModelSelectionError + swapPromptSession, so errors
like "No API key for provider: anthropic" propagated without trying the
configured planning fallback. Restore the dispatch with a WeakSet re-entry
guard that preserves the FN-4900 recursion fix for plugin-runtime sessions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Added a readonly tool allowlist enforcement for workflow steps, blocking execution of state-mutating tools (`fn_task_update`, `fn_task_move`, etc.) during workflow step runs. The policy is wired into the executor and merger execution paths, with tests covering allowlist enforcement and a documentati
Fusion-Task-Id: FN-4366
Adds reviewer prompt compaction and automatic retry logic when the reviewer hits context-window limits, with matching test coverage and a changeset for `@runfusion/fusion`.
Fusion-Task-Id: FN-4082
Extends AgentRuntimeOptions and AgentOptions with an optional
systemPromptLayers field (SystemPromptLayers) for cross-session prompt
caching. DefaultResourceLoader now uses the stable layer as
systemPromptOverride and the dynamic layer as appendSystemPromptOverride
when layers are provided, falling back to the flat systemPrompt string
for backward compatibility.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds durable heartbeat model fallback logic to the engine's heartbeat subsystem (`agent-heartbeat.ts`, `agent-session-helpers.ts`, `pi.ts`), allowing heartbeats to gracefully use alternative AI models when the primary model is unavailable, with documentation updates to `agents.md` and `settings-refe
Fusion-Task-Id: FN-3914
The merge adds section-aware prompt compaction for task triage (reducing spec payload size by intelligently trimming planning context), enriches the Settings modal with GitHub tracking configuration, and improves the engine's self-healing behavior.
Fusion-Task-Id: FN-3877
- Remove hard dependency on sendMessage in pi agent wrappers so no-approval gates can run without chat bindings
- Add regression coverage for createFnAgent behavior when sendMessage is absent and when tool calls still execute
- Add changeset for @runfusion/fusion documenting the no-approval gate send-message fix
Fusion-Task-Id: FN-3855
Hardens workflow gate execution to bypass the heartbeat terminal tool, preventing it from blocking terminal gates; adds regression tests covering approval request store and SSE relay behavior, with tightened typing on the test policy.
Fusion-Task-Id: FN-3852
The merge normalizes mention filtering in the chat components to handle underscore-prefixed handles, introducing a new `mentionMatching.ts` utility consumed by `AgentMentionPopup`, `ChatView`, and `QuickChatFAB`, with matching tests. It also removes a redundant try/catch in the PI approval gate (`pi
Fusion-Task-Id: FN-3850
Merges the FN-3548 approval pause/resume system: agents now stall at workflow gates pending approval, with a full lifecycle spanning gate context lookup, action-gate pause/retry, executor and heartbeat pause callbacks, and dedicated approval decision routes. Also lands FN-3744 agent action routes an
Fusion-Task-Id: FN-3548
Wired permanent-agent approval context into runtime paths for FN-3561, updating the agents documentation and adding test coverage for the heartbeat executor to validate the runtime behavior.
Fusion-Task-Id: FN-3561
The merge lands three major features: a permanent-agent gating system (FN-3560, 6 steps) that classifies and enforces tool access policies for permanent agents in the PI extension, with full test coverage and updated agent docs; an OpenClaw MCP bridge (FN-3717) adding MCP config, schema server, and
Fusion-Task-Id: FN-3560
Merged seven commits that introduce a runtime action gate for task execution (FN-3547) — adding action classification, git-based heuristics for branch/remote gating, and per-step session enforcement — with tests covering the gate logic, heartbeat integration, and PI agent creation. Also landed FN-37
Fusion-Task-Id: FN-3547
Added agent permission policy model with persistence in core, and wired web-builtin tool opt-in enabling planning and synthesis web tools in the dashboard with corresponding docs and a changeset. Also added an inline fast-mode toggle wired into peer executor state, retry logic for cluster task-ID ov
Fusion-Task-Id: FN-3713
When ChatView remounted (e.g. tab switch with keyboard still up), the
hook started with keyboardOpen=false and corrected itself only after
the effect ran. That single stale-state render briefly unhid the
executor status bar, which appeared as a blank pane covering half the
input box before the next state update settled it.
useState initializers now call getKeyboardMetrics() lazily on first
render so the very first paint already reflects the live keyboard
state.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merges FN-3534 to surface task provenance in CLI extension outputs (task list/show) with corresponding tests and a changeset for the published `@runfusion/fusion` package. Also includes FN-3297 test coverage for incomplete runtime distribution trees in the test-artifacts script.
Fusion-Task-Id: FN-3534
- Clarify task memory scope behavior across core types, project memory logic, engine tool prompts, and related docs
- Add regression coverage for memory scope and runtime plugin alias handling in core/dashboard/engine tests
- Add agent avatar API routes and dashboard UI support for avatar display and storage documentation
- Add line-number gutter toggle support in FileEditor and Files modal with accompanying component tests
- Include changeset for @runfusion/fusion documenting memory scope guidance update
Fusion-Task-Id: FN-3485
pi-ai's openai-codex-responses provider surfaces ChatGPT-plan WebSocket
drops as bare "WebSocket error" / "WebSocket closed <code>". The
underlying ErrorEvent.error is dropped by extractWebSocketError (it only
inspects event.message), so the cause is gone by the time we see it.
The engine then propagated these as fatal failures instead of retrying
a transient network blip.
- Add WebSocket patterns to TRANSIENT_ERROR_PATTERNS so the executor's
existing transient retry path picks them up.
- Tag the model id onto the thrown error and emit a structured warn in
promptSessionAndCheck so future drops can be triaged by transport.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Moonshot/Kimi returns a non-standard finish_reason of "repeat" when its
server-side repetition detector trips. pi-ai surfaces this as a fatal
session state error, killing the agent heartbeat. Filter that case in
promptSessionAndCheck so the truncated turn is logged and the heartbeat
continues on the next tick.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>