@chimix/agentscan 0.2.1 → 0.3.0

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 (3) hide show
  1. package/README.md +9 -12
  2. package/dist/cli.js +50 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -176,21 +176,18 @@ Flags for `check`:
176
176
  ## Sample output
177
177
 
178
178
  ```text
179
- agentscan v0.1.0 — touchagency
179
+ agentscan v0.3.0 — touchagency
180
180
 
181
- Stack: 46 deps · 54 skills · 1 mcp · 2 agents · packageManager=bun
181
+ Scanned: 46 deps · 54 skills · 1 mcp · 2 agents · packageManager=bun
182
182
 
183
- WARN hook:PreToolUse:.claude/hooks/guard-destructive-bash.js
184
- rule:hook.missing-script
185
- PreToolUse hook points at a script that does not exist: .claude/hooks/guard-destructive-bash.js
186
- evidence: hook PreToolUse @ …/.claude/settings.json · script .claude/hooks/guard-destructive-bash.js
187
-
188
- WARN hook:PreToolUse:.claude/hooks/protect-artists-json.js
189
- rule:hook.missing-script
190
- PreToolUse hook points at a script that does not exist: .claude/hooks/protect-artists-json.js
191
- evidence: hook PreToolUse @ …/.claude/settings.json · script .claude/hooks/protect-artists-json.js
183
+ WARN rule:hook.missing-script ×6
184
+ PreToolUse hook points at a script that does not exist
185
+ PostToolUse @ .claude/settings.json · .claude/hooks/notify-related-tests.js
186
+ PreToolUse @ .claude/settings.json · .claude/hooks/guard-destructive-bash.js
187
+ PreToolUse @ .claude/settings.json · .claude/hooks/protect-artists-json.js
188
+ PreToolUse @ .claude/settings.json · .claude/hooks/protect-env.js
192
189
 
193
- Summary: 6 warn · 4 info hidden (--verbose) · score 40/100
190
+ Summary: 6 warn · 4 info hidden (--verbose) · score 40/100 broken
194
191
  ```
195
192
 
196
193
  The `Stack:` line is orientation only — which project, how big. The summary lists
package/dist/cli.js CHANGED
@@ -12534,6 +12534,21 @@ function score(findings) {
12534
12534
  }
12535
12535
  return Math.max(0, 100 - deduction);
12536
12536
  }
12537
+ function scoreLabel(points) {
12538
+ if (points === 100) {
12539
+ return "clean";
12540
+ }
12541
+ if (points >= 90) {
12542
+ return "good";
12543
+ }
12544
+ if (points >= 70) {
12545
+ return "needs work";
12546
+ }
12547
+ if (points >= 50) {
12548
+ return "poor";
12549
+ }
12550
+ return "broken";
12551
+ }
12537
12552
 
12538
12553
  // src/report/exit-code.ts
12539
12554
  function exitCode(findings, failOn, failUnder) {
@@ -12685,10 +12700,10 @@ function renderText(args) {
12685
12700
  lines.push(` no package.json in ${safe(args.resolvedFrom)} — scanned ${safe(facts.root)}`);
12686
12701
  }
12687
12702
  lines.push("");
12688
- lines.push(`Stack: ${formatStack(facts)}`);
12703
+ lines.push(`Scanned: ${formatStack(facts)}`);
12689
12704
  lines.push("");
12690
- for (const f of visible) {
12691
- lines.push(...formatFinding(f));
12705
+ for (const group of groupByRule(visible)) {
12706
+ lines.push(...formatGroup(group, facts.root));
12692
12707
  lines.push("");
12693
12708
  }
12694
12709
  lines.push(summary);
@@ -12712,17 +12727,38 @@ function formatStack(facts) {
12712
12727
  `packageManager=${facts.packageManager}`
12713
12728
  ].join(" · ");
12714
12729
  }
12715
- function formatFinding(f) {
12730
+ function groupByRule(findings) {
12731
+ const byRule = new Map;
12732
+ for (const f of findings) {
12733
+ const bucket = byRule.get(f.ruleId);
12734
+ if (bucket === undefined) {
12735
+ byRule.set(f.ruleId, [f]);
12736
+ } else {
12737
+ bucket.push(f);
12738
+ }
12739
+ }
12740
+ return [...byRule.values()];
12741
+ }
12742
+ function shortPath(value, root) {
12743
+ return value.split(`${root}/`).join("");
12744
+ }
12745
+ function formatGroup(group, root) {
12746
+ const first = group[0];
12747
+ const count = group.length;
12716
12748
  const out = [];
12717
- out.push(`${actionColumn(f.action)} ${safe(f.subject)}`);
12718
- out.push(` rule:${safe(f.ruleId)}`);
12719
- out.push(` ${safe(f.message)}`);
12720
- if (f.evidence.length > 0) {
12721
- const ev = f.evidence.map((e) => `${safe(e.kind)} ${safe(e.value)}`).join(" · ");
12722
- out.push(` evidence: ${ev}`);
12749
+ out.push(`${actionColumn(first.action)} rule:${safe(first.ruleId)}${count > 1 ? ` ×${count}` : ""}`);
12750
+ out.push(` ${safe(count === 1 ? first.message : ruleHeadline(first))}`);
12751
+ for (const f of group) {
12752
+ const where = f.evidence.filter((e) => e.kind !== "count" && e.kind !== "threshold").map((e) => shortPath(e.value, root));
12753
+ const location = where.length > 0 ? where.join(" · ") : f.subject;
12754
+ out.push(` ${safe(shortPath(location, root))}`);
12723
12755
  }
12724
12756
  return out;
12725
12757
  }
12758
+ function ruleHeadline(f) {
12759
+ const cut = f.message.indexOf(": ");
12760
+ return cut === -1 ? f.message : f.message.slice(0, cut);
12761
+ }
12726
12762
  function formatSummary(findings, verbose) {
12727
12763
  const counts = {
12728
12764
  keep: 0,
@@ -12746,14 +12782,15 @@ function formatSummary(findings, verbose) {
12746
12782
  parts.push(`${infoHidden} info hidden (--verbose)`);
12747
12783
  }
12748
12784
  const points = score(findings);
12785
+ const scored = `score ${points}/100 ${scoreLabel(points)}`;
12749
12786
  if (parts.length === 0) {
12750
- return `Summary: no findings · score ${points}/100`;
12787
+ return `Summary: no findings · ${scored}`;
12751
12788
  }
12752
- return `Summary: ${parts.join(" · ")} · score ${points}/100`;
12789
+ return `Summary: ${parts.join(" · ")} · ${scored}`;
12753
12790
  }
12754
12791
 
12755
12792
  // src/version.ts
12756
- var VERSION = "0.2.1";
12793
+ var VERSION = "0.3.0";
12757
12794
 
12758
12795
  // src/commands/check.ts
12759
12796
  async function runCheck(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chimix/agentscan",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Find broken agent configuration in a project — hooks whose scripts are gone, MCP servers that cannot start, skills that disagree with their lockfile",
5
5
  "type": "module",
6
6
  "bin": {