Current harness — skills, rules, hooks, CLAUDE.md (audit Jun 30 2026)
Investigation, report-only (investigator skill). Generated 2026-06-30. Leads: memory_palace/summaries/2026-06-30-palace-measurement-and-dedup.md, tasks/TASK_BOARD.md, prior audit session af18b5f9.
Answer first
- One file wires every live hook:
Code/.claude/settings.json.Inspection/.claudehas 8 hook files but no settings.json → all 8 are inert (present, bound to nothing).Docs/.claudehas no hooks at all. A hook existing on disk does not mean it fires. - Not one duplicated skill or rule is byte-identical — every cross-tree copy has drifted. Same name, different behavior. Only two inert hooks (
ast-grep-nudge,firecrawl-nudge) are still identical. Drifted duplication is worse than plain duplication: a subagent or anInspection/Docs-rooted session silently loads a different skill than the one tested inCode. - The sim-runner debug hole is a path-frame mismatch. Every relative path in
sim-runner(.claude/rules/MEASUREMENT.md,analysis/data_analyzer.py,analysis/dispatch.py,YAMLs_by_domain/metrics.yaml) isInspection-relative, but the skill lives inCode/.claude/skillsand the session launches fromCode/. From theCoderoot they are all off by the missingInspection/prefix. - Compounding it:
MEASUREMENT.mdis path-scoped tovalidation/**/*.py+GNC/**/*.py. sim-runner’s measure/collect steps often touch neither (reading a log, editing atmp_YAML), so its “REQUIRED READING” never auto-loads — and through a subagent it never propagates (Inspection/CLAUDE.mddocuments this as a known open gap). Code/.claude/rules/is empty. The active project tree carries zero rules; all 9 rules live in the two path-scoped subtrees (Inspection5,Docs4), reachable only when you touch a matching path.- Non-finding (do not delete):
koans.py. It is unwired in settings because it is a shared library (from koans import koan) imported by four hooks, not an event hook.
Scope and the load model
“Loaded” depends on where a .claude tree sits relative to the session. Four scopes:
| Scope | Tree | When it loads |
|---|---|---|
| 🌐 Global | ~/.claude | Every session, always. CLAUDE.md + settings (permissions/plugins/sandbox). No rules, no hooks. |
| 🟢 Active project | Code/.claude | This session (cwd = Code/). The only tree whose hooks are wired. |
| 🟡 Path-scoped | Inspection/.claude, Docs/.claude | Rules + nested CLAUDE.md attach only when a tool touches a file matching the rule’s paths: glob. Subagents do not propagate them back up. |
| 💀 Inert | Inspection/.claude/hooks/* | On disk but bound to nothing (no settings.json wires them). |
Legend below: 🟢 active · 🌐 global · 🟡 path-scoped · 💀 inert · ⚠️ duplicated and drifted · 🎯 sim-runner focal.
The mind map
mindmap root((Harness<br/>4 .claude trees)) 🌐 HOME ~/.claude Global CLAUDE.md settings.json perms+plugins+sandbox no rules · no hooks Skills 7 caveman theme-factory firecrawl-research-papers obsidian-clipper-template-creator plannotator-annotate plannotator-last plannotator-review 🟢 CODE active project Project CLAUDE.md settings.json wires 9 hooks settings.local.json firecrawl-redirect rules EMPTY Hooks 9 live allow-read-only preflight_guard plotting-guard ast-grep-nudge firecrawl-nudge wiki_yq_nudge board_hygiene_stop reflow_md comms_nudge koans lib not a hook Skills 23 sim-runner 🎯 root-cause-analysis investigator ⚠️ loading-yamls ⚠️ validation-purge ⚠️ long-form-math ⚠️ grill-me handoff mempalace-capture checkin planning-with-files writing-great-skills mermaid ast-grep drawio firecrawl marp-magic matplotlib plotly pandas-to-latex obsidian-bases obsidian-markdown sympy 🟡 INSPECTION path-scoped CLAUDE.md orchestrator-invariants NO settings → hooks INERT 💀 allow-read-only 💀 preflight_guard 💀 plotting-guard 💀 ast-grep-nudge 💀 firecrawl-nudge 💀 check_board 💀 check_ongoing 💀 palace_capture 💀 Rules 5 MEASUREMENT 🎯 GNC ANALYSIS VALIDATION PYTHON ⚠️ Skills 9 log-driver note-taking searching-research-wiki investigator ⚠️ loading-yamls ⚠️ validation-purge ⚠️ wiki-docs ⚠️ wiki-ingest ⚠️ wiki-lint ⚠️ 🟡 DOCS path-scoped Project CLAUDE.md NO settings · NO hooks env-contract + hookify rules Rules 4 WIKI BULLETIN LATEX PYTHON ⚠️ Skills 10 arxiv-lookup research-assistant insight-guru tex-report-writing tikz-artist long-form-math ⚠️ wiki-docs ⚠️ wiki-ingest ⚠️ wiki-lint ⚠️ wiki-tidy
Full inventory
Skills (49 files across 4 trees)
| Skill | 🌐 ~ | 🟢 Code | 🟡 Inspection | 🟡 Docs | Status |
|---|---|---|---|---|---|
| investigator | ✓ | ✓ | ⚠️ drifted — Inspection adds disable-model-invocation:true + local MERMAID.md; Code says “use the mermaid skill” | ||
| loading-yamls | ✓ | ✓ | ⚠️ drifted | ||
| validation-purge | ✓ | ✓ | ⚠️ drifted | ||
| long-form-math | ✓ | ✓ | ⚠️ drifted | ||
| wiki-docs | ✓ | ✓ | ⚠️ drifted | ||
| wiki-ingest | ✓ | ✓ | ⚠️ drifted | ||
| wiki-lint | ✓ | ✓ | ⚠️ drifted | ||
| sim-runner | ✓ | 🎯 Code-only; Inspection-relative paths (see Findings) | |||
| checkin | ✓ | twin of log-driver (board item) | |||
| log-driver | ✓ | twin of checkin (board item) | |||
| wiki-tidy | ✓ | Docs-only; vault-relocation suspect | |||
| root-cause-analysis, grill-me, handoff, mempalace-capture, planning-with-files, writing-great-skills, mermaid, ast-grep, drawio, firecrawl, marp-magic, matplotlib, plotly, pandas-to-latex, obsidian-bases, obsidian-markdown, sympy | ✓ | unique to Code | |||
| note-taking, searching-research-wiki | ✓ | unique to Inspection | |||
| arxiv-lookup, research-assistant, insight-guru, tex-report-writing, tikz-artist | ✓ | unique to Docs | |||
| caveman, theme-factory, firecrawl-research-papers, obsidian-clipper-template-creator, plannotator-annotate/last/review | ✓ | global |
Rules (9 files — Code/.claude/rules is empty)
| Rule | Tree | paths: scope | Note |
|---|---|---|---|
| MEASUREMENT.md | Inspection | validation/**, GNC/** | 🎯 measurement contract; sim-runner’s required reading |
| GNC.md | Inspection | GNC/**/*.py | guidance/control orientation |
| ANALYSIS.md | Inspection | analysis/*.py | |
| VALIDATION.md | Inspection | validation/*.py | |
| PYTHON.md | Inspection | every *.py | ⚠️ drifted vs Docs PYTHON.md |
| WIKI.md | Docs | wiki paths | vault-relocation suspect (board) |
| BULLETIN.md | Docs | board lifecycle | |
| LATEX.md | Docs | LaTeX | |
| PYTHON.md | Docs | *.py | ⚠️ drifted vs Inspection PYTHON.md (likely different env — verify before merging) |
Hooks (wiring = Code/.claude/settings.json only)
| Hook | 🟢 Code (wired) | 🟡 Inspection (inert) | Cross-tree state |
|---|---|---|---|
| allow-read-only.py | PreToolUse Bash | 💀 | drifted |
| preflight_guard.py | PreToolUse Write/Edit | 💀 | drifted |
| plotting-guard.py | PreToolUse Write/Edit | 💀 | drifted |
| ast-grep-nudge.py | PreToolUse Bash/Grep | 💀 | identical |
| firecrawl-nudge.py | PreToolUse WebFetch/Search | 💀 | identical |
| wiki_yq_nudge.py | PreToolUse Bash | — | Code-only |
| board_hygiene_stop.py | Stop | — | Code-only |
| reflow_md.py | PostToolUse Write/Edit | — | Code-only |
| comms_nudge.py | UserPromptSubmit | — | Code-only |
| koans.py | library (imported by 4 hooks) | — | not an event hook — keep |
| check_board.py | — | 💀 | Inspection-only, now dead |
| check_ongoing.py | — | 💀 | Inspection-only, now dead |
| palace_capture.sh | — | 💀 | Inspection-only, now dead |
settings.local.json (Code) adds the WebFetch→deny firecrawl-redirect hook and the Edit/Write(**) allow. ~/.claude/settings.json carries no hooks block.
CLAUDE.md (8 files)
~/.claude (global advisor) · Code (project) · Inspection (orchestrator-invariants + path-scope map) · Docs (project) · Inspection/notes, Code/notes, vault, vault/research (scoped flavor notes) · Inspection/junk_drawer_june (stale, in a junk dir).
Findings
F1 — sim-runner paths are Inspection-relative but the skill lives in Code and launches from Code. Evidence: Code/.claude/skills/sim-runner/SKILL.md:8,10,12,78 reference .claude/rules/MEASUREMENT.md; :10,39 reference analysis/data_analyzer.py; :49,63,80 reference analysis/cluster.yaml/dispatch.py/YAMLs_by_domain/metrics.yaml. Code/.claude/rules/ is empty; the real files are under Inspection/. Impact: a fresh agent following sim-runner literally from the Code root hits dead paths — the “very easy to do” required-reading step fails. Decision (Jun 30): keep sim-runner in Code (stays globally invocable); add a one-line “paths relative to Inspection/” header and an explicit “read Inspection/.claude/rules/MEASUREMENT.md first” step (resolves F1+F2 together). Logged on TASK_BOARD.md Parked.
F2 — MEASUREMENT.md is path-scoped and won’t auto-load for most sim-runner work. Evidence: Inspection/.claude/rules/MEASUREMENT.md:2-6 → paths: validation/**/*.py, GNC/**/*.py. Inspection/CLAUDE.md “Orchestrator invariants”: scoped rules load only on direct touch of a matching file and “subagents do not propagate rules back up.” Impact: collecting/measuring a run (touching logs or a tmp_ YAML) never triggers the contract; sim-runner asserts it is loaded when it is not. Next step: sim-runner should instruct the agent to read Inspection/.claude/rules/MEASUREMENT.md explicitly at the start of any measure/collect step (the Inspection/CLAUDE.md preload pattern), not rely on path-scoped auto-load.
F3 — Every cross-tree duplicate skill/rule has drifted. Evidence: diff Jun 30 — investigator (3 hunks incl. disable-model-invocation), loading-yamls, validation-purge, long-form-math, wiki-docs, wiki-ingest, wiki-lint, PYTHON.md all report “differ”; only hooks ast-grep-nudge/firecrawl-nudge identical. Impact: behavior depends on which tree the agent is rooted in — the staleness engine. Next step: this is the board’s “skill/rule cross-tree dedup” item; pick a canonical tree per skill, collapse, never one-side-patch. (PYTHON.md may be legitimately env-specific — verify before merging.)
F4 — All 8 Inspection hooks are inert (no settings.json). Evidence: ls Inspection/.claude/ shows no settings file; find for settings*.json returns only ~ and Code. Impact: 5 are dead duplicates of live Code hooks; 3 (check_board, check_ongoing, palace_capture.sh) are Inspection-only logic now superseded by Code’s board_hygiene_stop.py/palace. They mislead anyone who reads the tree expecting them to fire. Next step: delete the 5 duplicates; decide whether check_board/check_ongoing/palace_capture carry unique logic worth porting to a wired Code hook, else delete.
F5 — koans.py is a shared library, not an orphan hook. Keep it. Evidence: grep koans → preflight_guard.py:23, allow-read-only.py:33, comms_nudge.py:10, plotting-guard.py:24 all from koans import …. Impact: none — recorded so a future dedup pass does not flag it for deletion on “unwired” grounds.
F6 — Docs wiki tooling vs the vault relocation (already on board). Docs/.claude still carries WIKI.md/BULLETIN.md + wiki-docs/wiki-ingest/wiki-lint/wiki-tidy, but the research wiki was retired/relocated to vault. Verify these don’t operate on a moved target.
Proposed next tasks
New (not yet on the board):
- Re-root sim-runner (F1+F2). Decide host tree + path convention, and add the explicit MEASUREMENT.md preload step. This is the headline “debug sim-runner” fix.
- Delete the 5 inert duplicate
Inspectionhooks (F4); triagecheck_board/check_ongoing/palace_capturefor unique logic first. - Drop
Inspection/junk_drawer_june/CLAUDE.md(stale CLAUDE.md in a junk dir).
Already parked on tasks/TASK_BOARD.md — this audit adds the drift evidence (F3), don’t re-log:
- Skill/rule cross-tree dedup (canonical-tree pick, collapse the 8 drifted pairs).
checkin↔log-drivertwin merge.Docswiki tooling vs vault relocation (F6).