|
1 | 1 | # Repo Map — @mcptoolshop/ai-loadout |
2 | 2 |
|
3 | 3 | ## Stack |
4 | | -- See package.json for full dependency list |
5 | 4 |
|
6 | | -## Primary seam (identified, not yet locked) |
7 | | -Matcher correctness — knowledge dispatch must resolve to the right context for the right agent |
| 5 | +- TypeScript (Node.js), zero runtime dependencies |
| 6 | +- 12 source modules, ~2,800 lines |
| 7 | +- Node built-in test runner (8 test files) |
| 8 | +- Single entry: CLI (`bin/ai-loadout`) |
| 9 | +- Library exports for programmatic use |
8 | 10 |
|
9 | | -## Validation law |
10 | | -- See package.json scripts for test/verify commands |
11 | | -- Init-only pass — detailed repo map will be written during lock |
| 11 | +## Module architecture |
| 12 | + |
| 13 | +| Layer | Modules | Purpose | I/O? | |
| 14 | +|-------|---------|---------|------| |
| 15 | +| Types | `types.ts` | LoadoutEntry, LoadoutIndex, MatchResult, MergedIndex, Budget, etc. | No | |
| 16 | +| Parsing | `frontmatter.ts` | YAML-like frontmatter extraction from markdown payloads | No | |
| 17 | +| Validation | `validate.ts` | Structural validation of indexes (duplicate IDs, missing fields, budget) | No | |
| 18 | +| Matching | `match.ts` | Deterministic keyword/pattern scoring against task descriptions | No | |
| 19 | +| Merging | `merge.ts` | Deterministic layer merge with conflict tracking and provenance | No | |
| 20 | +| Tokens | `tokens.ts` | Token estimation (chars / 4 heuristic) | No | |
| 21 | +| Analysis | `analysis.ts` | Dead entry detection, keyword overlap, budget breakdown | No | |
| 22 | +| Resolution | `resolve.ts` | Layer discovery (4 canonical locations), file loading, merge orchestration | Yes (reads) | |
| 23 | +| Runtime | `runtime.ts` | Agent API: planLoad, recordLoad, manualLookup | Yes (reads + appends) | |
| 24 | +| Usage | `usage.ts` | Append-only JSONL event logging, usage summarization | Yes (reads + appends) | |
| 25 | +| CLI | `cli.ts` | Command router (resolve, explain, usage, dead, overlaps, budget) | Yes | |
| 26 | +| Exports | `index.ts` | Public API surface | No | |
| 27 | + |
| 28 | +**Key architectural property:** All core logic (match, merge, validate, analysis) is pure functions. No filesystem, no network, no side effects. I/O is isolated to resolve/runtime/usage/cli layers. |
| 29 | + |
| 30 | +## Primary seam: Knowledge dispatch correctness |
| 31 | + |
| 32 | +### Dispatch decision flow |
| 33 | + |
| 34 | +``` |
| 35 | +planLoad(task) |
| 36 | + ├─ resolveLoadout() |
| 37 | + │ ├─ discoverLayers(): check global, org, project, session in fixed order |
| 38 | + │ │ └─ missing/malformed layers: silently skipped, recorded in searched[] |
| 39 | + │ └─ mergeIndexes(): later layer overrides earlier for same entry ID |
| 40 | + │ └─ all overrides tracked as conflicts with resolution: "override" |
| 41 | + │ |
| 42 | + ├─ matchLoadout(task, merged.index) |
| 43 | + │ ├─ tokenize(task): lowercase, strip non-alphanum, split, discard ≤1 char |
| 44 | + │ ├─ scoreEntry() per entry: |
| 45 | + │ │ ├─ core: score=1.0 (always included) |
| 46 | + │ │ ├─ manual: score=0 (never auto-included) |
| 47 | + │ │ └─ domain: (matchedKeywords/totalKeywords) + patternBonus(0.2) |
| 48 | + │ ├─ filter: score ≥ MIN_SCORE (0.1) |
| 49 | + │ └─ sort: score desc, then tokens_est asc |
| 50 | + │ |
| 51 | + └─ separate into: preload (core) / onDemand (domain ≥ 0.1) / manual (rest) |
| 52 | +``` |
| 53 | + |
| 54 | +### Contract surfaces that must stay synchronized |
| 55 | + |
| 56 | +| Surface | Location | What it governs | |
| 57 | +|---------|----------|-----------------| |
| 58 | +| MIN_SCORE threshold | `match.ts:17` | Hard boundary: domain entries below 0.1 are excluded | |
| 59 | +| Scoring formula | `match.ts:66-77` | keyword ratio + pattern bonus (0.2), capped at 1.0 | |
| 60 | +| Layer order | `resolve.ts:93-108` | global → org → project → session, fixed | |
| 61 | +| Override rule | `merge.ts` | Later layer wins for same entry ID, always | |
| 62 | +| Reason strings | `match.ts:104-110` | Machine-readable match explanation per entry | |
| 63 | +| Provenance | `merge.ts` → `runtime.ts` | Entry ID → source layer name mapping | |
| 64 | +| Conflict tracking | `merge.ts` | Every override recorded with layers and resolution | |
| 65 | + |
| 66 | +### Liar-path surfaces (where wrong dispatch could look right) |
| 67 | + |
| 68 | +| Risk | Where | Observable? | |
| 69 | +|------|-------|-------------| |
| 70 | +| Ambiguous keywords → wrong entry loads | `match.ts` scoring | Yes: `overlaps` command detects shared keywords | |
| 71 | +| Correct entry excluded by threshold | `match.ts:97` MIN_SCORE filter | No recovery — intentional hard filter | |
| 72 | +| Layer override silently replaces better version | `merge.ts` override logic | Yes: `explain` command shows full override chain | |
| 73 | +| Malformed layer silently skipped | `resolve.ts:122-125` catch block | Partially: marked as not found in searched[], but not distinguishable from genuinely missing | |
| 74 | +| Stale index routes to outdated payloads | Outside system scope | Yes: `dead` + `usage` commands detect drift over time | |
| 75 | +| Token estimate wildly off | `tokens.ts` chars/4 heuristic | Yes: `budget` command compares estimated vs observed | |
| 76 | + |
| 77 | +## Validation |
| 78 | + |
| 79 | +- `npm test` — 8 test files via Node `--test` |
| 80 | +- `npm run build` — TypeScript compilation |
| 81 | +- Key tests: `match.test.ts` (scoring determinism, threshold enforcement), `resolve.test.ts` (layer discovery, merge, conflict tracking) |
0 commit comments