mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
feat(admin): AI quality preview showing per-(severity x provider) helpful-rate
v1.4.16 phase B5e: ship the `/admin/ai-quality` route that surfaces
the daily aggregator's helpful-rate per (severity x metricSourceType
x provider x prompt-version) bucket. Renders as a compact 7-column
table with severity tinted by clinical-importance colour and the
helpful-rate column tinted green/yellow/orange by 0.8/0.5
thresholds.
New endpoint `GET /api/admin/ai-quality` (requireAdmin-gated) returns
the raw `AppSettings.adminAiInsightsFeedbackSummary` blob so the
v1.4.17 ratchet that consumes the same shape for prompt-tuning can
read what the worker writes without an envelope-reshape step.
Empty state ("no summary yet" / "buckets[] is empty") rendered as a
quiet message rather than a fake zero row so the operator can tell
"no feedback" apart from "all-zeros". Loading + error banners follow
the existing host-metrics pattern.
Section wiring:
- new `ai-quality` slug in ADMIN_SECTION_SLUGS (between
integrations and feedback so the IA flows General → Integrations
→ AI Quality → Feedback Inbox)
- new Sparkles icon entry in admin-shell
- new switch case in [section]/renderer.tsx
- EN+DE i18n keys: admin.section.ai-quality.{title,subtitle} +
admin.aiQuality.{title,loading,loadError,empty,windowLabel,
generatedAtLabel,col*}
Tests:
- 5 new ai-quality-section tests (loading, empty-null, empty-buckets,
table-render with multiple buckets, error)
- 1 admin-sections smoke test ensures the empty branch renders +
1 slug-list parity test
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5117266756
commit
887928211b
9 files changed
+437
No files matched your search
@@ -0,0 +1,42 @@
|
||||
import { apiHandler, requireAdmin } from "@/lib/api-handler";
|
||||
import { apiSuccess } from "@/lib/api-response";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { prisma } from "@/lib/db";
|
||||
|
||||
/**
|
||||
* v1.4.16 phase B5e — admin AI quality preview.
|
||||
*
|
||||
* Returns the latest aggregator-written summary from
|
||||
* `AppSettings.adminAiInsightsFeedbackSummary`. The pg-boss
|
||||
* `feedback-aggregator` queue writes this row daily at 04:00
|
||||
* Europe/Berlin. requireAdmin() gates the endpoint — cross-user
|
||||
* helpful-rate slices are admin-only telemetry per research §3.
|
||||
*
|
||||
* The response payload is intentionally the raw summary blob (no
|
||||
* envelope reshaping) so the v1.4.17 ratchet that consumes it for
|
||||
* prompt-tuning can read the same shape the worker writes.
|
||||
*
|
||||
* Empty state (`null` summary) means the aggregator hasn't run yet
|
||||
* OR there's been no feedback in the rolling window. The admin UI
|
||||
* surfaces a "no data yet" empty state rather than a fake zero row
|
||||
* so the operator can tell "no feedback" apart from "all-zeros".
|
||||
*/
|
||||
export const GET = apiHandler(async () => {
|
||||
await requireAdmin();
|
||||
|
||||
const settings = await prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: { adminAiInsightsFeedbackSummary: true },
|
||||
});
|
||||
|
||||
const summary = settings?.adminAiInsightsFeedbackSummary ?? null;
|
||||
|
||||
annotate({
|
||||
action: { name: "admin.ai_quality.read" },
|
||||
meta: {
|
||||
has_summary: summary !== null,
|
||||
},
|
||||
});
|
||||
|
||||
return apiSuccess({ summary });
|
||||
});
|
||||
Reference in new issue
Block a user