CLAUDE.md · git:20261028.336afb5 · 2026-10-28 · sha256 ae8f993359980ce1
CLAUDE.md git:20261028.336afb5A
Immutable. This exact content never changes and is served at /api/v1/blob/ae8f993359980ce1.
# CLAUDE.md: sshlg-skills House rules for this repository. Global language, quality, autonomy and routing belong to the host's instruction files; do not duplicate them here. ## Start here Read [docs/HANDOFF.md](docs/HANDOFF.md) for the current entry and dated receipts. Apply [the standing repository handoff instruction](docs/working-rules/repository-handoff.md) to every task. Read [the retrospective's standing instructions](docs/evidence/retro.md#standing-instructions) in full before work (that section only, about 12 KB; query the run stamps below it with `grep`, never read them whole) and [coordination](docs/AGENT_SYNC.md) before editing a shared registry. [DOCMAP](docs/DOCMAP.md) owns single homes and propagation rules; [backlog](docs/evidence/backlog.md) owns outstanding work; [verification](docs/evidence/verification.md) owns delivery evidence. ## What this repo owns A zero-dependency Node launcher and the family members as pinned git submodules. [skills.json](skills.json) is the member inventory; each member owns its doctrine. The hub owns the routing block that writes into operator-owned instruction files. Those files may have no version control: every write must be recoverable. ## Gate and evidence ```bash npm test # structural validator and discovered test suites ``` DOCMAP's ratchets are computed by that run, never carried from another revision. `python3 test/check_pins.py` queries npm and stays outside the offline gate. Numbers are measured; named commands run and named files resolve. Evidence belongs to the checked artifact, and a historical receipt is not a current runtime claim. ## Invariants - **One channel per agent.** Plain `~/.claude/skills/<id>` copies shadow plugins and freeze their version. `install` and `update` prune them after every skills-CLI run. - **Live document addresses resolve.** `test/doc_refs.py` extracts and resolves; `test/validate.py` owns the live/dated corpus. Live dead commands and paths fail; dated records are counted and disclosed, not rewritten. Negative controls cover the claim classes and an empty corpus. Quote a dead command as dead, never runnable. - **Submodule URLs are HTTPS.** An SSH URL works for a key holder and fails for other installers. `test/validate.py` rejects it; CI has a negative self-test. - **The pin is the promise.** The committed member version, `skills.json`, submodule pointer and README table agree. A checkout installs the advertised version. - **The operator's wording wins.** `authored` entries outrank packaged text; `routers` reports drift. Only `--adopt` replaces wording, one router at a time, retaining what it replaced. - **Inspect executable input.** The hygiene guard's `executablePart()` removes non-shell heredoc bodies and whole-line comments, but retains shell heredocs and quoted invocations, including `bash -c`. Quoting must not bypass `bareName` checks. - **Guards decide in pure modules; hooks move bytes.** `lib/guard.js`, `lib/hygiene.js`, `lib/gitdiscard.js` and `lib/repogate.js` decide from payloads, fixtured without a `HOME`; filesystem access is confined to backup boundaries, and the one probe (`git status` for the paths a destructive git command names) is run by the hook, bounded, and fails open. A hook entry's `if` filter is best-effort and fails open on unparsed commands; do not rely on it. - **Hooks fail silent; refusals name a remedy.** A malformed payload must not break other sessions. `test/hooks_e2e_test.js` asserts both through real script processes. Claude Code 2.1.295 added `onFailure: "block"`; family hooks keep the default `continue` on purpose: adding `block` is not hardening, it breaks this rule. ## Writing to operator files Applies to `~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`, `~/.gemini/GEMINI.md`, `~/.pi/agent/AGENTS.md`, `~/.cursor/rules/sshlg-routing.mdc`, `~/.obsidian-wiki/config`, the B-206 targets in `lib/instruction-targets.js` (`~/.agents/AGENTS.md`, `~/.zcode/AGENTS.md`, `~/.qwen/QWEN.md`, Kiro steering, Windsurf `global_rules.md`), the `visibility` edits to `~/.claude/settings.json`, `~/.codex/config.toml`, `~/.gemini/settings.json`, `~/.pi/agent/settings.json`, `~/.config/opencode/opencode.json` and Hermes' config.yaml (written by `hermes config set`, after a copy), the machine marks `~/.sshlg-skills/pack-marks.json`, the hooks wiring in the Claude profile's `settings.json` (`$CLAUDE_CONFIG_DIR` or `~/.claude`) and in Codex's `hooks.json` (`apply.protectedWrite`: compare before replace, then `protect()`), including the post-tool-use restore. Copies are 0600 in a 0700 directory: host settings can hold keys. 1. `lib/backup.js` copies before every write; backup failure cancels the write. Every new write path goes through `protect()` in `lib/apply.js`. Restore is a write too; `test/hooks_e2e_test.js` covers it. No second write path. The bytes then land through `lib/atomicwrite.js` (temp file, flush, rename), never an in-place write; `test/apply_test.js` fails on a raw one (B-260). 2. Prove idempotence where repetition happens: run the real command three times against a real file and compare hashes, not just pure round-trip fixtures. 3. Preserve everything outside sentinels byte for byte. Previews show removals as well as additions. Incident narratives remain in the [pre-cleanup source](https://github.com/ssheleg/sshlg-skills/blob/a4c65581787b5ddcb3df1e36a8cae1c89c066479/CLAUDE.md). The [coverage record](docs/evidence/context-research/README.md) maps this compaction back to each rule; the retrospective itself is unchanged.