feat(gbrain-repo-policy-client): repoPolicyTier accepts a spawn timeout

The policy script spawn was fixed at 10 s, more than twice the memorable
hook's whole budget. Callers on their own deadline pass what they can afford;
a timeout reads as unreadable and polarity stays the caller's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-09-09 03:19:04 +00:00
co-authored by Claude Fable 5.1
parent 4285556925
commit 7a24f9b0e5
+10 -2
View File
@@ -57,8 +57,16 @@ const POLICY_SCRIPT = join(import.meta.dir, "..", "bin", "gstack-gbrain-repo-pol
* Fast paths (no subprocess): no store on disk → `none`; no remote URL →
* `none` (policy is keyed by origin remote, so nothing can be set for the
* repo). Everything else shells to the script, which owns normalization.
*
* `timeoutMs` bounds that spawn (default 10 s). A caller on its own deadline
* (a Claude Code hook) passes what it can afford; a timeout reads as
* `unreadable`, and polarity stays the caller's.
*/
export function repoPolicyTier(url: string | null, env: NodeJS.ProcessEnv = process.env): RepoPolicyResult {
export function repoPolicyTier(
url: string | null,
env: NodeJS.ProcessEnv = process.env,
timeoutMs: number = 10_000,
): RepoPolicyResult {
if (!hasRepoPolicyStore(env)) return { tier: "none" };
if (!url) return { tier: "none" };
// The script is `#!/usr/bin/env bash`; win32 can't exec a shebang file, so
@@ -67,7 +75,7 @@ export function repoPolicyTier(url: string | null, env: NodeJS.ProcessEnv = proc
process.platform === "win32" ? ["bash", [POLICY_SCRIPT, "get", url]] : [POLICY_SCRIPT, ["get", url]];
const res = spawnSync(cmd, args, {
encoding: "utf-8",
timeout: 10_000,
timeout: Math.max(1, timeoutMs),
// Explicit env: Bun's spawnSync default env snapshot misses runtime
// process.env mutations (e.g. tests redirecting GSTACK_HOME).
env: { ...env } as NodeJS.ProcessEnv,