diff --git a/README.md b/README.md index 6084ce26..15ca94c4 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,13 @@ It also captures your Claude Code sessions automatically — each session's work is harvested and rolled up into a summary. But where the persistent-memory tools compress with an LLM and inject straight back, vouch's rollup is **mechanical (no LLM)** and the summary lands in the **same review gate**: nothing becomes durable memory until you approve it. -Still alpha — surface is small on purpose; expect breaking changes pre-1.0. - > **Built for Gittensor (SN74) miners.** Mining subnet 74 means landing merged PRs across a whitelist of repos that keeps shuffling — which means re-investigating each repo's codebase and merge bar every session your agent opens. vouch auto-captures what a session works out, you approve what's worth keeping, and the next session recalls it: less re-discovery, more merged PRs. → **[docs/gittensor.md](docs/gittensor.md)** ## Watch it work (110 seconds) -[![vouch demo — capture, summarize, approve, compile, recall](docs/img/how-it-works-poster.jpg)](docs/vouch-how-it-works.mp4) +[![vouch demo — capture, summarize, approve, compile, recall](docs/img/how-it-works-preview.gif)](docs/vouch-how-it-works.mp4) -**[▶ docs/vouch-how-it-works.mp4](docs/vouch-how-it-works.mp4)** — captured live from the review console, no mockups: a Claude Code session auto-captures itself, one click has an LLM summarize what it meant, a human approves it at the gate, **`vouch compile`** distills the approved claims into cited topic pages (drafted by a real LLM, every `[claim: …]` citation machine-verified, still gated), and the film ends on the actual `vouch recall` digest — the knowledge the video just built, injected into the next session's first turn. +Captured live from the review console, no mockups — the preview above is muted and 3× speed; the real thing is **[▶ docs/vouch-how-it-works.mp4](docs/vouch-how-it-works.mp4)**. A Claude Code session auto-captures itself, an LLM summarizes what it meant, a human approves it at the gate, **`vouch compile`** distills the approved claims into cited topic pages (every `[claim: …]` citation machine-verified, still gated), and `vouch recall` injects the result into the next session's first turn. ## Why this exists @@ -43,9 +41,8 @@ Four opinionated choices distinguish vouch from the neighbours: Worth it when: -- **You mine Gittensor (SN74).** Emissions come from merged PRs across a whitelist that keeps shuffling, so your agent burns each session re-learning the same codebases and merge bars. vouch captures each session's findings for approval and recalls them next time — it stops re-deriving what it already knew and keeps targeting the repos that pay. See [docs/gittensor.md](docs/gittensor.md). - **Multiple agents share a repo** (Claude Code + Cursor + a CI bot). Per-agent attribution in the audit log makes "which agent claimed what" answerable. -- **Sessions keep re-explaining the same context.** Curated, cited claims let new sessions start from your team's agreed answer instead of re-grepping — and vouch auto-captures each Claude Code session into a summary you can approve, so memory accrues without letting the agent write its own history. +- **Sessions keep re-explaining the same context.** Curated, cited claims let new sessions start from your team's agreed answer instead of re-grepping. - **You want decision records without the ADR ceremony.** `vouch crystallize` promotes a session's durable parts into proposals; one approve and they're permanent. - **You'd review agent-stated facts the way you review agent-written code.** Vouch is a PR queue for claimed knowledge. - **Compliance / audit trails matter.** Required citations + append-only audit log give you "who decided X, citing what, when" for free. @@ -64,15 +61,10 @@ curl -fsSL https://raw.githubusercontent.com/vouchdev/vouch/main/install.sh | sh # …or directly via pipx (vouch-kb on PyPI; the command stays `vouch`) pipx install vouch-kb - -# …or from the cloned repo, in a venv -pip install -e '.[dev]' ``` -The one-liner is POSIX `sh`, never needs `sudo`, and detects an existing -Claude Code install to point you at the next step (`vouch install-mcp -claude-code`). Inspect it first if you'd like — it's [`install.sh`](install.sh) -at the repo root. +The one-liner is POSIX `sh` and never needs `sudo` — inspect +[`install.sh`](install.sh) first if you'd like. Or skip the install entirely and run the released container image ([`ghcr.io/vouchdev/vouch`](https://github.com/vouchdev/vouch/pkgs/container/vouch)), @@ -87,33 +79,6 @@ docker run -i --rm -v "$PWD:/data" ghcr.io/vouchdev/vouch:latest docker run --rm -v "$PWD:/data" ghcr.io/vouchdev/vouch:latest status ``` -## Running the tests - -From a clone with the dev extras installed (`pip install -e '.[dev]'`): - -```bash -# the full CI gate — lint + types + unit tests (exactly what CI runs) -make check # == ruff check + mypy src + pytest - -# just the unit tests -python -m pytest tests/ -q --ignore=tests/embeddings - -# a single module or test -python -m pytest tests/test_capture.py -q -python -m pytest tests/test_recall.py::test_digest_includes_approved_claim_and_page -q - -# with coverage -make test-cov # term-missing + coverage.xml - -# end-to-end smoke checks for the claude-code session hooks -make smoke-capture # capture: observe → finalize → pending summary -make smoke-recall # recall: approved knowledge injected at session start -``` - -The embedding-heavy tests live under `tests/embeddings/` and need the extra -`pip install -e '.[embeddings]'` (they run as a separate CI job); drop the -`--ignore` flag once installed. - ## Quick start ```bash @@ -154,46 +119,18 @@ with your project's first real source and claim when you are ready. ### Automatic session capture -Once vouch's Claude Code hooks are installed, sessions capture *themselves* — -this is the loop the demo shows. A `PostToolUse` hook harvests each tool call -into a gitignored scratch buffer; at session end a `SessionEnd` hook rolls the -buffer plus a `git diff` backstop into **one pending "session summary" page** — -mechanically, no LLM, never auto-approved. You review and `vouch approve` it -like any other write, and the next session starts with it injected via `vouch -recall`. Passive harvest, human-gated commit, no re-explaining: +Once vouch's Claude Code hooks are installed, sessions capture *themselves*: +each tool call is harvested into a gitignored scratch buffer and rolled up at +session end into **one pending "session summary" page** — mechanically, no +LLM, never auto-approved. You review and `vouch approve` it like any other +write, and the next session starts with it injected via `vouch recall`: ![vouch auto-capture demo](docs/demo.gif) -The full walkthrough with real output lives at [docs/example-session.md](docs/example-session.md); re-render the GIF from [docs/demo.tape](docs/demo.tape) with `vhs docs/demo.tape`. - -Prefer reading to running? The [examples/](examples/) directory ships sample KBs as committed files, each with rendered screenshots of `vouch status`, `search`, `show`, `audit`, and `diff` against the fixture — see what the CLI returns before installing anything. - -## Gittensor (SN74) - -**Gittensor** — Bittensor subnet 74 — pays miners in TAO for landing *merged* pull requests into whitelisted open-source repos. Contributions are scored by code quality, each repo's allocation, and programming-language factors, and the whitelist itself shuffles as the subnet matures. So mining well means pointing a coding agent at a rotating set of target repos and landing mergeable PRs in the ones that pay. - -The tax on that is re-investigation. Every target repo means (re)learning its architecture, its CI, its `CONTRIBUTING.md`, the maintainer's merge bar, and which past attempts got rejected and why. Across a dozen repos and a dozen sessions, your agent re-derives all of it from cold each time — time not spent landing PRs. vouch turns each session's findings into reviewed memory the next session recalls, so the investigation happens once: - -```bash -cd acme-httpkit # a whitelisted target repo — Go, healthy allocation -vouch init # review-gated KB at .vouch/ -vouch install-mcp claude-code # wires the capture + recall hooks - -# session 1: the agent maps the repo and works issue #212 (a pool leak). -# the claude-code hooks auto-capture the work. you approve the durable -# summary and file one cited claim: httpkit's merge bar. -vouch pending -vouch approve --reason "accurate session summary" - -# session 2: opens with `vouch recall`. the agent already knows the layout, -# that merges need `make test` green + a changelog entry, and where #212's -# fix and regression test landed. it skips re-discovery and takes the PR -# to merge. -``` - -The KB compounds session over session: merge bars, rejected approaches, targeting notes. When the whitelist shuffles and httpkit's allocation drops, `vouch supersede` the claim that said it was worth targeting — your agent re-prioritizes toward a higher-allocation repo, and the decision stays cited and reviewed instead of lost in a Discord thread. Each session you approve makes the next one start further ahead; the walkthrough in [docs/gittensor.md](docs/gittensor.md) runs the loop with real output. - -vouch reads **no** live signals — it never checks on-chain scores, verifies PATs, or submits weights (that's the `gitt` miner client). It's the reviewed record of what your agent already worked out, so it never works it out twice. Full miner walkthrough: **[docs/gittensor.md](docs/gittensor.md)**. +The full walkthrough with real output lives at +[docs/example-session.md](docs/example-session.md); the [examples/](examples/) +directory ships sample KBs with rendered CLI output so you can see what vouch +returns before installing anything. ## Object model @@ -243,69 +180,27 @@ The files are the source of truth; `state.db` is a derivable cache (`vouch index ## CLI surface -``` -vouch init # set up .vouch/ at PATH +The daily loop: + +```text +vouch init # set up .vouch/ at the project root vouch install-mcp HOST [--tier T1-T4] # wire MCP + capture/recall hooks into a host -vouch discover [--path P] # find the nearest .vouch/ root -vouch capabilities # emit the JSON capabilities descriptor -vouch status [--json] # KB counts + pending proposals -vouch stats [--days N] [--json] # observability: queue, review rates, citations -vouch lint [--stale-days N] # user-actionable problems -vouch doctor # full sweep incl. source verification -vouch fsck # deep consistency: indexes, lifecycle, decided -vouch migrate [--check] [--dry-run] # upgrade .vouch/ format safely - -vouch pending # list pending proposals -vouch review [--limit N] [--type KIND] # guided proposal review queue -vouch show # show pending proposal details -vouch read-claim # read an approved claim -vouch read-page # read an approved page -vouch read-entity # read an approved entity -vouch read-relation # read an approved relation -vouch list-claims # list all approved claims -vouch list-pages # list all approved pages -vouch list-entities # list all approved entities -vouch list-relations # list all approved relations -vouch approve [--reason ...] -vouch reject --reason "..." -vouch expire [--apply] [--days N] [--json] # GC stale pending proposals - -vouch propose-claim --text ... --source ... [--type ...] [--confidence X] -vouch propose-page --title ... [--body -] [--claim ID ...] -vouch propose-entity --name ... --type ... -vouch propose-relation --from ID --rel uses --to ID - -vouch source add PATH [--title ...] [--url ...] -vouch source verify [--fail-on-issue] - -vouch supersede OLD_ID NEW_ID -vouch contradict CLAIM_A CLAIM_B -vouch archive CLAIM_ID -vouch confirm CLAIM_ID -vouch cite CLAIM_ID - -vouch session start [--task ...] [--note ...] -vouch session end SESSION_ID -vouch crystallize SESSION_ID [--no-page] - -vouch recall # digest of approved knowledge for session-start injection -vouch capture observe|finalize|finalize-all|banner # hook-driven session capture (claude code) - -vouch search QUERY [--limit N] -vouch context TASK [--max-chars N] [--min-items N] [--require-citations] -vouch index -vouch audit [--tail N] [--json] - -vouch export --out path.tar.gz -vouch export-check path.tar.gz -vouch import-check path.tar.gz -vouch import-apply path.tar.gz [--on-conflict skip|overwrite|fail] -vouch sync-check PATH_OR_BUNDLE -vouch sync-apply PATH_OR_BUNDLE [--on-conflict fail|skip|propose] - -vouch serve [--transport stdio|jsonl] +vouch serve [--transport stdio|jsonl] # the agent-facing tool server + +vouch status | pending | review | show # inspect the queue +vouch approve [--reason ...] # the gate +vouch reject --reason "..." + +vouch propose-claim|propose-page|... # human mirror of the kb.propose_* tools +vouch search QUERY | context TASK | recall # retrieval +vouch compile [--dry-run] # llm-wiki ingest: draft topic pages from claims +vouch export | import-check | import-apply # portable bundles ``` +The full surface — lifecycle ops, sessions, sources, maintenance, +migration — is listed by `vouch --help` and machine-readably by +`vouch capabilities`. + ## MCP tools / JSONL methods (same surface, two transports) Read (unrestricted): `kb.capabilities`, `kb.status`, `kb.search`, `kb.context`, `kb.read_{page,claim,entity,relation}`, `kb.list_{pages,claims,entities,relations,sources,pending}` @@ -385,35 +280,9 @@ The JSONL transport reads one envelope per line on stdin, writes one per line on Errors come back with `ok:false` and a structured `error.code` (`method_not_found`, `missing_param`, `invalid_request`, `internal_error`). -Every successful `kb.*` result that is object-shaped carries read-only trust metadata so clients can detect remote confinement: - -```json -{ - "id": "r1", - "ok": true, - "result": { - "backend": "fts5", - "hits": [], - "_meta": { - "vouch_trust": { - "remote": false, - "caller_kind": "jsonl", - "auth_subject": null - } - } - } -} -``` - -| Transport | `remote` | `caller_kind` | `auth_subject` | -|-----------|----------|---------------|----------------| -| JSONL stdio | `false` | `jsonl` | `null` | -| HTTP `/rpc` | `true` | `jsonl_http` | bearer fingerprint when authenticated | -| MCP stdio | `false` | `mcp_stdio` | `null` | -| HTTP `/mcp` | `true` | `mcp_http` | bearer fingerprint when authenticated | -| CLI `--json` | `false` | `cli` | `null` | - -The block is server-attached metadata — client mutations are ignored. Array-shaped read results (e.g. `kb.list_claims`) pass through unchanged; trust rides on dict-shaped responses only (#233). +Every dict-shaped `kb.*` result also carries a server-attached +`_meta.vouch_trust` block (`remote`, `caller_kind`, `auth_subject`) so clients +can detect remote confinement — see [SPEC.md](SPEC.md) for the full contract. ## Portable bundles @@ -441,27 +310,13 @@ vouch import-apply kb.tar.gz --on-conflict skip # apply (default skip; never de | Portable bundle | no | no | **yes** | | Transports | SDK / HTTP | none | **MCP + JSONL** | -## What ships today - -| Area | Current support | -|------|-----------------| -| Knowledge base | `.vouch/` folder, YAML claims/entities/relations/evidence/sessions, markdown pages with frontmatter, JSONL audit log, content-addressed sources | -| CLI | `init`, `install-mcp`, `discover`, `capabilities`, `status`, `lint`, `doctor`, `fsck`, `pending`, `show`, `approve`, `reject`, `propose-{claim,page,entity,relation}`, `source add`, `source verify`, `supersede`, `contradict`, `archive`, `confirm`, `cite`, `session {start,end}`, `crystallize`, `capture {observe,finalize,finalize-all,banner}`, `recall`, `search`, `context`, `index`, `audit`, `export`, `export-check`, `import-check`, `import-apply`, `serve` | -| Tool servers | MCP over stdio + JSONL over stdin/stdout, same `kb.*` surface across both transports, capabilities + knowledge-capability descriptor | -| Schemas | 13 JSON Schemas (Draft 2020-12) generated from pydantic in [schemas/](schemas/), plus hand-maintained `bundle.manifest` and `jsonl-envelope` schemas | -| Write safety | review-gated writes via [proposed/](spec/review-gate.md), `dry_run:true` previews, host trust required for `approve`/`reject`, atomic exclusive-create storage, path-traversal blocked on source intake and bundle import | -| Session capture | Claude Code hooks harvest each session (`PostToolUse` → `vouch capture observe`) into a gitignored scratch buffer; `SessionEnd` rolls it up mechanically (no LLM) into one review-gated session-summary page; `SessionStart` injects approved knowledge via `vouch recall` and nudges pending summaries. Never auto-approves | -| Retrieval | `retrieval.backend` in `config.yaml` selects the path: `auto` (default — embedding → FTS5 → substring), `embedding`, `fts5`, or `substring`. Semantic backends (`all-mpnet-base-v2`, `MiniLM-L6`, fastembed-BGE) ship behind install extras; `auto` degrades to FTS5 when they aren't installed. Context packs with citations + quality gate | -| Lifecycle | `supersede`, `contradict`, `archive`, `confirm`, `cite` — direct mutations, all audited | -| Portability | tar.gz bundles with per-file sha256 `manifest.json`, `export-check`, `import-check`, `import-apply` with skip/overwrite/fail conflict modes | -| Audit | append-only `audit.log.jsonl`, per-event actor (`VOUCH_AGENT`), object ids, dry-run flag, reversible flag | -| Adapters | Claude Code wiring documented via `.mcp.json` + `VOUCH_AGENT` env; per-runtime adapter templates not yet shipped | -| Validation | pytest suite (storage, FTS5, audit, source-verify, review-gate, bundle, JSONL), ruff + mypy gates, GitHub CI | -| Specification | dated snapshots under [spec/](spec/), JSON Schemas in [schemas/](schemas/), generator script at [scripts/gen_schemas.py](scripts/gen_schemas.py) | - ## Status -Pre-1.0. What's *not* in this implementation: per-runtime adapter templates, benchmark fixtures, multi-agent sync, scopes beyond a single field on Claim/Source. If a hole matters to you, file an issue. +Pre-1.0 — the surface is small on purpose; expect breaking changes. What's +*not* in this implementation: benchmark fixtures, multi-agent sync, scopes +beyond a single field on Claim/Source. If a hole matters to you, file an +issue. Development setup and the test gate live in +[CONTRIBUTING.md](CONTRIBUTING.md). ## License diff --git a/docs/img/how-it-works-poster.jpg b/docs/img/how-it-works-poster.jpg deleted file mode 100644 index 6aaaf48e..00000000 Binary files a/docs/img/how-it-works-poster.jpg and /dev/null differ diff --git a/docs/img/how-it-works-preview.gif b/docs/img/how-it-works-preview.gif new file mode 100644 index 00000000..3d660e31 Binary files /dev/null and b/docs/img/how-it-works-preview.gif differ