spb/autoscholar
Public
1import { listRuns } from "@autoscholar/core";2import Link from "next/link";3import { StatusBadge } from "@/components/StatusBadge";4import { ago } from "@/lib/format";5import { db } from "@/lib/server/db";67export const dynamic = "force-dynamic";89export default async function QualityIndex() {10 const runs = await listRuns(db(), {11 status: [12 "quality_check",13 "quality_failed",14 "ready_to_publish",15 "awaiting_approval",16 "publishing",17 "published",18 ],19 limit: 200,20 });21 return (22 <div className="space-y-6">23 <header>24 <p className="eyebrow">Gates</p>25 <h1 className="title-2 mt-1">Quality</h1>26 <p className="muted mt-1 text-sm">27 Deterministic gate outcomes computed on the control plane. Overrides are limited to soft/structural28 gates and are recorded with a rationale.29 </p>30 </header>31 <table className="table">32 <thead>33 <tr>34 <th>Run</th>35 <th>Status</th>36 <th>Mode</th>37 <th>Updated</th>38 </tr>39 </thead>40 <tbody>41 {runs.length === 0 && (42 <tr>43 <td colSpan={4} className="muted py-8 text-center">44 No run has reached quality evaluation.45 </td>46 </tr>47 )}48 {runs.map((r) => (49 <tr key={r.id}>50 <td>51 <Link href={`/admin/quality/${r.id}`}>{r.title}</Link>52 </td>53 <td>54 <StatusBadge status={r.status} />55 </td>56 <td>{r.researchMode}</td>57 <td className="subtle text-xs">{ago(r.updatedAt)}</td>58 </tr>59 ))}60 </tbody>61 </table>62 </div>63 );64}65