feat: add decision center service and cli

This commit is contained in:
Codex
2026-05-17 06:49:42 +00:00
parent 2b2a327301
commit 4d9eed6513
32 changed files with 1758 additions and 48 deletions
+121 -3
View File
@@ -39,6 +39,7 @@ const NETWORK_CHECK_NAMES = [
"network:todo-note-public-blocked",
"network:code-queue-public-blocked",
"network:oa-event-flow-public-blocked",
"network:decision-center-public-blocked",
"network:filebrowser-public-blocked",
] as const;
@@ -61,6 +62,7 @@ const SERVICE_CHECK_NAMES = [
"microservice:catalog-todo-note",
"microservice:catalog-oa-event-flow",
"microservice:catalog-code-queue",
"microservice:catalog-decision-center",
"microservice:k3sctl-adapter-status",
"microservice:k3sctl-control-plane",
"microservice:catalog-filebrowser",
@@ -92,6 +94,9 @@ const SERVICE_CHECK_NAMES = [
"microservice:code-queue-status",
"microservice:code-queue-health",
"microservice:code-queue-tasks",
"microservice:decision-center-status",
"microservice:decision-center-health",
"microservice:decision-center-records",
"microservice:oa-event-flow-status",
"microservice:oa-event-flow-health",
"microservice:oa-event-flow-diagnostics",
@@ -129,6 +134,7 @@ const FRONTEND_CHECK_NAMES = [
"frontend:todo-note-integrated-visible",
"frontend:findjob-integrated-visible",
"frontend:oa-event-flow-visible",
"frontend:decision-center-visible",
"frontend:code-queue-integrated-visible",
"frontend:code-queue-enqueue-await-smoke",
"frontend:code-queue-summary-mobile-wrap",
@@ -321,6 +327,7 @@ const LAYOUT_OVERFLOW_PAGE_TEST_IDS: Record<string, string> = {
"/app/met-nonlinear/": "met-nonlinear-page",
"/app/claudeqq/": "claudeqq-page",
"/app/oa-event-flow/": "oa-event-flow-page",
"/app/decision-center/": "decision-center-page",
"/app/code-queue/": "code-queue-page",
};
@@ -1025,6 +1032,7 @@ async function exposureChecks(config: UniDeskConfig, urls: PublicUrls, checks: E
const codeQueuePublic = await fetchProbe(`http://${config.network.publicHost}:14222/health`, 2500);
const oaEventFlowPublic = await fetchProbe(`http://${config.network.publicHost}:4255/health`, 2500);
const oaEventFlowRestriction = dockerUserPortRestriction(4255, allowedSourceCidrs);
const decisionCenterPublic = await fetchProbe(`http://${config.network.publicHost}:4277/health`, 2500);
const filebrowserPublic = await fetchProbe(`http://${config.network.publicHost}:4251/health`, 2500);
addSelectedCheck(checks, options, "network:only-frontend-provider-ports", !portsText.includes(`:${config.network.core.port}->`) && !portsText.includes(":14222->"), portSummary);
addSelectedCheck(checks, options, "network:core-public-blocked", (corePublic as { reachable?: boolean }).reachable === false, corePublic);
@@ -1035,6 +1043,7 @@ async function exposureChecks(config: UniDeskConfig, urls: PublicUrls, checks: E
addSelectedCheck(checks, options, "network:todo-note-public-blocked", (todoNotePublic as { reachable?: boolean }).reachable === false, todoNotePublic);
addSelectedCheck(checks, options, "network:code-queue-public-blocked", (codeQueuePublic as { reachable?: boolean }).reachable === false, codeQueuePublic);
addSelectedCheck(checks, options, "network:oa-event-flow-public-blocked", publicProbeBlockedOrRestricted(oaEventFlowPublic, oaEventFlowRestriction), { publicProbe: oaEventFlowPublic, restriction: oaEventFlowRestriction });
addSelectedCheck(checks, options, "network:decision-center-public-blocked", (decisionCenterPublic as { reachable?: boolean }).reachable === false, decisionCenterPublic);
addSelectedCheck(checks, options, "network:filebrowser-public-blocked", (filebrowserPublic as { reachable?: boolean }).reachable === false, filebrowserPublic);
}
@@ -1077,6 +1086,9 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
const codeQueueStatus = dockerCoreJson("/api/microservices/code-queue/status");
const codeQueueHealth = dockerCoreJson("/api/microservices/code-queue/health");
const codeQueueTasks = dockerCoreJson("/api/microservices/code-queue/proxy/api/tasks/overview?limit=5&transcriptLimit=1&compact=1&afterSeq=0&preferId=");
const decisionCenterStatus = dockerCoreJson("/api/microservices/decision-center/status");
const decisionCenterHealth = dockerCoreJson("/api/microservices/decision-center/health");
const decisionCenterRecords = dockerCoreJson("/api/microservices/decision-center/proxy/api/records?limit=20");
const filebrowserHealth = dockerCoreJson("/api/microservices/filebrowser/health");
const filebrowserWebui = dockerCoreJson("/api/microservices/filebrowser/proxy/");
const filebrowserD601Health = dockerCoreJson("/api/microservices/filebrowser-d601/health");
@@ -1127,6 +1139,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
const todoNote = microserviceList.find((service) => service.id === "todo-note");
const oaEventFlow = microserviceList.find((service) => service.id === "oa-event-flow");
const codeQueue = microserviceList.find((service) => service.id === "code-queue");
const decisionCenter = microserviceList.find((service) => service.id === "decision-center");
const filebrowser = microserviceList.find((service) => service.id === "filebrowser");
const filebrowserD601 = microserviceList.find((service) => service.id === "filebrowser-d601");
const findjobSummaryBody = (findjobSummary as { body?: { totalJobs?: number; prioritizedJobs?: number } }).body;
@@ -1150,6 +1163,8 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
const oaEventFlowStatsBody = (oaEventFlowStats as { body?: { ok?: boolean; stats?: unknown[]; returned?: number } }).body;
const codeQueueHealthBody = (codeQueueHealth as { body?: { ok?: boolean; egressProxy?: { connected?: boolean }; queue?: { defaultModel?: string; judgeConfigured?: boolean; modelReasoningEfforts?: Record<string, string> } } }).body;
const codeQueueTasksBody = (codeQueueTasks as { body?: { ok?: boolean; queue?: { defaultModel?: string; modelReasoningEfforts?: Record<string, string> }; tasks?: unknown[] } }).body;
const decisionCenterHealthBody = (decisionCenterHealth as { body?: { ok?: boolean; service?: string; storage?: string; schemaReady?: boolean; recordCount?: number; deploy?: { commit?: string } } }).body;
const decisionCenterRecordsBody = (decisionCenterRecords as { body?: { ok?: boolean; records?: unknown[]; returned?: number } }).body;
const k3sctlControlPlaneBody = (k3sctlControlPlane as { body?: {
ok?: boolean;
clusterId?: string;
@@ -1169,6 +1184,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
} }).body;
const k3sctlCodeQueueService = k3sctlControlPlaneBody?.services?.find((service) => service.id === "code-queue");
const k3sctlClaudeqqService = k3sctlControlPlaneBody?.services?.find((service) => service.id === "claudeqq");
const k3sctlDecisionCenterService = k3sctlControlPlaneBody?.services?.find((service) => service.id === "decision-center");
const filebrowserHealthBody = (filebrowserHealth as { body?: { status?: string } }).body;
const filebrowserD601HealthBody = (filebrowserD601Health as { body?: { status?: string } }).body;
const filebrowserWebuiText = String((filebrowserWebui as { body?: { text?: string } }).body?.text || "");
@@ -1216,6 +1232,15 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
&& codeQueue.runtime?.orchestrator === "k3sctl"
&& codeQueue.runtime?.container === null,
{ microservices });
addSelectedCheck(checks, options, "microservice:catalog-decision-center",
(microservices as { ok?: boolean }).ok === true
&& decisionCenter?.providerId === "D601"
&& decisionCenter.backend?.public === false
&& decisionCenter.backend?.proxyMode === "k3sctl-adapter-http"
&& decisionCenter.deployment?.mode === "k3sctl-managed"
&& decisionCenter.runtime?.orchestrator === "k3sctl"
&& decisionCenter.runtime?.container === null,
{ microservices });
addSelectedCheck(checks, options, "microservice:k3sctl-adapter-status",
(k3sctlStatus as { ok?: boolean; body?: { microservice?: { id?: string; providerId?: string } } }).ok === true
&& (k3sctlStatus as { body?: { microservice?: { id?: string; providerId?: string } } }).body?.microservice?.id === "k3sctl-adapter"
@@ -1238,6 +1263,11 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
&& k3sctlClaudeqqService?.servingHealthy === true
&& k3sctlClaudeqqService?.active?.id === "D601"
&& k3sctlClaudeqqService?.active?.healthy === true
&& k3sctlDecisionCenterService?.status === "healthy"
&& k3sctlDecisionCenterService?.topologyComplete === true
&& k3sctlDecisionCenterService?.servingHealthy === true
&& k3sctlDecisionCenterService?.active?.id === "D601"
&& k3sctlDecisionCenterService?.active?.healthy === true
&& (k3sctlCodeQueueService?.presentNodeIds ?? []).includes("D601")
&& (k3sctlCodeQueueService?.missingNodeIds ?? []).length === 0
&& (k3sctlCodeQueueService?.instances ?? []).some((instance) => instance.id === "D601" && instance.healthy === true),
@@ -1248,6 +1278,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
kubeApiProxy: k3sctlControlPlaneBody?.kubeApiProxy,
service: k3sctlCodeQueueService,
claudeqq: k3sctlClaudeqqService,
decisionCenter: k3sctlDecisionCenterService,
});
addSelectedCheck(checks, options, "microservice:catalog-filebrowser", (microservices as { ok?: boolean }).ok === true
&& filebrowser?.providerId === "D518"
@@ -1319,6 +1350,9 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2
addSelectedCheck(checks, options, "microservice:code-queue-status", (codeQueueStatus as { ok?: boolean }).ok === true && (codeQueueStatus as { body?: { microservice?: { id?: string; providerId?: string } } }).body?.microservice?.providerId === "D601", codeQueueStatus);
addSelectedCheck(checks, options, "microservice:code-queue-health", (codeQueueHealth as { ok?: boolean }).ok === true && codeQueueHealthBody?.ok === true && codeQueueHealthBody.egressProxy?.connected === true && codeQueueHealthBody.queue?.defaultModel === "gpt-5.5" && codeQueueHealthBody.queue?.modelReasoningEfforts?.["gpt-5.5"] === "xhigh", codeQueueHealth);
addSelectedCheck(checks, options, "microservice:code-queue-tasks", (codeQueueTasks as { ok?: boolean }).ok === true && codeQueueTasksBody?.ok === true && Array.isArray(codeQueueTasksBody.tasks) && codeQueueTasksBody.queue?.defaultModel === "gpt-5.5" && codeQueueTasksBody.queue?.modelReasoningEfforts?.["gpt-5.5"] === "xhigh", codeQueueTasks);
addSelectedCheck(checks, options, "microservice:decision-center-status", (decisionCenterStatus as { ok?: boolean }).ok === true && (decisionCenterStatus as { body?: { microservice?: { id?: string; providerId?: string } } }).body?.microservice?.providerId === "D601", decisionCenterStatus);
addSelectedCheck(checks, options, "microservice:decision-center-health", (decisionCenterHealth as { ok?: boolean }).ok === true && decisionCenterHealthBody?.ok === true && decisionCenterHealthBody.service === "decision-center" && decisionCenterHealthBody.storage === "postgres" && decisionCenterHealthBody.schemaReady === true, decisionCenterHealth);
addSelectedCheck(checks, options, "microservice:decision-center-records", (decisionCenterRecords as { ok?: boolean }).ok === true && decisionCenterRecordsBody?.ok === true && Array.isArray(decisionCenterRecordsBody.records), decisionCenterRecords);
const upgradeDispatch = dockerCoreJson("/api/dispatch", {
method: "POST",
body: { providerId: config.providerGateway.id, command: "provider.upgrade", payload: { source: "cli-e2e", mode: "plan" } },
@@ -1417,6 +1451,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
const needTodoNote = wants("frontend:todo-note-integrated-visible");
const needFindJob = wants("frontend:findjob-integrated-visible");
const needOaEventFlow = wants("frontend:oa-event-flow-visible");
const needDecisionCenter = wants("frontend:decision-center-visible");
const needCodeQueue = wantsAny([
"frontend:code-queue-integrated-visible",
"frontend:code-queue-enqueue-await-smoke",
@@ -1502,6 +1537,10 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
let findjobText = "";
let oaEventFlowText = "";
let oaEventFlowMetrics: any = { pageVisible: false, eventTableVisible: false, statsVisible: false, tagFilterValue: "", rawButtonCount: 0 };
let decisionCenterText = "";
let decisionCenterE2eRecord: any = null;
let decisionCenterDeleteResult: any = null;
let decisionCenterMetrics: any = { pageVisible: false, tableVisible: false, rawButtonCount: 0, rawJsonBlocks: 0, chatInputCount: 0, bodyContainsRecord: false };
let codeQueueText = "";
let codeQueueOutputText = "";
let codeQueueTaskCount = 0;
@@ -1717,9 +1756,9 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
}
}
if (needMicroserviceCatalog || needTodoNote || needFindJob || needOaEventFlow || needCodeQueue || needClaudeqq || needRouteDeepLink || needPipeline || needMetNonlinear) {
if (needMicroserviceCatalog || needTodoNote || needFindJob || needOaEventFlow || needDecisionCenter || needCodeQueue || needClaudeqq || needRouteDeepLink || needPipeline || needMetNonlinear) {
await page.getByRole("button", { name: /用户服务/ }).click();
if (needMicroserviceCatalog || needTodoNote || needFindJob || needOaEventFlow || needCodeQueue || needClaudeqq || needRouteDeepLink || needPipeline || needMetNonlinear) {
if (needMicroserviceCatalog || needTodoNote || needFindJob || needOaEventFlow || needDecisionCenter || needCodeQueue || needClaudeqq || needRouteDeepLink || needPipeline || needMetNonlinear) {
await page.waitForSelector('[data-testid="microservice-catalog-page"]', { timeout: 10000 });
}
if (needMicroserviceCatalog) {
@@ -1730,6 +1769,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
await page.waitForSelector('[data-testid="microservice-row-todo-note"]', { timeout: 10000 });
await page.waitForSelector('[data-testid="microservice-row-oa-event-flow"]', { timeout: 10000 });
await page.waitForSelector('[data-testid="microservice-row-code-queue"]', { timeout: 10000 });
await page.waitForSelector('[data-testid="microservice-row-decision-center"]', { timeout: 10000 });
microserviceCatalogText = await page.locator('[data-testid="microservice-catalog-page"]').innerText({ timeout: 5000 });
}
if (needTodoNote) {
@@ -1806,6 +1846,65 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
};
});
}
if (needDecisionCenter) {
const decisionCenterE2eTitle = `E2E Decision Center ${Date.now()}`;
decisionCenterE2eRecord = await page.evaluate(async (title) => {
const response = await fetch("/api/microservices/decision-center/proxy/api/records", {
method: "POST",
credentials: "same-origin",
headers: { "content-type": "application/json" },
body: JSON.stringify({
type: "meeting",
level: "G1",
status: "active",
title,
body: "E2E seeded meeting record for Decision Center frontend validation.",
tags: ["e2e", "decision-center"],
evidenceLinks: ["https://example.com/unidesk/decision-center-e2e"],
}),
});
return { ok: response.ok, status: response.status, body: await response.json().catch(() => null) };
}, decisionCenterE2eTitle);
await page.getByRole("button", { name: /Decision Center/ }).click();
await page.waitForSelector('[data-testid="decision-center-page"]', { timeout: 10000 });
await page.waitForSelector('[data-testid="decision-center-filters"]', { timeout: 30000 });
await page.waitForSelector('[data-testid="decision-center-record-table"]', { timeout: 30000 });
await page.waitForFunction((title) => {
const text = document.body.innerText;
return text.includes("Decision Center")
&& text.includes("G0/G1 目标")
&& text.includes("P0/P1 Blocker")
&& text.includes("停放事项")
&& text.includes("最近会议/决议")
&& text.includes("查看原始JSON")
&& text.includes(String(title));
}, decisionCenterE2eTitle, { timeout: 30000 });
decisionCenterText = await page.locator('[data-testid="decision-center-page"]').innerText({ timeout: 5000 });
decisionCenterMetrics = await page.evaluate(() => {
const root = document.querySelector('[data-testid="decision-center-page"]') as HTMLElement | null;
const table = document.querySelector('[data-testid="decision-center-record-table"]') as HTMLElement | null;
return {
pageVisible: Boolean(root),
tableVisible: Boolean(table),
rawButtonCount: root?.querySelectorAll('[data-testid^="raw-decision-center"], .ghost-btn').length ?? 0,
rawJsonBlocks: root?.querySelectorAll("pre.raw-json, [data-testid='raw-json']").length ?? 0,
chatInputCount: root?.querySelectorAll("textarea, [contenteditable='true']").length ?? 0,
recordCardCount: root?.querySelectorAll('[data-testid^="decision-record-"]').length ?? 0,
tableRows: table?.querySelectorAll("tbody tr").length ?? 0,
textPreview: root?.innerText.slice(0, 1000) || "",
};
});
const decisionCenterRecordId = String(decisionCenterE2eRecord?.body?.record?.id || "");
if (decisionCenterRecordId) {
decisionCenterDeleteResult = await page.evaluate(async (id) => {
const response = await fetch(`/api/microservices/decision-center/proxy/api/records/${encodeURIComponent(String(id))}`, {
method: "DELETE",
credentials: "same-origin",
});
return { ok: response.ok, status: response.status, body: await response.json().catch(() => null) };
}, decisionCenterRecordId);
}
}
if (needCodeQueue) {
await page.getByLabel("用户服务 子功能").getByRole("button", { name: "Code Queue" }).click();
await page.waitForSelector('[data-testid="code-queue-page"]', { timeout: 10000 });
@@ -2787,6 +2886,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
const microserviceCatalogTextLower = microserviceCatalogText.toLowerCase();
const todoNoteTextLower = todoNoteText.toLowerCase();
const findjobTextLower = findjobText.toLowerCase();
const decisionCenterTextLower = decisionCenterText.toLowerCase();
const codeQueueTextLower = codeQueueText.toLowerCase();
const claudeqqTextLower = claudeqqText.toLowerCase();
const pipelineTextLower = pipelineText.toLowerCase();
@@ -2821,7 +2921,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
addSelectedCheck(checks, options, "frontend:gateway-duration-subsecond-visible", gatewayHasSubsecondDuration && !gatewayHasRoundedZeroDuration, { gatewayHasSubsecondDuration, gatewayHasRoundedZeroDuration, gatewayTextPreview: gatewayText.slice(0, 900) });
addSelectedCheck(checks, options, "frontend:provider-operation-availability-visible", sshAvailabilityTexts.length >= 1 && upgradeAvailabilityTexts.length >= 1 && sshAvailabilityTexts.every((text) => text.includes("SSH 透传")) && upgradeAvailabilityTexts.every((text) => text.includes("远程更新")) && upgradeAvailabilityTexts.some((text) => text.includes("always-enabled")), { sshAvailabilityTexts, upgradeAvailabilityTexts });
addSelectedCheck(checks, options, "frontend:overview-pgdata-visible", bodyText.includes("PGDATA") && bodyText.includes(config.database.volume), { bodyPreview: bodyText.slice(0, 800) });
addSelectedCheck(checks, options, "frontend:microservice-catalog-visible", microserviceCatalogTextLower.includes("findjob") && microserviceCatalogTextLower.includes("pipeline") && microserviceCatalogTextLower.includes("todo note") && microserviceCatalogTextLower.includes("met nonlinear") && microserviceCatalogTextLower.includes("claudeqq") && microserviceCatalogTextLower.includes("oa event flow") && microserviceCatalogTextLower.includes("code queue") && microserviceCatalogText.includes("D601") && microserviceCatalogText.includes(config.providerGateway.id) && microserviceCatalogTextLower.includes("private") && microserviceCatalogText.includes("https://gitee.com/Lyon1998/findjob") && microserviceCatalogText.includes("https://github.com/pikasTech/pipeline") && microserviceCatalogText.includes("https://github.com/pikasTech/met_nonlinear") && microserviceCatalogText.includes("https://gitee.com/lyon1998/agent_skills") && microserviceCatalogText.includes("https://gitee.com/Lyon1998/todo_note") && microserviceCatalogText.includes("https://github.com/pikasTech/unidesk"), { microserviceCatalogPreview: microserviceCatalogText.slice(0, 2000) });
addSelectedCheck(checks, options, "frontend:microservice-catalog-visible", microserviceCatalogTextLower.includes("findjob") && microserviceCatalogTextLower.includes("pipeline") && microserviceCatalogTextLower.includes("todo note") && microserviceCatalogTextLower.includes("met nonlinear") && microserviceCatalogTextLower.includes("claudeqq") && microserviceCatalogTextLower.includes("oa event flow") && microserviceCatalogTextLower.includes("code queue") && microserviceCatalogTextLower.includes("decision center") && microserviceCatalogText.includes("D601") && microserviceCatalogText.includes(config.providerGateway.id) && microserviceCatalogTextLower.includes("private") && microserviceCatalogText.includes("https://gitee.com/Lyon1998/findjob") && microserviceCatalogText.includes("https://github.com/pikasTech/pipeline") && microserviceCatalogText.includes("https://github.com/pikasTech/met_nonlinear") && microserviceCatalogText.includes("https://gitee.com/lyon1998/agent_skills") && microserviceCatalogText.includes("https://gitee.com/Lyon1998/todo_note") && microserviceCatalogText.includes("https://github.com/pikasTech/unidesk"), { microserviceCatalogPreview: microserviceCatalogText.slice(0, 2000) });
addSelectedCheck(checks, options, "frontend:todo-note-integrated-visible", todoNoteTextLower.includes("todo note 工作台") && todoNoteText.includes("CONSTAR") && todoNoteText.includes("大论文") && todoNoteText.includes("UI E2E smoke task") && todoNoteText.includes("撤销") && todoNoteText.includes("重做") && todoNoteText.includes("全部展开") && todoNoteText.includes("仅 UniDesk frontend 代理访问"), { todoNoteTextPreview: todoNoteText.slice(0, 1400) });
addSelectedCheck(checks, options, "frontend:findjob-integrated-visible", findjobTextLower.includes("findjob 工作台".toLowerCase()) && findjobText.includes("岗位总量") && findjobText.includes("D601") && findjobText.includes("近期岗位") && findjobText.includes("仅 UniDesk frontend 代理访问") && /岗位总量\s+\d+/.test(findjobText) && /health\s+ok/i.test(findjobText) && /[1-9]\d*\/[1-9]\d*\s+preview/i.test(findjobText), { findjobTextPreview: findjobText.slice(0, 1200) });
addSelectedCheck(checks, options, "frontend:oa-event-flow-visible",
@@ -2837,6 +2937,24 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2
&& Number(oaEventFlowMetrics.rawButtonCount || 0) >= 2
&& !oaEventFlowText.includes("{\n"),
{ oaEventFlowMetrics, oaEventFlowTextPreview: oaEventFlowText.slice(0, 1400) });
addSelectedCheck(checks, options, "frontend:decision-center-visible",
decisionCenterTextLower.includes("decision center")
&& decisionCenterText.includes("G0/G1 目标")
&& decisionCenterText.includes("P0/P1 Blocker")
&& decisionCenterText.includes("停放事项")
&& decisionCenterText.includes("最近会议/决议")
&& decisionCenterText.includes("全部记录")
&& decisionCenterText.includes("PostgreSQL")
&& decisionCenterText.includes("查看原始JSON")
&& decisionCenterMetrics.pageVisible === true
&& decisionCenterMetrics.tableVisible === true
&& decisionCenterE2eRecord?.ok === true
&& decisionCenterDeleteResult?.ok === true
&& Number(decisionCenterMetrics.rawButtonCount || 0) >= 1
&& Number(decisionCenterMetrics.rawJsonBlocks || 0) === 0
&& Number(decisionCenterMetrics.chatInputCount || 0) === 0
&& !decisionCenterText.includes("{\n"),
{ decisionCenterMetrics, decisionCenterE2eRecord, decisionCenterDeleteResult, decisionCenterTextPreview: decisionCenterText.slice(0, 1400) });
addSelectedCheck(checks, options, "frontend:code-queue-integrated-visible", codeQueueTextLower.includes("code queue") && codeQueueText.includes("gpt-5.4-mini") && codeQueueText.includes("gpt-5.4") && codeQueueText.includes("gpt-5.5") && codeQueueText.includes("提交任务") && codeQueueText.includes("执行 Provider") && codeQueueText.includes("入队份数") && codeQueueText.includes("追加 prompt") && codeQueueText.includes("打断") && codeQueueTextLower.includes("查看 queue") && codeQueueText.includes("创建 queue") && codeQueueText.includes("合并 queue") && codeQueueOptions.some((text) => text.includes("All queues")) && codeQueueTracePlacement.firstChildIsTrace === true && codeQueueTracePlacement.noPageTopStatus === true && codeQueueTracePlacement.filterInsideTracePanel === true && codeQueueTracePlacement.taskSearchVisible === true && codeQueueTracePlacement.traceStatusVisible === true && codeQueueTracePlacement.markAllReadVisible === true && codeQueueGlobalStatus.activeMicroserviceVisible === true && codeQueueSidebarUpdateMetrics.hasRecentUpdateLabel === true && codeQueueHtmlGuard.rootAttrMissing === true && codeQueueHtmlGuard.sourceAttrMissing === true && codeQueueHtmlGuard.sourceNoBasePrompt === true && codeQueueSubmitQueueControl.tagName === "select" && codeQueueSubmitQueueControl.createButtonVisible === true && codeQueueSubmitQueueControl.mergeButtonVisible === true && codeQueueSubmitQueueControl.mergeSourceInlineMissing === true && codeQueueSubmitQueueControl.mergeDialogMissingBeforeClick === true && (codeQueueSubmitQueueControl.mergeButtonDisabled === true || (codeQueueSubmitQueueControl.mergeDialogVisible === true && codeQueueSubmitQueueControl.mergeDialogSelectVisible === true && Number(codeQueueSubmitQueueControl.mergeDialogSourceOptionCount || 0) > 1 && codeQueueSubmitQueueControl.mergeDialogSelectInsideSubmitForm !== true && codeQueueSubmitQueueControl.mergeDialogUsesCommonComponent === true && codeQueueSubmitQueueControl.mergeDialogDeleteNoteVisible === true)) && codeQueueSubmitQueueControl.oldInputMissing === true && codeQueueSubmitQueueControl.providerValue === "D601" && codeQueueSubmitQueueControl.cwdValue === "/workspace" && Array.isArray(codeQueueSubmitQueueControl.providerOptions) && codeQueueSubmitQueueControl.providerOptions.some((item: any) => item.value === "D601" && String(item.text || "").includes("/workspace")) && codeQueueSubmitQueueControl.maxAttemptsMax === "99" && codeQueueSubmitQueueControl.maxAttemptsValue === "99" && codeQueueSubmitQueueControl.moveQueueVisible === true && codeQueuePromptDefaultEmpty === true && codeQueueSubmitGuard.batchRowVisible === true && codeQueueSubmitGuard.checkboxVisible === true && codeQueueSubmitGuard.disabledBeforeConfirm === true && codeQueueSubmitGuard.enabledAfterConfirm === true && codeQueueSubmitGuard.waitElementMissingBeforeSubmit === true && codeQueueScrollbarMetrics.transcriptThin === true && codeQueueScrollbarMetrics.toolHorizontalHidden === true && (codeQueueSwitchMetrics.optionCount <= 1 || codeQueueSwitchMetrics.switched === true) && codeQueueTextLower.includes("attempts") && codeQueueText.includes("仅 UniDesk frontend 代理访问") && (codeQueueTaskCount === 0 || codeQueueOutputText.includes("Submitted prompt")), { codeQueueTaskCount, codeQueueOptions, codeQueueSwitchMetrics, codeQueueSubmitQueueControl, codeQueueSubmitGuard, codeQueueScrollbarMetrics, codeQueuePromptDefaultEmpty, codeQueueTracePlacement, codeQueueGlobalStatus, codeQueueSidebarUpdateMetrics, codeQueueHtmlGuard, codeQueueOutputPreview: codeQueueOutputText.slice(0, 900), codeQueueTextPreview: codeQueueText.slice(0, 1400) });
addSelectedCheck(checks, options, "frontend:code-queue-enqueue-await-smoke",
codeQueueEnqueueAwaitSmoke.checked === true