feat(awooop): pin manager situation board
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m0s
CD Pipeline / build-and-deploy (push) Successful in 7m9s
CD Pipeline / post-deploy-checks (push) Has been cancelled

This commit is contained in:
Your Name
2026-07-02 20:08:15 +08:00
parent f69cee4f74
commit 5d3dc2a9c2
3 changed files with 296 additions and 5 deletions

View File

@@ -9180,6 +9180,51 @@
"evidenceBoundary": "證據邊界"
}
},
"managerSituation": {
"eyebrow": "Manager overview",
"title": "StockPlatform P0",
"subtitle": "Blocker, impact, and next action are pinned to the first screen.",
"loading": "Reading production readback.",
"head": "Deployed source",
"decision": "Decision",
"decisionValue": "Fix P0, no side lane",
"blockingSources": "Blocking sources",
"noSourceNames": "Waiting for source contract readback",
"states": {
"sourceContract": "Source contract blocked",
"preflight": "Recovery preflight blocked",
"publicApi": "Public API blocked",
"ready": "Ready to verify",
"review": "Awaiting readback"
},
"cards": {
"now": {
"label": "Current blocker",
"detail": "{id}"
},
"impact": {
"label": "Impact",
"value": "Public API not green",
"detail": "Source trust is not sufficient."
},
"evidence": {
"label": "Evidence",
"value": "{count} sources failed",
"receipted": "receipt provided",
"missing": "receipt missing"
},
"next": {
"label": "Next step",
"value": "Repair source contract",
"detail": "Run verifier immediately after repair."
}
},
"chips": {
"noDbWrite": "no DB write",
"noSecret": "no secret",
"publicVerifier": "public verifier"
}
},
"stockplatformP0Receipt": {
"eyebrow": "P0-006 Runtime receipt",
"title": "StockPlatform data dependency readback",

View File

@@ -9180,6 +9180,51 @@
"evidenceBoundary": "證據邊界"
}
},
"managerSituation": {
"eyebrow": "管理者總覽",
"title": "StockPlatform P0",
"subtitle": "卡點、影響、下一步先放第一屏。",
"loading": "正在讀取正式 readback。",
"head": "正式部署",
"decision": "決策",
"decisionValue": "先修 P0不開支線",
"blockingSources": "阻塞來源",
"noSourceNames": "等待 source contract readback",
"states": {
"sourceContract": "來源合約卡住",
"preflight": "修復預檢卡住",
"publicApi": "公開 API 卡住",
"ready": "已可驗證",
"review": "等待判讀"
},
"cards": {
"now": {
"label": "目前卡點",
"detail": "{id}"
},
"impact": {
"label": "影響",
"value": "公開 API 未綠燈",
"detail": "資料來源可信度不足"
},
"evidence": {
"label": "證據",
"value": "{count} 個來源未通過",
"receipted": "receipt 已收件",
"missing": "receipt 未到"
},
"next": {
"label": "下一步",
"value": "補來源合約",
"detail": "修完直接跑 verifier"
}
},
"chips": {
"noDbWrite": "不寫 DB",
"noSecret": "不讀 secret",
"publicVerifier": "公開驗證器"
}
},
"stockplatformP0Receipt": {
"eyebrow": "P0-006 Runtime receipt",
"title": "StockPlatform 資料依賴回讀",

View File

@@ -22,6 +22,7 @@ import {
GitPullRequest,
ListChecks,
Network,
Radar,
RefreshCw,
SearchCheck,
ShieldCheck,
@@ -1065,7 +1066,16 @@ type CommanderInsertedRequirementWorkItem = {
};
type PriorityWorkOrderResponse = {
current_head?: {
gitea_main_sha?: string | null;
latest_successful_deployed_source_sha?: string | null;
latest_successful_deploy_marker?: string | null;
production_source_truth_available?: boolean | null;
} | null;
summary?: {
active_p0_state?: string | null;
next_executable_mainline_workplan_id?: string | null;
next_executable_mainline_state?: string | null;
commander_inserted_requirement_work_item_count?: number | null;
commander_inserted_requirement_p0_count?: number | null;
commander_inserted_requirement_p1_count?: number | null;
@@ -1187,6 +1197,11 @@ type PriorityWorkOrderResponse = {
stockplatform_source_contract_receipt_provided?: boolean | null;
stockplatform_source_contract_ready?: boolean | null;
stockplatform_source_contract_non_ok_source_count?: number | null;
stockplatform_source_contract_blocking_sources?: Array<{
source?: string | null;
category?: string | null;
status?: string | null;
}> | null;
} | null;
}>;
next_execution_order?: string[] | null;
@@ -8732,6 +8747,187 @@ function stockplatformCompactTone(value: string | boolean | null | undefined) {
return "border-[#c9d8ea] bg-[#eef5ff] text-[#1f5b9b]";
}
function shortSha(value: string | null | undefined) {
return value ? value.slice(0, 10) : "--";
}
function stockplatformManagerStateKey(value: string | null | undefined) {
const state = String(value ?? "");
if (state.includes("source_contract")) return "sourceContract";
if (state.includes("preflight")) return "preflight";
if (state.includes("public_api")) return "publicApi";
if (state.includes("ready")) return "ready";
return "review";
}
function ManagerSituationBoard({
priority,
loading,
}: {
priority: PriorityWorkOrderResponse | null;
loading: boolean;
}) {
const t = useTranslations("awooop.workItems.managerSituation");
const summary = priority?.summary;
const evidence = priority?.in_progress_or_blocked_in_priority_order?.find(
(item) =>
item.evidence?.stockplatform_source_contract_readback_status ||
item.evidence?.stockplatform_public_api_runtime_status
)?.evidence;
const activeWorkplan =
summary?.next_executable_mainline_workplan_id ??
"P0-006-STOCKPLATFORM-PUBLIC-API-CONTROLLED-RECOVERY-PREFLIGHT";
const activeState =
summary?.active_p0_state ??
"blocked_stockplatform_public_api_controlled_recovery_preflight";
const activeStateLabel = t(
`states.${stockplatformManagerStateKey(activeState)}` as never
);
const sourceContractStatus =
summary?.stockplatform_source_contract_readback_status ??
evidence?.stockplatform_source_contract_readback_status ??
"unknown";
const nonOkSourceCount =
summary?.stockplatform_source_contract_non_ok_source_count ??
evidence?.stockplatform_source_contract_non_ok_source_count ??
0;
const receiptProvided =
summary?.stockplatform_source_contract_receipt_provided ??
evidence?.stockplatform_source_contract_receipt_provided ??
false;
const blockingSources =
evidence?.stockplatform_source_contract_blocking_sources?.slice(0, 3) ?? [];
const sourceNames = blockingSources
.map((source) => source.source)
.filter(Boolean)
.join(" / ");
const deployedSha =
priority?.current_head?.latest_successful_deployed_source_sha ??
priority?.current_head?.gitea_main_sha;
const managerCards = [
{
key: "now",
icon: TriangleAlert,
label: t("cards.now.label"),
value: activeStateLabel,
detail: t("cards.now.detail", {
id: activeWorkplan.startsWith("P0-006") ? "P0-006" : activeWorkplan,
}),
tone: "border-[#f0c6a8] bg-[#fff8f1] text-[#9a4d16]",
},
{
key: "impact",
icon: Database,
label: t("cards.impact.label"),
value: t("cards.impact.value"),
detail: t("cards.impact.detail"),
tone: "border-[#c9d8ea] bg-[#eef5ff] text-[#1f5b9b]",
},
{
key: "evidence",
icon: SearchCheck,
label: t("cards.evidence.label"),
value: t("cards.evidence.value", { count: nonOkSourceCount }),
detail: receiptProvided ? t("cards.evidence.receipted") : t("cards.evidence.missing"),
tone: stockplatformCompactTone(sourceContractStatus),
},
{
key: "next",
icon: ArrowRight,
label: t("cards.next.label"),
value: t("cards.next.value"),
detail: t("cards.next.detail"),
tone: "border-[#cbd7bf] bg-[#f4faef] text-[#3d6b24]",
},
];
return (
<section
className="border border-[#d8d3c7] bg-white"
data-testid="awooop-manager-situation-board"
>
<div className="grid gap-px bg-[#e0ddd4] lg:grid-cols-[minmax(0,1.15fr)_minmax(0,1.85fr)]">
<div className="bg-[#141413] p-4 text-white">
<div className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[#c9d8ea]">
<Radar className="h-4 w-4" aria-hidden="true" />
{t("eyebrow")}
</div>
<h3 className="mt-3 text-xl font-semibold tracking-normal">
{t("title")}
</h3>
<p className="mt-2 text-sm leading-5 text-[#eee9dd]">
{loading ? t("loading") : t("subtitle")}
</p>
<div className="mt-4 grid gap-2 sm:grid-cols-2">
<div className="border border-[#4d4b44] bg-[#1d1c19] px-3 py-2">
<div className="text-[11px] font-semibold text-[#b7b4a8]">
{t("head")}
</div>
<div className="mt-1 font-mono text-sm font-semibold">
{shortSha(deployedSha)}
</div>
</div>
<div className="border border-[#4d4b44] bg-[#1d1c19] px-3 py-2">
<div className="text-[11px] font-semibold text-[#b7b4a8]">
{t("decision")}
</div>
<div className="mt-1 text-sm font-semibold">
{t("decisionValue")}
</div>
</div>
</div>
</div>
<div className="bg-white p-3">
<div className="grid gap-2 md:grid-cols-2 xl:grid-cols-4">
{managerCards.map((card) => {
const Icon = card.icon;
return (
<div
key={card.key}
className={cn("min-w-0 border px-3 py-3", card.tone)}
>
<div className="flex items-center justify-between gap-2">
<div className="text-[11px] font-semibold">{card.label}</div>
<Icon className="h-4 w-4 shrink-0" aria-hidden="true" />
</div>
<div className="mt-2 break-words text-sm font-semibold leading-5 text-[#141413]">
{loading ? "--" : card.value}
</div>
<div className="mt-1 break-words text-xs leading-4 text-[#5f5b52]">
{loading ? "--" : card.detail}
</div>
</div>
);
})}
</div>
<div className="mt-2 grid gap-2 border border-[#d8d3c7] bg-[#faf9f3] p-2 lg:grid-cols-[minmax(0,1fr)_auto]">
<div className="min-w-0">
<div className="text-[11px] font-semibold text-[#77736a]">
{t("blockingSources")}
</div>
<div className="mt-1 break-words font-mono text-xs font-semibold text-[#141413]">
{loading ? "--" : sourceNames || t("noSourceNames")}
</div>
</div>
<div className="flex flex-wrap items-center gap-1.5 text-[11px] font-semibold">
<span className="border border-[#d8d3c7] bg-white px-2 py-1 text-[#5f5b52]">
{t("chips.noDbWrite")}
</span>
<span className="border border-[#d8d3c7] bg-white px-2 py-1 text-[#5f5b52]">
{t("chips.noSecret")}
</span>
<span className="border border-[#d8d3c7] bg-white px-2 py-1 text-[#5f5b52]">
{t("chips.publicVerifier")}
</span>
</div>
</div>
</div>
</div>
</section>
);
}
function StockPlatformP0ReceiptPanel({
priority,
loading,
@@ -9607,11 +9803,7 @@ export default function AwoooPWorkItemsPage() {
</div>
</section>
<ProductionClaimBanner loading={loading} summary={telemetry.quality} />
<AutonomousRuntimeReceiptPanel mode="compact" />
<AiLoopLogSourceTagsPanel
<ManagerSituationBoard
priority={priorityWorkOrder}
loading={priorityWorkOrderLoading && !priorityWorkOrder}
/>
@@ -9621,6 +9813,15 @@ export default function AwoooPWorkItemsPage() {
loading={priorityWorkOrderLoading && !priorityWorkOrder}
/>
<ProductionClaimBanner loading={loading} summary={telemetry.quality} />
<AutonomousRuntimeReceiptPanel mode="compact" />
<AiLoopLogSourceTagsPanel
priority={priorityWorkOrder}
loading={priorityWorkOrderLoading && !priorityWorkOrder}
/>
<CommanderInsertedRequirementsPanel
priority={commanderInsertedRequirementWorkOrder}
loading={false}