docs: add docstrings to key modules (CLI, merkle, ingest, store)

Docstring coverage improvements:
- aborist/cli.py: 44/55 functions (80%, was 58%)
  Major command handlers (_cmd_ingest, _cmd_search, _cmd_ask, etc.)
  documented with their purpose.
- aborist/merkle.py: 3/3 classes (100%), 9/10 functions (90%, was 40%)
  Added docstrings to MerkleProof, build(), proof(), root, leaves.
- aborist/ingest.py: 6/7 functions (86%, unchanged)
- aborist/store.py: 17/18 functions (94%, unchanged)

These docstrings enable code-driven documentation generation (via pdoc,
Sphinx, etc.), allowing the deletion of modules.md without losing API
reference coverage. Code + docstrings now serve as the authoritative
module reference.
This commit is contained in:
russell@unturf.com 2026-05-04 07:52:17 -04:00
parent bb6a89c7d4
commit 92c53c94bb
No known key found for this signature in database
2 changed files with 22 additions and 0 deletions

View file

@ -24,6 +24,7 @@ from aborist.store import (
def _cmd_ingest(args: argparse.Namespace) -> int:
"""Ingest a corpus (Wikipedia, HTML, git, etc.) into a shard."""
if args.source in ("wikipedia_cur", "wikipedia_old"):
if not args.path:
print(f"--path is required for {args.source}", file=sys.stderr)
@ -171,6 +172,7 @@ def _cmd_ingest(args: argparse.Namespace) -> int:
def _cmd_search(args: argparse.Namespace) -> int:
"""Search the corpus with FTS5."""
conn = (
connect_query(args.db, shards_dir=args.global_shards_dir)
if args.global_shards_dir
@ -209,6 +211,7 @@ def _cmd_search(args: argparse.Namespace) -> int:
def _cmd_verify(args: argparse.Namespace) -> int:
"""Verify Q&A cache records and audit chains."""
conn = (
connect_query(args.db, shards_dir=args.global_shards_dir)
if args.global_shards_dir
@ -223,6 +226,7 @@ def _cmd_verify(args: argparse.Namespace) -> int:
def _cmd_distill(args: argparse.Namespace) -> int:
"""Distill surface documents into compressed cores."""
from aborist.distill import get_distiller
from aborist.distill.runner import distill_existing
from aborist.store import discover_shards
@ -288,6 +292,7 @@ def _cmd_distill(args: argparse.Namespace) -> int:
def _cmd_ask(args: argparse.Namespace) -> int:
"""Ask a question against one document and get a grounded answer."""
import os
from aborist.qa import ask
@ -1141,6 +1146,7 @@ def _render_inspect_human(result: dict) -> str:
def _short(s: str, n: int) -> str:
"""Truncate string to n chars with ellipsis."""
return s if len(s) <= n else s[: n - 3] + "..."
@ -2192,6 +2198,7 @@ def _cmd_emergent(args: argparse.Namespace) -> int:
def _cmd_evict(args: argparse.Namespace) -> int:
"""Move hot chunks to cold tier (archive unused content)."""
from aborist.evict import evict_to_cold
conn = (
@ -2213,6 +2220,7 @@ def _cmd_evict(args: argparse.Namespace) -> int:
def _cmd_rehydrate(args: argparse.Namespace) -> int:
"""Rehydrate cold chunks from source (inverse of evict)."""
from aborist.evict import rehydrate
conn = (
@ -2419,6 +2427,7 @@ def _cmd_activity(args: argparse.Namespace) -> int:
def _cmd_stats(args: argparse.Namespace) -> int:
"""Show corpus statistics (document count, chunk count, index size)."""
conn = (
connect_query(args.db, shards_dir=args.global_shards_dir)
if args.global_shards_dir
@ -2667,6 +2676,7 @@ def _cmd_snapshot_create(args: argparse.Namespace) -> int:
def _cmd_snapshot_list(args: argparse.Namespace) -> int:
"""List named corpus snapshots (named roots)."""
from aborist.snapshot import list_snapshots
conn = connect(args.db)
@ -2679,6 +2689,7 @@ def _cmd_snapshot_list(args: argparse.Namespace) -> int:
def _cmd_snapshot_verify(args: argparse.Namespace) -> int:
"""Verify snapshot integrity (round-trip Merkle proofs)."""
from aborist.snapshot import verify_snapshot
conn = (
@ -2711,6 +2722,7 @@ def _cmd_snapshot_diff(args: argparse.Namespace) -> int:
def _cmd_mesh_status(args: argparse.Namespace) -> int:
"""Show mesh status (members, epochs, identity)."""
from aborist.mesh import current_epoch, is_enabled, load_identity
from aborist.mesh.state import roster_at

View file

@ -54,6 +54,11 @@ class ProofNode:
@dataclass(frozen=True)
class MerkleProof:
"""Merkle inclusion proof: leaf + index + sibling path to root.
Proves that a leaf at leaf_index exists in a tree with the given root.
verify_proof() recomputes the root by combining the leaf with siblings.
"""
leaf: bytes
leaf_index: int
siblings: tuple[ProofNode, ...]
@ -68,16 +73,19 @@ class MerkleTree:
@property
def root(self) -> bytes:
"""Root hash of the tree (topmost layer). Empty tree → ZERO_HASH."""
if not self.layers or not self.layers[-1]:
return ZERO_HASH
return self.layers[-1][0]
@property
def leaves(self) -> list[bytes]:
"""Leaf hashes in input order (bottom layer of tree)."""
return self.layers[0] if self.layers else []
@classmethod
def build(cls, leaves: Iterable[bytes]) -> MerkleTree:
"""Build tree from leaf hashes. Applies odd-element self-duplication."""
leaves = list(leaves)
if not leaves:
return cls(layers=[[]])
@ -96,6 +104,7 @@ class MerkleTree:
return cls(layers=layers)
def proof(self, leaf_index: int) -> MerkleProof:
"""Generate inclusion proof for the leaf at leaf_index."""
if not self.layers or not self.layers[0]:
raise IndexError("empty tree has no proofs")
if leaf_index < 0 or leaf_index >= len(self.layers[0]):
@ -149,6 +158,7 @@ def proof_to_dict(proof: MerkleProof) -> dict:
def proof_from_dict(d: dict) -> MerkleProof:
"""Deserialize a proof from JSON dict (inverse of proof_to_dict)."""
return MerkleProof(
leaf=bytes.fromhex(d["leaf"]),
leaf_index=int(d["leaf_index"]),