You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore(sync): cascade predicate lift + docs/claude.md/ reorg from socket-repo-template
Resolves the local fork of prefer-undefined-over-null.js — the two predicates are now upstream in the template (isAssertionLibraryArg, isNullableTypeInitializer).
Copy file name to clipboardExpand all lines: CLAUDE.md
+9-5Lines changed: 9 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,7 +137,7 @@ The principle: the working tree at end-of-turn should match the user's mental mo
137
137
138
138
### Hook bypasses require the canonical phrase
139
139
140
-
🚨 Reverting tracked changes or bypassing a hook (--no-verify, DISABLE*PRECOMMIT*\*, --no-gpg-sign, force-push) requires the user to type **`Allow <X> bypass`** verbatim in a recent user turn (e.g. `Allow revert bypass`, `Allow no-verify bypass`). Paraphrases don't count. Enforced by `.claude/hooks/no-revert-guard/`. Full phrase table: [`docs/references/bypass-phrases.md`](docs/references/bypass-phrases.md).
140
+
🚨 Reverting tracked changes or bypassing a hook (--no-verify, DISABLE*PRECOMMIT*\*, --no-gpg-sign, force-push) requires the user to type **`Allow <X> bypass`** verbatim in a recent user turn (e.g. `Allow revert bypass`, `Allow no-verify bypass`). Paraphrases don't count. Enforced by `.claude/hooks/no-revert-guard/`. Full phrase table: [`docs/claude.md/bypass-phrases.md`](docs/claude.md/bypass-phrases.md).
141
141
142
142
### Variant analysis on every High/Critical finding
143
143
@@ -176,6 +176,10 @@ How to check:
176
176
177
177
Never silently let drift sit. Either reconcile in the same PR or open a follow-up PR titled `chore(sync): cascade <thing> from <newer-repo>` and link it.
178
178
179
+
### Never fork fleet-canonical files locally
180
+
181
+
🚨 Fleet-canonical files (anything tracked by `socket-repo-template/scripts/sync-scaffolding/manifest.mts`) MUST be edited in `socket-repo-template/template/...` and cascaded out — never branched locally in a downstream fleet repo. If you spot a useful predicate / helper / test / behavior in a fleet-canonical file in a downstream repo that's NOT in the template, that's a bug — lift it up first, then re-cascade. Full canonical-surface list + lifting workflow: [`docs/claude.md/no-local-fork-canonical.md`](docs/claude.md/no-local-fork-canonical.md).
182
+
179
183
### Code style
180
184
181
185
-**Comments** — default to none. Write one only when the WHY is non-obvious to a senior engineer. **When you do write a comment, the audience is a junior dev**: explain the constraint, the hidden invariant, the "why this and not the obvious thing." Don't label it ("for junior devs:", "intuition:", etc.) — just write in that voice. No teacher-tone, no condescension, no flattering the reader.
@@ -189,8 +193,8 @@ Never silently let drift sit. Either reconcile in the same PR or open a follow-u
189
193
-**File deletion** — route every delete through `safeDelete()` / `safeDeleteSync()` from `@socketsecurity/lib/fs`. Never `fs.rm` / `fs.unlink` / `fs.rmdir` / `rm -rf` directly — even for one known file. Prefer the async `safeDelete()` over `safeDeleteSync()` when the surrounding code is already async (test bodies, request handlers, build scripts that await elsewhere) — sync I/O blocks the event loop and there's no benefit when the caller is awaiting anyway. Reserve `safeDeleteSync()` for top-level scripts whose entire flow is sync.
190
194
-**Edits** — Edit tool, never `sed` / `awk`.
191
195
-**Generated reports** — quality scans, security audits, perf snapshots, anything an automated tool emits — write to `.claude/reports/` (naturally gitignored as part of `.claude/*`, no separate rule needed). Never commit reports to a tracked `reports/`, `docs/reports/`, or similarly-named tracked directory: dated reports rot the moment they land and the directory becomes a graveyard. The current state of the repo is the report; tools regenerate findings on demand. If a finding is genuinely worth keeping past one run, fix it or open an issue — don't pickle it as a markdown file.
192
-
-**Inclusive language** — see [`docs/references/inclusive-language.md`](docs/references/inclusive-language.md) for the substitution table.
193
-
-**Sorting** — sort alphanumerically (literal byte order, ASCII before letters). Applies to: object property keys (config + return shapes + internal state — `__proto__: null` first); named imports inside a single statement (`import { a, b, c }`); `Set` / `SafeSet` constructor arguments; allowlists / denylists / config arrays / interface members. Position-bearing arrays (where index matters) keep their meaningful order. Full details in [`docs/references/sorting.md`](docs/references/sorting.md). When in doubt, sort.
196
+
-**Inclusive language** — see [`docs/claude.md/inclusive-language.md`](docs/claude.md/inclusive-language.md) for the substitution table.
197
+
-**Sorting** — sort alphanumerically (literal byte order, ASCII before letters). Applies to: object property keys (config + return shapes + internal state — `__proto__: null` first); named imports inside a single statement (`import { a, b, c }`); `Set` / `SafeSet` constructor arguments; allowlists / denylists / config arrays / interface members. Position-bearing arrays (where index matters) keep their meaningful order. Full details in [`docs/claude.md/sorting.md`](docs/claude.md/sorting.md). When in doubt, sort.
194
198
-**`Promise.race` / `Promise.any` in loops** — never re-race a pool that survives across iterations (the handlers stack). See `.claude/skills/plug-leaking-promise-race/SKILL.md`.
195
199
-**`Safe` suffix** — non-throwing wrappers end in `Safe` (`safeDelete`, `safeDeleteSync`, `applySafe`, `weakRefSafe`). Read it as "X, but safe from throwing." The wrapper traps the thrown value internally and returns `undefined` (or the documented fallback). Don't invent alternative suffixes (`Try`, `OrUndefined`, `Maybe`) — pick `Safe`.
196
200
-**`node:smol-*` modules** — feature-detect, then require. From outside socket-btm (socket-lib, socket-cli, anywhere else): `import { isBuiltin } from 'node:module'; if (isBuiltin('node:smol-X')) { const mod = require('node:smol-X') }`. The `node:smol-*` namespace is provided by socket-btm's smol Node binary; on stock Node `isBuiltin` returns false and the require would throw. Wrap the loader in a `/*@__NO_SIDE_EFFECTS__*/` lazy-load that caches the result — see `socket-lib/src/smol/util.ts` and `socket-lib/src/smol/primordial.ts` for canonical shape. **Inside** socket-btm's `additions/source-patched/` JS (the smol binary's own bootstrap code), use `internalBinding('smol_X')` directly — that's the C++-binding access path and it's guaranteed available there.
@@ -260,7 +264,7 @@ An error message is UI. The reader should fix the problem from the message alone
260
264
3.**Saw vs. wanted** — the bad value and the allowed shape or set.
261
265
4.**Fix** — one imperative action (`rename the key to …`).
262
266
263
-
Use `isError` / `isErrnoException` / `errorMessage` / `errorStack` from `@socketsecurity/lib/errors` over hand-rolled checks. Use `joinAnd` / `joinOr` from `@socketsecurity/lib/arrays` for allowed-set lists. Full guidance in [`docs/references/error-messages.md`](docs/references/error-messages.md).
267
+
Use `isError` / `isErrnoException` / `errorMessage` / `errorStack` from `@socketsecurity/lib/errors` over hand-rolled checks. Use `joinAnd` / `joinOr` from `@socketsecurity/lib/arrays` for allowed-set lists. Full guidance in [`docs/claude.md/error-messages.md`](docs/claude.md/error-messages.md).
264
268
265
269
### Token hygiene
266
270
@@ -281,7 +285,7 @@ Full hook spec in [`.claude/hooks/token-guard/README.md`](.claude/hooks/token-gu
-**Handing off to another agent** — see [`docs/references/agent-delegation.md`](docs/references/agent-delegation.md) for when to reach for `codex:codex-rescue`, the `delegate` subagent (OpenCode → Fireworks/Synthetic/Kimi), `Explore`, `Plan`, vs. driving the skill CLIs directly. The CLI-subprocess contract used by skills lives in [`_shared/multi-agent-backends.md`](.claude/skills/_shared/multi-agent-backends.md).
288
+
-**Handing off to another agent** — see [`docs/claude.md/agent-delegation.md`](docs/claude.md/agent-delegation.md) for when to reach for `codex:codex-rescue`, the `delegate` subagent (OpenCode → Fireworks/Synthetic/Kimi), `Explore`, `Plan`, vs. driving the skill CLIs directly. The CLI-subprocess contract used by skills lives in [`_shared/multi-agent-backends.md`](.claude/skills/_shared/multi-agent-backends.md).
| ✗ |`Error: invalid component`| No rule, no saw, no where. |
24
-
| ✗ |`The "name" component of type "npm" failed validation because the provided value "" is empty, which is not allowed because names are required; please provide a non-empty name.`| Restates the rule three times. |
25
-
| ✓ |`npm "name" component is required`| Rule + where + implied saw (missing). Six words. |
26
-
| ✗ |`Error: bad name`| No rule. |
27
-
| ✓ |`name "__proto__" cannot start with an underscore`| Rule, where (`name`), saw (`__proto__`), fix implied. |
21
+
| ✗ / ✓ | Message | Notes |
22
+
| --- | --- | --- |
23
+
| ✗ |`Error: invalid component`| No rule, no saw, no where. |
24
+
| ✗ |`The "name" component of type "npm" failed validation because the provided value "" is empty, which is not allowed because names are required; please provide a non-empty name.`| Restates the rule three times. |
25
+
| ✓ |`npm "name" component is required`| Rule + where + implied saw (missing). Six words. |
26
+
| ✗ |`Error: bad name`| No rule. |
27
+
| ✓ |`name "__proto__" cannot start with an underscore`| Rule, where (`name`), saw (`__proto__`), fix implied. |
28
+
| ✗ |`Error: invalid argument`| No where, no rule, no fix. |
29
+
| ✓ |`orgSlug is required`| Rule + where (`orgSlug`), saw (missing), implies fix. |
30
+
| ✗ |`Error: request failed`| No status, no hint what to check. |
31
+
| ✓ |`Socket API rejected the token (401); check SOCKET_API_TOKEN`| Rule (401), where (token), fix (check env var). |
-**Saw vs. wanted**: saw = missing; wanted = a single-word lowercase filename, with `"parsing"` as a concrete model.
43
47
-**Fix**: `Add … to this part` — imperative, specific.
44
48
45
-
The trailing `to route /<slug>/part/3 at publish time` is optional. Include a _why_ clause only when the rule is non-obvious; skip it for rules the reader already knows (e.g. "names can't start with an underscore").
49
+
The trailing `to route /<slug>/part/3 at publish time` is optional. Include a *why* clause only when the rule is non-obvious; skip it for rules the reader already knows (e.g. "names can't start with an underscore").
Fleet-canonical files (anything tracked by `socket-repo-template/scripts/sync-scaffolding/manifest.mts`) MUST be edited in `socket-repo-template/template/...` and cascaded out — never branched locally in a downstream fleet repo.
4
+
5
+
## Canonical surfaces
6
+
7
+
These directories and files cascade fleet-wide. They are **not** repo-local:
If unsure, check `socket-repo-template/scripts/sync-scaffolding/manifest.mts`. Tracked = canonical.
19
+
20
+
## How to apply
21
+
22
+
If a downstream repo needs a behavior change in one of these files:
23
+
24
+
1. Edit the file in `socket-repo-template/template/...`.
25
+
2. Commit the template change.
26
+
3. Run `node scripts/sync-scaffolding/main.mts --target <downstream-repo> --fix` to cascade.
27
+
28
+
Do NOT edit the local copy in the downstream repo and rely on cascades to "preserve" your edits via `git checkout HEAD --` workarounds. That creates drift the sync mechanism then has to dance around, blocking other improvements from reaching that file in that repo.
29
+
30
+
## Spotting drift to lift
31
+
32
+
If you spot a useful predicate / helper / test / behavior in a fleet-canonical file in a downstream repo that is **not** in the template, that is a bug. Lift it up first, then re-cascade.
33
+
34
+
The fix is mechanical:
35
+
36
+
1. Diff the downstream version vs the template version.
37
+
2. Identify the additions (if there are any subtractions, those are also drift — usually they need to be added back to the downstream repo via a cascade).
38
+
3. Add the additions to the template.
39
+
4. Commit + push the template.
40
+
5. Re-cascade the downstream repo (overwrites its local copy with the now-superset canonical version).
41
+
42
+
## Why this matters
43
+
44
+
Local forks turn into "drift to preserve" hacks. Every cascade subagent has to be told to skip the locally-forked file, which makes the cascade fragile. Worse, those forks block fleet-wide improvements from reaching the forked repo: when the template's version of the file gets a real upgrade (e.g. a new fix predicate, a new exception case), the downstream repo's local copy never gets it.
45
+
46
+
The fleet's value is the shared canon. Branching locally splits the canon and erodes the value.
0 commit comments