From fe268efde13b2c54d4d91919a7a39c6c72a5064e Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 30 Oct 2026 13:05:05 -0700 Subject: [PATCH] test(seats): a credential streamed one character per delta never reaches the record Two cases beside the split tests, test-only (the store is unchanged): - the whole value streamed one character per delta: every delta is held while it is still a prefix of the value, the completed value is replaced by the marker, and the joined message text is exactly the marker, written before run.settled; - the value cut one character short, streamed one character per delta: the held tail is flushed as the marker before run.settled, and the joined text is exactly the marker. Mutation check: with the hold-back disabled in store.js, both new tests fail. The seats suite passes 247/247. TASK-604 Co-Authored-By: Claude Haiku 5.5 Co-authored-by: wren Agent-Model: claude/claude-haiku-5-5/max --- .../seats/test/record-redact-stream.test.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/seats/test/record-redact-stream.test.js b/packages/seats/test/record-redact-stream.test.js index 406a862f29..f783f228a0 100644 --- a/packages/seats/test/record-redact-stream.test.js +++ b/packages/seats/test/record-redact-stream.test.js @@ -115,6 +115,34 @@ test('two streams interleaved, each splitting the value, are scrubbed apart', () } })); +// One character per delta: each delta is a prefix of the value, so it is held +// until the whole value has arrived (the marker) or the stream ends (the flush). +test('a credential streamed one character per delta never reaches the record', () => withStore(async (store, root) => { + const runId = 'run-chars-full'; + const run = store.startRun({ runId }); + run.redact([CANARY]); + for (const ch of CANARY) run.emit('agent.message_chunk', { text: ch }); + run.emit('run.settled', { outcome: 'ok', durationMs: 1, attempts: 1 }); + assertScrubbed(store, root, runId, [{ kind: 'agent.message_chunk', expected: '[redacted]' }]); + const events = store.readRun(runId); + const settledAt = events.findIndex((e) => e.kind === 'run.settled'); + const marker = events.findIndex((e) => e.kind === 'agent.message_chunk' && e.data.text === '[redacted]'); + assert.ok(marker >= 0 && marker < settledAt, 'the marker landed before run.settled'); +})); + +test('a credential cut one character short, streamed one character per delta, flushes as the marker before settle', () => withStore(async (store, root) => { + const runId = 'run-chars-short-of-one'; + const run = store.startRun({ runId }); + run.redact([CANARY]); + for (const ch of CANARY.slice(0, -1)) run.emit('agent.message_chunk', { text: ch }); + run.emit('run.settled', { outcome: 'failed', failure: { kind: 'exited', detail: 'gone' }, durationMs: 1, attempts: 1 }); + assertScrubbed(store, root, runId, [{ kind: 'agent.message_chunk', expected: '[redacted]' }]); + const events = store.readRun(runId); + const settledAt = events.findIndex((e) => e.kind === 'run.settled'); + const marker = events.findIndex((e) => e.kind === 'agent.message_chunk' && e.data.text === '[redacted]'); + assert.ok(marker >= 0 && marker < settledAt, 'the held tail flushed before run.settled'); +})); + test('a stream that ends mid-value writes the marker before settle, never the prefix', () => withStore(async (store, root) => { const run = store.startRun({ runId: 'run-held-settle' }); run.redact([CANARY]);