capman 0.4.2 → 0.4.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/CODEBASE.md +393 -0
  3. package/README.md +1 -1
  4. package/bin/capman.js +11 -724
  5. package/bin/lib/cmd-demo.js +180 -0
  6. package/bin/lib/cmd-explain.js +72 -0
  7. package/bin/lib/cmd-generate.js +280 -0
  8. package/bin/lib/cmd-help.js +26 -0
  9. package/bin/lib/cmd-init.js +19 -0
  10. package/bin/lib/cmd-inspect.js +33 -0
  11. package/bin/lib/cmd-run.js +71 -0
  12. package/bin/lib/cmd-validate.js +32 -0
  13. package/bin/lib/shared.js +77 -0
  14. package/dist/cjs/cache.d.ts.map +1 -1
  15. package/dist/cjs/cache.js +8 -2
  16. package/dist/cjs/cache.js.map +1 -1
  17. package/dist/cjs/engine.d.ts +58 -1
  18. package/dist/cjs/engine.d.ts.map +1 -1
  19. package/dist/cjs/engine.js +312 -12
  20. package/dist/cjs/engine.js.map +1 -1
  21. package/dist/cjs/generator.d.ts.map +1 -1
  22. package/dist/cjs/generator.js +4 -0
  23. package/dist/cjs/generator.js.map +1 -1
  24. package/dist/cjs/index.d.ts +1 -1
  25. package/dist/cjs/index.d.ts.map +1 -1
  26. package/dist/cjs/index.js.map +1 -1
  27. package/dist/cjs/learning.d.ts.map +1 -1
  28. package/dist/cjs/learning.js +7 -2
  29. package/dist/cjs/learning.js.map +1 -1
  30. package/dist/cjs/matcher.d.ts.map +1 -1
  31. package/dist/cjs/matcher.js +23 -27
  32. package/dist/cjs/matcher.js.map +1 -1
  33. package/dist/cjs/parser.js +2 -1
  34. package/dist/cjs/parser.js.map +1 -1
  35. package/dist/cjs/resolver.js +6 -2
  36. package/dist/cjs/resolver.js.map +1 -1
  37. package/dist/cjs/types.d.ts +27 -0
  38. package/dist/cjs/types.d.ts.map +1 -1
  39. package/dist/cjs/version.d.ts +1 -1
  40. package/dist/cjs/version.js +1 -1
  41. package/dist/esm/cache.d.ts +49 -0
  42. package/dist/esm/cache.js +8 -2
  43. package/dist/esm/engine.d.ts +138 -0
  44. package/dist/esm/engine.js +312 -12
  45. package/dist/esm/generator.d.ts +7 -0
  46. package/dist/esm/generator.js +4 -0
  47. package/dist/esm/index.d.ts +47 -0
  48. package/dist/esm/learning.d.ts +55 -0
  49. package/dist/esm/learning.js +7 -2
  50. package/dist/esm/logger.d.ts +21 -0
  51. package/dist/esm/matcher.d.ts +6 -0
  52. package/dist/esm/matcher.js +23 -27
  53. package/dist/esm/parser.d.ts +10 -0
  54. package/dist/esm/parser.js +2 -1
  55. package/dist/esm/resolver.d.ts +21 -0
  56. package/dist/esm/resolver.js +6 -2
  57. package/dist/esm/schema.d.ts +740 -0
  58. package/dist/esm/types.d.ts +136 -0
  59. package/dist/esm/version.d.ts +1 -0
  60. package/dist/esm/version.js +1 -1
  61. package/package.json +5 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,153 @@
1
+ # Changelog
2
+
3
+ All notable changes to capman are documented here.
4
+
5
+ ---
6
+
7
+ ## [0.4.4] — 2026-04-05
8
+ ### Fixed
9
+ - Rate limit double-counting on LLM failure — `recordLLMFailure()` no longer increments `llmCallsThisMinute` (slot already reserved by `checkLLMAllowed()`)
10
+ - Negative `windowResetIn` in rate limit message — recalculates elapsed after window reset
11
+ - Hallucinated capability ID from LLM now correctly returns `out_of_scope` with `confidence: 0` instead of contradictory state
12
+ - `null` params no longer written as literal `"null"` into API URLs or nav targets
13
+ - Empty string `userId` now correctly injected into session params (was skipped by falsy check)
14
+ - `FileCache` and `FileLearningStore` now validate JSON structure before loading — corrupt or unexpected format starts fresh with a warning instead of silently emptying
15
+ - `explain()` privacy check now mirrors `resolve()` exactly — unauthenticated admin access correctly reports "requires authentication" not "requires admin role"
16
+ - `getFlag()` in CLI now errors clearly when a flag is provided without a value (e.g. `--from` with no path)
17
+ - `toSnakeCase()` in parser now strips trailing underscores (e.g. `"__init__"` → `"init"` not `"init_"`)
18
+ - Nav param values now URL-encoded in `resolveNav()` — matches API resolver behavior
19
+ - Removed dead `paramHints` computation in `extractParams()` — was computed but never used
20
+ - `MatchResult` in resolver `No match` test now includes required `candidates: []` field
21
+ - `matchWithLLM` correctly imported in matcher tests
22
+
23
+ ### Tests
24
+ - 73 tests passing (up from 67)
25
+ - Added null param URL tests — API and nav
26
+ - Added nav URL encoding test
27
+ - Added empty string userId injection test
28
+ - Added LLM hallucinated capability ID test
29
+ - Added undefined LLM reasoning graceful handling test
30
+
31
+ ---
32
+
33
+ ## [0.4.3] — 2026-04-03
34
+ ### Added
35
+ - `CapmanEngine.explain(query)` — explains what would match without executing
36
+ - Returns all candidates with per-candidate human-readable explanations
37
+ - Shows `wouldExecute.action` — what API call or nav would happen
38
+ - Shows `wouldExecute.blocked` — if privacy would prevent execution
39
+ - Fully respects rate limiting and circuit breaker (mirrors `ask()` logic)
40
+ - `ExplainResult` and `ExplainCandidate` types exported from public API
41
+ - `capman explain "query"` CLI command — shows full explanation in terminal
42
+ - LLM rate limiting and circuit breaker in `CapmanEngine`
43
+ - `maxLLMCallsPerMinute` — hard rate limit (default: 60)
44
+ - `llmCooldownMs` — minimum ms between consecutive LLM calls (default: 0)
45
+ - `llmCircuitBreakerThreshold` — failures before circuit opens (default: 3)
46
+ - `llmCircuitBreakerResetMs` — ms before circuit resets (default: 60000)
47
+ - `balanced` and `accurate` modes both respect all limits
48
+ - `explain()` shares the same rate limit state as `ask()`
49
+
50
+ ### Fixed
51
+ - `explain()` now mirrors `ask()` matching logic exactly — balanced mode escalates to LLM when confidence < threshold
52
+ - `matchWithLLM` internal try-catch removed — errors propagate to engine for proper circuit breaker tracking
53
+ - Removed `?? []` on required `candidates` field in trace building
54
+ - Removed `?.` on `candidates` in CLI `--debug` block
55
+ - Fixed mixed indentation in `ask()` switch statement
56
+
57
+ ---
58
+
59
+ ## [0.4.2] — 2026-02-01
60
+ ### Added
61
+ - `parseOpenAPI(specPathOrUrl)` — parses OpenAPI 3.x and Swagger 2.x specs into capman configs
62
+ - Reads local files or fetches from URL
63
+ - Extracts path params, query params, and request body fields
64
+ - Infers privacy scope from security schemes — bearer → `user_owned`, admin tags → `admin`
65
+ - Generates natural language examples from operation summaries
66
+ - Supports JSON specs; YAML requires `js-yaml` installed
67
+ - `capman generate --from <path|url>` — generate manifest from OpenAPI/Swagger spec
68
+ - `capman generate --ai` — AI-assisted manifest generation from plain English description
69
+ - Detects `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `OPENROUTER_API_KEY` automatically
70
+ - Validates generated config with Zod before writing
71
+ - `ParseResult` type exported from public API
72
+ - 9 new parser tests covering all extraction and inference paths
73
+
74
+ ### Fixed
75
+ - `bin/capman.js` `generate` command wrapped in async IIFE for proper async support
76
+ - OpenAPI duplicate capability IDs resolved automatically with method suffix
77
+
78
+ ---
79
+
80
+ ## [0.4.1] — 2026-03-28
81
+ ### Fixed
82
+ - Prompt injection sanitization in `matchWithLLM` — query now passed as JSON field
83
+ - `ask()` now delegates to `CapmanEngine` internally — eliminates logic duplication
84
+ - `FileLearningStore` and `MemoryLearningStore` now cap at 10,000 entries with oldest-first pruning
85
+ - Post-match cache key now uses `capabilityId + params` instead of raw query — higher hit rate
86
+ - Removed duplicate `AskOptions` interface declaration in `index.ts`
87
+ - Removed dead imports (`_match`, `_matchWithLLM`, `_resolve`) from `index.ts`
88
+ ---
89
+
90
+ ## [0.4.0] — 2026-03-xx
91
+ ### Added
92
+ - `CapmanEngine` class — unified entry point with caching, learning, and tracing
93
+ - `ExecutionTrace` — structured trace returned with every `engine.ask()` result
94
+ - `MatchCandidate[]` — all scored candidates returned, not just the winner
95
+ - `capman run "query" --debug` CLI command — shows all candidate scores
96
+ - `capman demo` CLI command — live demo with zero config
97
+ - Configurable retries and timeout on API resolver
98
+ - `MemoryCache`, `FileCache`, `ComboCache` — pluggable cache backends
99
+ - `FileLearningStore`, `MemoryLearningStore` — usage analytics and keyword index
100
+ - `MatchMode` — `cheap | balanced | accurate` matching modes
101
+
102
+ ### Fixed
103
+ - Optional params no longer get garbage fallback values
104
+ - `candidates` field made required (was optional `?`)
105
+ - Empty query and LLM paths now correctly set `candidates: []`
106
+ - `generate()` now deep-copies capabilities — prevents config mutation
107
+ - `MemoryCache` now has 512-entry cap with oldest-first eviction
108
+ - `fetchWithRetry` converted from recursive to iterative — no stack overflow risk
109
+
110
+ ---
111
+
112
+ ## [0.3.0] — 2026-03-xx
113
+ ### Added
114
+ - `CapmanEngine` initial design with cache and learning stores
115
+ - `FileLearningStore` — persists query history and keyword index
116
+ - `ComboCache` — memory-first with file fallback
117
+ - `scripts/version.js` — prebuild script keeps `src/version.ts` in sync
118
+ - Dual ESM/CJS build verification in CI
119
+
120
+ ### Fixed
121
+ - Default stores changed to memory-only — no silent filesystem writes
122
+ - `FileCache` and `FileLearningStore` converted to async `fs.promises`
123
+ - Shared `computeStats()` helper — eliminates code duplication
124
+
125
+ ---
126
+
127
+ ## [0.2.0] — 2026-03-xx
128
+ ### Added
129
+ - Dual CJS + ESM build (`dist/cjs/` and `dist/esm/`)
130
+ - `MatchMode` — `cheap | balanced | accurate`
131
+ - `AuthContext` — privacy enforcement per capability
132
+ - `ApiCallResult` with `status` and `data` fields
133
+ - Configurable `retries` and `timeoutMs` on resolver
134
+ - `setLogLevel()` exported from public API
135
+
136
+ ### Fixed
137
+ - POST/PUT/DELETE requests no longer silently dropped
138
+ - `extractParams` now extracts real values from queries
139
+ - Stopword filtering in scorer
140
+ - Zod runtime validation on config and manifest load
141
+ - `files` field in `package.json` — clean npm publish
142
+
143
+ ---
144
+
145
+ ## [0.1.0] — 2026-03-xx
146
+ ### Added
147
+ - Initial release
148
+ - CLI: `init`, `generate`, `validate`, `inspect`
149
+ - SDK: `match()`, `matchWithLLM()`, `resolve()`, `ask()`
150
+ - Two-tier matching: keyword-first, LLM fallback
151
+ - Privacy scopes: `public`, `user_owned`, `admin`
152
+ - Zod schema validation
153
+ - GitHub Actions CI
package/CODEBASE.md ADDED
@@ -0,0 +1,393 @@
1
+ # Codebase Map
2
+
3
+ A guide to every file in capman — what it does, what it exports, and how it connects to everything else.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ ```
10
+ capman/
11
+ ├── src/ ← TypeScript source — compiled to dist/
12
+ ├── dist/
13
+ │ ├── cjs/ ← CommonJS build (Node require)
14
+ │ └── esm/ ← ES Module build (bundlers, import)
15
+ ├── bin/ ← CLI entry point and command modules
16
+ │ └── lib/ ← one file per CLI command
17
+ ├── tests/ ← Vitest test suites
18
+ ├── scripts/ ← build-time utilities
19
+ └── test/ ← live integration tests (not in CI)
20
+ ```
21
+
22
+ ---
23
+
24
+ ## src/
25
+
26
+ ### `src/types.ts`
27
+ All TypeScript types and interfaces. No logic — pure declarations.
28
+
29
+ Key exports:
30
+ - `Capability`, `CapabilityParam`, `Manifest`, `CapmanConfig` — core data shapes
31
+ - `MatchResult` — what `match()` returns, including `candidates: MatchCandidate[]`
32
+ - `MatchCandidate` — `{ capabilityId, score, matched }` — all scored candidates
33
+ - `ResolveResult`, `ApiCallResult` — what `resolve()` returns, with `status` and `data`
34
+ - `ExecutionTrace`, `TraceStep` — full step-by-step trace returned by `engine.ask()`
35
+ - `ExplainResult`, `ExplainCandidate` — what `engine.explain()` returns
36
+ - `ValidationResult` — `{ valid, errors, warnings }`
37
+ - `Resolver`, `ApiResolver`, `NavResolver`, `HybridResolver` — discriminated union
38
+ - `PrivacyScope`, `ResolverType`, `HttpMethod` — enums/literals
39
+
40
+ ---
41
+
42
+ ### `src/schema.ts`
43
+ Zod runtime validation schemas. Mirrors `types.ts` but adds validation rules.
44
+
45
+ Key exports:
46
+ - `validateConfig(config)` — validates a `CapmanConfig` at load time
47
+ - `validateManifest(manifest)` — validates a `Manifest` at read time
48
+
49
+ Notable rules:
50
+ - `id` must match `/^[a-z][a-z0-9_]*$/` — snake_case only
51
+ - `description` minimum 10 characters
52
+ - Capability IDs must be unique within a manifest
53
+
54
+ ---
55
+
56
+ ### `src/generator.ts`
57
+ Manifest lifecycle — create, read, write, validate.
58
+
59
+ Key exports:
60
+ - `generate(config)` → `Manifest` — converts config to manifest, deep-copies capabilities
61
+ - `loadConfig(path?)` → `CapmanConfig` — loads `capman.config.js` via `require()`
62
+ - `writeManifest(manifest, path?)` — writes `manifest.json`
63
+ - `readManifest(path?)` → `Manifest` — reads and Zod-validates `manifest.json`
64
+ - `validate(manifest)` → `ValidationResult` — runs Zod + warns on missing examples
65
+ - `generateStarterConfig()` → `string` — returns starter `capman.config.js` content
66
+ - `VERSION` — current version string, auto-generated by `scripts/version.js`
67
+
68
+ ---
69
+
70
+ ### `src/matcher.ts`
71
+ Intent matching — keyword scoring and LLM-based matching.
72
+
73
+ Key exports:
74
+ - `match(query, manifest)` → `MatchResult`
75
+ - Scores every capability against the query
76
+ - Returns winner + all candidates with scores
77
+ - Extracts params from the query using keyword heuristics
78
+ - Returns `out_of_scope` if best score < 50%
79
+ - `matchWithLLM(query, manifest, { llm })` → `MatchResult`
80
+ - Sends structured prompt to LLM with query as JSON field (prompt injection safe)
81
+ - Returns matched capability, confidence, intent, extracted params
82
+ - Errors propagate to caller — no internal try/catch
83
+
84
+ Scoring algorithm (weights):
85
+ - Examples match: up to 60 points
86
+ - Description match: up to 30 points
87
+ - Name match: up to 10 points
88
+
89
+ Param extraction:
90
+ - `isIdParam` — single token (e.g. `order_id=1234`)
91
+ - `isNavParam` — single token after nav keywords (`to`, `open`, `show`)
92
+ - Everything else — multi-word joined with `-` (e.g. `product=blue-jacket`)
93
+ - Optional params stay `null` if no keyword match found
94
+
95
+ ---
96
+
97
+ ### `src/resolver.ts`
98
+ Capability execution — API calls, navigation, hybrid.
99
+
100
+ Key exports:
101
+ - `resolve(matchResult, params, options)` → `ResolveResult`
102
+ - Enforces privacy before executing
103
+ - Injects `auth.userId` into session params automatically
104
+ - Supports `dryRun: true` — returns call plan without executing
105
+ - Retries with `AbortController` timeout on failure
106
+ - - Returns `status` and parsed `data` from API response
107
+ - `null` and `undefined` params are never written into URLs — skipped silently
108
+ - Nav param values are URL-encoded via `encodeURIComponent` — matches API resolver behavior
109
+
110
+ `ResolveOptions`:
111
+ - `baseUrl` — prepended to all API paths
112
+ - `auth` — `{ isAuthenticated, role, userId }`
113
+ - `dryRun` — skip actual fetch
114
+ - `retries` — retry count on failure (default: 0)
115
+ - `timeoutMs` — abort timeout (default: 5000)
116
+ - `headers` — custom request headers
117
+ - `fetch` — injectable fetch function (used in tests)
118
+
119
+ Privacy enforcement:
120
+ - `public` — always allowed
121
+ - `user_owned` — requires `auth.isAuthenticated === true`
122
+ - `admin` — requires `auth.role === 'admin'`
123
+
124
+ ---
125
+
126
+ ### `src/cache.ts`
127
+ Pluggable cache backends.
128
+
129
+ Key exports:
130
+ - `CacheStore` interface — `get(key)`, `set(key, result)`, `clear()`, `size()`
131
+ - `MemoryCache` — in-memory Map, 512-entry cap with oldest-first eviction
132
+ - `FileCache` — async `fs.promises` read/write, lazy-loaded on first access
133
+ - `ComboCache` — memory-first with file fallback, promotes file hits to memory
134
+ - `normalizeQuery(query)` — lowercase + trim + collapse whitespace → cache key
135
+ - `buildCacheKey(query, capabilityId, params)` — smarter key using capability + params (exported for future post-match cache layer — not currently used by engine)
136
+
137
+ Notes:
138
+ - `FileCache` and `ComboCache` are single-instance only — concurrent writers will corrupt
139
+ - For multi-instance deployments, use a Redis adapter (planned v0.5)
140
+
141
+ ---
142
+
143
+ ### `src/learning.ts`
144
+ Usage analytics and keyword index.
145
+
146
+ Key exports:
147
+ - `LearningStore` interface — `record(entry)`, `getStats()`, `getTopCapabilities(limit)`
148
+ - `FileLearningStore` — persists to `.capman/learning.json`, caps at 10,000 entries
149
+ - `MemoryLearningStore` — in-memory only, used in tests
150
+
151
+ `LearningEntry`:
152
+ - `query`, `capabilityId`, `confidence`, `intent`, `extractedParams`
153
+ - `resolvedVia: 'keyword' | 'llm' | 'cache'`
154
+ - `timestamp`
155
+
156
+ `KeywordStats` (from `getStats()`):
157
+ - `index` — `{ word → { capabilityId → hitCount } }` — foundation for adaptive matching
158
+ - `totalQueries`, `llmQueries`, `cacheHits`, `outOfScope`
159
+
160
+ ---
161
+
162
+ ### `src/engine.ts`
163
+ The recommended API — orchestrates matching, caching, learning, and tracing.
164
+
165
+ Key exports:
166
+ - `CapmanEngine` class
167
+ - `EngineOptions` — all constructor options
168
+ - `EngineResult` — `{ match, resolution, resolvedVia, durationMs, trace }`
169
+
170
+ `CapmanEngine` methods:
171
+ - `ask(query, overrides?)` → `EngineResult` — full pipeline: cache → match → resolve → learn
172
+ - `explain(query)` → `ExplainResult` — match only, no execution, with candidate explanations
173
+ - `getStats()` → `KeywordStats | null`
174
+ - `getTopCapabilities(limit?)` → `Array<{ id, hits }>`
175
+ - `clearCache()`
176
+
177
+ Matching pipeline in `ask()`:
178
+ 1. Cache check — return immediately on hit
179
+ 2. Match — `cheap` / `balanced` / `accurate` mode
180
+ 3. Privacy check — recorded in trace
181
+ 4. Cache set — stores under normalized query key
182
+ 5. Resolve — actual API call or nav
183
+ 6. Reasoning build — human-readable array
184
+ 7. Learning record
185
+
186
+ LLM rate limiting (all modes respect these):
187
+ - `maxLLMCallsPerMinute` — sliding window (default: 60)
188
+ - `llmCooldownMs` — minimum gap between calls (default: 0)
189
+ - `llmCircuitBreakerThreshold` — failures before circuit opens (default: 3)
190
+ - `llmCircuitBreakerResetMs` — circuit reset time (default: 60,000ms)
191
+
192
+ ---
193
+
194
+ ### `src/parser.ts`
195
+ OpenAPI/Swagger → capman config converter.
196
+
197
+ Key exports:
198
+ - `parseOpenAPI(specPathOrUrl)` → `ParseResult`
199
+ - Accepts local file path or HTTP URL
200
+ - Parses JSON natively; YAML requires `js-yaml` installed
201
+ - Converts every path+method into a `Capability`
202
+ - Infers privacy from security schemes and tags
203
+ - Extracts path/query/body params
204
+ - Generates examples from operation summaries
205
+
206
+ `ParseResult`:
207
+ - `config` — ready-to-use `CapmanConfig`
208
+ - `stats` — `{ total, skipped, warnings }`
209
+
210
+ Supported: OpenAPI 3.x, Swagger 2.x (JSON or YAML)
211
+
212
+ ---
213
+
214
+ ### `src/logger.ts`
215
+ Minimal logger. Silent by default.
216
+
217
+ Key exports:
218
+ - `logger` — singleton with `debug()`, `info()`, `warn()`, `error()`
219
+ - `setLogLevel(level)` — `'silent' | 'error' | 'warn' | 'info' | 'debug'`
220
+ - `LogLevel` type
221
+
222
+ ---
223
+
224
+ ### `src/index.ts`
225
+ Public API surface. Re-exports everything the library exposes.
226
+
227
+ Notable:
228
+ - `ask(query, manifest, options?)` — convenience function, delegates to `CapmanEngine` internally
229
+ - Marked `@deprecated` — use `CapmanEngine` directly for full features
230
+ - `MatchMode` type — `'cheap' | 'balanced' | 'accurate'`
231
+ - All types, classes, and functions from all modules above
232
+
233
+ ---
234
+
235
+ ## bin/
236
+
237
+ ### `bin/capman.js`
238
+ Entry point only. Reads `command` from `process.argv` and routes to the correct module.
239
+ ~20 lines. No logic here.
240
+
241
+ ### `bin/lib/shared.js`
242
+ Shared utilities used by all command modules.
243
+
244
+ Exports:
245
+ - `args`, `command`, `flags` — parsed from `process.argv`
246
+ - `getFlag(name)` — returns value of `--name value` flag
247
+ - `c` — ANSI color codes (`reset`, `bold`, `teal`, `yellow`, `red`, `green`, `gray`)
248
+ - `log` — `{ info, success, warn, error, blank }`
249
+ - `header()` — prints capman version header
250
+ - `requireSrc()` — loads `dist/cjs/index.js`, auto-builds if missing
251
+
252
+ ### `bin/lib/cmd-init.js`
253
+ Creates `capman.config.js` starter file in current directory.
254
+
255
+ ### `bin/lib/cmd-generate.js`
256
+ Three generation paths:
257
+ - `--from <path|url>` → OpenAPI parser → `capman.config.js` + `manifest.json`
258
+ - `--ai` → LLM-assisted generation from plain English description
259
+ - _(no flags)_ → load `capman.config.js` manually → `manifest.json`
260
+
261
+ Contains `buildAIPrompt(description)` and `callLLM(provider, apiKey, prompt)`.
262
+ Supports `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `OPENROUTER_API_KEY`.
263
+
264
+ ### `bin/lib/cmd-validate.js`
265
+ Reads `manifest.json`, runs Zod validation, prints errors and warnings.
266
+ Exits with code 1 if invalid.
267
+
268
+ ### `bin/lib/cmd-inspect.js`
269
+ Prints all capabilities in `manifest.json` — name, ID, resolver type, privacy, description, first example.
270
+
271
+ ### `bin/lib/cmd-demo.js`
272
+ Live demo using a hardcoded e-commerce manifest.
273
+ Shows the full **QUERY → MATCH → EXECUTION → RESULT → EXPLANATION** blueprint for 4 sample queries.
274
+ No config or API key required.
275
+
276
+ ### `bin/lib/cmd-run.js`
277
+ Runs a single query against the current `manifest.json`.
278
+ `--debug` flag shows all candidate scores.
279
+
280
+ ### `bin/lib/cmd-explain.js`
281
+ Runs `engine.explain(query)` and prints the full explanation:
282
+ - What matched and why
283
+ - All candidates with per-candidate explanations
284
+ - What would execute (without executing)
285
+ - Whether privacy would block it
286
+
287
+ ---
288
+
289
+ ## tests/
290
+
291
+ ### `tests/matcher.test.ts`
292
+ 14 tests covering:
293
+ - Keyword scoring accuracy
294
+ - Out-of-scope detection
295
+ - Param extraction (single token, multi-word, ID params, nav params)
296
+ - `ask()` matching modes (cheap, balanced, accurate, default)
297
+
298
+ ### `tests/resolver.test.ts`
299
+ 18 tests covering:
300
+ - API resolver — dry run, path substitution, query string params
301
+ - Nav resolver — destination building
302
+ - Hybrid resolver — both API and nav
303
+ - No match — graceful failure
304
+ - Privacy enforcement — public, user_owned, admin, session injection
305
+ - Fetch error handling — network error, non-ok status, ok + data
306
+ - Retry behaviour — succeeds after N failures, exhausts retries
307
+
308
+ ### `tests/engine.test.ts`
309
+ 26 tests covering:
310
+ - Basic `ask()` — match and resolve
311
+ - Caching — cache hit, cache cleared, ComboCache promotion
312
+ - Learning — records queries, top capabilities, resolvedVia tracking
313
+ - Matching modes — cheap never calls LLM, accurate calls LLM
314
+ - Execution trace — candidates, reasoning, steps, cache hit trace
315
+ - `explain()` — matched, out of scope, candidates with explanations, wouldExecute, blocked, no side effects
316
+ - LLM rate limiting — rate limit, cooldown, circuit breaker, fallback on failure
317
+
318
+ ### `tests/parser.test.ts`
319
+ 9 tests covering:
320
+ - Capability extraction from spec
321
+ - Correct IDs from `operationId`
322
+ - Privacy inference from tags and security
323
+ - Path and query param extraction
324
+ - Request body field extraction
325
+ - Base URL extraction
326
+ - Skipping operations with insufficient info
327
+ - Error on missing file
328
+
329
+ ---
330
+
331
+ ## scripts/
332
+
333
+ ### `scripts/version.js`
334
+ Prebuild script. Reads `version` from `package.json` and writes:
335
+ ```typescript
336
+ // Auto-generated by scripts/version.js — do not edit manually
337
+ export const VERSION = '0.4.2'
338
+ ```
339
+ to `src/version.ts`. Runs automatically before every `pnpm run build`.
340
+
341
+ `src/version.ts` is gitignored.
342
+
343
+ ---
344
+
345
+ ## test/ (integration, not in CI)
346
+
347
+ ### `test/conduit.config.js`
348
+ capman config for the RealWorld Conduit app (`conduit.productionready.io`).
349
+ 8 capabilities covering all resolver types.
350
+
351
+ ### `test/test-conduit.ts`
352
+ Tests keyword matcher against live Conduit API.
353
+
354
+ ### `test/test-llm-live.ts`
355
+ Tests `matchWithLLM` and `CapmanEngine` accurate mode against live API using OpenRouter free models.
356
+
357
+ ---
358
+
359
+ ## Config files
360
+
361
+ | File | Purpose |
362
+ |---|---|
363
+ | `tsconfig.json` | CJS build → `dist/cjs/` |
364
+ | `tsconfig.esm.json` | ESM build → `dist/esm/` |
365
+ | `package.json` | Version, exports map, scripts, dependencies |
366
+ | `.github/workflows/ci.yml` | Build + test + verify dist on every push |
367
+ | `.gitignore` | Ignores `dist/`, `node_modules/`, `src/version.ts`, `.capman/` |
368
+ | `CHANGELOG.md` | All notable changes per version |
369
+ | `CODEBASE.md` | This file |
370
+
371
+ ---
372
+
373
+ ## Data flow
374
+
375
+ ```
376
+ Developer writes capman.config.js
377
+
378
+ capman generate
379
+
380
+ generator.ts → manifest.json
381
+
382
+ CapmanEngine.ask("user query")
383
+
384
+ cache.ts → cache hit? return immediately
385
+
386
+ matcher.ts → score all capabilities → pick winner
387
+
388
+ resolver.ts → enforce privacy → call API or navigate
389
+
390
+ learning.ts → record query + result
391
+
392
+ EngineResult → { match, resolution, trace, resolvedVia }
393
+ ```
package/README.md CHANGED
@@ -321,4 +321,4 @@ const result = await engine.ask('show my orders', {
321
321
 
322
322
  ## License
323
323
 
324
- MIT — [github.com/Hobbydefiningdoctory/capman]
324
+ MIT — [(github.com/Hobbydefiningdoctory/capman)](https://github.com/Hobbydefiningdoctory/capman.git)