fix: address Cloud Workbench feedback 117-120
This commit is contained in:
@@ -33,11 +33,44 @@ const chineseWorkbenchLabels = Object.freeze([
|
||||
"HWLAB 云工作台",
|
||||
"硬件资源",
|
||||
"Agent 对话",
|
||||
"执行轨迹",
|
||||
"工作清单",
|
||||
"可信记录",
|
||||
"内部复核",
|
||||
"使用说明"
|
||||
]);
|
||||
|
||||
const defaultHomepageForbiddenTerms = Object.freeze([
|
||||
"Gate",
|
||||
"诊断",
|
||||
"验收",
|
||||
"M0-M5",
|
||||
"BLOCKED",
|
||||
"db-live",
|
||||
"m3-hardware-loop-runtime",
|
||||
"执行轨迹"
|
||||
]);
|
||||
|
||||
const diagnosticsRequiredTerms = Object.freeze([
|
||||
"Gate / 诊断 / 验收",
|
||||
"M0-M5",
|
||||
"BLOCKED",
|
||||
"DB live readiness",
|
||||
"patch-panel DO1 -> DI1"
|
||||
]);
|
||||
|
||||
const incompletePrimaryNavLabels = Object.freeze(["台", "证", "诊", "帮"]);
|
||||
|
||||
const requiredWiringColumns = Object.freeze([
|
||||
"源设备",
|
||||
"源端口",
|
||||
"接线盘",
|
||||
"目标设备",
|
||||
"目标端口",
|
||||
"状态",
|
||||
"证据来源",
|
||||
"trace/evidence"
|
||||
]);
|
||||
|
||||
const workbenchMarkers = Object.freeze([
|
||||
"data-app-shell",
|
||||
"workbench-shell",
|
||||
@@ -46,7 +79,7 @@ const workbenchMarkers = Object.freeze([
|
||||
"resource-tree",
|
||||
"center-workspace",
|
||||
"conversation-list",
|
||||
"trace-list",
|
||||
"task-list",
|
||||
"right-sidebar",
|
||||
"hardware-list",
|
||||
"command-form"
|
||||
@@ -129,6 +162,26 @@ function runStaticSmoke() {
|
||||
evidence: chineseWorkbenchLabels
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "feedback-117-default-no-backstage", defaultHomepageHidesBackstage(files), "Default workbench hides Gate, diagnostics, acceptance, BLOCKED, and M0-M5 backstage information.", {
|
||||
blocker: "runtime_blocker",
|
||||
evidence: defaultHomepageForbiddenTerms
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "feedback-118-complete-nav", hasCompletePrimaryNavigation(files.html), "Primary navigation uses complete Chinese labels and removes the left-rail trusted-records shortcut.", {
|
||||
blocker: "contract_blocker",
|
||||
evidence: ["工作台", "内部复核", "使用说明", "资源树"]
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "feedback-119-gate-retains-diagnostics", gateRetainsDiagnostics(files.html, files.app), "Internal Gate page retains BLOCKED/M0-M5 diagnostics and the DB live plus patch-panel DO1 -> DI1 unblock path.", {
|
||||
blocker: "contract_blocker",
|
||||
evidence: diagnosticsRequiredTerms
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "feedback-120-wiring-table", wiringTableContract(files.html), "Patch-panel wiring panel is a table with source, target, status, evidence source, and trace/evidence columns.", {
|
||||
blocker: "contract_blocker",
|
||||
evidence: requiredWiringColumns
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "outer-scroll-contract", hasScrollLockContract(files.styles), "Outer page scrolling is locked and internal workbench panes own scrolling.", {
|
||||
blocker: "contract_blocker",
|
||||
evidence: ["html/body overflow hidden", "workbench-shell 100vh/100dvh overflow hidden", ".view overflow auto"]
|
||||
@@ -221,7 +274,15 @@ function baseReport({ mode, status, checks, blockers, evidenceLevel, devLive, he
|
||||
return {
|
||||
status,
|
||||
task: "DC-DCSN-P0-2026-003",
|
||||
refs: ["pikasTech/HWLAB#108", "pikasTech/HWLAB#99", "pikasTech/HWLAB#78"],
|
||||
refs: [
|
||||
"pikasTech/HWLAB#108",
|
||||
"pikasTech/HWLAB#99",
|
||||
"pikasTech/HWLAB#78",
|
||||
"pikasTech/HWLAB#117",
|
||||
"pikasTech/HWLAB#118",
|
||||
"pikasTech/HWLAB#119",
|
||||
"pikasTech/HWLAB#120"
|
||||
],
|
||||
mode,
|
||||
url,
|
||||
generatedAt: new Date().toISOString(),
|
||||
@@ -299,14 +360,49 @@ function secondaryViewsAreNotDefault({ html, app }) {
|
||||
const unhiddenSecondaryViews = [...html.matchAll(/<section\b[^>]*\bdata-view=["']([^"']+)["'][^>]*>/gu)]
|
||||
.filter((match) => match[1] !== "workspace")
|
||||
.filter((match) => !/\bhidden\b/u.test(match[0]));
|
||||
const diagnosticsPanel = html.match(/<section\b[^>]*\bdata-side-panel=["']diagnostics["'][^>]*>/u)?.[0] ?? "";
|
||||
return finalFallback === "workspace" && unhiddenSecondaryViews.length === 0 && /\bhidden\b/u.test(diagnosticsPanel);
|
||||
return finalFallback === "workspace" && unhiddenSecondaryViews.length === 0;
|
||||
}
|
||||
|
||||
function firstTagForDataView(html, view) {
|
||||
return html.match(new RegExp(`<section\\b[^>]*\\bdata-view=["']${escapeRegExp(view)}["'][^>]*>`, "u"))?.[0] ?? null;
|
||||
}
|
||||
|
||||
function sectionSource(source, viewId) {
|
||||
const start = source.search(new RegExp(`<section\\b[^>]*\\bdata-view=["']${escapeRegExp(viewId)}["'][^>]*>`, "u"));
|
||||
if (start === -1) return "";
|
||||
const next = source.slice(start + 1).search(/<section\b[^>]*\bdata-view=["'][^"']+["'][^>]*>/u);
|
||||
return next === -1 ? source.slice(start) : source.slice(start, start + 1 + next);
|
||||
}
|
||||
|
||||
function beforeSection(source, viewId) {
|
||||
const index = source.search(new RegExp(`<section\\b[^>]*\\bdata-view=["']${escapeRegExp(viewId)}["'][^>]*>`, "u"));
|
||||
return index === -1 ? source : source.slice(0, index);
|
||||
}
|
||||
|
||||
function defaultHomepageHidesBackstage({ html }) {
|
||||
const workspaceHtml = sectionSource(html, "workspace");
|
||||
const visibleShellHtml = `${beforeSection(html, "help")}\n${workspaceHtml}`;
|
||||
return defaultHomepageForbiddenTerms.every((term) => !visibleShellHtml.includes(term));
|
||||
}
|
||||
|
||||
function hasCompletePrimaryNavigation(html) {
|
||||
const navLabelsPresent = ["工作台", "内部复核", "使用说明", "资源树"].every((label) => html.includes(`>${label}<`));
|
||||
const legacyLabelsAbsent = incompletePrimaryNavLabels.every((label) => !html.includes(`>${label}<`));
|
||||
const noLeftSideRecordsShortcut = !/data-side-tab-jump=["']records["']/u.test(html);
|
||||
return navLabelsPresent && legacyLabelsAbsent && noLeftSideRecordsShortcut;
|
||||
}
|
||||
|
||||
function gateRetainsDiagnostics(html, app) {
|
||||
const gateHtml = sectionSource(html, "gate");
|
||||
const gateSource = `${gateHtml}\n${app}`;
|
||||
return diagnosticsRequiredTerms.every((term) => gateSource.includes(term));
|
||||
}
|
||||
|
||||
function wiringTableContract(html) {
|
||||
const wiringPanel = html.match(/<section\b[^>]*\bdata-side-panel=["']wiring["'][\s\S]*?<\/section>/u)?.[0] ?? "";
|
||||
return requiredWiringColumns.every((column) => wiringPanel.includes(`<th>${column}</th>`));
|
||||
}
|
||||
|
||||
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]);
|
||||
@@ -323,7 +419,7 @@ function hasScrollLockContract(styles) {
|
||||
/body\s*>\s*\[data-app-shell\]\s*\{[^\}]*min-height:\s*0;/su.test(styles) &&
|
||||
/\.workbench-shell\s*\{[^\}]*height:\s*100(?:d)?vh;[^\}]*overflow:\s*hidden;/su.test(styles) &&
|
||||
/\.view\s*\{[^\}]*min-height:\s*0;[^\}]*overflow:\s*auto;/su.test(styles) &&
|
||||
/\.(?:resource-tree|compact-list|conversation-list|trace-list|hardware-list)[^\{]*\{[^\}]*min-height:\s*0;[^\}]*overflow:\s*auto;/su.test(styles)
|
||||
/\.(?:resource-tree|compact-list|conversation-list|trace-list|task-list|hardware-list)[^\{]*\{[^\}]*min-height:\s*0;[^\}]*overflow:\s*auto;/su.test(styles)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -499,7 +595,7 @@ async function inspectLiveDom(url) {
|
||||
gateHidden: gate ? gate.hidden : null,
|
||||
diagnosticsHidden: diagnostics ? diagnostics.hidden : null,
|
||||
outerScrollLocked: document.documentElement.scrollHeight <= document.documentElement.clientHeight + 2,
|
||||
labelsPresent: ["硬件资源", "Agent 对话", "执行轨迹", "可信记录", "使用说明"].every((label) => text.includes(label))
|
||||
labelsPresent: ["硬件资源", "Agent 对话", "工作清单", "可信记录", "使用说明"].every((label) => text.includes(label))
|
||||
};
|
||||
});
|
||||
const pass =
|
||||
|
||||
Reference in New Issue
Block a user