1import { describe, it } from 'node:test';
2import assert from 'node:assert/strict';
3
4import {
5 completionAckForAcceptResult,
6 completionTypeForAcceptResult,
7} from '../skill/scripts/live-completion.mjs';
8
9describe('live completion type classification', () => {
10 it('treats generated-file fallback accept as normal agent handoff, not error', () => {
11 assert.equal(
12 completionTypeForAcceptResult('accept', { handled: false, mode: 'fallback' }),
13 'agent_done',
14 'event=live_poll.fallback_completion actor=agent operation=accept_generated_file risk=fallback_handoff_recorded_as_agent_error expected=agent_done actual=error',
15 );
16 });
17
18 it('treats unhandled non-error accept as normal manual agent handoff', () => {
19 assert.equal(
20 completionTypeForAcceptResult('accept', { handled: false, error: 'Session markers not found' }),
21 'agent_done',
22 'event=live_poll.manual_accept_completion actor=agent operation=accept_manual_cleanup risk=manual_handoff_recorded_as_agent_error expected=agent_done actual=error',
23 );
24 });
25
26 it('keeps carbonize-required accepts recoverable until cleanup is completed', () => {
27 assert.equal(
28 completionTypeForAcceptResult('accept', { handled: true, carbonize: true }),
29 'agent_done',
30 'event=live_poll.carbonize_completion actor=agent operation=accept_with_carbonize risk=carbonize_session_marked_completed_before_cleanup expected=agent_done actual=complete',
31 );
32 });
33
34 it('marks carbonize acknowledgements as non-final and requiring explicit completion', () => {
35 assert.deepEqual(
36 completionAckForAcceptResult('carbonize-1', 'agent_done', { handled: true, carbonize: true }),
37 {
38 ok: true,
39 type: 'agent_done',
40 final: false,
41 requiresComplete: true,
42 nextCommand: 'live-complete.mjs --id carbonize-1',
43 message: 'Carbonize cleanup must be verified, then the session must be completed explicitly before polling again.',
44 },
45 'event=live_poll.carbonize_ack actor=agent operation=accept_with_carbonize risk=active_session_never_completed expected=explicit_complete_required actual=missing_requires_complete',
46 );
47 });
48
49 it('keeps normal handled accepts terminal', () => {
50 assert.deepEqual(
51 completionAckForAcceptResult('done-1', 'complete', { handled: true, carbonize: false }),
52 { ok: true, type: 'complete' },
53 );
54 });
55
56 it('classifies handled accept/discard and real failures explicitly', () => {
57 assert.equal(completionTypeForAcceptResult('accept', { handled: true }), 'complete');
58 assert.equal(completionTypeForAcceptResult('discard', { handled: true }), 'discarded');
59 assert.equal(completionTypeForAcceptResult('accept', { handled: false, mode: 'error', error: 'boom' }), 'error');
60 });
61});