Anthropic Skills pinned the three-tier disclosure shape in
December 2025; Cursor / Codex / Cline / Aider absorbed it within
weeks. This crate is JouleClaw's typed version of that shape.
INDEX (always loaded) / BODY (on activation) / RESOURCES (on
demand by id). The matcher operates on INDEX only — the whole
point of the pyramid is to keep BODY / RESOURCES out of the
system-prompt budget until needed.
Energy as the orthogonal trust anchor: every tier carries an
`estimated_*_joules_uj`. The reason a disclosure pyramid exists
is that tier 1 is cheap and tier 3 is expensive — once you bother
to model that hierarchy, you have to be honest about cost or
you've defeated the purpose.
`DisclosureRegistry::find()` returns matches **ranked by total
joules if fully loaded** (cheapest first; lexical id tie-break
for stability), the same rule `jouleclaw-federation::
CheapestCapable` uses. A disclosure that matches but would
multiply the prompt energy 10× ranks below cheaper peers by
construction.
Surface:
- `IndexLayer { name, description, activation_predicates,
estimated_index_joules_uj }`.
- `BodyLayer { body_bytes_budget, content,
estimated_body_joules_uj }`.
- `ResourceLayer { bytes, mime, estimated_resource_joules_uj }`.
- `Disclosure { id, index, body, resources }` with
`total_joules_uj_if_fully_loaded()` for ranked selection.
- `DisclosureMatcher` trait; `KeywordMatcher` reference (case-
insensitive substring match against name + description + the
activation_predicates list).
- `DisclosureRegistry::{ register, find, load_body, load_resource,
stats }`. `DisclosureStats` rolls up per-tier joules and tags
`Provenance::Estimator`.
Honest scope (v1): bytes budget is advisory; flat (no DAG of
disclosures); resources are opaque blobs; matcher only sees
INDEX.
Kani harness (`#[cfg(kani)]`): adding a body to a disclosure
never lowers `total_joules_uj_if_fully_loaded` (monotone in
loaded tiers).
12 tests cover: total-joules sums all tiers; keyword matcher
matches case-insensitive name/description; predicates extension;
duplicate id rejected; cheapest-first ranking with lexical
tie-break; load_body attaches + unknown-id errors; load_resource
attaches/replaces; stats per-tier sums and provenance; JSON
round-trip; empty body/resources omitted from wire; non-matching
query returns empty.
Co-Authored-By: Claude Opus 4.7 <[email protected]>