import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import os from 'node:os'; import { runOrchestratorAdapter, runWatchdogChain, } from '../src/index.mjs'; const packageRoot = path.resolve(import.meta.dirname, '..'); function createFixtureRoot() { return fs.mkdtempSync(path.join(os.tmpdir(), 'reporting-governance-plugin-')); } function mkdirs(root, names) { for (const name of names) { fs.mkdirSync(path.join(root, name), { recursive: true }); } } function writeState(root) { const statePath = path.join(root, 'watchdog-state.json'); fs.writeFileSync(statePath, `${JSON.stringify({ version: 1, watchdogs: [ { id: 'reporting-governance-plugin-watchdog', task: 'reporting-governance plugin spec development', status: 'active', ownerSessionKey: 'agent:coder:main', reportChannel: 'telegram', reportTarget: '864811879', intervalMinutes: 10, lastMilestoneAt: '2026-05-07T08:00:00.000Z', lastAlertAt: null, }, ], }, null, 2)}\n`, 'utf8'); return statePath; } function readSingleJson(dirPath) { const files = fs.readdirSync(dirPath).filter((name) => name.endsWith('.json')).sort(); assert.equal(files.length, 1, `expected exactly one json file in ${dirPath}`); return { fileName: files[0], payload: JSON.parse(fs.readFileSync(path.join(dirPath, files[0]), 'utf8')), }; } test('package entrypoint can run watchdog chain through orchestrator adapter', () => { const root = createFixtureRoot(); try { mkdirs(root, ['evidence', 'events', 'queue', 'spool', 'receipts']); const statePath = writeState(root); const result = runWatchdogChain({ state: statePath, evidenceDir: path.join(root, 'evidence'), eventDir: path.join(root, 'events'), queueDir: path.join(root, 'queue'), spoolDir: path.join(root, 'spool'), receiptDir: path.join(root, 'receipts'), writeState: true, senderCommand: `node -e "process.stdout.write(JSON.stringify({state:'sent'}))"`, now: '2026-05-07T08:20:00.000Z', }); assert.equal(result.ok, true); assert.deepEqual(result.executionOrder, ['runner', 'queue', 'dispatcher', 'bridge', 'sender', 'ack_or_blocked_or_pending']); assert.equal(result.result.watchdog.notificationCount, 1); assert.equal(result.result.dispatcher.dispatchedCount, 1); assert.equal(result.result.supervisor.ackedCount, 1); const queueItem = readSingleJson(path.join(root, 'queue')).payload; assert.equal(queueItem.status, 'acked'); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test('dry-run path produces verifiable pending receipt via package adapter', () => { const root = createFixtureRoot(); try { mkdirs(root, ['evidence', 'events', 'queue', 'spool', 'receipts']); const statePath = writeState(root); const result = runOrchestratorAdapter({ state: statePath, evidenceDir: path.join(root, 'evidence'), eventDir: path.join(root, 'events'), queueDir: path.join(root, 'queue'), spoolDir: path.join(root, 'spool'), receiptDir: path.join(root, 'receipts'), writeState: true, dryRun: true, now: '2026-05-07T08:20:00.000Z', }); assert.equal(result.ok, true); assert.equal(result.orchestration.dryRun, true); assert.equal(result.result.watchdog.notificationCount, 1); assert.equal(result.result.dispatcher.dispatchedCount, 1); assert.equal(result.result.supervisor.pendingCount, 1); const queueItem = readSingleJson(path.join(root, 'queue')).payload; assert.equal(queueItem.status, 'dispatched'); const receipt = readSingleJson(path.join(root, 'receipts')).payload; assert.equal(receipt.state, 'pending_external_send'); assert.equal(receipt.supervisor_mode, 'dry_run'); assert.ok(receipt.suggested_command.includes('openclaw message send')); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test('orchestrator adapter can bootstrap from profile artifact loader path', () => { const root = createFixtureRoot(); try { mkdirs(root, ['evidence', 'events', 'queue', 'spool', 'receipts']); const statePath = writeState(root); const result = runOrchestratorAdapter({ profileId: 'strict-manager-mode', repoRootOverride: path.resolve(packageRoot, '..', '..'), state: statePath, evidenceDir: path.join(root, 'evidence'), eventDir: path.join(root, 'events'), queueDir: path.join(root, 'queue'), spoolDir: path.join(root, 'spool'), receiptDir: path.join(root, 'receipts'), writeState: true, dryRun: true, now: '2026-05-07T08:20:00.000Z', }); assert.equal(result.ok, true); assert.equal(result.result.watchdog.notificationCount, 1); assert.equal(result.result.dispatcher.dispatchedCount, 1); assert.equal(result.result.supervisor.pendingCount, 1); const receipt = readSingleJson(path.join(root, 'receipts')).payload; assert.equal(receipt.state, 'pending_external_send'); } finally { fs.rmSync(root, { recursive: true, force: true }); } });