From 62acb55a0798495207ec893c135f08cf629bc7aa Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 13 Jul 2026 14:54:05 +0200 Subject: [PATCH] =?UTF-8?q?fix(web-probe):=20=E6=8E=A5=E5=8F=97=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E7=AB=AF=E5=B7=B2=E9=80=89=20MDTODO=20=E8=AF=A6?= =?UTF-8?q?=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-node-web-observe-runner-control-source.ts | 8 ++-- ...web-observe-runner-sampling-source.test.ts | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/scripts/src/hwlab-node-web-observe-runner-control-source.ts b/scripts/src/hwlab-node-web-observe-runner-control-source.ts index 400a90b5..d7a72f07 100644 --- a/scripts/src/hwlab-node-web-observe-runner-control-source.ts +++ b/scripts/src/hwlab-node-web-observe-runner-control-source.ts @@ -1120,12 +1120,14 @@ async function waitForProjectManagementCommandReady(options = {}) { while (Date.now() <= deadline) { last = await projectManagementCommandSnapshot(); const path = String(last?.path || safeUrlPath(currentPageUrl()) || ""); + const needsTask = /\/tasks\//u.test(path); + const selectedTaskReady = Boolean(last?.selectedTaskId || last?.selectedTaskRef?.hash || last?.taskBodyVisible === true || last?.launchButtonVisible === true); + const taskCollectionReady = Number(last?.taskCount || 0) > 0; const baseReady = last?.pageKind === "project-management-mdtodo" && Number(last?.sourceCount || 0) > 0 && Number(last?.fileCount || 0) > 0 - && Number(last?.taskCount || 0) > 0; - const needsTask = /\/tasks\//u.test(path); - const taskReady = !needsTask || Boolean(last?.selectedTaskId || last?.selectedTaskRef?.hash || last?.taskBodyVisible === true || last?.launchButtonVisible === true); + && (needsTask ? selectedTaskReady : taskCollectionReady); + const taskReady = !needsTask || selectedTaskReady; const needsReport = /\/reports\//u.test(path); 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 }; diff --git a/scripts/src/hwlab-node-web-observe-runner-sampling-source.test.ts b/scripts/src/hwlab-node-web-observe-runner-sampling-source.test.ts index c72f3596..2462b356 100644 --- a/scripts/src/hwlab-node-web-observe-runner-sampling-source.test.ts +++ b/scripts/src/hwlab-node-web-observe-runner-sampling-source.test.ts @@ -6,6 +6,7 @@ import { nodeWebObserveRunnerSamplingSource, } from "./hwlab-node-web-observe-runner-sampling-source"; import { nodeWebObserveAnalyzerProjectSource } from "./hwlab-node-web-observe-analyzer-project-source"; +import { nodeWebObserveRunnerControlSource } from "./hwlab-node-web-observe-runner-control-source"; test("MDTODO task tree pane gap treats the pinned facts footer as content", async () => { assert.match( @@ -93,3 +94,40 @@ test("MDTODO pane gap ignores a naturally short task tree but keeps primary pane 1, ); }); + +test("MDTODO command readiness accepts a selected mobile task when the hidden tree has no visible rows", async () => { + const source = nodeWebObserveRunnerControlSource(); + const makeReady = (snapshot: Record) => new Function( + "projectManagementCommandSnapshot", + "safeUrlPath", + "currentPageUrl", + "page", + `${source}; return waitForProjectManagementCommandReady;`, + )( + async () => snapshot, + () => String(snapshot.path ?? ""), + () => `https://hwlab.pikapython.com${String(snapshot.path ?? "")}`, + { waitForTimeout: async () => undefined }, + ) as (options: { timeoutMs: number }) => Promise<{ ok: boolean; reason: string }>; + + const selectedMobileTask = { + path: "/projects/mdtodo/sources/source/files/file/tasks/R1", + pageKind: "project-management-mdtodo", + sourceCount: 3, + fileCount: 18, + taskCount: 0, + selectedTaskRef: { hash: "sha256:opaque" }, + taskBodyVisible: true, + launchButtonVisible: true, + }; + assert.equal((await makeReady(selectedMobileTask)({ timeoutMs: 1 })).ok, true); + + const unselectedRoot = { + path: "/projects/mdtodo", + pageKind: "project-management-mdtodo", + sourceCount: 3, + fileCount: 18, + taskCount: 0, + }; + assert.equal((await makeReady(unselectedRoot)({ timeoutMs: 1 })).ok, false); +});