feat(FN-4132): sync task ownership on agent reassignment

Adds a task reassignment sync helper to the core store, wires it into the system, and ships regression tests; includes a patch changeset for `@runfusion/fusion`.

Fusion-Task-Id: FN-4132

Fusion-Task-Lineage: 80ec3c62-7c09-49dd-9e49-74b203e48bf4
This commit is contained in:
Fusion
2026-05-12 10:04:56 -07:00
committed by gsxdsm
parent a289c00631
commit 6c1cb40c35
6 changed files with 264 additions and 11 deletions

View File

@@ -3677,6 +3677,20 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
...(runContext ? { runContext } : {}),
});
}
if (assignmentChanged) {
this.syncAgentTaskLinkOnReassignment(id, previousAssignedAgentId, task.assignedAgentId);
if (task.checkedOutBy === previousAssignedAgentId) {
task.checkedOutBy = undefined;
task.checkedOutAt = undefined;
}
task.log.push({
timestamp: new Date().toISOString(),
action: `Agent task link synced: ${previousAssignedAgentId ?? "none"}${task.assignedAgentId ?? "none"}`,
...(runContext ? { runContext } : {}),
});
}
if (updates.pausedByAgentId === null) {
task.pausedByAgentId = undefined;
} else if (updates.pausedByAgentId !== undefined) {
@@ -4595,6 +4609,51 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
`).run(updatedAt, updatedAt, taskId);
}
/**
* Sync `agents.taskId` when {@link updateTask} reassigns a task.
*
* Uses direct SQL against the shared `agents` table instead of AgentStore to
* avoid a circular dependency while keeping the column and JSON data blob in
* lockstep. Clearing the previous agent is race-guarded with `WHERE id = ?
* AND taskId = ?` so we do not clobber an agent that already moved on to a
* different task.
*/
private syncAgentTaskLinkOnReassignment(
taskId: string,
previousAgentId: string | undefined,
newAgentId: string | undefined,
): void {
const updatedAt = new Date().toISOString();
if (previousAgentId) {
this.db.prepare(`
UPDATE agents
SET
taskId = NULL,
updatedAt = ?,
data = CASE
WHEN json_valid(data) THEN json_set(json_remove(data, '$.taskId'), '$.updatedAt', ?)
ELSE data
END
WHERE id = ? AND taskId = ?
`).run(updatedAt, updatedAt, previousAgentId, taskId);
}
if (newAgentId) {
this.db.prepare(`
UPDATE agents
SET
taskId = ?,
updatedAt = ?,
data = CASE
WHEN json_valid(data) THEN json_set(data, '$.taskId', ?, '$.updatedAt', ?)
ELSE data
END
WHERE id = ?
`).run(taskId, updatedAt, taskId, updatedAt, newAgentId);
}
}
/**
* Clean up the git branch associated with a task.
*