fix(FN-3716): stabilize verification and role policy checks

- Add shared agent role policy helpers for implementation task detection and executor-role enforcement
- Provide a standardized role-mismatch error formatter for delegation and assignment paths
- Update test isolation leak detection to ignore ephemeral fusion-test-home-root temp directories while preserving baseline checks

Fusion-Task-Id: FN-3716
This commit is contained in:
Fusion
2026-05-08 02:00:04 -07:00
committed by gsxdsm
parent 30d0553c64
commit c0a2adf516
18 changed files with 365 additions and 15 deletions

View File

@@ -11,6 +11,8 @@ import {
resolveTitleSummarizerSettingsModel,
toReplicatedCreateInput,
validateNodeOverrideChange,
canAgentTakeImplementationTask,
formatRoleMismatchReason,
} from "@fusion/core";
import { planTaskWorktreePath } from "@fusion/engine";
import { ApiError, badRequest, conflict, notFound } from "../api-error.js";
@@ -1662,7 +1664,7 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
// Assign or unassign a task to an explicit agent
router.patch("/tasks/:id/assign", async (req, res) => {
try {
const { agentId } = req.body as { agentId?: string | null };
const { agentId, override } = req.body as { agentId?: string | null; override?: boolean };
if (agentId !== null && typeof agentId !== "string") {
throw badRequest("agentId must be a string or null");
}
@@ -1680,6 +1682,15 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
if (!agent) {
throw notFound("Agent not found");
}
const targetTask = await scopedStore.getTask(req.params.id);
if (!targetTask) {
throw notFound("Task not found");
}
if (override !== true && !canAgentTakeImplementationTask(agent, targetTask)) {
throw new ApiError(409, formatRoleMismatchReason(agent, targetTask));
}
}
const task = await scopedStore.updateTask(req.params.id, {