v0.3.0 — per-lens tuning, cross-runtime distillation, architecture hardening
witness v0.3.0 — per-lens tuning, cross-runtime distillation, and a big architecture-hardening pass.
Highlights
Per-lens runner + model (#75)
A lens can now declare its own runtime and models in lens.json (runner, extract_model, review_model). So one drain can span both Claude and OpenCode — the always-on default lens rides your default runner while a rare heavy lens runs a stronger (or free) model on the other runtime, without paying for it on every session. A per-runtime circuit breaker isolates an outage on one runtime from the lenses on the other.
witness lens try (#72)
A read-only preview of a lens's prompts against your real sessions before you register or backfill it — previews both the EXTRACT (mining) and, with --review, the REVIEW (facet synthesis) pass. Writes nothing. This is the fast prompt-tuning loop.
Distillation quality + observability
- prose-drift detection (#68): a below-floor model that returns no observations no longer masquerades as a "quiet session" —
doctorand backfill surface it so you know to raise the model. - per-lens watermark (#66): a newly-enabled lens backfills over history independently, without re-mining every other lens.
- profile dirty-tracking (#84): an unchanged review regenerates 0 profiles instead of N+1 — reviews are cheaper.
Architecture hardening (#73)
Worker-liveness via a single flock authority (#76); runner resolution collapsed to one source of truth (#71/#83); hot-path progress indexes (#80); RenderTranscript moved to the platform leaf so runtimes don't depend on each other (#81); the "global"→"default" naming cleanup (#79).
Notable fix
- Review no longer inherits a heavy ambient model (#87): when
distill_modelis empty, the review/profile stage now falls back totriage_modelinstead of whatever model your interactiveclaudeis configured with. Previously, running the worker inside a Claude-Code-on-Bedrock shell could make the batched review stall on a frontier model even though you'd set a lighttriage_model. Set onetriage_modeland the whole pipeline stays light.
Known issue
- #16 — L2 review input is unbounded. The reviewer feeds all observations for a lens into one call, so on a large archive (~1,700+ observations for a single lens) the review can exceed the model's context window and fail. Bounded/generational review is planned. If you hit this, keep per-lens archives smaller or use a large-context model for review until it lands.
Install
- OpenCode:
@witness-ai/opencodeon npm (auto-publishes with this release). - Claude Code / standalone: grab the binary for your platform below (or the self-contained Windows zip), then
witness install <claude|opencode>.
Full changelog: v0.2.3...v0.3.0 (21 commits).