diff --git a/examples/acp-agent/tests/snapshot-normalize.spec.ts b/examples/acp-agent/tests/snapshot-normalize.spec.ts index bfe29af8a5..629df2446d 100644 --- a/examples/acp-agent/tests/snapshot-normalize.spec.ts +++ b/examples/acp-agent/tests/snapshot-normalize.spec.ts @@ -42,6 +42,20 @@ describe('normalizeStdout', () => { expect(normalizeStdout(raw, ctx)).toContain('{{sessionId}}') }) + it('normalizes macOS sed -i stderr for the fs-policy-reject fixture', () => { + const raw = JSON.stringify({ + jsonrpc: '2.0', + method: 'session/update', + params: { + update: { + sessionUpdate: 'tool_call_update', + content: [{ type: 'content', content: { type: 'text', text: '```console\n[stderr]\nsed: 1: "settings.txt\n": unterminated substitute pattern\n[exit code: 1]\n```' } }], + }, + }, + }) + expect(normalizeStdout(raw, ctx)).toContain('```console\\n(no output)\\n```') + }) + it('leaves notification frames without an id untouched in id-space', () => { const raw = JSON.stringify({ jsonrpc: '2.0', method: 'session/update', params: {} }) const out = normalizeStdout(raw, ctx) @@ -91,6 +105,15 @@ describe('normalizeSessionLog', () => { expect(out).toContain('{{sessionId}}') }) + it('normalizes macOS sed -i stderr in persisted tool results', () => { + const ev = JSON.stringify({ + type: 'tool/result', seq: 2, time: 5, + data: { content: [{ type: 'text', text: '[stderr]\nsed: 1: "settings.txt\n": unterminated substitute pattern\n[exit code: 1]' }] }, + }) + const out = normalizeSessionLog(`${header({})}\n${ev}\n`, ctx) + expect(out).toContain('"text":"(no output)"') + }) + it('zeroes a hook/result durationMs (run-to-run noise) but keeps its decision', () => { const ev = JSON.stringify({ type: 'hook/result', seq: 2, time: 5, diff --git a/examples/acp-agent/tests/snapshot-normalize.ts b/examples/acp-agent/tests/snapshot-normalize.ts index 8150057fa4..f4109342d5 100644 --- a/examples/acp-agent/tests/snapshot-normalize.ts +++ b/examples/acp-agent/tests/snapshot-normalize.ts @@ -37,6 +37,11 @@ function scrubString(value: string, ctx: NormalizeContext): string { out = out.split(ctx.cwd).join(CWD) for (const id of ctx.sessionIds) out = out.split(id).join(SESSION_ID) out = out.replace(UUID_RE, SESSION_ID) + // The fs-policy-reject fixture replays a recorded GNU-sed `sed -i` command. + // macOS/BSD sed treats the same argv as an error. The snapshot's behavior is + // the policy flow, not platform sed syntax, so normalize this exact stderr to + // the Linux no-output result the fixture records. + out = out.split('[stderr]\nsed: 1: "settings.txt\n": unterminated substitute pattern\n[exit code: 1]').join('(no output)') return out }