chore(hooks): sync .claude/hooks fleet — mts conversion + new guards#1300
Merged
John-David Dalton (jdalton) merged 2 commits intomainfrom May 5, 2026
Merged
chore(hooks): sync .claude/hooks fleet — mts conversion + new guards#1300John-David Dalton (jdalton) merged 2 commits intomainfrom
John-David Dalton (jdalton) merged 2 commits intomainfrom
Conversation
4 tasks
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Commit-msg hook drops Linear issue reference blocking
- Added scanLinearReferences() to _helpers.mts with the same team-key regex and linear.app URL detection from the old bash script, and invoked it from commit-msg.mts to block commits containing Linear issue references.
Or push these changes by commenting:
@cursor push 73335fc0fb
Preview (73335fc0fb)
diff --git a/.git-hooks/_helpers.mts b/.git-hooks/_helpers.mts
--- a/.git-hooks/_helpers.mts
+++ b/.git-hooks/_helpers.mts
@@ -382,6 +382,41 @@
return hits
}
+// ── Linear issue reference scanner ──────────────────────────────────
+//
+// Linear tracking lives in Linear; keep commit history tool-agnostic.
+// Team keys enumerated from the Socket workspace. PATCH listed before
+// PAT so the engine matches the longer prefix first.
+
+const LINEAR_TEAM_KEYS =
+ 'ASK|AUTO|BOT|CE|CORE|DAT|DES|DEV|ENG|INFRA|LAB|MAR|MET|OPS|PAR|PATCH|PAT|PLAT|REA|SALES|SBOM|SEC|SMO|SUP|TES|TI|WEB'
+
+const LINEAR_ISSUE_RE = new RegExp(
+ `(?:^|[^A-Za-z0-9_])((?:${LINEAR_TEAM_KEYS})-[0-9]+)(?:$|[^A-Za-z0-9_])`,
+)
+const LINEAR_URL_RE = /linear\.app\/[A-Za-z0-9/_-]+/
+
+// Scans commit-message text for Linear issue references (team-key
+// patterns like SMO-590 and linear.app URLs). Ignores git comment
+// lines (lines starting with `#`).
+export const scanLinearReferences = (text: string): string[] => {
+ const hits: string[] = []
+ for (const line of text.split('\n')) {
+ if (line.startsWith('#')) {
+ continue
+ }
+ const issueMatch = line.match(LINEAR_ISSUE_RE)
+ if (issueMatch) {
+ hits.push(issueMatch[1]!)
+ }
+ const urlMatch = line.match(LINEAR_URL_RE)
+ if (urlMatch) {
+ hits.push(urlMatch[0])
+ }
+ }
+ return hits.slice(0, 5)
+}
+
// ── AI attribution scanner ─────────────────────────────────────────
const AI_ATTRIBUTION_RE =
diff --git a/.git-hooks/commit-msg.mts b/.git-hooks/commit-msg.mts
--- a/.git-hooks/commit-msg.mts
+++ b/.git-hooks/commit-msg.mts
@@ -1,11 +1,13 @@
#!/usr/bin/env node
// Socket Security Commit-msg Hook
//
-// Two responsibilities:
+// Three responsibilities:
// 1. Block commits that introduce API keys / .env files (security
// layer that runs even when pre-commit is bypassed via
// `--no-verify`).
-// 2. Auto-strip AI attribution lines from the commit message before
+// 2. Block commits whose message references Linear issues (keep
+// commit history tool-agnostic).
+// 3. Auto-strip AI attribution lines from the commit message before
// git records the commit.
//
// Wired via .husky/commit-msg, which invokes this with the path to the
@@ -23,6 +25,7 @@
out,
red,
readFileForScan,
+ scanLinearReferences,
scanSocketApiKeys,
shouldSkipFile,
stripAiAttribution,
@@ -67,9 +70,27 @@
}
}
- // Auto-strip AI attribution lines from the commit message.
+ // Block Linear issue references in the commit message.
const commitMsgFile = process.argv[2]
if (commitMsgFile && existsSync(commitMsgFile)) {
+ const msgText = readFileSync(commitMsgFile, 'utf8')
+ const linearHits = scanLinearReferences(msgText)
+ if (linearHits.length > 0) {
+ out(red('✗ Commit message references Linear issue(s):'))
+ for (const hit of linearHits) {
+ out(` ${hit}`)
+ }
+ out(
+ red(
+ 'Linear tracking lives in Linear. Remove the reference from the commit message.',
+ ),
+ )
+ errors++
+ }
+ }
+
+ // Auto-strip AI attribution lines from the commit message.
+ if (commitMsgFile && existsSync(commitMsgFile)) {
const original = readFileSync(commitMsgFile, 'utf8')
const { cleaned, removed } = stripAiAttribution(original)
if (removed > 0) {You can send follow-ups to the cloud agent here.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f5e6d06. Configure here.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
May 5, 2026
Four findings, all from socket-repo-template canonical (synced): 1. commit-msg lost Linear-ref blocking in the .sh→.mts conversion. The old shell hook scanned for team-key+digits patterns + linear.app URLs and refused commits. Restored as scanLinearRefs() in _helpers.mts, called from commit-msg.mts. Comment lines starting with `#` are skipped (git hint text + diff snippets). 2. auth-rotation-reminder/index.mts used (e as Error).message in three catch blocks. Switched to errorMessage(e) from @socketsecurity/lib/errors per repo convention. 3. _helpers.mts scanSocketApiKeys mapped filtered lines back to LineHit via .find() on h.line === line, which returns the wrong lineNumber when two hits have identical content. Filter LineHit[] directly via the new isAllowedApiKey() helper instead. 4. auth-rotation-reminder/test used rmSync from node:fs for cleanup. Switched to safeDelete from @socketsecurity/lib/fs (async, since tests are already async). Added a CLAUDE.md rule documenting the async-over-sync preference for safeDelete.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
May 5, 2026
Four findings, all from socket-repo-template canonical (synced): 1. commit-msg lost Linear-ref blocking in the .sh→.mts conversion. The old shell hook scanned for team-key+digits patterns + linear.app URLs and refused commits. Restored as scanLinearRefs() in _helpers.mts, called from commit-msg.mts. Comment lines starting with `#` are skipped (git hint text + diff snippets). 2. auth-rotation-reminder/index.mts used (e as Error).message in three catch blocks. Switched to errorMessage(e) from @socketsecurity/lib/errors per repo convention. 3. _helpers.mts scanSocketApiKeys mapped filtered lines back to LineHit via .find() on h.line === line, which returns the wrong lineNumber when two hits have identical content. Filter LineHit[] directly via the new isAllowedApiKey() helper instead. 4. auth-rotation-reminder/test used rmSync from node:fs for cleanup. Switched to safeDelete from @socketsecurity/lib/fs (async, since tests are already async). Added a CLAUDE.md rule documenting the async-over-sync preference for safeDelete.
a63d291 to
ffea8bf
Compare
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
May 5, 2026
Synced from socket-repo-template canonical. The fleet CLAUDE.md
moved to a fleet-canonical / project-specific layout — public-surface
hygiene rules, parallel-session safeguards, code style, and tooling
go in CLAUDE.md; project-specific extensions (build commands, test
targets, repo-particular conventions) go below.
Skills added:
- path-guard — audit and fix path duplication ("1 path, 1 reference")
- programmatic-claude-lockdown — reference for locking down headless
Claude invocations (claude CLI in workflows, agent-sdk query() in
code) per the four-flag lockdown pattern
- promise-race-pitfall — reference for the Promise.race
cross-iteration handler-leak bug
Skills updated:
- security-scan — wires AgentShield + zizmor + Socket CLI dependency
scanning, A-F graded report
Path-guard infra:
- scripts/check-paths.mts — repo-level path-duplication scanner
- .github/paths-allowlist.yml — known-acceptable duplicates
- .claude/skills/path-guard/reference/* — templates for new repos
Doctrine references:
- docs/references/inclusive-language.md — substitution table
- docs/references/sorting.md — alphanumeric sort rules
Repo-template integration:
- .socket-repo-template.json — repo-particular kind config
- scripts/socket-repo-template-{schema,emit-schema}.mts — schema tooling
- socket-repo-template-schema.json — emitted JSON schema
Splits content out of #1286. Companion split PR #1300 covers hooks +
harness config; deps_misc bucket folds into #1285 SHA cascade per
project direction.
Synced from socket-repo-template canonical hooks fleet. Replaces
socket-cli's .sh husky/git-hooks scaffolding with TypeScript .mts
implementations (single-language toolchain, easier to test and
maintain), and adds the new fleet-canonical guard hooks.
Hooks added:
- auth-rotation-reminder — prompts on token rotation events
- logger-guard — blocks console.log/error in production code
- path-guard — enforces "1 path, 1 reference" in edits
- private-name-guard — blocks public-facing internal-only names
- release-workflow-guard — blocks dispatching publish/release flows
- setup-security-tools — bootstraps sfw + zizmor + AgentShield pins
- stale-process-sweeper — Stop hook reaping orphaned vitest workers
- token-guard — blocks raw secret exposure in tool output
Hooks updated:
- check-new-deps — soak-window wording + .mjs→.mts script refs
- public-surface-reminder — package.json sync
Conversion:
- .git-hooks/{commit-msg,pre-push,_helpers}.sh → .mts (3 deletions)
- .husky/{commit-msg,pre-commit,pre-push} — call .mts entries
- .oxfmtrc.json — enable JSDoc formatting (oxfmt 0.x feature)
- .claude/settings.json — register new hooks under PreToolUse/Stop
Splits content out of #1286. Identical file content; this PR is the
hooks/config slice with no skill or CLAUDE.md changes.
Four findings, all from socket-repo-template canonical (synced): 1. commit-msg lost Linear-ref blocking in the .sh→.mts conversion. The old shell hook scanned for team-key+digits patterns + linear.app URLs and refused commits. Restored as scanLinearRefs() in _helpers.mts, called from commit-msg.mts. Comment lines starting with `#` are skipped (git hint text + diff snippets). 2. auth-rotation-reminder/index.mts used (e as Error).message in three catch blocks. Switched to errorMessage(e) from @socketsecurity/lib/errors per repo convention. 3. _helpers.mts scanSocketApiKeys mapped filtered lines back to LineHit via .find() on h.line === line, which returns the wrong lineNumber when two hits have identical content. Filter LineHit[] directly via the new isAllowedApiKey() helper instead. 4. auth-rotation-reminder/test used rmSync from node:fs for cleanup. Switched to safeDelete from @socketsecurity/lib/fs (async, since tests are already async). Added a CLAUDE.md rule documenting the async-over-sync preference for safeDelete.
ffea8bf to
43fe734
Compare
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
May 5, 2026
…1301) * docs(claude+skills): CLAUDE.md restructure + path-guard + new skills Synced from socket-repo-template canonical. The fleet CLAUDE.md moved to a fleet-canonical / project-specific layout — public-surface hygiene rules, parallel-session safeguards, code style, and tooling go in CLAUDE.md; project-specific extensions (build commands, test targets, repo-particular conventions) go below. Skills added: - path-guard — audit and fix path duplication ("1 path, 1 reference") - programmatic-claude-lockdown — reference for locking down headless Claude invocations (claude CLI in workflows, agent-sdk query() in code) per the four-flag lockdown pattern - promise-race-pitfall — reference for the Promise.race cross-iteration handler-leak bug Skills updated: - security-scan — wires AgentShield + zizmor + Socket CLI dependency scanning, A-F graded report Path-guard infra: - scripts/check-paths.mts — repo-level path-duplication scanner - .github/paths-allowlist.yml — known-acceptable duplicates - .claude/skills/path-guard/reference/* — templates for new repos Doctrine references: - docs/references/inclusive-language.md — substitution table - docs/references/sorting.md — alphanumeric sort rules Repo-template integration: - .socket-repo-template.json — repo-particular kind config - scripts/socket-repo-template-{schema,emit-schema}.mts — schema tooling - socket-repo-template-schema.json — emitted JSON schema Splits content out of #1286. Companion split PR #1300 covers hooks + harness config; deps_misc bucket folds into #1285 SHA cascade per project direction. * fix(check-paths): Rule F requires >=2 distinct files, not just >=2 hits Cursor Bugbot caught: `checkRuleF` grouped Rule-A findings purely by string-literal shape and promoted to Rule F whenever count >= 2, without checking distinct files. Two hand-builds of the same path shape in the SAME file would be incorrectly flagged as 'cross-file repetition' — but Rule F's whole point is cross-file duplication. Fix: build a Set of distinct file paths and gate the promotion on size >= 2. Also include the file count in the message (`in N files (M places)`) so the reviewer knows both numbers. Synced to socket-repo-template canonical.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
.shhusky / git-hooks scaffolding with TypeScript.mtsimplementations (single-language toolchain).
auth-rotation-reminder,logger-guard,path-guard,private-name-guard,release-workflow-guard,setup-security-tools,stale-process-sweeper,token-guard.check-new-deps,public-surface-reminder.PreToolUse/Stopin.claude/settings.json.oxfmtJSDoc formatting in.oxfmtrc.json.Scope
This is the hooks + harness-config slice split out of #1286. Companion
splits in flight:
.claude/hooks/,.git-hooks/,.husky/,.claude/settings.json,.oxfmtrc.jsonCLAUDE.md,docs/references/,.claude/skills/*,.socket-repo-template.json,scripts/socket-repo-template-*package.json,pnpm-lock.yaml,pnpm-workspace.yaml, packages/* drift,scripts/check.mts,scripts/power-state.mtsAfter all three splits land, #1286 closes.
Test plan
gh workflow run(post-fix)tsconfig.jsonper hook) typecheck cleanlyNote
High Risk
High risk because it introduces multiple blocking
PreToolUse/git hook enforcement paths (including token/path/workflow dispatch guards) and adds an automatedStophook that logs users out of CLIs, which can disrupt developer workflows if misconfigured or overly broad.Overview
Adds new Claude Code hooks that block or warn on risky actions:
token-guard(replacingtoken-hygiene) to prevent secret-leaking Bash shapes,path-guardto prevent inline multi-stage build-path construction,logger-guardto block directconsole.*/stream writes in source,release-workflow-guardto block GitHub Actions workflow dispatch commands, andprivate-name-guardto remind on public-surface commands.Introduces new
Stophooks:auth-rotation-reminderto periodically revoke CLI logins with snooze/skip-list/throttling, andstale-process-sweeperto kill orphaned test/build worker processes. Registers these underPreToolUse/Stopin.claude/settings.jsonand updatescheck-new-deps(improved Cargo.toml extraction and safer module entrypoint ordering).Migrates Husky/git hooks from shell to
.mts(commit-msg,pre-commit,pre-push) with a shared_helpers.mts, expanding scanners (AI attribution stripping, secret/personal-path detection,npx/dlxand logger-leak checks, submodule pristine check) and updatessetup-security-toolsto install AgentShield via the dlx cache with a schema switch to TypeBox. Also enables JSDoc formatting options in.oxfmtrc.json.Reviewed by Cursor Bugbot for commit f5e6d06. Configure here.