Skip to content
This repository was archived by the owner on Jun 16, 2026. It is now read-only.

Commit 3ad0998

Browse files
mcp-tool-shopclaude
andcommitted
feat: v1.4.0 — agent runtime contract (planLoad, recordLoad, manualLookup)
Adds the portable agent integration API: planLoad() wraps the full resolve → match → decide sequence into one call. AGENT_CONTRACT.md defines integration patterns for Claude agents, MCP servers, CLIs, and editor extensions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 50d12ab commit 3ad0998

7 files changed

Lines changed: 684 additions & 4 deletions

File tree

AGENT_CONTRACT.md

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Agent Contract
2+
3+
> How any agent consumes a resolved loadout.
4+
> Version: 1.4.0
5+
6+
## Overview
7+
8+
ai-loadout provides a portable knowledge routing contract. This document defines how agents — Claude Code, MCP servers, CLI wrappers, editor extensions, or any other consumer — integrate against it.
9+
10+
The contract is three things:
11+
12+
1. **A resolved-loadout schema** — the stable output shape agents receive
13+
2. **A match-and-load sequence** — the steps agents follow
14+
3. **Integration patterns** — how different agent types wire it up
15+
16+
## The Sequence
17+
18+
Every agent follows the same five steps:
19+
20+
```
21+
1. RESOLVE — discover and merge layered indexes
22+
2. MATCH — score entries against the current task
23+
3. DECIDE — separate preload / on-demand / manual
24+
4. LOAD — read payload files into context
25+
5. RECORD — log what was loaded (optional, enables observability)
26+
```
27+
28+
Steps 1-3 are handled by `planLoad(task)`. Steps 4-5 are the agent's responsibility.
29+
30+
## API Surface
31+
32+
### `planLoad(task, opts?)`
33+
34+
The primary integration point. Returns a `LoadPlan`:
35+
36+
```typescript
37+
import { planLoad } from "@mcptoolshop/ai-loadout";
38+
39+
const plan = planLoad("set up CI pipeline for the new repo");
40+
41+
// plan.preload — MatchResult[] — load these immediately (core entries)
42+
// plan.onDemand — MatchResult[] — load when task warrants it (domain entries)
43+
// plan.manual — LoadoutEntry[] — only on explicit request
44+
// plan.provenance — Record<string, string> — entryId → source layer
45+
// plan.budget — Budget — token budget summary
46+
// plan.conflicts — MergeConflict[] — entries overridden across layers
47+
// plan.layerNames — string[] — which layers contributed
48+
// plan.preloadTokens — number — total tokens in preload set
49+
// plan.onDemandTokens — number — total tokens in on-demand set
50+
```
51+
52+
### `recordLoad(entryId, trigger, mode, tokensEst, opts?)`
53+
54+
Optional. Records that an entry was loaded into context.
55+
56+
```typescript
57+
import { recordLoad } from "@mcptoolshop/ai-loadout";
58+
59+
recordLoad("github-actions", "keyword-ci", "lazy", 330, {
60+
usagePath: ".claude/loadout-usage.jsonl",
61+
taskHash: "abc123",
62+
});
63+
```
64+
65+
### `manualLookup(id, opts?)`
66+
67+
Explicit lookup for manual-priority entries.
68+
69+
```typescript
70+
import { manualLookup } from "@mcptoolshop/ai-loadout";
71+
72+
const entry = manualLookup("xrpl-reference");
73+
if (entry) {
74+
// read entry.path, load into context
75+
}
76+
```
77+
78+
## LoadPlan Schema
79+
80+
The stable output shape agents integrate against:
81+
82+
| Field | Type | Stability | Description |
83+
|-------|------|-----------|-------------|
84+
| `preload` | `MatchResult[]` | Stable | Core entries — always load these |
85+
| `onDemand` | `MatchResult[]` | Stable | Domain entries — load when task matches |
86+
| `manual` | `LoadoutEntry[]` | Stable | Manual entries — explicit lookup only |
87+
| `provenance` | `Record<string, string>` | Stable | entryId → source layer name |
88+
| `budget` | `Budget` | Stable | Token budget from resolved index |
89+
| `conflicts` | `MergeConflict[]` | Stable | Entries defined in multiple layers |
90+
| `layerNames` | `string[]` | Stable | Contributing layer names in order |
91+
| `preloadTokens` | `number` | Stable | Sum of preload entry tokens |
92+
| `onDemandTokens` | `number` | Stable | Sum of on-demand entry tokens |
93+
94+
### MatchResult (per entry)
95+
96+
| Field | Type | Description |
97+
|-------|------|-------------|
98+
| `entry` | `LoadoutEntry` | The full entry with id, path, keywords, etc. |
99+
| `score` | `number` | 0-1, match strength |
100+
| `matchedKeywords` | `string[]` | Which keywords matched |
101+
| `matchedPatterns` | `string[]` | Which patterns matched |
102+
| `reason` | `string` | Human-readable explanation |
103+
| `mode` | `LoadMode` | `"eager"` / `"lazy"` / `"manual"` |
104+
105+
## Layer Resolution
106+
107+
The resolver checks fixed locations in a fixed order:
108+
109+
| Priority | Layer | Location |
110+
|----------|-------|----------|
111+
| 1 (lowest) | `global` | `~/.ai-loadout/index.json` |
112+
| 2 | `org` | `$AI_LOADOUT_ORG` or explicit path |
113+
| 3 | `project` | `<cwd>/.claude/loadout/index.json` |
114+
| 4 (highest) | `session` | `$AI_LOADOUT_SESSION` or explicit path |
115+
116+
Later layers override earlier ones for the same entry ID. Missing layers are normal.
117+
118+
## Integration Patterns
119+
120+
### Claude Code Agent
121+
122+
The most common pattern. CLAUDE.md references the loadout, and the agent uses keyword matching to load rules on demand.
123+
124+
```
125+
.claude/
126+
loadout/
127+
index.json ← dispatch table
128+
rules/
129+
github-actions.md ← payload files
130+
shipcheck.md
131+
...
132+
CLAUDE.md ← references loadout, instructs lazy loading
133+
```
134+
135+
The agent:
136+
1. Reads CLAUDE.md (which includes the dispatch table or a pointer to it)
137+
2. On each task, matches against the index
138+
3. Loads matching payloads via the Read tool
139+
4. Records loads to `.claude/loadout-usage.jsonl`
140+
141+
### MCP Server
142+
143+
An MCP server can expose loadout matching as a tool:
144+
145+
```
146+
Tool: match_knowledge
147+
Input: { task: "deploy to production" }
148+
Output: { entries: [...], budget: {...} }
149+
```
150+
151+
The server calls `planLoad()` internally and returns the plan. The calling agent decides what to load.
152+
153+
### CLI Wrapper
154+
155+
A CLI tool wraps the runtime for shell-based workflows:
156+
157+
```bash
158+
# What should I load for this task?
159+
ai-loadout resolve
160+
161+
# Why did this entry win?
162+
ai-loadout explain github-actions
163+
164+
# After a session, what went unused?
165+
ai-loadout dead .claude/loadout/index.json usage.jsonl
166+
```
167+
168+
### Editor Extension
169+
170+
An editor extension (VS Code, etc.) can use the runtime to suggest relevant knowledge files when the user opens a project or starts a task.
171+
172+
## Observability Contract
173+
174+
Usage recording is optional but enables three diagnostic capabilities:
175+
176+
| Capability | Function | Requires |
177+
|-----------|----------|----------|
178+
| Dead entry detection | `findDeadEntries()` | Usage log |
179+
| Budget drift analysis | `analyzeBudget()` | Usage log |
180+
| Frequency tracking | `summarizeUsage()` | Usage log |
181+
182+
Usage events are:
183+
- **Append-only** — never modified or deleted
184+
- **Local-only** — never transmitted over the network
185+
- **JSONL format** — one JSON object per line
186+
- **Optional** — the system works without recording
187+
188+
## Guarantees
189+
190+
1. **Deterministic** — same inputs produce the same plan (except timestamps)
191+
2. **Graceful degradation** — missing layers, files, or configs don't crash
192+
3. **No network** — everything is local filesystem
193+
4. **No side effects**`planLoad()` only reads; `recordLoad()` only appends
194+
5. **Backward compatible** — new fields are additive; existing fields don't change meaning
195+
6. **Zero dependencies** — no runtime deps beyond Node.js

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 1.4.0 — 2026-03-06
4+
5+
- **Agent runtime contract**: `planLoad()`, `recordLoad()`, `manualLookup()` — the canonical agent integration API
6+
- **LoadPlan**: stable output shape with preload/onDemand/manual separation, provenance, budget, token costs
7+
- **AGENT_CONTRACT.md**: portable integration guide for Claude agents, MCP servers, CLIs, and editor extensions
8+
- SPEC.md updated with runtime section and LoadPlan schema
9+
- 13 new tests (runtime), 93 total
10+
311
## 1.3.0 — 2026-03-06
412

513
- **Hierarchical resolver**: `discoverLayers()`, `resolveLoadout()` for layered indexes (global → org → project → session)

SPEC.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ai-loadout Specification
22

33
> Context-aware knowledge router for AI agents.
4-
> Version: 1.3.0
4+
> Version: 1.4.0
55
66
## Overview
77

@@ -285,11 +285,44 @@ Layers are checked in a fixed order. Later layers override earlier ones for the
285285
| `--org <path>` | Org-level index path |
286286
| `--session <path>` | Session overlay index path |
287287

288+
## Agent Runtime
289+
290+
`planLoad(task, opts?)``LoadPlan`
291+
`recordLoad(entryId, trigger, mode, tokensEst, opts?)``void`
292+
`manualLookup(id, opts?)``LoadoutEntry | undefined`
293+
294+
The runtime is the primary agent-facing API. It wraps the full sequence: resolve → match → decide → record.
295+
296+
### LoadPlan
297+
298+
| Field | Type | Stability | Description |
299+
|-------|------|-----------|-------------|
300+
| `preload` | `MatchResult[]` | Stable | Core entries — load immediately |
301+
| `onDemand` | `MatchResult[]` | Stable | Domain entries — load when task matches |
302+
| `manual` | `LoadoutEntry[]` | Stable | Manual entries — explicit lookup only |
303+
| `provenance` | `Record<string, string>` | Stable | entryId → source layer |
304+
| `budget` | `Budget` | Stable | Token budget from resolved index |
305+
| `conflicts` | `MergeConflict[]` | Stable | Entries overridden across layers |
306+
| `layerNames` | `string[]` | Stable | Contributing layer names |
307+
| `preloadTokens` | `number` | Stable | Sum of preload entry tokens |
308+
| `onDemandTokens` | `number` | Stable | Sum of on-demand entry tokens |
309+
310+
### RuntimeOptions
311+
312+
Extends `ResolveOptions` with:
313+
314+
| Field | Type | Description |
315+
|-------|------|-------------|
316+
| `usagePath` | `string?` | JSONL file path for usage recording |
317+
| `taskHash` | `string?` | Session-local task identifier |
318+
319+
See `AGENT_CONTRACT.md` for full integration guide.
320+
288321
## Design Constraints
289322

290323
- Zero production dependencies
291324
- Pure TypeScript ESM
292325
- Node ≥ 20
293326
- Deterministic: same inputs → same outputs (except `generated` timestamps)
294327
- Core types, matcher, validator, and merge are pure functions (no I/O)
295-
- Resolver and usage modules perform filesystem I/O for practical use
328+
- Resolver, runtime, and usage modules perform filesystem I/O for practical use

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@mcptoolshop/ai-loadout",
3-
"version": "1.3.0",
4-
"description": "Context-aware knowledge router for AI agents. Dispatch table, matcher, hierarchical resolver, usage tracking, analysis CLI.",
3+
"version": "1.4.0",
4+
"description": "Context-aware knowledge router for AI agents. Dispatch table, matcher, hierarchical resolver, agent runtime contract, CLI.",
55
"type": "module",
66
"bin": {
77
"ai-loadout": "./dist/cli.js"
@@ -26,6 +26,7 @@
2626
"README.md",
2727
"CHANGELOG.md",
2828
"SPEC.md",
29+
"AGENT_CONTRACT.md",
2930
"LICENSE",
3031
"SECURITY.md",
3132
"logo.png"

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ export type {
5050
EntryExplanation,
5151
ResolveOptions,
5252
} from "./resolve.js";
53+
54+
// ── Runtime (Agent Contract) ─────────────────────────────────
55+
export { planLoad, recordLoad, manualLookup } from "./runtime.js";
56+
export type { RuntimeOptions, LoadPlan } from "./runtime.js";

0 commit comments

Comments
 (0)