feat(FN-4625): complete Step 7 — verification and docs updates
Fusion-Task-Id: FN-4625 Fusion-Task-Lineage: c1d9b414-b5dd-4786-ba51-0b8adec4acf5
This commit is contained in:
committed by
gsxdsm
parent
7c364da077
commit
8b371bae04
5
.changeset/fn-4625-worktrunk-onfailure.md
Normal file
5
.changeset/fn-4625-worktrunk-onfailure.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": minor
|
||||
---
|
||||
|
||||
Fail-hard by default when a delegated worktrunk operation fails: the task is paused with `pausedReason: "worktrunk_operation_failed"` and the underlying stderr is surfaced in the dashboard. Set `worktrunk.onFailure: "fallback-native"` to instead fall back transparently to Fusion's built-in worktree-pool and receive a one-shot dashboard alert per task.
|
||||
@@ -264,7 +264,7 @@ Sandbox backend precedence is:
|
||||
| --- | --- | --- | --- |
|
||||
| `worktrunk.enabled` | `boolean` | `false` | Enables `WorktreeBackend` selection in `packages/engine/src/worktree-backend.ts`. Tier: global + project, merged field-by-field with project overrides. |
|
||||
| `worktrunk.binaryPath` | `string \| undefined` | `undefined` | Optional absolute `worktrunk` binary path passed to the worktrunk backend. Tier: global + project with field-level precedence (project overrides only this field when set). |
|
||||
| `worktrunk.onFailure` | `"fail" \| "fallback-native"` | `"fail"` | Worktrunk failure mode in `packages/engine/src/worktree-backend.ts`: `fail` rethrows the backend error; `fallback-native` retries once with native `git worktree` and records fallback audit telemetry. Binary auto-install (FN-4624), dashboard settings UX (FN-4627), and CLI setter wiring (FN-4629) are downstream follow-ups. |
|
||||
| `worktrunk.onFailure` | `"fail" \| "fallback-native"` | `"fail"` | Failure disposition for delegated worktrunk operations (`create`, `sync`, `prune`, `remove`, install/resolve): `fail` (default) pauses the task with `pausedReason: "worktrunk_operation_failed"`, persists `task.worktrunkFailure`, and emits `worktree:worktrunk-failure`; `fallback-native` emits `worktree:worktrunk-fallback-native`, sends a one-shot per-task fallback alert guarded by `task.worktrunkFallbackAlertedAt`, then retries against native `git worktree`. |
|
||||
| `worktrunk.installedBinaryPath` | `string \| undefined` | `undefined` | Cached install path set by the auto-install flow. Managed by the engine; not intended for manual editing. Tier: global + project with field-level precedence. |
|
||||
|
||||
### Worktrunk auto-install flow
|
||||
@@ -286,7 +286,13 @@ Fusion maintains a pinned release version (`WORKTRUNK_PINNED_RELEASE` in `packag
|
||||
|
||||
If the platform has no pinned release asset, or if the release download/verification fails, Fusion falls back to `cargo install worktrunk --version <pinned>` when `cargo` is on `$PATH`. After cargo install, Fusion probes `$PATH` and `~/.cargo/bin/worktrunk` for the installed binary.
|
||||
|
||||
If both release and cargo paths fail, the install throws `WorktrunkInstallFailedError` and the worktrunk backend's `onFailure` setting determines whether the task pauses or falls back to native worktree operations.
|
||||
If both release and cargo paths fail, the install throws `WorktrunkInstallFailedError` and `worktrunk.onFailure` governs disposition (`fail` → pause task, `fallback-native` → native fallback with one-shot alert).
|
||||
|
||||
When fail-hard disposition is used, the task carries structured diagnostics:
|
||||
|
||||
- `pausedReason: "worktrunk_operation_failed"`
|
||||
- `worktrunkFailure: { op, stderr, exitCode, attemptedAt }`
|
||||
- `worktrunkFallbackAlertedAt` remains unset unless `fallback-native` is used
|
||||
|
||||
#### `network_api` action-gate
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ describe("acquireTaskWorktree backend wiring", () => {
|
||||
const task = { id: "FN-1", title: "Task", description: "Desc", branch: null, worktree: null } as any;
|
||||
const store = {
|
||||
updateTask: vi.fn().mockResolvedValue(undefined),
|
||||
pauseTask: vi.fn().mockResolvedValue(undefined),
|
||||
logEntry: vi.fn().mockResolvedValue(undefined),
|
||||
} as any;
|
||||
|
||||
@@ -30,6 +31,7 @@ describe("acquireTaskWorktree backend wiring", () => {
|
||||
execMock.mockReset();
|
||||
store.updateTask.mockClear();
|
||||
store.logEntry.mockClear();
|
||||
store.pauseTask.mockClear();
|
||||
});
|
||||
|
||||
it("uses native backend by default and emits no worktrunk audit", async () => {
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
} from "./worktrunk-installer.js";
|
||||
import {
|
||||
handleWorktrunkOperationFailure,
|
||||
type WorktreeOperationResult,
|
||||
type WorktrunkOpName,
|
||||
} from "./worktrunk-failure-handler.js";
|
||||
import type { RunAuditor } from "./run-audit.js";
|
||||
@@ -125,7 +126,7 @@ export async function acquireTaskWorktree(opts: AcquireTaskWorktreeOptions): Pro
|
||||
runContext,
|
||||
runAudit: audit,
|
||||
notify: ({ op: failedOp, stderr: failedStderr }) => notifyFallback(failedOp, failedStderr),
|
||||
nativeFallback: nativeFallback as (() => Promise<any>) | undefined,
|
||||
nativeFallback: nativeFallback as (() => Promise<WorktreeOperationResult>) | undefined,
|
||||
});
|
||||
if (disposition.kind === "fallback-native") {
|
||||
return disposition.result;
|
||||
|
||||
Reference in New Issue
Block a user