feat: F019 AI monitoring layer — output transparency & governance workspace

Full 2-panel workspace at /ops/ai-monitoring: metrics strip (total, failed,
pending, approval rate, top prompt version, active model), filterable output
table by type/status/error, and detail panel with output preview, prompt
versioning, error details, and role-aware review actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-17 13:11:35 +02:00
parent 5d3323617c
commit 71f4b1eeb6
16 changed files with 1164 additions and 265 deletions
@@ -0,0 +1,29 @@
import type { IAIMonitoringProvider, AIMonitoringFilters } from './IAIMonitoringProvider'
import type { AIOutput } from '../domain/aiOutput'
import type { ReviewStatus } from '../domain/enums'
import { mockAIOutputs } from '../mock-data/aiOutputs'
const store: AIOutput[] = [...mockAIOutputs]
export const MockupAIMonitoringProvider: IAIMonitoringProvider = {
async getOutputs(filters?: AIMonitoringFilters) {
let results = [...store]
if (filters?.type) results = results.filter(o => o.type === filters.type)
if (filters?.reviewStatus) results = results.filter(o => o.reviewStatus === filters.reviewStatus)
if (filters?.hasError === true) results = results.filter(o => !!o.error)
if (filters?.hasError === false) results = results.filter(o => !o.error)
if (filters?.model) results = results.filter(o => o.model === filters.model)
return results.sort((a, b) => b.createdAt.localeCompare(a.createdAt))
},
async getOutput(id: string) {
return store.find(o => o.id === id) ?? null
},
async updateReviewStatus(id: string, status: ReviewStatus): Promise<AIOutput> {
const idx = store.findIndex(o => o.id === id)
if (idx === -1) throw new Error(`AIOutput ${id} not found`)
store[idx] = { ...store[idx], reviewStatus: status }
return store[idx]
},
}