claudemd-cli 0.21.8 → 0.21.9
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 +25 -0
- package/README.md +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,31 @@ 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.21.9] - 2026-05-24
|
|
12
|
+
|
|
13
|
+
**Patch — fix: §8 SAFETY unquoted-`eval` indirect-exec coverage + docs alignment from end-to-end QA pass. Spec unchanged at v6.13.2.**
|
|
14
|
+
|
|
15
|
+
### Why this patch
|
|
16
|
+
|
|
17
|
+
End-to-end user simulation (running every CLI surface, script, and hook as a real user would) surfaced one §8 SAFETY silent-bypass plus two doc/UX inconsistencies that would bite users following the documentation literally:
|
|
18
|
+
|
|
19
|
+
1. `hooks/pre-bash-safety-check.sh` `unwrap_indirect` only handled **quoted** eval forms — `eval 'rm -rf $X'` / `eval "rm -rf $X"`. The unquoted form `eval rm -rf $X` (bash joins eval's argv with spaces before evaluating, so it's execution-equivalent) silently bypassed §8 SAFETY. Same family as v0.21.4 direct-path bypass and v0.21.8 indirect default-ON — a final coverage gap inside the §5.1 Never-downgrade SAFETY family.
|
|
20
|
+
2. `scripts/update.js` help text wrote `CLAUDEMD_UPDATE_CHOICE=apply` while the code accepts only `apply-all`. A user following the help verbatim hits `unknown choice: apply. Valid: 'apply-all' | 'cancel'` exit 1.
|
|
21
|
+
3. `README.md` `/claudemd-rules` row claimed default 90 / "matches §13.1 quarterly cadence"; actual default has been 30 since v0.13.1 (90d gate was structurally unreachable under typical log retention). Project-layout block listed 11 hooks / 11 commands; actual 17 / 12.
|
|
22
|
+
|
|
23
|
+
### What changed
|
|
24
|
+
|
|
25
|
+
- `hooks/pre-bash-safety-check.sh`: new sed rule in `unwrap_indirect` handling `(prefix)eval[ws]+(non-quote-start)...(stop-at-terminator)` — same prefix class as the existing quoted-eval handler so quoted-string `"eval rm -rf $X"` and word-boundary `evaluate ...` don't false-fire. Header docstring updated to note the unquoted-eval extension and to call out that `bash -c` / `sh -c` / `zsh -c` are NOT extended the same way (those builtins only treat their first non-flag arg as the script; unquoted form is not execution-equivalent — eval is the only shape where joining the argv with spaces yields the same result).
|
|
26
|
+
- `tests/fixtures/bash-safety/corpus.tsv`: +3 deny cases covering the unquoted-eval forms (`eval rm -rf $X`, `eval rm -rf "$X"`, `cmd && eval rm -rf $X`) and +5 pass cases for FP guards (`$HOME/cache` whitelist via unwrap, `[allow-rm-rf-var]` token survives unwrap, echo-of-quoted-string-literal stays inert, `evaluate` word-boundary not eval, `eval ls -la` benign).
|
|
27
|
+
- `scripts/update.js`: help text + env-var documentation line aligned to the only accepted value `apply-all` (matches `commands/claudemd-update.md` slash-command markdown which has been correct since v0.2.x; the script help was the lone outlier).
|
|
28
|
+
- `README.md`: `/claudemd-rules` row updated (default 30, with v0.13.1 lowering rationale inline); project-layout block updated (17 hooks / 12 commands).
|
|
29
|
+
|
|
30
|
+
### Heuristic limits (unchanged from v0.21.8)
|
|
31
|
+
|
|
32
|
+
`unwrap_indirect` remains regex-based — escaped quotes, nested heredocs, command-substitution (`$(rm -rf $X)`, `` `rm -rf $X` ``) at top level still escape detection. `[allow-rm-rf-var]` / `[allow-npx-unpinned]` bypass tokens survive unwrap and remain the authorized escape for legitimate indirect calls. `BASH_SAFETY_INDIRECT_CALL=0` opts out of the entire unwrap path (eval + bash-c + sh-c + zsh-c).
|
|
33
|
+
|
|
34
|
+
Lesson sources: `feedback_hook_env_test_hermeticity.md` (fixture-default discipline), `feedback_audit_tool_before_sweep.md` (run measurement before sweeping — end-to-end probe drove this catch).
|
|
35
|
+
|
|
11
36
|
## [0.21.8] - 2026-05-24
|
|
12
37
|
|
|
13
38
|
**Patch — fix: §8 SAFETY indirect-exec coverage default-ON (`BASH_SAFETY_INDIRECT_CALL` flip from opt-in to opt-out). Spec unchanged at v6.13.2.**
|
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ Per-hook timeout (3-5s in `hooks.json`); timeout = treated as exit 0 (pass) per
|
|
|
108
108
|
| `/claudemd-audit [--days N]` | Aggregate rule-hits over last N days (default 30). Top banned-vocab patterns, per-hook deny counts. |
|
|
109
109
|
| `/claudemd-toggle <hook-name>` | Enable/disable a specific hook by toggling `DISABLE_*_HOOK` in `settings.json` env. |
|
|
110
110
|
| `/claudemd-doctor [--prune-backups=N]` | Health checks; optionally prune `~/.claude/backup-*` dirs older than N. v0.7.1+ also flags rule sections whose bypass:deny ratio > 50% (R-N6 §0.1 demotion candidates). |
|
|
111
|
-
| `/claudemd-rules [N]` | v0.8.0+ — audit `spec/hard-rules.json` manifest over last N days (default
|
|
111
|
+
| `/claudemd-rules [N]` | v0.8.0+ — audit `spec/hard-rules.json` manifest over last N days (default 30 — lowered from 90d in v0.13.1 after the 90d gate was structurally unreachable under typical log retention). Surfaces `demoteCandidates` (hook-enforced rules with 0 hits) and `staleReviews` (rules whose `last_demote_review` is null/old). |
|
|
112
112
|
| `/claudemd-sparkline [--days=A,B,C]` | v0.8.4+ R-N9 — per-`spec_section` cumulative counts of signal events across 3 windows (default 30/60/90d). Trend arrow compares per-period rate; `(newly active)` / `(silenced)` annotations flag activation/deactivation transitions. Markdown block suitable for CHANGELOG header pre-release. |
|
|
113
113
|
| `/claudemd-clean-residue [--apply]` | Dry-run-by-default cleanup of stale `claudemd-sync-*` sentinels and historical `claudemd-(mockgh\|work).*` test sandboxes. |
|
|
114
114
|
| `/claudemd-uninstall` | Pre-uninstall cleanup: clears manifest + state + log + legacy `settings.json` hook entries. Run BEFORE `/plugin uninstall claudemd@claudemd` (see [Uninstall](#uninstall)). |
|
|
@@ -324,9 +324,9 @@ claudemd/
|
|
|
324
324
|
├── .claude-plugin/
|
|
325
325
|
│ ├── plugin.json # minimal manifest (name, version, author, license, keywords)
|
|
326
326
|
│ └── marketplace.json # marketplace catalog entry
|
|
327
|
-
├── hooks/ #
|
|
327
|
+
├── hooks/ # 17 shell hooks + hooks/lib/ (hook-common, rule-hits, platform)
|
|
328
328
|
│ └── hooks.json # authoritative hook registration (v0.1.5+); CC expands ${CLAUDE_PLUGIN_ROOT} here
|
|
329
|
-
├── commands/ #
|
|
329
|
+
├── commands/ # 12 slash-command markdown files
|
|
330
330
|
├── bin/ # standalone CLI entrypoint (claudemd-lint.js → `npx claudemd-cli` on npmjs.org)
|
|
331
331
|
├── scripts/ # 15 Node.js management scripts + scripts/lib/ (single-source registry, lint, etc.)
|
|
332
332
|
├── spec/ # shipped v6.13.0 CLAUDE*.md trio + OPERATOR.md + hard-rules.json manifest
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudemd-cli",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.9",
|
|
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": {
|