claudemd-cli 0.71.3 → 0.71.4

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/README.md CHANGED
@@ -371,7 +371,7 @@ claudemd/
371
371
  │ └── hooks.json # authoritative hook registration (v0.1.5+); CC expands ${CLAUDE_PLUGIN_ROOT} here
372
372
  ├── commands/ # 16 slash-command markdown files
373
373
  ├── bin/ # standalone CLI entrypoint (claudemd-lint.js → `npx claudemd-cli` on npmjs.org)
374
- ├── scripts/ # 18 Node.js scripts + scripts/lib/ (single-source registry, lint, etc.)
374
+ ├── scripts/ # 19 Node.js scripts + scripts/lib/ (single-source registry, lint, etc.)
375
375
  ├── spec/ # shipped v6.25.4 CLAUDE*.md trio + OPERATOR.md + hard-rules.json manifest
376
376
  ├── tests/ # hook shell tests + Node.js tests + integration + fixtures
377
377
  ├── docs/ # ADDING-NEW-HOOK.md + RULE-HITS-SCHEMA.md + superpowers/
@@ -361,7 +361,13 @@ function lintCmd(rawArgs) {
361
361
  // ... digit) OR the literal word `baseline`, ratio-class patterns (tagged
362
362
  // `@ratio` in their reason column) are suppressed. Non-ratio hedges /
363
363
  // adjectives still match.
364
- const HAS_NUMERIC_ARROW = /\d\S*\s*(?:→|->|=>)\s*\d/;
364
+ // `\S{0,64}`, not `\S*` (2026-09-02 audit R11-12): with an unbounded run and
365
+ // no arrow present, the unanchored scan retries from every offset and
366
+ // rescans the tail — quadratic, 710ms on a 20k digit run, and this runs on
367
+ // the RAW file before scan(), so lint.js:150-157's sanitizer fix for the same
368
+ // family never covered it. A digit-dense lockfile or hash dump hung the
369
+ // pre-commit hook. 64 is far past any real anchor (`p99 580ms→140ms` is 15).
370
+ const HAS_NUMERIC_ARROW = /\d\S{0,64}\s*(?:→|->|=>)\s*\d/;
365
371
  const HAS_BASELINE = /baseline/i;
366
372
  const baselineExempt = HAS_NUMERIC_ARROW.test(text) || HAS_BASELINE.test(text);
367
373
 
@@ -405,7 +411,17 @@ function auditCmd(rawArgs) {
405
411
  process.exit(2);
406
412
  }
407
413
 
408
- const jsonl = fs.readFileSync(transcriptPath, 'utf8');
414
+ // Mirrors the `lint --file` read path above (R11-11). The existsSync/statSync
415
+ // guards a few lines up both PASS on a mode-000 file, so an unreadable
416
+ // transcript reached this line and exited 1 with a V8 stack — colliding with
417
+ // the documented `1 = hits found`, which is what CI and pre-commit gate on.
418
+ let jsonl;
419
+ try {
420
+ jsonl = fs.readFileSync(transcriptPath, 'utf8');
421
+ } catch (e) {
422
+ process.stderr.write(`audit: failed to read ${transcriptPath}: ${e.message}\n`);
423
+ process.exit(2);
424
+ }
409
425
 
410
426
  // Silent-success guard: parseTranscript intentionally skips unparseable rows
411
427
  // (matches transcript-vocab-scan.sh). But if the WHOLE file fails to parse
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemd-cli",
3
- "version": "0.71.3",
3
+ "version": "0.71.4",
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": {
@@ -26,10 +26,27 @@
26
26
  "test:scripts": "bash -c 'source tests/lib/env-hygiene.sh && claudemd_reset_test_env && node --test tests/scripts/*.test.js'",
27
27
  "test:hooks": "for t in tests/hooks/*.test.sh; do bash \"$t\" || exit 1; done",
28
28
  "lint:argv": "node scripts/lint-argv.js",
29
- "version-check": "node scripts/version-cascade-check.js"
29
+ "version-check": "node scripts/version-cascade-check.js",
30
+ "test:coverage": "c8 --all --src=bin --src=scripts --include='bin/**/*.js' --include='scripts/**/*.js' --reporter=text-summary --reporter=html --reports-dir=coverage npm run test:scripts",
31
+ "lint": "npm run lint:argv && npm run version-check && npm run lint:sh && npm run lint:js",
32
+ "lint:sh": "F=$(bash tests/lib/shell-files.sh) && shellcheck --severity=warning $F",
33
+ "lint:js": "eslint bin scripts tests eslint.config.js",
34
+ "format": "prettier --write bin scripts tests eslint.config.js",
35
+ "format:check": "prettier --check bin scripts tests eslint.config.js",
36
+ "metrics": "node scripts/baseline-metrics.js",
37
+ "check": "npm run lint && npm test"
30
38
  },
31
39
  "engines": {
32
40
  "node": ">=20"
33
41
  },
34
- "license": "MIT"
42
+ "license": "MIT",
43
+ "devDependencies": {
44
+ "@eslint/js": "10.0.1",
45
+ "acorn": "8.18.0",
46
+ "c8": "12.0.0",
47
+ "eslint": "10.9.1",
48
+ "globals": "17.12.0",
49
+ "jscpd": "5.1.1",
50
+ "prettier": "3.9.6"
51
+ }
35
52
  }