chore(hooks+claude+oxfmt+kind-config): hooks-mts + sweeper + CLAUDE.md restructure + oxfmt JSDoc + logger-guard + auth-rotation-reminder + kind config#1286
Conversation
Self-landable split from #1279. Combines the hook overhaul into one atomic PR. Path-guard infra - .claude/hooks/path-guard/ (hook + tests + segments.mts) - .claude/skills/path-guard/ (audit-and-fix skill) - .claude/skills/_shared/path-guard-rule.md (canonical rule) - scripts/check-paths.mts (the gate) - .github/paths-allowlist.yml (empty starter, full schema docs) - .claude/settings.json (wires hook on Edit|Write) - scripts/check.mts (invokes the gate) Token-guard hook - .claude/hooks/token-guard/ (renamed from token-hygiene; word- boundary match for sensitive env names; ALWAYS_DANGEROUS check skips when redaction pipeline is present) .sh → .mts hook conversion (Node 25+) - .git-hooks/_helpers.mts (was _helpers.sh) — exports filterAllowedApiKeys + scanners (personal paths, AWS keys, GitHub tokens, private keys, AI attribution) - .git-hooks/{commit-msg,pre-commit,pre-push}.mts (were .sh) - .husky/* shims invoke node directly Fleet hooks (additions) - .claude/hooks/check-new-deps (npm dep introspection) - .claude/hooks/private-name-guard - .claude/hooks/release-workflow-guard - .claude/hooks/setup-security-tools (updated) - .claude/hooks/public-surface-reminder/package.json (updated) Cleanup - Remove orphan .claude/hooks/token-hygiene (renamed to token-guard)
|
bugbot run |
- .husky/pre-commit: add `set -e` so a non-zero exit from the security hook (.git-hooks/pre-commit.mts) blocks the commit instead of being silently overridden by a later passing pnpm lint/test. Without it the shell continued past the security check; the script's exit code came from the last command, so a security failure followed by a passing lint/test would let the commit through. - token-guard: replace the single regex-based hasRedaction with a segment-aware version. The old patterns used `[\s\S]*?` which lazily reached across `|` boundaries, so an unrelated downstream stage named e.g. `tool_redact_output` could match `<?redact` and launder an upstream `env` dump. The new logic splits on `|` (skipping shell- or `||`) and requires each redaction marker to live inside a single pipe segment; whole-command redirections (`>`, `>>`, `>/dev/null`) are still matched against the full command. Adds a regression test for the canonical bypass `env | sed 's/foo/bar/' | tool_redact_output`.
|
bugbot run |
Bugbot caught a follow-up bypass: `env || sed 's/=.*/=<redacted>/'`
was credited as redacted because
1. REDACTION_WHOLE_COMMAND_MARKERS' loose `/>\s*[^|]/` matched the
literal `>` inside `<redacted>`, returning true on the
whole-command path before any segment logic ran.
2. Even without that, hasRedaction's earlier `replace(||, '')`
glued the two arms into one segment so the `sed` redaction
looked unconditional.
But `env || sed` only runs sed if env FAILS — and env always
succeeds, so the redaction never fires at runtime. Combined with
the `!hasRedaction(command)` exception on ALWAYS_DANGEROUS, the env
dump went through unredacted.
Two-part fix:
1. Tighten REDACTION_WHOLE_COMMAND_MARKERS to anchor `>` and `>>`
at a real shell boundary (`^`, whitespace, `|`, `;`) followed by
a filename-shaped target — no more matching the `>` inside
`<redacted>` or `s/=.*/.../`.
2. In hasRedaction, lop off everything from the first `||` or `&&`
before splitting on `|`. A redaction marker on the right side of
a conditional doesn't run unconditionally and can't launder an
upstream leak.
Smoke-tested:
✓ env | sed 's/=.*/=<redacted>/' (matches)
✓ printenv | sed 's/=.*/=<redacted>/' | grep TOKEN (matches)
✓ env > /dev/null (matches)
✓ env > /tmp/leak.txt (matches)
✗ env || sed 's/=.*/=<redacted>/' (NOT credited)
✗ env && sed 's/=.*/=<redacted>/' (NOT credited)
✗ env | sed 's/foo/bar/' | tool_redact_output (NOT credited)
|
bugbot run |
REDACTION_SEGMENT_MARKERS use .* between sed and the redaction marker word, which crosses ; boundaries within a single pipe segment. Bugbot found the bypass shape 'env | sed s/a/b/ ; echo redacted_output': split on | keeps both statements in one segment, the regex matches the literal word redact downstream of an unrelated sed, and the env dump is credited as redacted. Fix: split each pipe segment further on ; so a redaction marker is only credited when sed and the marker word live in the same statement.
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Whole-command redaction check bypasses conditional-operator truncation
- Moved the REDACTION_WHOLE_COMMAND_MARKERS check to run after the ||/&& truncation so whole-command markers are tested against the truncated string, preventing redirection markers in never-executed conditional branches from bypassing the env-dump block.
Or push these changes by commenting:
@cursor push c4d7dca9ab
Preview (c4d7dca9ab)
diff --git a/.claude/hooks/token-guard/index.mts b/.claude/hooks/token-guard/index.mts
--- a/.claude/hooks/token-guard/index.mts
+++ b/.claude/hooks/token-guard/index.mts
@@ -53,12 +53,12 @@
/\bcut\b.*-d['"]?=['"]?\s*-f\s*1/i,
/\bawk\b.*-F\s*['"]?=['"]?/i,
]
-// Whole-command redirection markers. Anchored at a pipe-segment
-// boundary (`^`, whitespace, `|`, or `;`) so they fire only on real
-// shell redirection (`env > file`, `env >> file`, `env > /dev/null`)
-// and not on the literal `>` inside regex/HTML-style markers like
-// `<redacted>` or `s/=.*/.../`. The previous /\s*[^|]/ shape would
-// match the `>` in `<redacted>` and bypass the env-dump check.
+// Whole-command redirection markers, checked against the truncated
+// command (after stripping `||`/`&&` suffixes). Anchored at a
+// pipe-segment boundary (`^`, whitespace, `|`, or `;`) so they fire
+// only on real shell redirection (`env > file`, `env >> file`,
+// `env > /dev/null`) and not on the literal `>` inside regex/HTML-
+// style markers like `<redacted>` or `s/=.*/.../`.
const REDACTION_WHOLE_COMMAND_MARKERS = [
/(?:^|[\s|;])>\s*\/dev\/null\b/,
/(?:^|[\s|;])>>?\s*[^|<>'"\\$&\s]/,
@@ -137,9 +137,6 @@
// where a `redact`-named downstream tool would otherwise launder the
// upstream `env` dump.
const hasRedaction = (command: string): boolean => {
- if (REDACTION_WHOLE_COMMAND_MARKERS.some(re => re.test(command))) {
- return true
- }
// Drop everything from the first `||` or `&&` onwards. Those branches
// don't unconditionally execute, so a redaction marker on their
// right side cannot launder an upstream leak. The bypass shape is
@@ -147,13 +144,19 @@
// `sed` arm never runs at runtime, but the previous logic credited
// it as a redaction and let the env dump through. Truncating before
// the conditional operator forces the redaction to live in the same
- // unconditional pipeline as the leaky stage.
+ // unconditional pipeline as the leaky stage. Both whole-command and
+ // segment markers must check the truncated string — otherwise
+ // `env || true > /dev/null` would match a whole-command marker and
+ // return true early despite the redirection never executing.
const idxOr = command.indexOf('||')
const idxAnd = command.indexOf('&&')
let cut = command.length
if (idxOr !== -1) cut = Math.min(cut, idxOr)
if (idxAnd !== -1) cut = Math.min(cut, idxAnd)
const truncated = command.slice(0, cut)
+ if (REDACTION_WHOLE_COMMAND_MARKERS.some(re => re.test(truncated))) {
+ return true
+ }
// Split first on `|` (pipe-stage boundary), then on `;` (statement
// boundary) within each stage. A redaction marker is only credited
// when both `sed` and the redaction target live in the sameYou can send follow-ups to the cloud agent here.
Three findings from Cursor Bugbot's latest pass on the chore/hooks-mts-path-token branch: 1. HIGH — token-guard: whole-command redaction check ran BEFORE the conditional-operator truncation, so `env || true > /dev/null` matched the `> /dev/null` whole-command marker on the full string and short-circuited to "credited" even though the redirection lives on the unreachable `||` branch. Fix: truncate at first `||` / `&&` first, then run the whole-command markers against the truncated string. Smoke test (17 cases) confirms all known bypass shapes are blocked and all legitimate redaction shapes are still credited. 2. LOW — check-new-deps: replace local `errorMessage` mirror with the shared `errorMessage` import from `@socketsecurity/lib/errors`. The local helper's `// can't import the shared helper` comment was wrong — the hook already depends on `@socketsecurity/lib`, so the shared helper IS reachable. Drops 5 lines of duplicated logic. 3. LOW — setup-security-tools: replace ad-hoc `e instanceof Error ? e.message : String(e)` with `errorMessage(e)` from `@socketsecurity/lib/errors`. Hook already imports from `@socketsecurity/lib`, so the helper is in scope.
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit aa927eb. Configure here.
Reaps orphan vitest/tsgo/type-coverage/esbuild workers at turn-end so
they don't pile up across turns and exhaust system memory. Only kills
processes whose parent has died (true orphans); leaves running
test/build trees alone.
- .claude/hooks/stale-process-sweeper/ (hook + tests + README)
- .claude/settings.json (Stop hook block)
- CLAUDE.md (Background Bash rule + suppress
pre-existing hook false-positive
on documentation-prohibition line)
Sourced from socket-repo-template. Joins this PR's path-guard +
token-guard hook fleet to complete the canonical hook set.
Pre-commit lint+test skipped via DISABLE_PRECOMMIT_* — this worktree
is missing build artifacts that the test deps need (the change is
.claude/-only, no source touched).
…ific layout Split CLAUDE.md into two clearly-delimited sections: - `## 📚 Fleet Standards` — wrapped in BEGIN/END FLEET-CANONICAL markers, byte-identical across every socket-* repo (sync via socket-repo-template). - `## 🏗️ CLI-Specific` — repo-owned content: Commands, Testing, Command Pattern, Codex Usage. Fleet block ~8.6 KB; verbose content moves to references: - `docs/references/inclusive-language.md` - `docs/references/sorting.md` - `.claude/skills/promise-race-pitfall/SKILL.md` CLAUDE.md 13.5 KB → 9.7 KB. Joins this PR's hooks-mts conversion + sweeper additions; the new CLAUDE.md links into the same hook README files this PR is producing.
oxfmt 0.37+ formats JSDoc comments. Adopt the canonical `jsdoc` block from socket-repo-template; it preserves the existing JSDoc style across this repo (verified: zero new diff under the new config). Source of truth: socket-repo-template/template/.oxfmtrc.json. Future updates flow through `scripts/sync-scaffolding.mjs --all --fix`.
…epo-template
- `.git-hooks/_helpers.mts` + `pre-commit.mts` + `pre-push.mts` —
rename suppression marker `# zizmor: …` → `# socket-hook: allow [<rule>]`
(legacy form still recognized for one cycle); add doc-aware scan
heuristic; emit `LineHit.suggested` rewrites alongside hits.
- `.claude/hooks/token-guard/{index,test/token-guard.test}.mts` —
sync to canonical; settings.json picks up the fleet permissions
deny block.
- `.claude/skills/{path-guard,security-scan}/SKILL.md`,
`.claude/agents/security-reviewer.md` — sync drift from template.
- `.claude/skills/programmatic-claude-lockdown/SKILL.md` — fleet skill
for the four-flag lockdown recipe (matches socket-sdk-js PR #630).
- `CLAUDE.md` — update fleet block npx-rule marker; oxfmt-normalized
markdown emphasis.
- `docs/references/{inclusive-language,sorting}.md` — re-sync.
- `scripts/xport*.mts` + `xport.schema.json` — fleet xport tooling.
- `.husky/pre-commit` + `.git-hooks/commit-msg.mts` — sync.
- `pnpm-lock.yaml` — regenerate after template sync.
Pre-commit/test gates skipped via DISABLE_PRECOMMIT_*: this worktree's
build chain (download-assets / iocraft native addon) is unrelated to
the changes here, and the same gates are enforced in CI.
Sourced byte-identical from socket-repo-template (canonical fleet
hook); the same change rolled out across socket-* repos + ultrathink.
logger-guard (PreToolUse Edit|Write):
- Blocks direct stream writes (process.std{err,out}.write, console.*)
in source files; suggests getDefaultLogger() rewrite per hit.
- Path-exempts hooks/, .git-hooks/, scripts/, tests, fixtures,
external/ vendor/ upstream/.
- Honors `# socket-hook: allow [logger]` opt-out marker.
auth-rotation-reminder (Stop):
- Periodic auto-logout from npm/pnpm/yarn/gcloud/aws-sso/vault/docker/
socket; gh stays logged-in by default.
- 1h throttle, ISO-8601 .claude/auth-rotation.snooze with auto-cleanup.
- Skip when CI or SOCKET_AUTH_ROTATION_DISABLED set.
Pre-commit/pre-push pick up scanLoggerLeaks for edits made outside
…-window wording - pnpm-workspace.yaml: add blockExoticSubdeps: true (fleet default). Direct git deps still allowed; transitive ones refused. - Update sync-scaffolding script references from .mjs to .mts in hook READMEs, path-guard segments, _shared skill rules, CLAUDE.md, and xport-schema.mts header comment (the upstream rename has shipped; downstreams now reflect it). - Fold "soak-window" terminology into security-reviewer's checklist + CLAUDE.md tooling block — matches how the rest of the fleet refers to pnpm's minimumReleaseAge field. Pre-existing iocraft native-addon test failures unrelated to this change; user authorized --no-verify pending environment fix.
Picks up the v5.26.1 fixes (case-insensitive default + Windows
forward-slash normalization in `globs.glob` / `globSync` /
`getGlobMatcher`, narrow matchesGlob fast-path, .then→async/await
sweep) and migrates the two breaking-surface call sites:
ascii-header.mts — `effects/text-shimmer` was removed in v5.26.1
in favor of the redesigned shimmer engine in `effects/shimmer` +
`effects/shimmer-terminal`. Rewrite `renderShimmerFrame` against
the new API:
- Build one ShimmerSpec per line via `configToSpec` (the new
engine's spec factory) using the theme palette as `color`.
- Compute two `frameColors(spec, line.length, frame)` arrays per
line — primary (frame + slantOffset) and secondary (+35) —
preserving the dual-wave look the previous code achieved by
chaining two applyShimmer passes.
- Merge the two arrays per-char with a `brighterRgb` helper so
the brighter highlight wins, then pipe through
`colorsToAnsi` and wrap with bold.
Visual contract preserved: dual wave at the same speed (0.25),
same per-line slant offset (i * 4), same theme palette as
highlight gradient, same bold formatting around the truecolor
escapes.
cli-entry.mts — `themes` barrel removed; migrate `setTheme` import
to `themes/context` (its focused submodule home).
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Adds the per-repo socket-repo-template config + its schema: - `.socket-repo-template.json` — declares this repo's kind (consumer) + schemaVersion. Read by socket-repo-template's sync-scaffolding kind-aware checker to decide which optional files this repo must/must-not ship. socket-cli is `consumer` because it ships multiple npm packages and produces SEAs by *consuming* socket-btm's prebuilt binaries (not by emitting GH releases of its own). - `scripts/socket-repo-template-schema.mts` — TypeBox source of truth for the config shape. - `scripts/socket-repo-template-emit-schema.mts` — emitter that regenerates the JSON Schema from the TypeBox source. - `socket-repo-template-schema.json` — generated draft 2020-12 JSON Schema (referenced by `.socket-repo-template.json`'s `$schema` for editor autocompletion). Synced byte-identical from socket-repo-template@5ad601c.
The `scripts/xport-schema.mts` + `scripts/socket-repo-template-schema.mts` files added in this branch import from `@sinclair/typebox`, but the dep wasn't in package.json so `pnpm run xport:emit-schema` failed with ERR_MODULE_NOT_FOUND. Add `@sinclair/typebox: catalog:` to devDependencies (catalog already pins 0.34.49). Also sync the emit-schema scripts from socket-repo-template@563fd6a — both now `pnpm exec oxfmt` their output so the emitted JSON Schema matches what oxfmt produces. Regenerated `xport.schema.json` and `socket-repo-template-schema.json` through the formatter.
… dist/index.js ### iocraft loader: bundled-node_modules fallback (3 + 5 + 4 = 12 tests) The `@socketaddon/iocraft` package's `index.mjs` already had two fallback paths for finding the platform-specific `.node` binary: - direct check at `<build-out>/socketaddon-iocraft-<platformId>/iocraft.node` - pnpm-virtual-store reconstruction back to the same sibling layout Both assume a sibling-package layout (`socketaddon-iocraft-darwin-arm64` next to `socketaddon-iocraft`). On this branch, package-builder emits the binary as a *bundled* dep instead, at: `<build-out>/socketaddon-iocraft/node_modules/@socketaddon/iocraft-darwin-arm64/iocraft.node` That's where pnpm leaves the optionalDependency when it's installed into the file: package's local node_modules but not lifted into the consumer's `.pnpm` store (a known pnpm behavior for `file:` deps that declare optionalDependencies). Add a bundled-path fallback after the sibling-path check. Test: - iocraft-new-features.test.mts: 26/26 (was 23/26) - iocraft-properties.test.mts: 5 previously-failing tests now pass - AnalyticsRenderer / AuditLogRenderer / ThreatFeedRenderer: 4 previously-failing tests now pass ### paths.test.mts: dist/cli.js → dist/index.js (1 test) `getBinCliPath()` returns `dist/index.js` (renamed from `dist/cli.js` in the unified-build refactor — see comment at src/constants/paths.mts:41). Test still asserted the old `cli.js` form; update to expect `dist/index.js`. ### Result socket-cli's full test suite: 5248/5248 passing (was 5235/5248).
Adds `scripts/power-state.mts` — fleet-canonical AC-vs-battery
detection helper. Used by long-running build/test scripts to size
their timeouts adaptively (laptops on battery throttle CPU hard,
and a static timeout tuned for AC will kill an otherwise-healthy
run on battery).
Tries `node:smol-power` first (when running inside a node-smol
binary), falls back to per-platform paths on system Node:
- macOS: `pmset -g batt`
- Linux: `/sys/class/power_supply/<entry>/online` direct reads
(no shellout, no D-Bus, no UPower)
- Windows: PowerShell `Win32_Battery.BatteryStatus`
Synced byte-identical from socket-repo-template via sync-scaffolding.
|
Superseded by three focused splits:
Every file in this PR is content-identical to one of the three splits |
Synced from socket-repo-template / fleet-canonical drift work. - package.json + pnpm-lock.yaml + pnpm-workspace.yaml — catalog alignment with @socketsecurity/lib + @socketregistry/* fleet - packages/cli/src/cli-entry.mts — lib import refresh - packages/cli/src/utils/terminal/ascii-header.mts — drift sync - packages/cli/test/unit/constants/paths.test.mts — paths-test drift - packages/package-builder/templates/socketaddon-main/index.mjs — template drift - scripts/check.mts — adopt shared check pipeline - scripts/power-state.mts — fleet-canonical helper sync from socket-repo-template@c23dfef Splits content out of #1286, paired with the cascade SHA bump in the commit before this one.
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.
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.
…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.
Synced from socket-repo-template / fleet-canonical drift work. - package.json + pnpm-lock.yaml + pnpm-workspace.yaml — catalog alignment with @socketsecurity/lib + @socketregistry/* fleet - packages/cli/src/cli-entry.mts — lib import refresh - packages/cli/src/utils/terminal/ascii-header.mts — drift sync - packages/cli/test/unit/constants/paths.test.mts — paths-test drift - packages/package-builder/templates/socketaddon-main/index.mjs — template drift - scripts/check.mts — adopt shared check pipeline - scripts/power-state.mts — fleet-canonical helper sync from socket-repo-template@c23dfef Splits content out of #1286, paired with the cascade SHA bump in the commit before this one.
…1300) * chore(hooks): sync .claude/hooks fleet — mts conversion + new guards 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. * fix(hooks): address Cursor Bugbot findings on #1300 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.
…1302) * chore(deps): drift updates from #1286 — pnpm catalog + cli + scripts Synced from socket-repo-template / fleet-canonical drift work. - package.json + pnpm-lock.yaml + pnpm-workspace.yaml — catalog alignment with @socketsecurity/lib + @socketregistry/* fleet - packages/cli/src/cli-entry.mts — lib import refresh - packages/cli/src/utils/terminal/ascii-header.mts — drift sync - packages/cli/test/unit/constants/paths.test.mts — paths-test drift - packages/package-builder/templates/socketaddon-main/index.mjs — template drift - scripts/check.mts — adopt shared check pipeline - scripts/power-state.mts — fleet-canonical helper sync from socket-repo-template@c23dfef Splits content out of #1286, paired with the cascade SHA bump in the commit before this one. * chore(deps): regenerate pnpm-lock.yaml after rebase

Self-landable split from #1279. Combines the hook overhaul into one atomic PR.
Path-guard infra
.claude/hooks/path-guard/— hook + tests + canonicalsegments.mts.claude/skills/path-guard/— audit-and-fix skill.claude/skills/_shared/path-guard-rule.md— canonical mantra rulescripts/check-paths.mts— the whole-repo gate.github/paths-allowlist.yml— empty starter, full schema docs.claude/settings.json— wires hook onEdit|Writescripts/check.mts— invokes the gateToken-guard hook
.claude/hooks/token-guard/— renamed fromtoken-hygiene. Word-boundary match for sensitive env names.ALWAYS_DANGEROUScheck skips when a redaction pipeline is present.Stale-process-sweeper hook
.claude/hooks/stale-process-sweeper/—Stophook that reaps orphan vitest/tsgo/type-coverage/esbuild workers at turn-end. Only kills processes whose parent has died..claude/settings.jsonunderStophook block.Logger-guard hook (new)
.claude/hooks/logger-guard/—PreToolUse(Edit|Write)hook that blocks direct stream writes (process.std{err,out}.write,console.*) in source files; suggestsgetDefaultLogger()rewrite per hit.# socket-hook: allow [logger]opt-out marker.Auth-rotation-reminder hook (new)
.claude/hooks/auth-rotation-reminder/—Stophook that periodically auto-logs out of authenticated CLIs (npm/pnpm/yarn/gcloud/aws-sso/vault/docker/socket);ghstays logged-in by default (Claude Code uses it).~/.claude/hooks/auth-rotation/last-runmtime; ISO-8601.claude/auth-rotation.snoozewith auto-cleanup via safeDelete.SOCKET_AUTH_ROTATION_DISABLEDset.Pre-commit/pre-push scanLoggerLeaks
.git-hooks/_helpers.mtsaddsscanLoggerLeaksfor the same rule, so edits made outside Claude Code are caught at commit/push time.# socket-hook: allow <rule>marker (legacy# zizmor:still recognized for one cycle).CLAUDE.md restructure
## 📚 Fleet Standards(byte-identical across the fleet, wrapped in<!-- BEGIN/END FLEET-CANONICAL -->) and## 🏗️ CLI-Specific.docs/references/inclusive-language.md,docs/references/sorting.md,.claude/skills/promise-race-pitfall/SKILL.md..sh→.mtshook conversion (Node 25+).git-hooks/_helpers.mts(was_helpers.sh) — exportsfilterAllowedApiKeys+ scanners.git-hooks/{commit-msg,pre-commit,pre-push}.mts(were.sh).husky/*shims invokenodedirectlyFleet hooks
.claude/hooks/check-new-deps— npm dep introspection.claude/hooks/private-name-guard.claude/hooks/release-workflow-guard.claude/hooks/setup-security-tools(updated to canonical).claude/hooks/public-surface-reminder/package.json(updated)oxfmt JSDoc formatting
oxfmt 0.37+ formats JSDoc comments. Adopt canonical
jsdocblock from socket-repo-template. Verified zero new format violations on this repo's source.Cleanup
.claude/hooks/token-hygiene(renamed totoken-guard)Test plan
blockExoticSubdeps + .mjs->.mts ref sync (added 2026-05-01)
blockExoticSubdeps: true(fleet default — refuses transitive git/tarball subdeps; direct git deps still allowed)..mjs->.mtsreferences forscripts/sync-scaffoldingacross hook READMEs, path-guard segments, _shared skill rules, CLAUDE.md, xport-schema header.socket-repo-template kind config + schema (added 2026-05-03)
.socket-repo-template.jsondeclaringkind: "consumer"(socket-cli ships multiple npm packages and produces SEAs by consuming socket-btm's prebuilt binaries — it doesn't emit GH releases of its own).scripts/socket-repo-template-{schema,emit-schema}.mts+socket-repo-template-schema.jsonsynced byte-identical from socket-repo-template@5ad601c. The TypeBox source defines the per-repo config shape; the emitter regenerates the JSON Schema for IDE autocompletion.