import { describe, it, expect } from 'vitest'; import { reduceDelegateStreams } from './useJobStream'; describe('reduceDelegateStreams – originJobId contract', () => { it('lifecycle の originJobId を run に紐づける', () => { let s = reduceDelegateStreams( {}, { type: 'delegate_lifecycle', delegateRunId: 'r1', originJobId: 'sub1', status: 'running', depth: 1, description: 'x', }, ); s = reduceDelegateStreams(s, { type: 'delegate_text_delta', delegateRunId: 'r1', text: 'hello', }); const run = s['r1']; expect(run).toBeDefined(); expect(run.originJobId).toBe('sub1'); expect(run.text).toContain('hello'); }); it('originJobId が無い lifecycle は originJobId が null のまま', () => { const s = reduceDelegateStreams( {}, { type: 'delegate_lifecycle', delegateRunId: 'r2', status: 'running', depth: 1, description: 'parent', }, ); // originJobId は undefined か null — どちらも null-ish として扱われる expect(s['r2'].originJobId == null).toBe(true); }); it('originJobId は text_delta / tool イベントを経ても引き継がれる', () => { let s = reduceDelegateStreams( {}, { type: 'delegate_lifecycle', delegateRunId: 'r3', originJobId: 'sub2', status: 'running', depth: 1, description: 'y', }, ); s = reduceDelegateStreams(s, { type: 'delegate_tool', delegateRunId: 'r3', toolName: 'WebFetch', }); s = reduceDelegateStreams(s, { type: 'delegate_text_delta', delegateRunId: 'r3', text: 'result', }); expect(s['r3'].originJobId).toBe('sub2'); }); });