Gateway Module — `tools/`
1. Purpose
The tools module exposes the source-of-truth advertisement of the live gateway-side write-path Zod schemas (Dispatch 42). It exists to close the residual gap left by the Raw Twin pattern: the Claude Code MCP client caches every tool's inputSchema at session startup, so any post-startup server-side schema evolution is invisible to a running session. GET /api/tools/list returns a hand-curated SCHEMA_VERSION string plus every mutation tool's per-branch required/optional field contract, so the konnichiwagwan Phase F freshness probe can diff a session's cached view against live server state and warn the operator to restart before silent-strip bugs bite. The advertisement is deliberately hand-curated, not reflected from Zod internals — it IS a contract, and the manual duplication is the governance surface.
2. File Inventory
| File | Lines | Responsibility |
|---|---|---|
schema-introspection.ts | 366 | SCHEMA_VERSION, buildToolsList(), all branch specs (write_psychic_cache union + flat mutation tools + KG family) |
routes.ts | 31 | GET /list router with Cache-Control: no-store |
| Total | 397 |
No index.ts/types.ts — router wired directly (createToolsRouter(), mount index.ts:744); types are inline exports in schema-introspection.ts.
3. Public API Surface
REST Endpoints (mount: index.ts:744 → /api/tools)
| Method | Path | Auth | Body | Response | Side Effects |
|---|---|---|---|---|---|
| GET | /api/tools/list | Bearer | — | ToolsListResponse {schema_version, generated_at, tools[]} | None (read-only); Cache-Control: no-store to guarantee live state |
MCP Tools
None registered here. This module describes the MCP mutation tools (defined in mcp/index.ts); it does not register any.
4. Internal API
SCHEMA_VERSION(const, current value'2026-06-13a') — ISO-dated; MUST bump on any field/context_type add-remove (freshness probe diffs on this string).buildToolsList(): ToolsListResponse— assembles 11 tool specs:write_psychic_cache(9-branch discriminated union), 6 flat mutation tools (report_dispatch,report_progress,report_complete,commit_agent_memory,commit_memory,context_feedback), 4 KG tools (kg_add_triple,kg_query_entity,kg_timeline,kg_invalidate). Each carriesraw_toolsibling name +base_required/base_optional+ per-branchrequired/optional.- Exported interfaces:
ToolFieldSpec,WriteCacheTypeBranch,ToolSpec,ToolsListResponse.
5. Background Services
None.
6. Data Contracts
The advertised write-cache branches (mirror of psychic-cache/types.ts WriteCacheInputSchema):
- Base required:
mission_id,content,context_type. Base optional:agent_name,ttl_hours,tags,source_turn,dispatch_id. - Branches:
decision→decision_rationale;directive→directive_target;intel→intel_source;state_change→state_from+state_to;output→agent_name+output_url+dispatch_id(D1929/AK-439 addeddispatch_idrequired on the output branch ONLY — closes the D52 probe asymmetry);report→report_dispatch_id+report_outcome;escalation→escalation_target+escalation_reason;shadow_clone→subtasks;thread_checkpoint→7 required fields. - Flat tools emit a single synthetic
context_type='_flat'branch. KG branches carry D4 admission fields.
This introspection surface is the observable half of the Raw Twin Discipline: mcp/index.ts holds the client-facing tools (no schemas), psychic-cache/dispatch/etc. hold the Zod source of truth, and tools/ publishes the diffable contract between them.
7. Dependencies
- Gateway modules: none imported at runtime — the branch specs are hand-transcribed from the sibling modules' Zod schemas (governance-enforced parity, no code import).
- External:
express. - Environment variables: none.
8. Test Coverage
| Layer | File | Notes |
|---|---|---|
| Introspection | test/schema-introspection.test.ts | Enforces the "every tool has a raw_tool sibling" invariant; branch shape assertions |
| Routes | test/tools-routes.test.ts | GET /list response shape, no-store header |
9. Known Limitations
- The advertisement is manually curated. A new field added to a Zod branch but not to
schema-introspection.ts(or vice versa) drifts silently untilSCHEMA_VERSIONis bumped — there is no mechanical Zod↔advertisement parity test, only the "every tool has a raw twin" invariant and the CLAUDE.md Dependency Propagation Protocol. This is deliberate (the duplication IS the governance surface) but is a live drift risk (see the AK-439 comment: "no automated parity test enforces this pair"). SCHEMA_VERSIONmust be bumped by hand on every schema edit; a forgotten bump means stale sessions never receive a drift warning.- Read-only tools (
assemble_context) are excluded from the advertisement by design — drift impact there is graceful degradation, not data loss.
10. Change History
| Date | Dispatch | Summary |
|---|---|---|
| 2026-07-04 | 2296 | Module spec authored (Phase 4 §5.2), smoke-clone-2, HEAD 5c9a304 |
| — | 42 | Introspection endpoint origin; freshness-probe support |
| — | 1546 | AK-372 KG tool family + raw twins added to advertisement |
| — | 1929 | AK-439 — dispatch_id required on output branch; SCHEMA_VERSION bump |