LORE Knowledge Seam Contract
lore advanced 7 min read
ELI5
LORE and pebble speak a very precise language. Every time LORE asks pebble for data, pebble responds the same way — either “here’s what you wanted, everything is fine” or “something went wrong, here’s exactly what failed.” There are no surprises, no silent failures, and if the response shape ever changes unexpectedly, an alarm goes off.
Technical Deep Dive
The Result<T> Contract
Defined in atlas/doctrines/pebble-knowledge-seam-contract.doctrine.md and implemented in lore/src/lib/knowledge-api.ts. This is the typed failure contract that replaced the previous safe() helper which silently collapsed permission denials and missing rows into the same null UX.
type Result<T> = | { ok: true; data: T } | { ok: false; status: number; reason: string; detail?: string }Failure Classes Mapped to DegradedBanner Variants
| HTTP Status | reason | Banner Variant | UX |
|---|---|---|---|
| 502 / 503 / 504 | "outage" | Outage (red) | “Pebble is unreachable. Data shown may be stale.” |
| 403 | "permission" | Permission (amber) | “Your role cannot see this data.” |
| 422 | "shape" | Shape-drift (amber) | “Response format changed. Some data may not display.” |
| 404 | "not_found" | None — empty state rendered | ”No results found.” |
Route → MCP Tool Mapping
The 11 HTTP REST endpoints LORE proxies to pebble correspond directly to 4 MCP tools used by agents:
| HTTP Route (LORE) | MCP Tool (Agent) | Direction |
|---|---|---|
GET /api/knowledge/search | query_kb | Read |
GET /api/knowledge/decisions/:id | read_file | Read |
GET /api/knowledge/graph | get_context | Read |
POST /api/knowledge/log-decision | log_decision | Write |
GET /api/knowledge/governance | (none — UI-only) | Read |
GET /api/knowledge/decisions/:id/cairn-stones | (none — CAIRN backlink) | Read |
Shape-Drift Detection
The smoke harness at lore/verify-pebble-seam.mjs performs zero-install contract validation:
- No Zod, no runtime schema library dependency
- Fires a request to each of the 11 routes
- Checks
okflag,statusfield existence, and high-leveldatashape - Differentiates 404 (empty result) from 5xx (outage)
- Generates a punch-list table of pass/fail per route
Key Terms
- Result
→ The typed discriminated union that replaced safe()— every API call returns either success data or a failure reason - DegradedBanner → UI component with three visual variants (outage, permission, shape-drift) that renders when
ok === false - Shape-drift → When pebble’s response schema changes unexpectedly (missing fields, wrong types) — caught by smoke harness
- Smoke harness →
verify-pebble-seam.mjs— zero-install (no Zod) contract validation script
Q&A
Q: Why Result<T> instead of try/catch?
A: Exceptions don’t carry semantic failure reasons. Result<T> encodes status, reason, and optional detail into a typed object that the UI can pattern-match against for appropriate rendering.
Q: What happens if pebble returns a 200 with an unexpected shape?
A: The knowledge-api.ts wrapper performs a lightweight shape check on the response; if the expected top-level keys are missing, it coerces the response to { ok: false, status: 422, reason: "shape" }.
Q: How does the smoke harness avoid adding a Zod dependency?
A: It uses typeof checks and in operator guards — zero install, zero dependency, runnable with just Node.js.
Examples
The Result<T> contract is like a restaurant order system where every response is either “Here’s your meal” or “Kitchen closed (reason: outage)” or “You’re not on the guest list (reason: permission)” — you never get a blank stare, you always know why.
neighbors on the map
- LORE RBAC & Airlock Auth Flow implementing authentication in a new LORE page