diff --git a/scripts/src/hwlab-node-web-sentinel-service.ts b/scripts/src/hwlab-node-web-sentinel-service.ts index 386a7e92..ac76026c 100644 --- a/scripts/src/hwlab-node-web-sentinel-service.ts +++ b/scripts/src/hwlab-node-web-sentinel-service.ts @@ -614,8 +614,9 @@ function plannedRunBacklog(config: WebProbeSentinelServiceConfig, db: Database): readonly staleAfterSeconds: number; readonly stale: boolean; } { - const count = countWhere(db, "status = 'planned'"); - const oldest = db.query("SELECT id, scenario_id, created_at FROM runs WHERE status = 'planned' ORDER BY created_at ASC LIMIT 1") + const activeWhere = "status = 'planned' AND NOT EXISTS (SELECT 1 FROM runs newer WHERE newer.scenario_id = runs.scenario_id AND newer.status <> 'planned' AND newer.created_at > runs.created_at)"; + const count = countWhere(db, activeWhere); + const oldest = db.query(`SELECT id, scenario_id, created_at FROM runs WHERE ${activeWhere} ORDER BY created_at ASC LIMIT 1`) .get() as Record | null; const oldestCreatedAt = stringOrNull(oldest?.created_at); const oldestAgeSeconds = oldestCreatedAt === null ? null : ageSeconds(oldestCreatedAt); @@ -1316,6 +1317,8 @@ function recordRunResult(config: WebProbeSentinelServiceConfig, db: Database, in artifact_count = excluded.artifact_count, updated_at = excluded.updated_at `).run(runId, scenarioId, config.node, config.lane, status, observerId, stateDir, reportJsonSha256, findingCount, artifactCount, thisMaintenanceFlag(input), createdAt, now, JSON.stringify({ source: "recorded-analyze-summary", valuesRedacted: true })); + const supersededPlannedRuns = db.query("UPDATE runs SET status = 'superseded', updated_at = ? WHERE status = 'planned' AND scenario_id = ? AND created_at < ?") + .run(now, scenarioId, createdAt); db.query("DELETE FROM findings WHERE run_id = ?").run(runId); for (const item of findings) { const findingId = stringOrNull(item.id) ?? stringOrNull(item.kind) ?? stringOrNull(item.code) ?? "finding"; @@ -1339,7 +1342,7 @@ function recordRunResult(config: WebProbeSentinelServiceConfig, db: Database, in findingCount, valuesRedacted: true, }); - return { ok: true, runId, scenarioId, status, reportJsonSha256, findingCount, artifactCount, valuesRedacted: true }; + return { ok: true, runId, scenarioId, status, reportJsonSha256, findingCount, artifactCount, supersededPlannedRuns: Number(supersededPlannedRuns.changes ?? 0), valuesRedacted: true }; } function reportRunView(config: WebProbeSentinelServiceConfig, db: Database, view: string, runId: string | null): Record {