Batch 14 of the ad hoc timeout literal migration (epic #4445). Replaces every bare numeric timeout/timeoutMs object-literal property in tests/gsd-statusline.test.cjs and tests/teams-status.test.cjs with a named constant, per eslint-rules/no-adhoc-timeout-literal.cjs. Removes these 2 files from the rule's allowlist. Issue #4525 cautions against forcing either file onto PROBE_TIMEOUT_MS without checking, since both invoke a "long-lived status renderer." Checking each file's actual production handler separately found the caution applies to one file and not the other: gsd-statusline.test.cjs's 7 sites all spawn hooks/gsd-statusline.js, which does real rendering work (context-window, git, teams state) -- two new file-local constants (STATUSLINE_HOOK_TIMEOUT_MS=4000, 6 sites; STATUSLINE_HOOK_GIT_SHIM_TIMEOUT_MS =5000, 1 site for a heavier git-shim test). teams-status.test.cjs's 5 sites spawn `gsd-tools.cjs query teams-status`, whose handler (gsd-core/bin/lib/teams-status.cjs's cmdTeamsStatus) is a lightweight env-truthiness check with no rendering or fan-out -- genuinely matching PROBE_TIMEOUT_MS's class, confirmed by reading the handler directly rather than assumed from the matching value. No new shared-helper constant is needed this batch. No src/bin file touched, no numeric value changed anywhere. Co-authored-by: sim <sim@local> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
"tests/code-review.test.cjs",
|
||||
"tests/dispatcher.test.cjs",
|
||||
"tests/gate-predicate-evaluator.test.cjs",
|
||||
"tests/gsd-statusline.test.cjs",
|
||||
"tests/phase6-capstone-conformance.test.cjs",
|
||||
"tests/plan-phase-stall-detection.test.cjs",
|
||||
"tests/plan-review-convergence.test.cjs",
|
||||
@@ -17,6 +16,5 @@
|
||||
"tests/reviewer-manifest-body.test.cjs",
|
||||
"tests/reviewer-trust-disclosure.test.cjs",
|
||||
"tests/run-tests-temp-root.test.cjs",
|
||||
"tests/shell-command-projection-dispatch.test.cjs",
|
||||
"tests/teams-status.test.cjs"
|
||||
"tests/shell-command-projection-dispatch.test.cjs"
|
||||
]
|
||||
|
||||
@@ -24,6 +24,26 @@ const {
|
||||
} = require('../hooks/gsd-statusline.js');
|
||||
const { cleanup, saveSessionEnv, restoreSessionEnv, clearSessionEnv } = require('./helpers.cjs');
|
||||
|
||||
/**
|
||||
* A single hooks/gsd-statusline.js spawn, no fan-out -- the "long-lived
|
||||
* status renderer" class (renders context-window percentage, git
|
||||
* branch/status, active-teams state), a distinct and heavier operation
|
||||
* than a trivial CLI query despite this file's own PROBE_TIMEOUT_MS-sized
|
||||
* sibling class norm elsewhere in the suite.
|
||||
*/
|
||||
const STATUSLINE_HOOK_TIMEOUT_MS = 4000;
|
||||
|
||||
/**
|
||||
* The same hooks/gsd-statusline.js hook as STATUSLINE_HOOK_TIMEOUT_MS, but
|
||||
* this one test rigs a custom PATH (a git shim directory) and
|
||||
* CLAUDE_CONFIG_DIR override -- a heavier setup than the plain invocation,
|
||||
* hence the larger pre-existing bound. Coincides numerically with
|
||||
* tests/helpers/timeouts.cjs's SCAN_USAGE_ERROR_TIMEOUT_MS and
|
||||
* MALFORMED_INPUT_HOOK_TIMEOUT_MS (both 5000ms) but describes neither of
|
||||
* those operations -- kept local.
|
||||
*/
|
||||
const STATUSLINE_HOOK_GIT_SHIM_TIMEOUT_MS = 5000;
|
||||
|
||||
// ─── parseStateMd ───────────────────────────────────────────────────────────
|
||||
|
||||
describe('parseStateMd', () => {
|
||||
@@ -639,7 +659,7 @@ describe('context meter respects CLAUDE_CODE_AUTO_COMPACT_WINDOW (#2219)', () =>
|
||||
delete env.CLAUDE_CODE_AUTO_COMPACT_WINDOW;
|
||||
}
|
||||
|
||||
const r = runHookSeam(hookPath, [], { input: payload, env, timeoutMs: 4000 });
|
||||
const r = runHookSeam(hookPath, [], { input: payload, env, timeoutMs: STATUSLINE_HOOK_TIMEOUT_MS });
|
||||
const stdout = r.stdout;
|
||||
|
||||
// Parse normalized used% from the statusline bar output (e.g. "60%")
|
||||
@@ -736,7 +756,7 @@ describe('context meter boundary: acw at/near totalCtx does not pin used at 100%
|
||||
input: payload,
|
||||
env,
|
||||
encoding: 'utf8',
|
||||
timeout: 4000,
|
||||
timeout: STATUSLINE_HOOK_TIMEOUT_MS,
|
||||
});
|
||||
} catch (e) {
|
||||
stdout = e.stdout || '';
|
||||
@@ -878,7 +898,7 @@ describe('todo-resolution: resolves in_progress task from the newest matching to
|
||||
input: payload,
|
||||
env,
|
||||
encoding: 'utf8',
|
||||
timeout: 4000,
|
||||
timeout: STATUSLINE_HOOK_TIMEOUT_MS,
|
||||
});
|
||||
} catch (e) {
|
||||
stdout = e.stdout || '';
|
||||
@@ -1656,7 +1676,7 @@ test('config-set statusline.show_context_tokens yes → rejected', () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
const r = runHookSeam(hookPath, [], { input: payload, timeoutMs: 4000 });
|
||||
const r = runHookSeam(hookPath, [], { input: payload, timeoutMs: STATUSLINE_HOOK_TIMEOUT_MS });
|
||||
// eslint-disable-next-line no-control-regex -- stripping ANSI SGR sequences from captured CLI output
|
||||
return r.stdout.replace(/\x1b\[[0-9;]*m/g, '');
|
||||
}
|
||||
@@ -2254,7 +2274,7 @@ test('config-set statusline.show_context_tokens yes → rejected', () => {
|
||||
workspace: { current_dir: dir },
|
||||
session_id: `test-git-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
});
|
||||
const r = runHookSeam(hookPath, [], { input: payload, timeoutMs: 4000 });
|
||||
const r = runHookSeam(hookPath, [], { input: payload, timeoutMs: STATUSLINE_HOOK_TIMEOUT_MS });
|
||||
// eslint-disable-next-line no-control-regex -- stripping ANSI SGR sequences from captured CLI output
|
||||
return r.stdout.replace(/\x1b\[[0-9;]*m/g, '');
|
||||
}
|
||||
@@ -2514,7 +2534,7 @@ describe('evaluateUpdateCache lineage guard', () => {
|
||||
});
|
||||
const r = runHookSeam(path.join(cold.hooksDir, 'gsd-statusline.js'), [], {
|
||||
input: payload,
|
||||
timeoutMs: 4000,
|
||||
timeoutMs: STATUSLINE_HOOK_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(r.exitCode, 0, `must exit 0 on a build failure; stdout: ${r.stdout} stderr: ${r.stderr}`);
|
||||
assert.equal(r.stdout, '', 'must degrade to empty output, not throw a stack trace to stdout');
|
||||
@@ -3056,7 +3076,7 @@ describe('evaluateUpdateCache lineage guard', () => {
|
||||
const r = runHookSeam(hookPath, [], {
|
||||
input: payload,
|
||||
env: { ...process.env, PATH: `${shimDir}${path.delimiter}${process.env.PATH}`, CLAUDE_CONFIG_DIR: claudeDir },
|
||||
timeoutMs: 5000,
|
||||
timeoutMs: STATUSLINE_HOOK_GIT_SHIM_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(r.outcome, OUTCOME.EXITED, `expected clean exit, got outcome=${r.outcome}`);
|
||||
assert.equal(r.exitCode, 0);
|
||||
|
||||
@@ -15,6 +15,20 @@ const path = require('node:path');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
|
||||
const { resolveTeamsStatus } = require('../gsd-core/bin/lib/teams-status.cjs');
|
||||
/**
|
||||
* Reuses the existing PROBE_TIMEOUT_MS constant rather than declaring a
|
||||
* new one, despite this batch's own issue (#4525, epic #4445) cautioning
|
||||
* against forcing a "long-lived status renderer" onto PROBE_TIMEOUT_MS
|
||||
* without checking. Checked directly: gsd-core/bin/lib/teams-status.cjs's
|
||||
* cmdTeamsStatus (what these 5 sites spawn via `gsd-tools.cjs query
|
||||
* teams-status`) is a lightweight env-truthiness check plus one fast
|
||||
* synchronous runtime resolution -- no rendering, no subprocess fan-out --
|
||||
* genuinely matching PROBE_TIMEOUT_MS's class, not the heavier
|
||||
* "long-lived renderer" class the issue's caution targets (that class is
|
||||
* hooks/gsd-statusline.js, correctly kept off PROBE_TIMEOUT_MS in this
|
||||
* same batch's sibling file, tests/gsd-statusline.test.cjs).
|
||||
*/
|
||||
const { PROBE_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||
|
||||
const gsdToolsPath = path.resolve(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
|
||||
|
||||
@@ -120,7 +134,7 @@ describe('gsd-tools query teams-status — CLI subprocess tests', () => {
|
||||
[gsdToolsPath, 'query', 'teams-status'],
|
||||
{
|
||||
encoding: 'utf8',
|
||||
timeout: 15000,
|
||||
timeout: PROBE_TIMEOUT_MS,
|
||||
env: makeEnv({ runtime: 'claude', teamsFlag: '1' }),
|
||||
},
|
||||
);
|
||||
@@ -142,7 +156,7 @@ describe('gsd-tools query teams-status — CLI subprocess tests', () => {
|
||||
[gsdToolsPath, 'query', 'teams-status'],
|
||||
{
|
||||
encoding: 'utf8',
|
||||
timeout: 15000,
|
||||
timeout: PROBE_TIMEOUT_MS,
|
||||
env: makeEnv({ runtime: 'claude' }),
|
||||
},
|
||||
);
|
||||
@@ -158,7 +172,7 @@ describe('gsd-tools query teams-status — CLI subprocess tests', () => {
|
||||
[gsdToolsPath, 'query', 'teams-status', '--active'],
|
||||
{
|
||||
encoding: 'utf8',
|
||||
timeout: 15000,
|
||||
timeout: PROBE_TIMEOUT_MS,
|
||||
env: makeEnv({ runtime: 'claude', teamsFlag: '1' }),
|
||||
},
|
||||
);
|
||||
@@ -173,7 +187,7 @@ describe('gsd-tools query teams-status — CLI subprocess tests', () => {
|
||||
[gsdToolsPath, 'query', 'teams-status', '--active'],
|
||||
{
|
||||
encoding: 'utf8',
|
||||
timeout: 15000,
|
||||
timeout: PROBE_TIMEOUT_MS,
|
||||
env: makeEnv({ runtime: 'claude' }),
|
||||
},
|
||||
);
|
||||
@@ -186,7 +200,7 @@ describe('gsd-tools query teams-status — CLI subprocess tests', () => {
|
||||
[gsdToolsPath, 'query', 'teams-status', '--active'],
|
||||
{
|
||||
encoding: 'utf8',
|
||||
timeout: 15000,
|
||||
timeout: PROBE_TIMEOUT_MS,
|
||||
env: makeEnv({ runtime: 'codex', teamsFlag: '1' }),
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user