efaimo 0.1.2 → 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 (45) hide show
  1. package/CHANGELOG.md +160 -1
  2. package/README.md +75 -6
  3. package/SKILL.md +14 -7
  4. package/dist/check/diff.d.ts +124 -0
  5. package/dist/check/diff.js +165 -0
  6. package/dist/cli.js +237 -22
  7. package/dist/core/engine.d.ts +2 -1
  8. package/dist/core/engine.js +4 -0
  9. package/dist/core/types.d.ts +144 -0
  10. package/dist/find/bm25.d.ts +77 -0
  11. package/dist/find/bm25.js +107 -0
  12. package/dist/find/find.d.ts +122 -0
  13. package/dist/find/find.js +405 -0
  14. package/dist/find/tokenize.d.ts +64 -0
  15. package/dist/find/tokenize.js +116 -0
  16. package/dist/index.d.ts +7 -3
  17. package/dist/index.js +14 -3
  18. package/dist/reporters/json.d.ts +19 -1
  19. package/dist/reporters/json.js +13 -2
  20. package/dist/reporters/markdown.d.ts +2 -1
  21. package/dist/reporters/markdown.js +109 -11
  22. package/dist/reporters/pretty.d.ts +25 -1
  23. package/dist/reporters/pretty.js +228 -9
  24. package/dist/rules/find/index.d.ts +4 -0
  25. package/dist/rules/find/index.js +262 -0
  26. package/dist/rules/skill/index.js +32 -1
  27. package/dist/rules/version.d.ts +26 -0
  28. package/dist/rules/version.js +26 -0
  29. package/dist/testing/anthropicRunner.d.ts +30 -0
  30. package/dist/testing/anthropicRunner.js +43 -8
  31. package/dist/testing/harness.d.ts +32 -1
  32. package/dist/testing/harness.js +28 -3
  33. package/dist/testing/stats.d.ts +16 -0
  34. package/dist/testing/stats.js +26 -0
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/dist/weigh/anthropicExact.d.ts +12 -1
  38. package/dist/weigh/anthropicExact.js +9 -1
  39. package/dist/weigh/weigh.js +10 -3
  40. package/docs/INTEGRATIONS.md +15 -1
  41. package/docs/METHODOLOGY.md +110 -6
  42. package/docs/RULES.md +40 -3
  43. package/examples/scenario.crm.yaml +8 -0
  44. package/examples/scenario.example.yaml +8 -0
  45. package/package.json +3 -1
package/docs/RULES.md CHANGED
@@ -6,9 +6,14 @@ Severities: **error** (will bite you), **warn** (should fix), **info** (worth kn
6
6
  Grade starts at 100; each error costs 15, each warning 5, each info 1.
7
7
  `A >= 90, B >= 80, C >= 70, D >= 60, else F`.
8
8
 
9
+ Every JSON report carries a `rulesVersion`. The tool version does not identify a ruleset on its own: a patch
10
+ release can change what a rule fires on, so a published grade is only
11
+ reproducible next to the ruleset that produced it.
12
+
9
13
  MCP checks split into **2026-07-28 readiness** (E101-E118) and **quality**
10
- (E121-E128 and E130, with no E129); skill checks are S1xx. **Only quality and skill findings are
11
- graded.** Readiness findings are reported as a separate, ungraded **migration
14
+ (E121-E128 and E130, with no E129); skill checks are S1xx; **findability**
15
+ (E141-E145) is a third family reported by `efaimo find`.
16
+ **Only quality and skill findings are graded.** Readiness findings are reported as a separate, ungraded **migration
12
17
  diff**: the two answer different questions. The grade is what a model
13
18
  experiences from this tool surface; readiness is whether a 2026-07-28 client can
14
19
  talk to this server. Combining them scored the official reference server a C(79)
@@ -54,7 +59,7 @@ never reused, so a gap is permanent and is better stated than smoothed over.
54
59
  | E122 | warn | description misses 3+ of 4 quality axes (length, when-to-use, params documented, mentions result), mirrors Glama's tool-definition-quality dimensions, computed locally |
55
60
  | E123 | warn/info | no tools declare annotations; a destructive-looking tool lacks `destructiveHint` |
56
61
  | E124 | warn | many undocumented parameters, or an oversized `enum` inflating every prompt |
57
- | E125 | warn | tool count high enough (30+, 60+) to degrade routing and inflate context |
62
+ | E125 | warn | tool count high enough (30+, 60+) to degrade routing and inflate context. The lower boundary is not ours: Anthropic's tool search documentation states that "Claude's ability to pick the right tool degrades once you exceed 30-50 available tools". The 60 boundary is ours, and has no published source |
58
63
  | E126 | warn/info | tool names mix conventions or exceed 64 chars |
59
64
  | E127 | warn | a single tool definition costs 800+ tokens (needs `weigh` data) |
60
65
  | E128 | warn | total tool-definition tax over ~10k / ~25k tokens, estimated (needs `weigh` data); hard CI failure is left to the `--max-tokens`/`--diff` gate |
@@ -71,6 +76,38 @@ never reused, so a gap is permanent and is better stated than smoothed over.
71
76
  | S105 | info | instruction-injection patterns in the skill body or description (shallow heuristic, never a security verdict). **Reported but never scored** | internal |
72
77
  | S106 | error/warn/info | referenced file missing, escaping the skill dir (`..`), or nested more than one level deep | agentskills.io |
73
78
 
79
+ ## Findability (E141-E145)
80
+
81
+ Reported by `efaimo find`, never by `check`, and **never graded**. They answer a
82
+ question the other two families do not: when a host marks tools
83
+ `defer_loading: true`, the definitions stay out of the context window until a
84
+ search finds them, so a tool nothing surfaces costs nothing and does nothing.
85
+ Anthropic recommends turning that on once definitions pass ~10k tokens.
86
+
87
+ `find` prints two measured proportions, not a letter grade (ADR-030), and they
88
+ are different kinds of claim:
89
+
90
+ - **`distinct`** is a property of the catalog. A tool that owns no term the
91
+ other tools lack cannot be matched by any query that does not also match a
92
+ competitor. No model of how anyone searches is involved. This is the headline
93
+ and the number `--min-distinct` gates on.
94
+ - **`probe`** is a simulation: BM25 over the four searchable fields, each tool
95
+ queried with the top terms of its own description. It reads 100% on the
96
+ official reference server and on `@playwright/mcp`, so it is a floor test
97
+ that catches an empty description or a literal duplicate, not a ranking. The
98
+ output says so every run.
99
+
100
+ Method, parameters and limits: [METHODOLOGY.md](./METHODOLOGY.md).
101
+
102
+ | id | sev | what it catches |
103
+ |---|---|---|
104
+ | E141 | warn | the tool owns no term that no other tool has, so no search returns it without also returning a competitor. The one rule here that is not a heuristic |
105
+ | E142 | warn | the probe does not return the tool inside the result window (default 5), or its description offers no word to search for at all |
106
+ | E143 | warn | two tools score identically for one of their own queries, so only the alphabetical tie-break separates them |
107
+ | E144 | info | the tool name is built only from generic words (`run`, `execute_query`), so a broad pattern search reaches it only through its description |
108
+ | E145 | warn | Anthropic's guidance recommends tool search for a catalog this shape (10 or more tools, or over 10k tokens of definitions) **and** some tools cannot be singled out: once the catalog is deferred, those tools cost nothing and do nothing |
109
+ | E146 | info | every word the tool owns comes from its own name, so nothing in its description is unique. Names are searchable, so this is not E141; it means only someone who already knows the name can single it out |
110
+
74
111
  ## Notes on heuristics
75
112
 
76
113
  Rules that scan **source code** (E101-E104, E108, E110, E111, E114, E115) are
@@ -4,7 +4,15 @@
4
4
  name: contoso-crm-import helps on an unknowable format
5
5
  skill: ./contoso-crm-import
6
6
  model: claude-sonnet-5
7
+ # 8, because that is what the two committed runs in the README used. The dry
8
+ # run prints what a plan this size can detect: at 8 per arm nothing under about
9
+ # 63 points can reach p < 0.05, so raise it for anything less clear-cut than
10
+ # these two. The default when the key is absent is 20.
7
11
  trials: 8
12
+
13
+ # The judge defaults to the model above, which means a model grades its own
14
+ # answers. Point it somewhere else to remove that. (unreleased: needs 0.2.0)
15
+ # judge_model: claude-opus-5
8
16
  task: |
9
17
  Prepare these contacts for Contoso CRM import:
10
18
 
@@ -4,7 +4,15 @@
4
4
  name: csv-cleanup helps on a messy CSV
5
5
  skill: ./csv-cleanup
6
6
  model: claude-sonnet-5
7
+ # 8, because that is what the two committed runs in the README used. The dry
8
+ # run prints what a plan this size can detect: at 8 per arm nothing under about
9
+ # 63 points can reach p < 0.05, so raise it for anything less clear-cut than
10
+ # these two. The default when the key is absent is 20.
7
11
  trials: 8
12
+
13
+ # The judge defaults to the model above, which means a model grades its own
14
+ # answers. Point it somewhere else to remove that. (unreleased: needs 0.2.0)
15
+ # judge_model: claude-opus-5
8
16
  task: |
9
17
  Clean this CSV and summarize what you changed:
10
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "efaimo",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Audit what your agent loads: quality and context cost for MCP servers and Agent Skills",
5
5
  "keywords": [
6
6
  "mcp",
@@ -58,6 +58,8 @@
58
58
  "build": "tsc -p tsconfig.build.json",
59
59
  "typecheck": "tsc --noEmit",
60
60
  "test": "vitest run",
61
+ "preflight": "node scripts/preflight.mjs",
62
+ "preflight:fast": "node scripts/preflight.mjs --fast",
61
63
  "spec:drift": "node scripts/spec-drift.mjs",
62
64
  "test:watch": "vitest",
63
65
  "prepublishOnly": "npm run typecheck && npm run build && npm run test"