mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-03 13:22:14 +00:00
* feat(tasks): move task ledger to sqlite * feat(tasks): add task run audit command * style(tasks): normalize audit command formatting * fix(tasks): address audit summary and sqlite perms * fix(tasks): avoid duplicate lost audit findings
101 lines
2.9 KiB
TypeScript
101 lines
2.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { listTaskAuditFindings, summarizeTaskAuditFindings } from "./task-registry.audit.js";
|
|
import type { TaskRecord } from "./task-registry.types.js";
|
|
|
|
function createTask(partial: Partial<TaskRecord>): TaskRecord {
|
|
return {
|
|
taskId: partial.taskId ?? "task-1",
|
|
runtime: partial.runtime ?? "acp",
|
|
requesterSessionKey: partial.requesterSessionKey ?? "agent:main:main",
|
|
task: partial.task ?? "Background task",
|
|
status: partial.status ?? "queued",
|
|
deliveryStatus: partial.deliveryStatus ?? "pending",
|
|
notifyPolicy: partial.notifyPolicy ?? "done_only",
|
|
createdAt: partial.createdAt ?? Date.parse("2026-03-30T00:00:00.000Z"),
|
|
...partial,
|
|
};
|
|
}
|
|
|
|
describe("task-registry audit", () => {
|
|
it("flags stale running, lost, and missing cleanup tasks", () => {
|
|
const now = Date.parse("2026-03-30T01:00:00.000Z");
|
|
const findings = listTaskAuditFindings({
|
|
now,
|
|
tasks: [
|
|
createTask({
|
|
taskId: "stale-running",
|
|
status: "running",
|
|
startedAt: now - 40 * 60_000,
|
|
lastEventAt: now - 40 * 60_000,
|
|
}),
|
|
createTask({
|
|
taskId: "lost-task",
|
|
status: "lost",
|
|
error: "backing session missing",
|
|
endedAt: now - 5 * 60_000,
|
|
}),
|
|
createTask({
|
|
taskId: "missing-cleanup",
|
|
status: "failed",
|
|
endedAt: now - 60_000,
|
|
cleanupAfter: undefined,
|
|
}),
|
|
],
|
|
});
|
|
|
|
expect(findings.map((finding) => [finding.code, finding.task.taskId])).toEqual([
|
|
["lost", "lost-task"],
|
|
["stale_running", "stale-running"],
|
|
["missing_cleanup", "missing-cleanup"],
|
|
]);
|
|
});
|
|
|
|
it("summarizes findings by severity and code", () => {
|
|
const summary = summarizeTaskAuditFindings([
|
|
{
|
|
severity: "error",
|
|
code: "stale_running",
|
|
task: createTask({ taskId: "a", status: "running" }),
|
|
detail: "running task appears stuck",
|
|
},
|
|
{
|
|
severity: "warn",
|
|
code: "delivery_failed",
|
|
task: createTask({ taskId: "b", status: "failed" }),
|
|
detail: "terminal update delivery failed",
|
|
},
|
|
]);
|
|
|
|
expect(summary).toEqual({
|
|
total: 2,
|
|
warnings: 1,
|
|
errors: 1,
|
|
byCode: {
|
|
stale_queued: 0,
|
|
stale_running: 1,
|
|
lost: 0,
|
|
delivery_failed: 1,
|
|
missing_cleanup: 0,
|
|
inconsistent_timestamps: 0,
|
|
},
|
|
});
|
|
});
|
|
|
|
it("does not double-report lost tasks as missing cleanup", () => {
|
|
const now = Date.parse("2026-03-30T01:00:00.000Z");
|
|
const findings = listTaskAuditFindings({
|
|
now,
|
|
tasks: [
|
|
createTask({
|
|
taskId: "lost-projected",
|
|
status: "lost",
|
|
endedAt: now - 60_000,
|
|
cleanupAfter: undefined,
|
|
}),
|
|
],
|
|
});
|
|
|
|
expect(findings.map((finding) => finding.code)).toEqual(["lost"]);
|
|
});
|
|
});
|