Crux Response Contract v1 (CRC-v1)
June 10, 2026 · View on GitHub
Status: M0 — spec frozen. Canonical home for the portfolio-wide response contract.
Oracle: crc-v1.schema.json is the single source of truth. Every emitting endpoint serialises through it; CI validates real responses against it; the daemon serves it verbatim via get_bootstrap(topic="tool-output").
What it is
A unified, pointer-first, progressively-hydrated response envelope shared across CoreCrux /v1/query/*, VaultCrux /v1/memory/retrieve, and the Crux daemon HTTP + MCP surface. Instead of every endpoint stuffing full content in an ad-hoc JSON shape (~56K tok/q on the LME bench), a CRC-v1 response returns cheap pointers + a cost_estimate + an agent_decision + a freshness/receipts envelope, and the caller hydrates only what it needs (~1.6–7.5K tok/q at equal recall, measured on the agent-native LME benchmark).
Default-on, with a legacy escape hatch
CRC-v1 is the default response contract — there are no legacy consumers to preserve, so every read endpoint returns the pointer-first envelope by default. A caller that can't yet parse it opts out to the old full payload:
| Surface | Opt OUT to legacy (full payload) |
|---|---|
| HTTP | Accept-Contract: legacy request header (also v0/none/off, or ?contract=legacy) |
| MCP tool call | contract: "legacy" argument |
When opted out, the endpoint returns its legacy shape, byte-identical to pre-CRC-v1 — preserving CROWN receipt byte-identity for anyone who needs the old shape. The explicit opt-IN forms (Accept-Contract: crc-v1 / contract:"v1") still work but are redundant now that CRC-v1 is the default.
Default hydration is pointer (cheap epitomes); ask for ?hydrate=full|summary to get content inline within the CRC-v1 envelope, or opt out to legacy for the old full payload.
Shape (see the schema for the authority)
{
"contract": "crc-v1",
"kind": "search" | "addressed" | "fact" | "session",
"hydrate_tier": "pointer" | "summary" | "full", // CRC-v1 default = pointer
"pointers": [ { "id", "score", "epitome<=40tok", "reason" } ],
"content": [ { "id", "text", "token_count" } ], // ABSENT at pointer tier
"cost_estimate": { "pointer": N, "summary": N, "full": N },
"agent_decision": { "load_bearing_lane", "fused_confidence", "suggested_next_lane",
"lane_attribution", "read_pointers" } | null, // null unless kind=search
"envelope": { "freshness": {...}|null, "receipts_used", "memories_used",
"autonomy_consumed", "links": { "verify", "open_in_console" } },
"next": { "expand", "resolution_pointer", "canonical_slug" },
"meta": { ... per-endpoint diagnostics ... }
}
Per-kind field presence
| field | search | addressed | fact | session |
|---|---|---|---|---|
pointers | ✅ | ✅ | — | — |
content (at summary/full) | ✅ | ✅ | ✅ (value) | ✅ (state) |
cost_estimate | ✅ required | ✅ | optional | optional |
agent_decision | ✅ non-null | null | null | null |
envelope.freshness | — | optional | ✅ required | optional |
next.canonical_slug | optional | optional | ✅ | ✅ |
addressed = content-pointer hydration (fetch-content / query_expand): chunk bodies don't decay, so freshness/slug are optional. fact = fact-store resolve where decay/supersession is the whole point, so envelope.freshness is required.
Addressed recall is first-class: kind=addressed|fact|session is an exact key resolve and is never routed through the BM25 ranker. It echoes next.canonical_slug so the next turn re-addresses by key (cheap, exact) instead of re-searching (fuzzy, lossy), and carries envelope.freshness so a re-verify turn is unnecessary.
Invariants (enforced by the schema + per-repo tests)
hydrate_tier=pointer⇒contentabsent/empty (the cheap default actually stays cheap).kind=search⇒pointersandcost_estimatepresent.- Opted-out responses (
Accept-Contract: legacy) are byte-identical to pre-CRC-v1 (per-repo golden test; not expressible in this schema). - The schema served by
get_bootstrap("tool-output")is this exact file — drift between schema, serializer, and bootstrap seed is the failure mode M4 guards.
Vendoring
Repos that emit CRC-v1 (CoreCrux, VaultCrux) vendor a copy of crc-v1.schema.json and run validate_crc_v1.py against representative responses in CI. The canonical copy lives here; vendored copies are checked byte-equal in CI.
Validate
python3 validate_crc_v1.py crc-v1.schema.json fixtures/*.json