Merge pull request #1930 from pikasTech/fix/1927-mdtodo-pane-gap
Pipelines as Code CI / hwlab-web-probe-sentinel-nc01- Failed
Pipelines as Code CI / platform-infra-gitea-nc01- Success
Pipelines as Code CI / unidesk-host- Success

修复 WebProbe 对 MDTODO 短任务树留白的误报
This commit is contained in:
Lyon
2026-07-13 20:32:23 +08:00
committed by GitHub
2 changed files with 52 additions and 2 deletions
@@ -410,8 +410,12 @@ function projectManagementPaneGapRows(projectSamples) {
const maxGapPx = maxNumber(severeGaps.map((item) => item.bottomGapPx));
const maxGapRatio = maxNumber(severeGaps.map((item) => item.bottomGapRatio));
const multiPane = severeGaps.length >= 2;
const singleExtreme = maxGapPx >= 240 && maxGapRatio >= 0.45;
if (!multiPane && !singleExtreme) continue;
const singlePrimaryPaneExtreme = severeGaps.some((item) =>
item.name !== "task-tree"
&& Number(item.bottomGapPx ?? 0) >= 240
&& Number(item.bottomGapRatio ?? 0) >= 0.45
);
if (!multiPane && !singlePrimaryPaneExtreme) continue;
const selectedTaskRefHash = sample?.projectManagement?.selectedTaskRef?.hash ?? null;
const isMdtodo = sample?.projectManagement?.pageKind === "project-management-mdtodo";
const isInitialEmptyDetail = isMdtodo && !selectedTaskRefHash;
@@ -5,6 +5,7 @@ import {
MDTODO_TASK_TREE_PANE_CONTENT_SELECTOR,
nodeWebObserveRunnerSamplingSource,
} from "./hwlab-node-web-observe-runner-sampling-source";
import { nodeWebObserveAnalyzerProjectSource } from "./hwlab-node-web-observe-analyzer-project-source";
test("MDTODO task tree pane gap treats the pinned facts footer as content", async () => {
assert.match(
@@ -47,3 +48,48 @@ test("MDTODO task tree pane gap treats the pinned facts footer as content", asyn
]);
assert.equal(exitCode, 0, stderr);
});
test("MDTODO pane gap ignores a naturally short task tree but keeps primary pane regressions", () => {
const projectManagementPaneGapRows = new Function(
"maxNumber",
"projectManagementSampleRef",
`${nodeWebObserveAnalyzerProjectSource()}; return projectManagementPaneGapRows;`,
)(
(values: unknown[]) => Math.max(0, ...values.map((value) => Number(value ?? 0))),
(sample: Record<string, unknown>) => ({ seq: sample.seq ?? null }),
) as (samples: unknown[]) => { actionable: unknown[]; ignored: unknown[] };
const pane = (name: string, bottomGapPx: number, bottomGapRatio: number) => ({
name,
visible: true,
widthPx: 300,
heightPx: 600,
bottomGapPx,
bottomGapRatio,
contentNodeCount: 4,
});
const sample = (paneGaps: unknown[]) => ({
seq: 1,
projectManagement: {
pageKind: "project-management-mdtodo",
selectedTaskRef: { hash: "sha256:opaque" },
paneGaps,
},
});
assert.deepEqual(
projectManagementPaneGapRows([sample([pane("task-tree", 391, 0.618)])]),
{ actionable: [], ignored: [], valuesRedacted: true },
);
assert.equal(
projectManagementPaneGapRows([sample([pane("task-detail", 391, 0.618)])]).actionable.length,
1,
);
assert.equal(
projectManagementPaneGapRows([sample([
pane("task-tree", 240, 0.4),
pane("task-detail", 180, 0.3),
])]).actionable.length,
1,
);
});