claudemd-cli 0.9.21 → 0.9.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,24 @@ All notable changes to the `claudemd` plugin. This changelog tracks plugin artif
8
8
  - **Canonical spec version source**: `spec/CLAUDE.md` top-line title (`# AI-CODING-SPEC vX.Y.Z — Core`) + `spec/CLAUDE-changelog.md` top `##` entry.
9
9
  - **Plugin semver vs spec semver** are independent: plugin patch (0.2.0 → 0.2.1) may ship when spec is unchanged (this release); plugin minor (0.1.9 → 0.2.0) ships when spec minor updates (v0.2.0 shipped spec v6.10.0).
10
10
 
11
+ ## [0.9.22] - 2026-05-10
12
+
13
+ **Patch — `claudemd-doctor` now detects production-hook drift between source-of-truth and `~/.claude/plugins/marketplaces/claudemd/`.** Spec v6.11.7 → v6.11.8 (clarity-only wording fixes; see `spec/CLAUDE-changelog.md` v6.11.8 entry — `[fix]` §10 four-section "Lead with incomplete" disambiguation, `[fix]` §7 L2 evidence example annotated with absolute delta).
14
+
15
+ Surfaced during a dogfood pass simulating fresh-user spec adherence. Symptom: `~/.claude/logs/claudemd.jsonl` simultaneously holding two project encodings for the same cwd `/mnt/data_ssd/dev/projects/claudemd` — `-mnt-data-ssd-...` (post-v0.9.15 `tr '/._' '-'`, 46 entries) and `-mnt-data_ssd-...` (pre-v0.9.15 `tr '/.' '-'`, 196 entries). Root cause: source repo at v0.9.21 but `~/.claude/plugins/marketplaces/claudemd/.claude-plugin/plugin.json` reported v0.9.11 with three hook scripts (`hooks/lib/rule-hits.sh`, `hooks/memory-read-check.sh`, `hooks/session-summary.sh`) still on pre-fix code. `/plugin update` is a silent no-op in current Claude Code versions (memory: `reference_plugin_update_manual_refresh.md`), so the canonical refresh path is `uninstall → install → /reload-plugins` — but nothing flagged that the user *needed* to do this. Concretely: the §11-memory-read HARD rule was a silent no-op for any project with `_` in its cwd path, even after the v0.9.15 fix shipped, because the running hook code was older than the source. The prior `spec-hash` doctor check only compared the spec MD files; hook scripts had no drift signal.
16
+
17
+ ### Added
18
+
19
+ - `[feat]` **`scripts/lib/install-drift.js#compareHooks(sourceRoot, marketRoot)`** — recursively SHA-256-compares every `.sh` under `hooks/` between two roots. Returns `{skipped, skippedReason?, driftCount, diffs[]}`. Skip cases (not flagged as drift): `self-compare` (sourceRoot ≡ marketRoot by realpath, e.g. `/claudemd-doctor` running FROM the marketplace install), `market-root-missing` (no marketplace install on this machine), `no-hooks-in-source` (claudemd-cli npm package ships only `bin/`, no hooks). `.patterns` / `.json` configs deliberately excluded — that drift is `/claudemd-update` territory, not hook-CODE drift.
20
+ - `[feat]` **`hook-drift` check in `scripts/doctor.js`** — wires `compareHooks` into the doctor pipeline. Detail format on drift: `<N> hook script(s) differ between source and <marketRoot>: <first-3 file paths with reason> +<remaining> more. Likely cause: /plugin update is a silent no-op. Fix: /plugin uninstall claudemd@claudemd then /plugin install claudemd@claudemd, then /reload-plugins.` On the dogfood machine, this surfaces the exact 3-file drift (`hooks/lib/rule-hits.sh`, `hooks/memory-read-check.sh`, `hooks/session-summary.sh`) with the canonical fix command in the message.
21
+ - `[feat]` **`marketplacePluginRoot()` helper in `scripts/lib/paths.js`** — returns `~/.claude/plugins/marketplaces/claudemd`. Decoupled from `pluginCacheDir()` because the cache vs marketplaces directories can drift (cache holds per-version snapshots; marketplaces is the single live plugin root Claude Code resolves `${CLAUDE_PLUGIN_ROOT}` to at hook-fire time).
22
+ - `[test]` **8 new cases in `tests/scripts/install-drift.test.js`** — equal-content baseline, file-content-differs, file-missing-in-market, self-compare skip, market-missing skip, no-hooks-in-source skip, recursive scan into `hooks/lib/`, non-`.sh` files ignored.
23
+ - `[test]` **2 new cases in `tests/scripts/doctor.test.js`** — `hook-drift skips when no marketplace install exists` (fresh-install / npm-CLI-only does not fail-loudly) + `hook-drift flags differing hooks when marketplace install lags source` (mirrors the real source `hooks/` into a tmp marketplace and breaks one file to assert the drift surfaces with file path + remediation in the detail).
24
+
25
+ ### Why no L3 / pre-ship-review chain
26
+
27
+ `feat:` adds an additive doctor check + spec wording-only fixes. Per spec §2 hard-upgrade exclusion: spec wording fixes restoring documented intent are L2 max (the `[fix]` CHANGELOG framing). Doctor check is L2 (additive feature, multi-file with tests, no API change). No spec semantic change. Diff: 1 new lib (~80 LOC), 1 new lib helper (~5 LOC), 1 doctor branch (~20 LOC), 1 new test file (~110 LOC), 2 new doctor test cases (~30 LOC), spec wording shifts in `spec/CLAUDE.md` lines 180 + 238, version bumps across 3 manifests + spec headers + `hard-rules.json#spec_version`. Test count: 271 → 281 (+10 JS cases).
28
+
11
29
  ## [0.9.21] - 2026-05-10
12
30
 
13
31
  **Hotfix — `claudemd-cli lint <path>` silent-text-scan when path looks like a path but doesn't resolve to a regular file (v0.9.14 family residual).** Spec v6.11.7 unchanged. The v0.9.14 fix added auto-`--file` for the case where the positional was an existing regular file. The other branches — missing path, directory, dead symlink — still fell through to scanning the literal positional string. Three failure shapes surfaced during the dogfood session that produced v0.9.18–v0.9.20:
package/README.md CHANGED
@@ -61,7 +61,7 @@ Verify in one command (Linux): `node --version && jq --version && gh --version &
61
61
  | 12 shell hooks | `banned-vocab-check` · `pre-bash-safety-check` · `ship-baseline-check` · `residue-audit` · `memory-read-check` · `sandbox-disposal-check` · `session-start-check` · `session-summary` · `transcript-vocab-scan` · `transcript-structure-scan` · `version-sync` · `mem-audit` |
62
62
  | 9 slash commands | `/claudemd-status` · `/claudemd-update` · `/claudemd-audit` · `/claudemd-toggle` · `/claudemd-doctor` · `/claudemd-uninstall` · `/claudemd-rules` · `/claudemd-clean-residue` · `/claudemd-sparkline` |
63
63
  | 1 standalone CLI | `claudemd-cli lint` · `claudemd-cli audit` ([npm: `claudemd-cli`](https://www.npmjs.com/package/claudemd-cli)) |
64
- | Spec v6.11.7 | `~/.claude/CLAUDE.md` · `CLAUDE-extended.md` · `CLAUDE-changelog.md` (backup-before-overwrite) |
64
+ | Spec v6.11.8 | `~/.claude/CLAUDE.md` · `CLAUDE-extended.md` · `CLAUDE-changelog.md` (backup-before-overwrite) |
65
65
 
66
66
  Install moves any existing `~/.claude/CLAUDE*.md` to `~/.claude/backup-<ISO>/` (last 5 kept automatically). Uninstall offers `keep / restore / delete`; `delete` requires an extra confirmation.
67
67
 
@@ -299,7 +299,7 @@ claudemd/
299
299
  ├── commands/ # 9 slash-command markdown files
300
300
  ├── bin/ # standalone CLI entrypoint (claudemd-lint.js → `npx claudemd-cli` on npmjs.org)
301
301
  ├── scripts/ # 10 Node.js management scripts + scripts/lib/ (single-source registry, lint, etc.)
302
- ├── spec/ # shipped v6.11.7 CLAUDE*.md trio + hard-rules.json manifest
302
+ ├── spec/ # shipped v6.11.8 CLAUDE*.md trio + hard-rules.json manifest
303
303
  ├── tests/ # hook shell tests + Node.js tests + integration + fixtures
304
304
  ├── docs/ # ADDING-NEW-HOOK.md + RULE-HITS-SCHEMA.md + superpowers/
305
305
  └── .github/workflows/ # ci.yml (ubuntu+macOS × node 20) + npm-publish.yml (tag-triggered)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemd-cli",
3
- "version": "0.9.21",
3
+ "version": "0.9.22",
4
4
  "description": "Standalone CLI for §10-V banned-vocab + transcript scanning. Companion to the claudemd Claude Code plugin (github.com/sdsrss/claudemd) for use in git pre-commit hooks, GitHub Actions, and other agents.",
5
5
  "type": "module",
6
6
  "bin": {