indicium kernel contract¶
A kernel is a small, shared, dependency-light module other projects build on
(the reference example is src/indicium/verify.py, verify_quote). New kernels
must meet this bar.
Required properties¶
- Pure-Python, dependency-light. Standard library only (
re,dataclasses,difflib,typing). No third-party imports, no I/O, no network, no global state. - Never raises. A kernel function returns a typed result for every input,
including degenerate ones (empty,
None, wrong-typed entries are coerced or mapped to a benign result). Defensive coercion is the only try/except, and it lives at one documented boundary — not scattered. - One clear job, one frozen result type. A single public function (or a
tiny set) and a
@dataclass(frozen=True)result whose fields are documented inline. Structural invariants are stated (e.g. "unverified ⇒ matched_index / quote_exact are None"). - Additive / non-invasive. A kernel adds a verb; it must not edit
generated/model.py, the SHACL shapes, or any enum. New result fields are appended with defaults so existing callers keep working. - Backward-compatible evolution. New behavior is opt-in (a defaulted keyword param) and new outputs are defaulted fields. Existing callers' tests pass unchanged across the upgrade.
- WHY-not-WHAT comments; tight docstrings. Comments explain a non-obvious invariant or a coercion's reason. Docstrings state the current contract, not change history or commit hashes.
Worked example: verify_quote¶
- ~165 lines, stdlib-only, one public function + one frozen
VerificationResult. - Three outcomes (
verified/repaired/unverified) with a stated tie-break and a documented "unverified ⇒ None span" invariant. - The only
try/except-shaped defense is theNone/non-str candidate coercion, with a comment explaining it preservesmatched_indexalignment. - 1.9.0 added
char_span(defaulted field) andpunctuation_flexible(defaulted param) additively — prior tests passed unchanged; the suite now covers the additions (17 tests).
Checklist for a new kernel¶
- [ ] stdlib-only; no I/O / network / globals
- [ ] returns a typed result for every input; never raises
- [ ] single responsibility; frozen result type; invariants documented
- [ ] no edits to model.py / SHACL / enums
- [ ] new behavior opt-in, new outputs defaulted
- [ ] WHY-comments; contract-only docstrings
- [ ] full unit coverage incl. degenerate inputs