From 7715c506d584dd24efcb7c1911c7fa7c0134cb1a Mon Sep 17 00:00:00 2001 From: lyon Date: Mon, 15 Jun 2026 20:06:50 +0800 Subject: [PATCH] fix(probe): include login failure diagnostics --- scripts/web-live-dom-probe.mjs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/scripts/web-live-dom-probe.mjs b/scripts/web-live-dom-probe.mjs index 0d0f6f79..63280523 100644 --- a/scripts/web-live-dom-probe.mjs +++ b/scripts/web-live-dom-probe.mjs @@ -217,6 +217,7 @@ export async function runProbe(args) { const { width, height } = parseViewport(args.viewport); const actions = []; let browser; + let page; let result; if (args.credentialError) { result = { @@ -247,7 +248,7 @@ export async function runProbe(args) { const { chromium } = await importPlaywright(); browser = await launchChromium(chromium); const context = await browser.newContext({ viewport: { width, height } }); - const page = await context.newPage(); + page = await context.newPage(); const bootstrapRoutes = observeBootstrapRoutes(page); await page.goto(args.url, { waitUntil: "domcontentloaded", timeout: args.timeoutMs }); await waitForAuthBootstrap(page, args, actions); @@ -300,6 +301,8 @@ export async function runProbe(args) { actions, credentials: args.credentials, error: error instanceof Error ? error.message : String(error), + finalUrl: page ? page.url() : null, + failureDom: page ? await collectFailureDomEvidence(page).catch((domError) => ({ error: domError instanceof Error ? domError.message : String(domError) })) : null, artifacts: { reportPath, screenshotPath } }; } finally { @@ -317,6 +320,30 @@ export async function runProbe(args) { return result; } +async function collectFailureDomEvidence(page) { + return page.evaluate(() => { + const text = (selector) => document.querySelector(selector)?.textContent?.trim() ?? null; + const bodyText = document.body?.innerText?.replace(/\s+/gu, " ").trim() ?? ""; + return { + authState: document.body?.getAttribute("data-auth-state") ?? null, + title: document.title || null, + locationPath: window.location.pathname, + login: { + cardVisible: Boolean(document.querySelector(".login-card")), + usernameVisible: Boolean(document.querySelector('#login-username, input[autocomplete="username"]')), + passwordVisible: Boolean(document.querySelector('#login-password, input[autocomplete="current-password"], input[type="password"]')), + errorText: text(".login-error, [role='alert'], .error, .text-red-500, .text-destructive") + }, + requiredSelectors: { + workspace: Boolean(document.querySelector("#workspace")), + commandInput: Boolean(document.querySelector("#command-input")), + conversationList: Boolean(document.querySelector("#conversation-list")) + }, + bodyTextPreview: bodyText.slice(0, 500) + }; + }); +} + function validatePromptFinalResponse(dom, args) { if (!args.message) return { ok: true, applicable: false, reason: "no-prompt-submitted" }; const messages = Array.isArray(dom.messages) ? dom.messages : [];