fix(engine): bind self-owned worktree liveness probe (#3419)
## Summary Supersedes #3416 — the fork head is not writable from maintainers, so this branch carries the same fix merged onto current `main`. ## Changes - Bind the self-owned worktree liveness probe in task-executor pure facades (from #3416). - Merge current main so the lifecycle-column census baseline stays green. ## Test plan - [x] `pnpm check:lifecycle-columns` clean after merge - [ ] CI green Closes context from #3416. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed cleanup for self-owned worktrees so it no longer crashes before checking whether an active session is present. * Improved safety during worktree reconciliation by correctly verifying that the worktree is still active before removal. * **Documentation** * Added a changeset documenting the worktree cleanup fix. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: BESA-Franz <49682134+BESA-Franz@users.noreply.github.com>
This commit is contained in:
7
.changeset/bind-self-owned-worktree-probe.md
Normal file
7
.changeset/bind-self-owned-worktree-probe.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
summary: Prevent worktree conflict cleanup from crashing before its active-session safety check.
|
||||||
|
category: fix
|
||||||
|
dev: Binds the executor live-worktree probe when the self-owned reconcile facade calls its extracted helper.
|
||||||
@@ -22,7 +22,23 @@ export abstract class TaskExecutorWorktreePureFacades extends TaskExecutorState
|
|||||||
protected async isLiveCleanupRefusal(worktreePath: string, taskId: string): Promise<boolean> { return pure.isLiveCleanupRefusal(this.activeWorktrees, this.store, worktreePath, taskId); }
|
protected async isLiveCleanupRefusal(worktreePath: string, taskId: string): Promise<boolean> { return pure.isLiveCleanupRefusal(this.activeWorktrees, this.store, worktreePath, taskId); }
|
||||||
protected async cleanupStaleBranch(branch: string, taskId: string): Promise<boolean> { return pure.cleanupStaleBranch(this.rootDir, this.store, branch, taskId); }
|
protected async cleanupStaleBranch(branch: string, taskId: string): Promise<boolean> { return pure.cleanupStaleBranch(this.rootDir, this.store, branch, taskId); }
|
||||||
protected async planSquashImportFromDep(...args: FacadeAfterSecond<typeof pure.planSquashImportFromDep>): ReturnType<typeof pure.planSquashImportFromDep> { return pure.planSquashImportFromDep(this.rootDir, this.store, ...args); }
|
protected async planSquashImportFromDep(...args: FacadeAfterSecond<typeof pure.planSquashImportFromDep>): ReturnType<typeof pure.planSquashImportFromDep> { return pure.planSquashImportFromDep(this.rootDir, this.store, ...args); }
|
||||||
protected async reconcileSelfOwnedBeforeRemove(...args: FacadeRestArgs<typeof pure.reconcileSelfOwnedBeforeRemove>): ReturnType<typeof pure.reconcileSelfOwnedBeforeRemove> { return pure.reconcileSelfOwnedBeforeRemove(this.store, ...args); }
|
/*
|
||||||
|
FNXC:WorktreeConflictRecovery 2026-08-10-20:31:
|
||||||
|
The free reconcile helper requires the executor's live-binding probe in addition to its store.
|
||||||
|
Bind that host-owned callback here so every two-argument facade caller receives the production
|
||||||
|
liveness guard instead of forwarding an undefined third argument into conflict cleanup.
|
||||||
|
*/
|
||||||
|
protected async reconcileSelfOwnedBeforeRemove(
|
||||||
|
worktreePath: string,
|
||||||
|
taskId: string,
|
||||||
|
): ReturnType<typeof pure.reconcileSelfOwnedBeforeRemove> {
|
||||||
|
return pure.reconcileSelfOwnedBeforeRemove(
|
||||||
|
this.store,
|
||||||
|
worktreePath,
|
||||||
|
taskId,
|
||||||
|
(ownerTaskId, path) => this.hasActiveWorktreeBinding(ownerTaskId, path),
|
||||||
|
);
|
||||||
|
}
|
||||||
protected async emitStaleLockAudit(...args: FacadeRestArgs<typeof pure.emitStaleLockAudit>): ReturnType<typeof pure.emitStaleLockAudit> { return pure.emitStaleLockAudit(bags.buildStaleLockRecoveryDeps(this), ...args); }
|
protected async emitStaleLockAudit(...args: FacadeRestArgs<typeof pure.emitStaleLockAudit>): ReturnType<typeof pure.emitStaleLockAudit> { return pure.emitStaleLockAudit(bags.buildStaleLockRecoveryDeps(this), ...args); }
|
||||||
protected async recoverIndexLockIfStale(taskId: string, path: string, conflictInfo: { lockPath?: string; message?: string }): Promise<boolean> { return pure.recoverIndexLockIfStale(bags.buildStaleLockRecoveryDeps(this), taskId, path, conflictInfo); }
|
protected async recoverIndexLockIfStale(taskId: string, path: string, conflictInfo: { lockPath?: string; message?: string }): Promise<boolean> { return pure.recoverIndexLockIfStale(bags.buildStaleLockRecoveryDeps(this), taskId, path, conflictInfo); }
|
||||||
protected async recoverStaleRegistration(taskId: string, path: string, conflictInfo: { path?: string; message?: string }): Promise<boolean> { return pure.recoverExecutorStaleRegistration(bags.buildStaleLockRecoveryDeps(this), taskId, path, conflictInfo); }
|
protected async recoverStaleRegistration(taskId: string, path: string, conflictInfo: { path?: string; message?: string }): Promise<boolean> { return pure.recoverExecutorStaleRegistration(bags.buildStaleLockRecoveryDeps(this), taskId, path, conflictInfo); }
|
||||||
|
|||||||
Reference in New Issue
Block a user