fix(web-probe): require visible mdtodo report preview

This commit is contained in:
Codex
2026-06-27 06:35:56 +00:00
parent 5dc54ea950
commit f36dfee57c
@@ -1266,7 +1266,7 @@ async function waitForProjectManagementCommandReady(options = {}) {
const needsTask = /\/tasks\//u.test(path);
const taskReady = !needsTask || Boolean(last?.selectedTaskId || last?.selectedTaskRef?.hash || last?.taskBodyVisible === true || last?.launchButtonVisible === true);
const needsReport = /\/reports\//u.test(path);
const reportReady = !needsReport || last?.reportPreviewVisible === true || last?.reportFullscreenVisible === true || Number(last?.reportLinkCount || 0) > 0;
const reportReady = !needsReport || last?.reportPreviewVisible === true || last?.reportFullscreenVisible === true;
if (baseReady && taskReady && reportReady) return { ok: true, reason: "project-management-command-ready", durationMs: Date.now() - started, snapshot: last, valuesRedacted: true };
await page.waitForTimeout(250).catch(() => {});
}
@@ -2744,19 +2744,53 @@ async function openMdtodoReportPreview(command) {
error.details = { beforeUrl, linkState, beforeProject, valuesRedacted: true };
throw error;
}
const responsePromise = page.waitForResponse((response) => {
const attempts = [];
let response = null;
let afterProject = null;
for (let attempt = 1; attempt <= 3; attempt += 1) {
const responsePromise = page.waitForResponse((item) => {
try {
const request = item.request();
return request.method().toUpperCase() === "GET" && new URL(item.url()).pathname === "/v1/project-management/mdtodo/report-preview";
} catch {
return false;
}
}, { timeout: 10000 }).then((item) => ({ observed: true, status: item.status(), path: new URL(item.url()).pathname })).catch((error) => ({ observed: false, waitError: errorSummary(error) }));
const clickMode = attempt === 1 ? "normal" : "force";
let click = { ok: true, mode: clickMode, valuesRedacted: true };
await link.scrollIntoViewIfNeeded().catch(() => null);
try {
const request = response.request();
return request.method().toUpperCase() === "GET" && new URL(response.url()).pathname === "/v1/project-management/mdtodo/report-preview";
} catch {
return false;
if (attempt === 1) await link.click();
else await link.click({ force: true, timeout: 5000 });
} catch (error) {
click = { ok: false, mode: clickMode, error: errorSummary(error), valuesRedacted: true };
await link.evaluate((element) => element.click()).catch(() => null);
}
}, { timeout: 30000 }).then((response) => ({ observed: true, status: response.status(), path: new URL(response.url()).pathname })).catch((error) => ({ observed: false, waitError: errorSummary(error) }));
await link.scrollIntoViewIfNeeded().catch(() => null);
await link.click();
const response = await responsePromise;
await page.locator('[data-testid="mdtodo-report-preview"], [data-testid="mdtodo-report-error"]').first().waitFor({ state: "visible", timeout: 10000 }).catch(() => null);
return { beforeUrl, afterUrl: currentPageUrl(), type: "openMdtodoReportPreview", selection, linkState, response, beforeProject, afterProject: await projectManagementCommandSnapshot(), pageId, valuesRedacted: true };
await page.locator('[data-testid="mdtodo-report-preview"], [data-testid="mdtodo-report-error"]').first().waitFor({ state: "visible", timeout: 5000 }).catch(() => null);
afterProject = await projectManagementCommandSnapshot();
response = afterProject?.reportPreviewVisible === true
? { observed: null, skippedAfterPreviewVisible: true, valuesRedacted: true }
: await responsePromise;
attempts.push({
attempt,
click,
response,
afterUrl: currentPageUrl(),
reportPreviewVisible: afterProject?.reportPreviewVisible === true,
reportErrorVisible: afterProject?.reportErrorVisible === true,
reportFullscreenVisible: afterProject?.reportFullscreenVisible === true,
valuesRedacted: true
});
if (afterProject?.reportPreviewVisible === true) break;
await page.waitForTimeout(700).catch(() => null);
}
afterProject = afterProject ?? await projectManagementCommandSnapshot();
if (afterProject?.reportPreviewVisible !== true) {
const error = new Error("openMdtodoReportPreview did not show markdown report preview");
error.details = { beforeUrl, afterUrl: currentPageUrl(), selection, linkState, response, attempts, beforeProject, afterProject, pageId, valuesRedacted: true };
throw error;
}
return { beforeUrl, afterUrl: currentPageUrl(), type: "openMdtodoReportPreview", selection, linkState, response, attempts, beforeProject, afterProject, pageId, valuesRedacted: true };
}
async function toggleMdtodoReportFullscreen(command) {
@@ -2977,6 +3011,7 @@ async function projectManagementCommandSnapshot(options = {}) {
const launch = document.querySelector('[data-testid="mdtodo-workbench-launch"], [data-action="launch-workbench"]');
const bodyRendered = document.querySelector('[data-testid="mdtodo-body-rendered"]');
const reportPreview = document.querySelector('[data-testid="mdtodo-report-preview"]');
const reportError = document.querySelector('[data-testid="mdtodo-report-error"]');
const reportFullscreen = document.querySelector('[data-testid="mdtodo-report-fullscreen-dialog"]');
const reportLinks = Array.from(document.querySelectorAll('[data-testid="mdtodo-report-link"]')).filter(visible);
return {
@@ -3002,6 +3037,8 @@ async function projectManagementCommandSnapshot(options = {}) {
reportLinkCount: reportLinks.length,
reportPreviewVisible: visible(reportPreview),
reportPreviewText: visible(reportPreview) ? text(reportPreview) : "",
reportErrorVisible: visible(reportError),
reportErrorText: visible(reportError) ? text(reportError) : "",
reportFullscreenVisible: visible(reportFullscreen),
launchButtonVisible: visible(launch),
launchButtonEnabled: visible(launch) && !launch.disabled && launch.getAttribute("aria-disabled") !== "true",
@@ -3044,6 +3081,8 @@ function sanitizeProjectCommandSnapshot(value) {
taskBody: value.taskBodyText ? textDigest(value.taskBodyText, 200) : null,
reportPreviewText: undefined,
reportPreview: value.reportPreviewText ? textDigest(value.reportPreviewText, 200) : null,
reportErrorText: undefined,
reportError: value.reportErrorText ? textDigest(value.reportErrorText, 200) : null,
launchButtonTextHash: value.launchButtonText ? sha256Text(value.launchButtonText) : null,
launchButtonTextPreview: value.launchButtonText ? truncate(value.launchButtonText, 80) : null,
launchButtonText: undefined,