fix(confidence-engine): log case-start failures

This commit is contained in:
2026-09-05 14:37:29 +01:00
parent 72324e63c8
commit 8c3edfec7d
3 changed files with 66 additions and 3 deletions
+22 -2
View File
@@ -16,10 +16,25 @@ export async function POST(request) {
? result.statusCode
: 500;
const diagnostics = {
status,
error: result.error ?? "Start case failed",
validationErrors: result.validationErrors,
analysisErrors: result.analysisErrors,
validationIssues: result.validationIssues,
rawResponse: result.rawResponse ?? undefined,
};
if (status >= 500) {
console.error("[api/cases/start] error response", diagnostics);
} else {
console.warn("[api/cases/start] error response", diagnostics);
}
return Response.json(
{
success: false,
error: result.error ?? "Start case failed",
error: diagnostics.error,
validationErrors: result.validationErrors,
diagnostics: result.diagnostics,
analysisErrors: result.analysisErrors,
@@ -28,7 +43,12 @@ export async function POST(request) {
},
{ status },
);
} catch {
} catch (error) {
console.error("[api/cases/start] unhandled exception", {
message: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
error,
});
return Response.json(
{
success: false,
+6
View File
@@ -57,6 +57,12 @@
- This is a generation-time relationship-reference integrity defect. v0.5 now requires semantic units before relationships and exact reuse of emitted endpoint IDs; legitimate missing endpoint concepts must be materialised first under existing provenance rules.
- The builder remains unchanged. Live compliance remains untested; next restart point is one production-default relationship-reference-integrity validation.
## Case-start error logging
- The latest live validation was blocked by an HTTP 500 route-level exception with generic client output. `/api/cases/start` now writes structured Next.js server-console diagnostics for every route-owned error response: 4xx at warning level and 5xx/502 at error level.
- Caught exceptions log their actual exception, message, and stack while the client response remains generic; successful responses are not logged. No reasoning, status, or response semantics changed.
- Next restart point: one production-default manufacturing call while observing the Next.js dev-server terminal.
## Current product architecture
Three distinct routes, not a single page:
+38 -1
View File
@@ -1,6 +1,8 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
const mockStartCase = vi.fn();
let warnSpy;
let errorSpy;
vi.mock("@/lib/graph/orchestrator.js", () => ({
startCase: (...args) => mockStartCase(...args),
@@ -10,6 +12,13 @@ describe("app/api/cases/start route", () => {
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
});
afterEach(() => {
warnSpy.mockRestore();
errorSpy.mockRestore();
});
it("delegates request body to the orchestrator", async () => {
@@ -78,6 +87,8 @@ describe("app/api/cases/start route", () => {
success: true,
reconstruction,
});
expect(warnSpy).not.toHaveBeenCalled();
expect(errorSpy).not.toHaveBeenCalled();
});
it("returns 400 for invalid request input", async () => {
@@ -102,6 +113,12 @@ describe("app/api/cases/start route", () => {
success: false,
error: "Invalid start-case request",
});
expect(warnSpy).toHaveBeenCalledTimes(1);
expect(warnSpy).toHaveBeenCalledWith(
"[api/cases/start] error response",
expect.objectContaining({ status: 400, error: "Invalid start-case request" }),
);
expect(errorSpy).not.toHaveBeenCalled();
});
it("returns provider/internal failures as 5xx without stack traces", async () => {
@@ -148,6 +165,18 @@ describe("app/api/cases/start route", () => {
received: "undefined",
}),
]);
expect(errorSpy).toHaveBeenCalledTimes(1);
expect(errorSpy).toHaveBeenCalledWith(
"[api/cases/start] error response",
expect.objectContaining({
status: 502,
error: "Provider unavailable",
analysisErrors: ["reconstruction: Required"],
validationIssues: expect.any(Array),
rawResponse,
}),
);
expect(warnSpy).not.toHaveBeenCalled();
});
it("returns structured 500 on malformed JSON", async () => {
@@ -163,5 +192,13 @@ describe("app/api/cases/start route", () => {
success: false,
error: "Internal server error",
});
expect(errorSpy).toHaveBeenCalledWith(
"[api/cases/start] unhandled exception",
expect.objectContaining({
message: "Unexpected token",
stack: expect.any(String),
error: expect.any(Error),
}),
);
});
});