import assert from "node:assert/strict"; import { execFile } from "node:child_process"; import { access, mkdtemp, rm } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import test from "node:test"; import { promisify } from "node:util"; const execFileAsync = promisify(execFile); const bunCommand = process.env.HWLAB_TEST_BUN_COMMAND || process.env.HWLAB_BUN_COMMAND || (process.versions.bun ? process.execPath : "bun"); test("agent worker health and dry-run preserve session evidence and cleanup behavior", async () => { const stateDir = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-worker-")); try { const health = await runWorkerJson(["health", "--state-dir", stateDir]); assert.equal(health.serviceId, "hwlab-agent-worker"); assert.equal(health.ok, true); assert.equal(health.status, "ok"); assert.equal(health.skills.status, "degraded"); await runManagerJson([ "create", "--agent-session-id", "ags_worker", "--project-id", "prj_worker", "--skill-commit-id", "commit-worker", "--skill-version", "2.0.0", "--state-dir", stateDir ]); const dryRun = await runWorkerJson([ "dry-run", "--agent-session-id", "ags_worker", "--skill-commit-id", "commit-worker", "--skill-version", "2.0.0", "--state-dir", stateDir ]); assert.equal(dryRun.serviceId, "hwlab-agent-worker"); assert.equal(dryRun.dryRun, true); assert.equal(dryRun.task.status, "completed"); assert.equal(dryRun.health.status, "ok"); assert.equal(dryRun.evidenceRecord.evidenceId, "evi_ags_worker"); assert.equal(dryRun.cleanup.completed, true); assert.equal(dryRun.workspace.cleaned, true); assert.equal(dryRun.workspace.existsAfterCleanup, false); await assert.rejects(access(dryRun.workspace.path)); const evidence = await runManagerJson(["evidence", "--agent-session-id", "ags_worker", "--state-dir", stateDir]); assert.equal(evidence.evidenceRecords.length, 1); assert.equal(evidence.evidenceRecords[0].serviceId, "hwlab-agent-worker"); } finally { await rm(stateDir, { recursive: true, force: true }); } }); test("agent worker dry-run requires agent session id", async () => { const result = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-worker/main.ts", "dry-run"], { cwd: process.cwd(), maxBuffer: 1024 * 1024 }).then( () => ({ code: 0, stderr: "" }), (error) => ({ code: error.code, stderr: error.stderr }) ); assert.equal(result.code, 1); const payload = JSON.parse(result.stderr); assert.equal(payload.serviceId, "hwlab-agent-worker"); assert.match(payload.error.message, /--agent-session-id is required/u); }); async function runManagerJson(args) { const { stdout } = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-mgr/main.ts", ...args], { cwd: process.cwd(), maxBuffer: 1024 * 1024 }); return JSON.parse(stdout); } async function runWorkerJson(args) { const { stdout } = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-worker/main.ts", ...args], { cwd: process.cwd(), maxBuffer: 1024 * 1024 }); return JSON.parse(stdout); }