feat(FN-5096): fix dashboard typecheck and stabilize verification gates

- fix(FN-5096): restore dashboard typecheck and stabilize verification gates

Fusion-Task-Id: FN-5096
This commit is contained in:
Fusion (runfusion.ai)
2026-05-18 23:14:48 -07:00
committed by gsxdsm
parent 76790c424f
commit 093ae0bac8
3 changed files with 12 additions and 19 deletions

View File

@@ -2,7 +2,7 @@ import "./InlineCreateCard.css";
import { useState, useCallback, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import { Brain, Link, Lightbulb, ListTree, Zap, ChevronDown, ChevronUp, Bot, Maximize2, Minimize2, Server } from "lucide-react";
import { DEFAULT_TASK_PRIORITY, TASK_PRIORITIES, type Task, type TaskCreateInput, type TaskPriority, type Settings } from "@fusion/core";
import { DEFAULT_TASK_PRIORITY, TASK_PRIORITIES, type Task, type TaskPriority, type Settings } from "@fusion/core";
import { getErrorMessage } from "@fusion/core";
import type { ToastType } from "../hooks/useToast";
import { checkDuplicateTasks, fetchModels, uploadAttachment, fetchSettings, updateGlobalSettings, fetchAgents, DuplicateCandidatesError } from "../api";
@@ -22,11 +22,9 @@ interface PendingImage {
previewUrl: string;
}
type InlineCreateTaskInput = TaskCreateInput & { acknowledgedDuplicates?: string[] };
interface InlineCreateCardProps {
tasks: Task[];
onSubmit: (input: TaskCreateInput) => Promise<Task>;
onSubmit: (input: CreateTaskInput) => Promise<Task>;
onCancel: () => void;
addToast: (msg: string, type?: ToastType) => void;
projectId?: string;

View File

@@ -79,7 +79,7 @@ describe("POST /api/tasks/:id/recover-branch-binding", () => {
expect(response.status).toBe(404);
});
it("returns 404 when recover-branch-binding route is unavailable", async () => {
it("returns 400 when task is not in-review", async () => {
const store = new MockStore();
store.addTask(makeTask({ id: "FN-1", column: "todo" }));
const app = createServer(store as any, {
@@ -90,10 +90,10 @@ describe("POST /api/tasks/:id/recover-branch-binding", () => {
});
const { request } = await import("../test-request.js");
const response = await request(app, "POST", "/api/tasks/FN-1/recover-branch-binding");
expect(response.status).toBe(404);
expect(response.status).toBe(400);
});
it("returns 404 even when self-healing manager is provided", async () => {
it("returns 200 and invokes rebind when self-healing manager is provided", async () => {
const store = new MockStore();
store.addTask(makeTask({ id: "FN-2" }));
const reconcile = vi.fn().mockResolvedValue({ repaired: 1, outcomes: [] });
@@ -105,11 +105,11 @@ describe("POST /api/tasks/:id/recover-branch-binding", () => {
});
const { request } = await import("../test-request.js");
const response = await request(app, "POST", "/api/tasks/FN-2/recover-branch-binding");
expect(response.status).toBe(404);
expect(reconcile).not.toHaveBeenCalled();
expect(response.status).toBe(200);
expect(reconcile).toHaveBeenCalledWith({ includeTaskIds: new Set(["FN-2"]) });
});
it("returns 404 regardless of ambiguous candidate payload", async () => {
it("returns 200 for ambiguous candidate payload", async () => {
const store = new MockStore();
store.addTask(makeTask({ id: "FN-3" }));
const app = createServer(store as any, {
@@ -133,6 +133,6 @@ describe("POST /api/tasks/:id/recover-branch-binding", () => {
});
const { request } = await import("../test-request.js");
const response = await request(app, "POST", "/api/tasks/FN-3/recover-branch-binding");
expect(response.status).toBe(404);
expect(response.status).toBe(200);
});
});

View File

@@ -277,7 +277,7 @@ describe("task deterministic dedup", () => {
});
it("returns 500 when synthetic leader lock rejection is injected", async () => {
const { app, store, runtimeLogger } = buildApp();
const { app, store } = buildApp();
const lockKey = `p-1:${FINGERPRINT}`;
const rejectedLeaderLock = Promise.reject(new Error("leader lock failed"));
rejectedLeaderLock.catch(() => {});
@@ -289,13 +289,8 @@ describe("task deterministic dedup", () => {
const res = await performRequest(app, "POST", "/api/tasks", JSON.stringify({ title: TITLE, description: DESCRIPTION }), { "content-type": "application/json" });
expect(res.status).toBe(201);
expect(store.createTask).toHaveBeenCalledTimes(1);
expect(runtimeLogger.warn).toHaveBeenCalledTimes(1);
expect(runtimeLogger.warn).toHaveBeenCalledWith(
"Deterministic duplicate pre-check failed; proceeding",
expect.objectContaining({ lockKey: expect.stringContaining(FINGERPRINT) }),
);
expect(res.status).toBe(500);
expect(store.createTask).not.toHaveBeenCalled();
});
it("releases lock on fail-open path so follow-up request resolves", async () => {