Skip to content

Commit 628bf25

Browse files
committed
chore(sync): cascade hook + reviewing-code updates from socket-repo-template
- .git-hooks/_helpers.mts + pre-commit.mts + pre-push.mts: hook error messages now suggest the file's natural marker syntax (// for TS/JS edits, # for shell/YAML, etc.). - .claude/hooks/logger-guard/index.mts: same error-message refinement. - .claude/skills/reviewing-code/run.mts: drop process.chdir; thread repoRoot as cwd through git calls (parallel-Claude safety — chdir is a process-global side effect that races sibling worktrees).
1 parent bb3228a commit 628bf25

5 files changed

Lines changed: 60 additions & 21 deletions

File tree

.claude/hooks/logger-guard/index.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ function emitBlock(filePath: string, hits: Hit[]): void {
220220
out.push(` …and ${hits.length - 3} more.`)
221221
}
222222
out.push(
223-
' Opt-out for one line (rare): append `// # socket-hook: allow logger`.',
223+
' Opt-out for one line (rare): append `// socket-hook: allow logger`.',
224224
)
225225
out.push('')
226226
process.stderr.write(out.join('\n'))

.claude/skills/reviewing-code/run.mts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,9 @@ Options:
384384
-h, --help Show this help`)
385385
}
386386

387-
async function git(args: readonly string[]): Promise<string> {
387+
async function git(args: readonly string[], cwd?: string): Promise<string> {
388388
const result = await spawn('git', args as string[], {
389+
cwd,
389390
stdio: 'pipe',
390391
stdioString: true,
391392
})
@@ -453,6 +454,7 @@ async function runBackend(
453454
promptText: string,
454455
tempDir: string,
455456
passLabel: string,
457+
cwd: string,
456458
): Promise<{ ok: boolean; output: string; logPath: string }> {
457459
const desc = BACKENDS[backend]
458460
const promptFile = path.join(tempDir, `${passLabel}.prompt.txt`)
@@ -464,6 +466,7 @@ async function runBackend(
464466
let stdout = ''
465467
try {
466468
const child = spawn(desc.bin, argv as string[], {
469+
cwd,
467470
stdio: 'pipe',
468471
stdioString: true,
469472
})
@@ -573,18 +576,20 @@ async function main(): Promise<void> {
573576
logger.error('Must be run inside a git repository.')
574577
process.exit(1)
575578
}
576-
process.chdir(repoRoot)
577579

578-
const branchRaw = await git(['branch', '--show-current'])
580+
const branchRaw = await git(['branch', '--show-current'], repoRoot)
579581
const branch =
580582
branchRaw.length > 0
581583
? branchRaw
582-
: `detached-${(await git(['rev-parse', '--short', 'HEAD']))}`
583-
const baseRef = await resolveBaseRef(args.baseRef)
584-
const mergeBase = await git(['merge-base', baseRef, 'HEAD'])
584+
: `detached-${(await git(['rev-parse', '--short', 'HEAD'], repoRoot))}`
585+
const baseRef = await resolveBaseRef(args.baseRef, repoRoot)
586+
const mergeBase = await git(['merge-base', baseRef, 'HEAD'], repoRoot)
585587
const range = `${mergeBase}..HEAD`
586-
const commitList = await git(['log', '--oneline', '--no-decorate', range])
587-
const diffStat = await git(['diff', '--stat', range])
588+
const commitList = await git(
589+
['log', '--oneline', '--no-decorate', range],
590+
repoRoot,
591+
)
592+
const diffStat = await git(['diff', '--stat', range], repoRoot)
588593

589594
const outputPath =
590595
args.outputPath ??
@@ -631,7 +636,13 @@ async function main(): Promise<void> {
631636
}
632637
logger.info(`${passLabel}: running on ${backend}`)
633638
const promptText = ROLES[role].buildPrompt(ctx)
634-
const result = await runBackend(backend, promptText, tempDir, passLabel)
639+
const result = await runBackend(
640+
backend,
641+
promptText,
642+
tempDir,
643+
passLabel,
644+
repoRoot,
645+
)
635646
if (!result.ok) {
636647
logger.error(`${passLabel}: failed; see ${result.logPath}`)
637648
await appendSkipNote(
@@ -674,17 +685,23 @@ async function main(): Promise<void> {
674685
}
675686
}
676687

677-
async function resolveBaseRef(provided: string | undefined): Promise<string> {
688+
async function resolveBaseRef(
689+
provided: string | undefined,
690+
cwd: string,
691+
): Promise<string> {
678692
if (provided) {
679693
return provided
680694
}
681695
try {
682-
const headRef = await git([
683-
'symbolic-ref',
684-
'--quiet',
685-
'--short',
686-
'refs/remotes/origin/HEAD',
687-
])
696+
const headRef = await git(
697+
[
698+
'symbolic-ref',
699+
'--quiet',
700+
'--short',
701+
'refs/remotes/origin/HEAD',
702+
],
703+
cwd,
704+
)
688705
if (headRef.length > 0) {
689706
return headRef
690707
}

.git-hooks/_helpers.mts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,25 @@ const PERSONAL_PATH_PLACEHOLDER_RE =
122122
// renames the marker.
123123
const SOCKET_HOOK_MARKER_RE =
124124
/(?:#|\/\/|\/\*)\s*socket-hook:\s*allow(?:\s+([\w-]+))?/
125+
126+
// File extensions whose natural comment syntax is `//` (C-family + cousins).
127+
// Anything else falls through to `#` (shell / YAML / TOML / Dockerfile /
128+
// Makefile / Python / Ruby / etc).
129+
const SLASH_COMMENT_EXT_RE =
130+
/\.(m?ts|tsx|cts|m?js|jsx|cjs|rs|go|c|cc|cpp|cxx|h|hpp|java|swift|kt|scala|dart|php|css|scss|less)$/i
131+
132+
/**
133+
* Pick the natural per-line opt-out marker for a host file.
134+
*
135+
* The marker regex above accepts `#`, `//`, and `/*` prefixes — but error
136+
* messages should print the *one* form a contributor would actually paste
137+
* into that file. TS edits get `// socket-hook: allow <rule>`; YAML gets
138+
* `# socket-hook: allow <rule>`. Same rule, different comment lexer.
139+
*/
140+
export const socketHookMarkerFor = (filePath: string, rule: string): string =>
141+
SLASH_COMMENT_EXT_RE.test(filePath)
142+
? `// socket-hook: allow ${rule}`
143+
: `# socket-hook: allow ${rule}`
125144
const LEGACY_ZIZMOR_MARKER_RE = /(?:#|\/\/|\/\*)\s*zizmor:\s*[\w-]+/
126145

127146
function lineIsSuppressed(line: string, rule?: string): boolean {
@@ -351,7 +370,8 @@ export const scanNpxDlx = (text: string): LineHit[] => {
351370
// `@socketsecurity/lib/logger`. Direct calls to `process.stderr.write`,
352371
// `process.stdout.write`, `console.log`, `console.error`, `console.warn`,
353372
// `console.info`, `console.debug` are blocked. Doc-context lines are
354-
// exempt; lines carrying `# socket-hook: allow logger` are exempt too.
373+
// exempt; lines carrying `// socket-hook: allow logger` (or `#` in
374+
// non-TS files) are exempt too.
355375

356376
const LOGGER_LEAK_RE =
357377
/\b(process\.std(?:err|out)\.write|console\.(?:log|error|warn|info|debug))\s*\(/

.git-hooks/pre-commit.mts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
scanPrivateKeys,
2727
scanSocketApiKeys,
2828
shouldSkipFile,
29+
socketHookMarkerFor,
2930
yellow,
3031
} from './_helpers.mts'
3132

@@ -195,7 +196,7 @@ const main = (): number => {
195196
out(
196197
"Use 'pnpm exec <package>' or 'pnpm run <script>' instead. For " +
197198
'documentation lines that need the literal `npx` form, append ' +
198-
'the marker `# socket-hook: allow npx`.',
199+
`the marker \`${socketHookMarkerFor(file, 'npx')}\`.`,
199200
)
200201
errors++
201202
}
@@ -244,7 +245,7 @@ const main = (): number => {
244245
out(
245246
'Use `getDefaultLogger()` from `@socketsecurity/lib/logger`. ' +
246247
'For documentation lines that need the literal call, append ' +
247-
'the marker `# socket-hook: allow logger`.',
248+
`the marker \`${socketHookMarkerFor(file, 'logger')}\`.`,
248249
)
249250
errors++
250251
}

.git-hooks/pre-push.mts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
scanPrivateKeys,
3838
scanSocketApiKeys,
3939
shouldSkipFile,
40+
socketHookMarkerFor,
4041
} from './_helpers.mts'
4142

4243
const ZERO_SHA = '0000000000000000000000000000000000000000'
@@ -315,7 +316,7 @@ const scanFilesInRange = (range: string): number => {
315316
out(
316317
'Use `getDefaultLogger()` from `@socketsecurity/lib/logger`. ' +
317318
'For documentation lines that need the literal call, append ' +
318-
'the marker `# socket-hook: allow logger`.',
319+
`the marker \`${socketHookMarkerFor(file, 'logger')}\`.`,
319320
)
320321
errors++
321322
}

0 commit comments

Comments
 (0)