claudemd-cli 0.23.18 → 0.23.20

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.
Files changed (2) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,34 @@ 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.23.20] - 2026-06-13
12
+
13
+ **Patch — two telemetry-integrity fixes found by a 7-day /claudemd-audit self-review: ad-hoc debug sentinels polluted audit views, and banned-vocab's bypass event violated its own documented schema.** Spec content unchanged (stays v6.14.1).
14
+
15
+ ### Fixed — audit views: ad-hoc manual-debug sentinel rows counted as real traffic
16
+
17
+ - `scripts/lib/rule-hits-parse.js` (`excludeTestSessions`): the v0.17.7 filter full-matched only `session_id='t'/'test'`, so manual hook debugging with other one-char sentinels slipped through — eight 2026-06-09 ship-baseline fixture rows with `session_id='s'` / `tool_use_id='t'` / `run_url=https://x/runs/99` inflated self-deny counts (9 denies reported, 8 synthetic) AND faked `duplicate_rows_real=6`, the signal /claudemd-audit documents as a "registration/lib double-fire bug candidate". Fix: also strip any non-null session_id of ≤7 chars — real CC session ids are 36-char UUIDs; all observed synthetic values (`s`, `p`, `probe`, `r4-test`, 353 rows all-time) fall under the cap, while longer one-offs (`dogfood-fresh`, 7 rows) age out naturally. Post-fix on the live log (7-day window): `testSessionsFiltered` 0 → 33, ship-baseline `duplicate_rows_real` 6 → 0, ship-baseline denies 9 → 1 (the survivor is the genuine daagu red-CI interception). Three test fixtures using short ids (`s1`/`s2`/`sess-A`) renamed to ≥8 chars — they simulated real sessions with a shape real sessions never have. Docs synced: `commands/claudemd-audit.md` + `scripts/audit.js` comments.
18
+
19
+ ### Fixed — `banned-vocab`: bypass-escape-hatch recorded `extra:null`, contradicting RULE-HITS-SCHEMA
20
+
21
+ - `hooks/banned-vocab-check.sh:80`: `docs/RULE-HITS-SCHEMA.md` line 33 documents bypass-escape-hatch as "records token name in `extra`", and the pre-bash-safety siblings do (`{"token":"allow-rm-rf-var"}`), but banned-vocab passed literal `null` — the audit's `byBypass` showed `(unspecified)` ×3 sitting exactly on the ≥3 §0.1 review-candidate threshold with no way to tell which token fired (same spec≠impl gap class as `feedback_hook_header_quote_partial_impl`). Fix: record `{"token":"allow-banned-vocab"}`; `tests/hooks/contract.test.sh` A.1 tightened from event-presence to `.extra.token=="allow-banned-vocab"` (pre-fix FAIL showing `extra:null`, post-fix PASS). A `tests/hooks/session-end-check.test.sh` fixture already assumed this shape — implementation now matches it. Full run post-fix: `OVERALL: all suites passed` (4 mid-bundle failures from the sentinel-cap widening fixed by the fixture renames above).
22
+
23
+ ## [0.23.19] - 2026-06-13
24
+
25
+ **Patch — two field-report FPs (external transcript, bat-html-website session 2026-06-12): §8-npx denied a fetch-free `npx --no-install` probe; §10-V Path 2 denied 3 consecutive pushes on a banned word living only inside a branch name.** Spec content unchanged (stays v6.14.1).
26
+
27
+ ### Fixed — `pre-bash-safety`: `npx --no-install <pkg>` denied despite being unable to fetch
28
+
29
+ - `hooks/pre-bash-safety-check.sh`: the npx flag loop treated `--no-install` as a generic skippable flag, took the following token as the package name, and denied when the cwd had no lockfile/local install. But `--no-install` (npx v6) / `--no` (npm 7+) forbid registry fetch entirely — npx runs an already-installed binary or exits non-zero, so no unknown-origin code can land, which is what the §8 NPX chain guards. The denied command was the agent's harmless capability probe (`npx --no-install htmlhint --version … || echo "htmlhint not local"`), and the deny forced it to abandon the tool instead. Fix: recognize `--no-install` / `--no` BEFORE the package token and allow, recording a new `npx-allow-no-install` telemetry event (documented in `docs/RULE-HITS-SCHEMA.md` + contract test). Flags after the package name belong to the package and do NOT lift the gate. Tests: +5 (incl. byte-exact field-report chain; pre-fix 149/152 → post-fix 152/152).
30
+
31
+ ### Fixed — `banned-vocab` Path 2: identifier/path mentions and prior-turn text caused an un-escapable deny loop
32
+
33
+ - `hooks/banned-vocab-check.sh` (two FP vectors, one field report): pushing `docs/comprehensive-audit-2026-06-12` was denied; the agent renamed the branch and was denied twice more, because (a) `\b`-anchored high-fire patterns match INSIDE slashed/hyphenated identifiers (`-` and `/` are word boundaries), so the branch name quoted in prose fired the scan, and (b) the "last assistant turn" extraction actually concatenated ALL assistant text in the tail-200 window (`tail -c 4096` cap), so the original prose kept re-firing on every retry — only the bypass token could exit the loop, contradicting the deny message's own "preceding assistant turn" claim. Fix (a): sanitize the scanned prose before matching — strip fenced code blocks, inline backtick spans, and path-like ASCII runs containing `/` (the path class is ASCII-only so 中文 prose around a path stays intact; bare-prose violations still match). Fix (b): extract assistant entries AFTER the last real typed user prompt (STRING content per `feedback_cc_user_content_string_vs_array`; tool_result ARRAY entries and `<system-reminder>`/`isMeta` injections are mid-turn, NOT boundaries; no prompt in window → pre-fix whole-window fallback). Tests: +6 — slashed-branch (byte-near field report), backtick span, fenced block, bare-prose-beside-path regression guard, prior-turn-before-prompt pass, tool_result-not-a-boundary deny (pre-fix 37/41 → post-fix 41/41). Sibling advisory scanners (`transcript-vocab-scan.sh`, CLI lint) share the identifier FP class at advisory-only severity — queued in `tasks/banned-vocab-sanitizer-siblings.md`.
34
+
35
+ ### Fixed — `tests/scripts/audit.test.js`: two tests were date time-bombs (mid-bundle discovery)
36
+
37
+ - Tests `v0.9.34` and `v0.21.7` pinned fixture timestamps to literal dates (`2026-05-11`, `2026-05-24`); once today's date drifted past the `days: 30` audit window the rows were filtered out and the bucket lookups threw `Cannot read properties of undefined (reading 'rows')`. The first expired on 2026-06-10 (red on clean main since then, locally; CI last ran 2026-06-09 so it never surfaced there), the second would expire 2026-06-23. Fix: derive timestamps from `Date.now() - 60s` with per-row second offsets — dedup semantics (same-second collisions) preserved. Found because this release's full-suite run hit it; unrelated to the field report.
38
+
11
39
  ## [0.23.18] - 2026-06-10
12
40
 
13
41
  **Patch — install/uninstall crashed with a cryptic error on a malformed-but-valid-JSON settings.json.** Spec content unchanged (stays v6.14.1). Continues the end-to-end user-test sweep into the install path.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemd-cli",
3
- "version": "0.23.18",
3
+ "version": "0.23.20",
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": {