From 91829cbf0d87bbf9b8a6618985f7af5d053b31cf Mon Sep 17 00:00:00 2001 From: sivaratrisrinivas <193684336+sivaratrisrinivas@users.noreply.github.com> Date: Tue, 27 Oct 2026 00:20:53 +0530 Subject: [PATCH 1/2] fix(build-logs): strip bidi overrides and C1 controls from build log output --- src/build-logs.ts | 2 +- test/build-logs.test.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/build-logs.ts b/src/build-logs.ts index 58c5227..bfbed6a 100644 --- a/src/build-logs.ts +++ b/src/build-logs.ts @@ -100,7 +100,7 @@ export async function readBuildLogs(api: Api, projectId: string, source: BuildSo return { ...first, nextCursor: undefined, state: pending ? 'pending' : first.state, steps, output } } -const safeText = (text: string) => stripVTControlCharacters(text).replace(/[\x00-\x08\x0b-\x1f\x7f]/g, '') +const safeText = (text: string) => stripVTControlCharacters(text).replace(/[\x00-\x08\x0b-\x1f\x7f-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069]/g, '') export class BuildLogPrinter { private seen = new Map() diff --git a/test/build-logs.test.ts b/test/build-logs.test.ts index 8cd15d7..35c52e1 100644 --- a/test/build-logs.test.ts +++ b/test/build-logs.test.ts @@ -47,6 +47,13 @@ describe('build logs', () => { expect(write.mock.calls.map(([text]) => text)).toEqual(['RUN test\n', 'same\n', 'same\n', 'late\n', 'same\n']) }) + it('strips bidi overrides, invisible marks and C1 controls while keeping tabs and newlines', () => { + const printer = new BuildLogPrinter() + const write = vi.fn() + printer.print({ ...base, state: 'ready', output: [{ step: 'step1', name: 'RUN test', entries: [entry('a\u202eb\u0085c\u2066d\u2069e\u200ef\u200fg\u202ah\u009fi\n'), entry('col1\tcol2\n'), entry('plain text ok\n')] }] }, write) + expect(write.mock.calls.map(([text]) => text)).toEqual(['RUN test\n', 'abcdefghi\n', 'col1\tcol2\n', 'plain text ok\n']) + }) + it('resumes after transient errors and reads delayed terminal output', async () => { let reads = 0 const api = apiWith((path) => { From 47a956e1ae82852699815cff453d17cd0385affc Mon Sep 17 00:00:00 2001 From: sivaratrisrinivas <193684336+sivaratrisrinivas@users.noreply.github.com> Date: Tue, 27 Oct 2026 00:27:47 +0530 Subject: [PATCH 2/2] test(build-logs): cover U+0080 at the C1 lower bound --- test/build-logs.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/build-logs.test.ts b/test/build-logs.test.ts index 35c52e1..008924c 100644 --- a/test/build-logs.test.ts +++ b/test/build-logs.test.ts @@ -50,7 +50,7 @@ describe('build logs', () => { it('strips bidi overrides, invisible marks and C1 controls while keeping tabs and newlines', () => { const printer = new BuildLogPrinter() const write = vi.fn() - printer.print({ ...base, state: 'ready', output: [{ step: 'step1', name: 'RUN test', entries: [entry('a\u202eb\u0085c\u2066d\u2069e\u200ef\u200fg\u202ah\u009fi\n'), entry('col1\tcol2\n'), entry('plain text ok\n')] }] }, write) + printer.print({ ...base, state: 'ready', output: [{ step: 'step1', name: 'RUN test', entries: [entry('a\u202eb\u0080\u0085c\u2066d\u2069e\u200ef\u200fg\u202ah\u009fi\n'), entry('col1\tcol2\n'), entry('plain text ok\n')] }] }, write) expect(write.mock.calls.map(([text]) => text)).toEqual(['RUN test\n', 'abcdefghi\n', 'col1\tcol2\n', 'plain text ok\n']) })