feat: group Cloud Workbench trusted records
Merge PR #146 after Code Queue rebase to main a444387 and validation. This improves the deployed workbench UI surface for trusted records with explicit DEV-LIVE/SOURCE/DRY-RUN/BLOCKED labels. It does not claim M3 DEV-LIVE and does not change PROD or secrets.
This commit is contained in:
@@ -73,6 +73,21 @@ const requiredWiringColumns = Object.freeze([
|
||||
"trace/evidence"
|
||||
]);
|
||||
|
||||
const requiredTrustedRecordTerms = Object.freeze([
|
||||
"Code Agent 对话记录",
|
||||
"接线/operation",
|
||||
"audit 记录",
|
||||
"evidence 证据",
|
||||
"trace/messageId",
|
||||
"audit.event.query + SOURCE 回退",
|
||||
"evidence.record.query + SOURCE 回退",
|
||||
"conversationId、traceId 和 messageId",
|
||||
"失败原因=",
|
||||
"只读 audit 缺少 M3 patch-panel live report / operation / trace / evidence 绑定",
|
||||
"只读 evidence 缺少 M3 patch-panel live report / operation / trace / audit 绑定",
|
||||
"当前显示 SOURCE 回退,不能冒充 DEV-LIVE"
|
||||
]);
|
||||
|
||||
const requiredHardwareStatusTerms = Object.freeze([
|
||||
"hardware-source-status",
|
||||
"hardwareGroup",
|
||||
@@ -208,6 +223,11 @@ function runStaticSmoke() {
|
||||
evidence: requiredWiringColumns
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "trusted-record-groups", trustedRecordGroups(files), "Trusted Records panel groups Code Agent, wiring/operation, audit, and evidence summaries with source labels and live-failure fallback.", {
|
||||
blocker: "observability_blocker",
|
||||
evidence: requiredTrustedRecordTerms
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "hardware-status-rich-structure", hardwareStatusStructureContract(files), "Right hardware status renders Gateway/Box, DI/DO/AI/AO/FREQ, patch-panel, and DO1 -> DI1 source-labeled link state.", {
|
||||
blocker: "contract_blocker",
|
||||
evidence: requiredHardwareStatusTerms
|
||||
@@ -512,6 +532,38 @@ function defaultTopologyIsM3Only() {
|
||||
);
|
||||
}
|
||||
|
||||
function trustedRecordGroups({ html, app, styles }) {
|
||||
const source = `${html}\n${app}\n${styles}`;
|
||||
return (
|
||||
/id=["']records-list["']/u.test(html) &&
|
||||
/function\s+renderRecords\s*\(/u.test(app) &&
|
||||
/function\s+codeAgentRecordCards\s*\(/u.test(app) &&
|
||||
/function\s+operationRecordCards\s*\(/u.test(app) &&
|
||||
/function\s+auditRecordCards\s*\(/u.test(app) &&
|
||||
/function\s+evidenceRecordCards\s*\(/u.test(app) &&
|
||||
/function\s+auditCard\s*\(/u.test(app) &&
|
||||
/function\s+evidenceCard\s*\(/u.test(app) &&
|
||||
/function\s+recordGroup\s*\(/u.test(app) &&
|
||||
/function\s+recordField\s*\(/u.test(app) &&
|
||||
/function\s+sourceKindLabel\s*\(/u.test(app) &&
|
||||
/function\s+liveFailureCard\s*\(/u.test(app) &&
|
||||
/state\.liveSurface/u.test(app) &&
|
||||
/renderRecords\(state\.liveSurface\)/u.test(app) &&
|
||||
/traceId: error\.traceId \|\| traceId/u.test(app) &&
|
||||
/error\.traceId = traceId/u.test(app) &&
|
||||
requiredTrustedRecordTerms.every((term) => source.includes(term)) &&
|
||||
/\.record-group\s*\{/u.test(styles) &&
|
||||
/\.record-group-title\s*\{/u.test(styles) &&
|
||||
/\.record-group-list\s*\{/u.test(styles) &&
|
||||
/replaceChildren\(el\.recordsList, \.\.\.groups\)/u.test(app) &&
|
||||
/gateSummary\.operations\.map/u.test(app) &&
|
||||
/gateSummary\.auditEvents\.slice\(0,\s*4\)\.map/u.test(app) &&
|
||||
/gateSummary\.evidenceRecords\.map/u.test(app) &&
|
||||
/message\.status === "failed" \? "blocked" : "source"/u.test(app) &&
|
||||
!/message\.status === "completed"\s*\?\s*"dev-live"/u.test(app)
|
||||
);
|
||||
}
|
||||
|
||||
function finalRouteFallback(app) {
|
||||
const body = app.match(/function\s+routeFromLocation\s*\(\)\s*\{([\s\S]*?)\n\}/u)?.[1] ?? "";
|
||||
const returns = [...body.matchAll(/return\s+["']([^"']+)["']\s*;/gu)].map((match) => match[1]);
|
||||
@@ -591,6 +643,8 @@ function sourceEvidenceNotDevLive(source) {
|
||||
const m3 = gateSummary.milestones.find((item) => item.id === "M3");
|
||||
return (
|
||||
m3?.status === "blocked" &&
|
||||
gateSummary.operations.every((operation) => operation.dryRun === true) &&
|
||||
gateSummary.auditEvents.every((event) => event.dryRun === true) &&
|
||||
gateSummary.evidenceRecords.every((record) => record.dryRun === true) &&
|
||||
gateSummary.safety.allowNetwork === false &&
|
||||
["来源 SOURCE", "演练 DRY-RUN", "开发实况 DEV-LIVE", "阻塞 BLOCKED"].every((label) => source.includes(label))
|
||||
|
||||
Reference in New Issue
Block a user