feat(FN-4698): complete verification and docs updates
Fusion-Task-Id: FN-4698 Fusion-Task-Lineage: 267131ce-b02a-4e54-8d71-c949e3b55e56
This commit is contained in:
committed by
gsxdsm
parent
6e74f6366c
commit
e1e21f6462
9
.changeset/fn-4698-worktrunk-path-resolution.md
Normal file
9
.changeset/fn-4698-worktrunk-path-resolution.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Reconcile worktrunk backend path contract: resolve the actual worktree
|
||||
path via `git worktree list --porcelain` after `wt switch --create`
|
||||
instead of assuming worktrunk uses Fusion's `.worktrees/<task-id>`
|
||||
layout. Fixes silent `task.worktree` drift on worktrunk-enabled
|
||||
projects.
|
||||
@@ -1462,6 +1462,7 @@ When a tracked task transitions into `done`, Fusion closes the linked GitHub iss
|
||||
- Backend contract: `WorktreeBackend` (`packages/engine/src/worktree-backend.ts`, re-exported via `packages/engine/src/worktree-pool.ts`).
|
||||
- Implementations: `NativeWorktreeBackend` (Fusion-managed `git worktree` flow) and `WorktrunkWorktreeBackend` (delegates to external `worktrunk` CLI).
|
||||
- Backend selection is driven by `worktrunk.enabled`; when enabled, worktrunk-managed layout overrides `worktreesDir` for delegated operations.
|
||||
- Worktrunk layout is authoritative on create: after `wt switch --create`, Fusion resolves the actual registered worktree path via `git worktree list --porcelain` and uses that path (instead of assuming `resolveTaskWorktreePath` alignment).
|
||||
- Delegated operation surface in the interface: `create`, `sync`, `prune`, `remove` (plus backend path resolution via `resolveWorktreePath`).
|
||||
- Executor acquisition paths (`worktree-acquisition.ts`) resolve backend selection centrally, so create flow stays backend-agnostic above the pool/acquisition layer.
|
||||
- Self-healing is worktrunk-aware for failure recovery: tasks paused with `pausedReason: "worktrunk_operation_failed"` are explicitly skipped in reclaim sweeps (`self-healing.ts`) until operator intervention.
|
||||
|
||||
@@ -11,13 +11,14 @@ vi.mock("../worktree-db-hydrate.js", () => ({
|
||||
hydrateWorktreeDb: vi.fn().mockResolvedValue({ degraded: false, tasksCopied: 1, documentsCopied: 1 }),
|
||||
}));
|
||||
|
||||
const { execMock } = vi.hoisted(() => {
|
||||
const { execMock, existsSyncMock } = vi.hoisted(() => {
|
||||
const mock = vi.fn();
|
||||
(mock as any)[Symbol.for("nodejs.util.promisify.custom")] = mock;
|
||||
return { execMock: mock };
|
||||
return { execMock: mock, existsSyncMock: vi.fn() };
|
||||
});
|
||||
|
||||
vi.mock("node:child_process", () => ({ exec: execMock }));
|
||||
vi.mock("node:fs", () => ({ existsSync: existsSyncMock }));
|
||||
|
||||
describe("acquireTaskWorktree backend wiring", () => {
|
||||
const task = { id: "FN-1", title: "Task", description: "Desc", branch: null, worktree: null } as any;
|
||||
@@ -29,6 +30,8 @@ describe("acquireTaskWorktree backend wiring", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
execMock.mockReset();
|
||||
existsSyncMock.mockReset();
|
||||
existsSyncMock.mockReturnValue(true);
|
||||
store.updateTask.mockClear();
|
||||
store.logEntry.mockClear();
|
||||
store.pauseTask.mockClear();
|
||||
@@ -58,7 +61,17 @@ describe("acquireTaskWorktree backend wiring", () => {
|
||||
});
|
||||
|
||||
it("routes through worktrunk backend when enabled and emits audit once", async () => {
|
||||
execMock.mockResolvedValue({ stdout: "", stderr: "" });
|
||||
execMock.mockImplementation((command: string) => {
|
||||
if (command.includes('"config" "show"')) return Promise.resolve({ stdout: "", stderr: "" });
|
||||
if (command.includes('"switch" "--create"')) return Promise.resolve({ stdout: "", stderr: "" });
|
||||
if (command === "git worktree list --porcelain") {
|
||||
return Promise.resolve({
|
||||
stdout: "worktree /repo/.worktrees/fusion/fn-1\nbranch refs/heads/fusion/fn-1\n",
|
||||
stderr: "",
|
||||
});
|
||||
}
|
||||
return Promise.resolve({ stdout: "", stderr: "" });
|
||||
});
|
||||
const audit = { git: vi.fn().mockResolvedValue(undefined) };
|
||||
|
||||
await acquireTaskWorktree({
|
||||
|
||||
Reference in New Issue
Block a user