diff --git a/src/resources/extensions/gsd/constants.ts b/src/resources/extensions/gsd/constants.ts new file mode 100644 index 000000000..636f2d808 --- /dev/null +++ b/src/resources/extensions/gsd/constants.ts @@ -0,0 +1,21 @@ +/** + * GSD Extension — Shared Constants + * + * Centralized timeout and cache-size constants used across the GSD extension. + */ + +// ─── Timeouts ───────────────────────────────────────────────────────────────── + +/** Default timeout for verification-gate commands (ms). */ +export const DEFAULT_COMMAND_TIMEOUT_MS = 120_000; + +/** Default timeout for the dynamic bash tool (seconds). */ +export const DEFAULT_BASH_TIMEOUT_SECS = 120; + +// ─── Cache Sizes ────────────────────────────────────────────────────────────── + +/** Max directory-listing cache entries before eviction (#611). */ +export const DIR_CACHE_MAX = 200; + +/** Max parse-cache entries before eviction. */ +export const CACHE_MAX = 50; diff --git a/src/resources/extensions/gsd/files.ts b/src/resources/extensions/gsd/files.ts index 66099f1be..989bf6e12 100644 --- a/src/resources/extensions/gsd/files.ts +++ b/src/resources/extensions/gsd/files.ts @@ -23,11 +23,10 @@ import { checkExistingEnvKeys } from '../get-secrets-from-user.js'; import { parseRoadmapSlices } from './roadmap-slices.js'; import { nativeParseRoadmap, nativeExtractSection, nativeParsePlanFile, nativeParseSummaryFile, NATIVE_UNAVAILABLE } from './native-parser-bridge.js'; import { debugTime, debugCount } from './debug-logger.js'; +import { CACHE_MAX } from './constants.js'; // ─── Parse Cache ────────────────────────────────────────────────────────── -const CACHE_MAX = 50; - /** Fast composite key: length + first/mid/last 100 chars. The middle sample * prevents collisions when only a few characters change in the interior of * a file (e.g., a checkbox [ ] → [x] that doesn't alter length or endpoints). */ diff --git a/src/resources/extensions/gsd/index.ts b/src/resources/extensions/gsd/index.ts index 36f109d3a..454211125 100644 --- a/src/resources/extensions/gsd/index.ts +++ b/src/resources/extensions/gsd/index.ts @@ -62,6 +62,7 @@ import { Text } from "@gsd/pi-tui"; import { pauseAutoForProviderError, classifyProviderError } from "./provider-error-pause.js"; import { toPosixPath } from "../shared/path-display.js"; import { isParallelActive, shutdownParallel } from "./parallel-orchestrator.js"; +import { DEFAULT_BASH_TIMEOUT_SECS } from "./constants.js"; // ── Agent Instructions ──────────────────────────────────────────────────── // Lightweight "always follow" files injected into every GSD agent session. @@ -171,7 +172,6 @@ export default function (pi: ExtensionAPI) { // the timeout parameter, commands run indefinitely, causing hangs on // Windows where process killing is unreliable (see #40). We wrap execute // to inject a 120-second default when no timeout is provided. - const DEFAULT_BASH_TIMEOUT_SECS = 120; const baseBash = createBashTool(process.cwd(), { spawnHook: (ctx) => ({ ...ctx, cwd: process.cwd() }), }); diff --git a/src/resources/extensions/gsd/paths.ts b/src/resources/extensions/gsd/paths.ts index 6e7458db6..df9ae1062 100644 --- a/src/resources/extensions/gsd/paths.ts +++ b/src/resources/extensions/gsd/paths.ts @@ -12,12 +12,10 @@ import { readdirSync, existsSync, Dirent } from "node:fs"; import { join } from "node:path"; import { nativeScanGsdTree, type GsdTreeEntry } from "./native-parser-bridge.js"; +import { DIR_CACHE_MAX } from "./constants.js"; // ─── Directory Listing Cache ────────────────────────────────────────────────── -/** Max entries before eviction. Prevents unbounded growth in long sessions (#611). */ -const DIR_CACHE_MAX = 200; - const dirEntryCache = new Map(); const dirListCache = new Map(); diff --git a/src/resources/extensions/gsd/verification-gate.ts b/src/resources/extensions/gsd/verification-gate.ts index 5a8b2fa01..f23908a0f 100644 --- a/src/resources/extensions/gsd/verification-gate.ts +++ b/src/resources/extensions/gsd/verification-gate.ts @@ -7,6 +7,7 @@ import { spawnSync } from "node:child_process"; import { existsSync, readFileSync } from "node:fs"; import { join, basename } from "node:path"; import type { AuditWarning, RuntimeError, VerificationCheck, VerificationResult } from "./types.js"; +import { DEFAULT_COMMAND_TIMEOUT_MS } from "./constants.js"; /** Maximum bytes of stdout/stderr to retain per command (10 KB). */ const MAX_OUTPUT_BYTES = 10 * 1024; @@ -152,9 +153,6 @@ function sanitizeCommand(cmd: string): string | null { return cmd; } -/** Default timeout for verification commands (ms). */ -const DEFAULT_COMMAND_TIMEOUT_MS = 120_000; - export interface RunVerificationGateOptions { basePath: string; unitId: string;