Skip to content

Releases: IngTian/witness

v0.5.1

Choose a tag to compare

@IngTian IngTian released this 26 Jul 19:32
84d03c5

Metadata-only patch release. No functional change from v0.5.0.

Why: the MCP Registry (schema 2025-12-11) verifies package ownership by requiring the referenced npm package to declare an mcpName field matching the server name. v0.5.0's @witness-ai/opencode lacked it, so mcp-publisher publish rejected it. npm versions are immutable, so the field ships via this patch.

Changes:

  • npm/opencode/package.json: add "mcpName": "io.github.IngTian/witness".
  • Version bump 0.5.00.5.1 across npm packages, Claude plugin manifests, and server.json.

Binaries below; npm packages published automatically via OIDC.

🤖 Generated with Claude Code

v0.5.0 — witness ingest (records-in engine) + install/wire split

Choose a tag to compare

@IngTian IngTian released this 26 Jul 18:59
f799c1d

witness becomes a generic records-in distillation engine — it now ingests your own records (notes, articles, any text stream), not just Claude Code / OpenCode chats — and the install surface is split so witness can be set up as a standalone library without wiring an editor.

Highlights

  • witness ingest — feed witness a documented NDJSON record contract (one JSON object per line, via stdin or --file) and it distills those records exactly like a coding session: observations → bi-temporal facets → a narrative profile, per lens, served over MCP. witness owns the format + protocol; you bring clean records (it parses no files itself).
    {"text": "...", "id": "stable-dedup-key", "session": "optional-group", "ts": "2026-07-26", "role": "document"}
    Dedup keys on your id (same id + unchanged → skip; same id + changed → update; new id → append), so re-ingesting is idempotent and never deletes records you didn't mention. ts is the temporal axis; session optionally groups records mined together.
  • file platform adapter — an ingested source distills through the unchanged engine; file:-namespaced sessions never collide with editor sessions.
  • install ≠ wire (breaking rename): witness install [--path <dir>] now provisions an archive (no editor, no person-growth default lens — a blank engine you fill with your own lens); witness wire <claude|opencode> connects an editor (was install <target>); witness unwire (was uninstall). Run several install --path for isolated archives (one per data source).
  • Contract documented + versioned in prompts/SCHEMA.md — the public API a downstream tool builds against.

Breaking changes

  • witness install <claude|opencode>witness wire <claude|opencode>; witness uninstall <target>witness unwire <target>. witness install with no target now provisions an archive.
  • Already-wired editors keep working — the installed hook contract (capture/session-start/session-end) is unchanged; only the human-facing command names moved. Re-run witness wire <target> (or make install) if you want to re-wire.

Verification

Built via a fresh-subagent-per-task workflow with a final whole-branch review that caught + fixed a Critical incremental-append data-loss bug before release (dedup now uses true merge/append semantics). make fmt vet test + -race green; hook ABI byte-unchanged; zero distillation-engine changes; live end-to-end verified (a file: session mines observations under a domain lens on an isolated archive).

v0.4.0 — CLI surface diet: a ~6-verb front door, unified config, readable help

Choose a tag to compare

@IngTian IngTian released this 26 Jul 05:25
6c9a26e

A CLI surface overhaul — witness's command surface is now organized around what a user actually does, with the engine's internal vocabulary moved off the front door. Breaking for anyone scripting the old commands (see below); the distillation engine and data are unchanged.

The new front door (~6 verbs, grouped)

READ     profile · status
LENSES   lens
CONFIG   config
SETUP    install · uninstall · doctor
MAINT    export · cleanup

Highlights

  • witness status — one read for "is it working / what's captured / is it fresh" (replaces distill status).
  • Unified config — one scoped tree: witness config set <key> <value> [--lens <name>], canonical keys runner/mine_model/review_model at both scopes, and config list shows an origin view ((lens override) vs inherited from default, never blank) so per-lens overrides are legible. witness lens set is gone — it's config set --lens now.
  • install is host-wiring only — it wires the editor integration + MCP; the runner default moves to witness config set runner <claude|opencode>.
  • Scannable lens show — a compact card by default (dimensions, models, prompt excerpts); witness lens show <name> --prompts for the full prompt text.
  • De-jargoned, grouped help — the L0/L1/L2 pipeline vocabulary no longer leaks into user-facing help/output; witness --help is sectioned.
  • The worker moved off the front doordistill/review are now the hidden witness worker run|stop|review operator group (a normal user never needs them; the worker runs off editor hooks). import is hidden plumbing.

Breaking changes

  • witness distill statuswitness status; witness distill start/--all/stopwitness worker run [--detach] / witness worker stop; witness reviewwitness worker review.
  • witness lens set <name> …witness config set <key> <value> --lens <name>.
  • witness versionwitness --version.
  • Installed editor hooks are unaffected — the hook contract (capture/session-start/session-end) is unchanged, so existing installs keep capturing. Only the human-facing command names moved.

Verification

Built and reviewed via a fresh-subagent-per-task workflow with a final whole-branch review (which caught + fixed a command-name collision before release); make fmt vet test + -race green; hook ABI verified byte-unchanged; --json outputs undecorated; live smoke on an isolated archive. Zero engine changes.

v0.3.1 — install=mechanism · deletable auto-seeded default · unified backfill

Choose a tag to compare

@IngTian IngTian released this 19 Jul 22:42
1aee13f

CLI-surface cleanup (#102 / #103): the install and lens commands now follow a clean separation of concerns, and the built-in "default" lens is an ordinary, deletable lens rather than a special built-in.

Highlights

  • install is a pure mechanism. It wires the Claude Code hooks / OpenCode plugin + MCP server and binds the runner — and never prompts or seeds content. Safe to run as a hook subprocess and in CI.
  • The built-in "default" person-growth lens is auto-seeded once on the first time an archive is opened (a fresh personal install, or a pre-1a migration), and is fully deletable: witness lens disable/deregister default sticks forever — it will not silently come back. Restore it any time with witness lens load-default, or opt a fresh archive out entirely with WITNESS_NO_DEFAULT_LENS=1.
  • install now prints the enabled-lens set so you can see what will run (and cost an LLM call) on every session.
  • lens rebuild is unified into lens backfill <name> [--fresh]. Backfill now always refreshes the lens's facets after re-mining (fixing a drift where facets could lag the re-mined observations). --fresh (the old rebuild) drops the lens's observations + facets first, and is now guarded: it fails fast if a worker is running, asks for confirmation with exact counts (--yes to skip), and warns that in-session (hand-recorded) observations are not reproducible by a re-mine.
  • Docs/messages corrected for the "default is an ordinary lens" world (profile/facets help + empty states).

Verification

make fmt vet test + -race green; npm checks 26/26; a full live end-to-end run (real LLM: capture → mine → observations → review → facets → profile) on an isolated archive; and an adversarial merge-gate review (correctness / best-practices / long-term-plan / UX) that came back GREEN with no blockers.

Upgrade is transparent for existing archives (the pre-1a default is migrated in automatically on first open).

v0.3.0 — per-lens tuning, cross-runtime distillation, architecture hardening

Choose a tag to compare

@IngTian IngTian released this 18 Jul 15:22
3fa8628

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" — doctor and 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_model is empty, the review/profile stage now falls back to triage_model instead of whatever model your interactive claude is 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 light triage_model. Set one triage_model and 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/opencode on 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).

v0.2.4 — audit fixes: worker livelock, watermark CAS, hardening

Choose a tag to compare

@IngTian IngTian released this 13 Jul 21:03
1a18915

Audit-hardening patch release. A comprehensive adversarial audit of v0.2.3 (#49) surfaced two latent-race CRITICALs and several hardening items; this release fixes all of the CRITICALs plus the cheap IMPORTANTs. All fixes were live-tested end-to-end on both runtimes (real claude -p + real opencode serve) and are test-locked.

Fixes

Critical

  • Worker review-only livelock (#50) — a review-only worker that had new work land during the review would spin at 100% CPU holding the global worker lock forever, silently halting all distillation until a manual distill stop. The drain loop now re-checks pending work on a fresh read each pass. Refs #49 (C1).
  • Watermark resurrection on a raw replace/delete mid-mine (#51) — when an OpenCode history rewrite (or witness cleanup) deleted a session's raw rows while the worker was mining it, a blind watermark write could mark never-mined turns as done, silently leaving stale L1. The watermark write is now a compare-and-set keyed on the raw generation actually mined (MarkDistilledIfCurrent); it advances only if that generation still exists, else the session re-mines cleanly. Runtime-agnostic — free insurance on the append-only Claude path. Refs #49 (C2).

Hardening (#52)

  • review_every <= 0 now clamps to the default instead of firing the reviewer on every session-end (I1).
  • Install hook-strip match is basename-exact + token instead of a loose substring that could strip an unrelated foreign hook merely containing "witness.sh" (I3).
  • /dist/ added to .gitignore so release-staging binaries can't be accidentally committed (I6).

Compatibility

No schema changes, no config-format changes. A drop-in upgrade from v0.2.3. Existing archives are used in place.

Artifacts

6 raw binaries (darwin/linux × amd64/arm64, .exe for Windows inside the zips), 2 self-contained Windows zips (exe + prompts + embedding model, ~295MB each), and SHA256SUMS.txt. The npm package @witness-ai/opencode@0.2.4 (+ the two platform packages) publishes automatically from this release via OIDC trusted publishing.

v0.2.3 — parallel mining · opencode idle-reconcile · discovery

Choose a tag to compare

@IngTian IngTian released this 13 Jul 15:15
c96e471

Highlights

  • Parallel mining + self-draining worker (#22). Distillation now mines many sessions at once (bounded map-reduce pool, mine_concurrency default 4, capped at min(16, GOMAXPROCS)); a full-history backfill drops from ~28h → ~7h (Haiku, conc=4). New witness distill start --all foreground backfill. Removed the old 1 Hz wakeup cascade + respawn/debounce machinery — the worker now re-checks its own queue under the lock. OpenCode distillation is parallel too (narrowed the serve mutex). Adversarially reviewed twice (internal 3-lens audit + a maintainer PR review that caught 3 more real issues, all fixed).
  • OpenCode reconcile on session.status=idle (#41, closes #33). Retires the dead event-driven capture path (the SQLite store is the only complete source of truth), makes Capturer an optional platform capability, adds targeted --session reconcile that doesn't advance the global watermark, single-flights imports in both plugins with graceful dispose, and resolves the DB via XDG_DATA_HOME. Thanks @ChangeHow.
  • Agent discoverability + metadata fixes (#46). Corrected stale/wrong plugin & marketplace metadata (version, "pure tool" framing, global lenses), the MCP handshake now reports the real build version, and descriptions/keywords/README/llms.txt seed the vocabulary an agent uses to find the tool.

Install

  • Claude Code: witness install claude · OpenCode: witness install opencode
  • npm (OpenCode): @witness-ai/opencode@0.2.3
  • Binaries below (darwin/linux amd64+arm64, Windows self-contained zips), verify with SHA256SUMS.txt.

Single pure-Go binary, CGO_ENABLED=0. Windows Claude Code support is smoke-tested; OpenCode-on-Windows is not yet at parity.

v0.2.1 — module rename, export, npm auto-publish

Choose a tag to compare

@IngTian IngTian released this 07 Jul 15:57
616a657

Since v0.2.0. Small, non-breaking release; also the first to auto-publish the OpenCode npm plugin.

Changes

  • feat(export): witness export <path> — consistent single-file DB snapshot via VACUUM INTO (#15).
  • feat(opencode): publishable @witness-ai/opencode npm package + witness.js plugin rename with self-healing legacy cleanup (fixes the double-capture bug, #7 / #13).
  • chore: Go module + display strings claude-witnesswitness (repo/command name alignment; runtime-neutral) (#14).
  • ci: auto-publish @witness-ai/opencode to npm on release via OIDC trusted publishing — no stored token, provenance attested (#17).

Notes

  • Binaries below are attached from make build-all; the @witness-ai/opencode npm package (which bundles them) publishes automatically from this release.
  • Data-dir adoption unchanged: existing archives under claude-witness/ are used in place; fresh installs use witness/.
  • OpenCode-on-Windows remains unsupported (#10).

🤖 Generated with Claude Code

v0.2.0 — Windows (Claude Code) + hardening

Choose a tag to compare

@IngTian IngTian released this 05 Jul 16:59
31c41ae

Windows support (Claude Code) + OpenCode on macOS/Linux + reliability hardening.

Highlights since v0.1.0

  • Windows — Claude Code (new). witness now cross-compiles and runs on Windows (amd64 + arm64), and witness install claude wires Claude Code natively: exec-form hooks pointing at witness.exe (no shell/Git Bash needed), install into %LOCALAPPDATA%\witness, and user-PATH registration. Verified end-to-end on real Intel Windows. (#6, #9)
  • OpenCode (macOS/Linux). Full OpenCode runtime support — plugin + MCP + long-session distillation stability. (#3, #5)
  • Self-healing data dir. The archive directory now adopts an existing install in place and only creates the new preferred name (witness) on a fresh machine — the rename never orphans an existing archive. (#12)

Install

macOS / Linux — from a checkout:

./install.sh claude      # or: opencode

Windows (Claude Code) — download witness-v0.2.0-windows-amd64.zip (Intel/AMD) or -arm64.zip, unzip to a witness\ folder, then from inside it:

.\witness.exe install claude

The zip is self-contained (exe + prompt templates + the ~448 MB embedding model). Install copies everything into %LOCALAPPDATA%\witness and adds it to your PATH, so you can delete the download afterward.

Not yet supported

  • OpenCode on Windows — the OpenCode plugin still relies on a shell shim; the native Windows path is designed but not built (tracked in #10). OpenCode works on macOS/Linux.
  • Windows uninstall leaves the copied %LOCALAPPDATA%\witness files + PATH entry in place.

Notes

  • Existing installs keep using ~/.local/share/claude-witness; fresh installs use ~/.local/share/witness. Both are adopted automatically — no migration, no data loss.
  • Windows binaries are unsigned; SmartScreen may warn on first run ("More info → Run anyway").

Artifacts

  • macOS/Linux: raw witness-v0.2.0-<os>-<arch> binaries.
  • Windows: self-contained witness-v0.2.0-windows-<arch>.zip (exe + prompts + model).
  • SHA256SUMS.txt for all of the above.

🤖 Generated with Claude Code

v0.1.0 — Claude Code

Choose a tag to compare

@IngTian IngTian released this 03 Jul 14:37

First tagged release of claude-witness — a Claude Code plugin that keeps a person-centric archive of how you think, work, and grow across sessions. This is a stable, end-to-end-verified cut of the Claude Code integration.

What's in this release

  • Capture (L0) — every turn recorded verbatim from stable Claude Code hook fields (UserPromptSubmit.prompt, Stop.last_assistant_message); no fragile transcript parsing. Append-only, never LLM-touched.
  • Distillation (L1/L2/L4) — a detached worker mines per-session observations, a periodic reviewer synthesizes them into bi-temporal facets, and profiles are regenerated on top. Runs on your existing Claude Code auth via claude -p.
  • Local & self-contained — one pure-Go static binary (CGO_ENABLED=0), local multilingual (EN + ZH) embeddings via GoMLX. No Python, no external services, no vector DB, no cloud key.
  • MCP server — agents read the profile on demand via get_profile / get_facets / search_observations / record_observation / delete_observation.
  • Lenses — pluggable observation dimensions; ships with a default lens and a lens-authoring guide.
  • Commandswitness <doctor | profile | lens | cleanup | install | uninstall>.

Verified

gofmt, go vet, go test ./..., and make build-all (darwin/linux × amd64/arm64) all green at this commit.

Install

./install.sh        # builds, fetches the embedding model (~448MB, once), wires hooks + MCP

Or download a prebuilt binary below and run witness install. The embedding model is fetched separately on first run (not bundled in the binary).

Scope note

This release is the Claude Code integration. OpenCode support is in progress on a separate branch and is not part of v0.1.0.

Assets

Prebuilt binaries for darwin/linux × amd64/arm64, plus SHA256SUMS.txt. Verify with shasum -a 256 -c SHA256SUMS.txt.