Skip to content

v0.22.0 - the “scale” release

Choose a tag to compare

@tcballard tcballard released this 10 Jul 07:16

The rac-core "scale" release: retrieval that stops growing with corpus size — and now warm by default, so a caller who types nothing gets the fast path. Plus tags as a first-class search signal, decisions that know the code they govern, and team-scale MCP serving. Every scale feature is byte-identical to the uncached path.

This is the first PyPI release after v0.19.0. Versioning reverted from a brief CalVer detour back to SemVer (ADR-111 supersedes ADR-076), and the three intervening releases — Hardening (v0.20.0), unlock (v0.21.0), rename (v0.21.1) — ship only as git tags; their CalVer PyPI dists are yanked. So pip install -U rac-core from v0.19.0 lands here and delivers all four releases' worth of change at once. The "scale" work is below; everything folded in since v0.19.0 is in § Also included. Compatibility still lives on schema_version (ADR-007), never the release number.

Highlights — "scale"

  • The cache is on by default (ADR-112). rac find, rac validate, and rac mcp now reuse the persistent memory-mapped index and per-file result caches without a flag — repeated queries against an unchanged corpus are bound by query selectivity, not corpus size. Freshness is verified by a fast (size, mtime_ns) stat scan; a one-shot rac find now persists a stat manifest, so a warm run reads zero artifact bytes (enumeration + stats only). Byte-identical to the uncached walk. Escapes: --no-cache per invocation, RAC_NO_CACHE=1 per environment, and --verify (on find/validate) to force the full byte re-hash floor. A homeless environment degrades to a temp-dir cache — a missing cache location never fails a query.
  • Search by tags. The frontmatter tags you already write are now a retrieval signal: a query term matches them (a metadata tier between title and path), and a repeatable --tag facet on rac find / a tags argument on search_artifacts narrows to artifacts carrying every requested tag. Deterministic and lexical throughout, never an embedding (ADR-037/038/109).
  • Single-node scale. For large corpora the derived index — repository index, resolved relationship graph, and search token vectors — is a persistent, memory-mapped segment store; search is served from term-major postings; freshness is tracked incrementally; and the cold build parallelises across cores. Keyed on a corpus content hash, byte-identical to the uncached path, and safe to delete — the cache can only change speed, never an answer (ADR-103/104/105/107/108).
  • Decisions know the code they govern. A decision can declare an ## Applies To scope; rac relationships --validate existence-checks literal paths (new applies-to-target-not-found finding). Ask the inverse with rac decisions-for <path>, the find_decisions MCP tool's new path argument, and Explorer's /decisions-for — declared and validated, never inferred; deterministic and offline.
  • Lore at team scale. rac mcp --transport http serves one always-current, read-only endpoint for a whole team (stdio stays the default); a content-addressed cache (on by default) stops per-call latency scaling with corpus size; per-caller X-Lore-Principal audit attribution answers "who read what, when"; and a new Shared Server operator guide. Servers and caches over git — no database (ADR-098/099).
  • Note-tool ingest. rac ingest now imports Obsidian, Logseq, Notion, and Roam exports, carrying each source's link graph in as candidate ## Related references to promote — never asserted edges. Deterministic, offline, lossless, and it never overwrites (ADR-079).
  • Freshness where you pick artifacts. rac find and search_artifacts carry a git-derived recency object (last_committed, age_days, stale) per match; rac doctor / rac review surface a suspect-artifact drift finding when a target was committed more recently than its referrer. Advisory beside the date, never a verdict; derived from git, never a stored frontmatter date (ADR-045).
  • Lean, measured context delivery. The five-tool MCP surface is now a regression-checked token budget (~915 against a 1000 cap, deterministic and offline), plus new Context Cost guidance on selective-by-default retrieval and the CLI as the lowest-tax delivery path (ADR-033/066).
  • Harness integration recipes. A recipe template + authoring guide and the first four client recipes (Windsurf, Cline, Zed, opencode), each with a fixed post-edit-enforcement shape and zero engine diff (ADR-067).

Also included since v0.19.0

The releases folded into this one — full detail in the CHANGELOG.

Hardening (v0.20.0) — grounding you can see and trust:

  • Explainable retrieval — every result shows why it matched (field, term, edge) on search_artifacts / get_related / rac find --explain.
  • rac doctor — one command diagnoses a corpus and emits paste-ready fixes.
  • Provenance on get_artifact — git-derived author, dates, and reconstructed status history.
  • Documented trust model (SECURITY.md) and a gated grounding benchmark (rac eval --check: deterministic Precision@k / Recall@k with a committed baseline).

unlock (v0.21.0) — the accumulated user-facing wave:

  • Reimagined Explorer TUI — three themes, a sortable portfolio list view with live fuzzy search, and a split master-detail layout.
  • Exportable corpusrac export --documents (ingestion-ready JSONL for RAG/memory backends) and rac export --graph (typed node+edge graph with real, validated relationship kinds) (ADR-074).
  • Visible grounding & coverage — content-free telemetry, a coverage view for gaps in the graph, and a bounded multi-hop get_related.
  • Fail-closed publish gate (python -m rac.release) rejecting a malformed or undocumented release before PyPI.

rename (v0.21.1) — the package rename + first enterprise wave:

  • PyPI package renamed requirements-as-coderac-core (ADR-092); import name rac and the CLI unchanged.
  • Enterprise, all opt-in and content-free by default — telemetry hard-lock (rac telemetry off --enterprise, ADR-086), a read-access audit recorder (ADR-084), external ticket references (## Related Tickets, ADR-087), rac init --profile scaffolding (ADR-088), and the rac-capture interview skill (ADR-077).

Upgrade notes

  • The cache is now on by default (ADR-112, behavioral change). rac find / rac validate / rac mcp reuse the persistent derived-index and per-file caches without a flag, byte-identical to the uncached walk. Opt out per-call with --no-cache or environment-wide with RAC_NO_CACHE=1. The default freshness check is a (size, mtime_ns) stat scan; --verify forces the full byte re-hash — the one case stats can miss is a size- and mtime-preserving in-place rewrite between two warm runs.
  • Package renamed → rac-core. If you're coming from v0.19.0 you were on requirements-as-code; install pip install rac-core now. The old name still works via a transitional redirect, and pinned requirements-as-code== installs still resolve to their historical builds. Import name rac and the rac CLI are unchanged (ADR-092).
  • License changed MIT → Apache-2.0. The package and CLI carry Apache-2.0 metadata with a NOTICE file; it adds an express patent grant and stays permissive, so usage rights are unaffected. Contributions now require a DCO sign-off (git commit -s) — no CLA (ADR-071).
  • Search evidence.tier integers shifted by one (tags added at rank 2): path 2→3, heading 3→4, body 4→5. Ranking order is unchanged (BM25F-driven) and the matched field name is unchanged — a consumer reading the field name is unaffected; one that pinned the integer should re-read it (ADR-109).
  • The persisted index-store format bumped. An index built by an older rac fails the version gate closed and is transparently rebuilt on next use — a one-time rebuild of a disposable structure, never a different result (ADR-104/109).

Install

pip install --upgrade rac-core        # 0.22.0
# or, no Python:
docker run --rm -v "$PWD:/work" ghcr.io/itsthelore/rac:v0.22.0 validate rac/

Full detail in the CHANGELOG.