fix: final review pass — email collision, orphaned-run loop, null confidence guards

- changeEmail validates and refuses an address another account owns (users.email is UNIQUE; a collision was a 500 inside the settings form).
- /app/[id] no longer redirects a 'running' row to itself; it renders what exists and says the run was interrupted.
- ScoreBar / OptionRow / VerdictBlock survive null numbers from the model instead of throwing and losing the block (seen live: '[openui] runtime/render-error: Component ScoreBar render failed').
- drop the ad-hoc render-debug scripts now that Playwright covers the browser.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
ahmed mohammed
2026-09-22 09:10:29 +03:00
co-authored by Claude Opus 4.7
parent 07dd3d6bf8
commit 5160a00db5
12 changed files with 101 additions and 80 deletions
+13
View File
@@ -13,3 +13,16 @@ test("every spec has a renderer, so the model can never emit an unrenderable blo
const { library } = await import("../lib/report-ui.ts");
for (const s of specs) assert.ok(library.components[s.name], `no renderer for ${s.name}`);
});
test("a null confidence from the model does not blank the block", async () => {
// The prompt says optional; models still send null. confidence != undefined let null through to .toFixed().
const { library } = await import("../lib/report-ui.ts");
const renderNode = () => null;
for (const [name, props] of [
["ScoreBar", { label: "fit", value: 0.5, confidence: null }],
["VerdictBlock", { headline: "h", why: "w", source: "jev", confidence: null }],
] as const) {
const el = library.components[name].component({ props: props as any, renderNode } as any);
assert.ok(el, `${name} returned nothing`);
}
});