From 986bb4c368b1072a4671aecb16fa05b74ecac893 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Mon, 18 May 2026 01:28:47 -0500 Subject: docs(commits): check disk before declaring /review-code unavailable Step 1 told the agent to run /review-code but didn't say what to do when the skill exists on disk yet isn't in the session's available-skills list. The list covers plugin-installed skills only. User commands under ~/.claude/commands/ are routable as slash-commands but don't appear in it, so the agent could declare /review-code unavailable and fall through to the trivial-one-liner exception in Step 2. The new Discovery check tells the agent to verify both ~/.claude/commands/review-code.md and ./.claude/commands/review-code.md on disk before declaring the skill unavailable, and surface the mismatch rather than auto-skipping. Also drops three absorbed or stale inbox files: the skill-discovery handoff (signal absorbed by this edit), the missing-inbox-dir handoff (already resolved by 470085f), and a stale date-coverage scan output (deferred until the task-review habit lands). --- claude-rules/commits.md | 2 + ...f-from-dotemacs-review-code-skill-discovery.org | 118 --------------------- ...ff-from-dotemacs-rulesets-missing-inbox-dir.org | 75 ------------- inbox/lint-followups.org | 30 ------ 4 files changed, 2 insertions(+), 223 deletions(-) delete mode 100644 inbox/2026-05-16-handoff-from-dotemacs-review-code-skill-discovery.org delete mode 100644 inbox/2026-05-16-handoff-from-dotemacs-rulesets-missing-inbox-dir.org delete mode 100644 inbox/lint-followups.org diff --git a/claude-rules/commits.md b/claude-rules/commits.md index 9e1a8e0..41d17e7 100644 --- a/claude-rules/commits.md +++ b/claude-rules/commits.md @@ -272,6 +272,8 @@ Run the `review-code` skill against the change: - Before a PR: `/review-code` (branch diff against `main` merge-base) - Before commenting on someone else's PR: `/review-code ` +**Discovery check.** If `/review-code` doesn't appear in the session's available-skills list, check `~/.claude/commands/review-code.md` and `./.claude/commands/review-code.md` on disk before declaring it unavailable. The available-skills enumeration covers plugin-installed skills but can miss user commands under `~/.claude/commands/`, which are still routable as slash-commands. If either file exists, surface the discrepancy to the user before falling through to the trivial-one-liner exception in Step 2 — don't auto-skip. + Surface **all** findings to the user: Critical, Important, and Minor. **Default block:** any Critical or Important finding stops the flow. Fix the diff --git a/inbox/2026-05-16-handoff-from-dotemacs-review-code-skill-discovery.org b/inbox/2026-05-16-handoff-from-dotemacs-review-code-skill-discovery.org deleted file mode 100644 index ae832b0..0000000 --- a/inbox/2026-05-16-handoff-from-dotemacs-review-code-skill-discovery.org +++ /dev/null @@ -1,118 +0,0 @@ -#+TITLE: Handoff: =/review-code= skill missing from session menu -#+FROM: dotemacs (~/.emacs.d) -#+DATE: 2026-05-16 - -* Context - -During a =/start-work= invocation in =~/.emacs.d= on 2026-05-15, Phase 7 -(Review-and-Publish handoff) called for =/review-code --staged= before -the commit. I declared the skill unavailable based on the session's -available-skills system-reminder list and proceeded under the -trivial-one-liner exception in =commits.md=. - -After the commit landed and the chore-close followed, Craig asked: "what -did you do that you couldn't see it?" - -* What I missed - -Checking the filesystem after the fact: - -- =/home/cjennings/.claude/commands/review-code.md= exists. -- =/home/cjennings/code/rulesets/.claude/commands/review-code.md= is the - canonical source. -- =/home/cjennings/.claude/commands/start-work.md= also exists — and - =/start-work= is the workflow I just executed. - -So =/review-code= is on disk and routable as a slash-command. The -session's available-skills system-reminder list contained only the -plugin-installed skills (=pairwise-tests=, =root-cause-trace=, =voice=, -=debug=, =init=, =review=, =security-review=, etc.) — not Craig's custom -commands at =~/.claude/commands/=. - -I treated the available-skills list as authoritative. I never ran =ls -~/.claude/commands/= to verify. - -* The rule that produced the dead end - -Claude Code's session instructions say: - -#+begin_quote -Only invoke a skill that appears in that list, or one the user explicitly -typed as / in their message. Never guess or invent a skill name -from training data. -#+end_quote - -That rule is correct for preventing hallucinated skill calls. But it -produces a false negative for custom commands at =~/.claude/commands/= -that are routable via slash-command but absent from the session-time -available-skills enumeration. The instruction has no opt-in for "verify -against filesystem before declaring unavailable." - -The "user explicitly typed =/=" branch is also a near-miss: Craig -typed =/start-work=, which routed correctly because it was loaded -inline. =/start-work='s workflow body referenced =/review-code= as part -of Phase 7. The "user typed it" rule reads strictly — Craig didn't type -=/review-code= himself — so I treated the workflow-internal reference as -not user-explicit and skipped invocation. - -The trivial-one-liner exception in =commits.md= happened to give me an -honest off-ramp ("dictated subject, skip draft-file + voice"), so I took -it without surfacing the discrepancy as the actual blocker. - -* Narrow failure - -I noted the discrepancy in chat ("=/review-code= isn't in the available -skills here") and moved on without verifying against the filesystem. One -=ls ~/.claude/commands/= would have surfaced the file. I had Bash; I -just didn't think to use it. - -* Proposed adjustments - -Two angles, each tractable on the rulesets side: - -1. *Tighten the "skip =/review-code=" off-ramp in =commits.md=.* Step 1 - today says: "Run =/review-code --staged= before each commit, or - =/review-code= on the whole branch before the PR. Block on Critical - or Important findings." Add a sub-step: "If =/review-code= isn't in - the session's available-skills list, check - =~/.claude/commands/review-code.md= and - =./.claude/commands/review-code.md= on disk; if the file exists, - surface the discrepancy to the user before deciding to skip — don't - auto-skip via the trivial-one-liner exception." - -2. *Reconsider how =~/.claude/commands/= surfaces in available-skills.* - Out of scope for the rulesets repo itself, but worth flagging. - Claude Code's session-init lists plugin skills as "available" but - not user commands. The plugin/rules layer can't change Claude Code's - behavior. The workaround in #1 only helps once the agent thinks to - check. Trip-wire phrasing: "if the skill isn't in the list, ls before - declaring missing." - -* What I'd do differently - -A one-line check before declaring any =/= unavailable: - -#+begin_src bash -ls ~/.claude/commands/.md -ls ./.claude/commands/.md -#+end_src - -If either exists: read it and run inline, or surface the discrepancy. - -* Outcome of the dotemacs session - -Original task shipped clean: - -- =3b4c8d8 fix(ai-config): Ensure gptel-magit is installed via use-package= -- =26572be chore(todo): close transient-setup gptel-magit fix= - -The =/review-code= skip didn't hurt anything (trivial 2-line org-keyword -change). The /reasoning/ I used to skip was wrong — I assumed the skill -didn't exist, when it did. - -* Filing - -Rule/workflow-improvement signal, not a code bug. Belongs in rulesets's -=todo.org= as a tracked task if it warrants one, or in =notes.org= / -relevant rule file as a reminder. The narrow ask: add a "check disk -before declaring skill unavailable" line to =commits.md= Step 1. diff --git a/inbox/2026-05-16-handoff-from-dotemacs-rulesets-missing-inbox-dir.org b/inbox/2026-05-16-handoff-from-dotemacs-rulesets-missing-inbox-dir.org deleted file mode 100644 index 5f1e0ea..0000000 --- a/inbox/2026-05-16-handoff-from-dotemacs-rulesets-missing-inbox-dir.org +++ /dev/null @@ -1,75 +0,0 @@ -#+TITLE: Handoff: rulesets has no top-level =inbox/= directory -#+FROM: dotemacs (~/.emacs.d) -#+DATE: 2026-05-16 - -* Context - -While trying to deliver a cross-project handoff from the dotemacs session -(~/.emacs.d) to the rulesets project, I discovered that -=~/code/rulesets/= has no top-level =inbox/= directory. - -The =inbox-send.py= script (the canonical mechanism documented in -=claude-rules/cross-project.md=) requires the target project to have -*both* =.ai/= AND =inbox/=: - -#+begin_src python -def is_project(path: Path) -> bool: - """A project has a `.ai/` marker AND a top-level `inbox/` directory.""" - return (path / ".ai").is_dir() and (path / "inbox").is_dir() -#+end_src - -(=.ai/scripts/inbox-send.py:61-62=) - -So =inbox-send.py --list= did not list =rulesets= as an available target, -even though it has =.ai/=. I worked around this by: - -1. =mkdir -p ~/code/rulesets/inbox/= -2. =Write= the handoff file directly to that new directory. - -This handoff file landed at: -=~/code/rulesets/inbox/2026-05-16-handoff-from-dotemacs-rulesets-missing-inbox-dir.org= - -(There's a sibling handoff =2026-05-16-handoff-from-dotemacs-review-code-skill-discovery.org= -also in this inbox from the same session.) - -* What's missing - -- =~/code/rulesets/inbox/= didn't exist before this session. -- The directory is not gitignored (per the project's =.gitignore=). -- No prior commits reference =inbox/= except for the =inbox-send.py= - script itself. - -* Why this matters - -The rulesets project is an active Claude-managed project — it has -=.ai/protocols.org=, =.ai/sessions/=, a startup workflow, and its own -=todo.org=. Without an =inbox/= dir: - -- Cross-project handoffs from other projects can't land via the canonical - =inbox-send= mechanism. -- The rulesets startup workflow has no inbox-processing step that would - pick up cross-project messages on session start. -- I had to bypass =inbox-send.py= and =Write= directly, which skips - filename auto-derivation and source-project provenance handling. - -The =claude-templates/= subdir inside rulesets also has =.ai/= but no -=inbox/=, with the same effect. - -* What to fix - -Two changes, low effort: - -1. *Create =~/code/rulesets/inbox/= and commit it.* Add a =.gitkeep= or - a README so the directory exists in the tree from the start. Once it - exists, =inbox-send.py --list= will discover the project and future - cross-project handoffs will route normally. - -2. *(Optional) Same for =~/code/rulesets/claude-templates/inbox/=.* If - claude-templates is considered its own routable project rather than a - subdir-only artifact, mirror the change there. - -* Filing - -This is project-hygiene signal — track in =todo.org= as a single quick -fix (S effort, single =mkdir= + =.gitkeep= + commit), and the -=inbox-send.py= discovery starts working automatically. diff --git a/inbox/lint-followups.org b/inbox/lint-followups.org deleted file mode 100644 index 6fb4c0d..0000000 --- a/inbox/lint-followups.org +++ /dev/null @@ -1,30 +0,0 @@ - -* 2026-05-16 lint-org follow-ups — todo.org -** TODO line 2153 — misplaced-heading — Possibly misplaced heading line - -* 2026-05-16 Sat — Date coverage: [#A] / [#B] tasks without DEADLINE or SCHEDULED -Review each: add a date, drop the priority, or confirm 'no-date by intent' inline. -- 10: ** TODO [#A] Implement task-review daily-habit per spec -- 28: ** DOING [#A] Check that memories are sync'd across machines via git.m -- 58: ** TODO [#A] Build =create-documentation= skill for high-quality project/product docs -- 692: ** TODO [#A] Review pass: tighten skills and rulesets after 2026-05-04 audit -- 1221: ** TODO [#B] Build =ov-1= skill for DoDAF OV-1 (High-Level Operational Concept Graphic) -- 1295: ** TODO [#A] Build =/update-skills= skill for keeping forks in sync with upstream -- 1621: ** TODO [#B] Add =make remove= for interactive ruleset removal via fzf -- 1686: ** TODO [#B] Document the =mcp/= install pipeline in =mcp/README.org= -- 1773: ** TODO [#B] Phase A startup blind to =claude-templates/inbox/= post-fold :bug:fold: - -* 2026-05-17 lint-org follow-ups — todo.org -** TODO line 2153 — misplaced-heading — Possibly misplaced heading line - -* 2026-05-17 Sun — Date coverage: [#A] / [#B] tasks without DEADLINE or SCHEDULED -Review each: add a date, drop the priority, or confirm 'no-date by intent' inline. -- 10: ** TODO [#A] Implement task-review daily-habit per spec -- 28: ** DOING [#A] Check that memories are sync'd across machines via git.m -- 58: ** TODO [#A] Build =create-documentation= skill for high-quality project/product docs -- 692: ** TODO [#A] Review pass: tighten skills and rulesets after 2026-05-04 audit -- 1221: ** TODO [#B] Build =ov-1= skill for DoDAF OV-1 (High-Level Operational Concept Graphic) -- 1295: ** TODO [#A] Build =/update-skills= skill for keeping forks in sync with upstream -- 1621: ** TODO [#B] Add =make remove= for interactive ruleset removal via fzf -- 1686: ** TODO [#B] Document the =mcp/= install pipeline in =mcp/README.org= -- 1773: ** TODO [#B] Phase A startup blind to =claude-templates/inbox/= post-fold :bug:fold: -- cgit v1.2.3