import test from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, rmSync } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { Store } from '../../bus/src/store.mjs'; import { Broker } from '../../bus/src/broker.mjs'; import { createProcessing } from '../../processing-control/src/coordinator.mjs'; import { main } from '../src/cli.mjs'; import { io, BUSINESSES } from './helpers.mjs'; function setup(t) { const dataRoot = mkdtempSync(join(tmpdir(), 'processing-cli-')), calls = []; const processing = createProcessing({ dataRoot }); const store = new Store(dataRoot); const b = new Broker({ store, businesses: BUSINESSES, processing }); const human = b.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true }); const deps = { system: { dataRoot }, transport: business => async (verb, args = {}) => { assert.equal(business, 'demo'); calls.push(verb); return b.request(human, { verb, args }); } }; t.after(async () => { await processing.close(); store.close(); rmSync(dataRoot, { recursive: true, force: true }); }); return { dataRoot, deps, calls }; } test('human halt/status/resume uses management transport without loading any channel', async t => { const f = setup(t), x = io(); await main(['halt', '--business', 'demo'], x, f.deps); assert.match(x.out.text, /processing halted/); assert.ok(x.out.text.includes(f.dataRoot), 'the affected instance root is named'); const status = io(); await main(['processing', 'status', '--business', 'demo', '--json'], status, f.deps); assert.equal(JSON.parse(status.out.text).halted, true); const resumed = io(); await main(['resume', '--business', 'demo'], resumed, f.deps); assert.match(resumed.out.text, /processing resumed/); assert.deepEqual(f.calls, ['processing.halt', 'processing.status', 'processing.status', 'processing.resume']); }); for (const verb of ['halt', 'resume']) test(`${verb} refuses inside an agent before transport`, async t => { const f = setup(t), x = io({ MOSAIC_RUN_ID: 'managed-run' }); await assert.rejects(main([verb, '--business', 'demo'], x, f.deps), e => e.exitCode === 3); assert.deepEqual(f.calls, []); }); test('unknown and partially stopped outcomes are never reported as a successful halt', async t => { const f = setup(t); const unknown = io(); await assert.rejects(main(['halt', '--business', 'demo'], unknown, { ...f.deps, transport: () => async () => { throw Object.assign(new Error('outcome-unknown'), { code: 'outcome-unknown' }); }, }), e => e.exitCode === 1 && /status/.test(e.message)); assert.doesNotMatch(unknown.out.text, /processing halted/); const partial = io(); await assert.rejects(main(['halt', '--business', 'demo'], partial, { ...f.deps, transport: () => async () => ({ version: 1, generation: '11111111-1111-4111-8111-111111111111', operation: '11111111-1111-4111-8111-111111111111', business: 'demo', human: 'jason', at: '2026-10-20T00:00:00.000Z', recovered: false, halted: true, quiescent: false, remaining: 1, stopped: 0 }), }), e => e.exitCode === 1 && /1.*unconfirmed/.test(e.message)); assert.doesNotMatch(partial.out.text, /all.*stopped/); });