Commit Graph

3178 Commits

Author SHA1 Message Date
gsxdsm
f23619c2d4 fix: preserve user pause across executor pause teardown (FN-7851 pause-bounce loop)
Pausing an in-progress task never stuck: the pause teardown re-queued the
row to todo with a plain engine move, and the reopen block wiped
paused/pausedByAgentId/pausedReason. The graph-failure classifier then saw
an unpaused row, misread the hard-cancel as an engine-internal abort, and
auto-continued the session (graphResumeRetryCount 1/2, 2/2); once the
budget was exhausted the benign re-queue left the row dispatchable and the
scheduler re-dispatched it seconds later — an indefinite pause/resume
bounce, burning a fresh worktree + pnpm install per cycle.

- store: new moveTask option `preservePause` keeps the pause park across a
  reopen-to-todo/triage move (flag-ON trait hook + flag-OFF legacy inline,
  kept in sync). It never SETS a pause, only prevents clearing one.
- executor teardown: when the pause that caused the abort is still in
  force, move with preservePause so the row lands in todo still parked
  (scheduler skips paused/userPaused rows until explicit unpause).
- classifier: a live task pause is labeled operator intent, never
  "engine abort during pause/resume"; the benign log now says
  "parked … awaiting explicit unpause" instead of the contradictory
  "cleared for normal scheduling" for parked rows.

Surfaces covered by tests: flag-ON hook (preserve + never-set + default
clear), classifier no-auto-continue for task-pause/user-pause/global-pause
rows in todo, provenance labels.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 10:04:29 -07:00
gsxdsm
f82a3d2840 chore(release): v0.58.0
Version bump via changesets.
2026-07-11 23:50:00 -07:00
gsxdsm
a850cb7ead fix: document non-pi customTools fail-open when gate context omitted
Matches pi wrapToolsWithActionGate semantics: callers that omit
actionGateContext (chat/triage) intentionally leave tools ungated.
Add a content-free warn when a non-pi runtime receives customTools without
gate context so the path is visible without inventing deny-all defaults.
2026-07-11 23:34:35 -07:00
gsxdsm
0b4ce01ea8 fix: gate customTools for non-pi runtimes before createSession
Greptile P1 on PR #2011: Grok ACP (and other plugin runtimes) previously
executed engine-injected fn_* tools without the pi action-gate / permanent-
agent / RTK rewrite chain. Wrap customTools once in createResolvedAgentSession
for non-pi runtimes so loopback MCP bridges dispatch already-gated closures.
Pi still owns its own wrap chain inside createFnAgent to avoid double-wrapping.
2026-07-11 23:34:35 -07:00
gsxdsm
6267a762a4 feat: drive Grok CLI sessions over ACP with tools, skills, and MCP
Replace one-shot grok -p JSON with native grok agent stdio (ACP) for realtime
streaming, tool visibility, and multi-turn sessions. Vendor the ACP client
into fusion-plugin-grok-runtime, forward Fusion fn_* tools and operator MCP,
stage Fusion skills via --plugin-dir, authenticate per xAI headless docs, and
align project chat manager store resolution so Grok chat sessions can send.
2026-07-11 23:23:31 -07:00
gsxdsm
9b7623bc4c test: fix heartbeat getSettings mock + recoveryEligible (FN-7835), skip planner confirmation gate (FN-7840), chat engine mock, dashboard lucide+tabs 2026-07-11 23:08:36 -07:00
gsxdsm
c9d0211bec FN-7844: coordinate heartbeat and self-healing durable-agent error recovery
Unifies the two independent durable-agent error-recovery paths (heartbeat timer and self-healing sweep) so they share one retry budget, eligibility check, and audit surface instead of racing separate counters.

- Share the heartbeatErrorRecovery attempt budget between HeartbeatMonitor's timer-entry recovery and SelfHealingManager.recoverOrphanedAgents(), with self-healing's legacy durableErrorRecovery metadata folded into the same counter via readHeartbeatErrorRetryCount().
- Add isHeartbeatErrorRecoverable() as the single transient/non-operator-actionable eligibility check, used by both the heartbeat timer and self-healing paths (self-healing additionally allows stale-worktree module-resolution errors).
- resetHeartbeatErrorRecoveryMetadata() now strips the legacy durableErrorRecovery field so recovered agents don't retain stale sweep bookkeeping.
- Self-healing emits the shared agent:auto-recover-error-state / agent:error-retry-exhausted run-audit events with source:"self-healing", and parks the agent paused with pauseReason:"error-retry-exhausted" on budget exhaustion, matching the heartbeat-timer behavior.
- Update AGENTS.md, docs/architecture.md, and docs/agents.md to describe the consolidated recovery budget and audit surface.
- Add a patch changeset documenting the fix for @runfusion/fusion.

Files changed:
 .changeset/fn-7844-error-recovery-coordination.md  |  7 ++
 AGENTS.md                                          |  2 +-
 docs/agents.md                                     | 14 ++--
 docs/architecture.md                               |  2 +-
 packages/engine/src/__tests__/heartbeat-error-recovery.test.ts | 13 +++-
 packages/engine/src/__tests__/self-healing.test.ts | 58 ++++++++++++++-
 packages/engine/src/agent-heartbeat.ts             | 35 ++++++---
 packages/engine/src/self-healing.ts                | 85 ++++++++++++++++++----
 8 files changed, 180 insertions(+), 36 deletions(-)

Fusion-Task-Id: FN-7844
Fusion-Task-Lineage: b70dcba5-56b6-412c-8be2-ef827bee9964
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 22:31:30 -07:00
gsxdsm
4397cafb94 fix: wire push-after-merge into the unified runAiMerge path with remote/branch dropdown settings
pushAfterMerge was only implemented in the soft-deprecated legacy aiMergeTask
pipeline, so after master-plan U0 made runAiMerge the sole merge path the
setting silently did nothing and origin fell permanently behind local main.

- runAiMerge now runs a post-finalize push step: working-tree-independent
  ref-to-ref push fast path; on remote divergence a detached clean-room
  pull --rebase (with AI conflict resolution) pushes HEAD and CAS-advances
  the local integration ref (explicit non-FF opt-in, push path only), then
  runs merge-advance auto-sync and refreshes mergeDetails.commitSha.
- Push failures stay non-fatal (task finalizes done) with push:origin
  run-audit events and PushToRemoteFailed task-log entries.
- Merge settings: Push Remote free-text replaced by remote + target-branch
  dropdowns (Custom… escape, free-text fallback when no remotes), persisting
  to the same pushRemote setting string. New GET /api/git/remotes/:name/branches
  endpoint lists remote-tracking branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:16:48 -07:00
gsxdsm
391ff0d269 FN-7835: auto-clear durable agent error state and retry on next heartbeat
Heartbeat-managed durable agents that land in state:"error" now self-recover on the next heartbeat instead of staying stuck until an operator intervenes.

- HeartbeatTriggerScheduler keeps timers armed for durable heartbeat-managed agents in error state when the last error is transient and not operator-actionable (credential/quota/model-access/permanent-config failures stay parked).
- executeHeartbeat clears recoverable errors at run entry (error → active, clears lastError), bounded by MAX_HEARTBEAT_ERROR_RECOVERY_ATTEMPTS (settings-overridable); a successful run resets the counter.
- On budget exhaustion, the agent is parked paused with pauseReason:"error-retry-exhausted".
- Emits new run-audit events agent:auto-recover-error-state and agent:error-retry-exhausted (added to DatabaseMutationType).
- Adds heartbeat-error-recovery.test.ts and extends heartbeat-scheduler.test.ts to cover the recovery/exhaustion paths.
- Adds changeset and documents the new behavior in AGENTS.md and docs/architecture.md.

Files changed:
 .changeset/fn-7835-agent-error-auto-recovery.md    |   7 +
 AGENTS.md                                          |   1 +
 docs/architecture.md                               |   2 +
 .../src/__tests__/heartbeat-error-recovery.test.ts | 323 +++++++++++++++++++++
 .../src/__tests__/heartbeat-scheduler.test.ts      |  89 +++++-
 packages/engine/src/agent-heartbeat.ts             | 209 ++++++++++++-
 packages/engine/src/run-audit.ts                   |   2 +
 7 files changed, 618 insertions(+), 15 deletions(-)

Fusion-Task-Id: FN-7835

Fusion-Task-Lineage: 1bbb28a3-8eb9-40e3-8177-6658ec5dae40

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 22:16:48 -07:00
gsxdsm
14b7244bcb FN-7840: suppress advisory merger/pull-request await-confirmation interventions
Stops decidePlannerRecovery from recording noisy advisory confirmation interventions for merger/pull-request stages that never actually block progress when auto-merge will proceed unattended.

- decidePlannerRecovery now returns action "none" (no pending confirmation, no steering comment, no overseer:intervention entry) for merger/pull-request stages when autoMergeWillProceed === true, since this checkpoint is purely advisory in that case
- Genuine human-approval blocks (autoMergeWillProceed === false) and the neutral pure-function default (undefined) keep the await_confirmation decision intact
- Updated planner-recovery.test.ts to assert the new "none" outcome for the advisory case
- Simplified planner-overseer-intervention-wiring.test.ts to match the reduced intervention surface
- Added changeset documenting the fix as a patch-level bug fix

Files changed:
 .changeset/fn-7840-advisory-merger-confirmations.md            |   7 ++
 packages/core/src/__tests__/planner-recovery.test.ts           |  32 ++---
 packages/core/src/planner-recovery.ts                          |  47 ++++---
 packages/engine/src/__tests__/planner-overseer-intervention-wiring.test.ts | 135 +++++----------------
 4 files changed, 79 insertions(+), 142 deletions(-)

Fusion-Task-Id: FN-7840

Fusion-Task-Lineage: 610a9003-f229-4e78-9948-ee0bb85193bc

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 22:16:48 -07:00
gsxdsm
0a90dc4b55 FN-7821: refresh-then-recheck OAuth credentials before dispatching expiry notifications
Aligns OAuthExpiryMonitor's ntfy push notifications with the /api/auth/status refresh-then-recheck logic that drives the in-app OAuthReloginBanner, so providers that silently auto-refresh (e.g. GitHub Copilot's ephemeral token) no longer trigger false "OAuth token expired" pushes with no matching banner.

- OAuthExpiryMonitor.check() now performs a best-effort authStorage.getApiKey() refresh and reloads/re-resolves the credential before dispatching oauth-token-expired, instead of relying solely on the stored expiry timestamp
- resolveEffectiveOAuthCredential() now also guards against non-finite expires values in addition to non-numeric ones
- Updated docs/dashboard-guide.md and docs/settings-reference.md to describe the refresh-then-recheck behavior generically (not just Claude/Anthropic) and documented the FN-7821 fix in FNXC provenance comments
- Added regression tests covering the refresh-then-recheck flow in oauth-expiry-monitor.test.ts
- Added a patch changeset describing the fix for release notes

Files changed:
 .changeset/fn-7821-oauth-expiry-notification-banner-consistency.md               |   7 +
 docs/dashboard-guide.md                                                          |   6 +-
 docs/settings-reference.md                                                       |   6 +-
 packages/engine/src/notification/__tests__/oauth-expiry-monitor.test.ts          | 146 ++++++++++++++++++++-
 packages/engine/src/notification/oauth-expiry-monitor.ts                         |  48 ++++++-
 5 files changed, 199 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-7821

Fusion-Task-Lineage: 5954592c-adda-4fd4-b205-265860eddf3d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
51d5f9a28f test: fix executor artifact-register assertion (FN-7790) + i18n versionShort parity 2026-07-11 18:06:45 -07:00
Phil Larson
6ee86c5db7 fix(missions): address lifecycle review blockers 2026-07-11 17:04:22 -07:00
Phil Larson
c68b053162 fix(missions): reconcile lifecycle invariants 2026-07-11 17:04:22 -07:00
gsxdsm
8fa2ad0ecd Address PR review feedback (#1996)
- contain fn_artifact_register path payloads: realpath-canonicalized
  containment before stat/read — relative paths require and must stay
  inside baseDir, absolute paths allowed only under baseDir or the OS
  temp dir (deliberate allowance for browser/screenshot tooling);
  the process.cwd() fallback is gone, symlink escapes rejected
- bind task-scoped heartbeat artifact registration to the acquired
  worktree (baseDir: sessionCwd rebind after acquisition); no-task
  heartbeat prompt now says to pass absolute temp-dir paths
- enforce exactly-one payload source (content/uri/dataBase64/path);
  content+uri combos are now rejected to match the documented contract
- add FNXC rationale comments at both visual-artifact instruction sites
  in the planning prompts (sync contract with the executor prompt)
- media route: statSync -> await stat from node:fs/promises
- range tests ride the in-memory MockSocket harness (TestResponse gains
  binary-safe bodyBuffer; real-TCP helper deleted) and assert the full
  206 Content-Range/Content-Length contract for every range form
- add PdfViewer coverage (iframe src/title) in DocumentsView tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00
gsxdsm
a8eafbbb14 feat: video, HTML mockup, and PDF artifact support end-to-end
Video was registrable but effectively unusable, and HTML/PDF deliverables
had no first-class path from agents to the gallery.

- media route now serves HTTP byte ranges (Accept-Ranges, 206 +
  Content-Range, 416 on unsatisfiable) so <video>/<audio> seeking works
  and Safari plays media at all
- video attachments (mp4/webm/mov, 100MB cap vs 5MB for other types)
  bridge into the artifact registry like images; multer transport ceiling
  raised to 100MB with per-type caps enforced in the store
- fn_artifact_register path payloads are signature-validated for video
  (ftyp box / EBML header) and PDF (%PDF- prefix), mirroring images
- HTML doc artifacts (mimeType text/html) render as live sandboxed
  iframe previews by default in the doc viewer, with a Preview/Source
  toggle and the same FileEditor edit mode
- executor/heartbeat/planning prompts and tool descriptions now cover
  the full type matrix: images, videos, audio, HTML mockups, PDFs, and
  markdown docs, each with the registration recipe

Verified live: range requests (200/206/416) via curl, an ffmpeg-generated
mp4 playing to completion in the gallery lightbox, and an interactive
HTML mockup rendering in the sandboxed preview.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00
gsxdsm
9024f3a639 feat: agent-created visual artifacts end-to-end + redesigned category gallery with doc editing
Agents could never get screenshots/wireframes/mocks into the Artifacts view:
fn_artifact_register was gated on assignedAgentId (never set in default
ephemeral mode), the only image payload source was inline base64, and no
prompt ever told agents to register visual deliverables.

- always expose fn_artifact_register to executor sessions ("executor" author
  fallback), resolve relative paths against the task worktree, and default
  taskId to the executing task (heartbeat task lane too)
- add a `path` payload source: file read with 50MB cap, extension MIME
  inference, PNG/JPEG/GIF/WebP signature + SVG sniff validation, persisted
  through managed artifact storage
- executor/heartbeat/planning prompts + engine-tools reference now instruct
  agents to register screenshots, wireframes, mockups, and recordings
- new ArtifactsGallery: Images/Docs/PDFs/Videos/Audio/Other category sections
  and filter chips, visual tile grid + lightbox, embedded PDF viewer, audio
  player rows, download rows; mobile-responsive down to the 768px breakpoint
- doc artifacts open a full viewer rendered as markdown by default with an
  in-place edit mode using the shared CodeMirror FileEditor; persisted via new
  GET/PATCH /api/artifacts/:id + TaskStore.updateArtifact and live-refreshed
  through the new artifact:updated SSE event

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00
Phil Larson
d116018ed4 fix(FN-1997): bind stranded AI merge recovery to reviewed commit 2026-07-10 23:32:57 -07:00
Phil Larson
e7549e354f Recover AI merge commits before pruning clean rooms 2026-07-10 23:32:57 -07:00
Phil Larson
93d4be7b99 Recover stranded approved AI merge commits 2026-07-10 23:32:57 -07:00
gsxdsm
49f03f8440 test(engine): add getBranchGroup to shared createMockStore (FN-7750 shared-branch-group integration) 2026-07-10 23:21:37 -07:00
gsxdsm
f05f54c86a test(engine): update grok-runtime-routing for single-JSON parse contract (FN-7796) 2026-07-10 23:21:37 -07:00
gsxdsm
1c3eceec5b test(engine): complete agent-session-helpers thinking-level resolver set + pi mocks (restart/mcp-pr/triage) 2026-07-10 23:21:37 -07:00
gsxdsm
f164837e0f test(engine): add resolveExecutorThinkingLevel to step-session agent-session-helpers mock 2026-07-10 23:21:37 -07:00
gsxdsm
7d5f8ee9ea test(engine): add describeModel to heartbeat pi.js mocks (heartbeat-executor + heartbeat-skills) 2026-07-10 23:21:37 -07:00
gsxdsm
21fb8f6786 FN-7802: recover phantom-worktree tasks stuck merge-active with scopeOverride
Fixes phantom-worktree context bleed where the engine refused to start a
coding agent in a missing worktree for in-review/merge-active tasks even
when scopeOverride=1, stranding them past the normal recovery paths and
retry budget.

- Add isMergeActiveMissingWorktreeSessionStartFailure/isInReviewMissingWorktreeSessionStartFailure classifiers and MERGE_ACTIVE_MISSING_WORKTREE_STATUSES (merging/merging-pr/merging-fix) in restart-recovery-coordinator.ts, exported from @fusion/engine.
- Self-healing: reorder missing-worktree-review-failures sweep earlier, extend the in-review sweep to also match merge-active missing-worktree failures with a triple-proof-guarded, bounded (recoveryRetryCount) stale-metadata clear and fresh session-start retry budget reset.
- Self-healing: extend scopeOverride worktree-metadata reconciliation to safely clear phantom worktree/branch/session metadata for in-review tasks stuck in a merge-active sub-status, narrowly scoped to avoid clobbering genuinely live in-progress/mid-step tasks (FN-5256 guard preserved).
- CLI (task.ts), pi extension (extension.ts), and dashboard route (register-task-workflow-routes.ts) retry paths now bypass the merge-active status gate via a signature-only check, clearing worktree/branch/sessionFile and requeuing to todo while preserving progress.
- Add regression coverage across self-healing.test.ts, restart-recovery-coordinator.test.ts, extension.test.ts, task-retry.test.ts, and routes-tasks-ops.test.ts; update mockCoreEngine.ts test scaffolding.
- Update docs/architecture.md, docs/self-healing-backward-move-audit.md, docs/task-management.md, and AGENTS.md to describe the new merge-active missing-worktree recovery behavior.
- Add changeset (patch) for @runfusion/fusion.

Files changed:
 .changeset/fn-7802-phantom-worktree-merge-active-recovery.md      |   7 +
 AGENTS.md                                                          |   1 +
 docs/architecture.md                                               |   4 +-
 docs/self-healing-backward-move-audit.md                           |   5 +-
 docs/task-management.md                                            |   2 +-
 packages/cli/src/__tests__/extension.test.ts                       |  64 +++++
 packages/cli/src/__tests__/task-retry.test.ts                      |  49 ++++
 packages/cli/src/commands/task.ts                                  |  28 +-
 packages/cli/src/extension.ts                                      |  26 +-
 packages/dashboard/src/__tests__/routes-tasks-ops.test.ts          |  52 ++++
 packages/dashboard/src/routes/register-task-workflow-routes.ts     |  25 +-
 packages/dashboard/src/test/mockCoreEngine.ts                      |  11 +
 packages/engine/src/__tests__/restart-recovery-coordinator.test.ts |  20 ++
 packages/engine/src/__tests__/self-healing.test.ts                 | 297 +++++++++++++++++++++
 packages/engine/src/index.ts                                       |  13 +
 packages/engine/src/restart-recovery-coordinator.ts                |  19 +-
 packages/engine/src/self-healing.ts                                | 157 +++++++++--
 17 files changed, 744 insertions(+), 36 deletions(-)

Fusion-Task-Id: FN-7802

Fusion-Task-Lineage: 5897105b-6b5c-49d5-a8e8-519902182861

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 22:25:21 -07:00
gsxdsm
725ce45c5d FN-7799: fix false-negative Git repository detection blocking task execution
Replace the boolean isGitRepository() check with a tri-state Git detection so environmental git failures (dubious ownership, missing git binary, timeouts) are no longer misreported as "not a Git repository", which previously blocked all task execution in valid repos and survived engine restarts.

- Add detectGitRepository() in worktree-pool.ts returning repo / not-repo / error (with reason: dubious-ownership, git-missing, timeout, unknown), classified from git's stderr; bound the git rev-parse call with a 10s timeout and maxBuffer; keep isGitRepository() as a backward-compatible wrapper
- Route the executor dispatch preflight guard through detectGitRepository(): only emit the original "not a Git repository / run git init" fatal on a positive not-repo verdict; on error, throw a distinct accurate error naming the real git failure, including the safe.directory remedy for dubious ownership
- Route the in-process runtime startup warning through the same tri-state detection so it only warns "not a Git repository" on a positive not-repo verdict
- Add a regression test locking extractWorktreeConflictInfo() to NOT misclassify a dubious-ownership git worktree add failure as not-git-repo
- Add targeted tests across worktree-pool, executor-worktree, and in-process-runtime test suites covering repo/not-repo/dubious-ownership/git-missing/timeout classifications on Windows OneDrive-style and POSIX paths
- Add changeset and a docs/solutions/logic-errors write-up of the false-negative root cause and fix

Files changed:
 .changeset/fn-7799-git-detection-false-negative.md |  7 +++
 .../logic-errors/git-detection-false-not-repo.md   | 54 ++++++++++++++++
 .../engine/src/__tests__/executor-worktree.test.ts | 61 +++++++++++++++++++
 .../engine/src/__tests__/worktree-pool.test.ts     | 71 +++++++++++++++++++---
 packages/engine/src/executor.ts                    | 38 +++++++++---
 .../runtimes/__tests__/in-process-runtime.test.ts  | 53 ++++++++++++++--
 packages/engine/src/runtimes/in-process-runtime.ts | 16 ++++-
 packages/engine/src/worktree-pool.ts               | 66 ++++++++++++++++++--
 8 files changed, 334 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-7799
Fusion-Task-Lineage: 25a84283-bf47-472b-8a98-a10bf7e494de
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 21:19:22 -07:00
gsxdsm
fc4acd4d66 FN-7794: apply fallback model's own thinking level when swapping in at runtime
Adds fallbackThinkingLevel plumbing so, when Fusion swaps from a primary model to a configured fallback model (executor, validator/reviewer, merger, planning, title-summarizer, heartbeat, and workflow-step lanes), the fallback's own configured thinking level is applied instead of silently reusing the primary lane's level.

- Add fallbackThinkingLevel option to AgentRuntimeOptions (agent-runtime.ts), AgentOptions (pi.ts), and ReviewOptions (reviewer.ts)
- Add per-lane resolvers: resolveExecutorFallbackThinkingLevel, resolvePlanningFallbackThinkingLevel, resolveValidatorFallbackThinkingLevel, resolveTitleSummarizerFallbackThinkingLevel, resolveMergerFallbackThinkingLevel (agent-session-helpers.ts), each following fallback-provider precedence and falling back to the primary lane/default thinking level when unset
- Export new resolvers from packages/engine/src/index.ts
- Apply the resolved fallback thinking level in createFnAgent's applyThinkingLevelIfSupported once a session has swapped to the fallback model (pi.ts)
- Wire fallbackThinkingLevel through executor session creation (workflow-step, task validator, child-agent, and main executor session paths), merger session creation, and heartbeat session creation
- Promote the fallback thinking level alongside the fallback model/provider when the no-visible-key Grok CLI fallback is promoted to primary, so the cleared fallback pair doesn't leave the session on the superseded primary's thinking level
- Route workflow-step fallback thinking level by which fallback candidate (validatorFallback vs globalFallback) actually matched
- Document fallbackThinkingLevel runtime-swap behavior in docs/settings-reference.md
- Add minor changeset for @runfusion/fusion
- Add regression tests covering fallback thinking-level resolution and application (agent-session-helpers.test.ts, pi.test.ts) and a shared test helper (executor-test-helpers.ts)

Files changed:
 .changeset/fn-7794-fallback-thinking-level.md      |   7 ++
 docs/settings-reference.md                         |   3 +
 .../src/__tests__/agent-session-helpers.test.ts    |  38 ++++++
 .../engine/src/__tests__/executor-test-helpers.ts  |  23 ++++
 packages/engine/src/__tests__/pi.test.ts           | 136 +++++++++++++++++++++
 packages/engine/src/agent-heartbeat.ts             |   3 +-
 packages/engine/src/agent-runtime.ts               |   5 +
 packages/engine/src/agent-session-helpers.ts       |  54 ++++++++
 packages/engine/src/executor.ts                    |  31 ++++-
 packages/engine/src/index.ts                       |   5 +
 packages/engine/src/merger.ts                      |   7 +-
 packages/engine/src/pi.ts                          |  16 ++-
 packages/engine/src/reviewer.ts                    |   6 +
 13 files changed, 327 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7794

Fusion-Task-Lineage: c94d621a-ccbd-42b2-9fe6-cb619418ad90

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 11:53:07 -07:00
gsxdsm
d80cdd2b3b FN-7787: honor assigned agent's runtimeConfig model in task execution sessions
Task execution sessions previously ignored the assigned permanent agent's
runtimeConfig model whenever the executor was handed an agents-less
worktree AgentStore, silently drifting to the pi runtime's built-in
default model instead of the configured one.

- Add TaskExecutor.getAuthoritativeAssignedAgent(): falls back to the
  authoritative project `.fusion` AgentStore when the live executor's
  worktree AgentStore has no record of the assigned agent, so
  runtimeConfig resolution matches chat-session behavior.
- Replace direct `this.options.agentStore.getAgent(...)` lookups across
  step-session, workflow-graph, and legacy execution paths with the new
  authoritative lookup helper.
- Warn and audit (`noModelResolved` / `runtimeBuiltInFallbackModel`) when
  a non-mock, non-test-mode session resolves no provider/model pair and
  falls back to the runtime's built-in default, so the drift is visible
  instead of silent.
- Add regression tests covering assigned-agent runtime-config resolution
  and the new runtime-resolved audit fields.
- Add changeset (patch) and update docs/settings-reference.md and
  AGENTS.md.

Files changed:
 .changeset/fuzzy-fable-fallback.md                 |  7 +++
 AGENTS.md                                          |  1 +
 docs/settings-reference.md                         |  2 +-
 .../executor-assigned-agent-runtime-config.test.ts | 68 ++++++++++++++++++++++
 .../run-audit-session-runtime-resolved.test.ts     | 44 ++++++++++++++
 packages/engine/src/agent-session-helpers.ts       | 31 +++++++---
 packages/engine/src/executor.ts                    | 43 +++++++++-----
 7 files changed, 174 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-7787

Fusion-Task-Lineage: 40fccad5-2e67-4ee2-8199-4548ce9025c6

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 10:13:38 -07:00
gsxdsm
30bd7790e7 FN-7788: diagnose zero-NDJSON Grok CLI headless exits as a real failure
Fixes the residual "Grok CLI still returns no message immediately" case where a headless run exits code 0 but never emits any parsed NDJSON event, previously treated as a silent success.

- Detect a code-0 close with zero parsed NDJSON events and surface a diagnostic explaining the likely cause (wrong/unsupported grok binary falling into interactive mode and hitting EOF on stdin).
- Track and emit assistant text/diagnostics via a new appendMessage/emitDiagnosticText path so onText and session.state.errorMessage stay in sync, including on spawn failure and inactivity/first-line timeouts.
- Add first-line/inactivity timeout diagnostics with concrete elapsed-time messaging instead of silent kills.
- Add regression coverage in runtime-adapter.test.ts and grok-runtime-routing.test.ts for the zero-NDJSON exit path.
- Document the contract update in docs/grok-cli-contract.md.
- Add a patch changeset for @runfusion/fusion.

Files changed:
$(cat /tmp/diffstat_fn7788.txt)

Fusion-Task-Id: FN-7788

Fusion-Task-Lineage: dbb238a9-9601-47fc-8a88-40817d749337

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 10:01:49 -07:00
gsxdsm
035caca6c8 FN-7775: Add thinking level selection to new chat model picker
Adds a per-session thinking-level selector to the new chat model dropdown, persisting the choice through the chat store and engine session options.

- Adds thinkingLevel column to chat_sessions with a db migration
- Extends chat-store, chat-types, and chat.ts to read/write thinkingLevel
- ChatView model selector now exposes a thinking-level control alongside model choice
- useChat and register-chat-routes plumb thinkingLevel through session creation/API
- engine/src/index.ts passes thinkingLevel as defaultThinkingLevel session option
- Adds a minor changeset and updates settings-reference/dashboard-guide docs
- Adds/updates unit tests across core and dashboard packages

Files changed:
 .changeset/fn-7775-chat-thinking-level.md          |  7 ++
 docs/dashboard-guide.md                            |  1 +
 docs/settings-reference.md                         |  2 +-
 packages/core/src/__tests__/chat-store.test.ts     | 15 +++-
 packages/core/src/__tests__/db-migrate.test.ts     | 33 ++++++++
 packages/core/src/chat-store.ts                    | 12 ++-
 packages/core/src/chat-types.ts                    |  6 ++
 packages/core/src/db.ts                            | 14 +++-
 packages/dashboard/app/api/legacy.ts               |  2 +-
 packages/dashboard/app/components/ChatView.tsx     | 16 +++-
 .../__tests__/ChatView.core-interactions.test.tsx  | 75 +++++++++++++++---
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 17 +++-
 packages/dashboard/app/hooks/useChat.ts            |  6 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   | 90 ++++++++++++++++++++++
 packages/dashboard/src/chat.ts                     | 23 ++++++
 .../dashboard/src/routes/register-chat-routes.ts   | 25 +++++-
 packages/engine/src/index.ts                       |  1 +
 17 files changed, 318 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7775

Fusion-Task-Lineage: e16c7d3b-361e-4908-87ad-10be17a47c47

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 08:00:34 -07:00
gsxdsm
57c3d7ceb8 FN-7776: evaluate promptContribution.condition against effective plugin settings
Plugin prompt contributions declared a `condition` field in the SDK, but the host never evaluated it, so gated prompt content always rendered unconditionally.

- Add packages/core/src/plugin-prompt-condition.ts implementing a minimal, non-eval `settings["key"] === "value"` / `!==` condition grammar
- Wire condition evaluation into plugin-runner.ts / agent-instructions.ts / executor.ts / reviewer.ts / triage.ts / agent-heartbeat.ts so prompt contributions are filtered by effective plugin settings at each call site
- Extend plugin-types.ts and core index.ts/index.gate.ts to expose the new evaluator and condition typing
- Document the condition grammar in docs/PLUGIN_AUTHORING.md
- Add regression tests covering the evaluator and its wiring through plugin-runner and agent-instructions
- Add changeset (@runfusion/fusion minor, feature) describing the new gating behavior

Files changed:
 .changeset/fn-7776-prompt-condition.md             |  7 ++
 docs/PLUGIN_AUTHORING.md                           | 13 ++-
 .../src/__tests__/plugin-prompt-condition.test.ts  | 90 ++++++++++++++++++++
 packages/core/src/index.gate.ts                    |  6 ++
 packages/core/src/index.ts                         |  6 ++
 packages/core/src/plugin-prompt-condition.ts       | 51 +++++++++++
 packages/core/src/plugin-types.ts                  | 10 ++-
 .../src/__tests__/agent-instructions.test.ts       | 33 ++++++--
 .../engine/src/__tests__/plugin-runner.test.ts     | 98 +++++++++++++++++++++-
 packages/engine/src/agent-heartbeat.ts             |  2 +-
 packages/engine/src/agent-instructions.ts          |  6 +-
 packages/engine/src/executor.ts                    | 28 +++++--
 packages/engine/src/plugin-runner.ts               | 64 ++++++++++++--
 packages/engine/src/reviewer.ts                    |  2 +-
 packages/engine/src/triage.ts                      |  2 +-
 packages/plugin-sdk/src/index.ts                   |  4 +
 16 files changed, 385 insertions(+), 37 deletions(-)

Fusion-Task-Id: FN-7776

Fusion-Task-Lineage: ba8dcd52-260a-4166-a712-f3dd39b81b15

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 07:46:52 -07:00
gsxdsm
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>
2026-07-10 02:21:01 -07:00
gsxdsm
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>
2026-07-10 01:49:15 -07:00
gsxdsm
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>
2026-07-10 01:15:40 -07:00
gsxdsm
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>
2026-07-09 23:48:45 -07:00
gsxdsm
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>
2026-07-09 23:43:15 -07:00
gsxdsm
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>
2026-07-09 22:19:22 -07:00
gsxdsm
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>
2026-07-09 21:36:14 -07:00
gsxdsm
28c82331e7 FN-7755: upgrade bundled pi SDK to 0.80.6
Bumps the pi SDK dependencies to 0.80.6 across the CLI, dashboard, engine, and pi-claude-cli packages, and adapts the Claude CLI thinking-effort mapper for the new `max` ThinkingLevel.

- Bump @earendil-works/pi-ai and @earendil-works/pi-coding-agent from ^0.80.5 to ^0.80.6 in packages/cli, packages/dashboard, packages/engine, and packages/pi-claude-cli (dependency/peerDependency/devDependency entries)
- Regenerate pnpm-lock.yaml for the new SDK versions
- Map the new `max` ThinkingLevel in packages/pi-claude-cli/src/thinking-config.ts: non-Opus models downgrade to `high` (effort max unsupported), Opus models map to `max`
- Extend packages/pi-claude-cli/src/__tests__/thinking-config.test.ts with coverage for the `max` level
- Add .changeset/fn-7755-pi-sdk-bump.md (patch) documenting the SDK bump

Files changed:
 .changeset/fn-7755-pi-sdk-bump.md                  |  7 ++
 packages/cli/package.json                          |  4 +-
 packages/dashboard/package.json                    |  2 +-
 packages/engine/package.json                       |  4 +-
 packages/pi-claude-cli/package.json                |  8 +-
 .../src/__tests__/thinking-config.test.ts          | 12 +++
 packages/pi-claude-cli/src/thinking-config.ts      | 10 ++-
 pnpm-lock.yaml                                     | 92 +++++++++++-----------
 8 files changed, 82 insertions(+), 57 deletions(-)

Fusion-Task-Id: FN-7755

Fusion-Task-Lineage: f6a9084b-dfb9-4ad5-bd99-4627dae4c666

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 21:32:59 -07:00
gsxdsm
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>
2026-07-09 21:30:34 -07:00
gsxdsm
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>
2026-07-09 19:58:08 -07:00
gsxdsm
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>
2026-07-09 19:58:08 -07:00
gsxdsm
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>
2026-07-09 19:58:07 -07:00
gsxdsm
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>
2026-07-09 19:58:07 -07:00
gsxdsm
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>
2026-07-09 19:58:07 -07:00
gsxdsm
9d7b087188 FN-7742: bump pi SDK to 0.80.5 and add GPT-5.6 codex-tier model pricing
Updates the @earendil-works/pi SDK dependency and adds pricing entries for the new GPT-5.6 codex-tier models so Command Center reports real cost instead of unavailable.

- Bump @earendil-works/pi-ai and @earendil-works/pi-coding-agent from ^0.80.3 to ^0.80.5 in packages/cli, packages/dashboard, packages/engine, and packages/pi-claude-cli
- Add openai-codex:gpt-5.6-luna, openai-codex:gpt-5.6-sol, and openai-codex:gpt-5.6-terra pricing entries to model-pricing.ts, mirroring the existing gpt-5.3-codex rate
- Bump pricingAsOf to 2026-07-09
- Add regression tests covering the new GPT-5.6 pricing entries
- Add changeset (minor) for @runfusion/fusion
- Update pnpm-lock.yaml for the dependency bump

Files changed:
 .changeset/fn-7742-pi-sdk-gpt-5-6.md              |   7 +
 packages/cli/package.json                         |   4 +-
 packages/core/src/__tests__/model-pricing.test.ts |  14 +
 packages/core/src/model-pricing.ts                |  35 ++-
 packages/dashboard/package.json                   |   2 +-
 packages/engine/package.json                      |   4 +-
 packages/pi-claude-cli/package.json               |   8 +-
 pnpm-lock.yaml                                    | 323 ++++++++++++----------
 8 files changed, 246 insertions(+), 151 deletions(-)

Fusion-Task-Id: FN-7742

Fusion-Task-Lineage: 2fae3ac1-0877-4d12-b08f-d53d261f2fea

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 19:58:07 -07:00
gsxdsm
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>
2026-07-09 19:58:06 -07:00
gsxdsm
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>
2026-07-09 19:58:06 -07:00
gsxdsm
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>
2026-07-09 19:58:05 -07:00