claudemd-cli 0.72.0 → 0.73.1
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/bin/claudemd-lint.js +17 -2
- package/package.json +3 -3
- package/scripts/lib/lint.js +13 -3
package/bin/claudemd-lint.js
CHANGED
|
@@ -480,7 +480,20 @@ function auditCmd(rawArgs) {
|
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
|
|
483
|
-
|
|
483
|
+
// `integrity` counts the rows parseTranscript drops. The pre-flight above
|
|
484
|
+
// only catches an ENTIRELY unparseable file; a transcript that is 30%
|
|
485
|
+
// corrupt passed it and then printed "no §10-V hits across N turn(s)" with N
|
|
486
|
+
// silently short (audit R11-24). Same warning shape as the string-row skip
|
|
487
|
+
// below — the verdict still comes from the rows that parsed, but the reader
|
|
488
|
+
// is told how many did not.
|
|
489
|
+
const integrity = { totalLines: 0, badLines: 0 };
|
|
490
|
+
const turns = parseTranscript(jsonl, integrity);
|
|
491
|
+
if (integrity.badLines > 0) {
|
|
492
|
+
process.stderr.write(
|
|
493
|
+
`audit: warning: skipped ${integrity.badLines} of ${integrity.totalLines} non-empty line(s) ` +
|
|
494
|
+
`that did not parse as JSON — the turn count below covers only the rows that parsed.\n`
|
|
495
|
+
);
|
|
496
|
+
}
|
|
484
497
|
// QA ISSUE-002 (option c): string-shape assistant rows are outside the
|
|
485
498
|
// block-array input domain and never reach the scanner. Keep the verdict
|
|
486
499
|
// based on scanned turns, but say so on stderr — a silent skip here is the
|
|
@@ -514,7 +527,9 @@ function auditCmd(rawArgs) {
|
|
|
514
527
|
const flaggedCount = annotated.reduce((n, t) => n + (t.hits.length > 0 ? 1 : 0), 0);
|
|
515
528
|
|
|
516
529
|
if (json) {
|
|
517
|
-
process.stdout.write(
|
|
530
|
+
process.stdout.write(
|
|
531
|
+
formatJSON({ scope: 'audit', transcript: transcriptPath, turns: annotated, integrity }) + '\n'
|
|
532
|
+
);
|
|
518
533
|
} else {
|
|
519
534
|
const out = formatHumanReadable({ scope: 'audit', turns: annotated });
|
|
520
535
|
if (flaggedCount === 0) process.stdout.write(out + '\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudemd-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.1",
|
|
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": {
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"scripts": {
|
|
25
25
|
"test": "bash tests/run-all.sh",
|
|
26
26
|
"test:scripts": "bash -c 'source tests/lib/env-hygiene.sh && claudemd_reset_test_env && node --test tests/scripts/*.test.js'",
|
|
27
|
-
"test:hooks": "for t in tests/hooks/*.test.sh; do
|
|
27
|
+
"test:hooks": "bash -c 'source tests/lib/env-hygiene.sh && claudemd_reset_test_env && source tests/lib/run-suite.sh && for t in tests/hooks/*.test.sh; do run_suite \"$t\" 300 || exit 1; done'",
|
|
28
28
|
"lint:argv": "node scripts/lint-argv.js",
|
|
29
29
|
"version-check": "node scripts/version-cascade-check.js",
|
|
30
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",
|
|
31
|
+
"lint": "npm run lint:argv && npm run version-check && npm run lint:sh && npm run lint:js && npm run format:check",
|
|
32
32
|
"lint:sh": "F=$(bash tests/lib/shell-files.sh) && shellcheck --severity=warning $F",
|
|
33
33
|
"lint:js": "eslint bin scripts tests eslint.config.js",
|
|
34
34
|
"format": "prettier --write bin scripts tests eslint.config.js",
|
package/scripts/lib/lint.js
CHANGED
|
@@ -383,21 +383,31 @@ export function scan(text, { excludeRatio = false, patterns, sanitize = false }
|
|
|
383
383
|
return hits;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
// parseTranscript(jsonlText) → [{turnIndex, line, text}, ...]
|
|
386
|
+
// parseTranscript(jsonlText, integrity) → [{turnIndex, line, text}, ...]
|
|
387
387
|
// Iterates jsonl, returns one entry per assistant text-content turn. Each
|
|
388
388
|
// entry concatenates all .message.content[*].text blocks for that turn.
|
|
389
|
-
// Corrupt rows (unparseable JSON, missing fields)
|
|
389
|
+
// Corrupt rows (unparseable JSON, missing fields) are skipped — matches
|
|
390
390
|
// transcript-vocab-scan.sh's `try fromjson catch empty` design.
|
|
391
|
-
|
|
391
|
+
//
|
|
392
|
+
// `integrity` (out param, optional): `{ totalLines, badLines }` written back
|
|
393
|
+
// so the skip is countable rather than invisible. Skipping is still the right
|
|
394
|
+
// behavior — a half-corrupt transcript is worth scanning — but until 2026-09-03
|
|
395
|
+
// (audit R11-24) nothing downstream could tell "0 hits across 40 turns" from
|
|
396
|
+
// "0 hits across the 40 turns that happened to parse". readLogRows in
|
|
397
|
+
// rule-hits-parse.js has carried the same counter since a 33% corruption went
|
|
398
|
+
// unnoticed there; this is the same counter on the transcript side.
|
|
399
|
+
export function parseTranscript(jsonlText, integrity = null) {
|
|
392
400
|
const lines = jsonlText.split('\n');
|
|
393
401
|
const turns = [];
|
|
394
402
|
let turnIndex = 0;
|
|
395
403
|
for (let i = 0; i < lines.length; i++) {
|
|
396
404
|
if (!lines[i].trim()) continue;
|
|
405
|
+
if (integrity) integrity.totalLines = (integrity.totalLines || 0) + 1;
|
|
397
406
|
let row;
|
|
398
407
|
try {
|
|
399
408
|
row = JSON.parse(lines[i]);
|
|
400
409
|
} catch {
|
|
410
|
+
if (integrity) integrity.badLines = (integrity.badLines || 0) + 1;
|
|
401
411
|
continue;
|
|
402
412
|
}
|
|
403
413
|
if (row.type !== 'assistant') continue;
|