Architecture

heepx.learn("warrant") is four pieces of the SDK working in sequence, each independently swappable:

Registry.latest/download_url  →  downloader.download  →  Cache.store  →  loader.load_capability
   (where is it?)                  (fetch the bytes)      (extract, checksum)   (parse, validate)
  1. Registry answers "what exists" and "where do I get it" — search, versions, latest, info, download_url. GitHubRegistry (default) and LocalRegistry are both plain implementations of one abstract class; nothing above this layer knows which one it's talking to.
  2. Downloader turns a URL into bytes — http://, https://, or file:// (which is how LocalRegistry serves local archives through the exact same code path as a real network fetch).
  3. Cache extracts an archive once per version, computes its SHA-256 checksum and content fingerprint, and records both in a manifest alongside the files. A version already extracted is never re-fetched.
  4. Loader validates the extracted directory (CAPABILITY.yaml and LICENSE present, the descriptor parses, its declared id matches, every load_order path exists) and returns a typed, immutable Capability.

heepx.verify re-runs step 3's fingerprint computation against what's on disk right now and compares it to what was recorded at cache time — this is what catches local tampering or corruption, independent of the network entirely.

Why a registry abstraction

Freezing the interface (Registry's five methods) rather than a specific backend is what lets GitHubRegistry and LocalRegistry both exist without heepx.learn, the cache, or the loader knowing which one they're talking to. The same freedom is available to anyone who wants a private, authenticated, or otherwise different registry.

See Registry and Capability Standard for the two format specifications this architecture is built around.