From 21dee21a6d9d398bb332ddf0f85fbb4d5de7cd1b Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Tue, 28 Jul 2026 10:22:33 -0700 Subject: [PATCH] test(cli): lock CLI-compatible timeout parse contract (#11206) parsePositiveSafeIntegerNumericText mirrors the CLI's own Number() coercion on purpose: text like `600000.000000000000001` is the budget the CLI will actually wait on, so rejecting it here would leave the relay and SSH kill timers shorter than the CLI's and cut the request short. Document that and pin it with regression cases. --- src/shared/timer-delay.test.ts | 27 ++++++++++++++++++++------- src/shared/timer-delay.ts | 6 ++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/shared/timer-delay.test.ts b/src/shared/timer-delay.test.ts index 23171a60e99..7f94b33a655 100644 --- a/src/shared/timer-delay.test.ts +++ b/src/shared/timer-delay.test.ts @@ -33,17 +33,30 @@ describe('timer delay policy', () => { expect(parsePositiveSafeIntegerText(raw)).toBe(expected) }) - it.each(['', '0', '-1', '1.5', '.1', '1e-1', '9007199254740991.1', '9007199254740992'])( - 'rejects inexact or unsafe integer text %s', - (raw) => { - expect(parsePositiveSafeIntegerText(raw)).toBeNull() - } - ) + it.each([ + '', + '0', + '-1', + '1.5', + '.1', + '1e-1', + '1.0000000000000000001', + '+1.0000000000000000001', + '9007199254740991.1', + '9007199254740992' + ])('rejects inexact or unsafe integer text %s', (raw) => { + expect(parsePositiveSafeIntegerText(raw)).toBeNull() + }) + // Values the CLI's own Number() coercion accepts must parse to the same + // budget here, or the caller's timer expires before the CLI's does. it.each([ ['+1000', 1_000], ['1000.0', 1_000], - ['1e3', 1_000] + ['1e3', 1_000], + ['1.0000000000000000001', 1], + ['+1.0000000000000000001', 1], + ['600000.000000000000001', 600_000] ])('parses CLI-compatible positive integer text %s', (raw, expected) => { expect(parsePositiveSafeIntegerNumericText(raw)).toBe(expected) }) diff --git a/src/shared/timer-delay.ts b/src/shared/timer-delay.ts index 99172b99f45..5f57bb4c10e 100644 --- a/src/shared/timer-delay.ts +++ b/src/shared/timer-delay.ts @@ -19,6 +19,12 @@ export function parsePositiveSafeIntegerText(raw: string): number | null { return exactValue === BigInt(value) ? value : null } +// Why: mirrors the CLI's own `Number()` coercion for generic `--timeout-ms` +// flags (cli/flags.ts getOptionalPositiveIntegerFlag). Text that coerces to an +// exact integer — `1000.0`, `600000.000000000000001` — is the budget the CLI +// will actually wait on, so rejecting it here would leave the caller's timer +// shorter than the CLI's and cut the request short. Callers that need exact +// text (orchestration ask) use parsePositiveSafeIntegerText instead. export function parsePositiveSafeIntegerNumericText(raw: string): number | null { const value = Number(raw) return Number.isSafeInteger(value) && value > 0 ? value : null