diff --git a/eslint.config.mjs b/eslint.config.mjs index f7891018f..17f7c3438 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -222,7 +222,7 @@ export default tseslint.config( // Downgraded from recommended error → warn (pre-existing violations; follow-up to fix) 'no-useless-escape': 'warn', 'no-regex-spaces': 'warn', - 'no-control-regex': 'warn', + 'no-control-regex': 'error', 'no-irregular-whitespace': 'warn', }, }, diff --git a/tests/bug-2957-claude-global-postinstall-message.test.cjs b/tests/bug-2957-claude-global-postinstall-message.test.cjs index 571f20a45..a83758c21 100644 --- a/tests/bug-2957-claude-global-postinstall-message.test.cjs +++ b/tests/bug-2957-claude-global-postinstall-message.test.cjs @@ -39,6 +39,7 @@ function captureFinishInstallOutput(runtime, isGlobal) { console.log = original; } // Strip ANSI color escapes so message-content assertions don't couple to colors. + // eslint-disable-next-line no-control-regex -- \x1b (ESC) is the required leading byte of ANSI SGR color sequences; matching it is the purpose of stripping ANSI codes from captured CLI/console output return lines.join('\n').replace(/\x1B\[[0-9;]*m/g, ''); } diff --git a/tests/bug-3582-codex-skills-materialized.test.cjs b/tests/bug-3582-codex-skills-materialized.test.cjs index ac6ae112d..306e24d7d 100644 --- a/tests/bug-3582-codex-skills-materialized.test.cjs +++ b/tests/bug-3582-codex-skills-materialized.test.cjs @@ -53,6 +53,7 @@ const COMMANDS_DIR = path.join(ROOT, 'commands', 'gsd'); // Strip ANSI color codes so log assertions don't depend on TTY detection. function stripAnsi(s) { + // eslint-disable-next-line no-control-regex -- \x1b (ESC) is the required leading byte of ANSI SGR color sequences; matching it is the purpose of stripping ANSI codes from captured CLI/console output return s.replace(/\x1b\[[0-9;]*m/g, ''); } diff --git a/tests/feat-2795-update-banner.test.cjs b/tests/feat-2795-update-banner.test.cjs index 0189e0e92..b1c49e148 100644 --- a/tests/feat-2795-update-banner.test.cjs +++ b/tests/feat-2795-update-banner.test.cjs @@ -317,6 +317,7 @@ describe('install.js update-banner wiring', () => { // Strip ANSI color escapes before structural assertions — the choice // digits are wrapped in color codes so word-boundary regex against the // raw text would miss them. + // eslint-disable-next-line no-control-regex -- \x1b (ESC) is the required leading byte of ANSI SGR color sequences; matching it is the purpose of stripping ANSI codes from captured CLI/console output const stripped = text.replace(/\x1b\[[0-9;]*m/g, ''); // Prompt must offer at least two choices (default + opt-in). assert.match(stripped, /\b1\b/); diff --git a/tests/gsd-statusline.test.cjs b/tests/gsd-statusline.test.cjs index 4960a6d04..5425bf235 100644 --- a/tests/gsd-statusline.test.cjs +++ b/tests/gsd-statusline.test.cjs @@ -334,6 +334,7 @@ describe('context meter respects CLAUDE_CODE_AUTO_COMPACT_WINDOW (#2219)', () => // Parse normalized used% from the statusline bar output (e.g. "60%") // Strip ANSI escape codes then extract the percentage digit(s) before "%" + // eslint-disable-next-line no-control-regex -- \x1b (ESC) is the required leading byte of ANSI SGR color sequences; matching it is the purpose of stripping ANSI codes from captured CLI/console output const clean = stdout.replace(/\x1b\[[0-9;]*m/g, ''); const match = clean.match(/(\d+)%/); const normalizedUsed = match ? parseInt(match[1], 10) : null; diff --git a/tests/installer-migration-install-integration.test.cjs b/tests/installer-migration-install-integration.test.cjs index 2f4f79dc4..857bc101f 100644 --- a/tests/installer-migration-install-integration.test.cjs +++ b/tests/installer-migration-install-integration.test.cjs @@ -133,6 +133,7 @@ function withSdkDistPresent(fn) { } function stripAnsi(value) { + // eslint-disable-next-line no-control-regex -- \x1b (ESC) is the required leading byte of ANSI SGR color sequences; matching it is the purpose of stripping ANSI codes from captured CLI/console output return value.replace(/\x1b\[[0-9;]*m/g, ''); }