feat(stockplatform): surface data readiness receipt
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 53s
CD Pipeline / build-and-deploy (push) Successful in 6m56s
CD Pipeline / post-deploy-checks (push) Successful in 1m59s

This commit is contained in:
Your Name
2026-07-02 18:39:40 +08:00
parent 12cb07bdeb
commit ae5844733d
10 changed files with 835 additions and 24 deletions

View File

@@ -1127,6 +1127,12 @@ type PriorityWorkOrderResponse = {
ai_automation_node_receipt_metadata_only?: boolean | null;
ai_automation_node_receipt_lanes?: string[] | null;
ai_automation_node_receipt_work_items?: string[] | null;
stockplatform_public_api_runtime_status?: string | null;
stockplatform_public_api_controlled_recovery_preflight_status?: string | null;
stockplatform_public_api_controlled_recovery_data_dependency?: string | null;
stockplatform_public_api_recovery_control_path_status?: string | null;
stockplatform_postgres_readiness_or_data_source_readback_status?: string | null;
stockplatform_postgres_readiness_or_data_source_receipt_provided?: boolean | null;
} | null;
in_progress_or_blocked_in_priority_order?: Array<{
evidence?: {
@@ -1161,8 +1167,21 @@ type PriorityWorkOrderResponse = {
controlled_cd_lane_live_gitea_actions_active_process_count?: number | null;
controlled_cd_lane_live_metric_blocker_count?: number | null;
controlled_cd_lane_live_metric_blockers?: string[] | null;
stockplatform_public_api_runtime_status?: string | null;
stockplatform_public_api_runtime_ready?: boolean | null;
stockplatform_public_api_health_http_status?: number | null;
stockplatform_freshness_http_status?: number | null;
stockplatform_ingestion_http_status?: number | null;
stockplatform_controlled_recovery_preflight_status?: string | null;
stockplatform_controlled_recovery_data_dependency?: string | null;
stockplatform_recovery_control_path_status?: string | null;
stockplatform_postgres_readiness_or_data_source_readback_status?: string | null;
stockplatform_postgres_readiness_or_data_source_readback_present?: boolean | null;
stockplatform_postgres_readiness_or_data_source_receipt_provided?: boolean | null;
stockplatform_postgres_readiness_or_data_source_postgres_ready?: boolean | null;
} | null;
}>;
next_execution_order?: string[] | null;
commander_inserted_requirement_work_items?: CommanderInsertedRequirementWorkItem[];
ai_automation_node_receipts?: AiAutomationNodeReceipt[];
ai_automation_node_receipt_schema?: {
@@ -8691,6 +8710,166 @@ function AiLoopLogSourceTagsPanel({
);
}
function stockplatformReceiptTone(value: string | boolean | null | undefined) {
if (value === true || value === "ready" || String(value).includes("_ready")) {
return "border-[#b9d9c2] bg-[#f2fbf3] text-[#236332]";
}
if (String(value).includes("blocked") || value === false) {
return "border-[#f0c6a8] bg-[#fff8f1] text-[#9a4d16]";
}
return "border-[#d8d3c7] bg-[#faf9f3] text-[#5f5b52]";
}
function StockPlatformP0ReceiptPanel({
priority,
loading,
}: {
priority: PriorityWorkOrderResponse | null;
loading: boolean;
}) {
const t = useTranslations("awooop.workItems.stockplatformP0Receipt");
const summary = priority?.summary;
const evidence = priority?.in_progress_or_blocked_in_priority_order?.find(
(item) =>
item.evidence?.stockplatform_postgres_readiness_or_data_source_readback_status ||
item.evidence?.stockplatform_controlled_recovery_preflight_status ||
item.evidence?.stockplatform_public_api_runtime_status
)?.evidence;
const readbackStatus =
summary?.stockplatform_postgres_readiness_or_data_source_readback_status ??
evidence?.stockplatform_postgres_readiness_or_data_source_readback_status ??
"--";
const receiptProvided =
summary?.stockplatform_postgres_readiness_or_data_source_receipt_provided ??
evidence?.stockplatform_postgres_readiness_or_data_source_receipt_provided ??
false;
const dataDependency =
summary?.stockplatform_public_api_controlled_recovery_data_dependency ??
evidence?.stockplatform_controlled_recovery_data_dependency ??
"--";
const preflightStatus =
summary?.stockplatform_public_api_controlled_recovery_preflight_status ??
evidence?.stockplatform_controlled_recovery_preflight_status ??
"--";
const runtimeStatus =
summary?.stockplatform_public_api_runtime_status ??
evidence?.stockplatform_public_api_runtime_status ??
"--";
const recoveryStatus =
summary?.stockplatform_public_api_recovery_control_path_status ??
evidence?.stockplatform_recovery_control_path_status ??
"--";
const postgresReady =
evidence?.stockplatform_postgres_readiness_or_data_source_postgres_ready ??
false;
const nextOrder = priority?.next_execution_order?.[0] ?? "";
const metrics = [
{
key: "runtime",
label: t("metrics.runtime"),
value: runtimeStatus,
tone: stockplatformReceiptTone(runtimeStatus),
},
{
key: "receipt",
label: t("metrics.receipt"),
value: receiptProvided ? t("values.received") : t("values.missing"),
tone: stockplatformReceiptTone(receiptProvided),
},
{
key: "data",
label: t("metrics.dataDependency"),
value: dataDependency,
tone: stockplatformReceiptTone(readbackStatus),
},
{
key: "postgres",
label: t("metrics.postgres"),
value: postgresReady ? t("values.ready") : t("values.notReady"),
tone: stockplatformReceiptTone(postgresReady),
},
];
return (
<section
className="border border-[#d8d3c7] bg-white"
data-testid="stockplatform-p0-runtime-receipt"
>
<div className="p-4">
<div className="flex flex-wrap items-start justify-between gap-4">
<div className="flex min-w-0 items-center gap-3">
<Database className="h-5 w-5 shrink-0 text-[#1f5b9b]" aria-hidden="true" />
<div className="min-w-0">
<p className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#9a968c]">
{t("eyebrow")}
</p>
<h3 className="mt-1 text-base font-semibold tracking-normal text-[#141413]">
{t("title")}
</h3>
<p className="mt-2 max-w-3xl text-xs leading-5 text-[#77736a]">
{t("subtitle")}
</p>
</div>
</div>
<span
className={cn(
"border px-3 py-2 font-mono text-[11px] font-semibold",
stockplatformReceiptTone(readbackStatus)
)}
>
{loading ? "--" : readbackStatus}
</span>
</div>
<div className="mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4">
{metrics.map((metric) => (
<div key={metric.key} className={cn("border px-3 py-2", metric.tone)}>
<div className="text-[11px] font-semibold">{metric.label}</div>
<div className="mt-1 break-words font-mono text-xs font-semibold text-[#141413]">
{loading ? "--" : metric.value}
</div>
</div>
))}
</div>
<div className="mt-3 grid gap-2 border border-[#c9d8ea] bg-[#eef5ff] p-3 lg:grid-cols-[minmax(0,0.75fr)_minmax(0,1.8fr)]">
<div className="min-w-0">
<div className="text-[11px] font-semibold text-[#1f5b9b]">
{t("preflight")}
</div>
<div className="mt-1 break-words font-mono text-xs font-semibold text-[#141413]">
{loading ? "--" : preflightStatus}
</div>
<div className="mt-2 break-words font-mono text-[10px] leading-4 text-[#5f5b52]">
{loading ? "--" : recoveryStatus}
</div>
</div>
<div className="min-w-0">
<div className="text-[11px] font-semibold text-[#1f5b9b]">
{t("next")}
</div>
<div className="mt-1 break-words text-xs leading-5 text-[#141413]">
{loading ? "--" : nextOrder || t("empty")}
</div>
</div>
</div>
<div className="mt-3 flex flex-wrap gap-2 text-[11px] font-semibold">
<span className="border border-[#d8d3c7] bg-[#faf9f3] px-2 py-1 text-[#5f5b52]">
{t("boundaries.publicHttps")}
</span>
<span className="border border-[#d8d3c7] bg-[#faf9f3] px-2 py-1 text-[#5f5b52]">
{t("boundaries.noDbWrite")}
</span>
<span className="border border-[#d8d3c7] bg-[#faf9f3] px-2 py-1 text-[#5f5b52]">
{t("boundaries.noSecret")}
</span>
</div>
</div>
</section>
);
}
function commanderPriorityTone(priority: string) {
switch (priority) {
case "P0":
@@ -9318,6 +9497,11 @@ export default function AwoooPWorkItemsPage() {
loading={priorityWorkOrderLoading && !priorityWorkOrder}
/>
<StockPlatformP0ReceiptPanel
priority={priorityWorkOrder}
loading={priorityWorkOrderLoading && !priorityWorkOrder}
/>
<CommanderInsertedRequirementsPanel
priority={commanderInsertedRequirementWorkOrder}
loading={false}