* test(#3662): failing-first suite for runtime-resolving hook runners * fix(#3662): resolve managed hook node runners at hook-fire time * fix(#3662): close review findings and document the resolver * fix(#3662): close adversarial and security review findings * chore(#3662): backfill changeset pr number * test(#3662): honor win32 skip return and platform-aware sh runner pin * test(#3662): pin the bare win32-claude sh-hook shape omitting the bash runner --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -205,6 +205,13 @@ const MANAGED_HOOK_BASENAMES_BY_SURFACE: Record<string, Set<string>> = {
|
||||
'gsd-read-injection-scanner.js',
|
||||
'gsd-update-banner.js',
|
||||
'gsd-workflow-guard.js',
|
||||
// #3662: the three PreToolUse guards are GSD-managed JS hooks (registered
|
||||
// only-if-absent by applySettingsJsonHooks) but sat outside this set, so
|
||||
// the #2979 runner rewriter never reached them — the issue's reported
|
||||
// mixed state lived on exactly these hooks.
|
||||
'gsd-write-guard.js',
|
||||
'gsd-agent-isolation-guard.js',
|
||||
'gsd-worktree-path-guard.js',
|
||||
]),
|
||||
'codex-toml': new Set([
|
||||
'gsd-check-update.js',
|
||||
@@ -225,6 +232,14 @@ const MANAGED_HOOK_COMMAND_BASENAMES_BY_SURFACE: Record<string, Set<string>> = {
|
||||
'gsd-session-state.sh',
|
||||
'gsd-validate-commit.sh',
|
||||
'gsd-phase-boundary.sh',
|
||||
// #3662: same three guards as MANAGED_HOOK_BASENAMES_BY_SURFACE above —
|
||||
// their absence here meant isManagedHookCommand never recognized them, so
|
||||
// the settings.json→settings.local.json migration filter (and uninstall
|
||||
// cleanup) skipped GSD's own guard entries. Folded-in fix, surfaced by the
|
||||
// #3662 issue thread.
|
||||
'gsd-write-guard.js',
|
||||
'gsd-agent-isolation-guard.js',
|
||||
'gsd-worktree-path-guard.js',
|
||||
]),
|
||||
'codex-toml': new Set([
|
||||
'gsd-check-update.js',
|
||||
@@ -320,21 +335,27 @@ const ANCHORED_HOOK_SCRIPT_TOKEN = /^"\$[A-Za-z_][A-Za-z0-9_]*"\//;
|
||||
* Non-Windows keeps the original script token shape when provided (single
|
||||
* quote / bareword / quoted), while Windows normalizes to double-quoted
|
||||
* forward-slash path tokens for stable cross-shell behavior.
|
||||
*
|
||||
* #3662: `runnerToken` is the runner the current install would emit — since
|
||||
* #3662 that is the runtime-resolving chain token (see
|
||||
* buildNodeRunnerChainToken), not a bare absolute path, so re-projected
|
||||
* entries converge onto a runner that resolves in every environment sharing
|
||||
* the config root.
|
||||
*/
|
||||
export function projectLegacySettingsHookCommand({
|
||||
absoluteRunner,
|
||||
runnerToken,
|
||||
scriptPath,
|
||||
scriptToken,
|
||||
runtime = 'generic',
|
||||
platform = process.platform,
|
||||
}: {
|
||||
absoluteRunner?: string | null;
|
||||
runnerToken?: string | null;
|
||||
scriptPath?: string | null;
|
||||
scriptToken?: string | null;
|
||||
runtime?: string;
|
||||
platform?: string;
|
||||
}): string | null {
|
||||
if (!absoluteRunner || !scriptPath) return null;
|
||||
if (!runnerToken || !scriptPath) return null;
|
||||
const normalizedScriptPath = platform === 'win32' ? posixNormalize(scriptPath) : scriptPath;
|
||||
// #1693: a script path already carrying a `"$CLAUDE_PROJECT_DIR"`-anchored
|
||||
// quoted prefix (local installs) is already a valid shell token — only the
|
||||
@@ -352,7 +373,7 @@ export function projectLegacySettingsHookCommand({
|
||||
: JSON.stringify(normalizedScriptPath))
|
||||
: (scriptToken || JSON.stringify(normalizedScriptPath));
|
||||
return projectShellCommandText({
|
||||
runnerToken: absoluteRunner,
|
||||
runnerToken,
|
||||
argTokens: [commandScriptToken],
|
||||
runtime,
|
||||
platform,
|
||||
|
||||
Reference in New Issue
Block a user