diff --git a/scripts/src/hwlab-node-web-sentinel-p5-observe.test.ts b/scripts/src/hwlab-node-web-sentinel-p5-observe.test.ts index 15abae79..8da2dddc 100644 --- a/scripts/src/hwlab-node-web-sentinel-p5-observe.test.ts +++ b/scripts/src/hwlab-node-web-sentinel-p5-observe.test.ts @@ -46,6 +46,51 @@ test("recorded sentinel run is available through the latest report index", () => } }); +test("latest report selects the newest stored run without a report SHA", () => { + const stateRoot = mkdtempSync(join(tmpdir(), "unidesk-sentinel-index-")); + const service = createWebProbeSentinelService({ + spec: hwlabRuntimeLaneSpecForNode("v03", "NC01"), + sentinelId: "nc01-web-probe-sentinel", + stateRootOverride: stateRoot, + schedulerEnabled: false, + }); + try { + const scenarioId = String(service.config.scenarios[0]?.id); + service.recordRun({ + runId: "sentinel-run-old-artifact", + scenarioId, + status: "succeeded", + reportJsonSha256: "sha256:old-artifact", + summary: { source: "test", valuesRedacted: true }, + views: { summary: { renderedText: "old indexed summary" } }, + findingCount: 0, + artifactCount: 0, + valuesRedacted: true, + }); + service.recordRun({ + runId: "sentinel-run-new-stored-finding", + scenarioId, + status: "blocked", + summary: { source: "test", valuesRedacted: true }, + views: { summary: { renderedText: "new stored summary" } }, + findings: [{ id: "quick-verify-observer-start-failed", severity: "error", summary: "observer start failed" }], + findingCount: 1, + artifactCount: 0, + valuesRedacted: true, + }); + + const latest = service.report("summary", null); + assert.equal(latest.ok, true); + assert.equal((latest.run as Record).id, "sentinel-run-new-stored-finding"); + assert.equal((latest.run as Record).reportJsonSha256, null); + assert.match(String(latest.renderedText), /run=sentinel-run-new-stored-finding/u); + assert.match(String(latest.renderedText), /页面观察未启动/u); + } finally { + service.close(); + rmSync(stateRoot, { recursive: true, force: true }); + } +}); + function forceStopStep(observer: Record): Record { return { phase: "observe-stop-after-terminal", diff --git a/scripts/src/hwlab-node-web-sentinel-service.ts b/scripts/src/hwlab-node-web-sentinel-service.ts index 335e0959..0cc58e6c 100644 --- a/scripts/src/hwlab-node-web-sentinel-service.ts +++ b/scripts/src/hwlab-node-web-sentinel-service.ts @@ -2727,7 +2727,7 @@ function reportRunView(config: WebProbeSentinelServiceConfig, db: Database, view return { ok: false, error: "unsupported-report-view", view, valuesRedacted: true }; } const row = runId === null - ? db.query("SELECT * FROM runs WHERE report_json_sha256 IS NOT NULL AND sentinel_id = ? AND node = ? AND lane = ? ORDER BY updated_at DESC LIMIT 1").get(config.sentinelId, config.node, config.lane) as Record | null + ? db.query("SELECT * FROM runs WHERE sentinel_id = ? AND node = ? AND lane = ? ORDER BY updated_at DESC LIMIT 1").get(config.sentinelId, config.node, config.lane) as Record | null : readRunRow(config, db, runId); if (row === null) return { ok: false, error: "report-run-missing", runId, view, valuesRedacted: true }; const selectedRunId = stringOrNull(row.id);