From c3442ebe41b7a9e18d17f66ab0bf9f1482dcbc3e Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 2 Jul 2026 21:47:47 +0800 Subject: [PATCH] feat(awooop): surface telegram verifier receipts --- apps/web/messages/en.json | 18 ++ apps/web/messages/zh-TW.json | 18 ++ .../autonomous-runtime-receipt-panel.tsx | 219 +++++++++++++++++- 3 files changed, 254 insertions(+), 1 deletion(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 19f5db62c..61d0e136f 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -11825,6 +11825,24 @@ "aiAgent": "AI Agent" } }, + "postApplyVerifier": { + "title": "Telegram post-apply verifier", + "subtitle": "Telegram alert context receipts now read back target selector, source diff, check-mode, rollback, and post verifier proof.", + "status": "Verifier status", + "statusDetail": "production endpoint readback", + "contexts": "Verified receipts", + "contextsDetail": "verified / total context receipts", + "targets": "Verified targets", + "targetsDetail": "KM / RAG / PlayBook / MCP / Verifier / AI Agent", + "aiAgent": "AI Agent context", + "aiAgentDetail": "AI Agent consumable context receipts", + "refs": "Verifier refs", + "refsDetail": "post-apply verifier references", + "boundaries": "Safety boundary", + "boundariesDetail": "runtime writes {runtime} / telegram sends {telegram}", + "blockers": "Active blockers", + "noBlockers": "No active blocker" + }, "recent": "近 24h {count}", "missing": "缺 {count} 節點", "closedDetail": "required stages ok", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 8f08d201e..70c878665 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -11825,6 +11825,24 @@ "aiAgent": "AI Agent" } }, + "postApplyVerifier": { + "title": "Telegram post-apply verifier", + "subtitle": "Telegram 告警 context receipt 已完成 target selector、source diff、check-mode、rollback 與 post verifier 讀回。", + "status": "Verifier status", + "statusDetail": "正式 endpoint readback", + "contexts": "Verified receipts", + "contextsDetail": "verified / total context receipts", + "targets": "Verified targets", + "targetsDetail": "KM / RAG / PlayBook / MCP / Verifier / AI Agent", + "aiAgent": "AI Agent context", + "aiAgentDetail": "AI Agent 可使用的 context receipts", + "refs": "Verifier refs", + "refsDetail": "post-apply verifier references", + "boundaries": "Safety boundary", + "boundariesDetail": "runtime writes {runtime} / telegram sends {telegram}", + "blockers": "Active blockers", + "noBlockers": "無 active blocker" + }, "recent": "近 24h {count}", "missing": "缺 {count} 節點", "closedDetail": "required stages ok", diff --git a/apps/web/src/components/awooop/autonomous-runtime-receipt-panel.tsx b/apps/web/src/components/awooop/autonomous-runtime-receipt-panel.tsx index 740be16c9..14a719c40 100644 --- a/apps/web/src/components/awooop/autonomous-runtime-receipt-panel.tsx +++ b/apps/web/src/components/awooop/autonomous-runtime-receipt-panel.tsx @@ -252,6 +252,34 @@ type LogConsumerReadbackPayload = { } | null; }; +type TelegramPostApplyVerifierPayload = { + status?: string | null; + active_blockers?: string[] | null; + rollups?: { + telegram_alert_learning_context_post_apply_verifier_ready?: boolean | null; + context_receipt_count?: number | null; + verified_context_receipt_count?: number | null; + verified_target_count?: number | null; + target_count?: number | null; + verified_ai_agent_context_receipt_count?: number | null; + post_apply_verifier_ref_count?: number | null; + metadata_only_receipt_count?: number | null; + raw_payload_included_count?: number | null; + secret_value_read_count?: number | null; + runtime_write_performed_count?: number | null; + telegram_send_performed_count?: number | null; + failed_context_receipt_count?: number | null; + verified_targets?: string[] | null; + } | null; + operation_boundaries?: { + raw_payload_included?: boolean | null; + secret_value_collection_allowed?: boolean | null; + runtime_target_write_performed?: boolean | null; + telegram_send_performed?: boolean | null; + github_api_used?: boolean | null; + } | null; +}; + type PanelMode = "full" | "compact"; type Tone = "ok" | "warn" | "neutral"; type WorkFilter = "all" | "completed" | "active" | "pending" | "blocked"; @@ -376,6 +404,23 @@ async function fetchLogConsumerReadback(): Promise { + const controller = new AbortController(); + const timeout = window.setTimeout(() => controller.abort(), 12_000); + try { + const response = await fetch(`${API_BASE}/api/v1/agents/telegram-alert-learning-context-post-apply-verifier`, { + cache: "no-store", + signal: controller.signal, + }); + if (!response.ok) return null; + return (await response.json()) as TelegramPostApplyVerifierPayload; + } catch { + return null; + } finally { + window.clearTimeout(timeout); + } +} + export function AutonomousRuntimeReceiptPanel({ mode = "full", }: { @@ -386,6 +431,7 @@ export function AutonomousRuntimeReceiptPanel({ const [payload, setPayload] = useState(null); const [priorityPayload, setPriorityPayload] = useState(null); const [consumerPayload, setConsumerPayload] = useState(null); + const [telegramVerifierPayload, setTelegramVerifierPayload] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(false); const [updatedAt, setUpdatedAt] = useState(null); @@ -393,14 +439,16 @@ export function AutonomousRuntimeReceiptPanel({ const refresh = useCallback(async () => { setLoading(true); - const [next, priority, consumer] = await Promise.all([ + const [next, priority, consumer, telegramVerifier] = await Promise.all([ fetchRuntimeControl(), fetchPriorityWorkOrder(), fetchLogConsumerReadback(), + fetchTelegramPostApplyVerifier(), ]); setPayload(next); setPriorityPayload(priority); setConsumerPayload(consumer); + setTelegramVerifierPayload(telegramVerifier); setError(next === null); setUpdatedAt(next ? new Date() : null); setLoading(false); @@ -415,6 +463,7 @@ export function AutonomousRuntimeReceiptPanel({ const hasRuntimeReadback = payload !== null; const hasPriorityReadback = priorityPayload !== null; const hasConsumerReadback = consumerPayload !== null; + const hasTelegramVerifierReadback = telegramVerifierPayload !== null; const readback = payload?.runtime_receipt_readback; const ledger = readback?.autonomous_execution_loop_ledger; const traceLedger = readback?.trace_ledger; @@ -434,8 +483,13 @@ export function AutonomousRuntimeReceiptPanel({ const rollups = payload?.rollups ?? {}; const consumerRollups = consumerPayload?.rollups ?? {}; const consumerBlockers = consumerPayload?.active_blockers ?? []; + const telegramVerifierRollups = telegramVerifierPayload?.rollups ?? {}; + const telegramVerifierBlockers = telegramVerifierPayload?.active_blockers ?? []; const consumerReady = consumerRollups.controlled_consumer_readback_ready === true || consumerPayload?.status === "controlled_writeback_consumer_readback_ready"; + const telegramPostApplyVerifierReady = + telegramVerifierRollups.telegram_alert_learning_context_post_apply_verifier_ready === true + || telegramVerifierPayload?.status === "telegram_alert_learning_context_post_apply_verified"; const runtimeTargetWritePerformed = consumerRollups.runtime_target_write_performed === true || consumerPayload?.controlled_consume?.runtime_target_write_performed === true || consumerPayload?.operation_boundaries?.runtime_target_write_performed === true @@ -887,6 +941,121 @@ export function AutonomousRuntimeReceiptPanel({ icon: Rocket, }, ]; + const telegramVerifierCards = [ + { + key: "status", + label: t("postApplyVerifier.status"), + value: !hasTelegramVerifierReadback + ? t("states.loading") + : telegramPostApplyVerifierReady + ? t("states.closed") + : t("states.open"), + detail: t("postApplyVerifier.statusDetail"), + icon: ShieldCheck, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : telegramPostApplyVerifierReady ? "ok" as Tone : "warn" as Tone, + }, + { + key: "contexts", + label: t("postApplyVerifier.contexts"), + value: readbackRatio( + telegramVerifierRollups.verified_context_receipt_count, + telegramVerifierRollups.context_receipt_count, + hasTelegramVerifierReadback + ), + detail: t("postApplyVerifier.contextsDetail"), + icon: ListChecks, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : toNumber(telegramVerifierRollups.failed_context_receipt_count) === 0 + && toNumber(telegramVerifierRollups.verified_context_receipt_count) > 0 + ? "ok" as Tone + : "warn" as Tone, + }, + { + key: "targets", + label: t("postApplyVerifier.targets"), + value: readbackRatio( + telegramVerifierRollups.verified_target_count, + telegramVerifierRollups.target_count, + hasTelegramVerifierReadback + ), + detail: t("postApplyVerifier.targetsDetail"), + icon: Database, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : toNumber(telegramVerifierRollups.verified_target_count) === toNumber(telegramVerifierRollups.target_count) + && toNumber(telegramVerifierRollups.target_count) > 0 + ? "ok" as Tone + : "warn" as Tone, + }, + { + key: "aiAgent", + label: t("postApplyVerifier.aiAgent"), + value: readbackNumber( + telegramVerifierRollups.verified_ai_agent_context_receipt_count, + hasTelegramVerifierReadback + ), + detail: t("postApplyVerifier.aiAgentDetail"), + icon: Rocket, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : toNumber(telegramVerifierRollups.verified_ai_agent_context_receipt_count) > 0 + ? "ok" as Tone + : "warn" as Tone, + }, + { + key: "refs", + label: t("postApplyVerifier.refs"), + value: readbackNumber( + telegramVerifierRollups.post_apply_verifier_ref_count, + hasTelegramVerifierReadback + ), + detail: t("postApplyVerifier.refsDetail"), + icon: Gauge, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : toNumber(telegramVerifierRollups.post_apply_verifier_ref_count) > 0 + ? "ok" as Tone + : "warn" as Tone, + }, + { + key: "boundaries", + label: t("postApplyVerifier.boundaries"), + value: readbackRatio( + telegramVerifierRollups.raw_payload_included_count, + telegramVerifierRollups.secret_value_read_count, + hasTelegramVerifierReadback + ), + detail: t("postApplyVerifier.boundariesDetail", { + runtime: readbackNumber(telegramVerifierRollups.runtime_write_performed_count, hasTelegramVerifierReadback), + telegram: readbackNumber(telegramVerifierRollups.telegram_send_performed_count, hasTelegramVerifierReadback), + }), + icon: TriangleAlert, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : toNumber(telegramVerifierRollups.raw_payload_included_count) === 0 + && toNumber(telegramVerifierRollups.secret_value_read_count) === 0 + && telegramVerifierPayload?.operation_boundaries?.github_api_used !== true + ? "ok" as Tone + : "warn" as Tone, + }, + { + key: "blockers", + label: t("postApplyVerifier.blockers"), + value: readbackNumber(telegramVerifierBlockers.length, hasTelegramVerifierReadback), + detail: !hasTelegramVerifierReadback + ? t("states.loading") + : telegramVerifierBlockers.length > 0 + ? telegramVerifierBlockers[0] + : t("postApplyVerifier.noBlockers"), + icon: TriangleAlert, + tone: !hasTelegramVerifierReadback + ? "neutral" as Tone + : telegramVerifierBlockers.length > 0 ? "warn" as Tone : "ok" as Tone, + }, + ]; const visibleWorkItems = orderedWorkItems.filter((item) => matchesWorkFilter(item, workFilter)); const orderedCompleted = orderedWorkItems.filter((item) => item.status === "completed").length; const orderedActive = orderedWorkItems.filter((item) => ( @@ -1032,6 +1201,54 @@ export function AutonomousRuntimeReceiptPanel({ ); })} +
+
+
+
+
+

+ {t("postApplyVerifier.subtitle")} +

+
+ + {!hasTelegramVerifierReadback + ? t("states.loading") + : telegramVerifierPayload?.status ?? "--"} + +
+
+ {telegramVerifierCards.map((card) => { + const Icon = card.icon; + return ( +
+
+
+

{card.label}

+

+ {card.value} +

+
+ + +
+

+ {card.detail} +

+
+ ); + })} +
+