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
Copy file name to clipboardExpand all lines: CLAUDE.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -99,6 +99,10 @@ Rules:
99
99
100
100
The principle: the working tree at end-of-turn should match the user's mental model of where the work is. "Done" means committed; anything else is paused, and pause states need to be announced.
101
101
102
+
### Smallest chunks, land ASAP
103
+
104
+
π¨ Make changes in the **smallest possible chunks** and land them as soon as possible. Default to direct-push-to-main (the fleet norm β see _Commits & PRs_ "Push policy"). Don't accumulate work across multiple worktrees or long-lived feature branches; each unmerged branch is in-flight state that has to be tracked, rebased, and reconciled later. **Why:** Incident 2026-05-20 β socket-wheelhouse accumulated 4 sibling worktrees (two dead with 0 unmerged commits 59-113 behind, two with small work that needed rebasing). Consolidation burned a turn that should have been spent on the actual queue. The same instinct that flags _Drift watch_ across fleet repos applies to in-flight branches in one repo: drift is a defect, not a feature. **How to apply:** finish a branch the same session it's opened; if you find a worktree pile-up at session start, consolidate first (empty branches deleted, small unmerged work rebased + landed) before resuming the queue; don't pre-open branches "to be safe."
105
+
102
106
### Untracked-by-default for vendored / build-copied trees
103
107
104
108
π¨ Untracked dirs under `additions/source-patched/`, `vendor/`, `third_party/`, `external/`, `upstream/`, `deps/<libname>/`, `pkg-node/`, or `*-bundled`/`*-vendored` paths are **untracked-by-default**. Before staging: `git status --ignored` + read `.gitignore` (look for `dir/*` + `!dir/file` allowlists β the allowlisted file is our hand-written glue, not the whole tree) + grep for the build script that copies the dir in. When REMOVING a class / attribute / selector that other code consumes, grep BOTH the repo root AND every `upstream/` / `vendor/` / `third_party/` submodule before deleting β past incident: stripped a CSS class because repo-root grep found 0 hits; upstream bundle hydrated from it and the rendered output went blank (enforced by `.claude/hooks/consumer-grep-reminder/`). Ban "must be" / "presumably" / "looks like" when handling someone else's tree β run the command instead. Ask before committing 100+ file or multi-MB drops. Full playbook in [`docs/claude.md/fleet/untracked-by-default.md`](docs/claude.md/fleet/untracked-by-default.md).
@@ -133,6 +137,10 @@ For non-trivial work (multi-file refactor, new feature, migration), the plan its
133
137
134
138
π¨ **Drift across fleet repos is a defect, not a feature.** When two socket-\* repos pin different versions of the same shared resource (a tool in `external-tools.json`, a workflow SHA, a CLAUDE.md fleet block, a hook in `.claude/hooks/`, an upstream submodule, `.gitmodules``# name-version` annotations enforced by `.claude/hooks/gitmodules-comment-guard/`, pnpm/Node `packageManager`/`engines`), **opt for the latest**. Canonical sources: `socket-registry`'s `setup-and-install` action for tool SHAs; `socket-wheelhouse`'s `template/` tree for `.claude/`, CLAUDE.md fleet block, hooks. Either reconcile in the same PR or open `chore(sync): cascade <thing> from <newer-repo>` and link it (enforced by `.claude/hooks/drift-check-reminder/`). Full drift-surface list + cascade-PR convention in [`docs/claude.md/fleet/drift-watch.md`](docs/claude.md/fleet/drift-watch.md).
135
139
140
+
### Stranded cascades
141
+
142
+
π¨ Local-only `chore(sync): cascade fleet template@<sha>` commits + `chore/sync-<sha>` worktrees whose template SHA has been superseded on origin accumulate from interrupted cascade waves and silently block future pushes. The wheelhouse cascade auto-runs `socket-wheelhouse/scripts/cascade-tooling/cleanup-stranded.mts --target <repo>` at the start of every wave (default = fix; pass `--dry-run` to report only). Safety rails: cascade-subject regex match + trusted commit author + strict-ancestor proof of supersession + cascade-allowlist file check. Any ambiguity β bail the whole repo. Full algorithm + recovery instructions in [`docs/claude.md/fleet/stranded-cascades.md`](docs/claude.md/fleet/stranded-cascades.md).
143
+
136
144
### Never fork fleet-canonical files locally
137
145
138
146
π¨ Edit fleet-canonical files (anything in the sync manifest) ONLY in `socket-wheelhouse/template/...` β never in a downstream repo. Spot a missing helper in a downstream copy? Lift it upstream and re-cascade (enforced by `.claude/hooks/no-fleet-fork-guard/`; bypass: `Allow fleet-fork bypass`). Full canonical-surface list + lifting workflow: [`docs/claude.md/wheelhouse/no-local-fork-canonical.md`](docs/claude.md/wheelhouse/no-local-fork-canonical.md).
@@ -210,6 +218,8 @@ Use `isError` / `isErrnoException` / `errorMessage` / `errorStack` from `@socket
210
218
211
219
**Tokens belong in env vars (CI) or the OS keychain (dev local) β nowhere else.** Never in `.env` / `.env.local` / `.envrc` / `~/.sfw.config` / `~/.config/socket/*` / any dotfile. Dotfiles leak via accidental commits, file-indexers, backup clients, shell-history dumps. Initial setup: `node .claude/hooks/setup-security-tools/install.mts` (prompts + persists via macOS Keychain / Linux libsecret / Windows CredentialManager). **Rotation: `node .claude/hooks/setup-security-tools/install.mts --rotate`** β TTY-muted prompt, overwrites the keychain entry unconditionally, ignores stale dotfile / env-var lookup. This is the ONLY correct rotator. Suggesting any other path (`socket login`, hand-editing `~/.sfw.config`, `export SOCKET_API_TOKEN=β¦` in a shell rc) is a token-hygiene violation. The Stop-hook flags broken sfw shims, free-vs-enterprise edition drift, and 401-rejection patterns from the last assistant turn (enforced by `.claude/hooks/setup-security-tools/`, `.claude/hooks/no-token-in-dotenv-guard/`).
212
220
221
+
π¨ **Never call platform keychain CLIs directly from Bash to read a token.**`security find-generic-password` (macOS), `secret-tool lookup` (Linux), `Get-StoredCredential` (Windows PowerShell), `keyring get` (cross-platform) all surface a UI auth prompt on the user's screen β and that prompt fires _per call_, so a hook chain that reads the keychain three times costs three prompts. The token is already cached in process memory after the first resolution (see [`api-token.mts`](.claude/hooks/setup-security-tools/lib/api-token.mts) module-scope cache); read it from `findApiToken()` or `process.env.SOCKET_API_KEY` / `SOCKET_API_TOKEN` instead. Writes (`security add-generic-password`, `secret-tool store`, `New-StoredCredential`) and deletes are allowed β they happen during operator-driven setup / rotation, never on hot paths. Bypass: `Allow blind-keychain-read bypass` (enforced by `.claude/hooks/no-blind-keychain-read-guard/`).
222
+
213
223
**Socket API token env var** β fleet docs / workflow inputs / `.env.example` use the forward-canonical name `SOCKET_API_TOKEN`. For local-dev (keychain + `~/.zshenv`) the install hook stores under and exports `SOCKET_API_KEY` because it's universally supported across every Socket tool (CLI, SDK, sfw, fleet scripts) β one env var, no fallback chain. `SOCKET_API_TOKEN` is accepted as a secondary read; `SOCKET_SECURITY_API_TOKEN` / `SOCKET_SECURITY_API_KEY` remain accepted aliases for one cycle. Don't confuse any of these with `SOCKET_CLI_API_TOKEN` (socket-cli's separate setting).
214
224
215
225
Full spec (hook details, personal-path placeholders, cross-repo path references) in [`docs/claude.md/fleet/token-hygiene.md`](docs/claude.md/fleet/token-hygiene.md).
0 commit comments