diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-02 05:19:01 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-02 05:19:01 -0400 |
| commit | b6a977cec25fddf1e498896cec3ad9462fc149db (patch) | |
| tree | 9bbd5a1ac2609c9d1b4cba719360fa7e319db85f /.ai | |
| parent | 78bbaae5d8634d52588c1a60d7b7f430bed238c7 (diff) | |
| download | rulesets-b6a977cec25fddf1e498896cec3ad9462fc149db.tar.gz rulesets-b6a977cec25fddf1e498896cec3ad9462fc149db.zip | |
feat(rules): add the host-identity guard rule and startup probe
A tracked or synced doc asserting "this machine is X" is false on every machine but its origin, and an agent trusting it reasons backwards all session. It happened live: a stale "ratio" claim steered a session running on velox. The new rule bans fixed identity claims in tracked/synced docs and requires the runtime derivation instead (uname -n, since the hostname binary is often absent). Describing the fleet stays legal. Claiming the current member doesn't.
startup gained a read-only probe that greps CLAUDE.md and notes.org for the pattern and surfaces hits as a judgment flag, never a block. Fixture-verified under bash and zsh.
Diffstat (limited to '.ai')
| -rw-r--r-- | .ai/workflows/startup.org | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/.ai/workflows/startup.org b/.ai/workflows/startup.org index 9488dd0..943bbea 100644 --- a/.ai/workflows/startup.org +++ b/.ai/workflows/startup.org @@ -176,6 +176,15 @@ These calls have no dependencies on each other. Issue them all together in one m The stray-root check uses =find= rather than a glob so the probe behaves identically under bash and zsh (=compgen= is bash-only, and zsh aborts on an unmatched glob). +13. Host-identity probe (see the host-identity rule in =claude-rules/=). Read-only; flags fixed machine-identity claims in the project's tracked/synced docs — the "This machine is ratio" trap, false on every machine but the one that wrote it. Silent when nothing matches. + + #+begin_src bash + grep -inE '\b(this|the current) (machine|host|box|laptop|workstation) is ' \ + CLAUDE.md .ai/notes.org 2>/dev/null | head -3 || true + #+end_src + + Fleet descriptions ("the fleet is ratio and velox") and runtime derivations ("run =uname -n= to find the hostname") don't match — only current-identity assertions do. Fixture-verified under bash and zsh. + Notes on the rsync commands: - Trailing slashes on both source and destination matter — they tell rsync to sync /contents/ rather than nest a directory inside. - =--delete= on the directory syncs lets retired template files actually disappear from each project on next startup. @@ -210,6 +219,7 @@ This phase touches the user and runs sequentially: - *KB consult nudge (read side).* If the Phase A KB-surface prep returned any =kb-relevant-titles=, surface one line listing them (capped 5): "KB lessons that may be relevant: =<title>=; =<title>=… — open the node before related work." The titles are declarative, so the list alone tells you whether to open one. Gated on the roam clone; silent when the clone is absent or nothing relevant surfaced. See the best-practices node and =knowledge-base.md=. - *KB contribute nudge (write side).* Once per session, surface one line pointing at the best-practices node (the =kb-bestpractices= path from Phase A): "Learned something durable? See =<path>= for how to write a KB node — contributing cross-project facts is welcome (personal projects only; work/unknown projects never write per =knowledge-base.md=)." Light encouragement, never a gate. Gated on the roam clone; silent when absent. - *Spec-sort nudge.* If the Phase A spec-sort probe printed =spec-sort: unsorted docs present=, surface one line: "this project's docs pile has never been spec-sorted — say 'run spec-sort' to sort it." If the probe was silent, say nothing. A project with nothing to sort never sees the line; a stamped =:LAST_SPEC_SORT:= marker permanently clears it. See the docs-lifecycle rule and the spec in =docs/specs/=. + - *Host-identity flag.* If the Phase A host-identity probe printed any match, surface it with the file:line and the fix: "this doc asserts a fixed machine identity — false on every other machine; replace with a runtime derivation (run =uname -n=), per the host-identity rule." The probe flags for judgment, never blocks. Silent when the probe is silent. - *Language-bundle sync.* If the Phase A step-12 call (=sync-language-bundle.sh=) printed anything, surface it. =fixed= lines are informational — the drift was already repaired (note that =.claude/= is now dirty if the project commits it). A =drift= line on =settings.json= is surface-only and needs the printed =make install-<lang> PROJECT=.= to reconcile; flag it so the user can decide. If the call was silent, say nothing. - *Newly-installed symlinks.* If the Phase A.0 =make install= step printed any =link= / =relink= / =WARN= line, surface it. A =link= line means a skill, rule, hook, or script added to rulesets is now linked into =~/.claude= for the first time on this machine. For a newly-linked *skill*, check the agent's available-skills list: if the harness already registered it mid-session, note it's available and move on; if it's absent, stop and tell Craig to restart the agent so it loads (whether a mid-session reload works is harness-version-dependent). For a newly-linked *hook*, note that the harness reads hooks at session start — it fires from the next session (or after Craig opens =/hooks= once); its settings.json wiring travels with the tracked file, so the link is usually the only missing piece. A =WARN ... not a symlink= line is a real collision at the target path — surface it; it needs a human. If the step printed only "nothing new to link", say nothing. - *Template-sync churn (safety net).* Check whether Phase A's rsync left uncommitted churn in the synced =.ai/= paths — accumulated from a prior session that crashed before wrap-up, or freshly added this session when rulesets advanced. Without surfacing, it builds up silently until it blocks Phase A.0's auto-ff (git won't ff a dirty tree). Skip in the rulesets repo itself (there =.ai/= is a committed mirror, kept honest by the pre-commit hook). The check is sequential here, after the rsync has finished — not a Phase A step, to keep that batch race-free. |
