fix: support direct help route

This commit is contained in:
Code Queue Review
2026-05-23 02:27:05 +00:00
parent 0a7311c3c2
commit ff19c36696
5 changed files with 59 additions and 8 deletions
+1 -1
View File
@@ -468,7 +468,7 @@ async function serveCloudWeb() {
}
const routePath = url.pathname.replace(/\/+$/, "") || "/";
const relativePath = routePath === "/" || routePath === "/gate" || routePath === "/diagnostics/gate" ? "index.html" : url.pathname.slice(1);
const relativePath = routePath === "/" || routePath === "/gate" || routePath === "/diagnostics/gate" || routePath === "/help" ? "index.html" : url.pathname.slice(1);
for (const root of roots) {
const candidate = path.resolve(root, relativePath);
if (!candidate.startsWith(root)) continue;
+46 -5
View File
@@ -64,6 +64,7 @@ const diagnosticsRequiredTerms = Object.freeze([
]);
const gateRouteAliases = Object.freeze(["/gate", "/diagnostics/gate"]);
const helpRouteAliases = Object.freeze(["/help"]);
const incompletePrimaryNavLabels = Object.freeze(["台", "证", "诊", "帮"]);
@@ -253,6 +254,11 @@ function runStaticSmoke() {
evidence: gateRouteAliases
});
addCheck(checks, blockers, "direct-help-route-alias", helpRouteAliasesAreServed(files.app, artifactPublisher, buildScript, distContractScript), "/help is a direct user-facing help alias and does not become the default route.", {
blocker: "runtime_blocker",
evidence: [...helpRouteAliases, "routeFromLocation final fallback is workspace"]
});
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
@@ -966,6 +972,19 @@ function gateRouteAliasesAreServed(app, artifactPublisher, buildScript, distCont
);
}
function helpRouteAliasesAreServed(app, artifactPublisher, buildScript, distContractScript) {
const routeBody = functionBody(app, "routeFromLocation");
return (
/helpPathnames\(\)\.has/u.test(routeBody) &&
helpRouteAliases.every((route) => app.includes(`"${route}"`)) &&
helpRouteAliases.every((route) => artifactPublisher.includes(`routePath === "${route}"`)) &&
/buildCloudWebDist/u.test(buildScript) &&
/help\/index\.html/u.test(distContractScript) &&
/return "help"/u.test(routeBody) &&
finalRouteFallback(app) === "workspace"
);
}
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>`));
@@ -1321,7 +1340,7 @@ function inspectHelpRoute(html, app) {
/data-route=["']help["']/u.test(html) ||
/data-view=["']help["']/u.test(html) ||
/#help\b/u.test(html + app) ||
/pathname[\s\S]{0,160}\/help/u.test(app);
/pathname[\s\S]{0,220}\/help/u.test(app);
const finalFallback = finalRouteFallback(app);
const helpViewHidden = helpViewTag ? /\bhidden\b/u.test(helpViewTag) : false;
return {
@@ -1983,6 +2002,12 @@ export async function runDevCloudWorkbenchMobileSmoke() {
await page.click('[data-route="help"]');
await page.waitForFunction(() => document.querySelector("#help-content")?.dataset.helpState === "ready", null, { timeout: 8000 });
const help = await inspectHelpMarkdownRoute(page);
await page.goto(new URL("/#/help", server.url).toString(), { waitUntil: "networkidle", timeout: 15000 });
await page.waitForFunction(() => document.querySelector("#help-content")?.dataset.helpState === "ready", null, { timeout: 8000 });
const slashHashHelp = await inspectHelpMarkdownRoute(page);
await page.goto(new URL("/help", server.url).toString(), { waitUntil: "networkidle", timeout: 15000 });
await page.waitForFunction(() => document.querySelector("#help-content")?.dataset.helpState === "ready", null, { timeout: 8000 });
const directHelp = await inspectHelpMarkdownRoute(page);
await page.click('[data-route="workspace"]');
await page.waitForFunction(() => document.querySelector('[data-view="workspace"]')?.hidden === false, null, { timeout: 8000 });
await page.click("#explorer-toggle");
@@ -2018,10 +2043,22 @@ export async function runDevCloudWorkbenchMobileSmoke() {
},
{
id: "mobile-help-markdown-route",
status: help.nonDefaultMarkdownHelp && help.termsPresent ? "pass" : "blocked",
summary: "Help opens as a non-default internal route rendered from help.md by the vendored Markdown renderer.",
status: help.nonDefaultMarkdownHelp && help.routeIsHashHelp && help.termsPresent ? "pass" : "blocked",
summary: "Help opens from the rail as a non-default hash route rendered from help.md by the vendored Markdown renderer.",
observations: help
},
{
id: "mobile-slash-hash-help-route",
status: slashHashHelp.nonDefaultMarkdownHelp && slashHashHelp.routeIsSlashHashHelp && slashHashHelp.termsPresent ? "pass" : "blocked",
summary: "Direct #/help opens the user-facing help view.",
observations: slashHashHelp
},
{
id: "mobile-direct-help-route",
status: directHelp.nonDefaultMarkdownHelp && directHelp.routeIsDirectHelp && directHelp.termsPresent ? "pass" : "blocked",
summary: "Direct /help opens the user-facing help view instead of raw API 404 JSON.",
observations: directHelp
},
{
id: "mobile-default-hit-test",
status: closed.primaryControlsReachable ? "pass" : "blocked",
@@ -2109,7 +2146,7 @@ async function startStaticWebServer(options = {}) {
return;
}
let pathname = decodeURIComponent(url.pathname);
if (pathname === "/" || pathname === "/workbench" || pathname === "/gate" || pathname === "/diagnostics/gate") {
if (pathname === "/" || pathname === "/workbench" || pathname === "/gate" || pathname === "/diagnostics/gate" || pathname === "/help") {
pathname = "/index.html";
}
const filePath = path.resolve(webRoot, pathname.replace(/^\/+/, ""));
@@ -2490,6 +2527,7 @@ async function inspectHelpMarkdownRoute(page) {
document.body.scrollHeight <= document.body.clientHeight + 2;
return {
hash: window.location.hash,
pathname: window.location.pathname,
helpState: helpContent?.dataset.helpState ?? null,
workspaceHidden: workspace ? workspace.hidden : null,
gateHidden: gate ? gate.hidden : null,
@@ -2504,8 +2542,11 @@ async function inspectHelpMarkdownRoute(page) {
helpPanelScrolls: Boolean(helpScroll && helpScroll.scrollHeight > helpScroll.clientHeight && helpScroll.after > helpScroll.before),
rootStillLocked,
helpScroll,
routeIsHashHelp: window.location.hash === "#help",
routeIsSlashHashHelp: window.location.hash === "#/help",
routeIsDirectHelp: (window.location.pathname.replace(/\/+$/, "") || "/") === "/help",
nonDefaultMarkdownHelp:
window.location.hash === "#help" &&
(window.location.hash === "#help" || window.location.hash === "#/help" || (window.location.pathname.replace(/\/+$/, "") || "/") === "/help") &&
workspace?.hidden === true &&
gate?.hidden === true &&
help?.hidden === false &&