diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b08e683..7c0b613 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "claude-kit", - "version": "0.4.5", + "version": "0.4.6", "description": "Shareable Claude Code agent kit: orchestration, batch-dispatch, review, ADR-authoring, and memory/skill-hygiene skills plus critic/implementer/code-reviewer agents. PR-workflow hooks ship separately as claude-kit-hooks.", "author": { "name": "Tomohito YABU", diff --git a/.gitignore b/.gitignore index f4d58e7..e28156f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ memory/ settings.json settings.local.json settings*.json +# parked worktrees — otherwise `git ls-files --others` enumerates them as duplicate trees +.claude/worktrees/ # OS/editor noise .DS_Store __pycache__/ diff --git a/docs/claim-verification.md b/docs/claim-verification.md index 2101124..2996cf6 100644 --- a/docs/claim-verification.md +++ b/docs/claim-verification.md @@ -76,6 +76,24 @@ lowercase filename back in, the grep fires and the next editor picks a dispositi mechanism working, not a regression. **Any doc quoting that example inherits the same constraint**, this one included. +It still shipped with a blind spot, and the negative control is what missed it: the first form +recursed with `rg`, which skips hidden directories, so `.claude/**` — rules, skills, agents — went +unscanned, and the control sat at the repo root, inside the guard's existing reach, reddening +without testing the question. **Scope a control to the claim's habitat, not just its pattern.** + +The deeper error was the *file set*: a recursive grep answers "which files lie here", the rule asks +"which are repo-tracked", and the two diverge both ways — a tracked file under an ignored directory +is missed, never-committed scratch is falsely flagged. `--hidden` closes that instance and leaves +the class open; the fix was to enumerate with `git ls-files --cached --others --exclude-standard`, +as `scripts/scrub-check.sh` already did — two mechanisms answering the same question differently is +drift waiting to happen. **When a detector's file set is not the claim's file set, no flag fixes it.** + +It surfaced only when the detector ran against a repo it was not written in — the cheapest general +form of this check, since the authoring repo is where a self-referential detector is least able to +fail. The hit there was that repo's copy of the prose example, still spelling a concrete filename: +the constraint above reaches consumer mirrors, which must import the placeholder rewrite along with +the detector, or report their own rule file as a violation. Sequence and measurements: #30, #32. + One shape has no in-session probe at all: a rules file created mid-session never injects in that session, so verify it from fresh subagent probes against a positive control. Mechanism, scope limits and re-runnable probes: `~/.claude/kit-docs/code-review-path-scoped-rules.md`. diff --git a/rules/knowledge-layering.md b/rules/knowledge-layering.md index 0e18084..db8d30e 100644 --- a/rules/knowledge-layering.md +++ b/rules/knowledge-layering.md @@ -61,10 +61,12 @@ shared repo needs to carry itself. (`#N`, `ADR-NNN`). Memory refs are fine only in never-committed places (`~/.claude/CLAUDE.md`, this file, conversational scratch). -**Detect** — new code must not *add* hits (the *reframe* disposition below, not a "must return 0"): +**Detect** — new code must not *add* hits (the *reframe* disposition below, not a "must return 0"). +A recursive grep silently skips dot-dirs and tracked-but-ignored files — enumerate, don't recurse: ```sh -rg -n 'memory `[a-z_]+\.md`' --glob '!**/memory/**' --glob '!.git/**' +git ls-files -z --cached --others --exclude-standard \ + | xargs -0 grep -nHE 'memory `[a-z_]+\.md`' ``` ## Verify before you lock it