claudemd-cli 0.17.3 → 0.17.5
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 +127 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,133 @@ 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.17.5] - 2026-05-14
|
|
12
|
+
|
|
13
|
+
**Patch — fix: `memory-read-check.sh` + `memory-prompt-hint.sh` backtick-form TAG_BLOCK parsing matched the LAST `\`[token]\`` on each MEMORY.md index line — so a decorative backtick block in the description hijacked the parsed tag and silently shadowed the real tag.**
|
|
14
|
+
|
|
15
|
+
### Background
|
|
16
|
+
|
|
17
|
+
Round 6 dogfood probe of `memory-prompt-hint.sh` against a synthetic MEMORY.md line:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
- [Has both](feedback_btq.md) `[realtag]` — see also `[decortag]` inline
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Prompts containing `realtag` were SILENT (no hint emitted). Prompts containing `decortag` (which sits in the description, not the tag block) WERE flagged. Both backtick blocks parsed the same way because the regex was:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
sed -n 's/.*`\[\([^]]*\)\]`.*/\1/p'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The greedy `.*` consumed up to the LAST `\`[...]\`` token on the line — so descriptions that decoratively quote a token inside backticks (a very common technical-prose pattern) silently became the parsed tag.
|
|
30
|
+
|
|
31
|
+
**Production impact**: the project's own `MEMORY.md` has at least one affected entry — `feedback_cc_cwd_encoding_dots.md` is documented as
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
... `[cwd, encoding, projects, underscore]` — CC encodes every non-`[a-zA-Z0-9-]` char to `-`; ...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Pre-fix, this line's parsed tag was `a-zA-Z0-9-` (the regex example inside the description), not the intended `cwd, encoding, projects, underscore`. Any prompt about cwd encoding / project paths / underscore handling silently missed the §11 read-check rule because the real tags were never registered.
|
|
38
|
+
|
|
39
|
+
### What changed
|
|
40
|
+
|
|
41
|
+
- `[fix MED]` **`hooks/memory-read-check.sh`** — backtick TAG_BLOCK regex now anchors on `.md)`:
|
|
42
|
+
|
|
43
|
+
```diff
|
|
44
|
+
- sed -n 's/.*`\[\([^]]*\)\]`.*/\1/p'
|
|
45
|
+
+ sed -n 's/.*\.md)[[:space:]]*`\[\([^]]*\)\]`.*/\1/p'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The `.md)` anchor forces the match to start at the close of the markdown link, before any decorative backtick block in the description. The greedy `.*` before `.md)` is fine because `.md)` itself is the unambiguous anchor (only one per line in practice — the link target).
|
|
49
|
+
|
|
50
|
+
Mirrors the existing plain-form fallback (line 146 of the same file), which already anchored on `.md)` since v0.11.0. The backtick variant was added separately and missed the anchor.
|
|
51
|
+
|
|
52
|
+
- `[fix MED]` **`hooks/memory-prompt-hint.sh`** — same one-line change; this hook duplicates the parsing logic from `memory-read-check.sh` and was added with the same flaw in v0.11.0.
|
|
53
|
+
|
|
54
|
+
- `[test]` **`tests/hooks/memory-read-check.test.sh`** Cases 30+31 — real-tag-matched + decorative-token-not-matched pair, anchored on a fresh `S30_DIR/S30_CWD` so the existing Cases don't interfere. 29 → 31.
|
|
55
|
+
|
|
56
|
+
- `[test]` **`tests/hooks/memory-prompt-hint.test.sh`** Cases 13+14 — same pair on a `BTQ_CWD` fixture. 12 → 14.
|
|
57
|
+
|
|
58
|
+
### Why patch
|
|
59
|
+
|
|
60
|
+
Restores the documented spec §11 tag-match contract — only `\`[tag, tag]\`` immediately following the markdown link is a tag block. Description-decorative backtick blocks were never supposed to be tags. CHANGELOG `fix:` not `change:`. No new flags, no new behavior, no LLM-visible metadata bump (the hooks are mechanical filters; spec text is unchanged).
|
|
61
|
+
|
|
62
|
+
### Tests
|
|
63
|
+
|
|
64
|
+
- `bash tests/run-all.sh`: 411 node-test + 2 integration suites pass.
|
|
65
|
+
- `bash tests/hooks/memory-read-check.test.sh`: 31/31 (was 29; +2).
|
|
66
|
+
- `bash tests/hooks/memory-prompt-hint.test.sh`: 14/14 (was 12; +2).
|
|
67
|
+
- All other hook suites unchanged (76/76 pre-bash-safety, 24/24 banned-vocab, 15/15 ship-baseline, etc.).
|
|
68
|
+
- `spec-coherence-audit`: 3/3 clean.
|
|
69
|
+
|
|
70
|
+
### Operator notes
|
|
71
|
+
|
|
72
|
+
- Update path: plugin marketplace update + `/reload-plugins`. `${CLAUDE_PLUGIN_ROOT}` expansion picks up new hook bodies automatically.
|
|
73
|
+
- **If you have a MEMORY.md entry whose description contains backtick-wrapped tokens** (`` `[regex]` ``, `` `[example]` ``, `` `[type]` ``, etc.), this release re-enables tag-matching on the real tag — you may see hints / denies fire on prompts you previously didn't, because the real tags are now correctly indexed.
|
|
74
|
+
- Audit your project's MEMORY.md: `grep -E '\`\[[^]]+\]\`.*\`\[[^]]+\]\`' <path-to-MEMORY.md>` lists lines with multiple backtick blocks that were ambiguously parsed pre-fix.
|
|
75
|
+
|
|
76
|
+
## [0.17.4] - 2026-05-14
|
|
77
|
+
|
|
78
|
+
**Patch — fix: `banned-vocab-check.sh` + `ship-baseline-check.sh` trigger filter false-positives on `git commit` / `git push` substrings inside shell comments and heredoc bodies. Ports the v0.9.28 `memory-read-check.sh` segment-anchor regex (CMD flatten + `^|[[:space:]]*[;&|]+[[:space:]]*` separator) to both hooks. Closes the last two raw-`$CMD`-grep sites identified in the v0.17.3 sister-pattern sweep.**
|
|
79
|
+
|
|
80
|
+
### Background
|
|
81
|
+
|
|
82
|
+
After v0.17.3 closed the multi-line CMD §8 bypass in `pre-bash-safety-check.sh`, a sister-pattern grep across all hooks revealed two remaining raw-`$CMD` trigger sites:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
hook → reads CMD → has sanitize → has flatten
|
|
86
|
+
pre-bash-safety-check.sh ✓ ✓ ✓ (v0.17.1 + v0.17.3)
|
|
87
|
+
memory-read-check.sh ✓ ✓ ✓ (v0.9.28 + v0.17.1)
|
|
88
|
+
banned-vocab-check.sh ✓ ✗ ✗ ← Bug 16
|
|
89
|
+
ship-baseline-check.sh ✓ ✗ ✗ ← Bug 15
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Both used the loose prefix `(^|[[:space:];&|])` — which accepts ANY whitespace as a separator. That lets a space after `#` (comment) or a space inside a heredoc body line satisfy the prefix, so:
|
|
93
|
+
|
|
94
|
+
- `# git commit -m "significantly faster"` (comment) → banned-vocab fires, message-extract finds `-m "..."`, hook denies a non-existent commit.
|
|
95
|
+
- `cat <<EOF\ngit push origin main\nEOF` (heredoc body) → ship-baseline fires when CI is red, denying a `cat` command that doesn't push anything.
|
|
96
|
+
|
|
97
|
+
`memory-read-check.sh` already solved this in v0.9.28 by flattening CMD to a single line and tightening the prefix to `(^|[[:space:]]*[;&|]+[[:space:]]*)` — real shell separator only. This release ports that fix verbatim to the two remaining hooks.
|
|
98
|
+
|
|
99
|
+
### What changed
|
|
100
|
+
|
|
101
|
+
- `[fix MED]` **`hooks/banned-vocab-check.sh`** — trigger filter now flattens `$CMD` with `tr '\n' ' '` and uses the segment-anchor `TRIGGER_RE='(^|[[:space:]]*[;&|]+[[:space:]]*)git([[:space:]]+-c[[:space:]]+[^[:space:]]+)*[[:space:]]+commit([[:space:]]|$)'`. Message extraction below the trigger gate is unchanged — its `-m "..."` regex was already quote-aware and only ran AFTER trigger fired, so the upstream tightening alone is enough. `tests/hooks/banned-vocab.test.sh` 20 → 24 (+3 FP-anchor + 1 non-regression on chained `make && git commit`).
|
|
102
|
+
|
|
103
|
+
- `[fix LOW]` **`hooks/ship-baseline-check.sh`** — same shape: `CMD_FLAT=$(printf '%s' "$CMD" | tr '\n' ' ')` + segment-anchor `TRIGGER_RE='(^|[[:space:]]*[;&|]+[[:space:]]*)git[[:space:]]+push([[:space:]]|$)'`. The `--help` short-circuit on line 29 also reads `CMD_FLAT` for consistency. `tests/hooks/ship-baseline.test.sh` 11 → 15 (+3 FP-anchor + 1 non-regression on chained `make && git push`).
|
|
104
|
+
|
|
105
|
+
### Why patch
|
|
106
|
+
|
|
107
|
+
Both changes restore intended hook behavior — comments and heredoc bodies are not shell-executable contexts; the spec rules (§10-V banned-vocab on real commits, §7 ship-baseline on real pushes) were never supposed to fire on them. `memory-read-check.sh` already shipped this design; the sister hooks were inconsistent. CHANGELOG `fix:` not `change:` — no new behavior, just tighter scoping of an existing rule.
|
|
108
|
+
|
|
109
|
+
Severity:
|
|
110
|
+
|
|
111
|
+
- **Bug 16 (banned-vocab) — MED FP**: blocks legitimate commits whenever a previous bash command on the same Claude tool call contained a `# git commit -m "..."` example in a comment or a `cat <<EOF ... git commit ... EOF` shell snippet in a heredoc. Users would see deny on the very next real commit because the agent's running bash CMD included an example-as-text.
|
|
112
|
+
|
|
113
|
+
- **Bug 15 (ship-baseline) — LOW FP**: only surfaces when CI is currently red; the hook then denies the `cat`/`echo`/`ls` command for containing a `git push` substring. No security impact (FP makes hook overly strict, never overly permissive).
|
|
114
|
+
|
|
115
|
+
### Non-regression anchors
|
|
116
|
+
|
|
117
|
+
Each hook test gained an explicit case for chained-real shape (`make && git commit -m "..."` / `make && git push origin main`) that fires the trigger via `&&` separator. These lock that the tightened regex still matches real shell-separator chains, only rejecting whitespace-only prefixes.
|
|
118
|
+
|
|
119
|
+
### Tests
|
|
120
|
+
|
|
121
|
+
- `bash tests/run-all.sh`: 411 node-test + 2 integration suites pass.
|
|
122
|
+
- `bash tests/hooks/banned-vocab.test.sh`: 24/24 (was 20).
|
|
123
|
+
- `bash tests/hooks/ship-baseline.test.sh`: 15/15 (was 11).
|
|
124
|
+
- `bash tests/hooks/pre-bash-safety.test.sh`: 76/76 (unchanged).
|
|
125
|
+
- `bash tests/hooks/memory-read-check.test.sh`: 29/29 (unchanged).
|
|
126
|
+
- Manual end-to-end: 8 FP probes (4 per hook: full-comment / inline-comment / heredoc body / quoted string) verified post-fix; 2 non-regression chained-real probes verified.
|
|
127
|
+
|
|
128
|
+
### Operator notes
|
|
129
|
+
|
|
130
|
+
- Update path: plugin marketplace update + `/reload-plugins`. `${CLAUDE_PLUGIN_ROOT}` expansion means installed plugin picks up the new hook bodies automatically.
|
|
131
|
+
- Bypass tokens unchanged: `[allow-banned-vocab]` and `known-red baseline: <reason>` continue to work the same.
|
|
132
|
+
- If you'd intentionally been writing bash with `# git commit -m "..."` example comments and getting denied — this release is your fix; no `[allow-banned-vocab]` needed for non-commit contexts.
|
|
133
|
+
|
|
134
|
+
### Sister-pattern sweep — final state
|
|
135
|
+
|
|
136
|
+
After this release, all four `*-check.sh` hooks that read `tool_input.command` and act on it (`pre-bash-safety`, `memory-read-check`, `banned-vocab-check`, `ship-baseline-check`) use the same defense-in-depth shape: (1) `tr '\n' ' '` flatten, (2) segment-anchor trigger regex, (3) sanitize (where applicable for tag/message extraction). No remaining raw-multi-line-`$CMD` grep sites in the hook fleet.
|
|
137
|
+
|
|
11
138
|
## [0.17.3] - 2026-05-14
|
|
12
139
|
|
|
13
140
|
**Patch — fix: CRITICAL — `pre-bash-safety-check.sh` multi-line CMD §8 SAFETY bypass closure. Multi-line bash commands containing `rm -rf $UNSAFE_VAR` on any line other than the first silently passed the hook; the matching multi-line `npx pkg@PIN` case wrongly denied as unpinned. One root cause, two opposite-direction defects.**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudemd-cli",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.5",
|
|
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": {
|