@uxcontinuum/ccaudit 1.0.2 → 1.0.3
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/index.js +94 -18
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -362,17 +362,19 @@ function grade(stats, setup) {
|
|
|
362
362
|
// 2. Project hygiene (human sessions only).
|
|
363
363
|
// Three signals: custom titles (strongest), slugs (informal auto-titles),
|
|
364
364
|
// and CWD diversity (project-scoped work via tmux or shell). Any of these
|
|
365
|
-
// counts as organizational hygiene.
|
|
365
|
+
// counts as organizational hygiene. Long prompts are a tell only when CWD
|
|
366
|
+
// count is low (single project + walls of text = unscoped sprawl).
|
|
366
367
|
if (human.sessions) {
|
|
367
368
|
let hScore = 50;
|
|
368
369
|
hScore += Math.round(human.titledPct * 0.35); // formal title bonus
|
|
369
|
-
hScore += Math.round(human.sluggedPct * 0.15); // slug bonus
|
|
370
|
-
// CWD diversity: launching
|
|
371
|
-
if (human.uniqueCwds >= 3) hScore +=
|
|
372
|
-
if (human.uniqueCwds >= 10) hScore +=
|
|
373
|
-
if (human.uniqueCwds >= 25) hScore +=
|
|
374
|
-
if (human.avgPromptLen > 0 && human.avgPromptLen < 80) hScore -=
|
|
375
|
-
|
|
370
|
+
hScore += Math.round(human.sluggedPct * 0.15); // slug bonus
|
|
371
|
+
// CWD diversity: launching from named project dirs is real hygiene.
|
|
372
|
+
if (human.uniqueCwds >= 3) hScore += 10;
|
|
373
|
+
if (human.uniqueCwds >= 10) hScore += 10;
|
|
374
|
+
if (human.uniqueCwds >= 25) hScore += 6;
|
|
375
|
+
if (human.avgPromptLen > 0 && human.avgPromptLen < 80) hScore -= 6;
|
|
376
|
+
// Walls of text are only a problem when work is unscoped.
|
|
377
|
+
if (human.avgPromptLen > 2500 && human.uniqueCwds < 5) hScore -= 8;
|
|
376
378
|
hScore = Math.max(0, Math.min(100, hScore));
|
|
377
379
|
const titleNote = human.titledPct > 0
|
|
378
380
|
? `${human.titledPct}% titled`
|
|
@@ -387,21 +389,39 @@ function grade(stats, setup) {
|
|
|
387
389
|
});
|
|
388
390
|
}
|
|
389
391
|
|
|
390
|
-
// 3. Tool balance (human sessions only).
|
|
392
|
+
// 3. Tool balance (human sessions only). Adaptive: don't punish Bash
|
|
393
|
+
// dominance if absolute Edit volume is high, because that's "busy operator"
|
|
394
|
+
// not "bash hammer." Only penalize when Edit absolute volume is also low.
|
|
391
395
|
if (human.sessions && human.totalTools > 0) {
|
|
392
396
|
let bScore = 75;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
+
const editAbs = Math.round(human.editPct * human.totalTools / 100);
|
|
398
|
+
const readAbs = Math.round(human.readPct * human.totalTools / 100);
|
|
399
|
+
|
|
400
|
+
// Bash dominance penalty scales with how thin the rest of the toolkit is.
|
|
401
|
+
if (human.bashPct > 65) {
|
|
402
|
+
if (editAbs > 500) bScore -= 6; // big absolute Edit volume — busy operator
|
|
403
|
+
else if (editAbs > 100) bScore -= 12;
|
|
404
|
+
else bScore -= 18; // truly a bash hammer
|
|
405
|
+
} else if (human.bashPct > 50) {
|
|
406
|
+
bScore -= 4;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (human.readPct + human.grepPct + human.editPct < 15) bScore -= 10;
|
|
410
|
+
if (human.editPct > 10 && human.editPct < 55) bScore += 8;
|
|
411
|
+
if (human.agentPct > 2) bScore += 7;
|
|
412
|
+
if (human.agentPct > 5) bScore += 5;
|
|
413
|
+
|
|
397
414
|
bScore = Math.max(0, Math.min(100, bScore));
|
|
415
|
+
|
|
416
|
+
const fix = human.bashPct > 65 && editAbs < 200
|
|
417
|
+
? 'You are running things, not editing things. Use Edit/Write more.'
|
|
418
|
+
: null;
|
|
419
|
+
|
|
398
420
|
dims.push({
|
|
399
421
|
name: 'Tool balance (human)',
|
|
400
422
|
score: bScore,
|
|
401
|
-
detail: `Bash ${human.bashPct}%, Edit+Write ${human.editPct}
|
|
402
|
-
fix
|
|
403
|
-
? 'You are running things, not editing things. Use Edit/Write more.'
|
|
404
|
-
: null,
|
|
423
|
+
detail: `Bash ${human.bashPct}%, Edit+Write ${human.editPct}% (${editAbs} calls), Read ${human.readPct}%, Grep+Glob ${human.grepPct}%, Agent/Task ${human.agentPct}%.`,
|
|
424
|
+
fix,
|
|
405
425
|
});
|
|
406
426
|
}
|
|
407
427
|
|
|
@@ -539,4 +559,60 @@ const stats = aggregate(sessions);
|
|
|
539
559
|
const setup = inspectClaudeDir(CLAUDE_DIRS[0]);
|
|
540
560
|
const graded = grade(stats, setup);
|
|
541
561
|
|
|
542
|
-
|
|
562
|
+
if (hasFlag('--json')) {
|
|
563
|
+
// Programmatic output. Stable shape for downstream tools and the future
|
|
564
|
+
// public-benchmark backend. No personal content (prompts, slugs, CWDs).
|
|
565
|
+
const payload = {
|
|
566
|
+
schema: 'ccaudit/1',
|
|
567
|
+
generated_at: new Date().toISOString(),
|
|
568
|
+
window_days: days,
|
|
569
|
+
overall: { score: graded.overall, letter: graded.letter },
|
|
570
|
+
dimensions: graded.dims.map(d => ({
|
|
571
|
+
name: d.name,
|
|
572
|
+
score: d.score,
|
|
573
|
+
letter: letterFor(d.score),
|
|
574
|
+
detail: d.detail,
|
|
575
|
+
fix: d.fix,
|
|
576
|
+
})),
|
|
577
|
+
setup: {
|
|
578
|
+
total_hooks: setup.totalHooks,
|
|
579
|
+
hooks_by_event: setup.hooksByEvent,
|
|
580
|
+
auto_memory_enabled: setup.autoMemoryEnabled,
|
|
581
|
+
mcp_servers: setup.mcpServers,
|
|
582
|
+
hook_files: setup.hookFiles.length,
|
|
583
|
+
has_claude_md: setup.hasClaudeMd,
|
|
584
|
+
claude_md_bytes: setup.claudeMdBytes,
|
|
585
|
+
skills_installed: setup.skillCount,
|
|
586
|
+
settings_parse_error: setup.settingsParseError,
|
|
587
|
+
},
|
|
588
|
+
human: stats.human ? {
|
|
589
|
+
sessions: stats.human.sessions,
|
|
590
|
+
prompts: stats.human.prompts,
|
|
591
|
+
titled_pct: stats.human.titledPct,
|
|
592
|
+
slugged_pct: stats.human.sluggedPct,
|
|
593
|
+
unique_cwds: stats.human.uniqueCwds,
|
|
594
|
+
avg_prompt_len: stats.human.avgPromptLen,
|
|
595
|
+
just_count: stats.human.justCount,
|
|
596
|
+
please_count: stats.human.pleaseCount,
|
|
597
|
+
total_tools: stats.human.totalTools,
|
|
598
|
+
tool_distribution: {
|
|
599
|
+
bash_pct: stats.human.bashPct,
|
|
600
|
+
edit_write_pct: stats.human.editPct,
|
|
601
|
+
read_pct: stats.human.readPct,
|
|
602
|
+
grep_glob_pct: stats.human.grepPct,
|
|
603
|
+
agent_task_pct: stats.human.agentPct,
|
|
604
|
+
},
|
|
605
|
+
output_tokens: stats.human.outputTokens,
|
|
606
|
+
input_tokens: stats.human.inputTokens,
|
|
607
|
+
} : null,
|
|
608
|
+
agent: stats.agent ? {
|
|
609
|
+
sessions: stats.agent.sessions,
|
|
610
|
+
prompts: stats.agent.prompts,
|
|
611
|
+
output_tokens: stats.agent.outputTokens,
|
|
612
|
+
input_tokens: stats.agent.inputTokens,
|
|
613
|
+
} : null,
|
|
614
|
+
};
|
|
615
|
+
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
616
|
+
} else {
|
|
617
|
+
renderCard(stats, setup, graded);
|
|
618
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxcontinuum/ccaudit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "A diagnostic for your Claude Code setup. Reads ~/.claude/ locally, grades you across hook coverage, project hygiene, tool balance, prompt tells, and pipeline ops. Zero install: npx @uxcontinuum/ccaudit",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|