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
+10 -5
View File
@@ -10,6 +10,11 @@ const muted = { color: "var(--qai-ink-muted)" };
const small = { fontSize: "var(--qai-text-xs)", color: "var(--qai-ink-muted)" };
const disp = { fontFamily: "var(--qai-font-display)" };
// Model output is untrusted: the schema says a number is optional, models still send null, and one throw
// deletes the whole block from the report. 0 is the honest stand-in for "the model did not give a number".
const num = (v: unknown) => (typeof v === "number" && Number.isFinite(v) ? v : 0);
const conf = (v: unknown) => (typeof v === "number" ? ` ${v.toFixed(2)}` : " not reported");
const renderers: Record<string, (x: any) => any> = {
Headline: ({ props }) => el("header", null,
el("p", { className: "label" }, props.severity === "critical" ? "Critical" : props.severity === "warning" ? "Warning" : "Note"),
@@ -50,14 +55,14 @@ const renderers: Record<string, (x: any) => any> = {
props.caption ? el("p", { style: small }, props.caption) : null),
ScoreBar: ({ props }) => el("div", null,
el("p", { className: "label" }, props.label + (props.confidence !== undefined
? ` · confidence ${props.confidence.toFixed(2)}` : " · no confidence reported")),
el("div", { className: "bar", style: { width: `${Math.round(props.value * 100)}%` } }),
el("p", { className: "label" }, props.label + (props.confidence === undefined
? " · no confidence reported" : ` · confidence${conf(props.confidence)}`)),
el("div", { className: "bar", style: { width: `${Math.round(num(props.value) * 100)}%` } }),
props.note ? el("p", { style: small }, props.note) : null),
OptionRow: ({ props }) => el("tr", { "data-headline": props.headline || undefined },
el("td", null, String(props.rank)), el("td", null, props.title),
el("td", { className: "sql" }, props.composite.toFixed(2)),
el("td", { className: "sql" }, num(props.composite).toFixed(2)),
el("td", null, props.flags || "—")),
OptionTable: ({ props, renderNode }: any) => el("section", { className: "card" },
@@ -67,7 +72,7 @@ const renderers: Record<string, (x: any) => any> = {
VerdictBlock: ({ props }) => el("section", { className: "card", "data-verdict": "" },
el("p", { className: "label" }, "First move · " + (props.source === "jev"
? `Jev, confidence ${props.confidence.toFixed(2)}` : "composite order — Jev did not decide")),
? `Jev, confidence${conf(props.confidence)}` : "composite order — Jev did not decide")),
p({ ...disp, fontSize: "var(--qai-text-lg)" }, props.headline),
p({}, props.why)),