feat(FN-4092): complete Step 3 — advisory fallthrough for plan/spec unavailable

Fusion-Task-Id: FN-4092
Fusion-Task-Lineage: fcee3a44-5c36-4899-bf9d-835d36abdf2e
This commit is contained in:
Fusion
2026-05-13 02:44:01 -07:00
committed by gsxdsm
parent 6fadb92025
commit 688a764db1
2 changed files with 60 additions and 1 deletions

View File

@@ -404,6 +404,43 @@ describe("Code review verdict tracking", () => {
const updateResult = await tools.fn_task_update("call2", { step: 1, status: "done" });
expect(updateResult.content[0].text).toContain("→ done");
});
it("plan review UNAVAILABLE is advisory and does not block step completion", async () => {
mockedReviewStep.mockResolvedValue({
verdict: "UNAVAILABLE",
review: "Reviewer unavailable",
summary: "No verdict",
});
const tools = await captureTools();
const result = await tools.fn_review_step("call1", {
step: 0,
type: "plan",
step_name: "Implement",
});
expect(result.content[0].text).toContain("UNAVAILABLE (advisory)");
const updateResult = await tools.fn_task_update("call2", { step: 1, status: "done" });
expect(updateResult.content[0].text).toContain("→ done");
});
it("code review UNAVAILABLE remains blocking guidance", async () => {
mockedReviewStep.mockResolvedValue({
verdict: "UNAVAILABLE",
review: "Reviewer unavailable",
summary: "No verdict",
});
const tools = await captureTools();
const result = await tools.fn_review_step("call1", {
step: 0,
type: "code",
step_name: "Implement",
baseline: "abc123",
});
expect(result.content[0].text).toContain("Code review remains blocking");
});
});
describe("Code review verdict enforcement - fn_task_update blocking", () => {

View File

@@ -4428,6 +4428,7 @@ export class TaskExecutor {
): ToolDefinition {
const store = this.store;
const options = this.options;
const planSpecUnavailableCounts = new Map<string, number>();
return {
name: "fn_review_step",
@@ -4637,7 +4638,28 @@ export class TaskExecutor {
}
break;
}
default: text = "UNAVAILABLE — reviewer did not produce a usable verdict.";
default:
if (reviewType === "plan" || reviewType === "spec") {
const key = `${reviewType}:${step}`;
const count = (planSpecUnavailableCounts.get(key) ?? 0) + 1;
planSpecUnavailableCounts.set(key, count);
const advisoryMessage = `${reviewType} review Step ${step}: UNAVAILABLE — proceeding advisory after fallback retry exhausted`;
await store.logEntry(taskId, advisoryMessage);
reviewerLog.warn(`${taskId}: ${advisoryMessage}`);
if (count >= 2) {
await store.logEntry(
taskId,
`${reviewType} review Step ${step}: repeated UNAVAILABLE (${count}) — advisory continuation active; operator may inspect reviewer logs in dashboard`,
);
}
text = `UNAVAILABLE (advisory) — reviewer could not produce a verdict after fallback retry. ${reviewType === "plan" ? "Plan" : "Spec"} reviews are advisory; proceed with implementation. Do NOT re-call fn_review_step for the ${reviewType} of Step ${step}.`;
} else {
const blockingMessage = `code review Step ${step}: UNAVAILABLE — blocking until reviewer returns a usable verdict`;
await store.logEntry(taskId, blockingMessage);
reviewerLog.warn(`${taskId}: ${blockingMessage}`);
text = "UNAVAILABLE — reviewer did not produce a usable verdict. Code review remains blocking; retry once or escalate via dashboard.";
}
break;
}
return { content: [{ type: "text" as const, text }], details: {} };