chore(release): prepare 1.5.0#533
Conversation
the per-prompt hook injected raw context ("consider it before
answering") with no instruction, so the model absorbed kb knowledge
invisibly and the user could not tell recall from silence — the single
most-reported "vouch isn't working" symptom. three changes:
- with relevant approved items, the banner now instructs the model to
open its reply with "From vouch memory:" and ground in the cited
items, citing each id. recall becomes visible on every turn.
- with no relevant items, the hook injects an explicit "found nothing
relevant — open with 'Nothing in vouch on this.'" banner instead of
nothing, so an empty kb reads as an empty kb, not a broken install.
- opt-in confidence short-circuit (retrieval.short_circuit.{enabled,
min_confidence}, default off): a high-confidence non-action lookup
may collapse to a verbatim vouched answer. scores squash to 0-1 via
1-exp(-score/5); a prompt whose first word is an imperative "do work"
verb never short-circuits, however confident the match — the action
gate, not the score, keeps it safe.
tests cover the three banners, the action gate, the opt-in default,
the threshold, and defensive config parsing; the no-hits test now pins
the explicit banner. readme documents the visible behaviour and drops
the stale "one-time approval" workaround note superseded by the
install-mcp auto-registration.
feat(hooks): instructional recall banners for visible memory
real-world test: on tool-heavy prompts the model explored the codebase and dropped the soft "open your reply with" instruction from its final message, so recall ran invisibly — the exact symptom the banners exist to kill. verified on a live project: memory-shaped prompts opened with "From vouch memory:", tool-heavy ones did not. state the opener as a hard output contract in all three banners: the final reply MUST open with the exact words, even if the model uses tools or explores first. re-verified end-to-end on the same project — the previously-failing prompt now opens with "From vouch memory:", grounds in cited ids, and still does its tool exploration afterwards.
fix(hooks): make the recall opener survive tool use
recalled facts and the model's own reasoning were indistinguishable in
the rendered reply — both plain prose, with only the [ev-…] ids
hinting at provenance. the banners now instruct a visual contract on
top of the opener: every fact taken from memory renders as its own
markdown blockquote line ending in its id ("> fact — [id]"), and
anything beyond memory follows as normal prose. the short-circuit
banner quotes its verbatim items the same way.
verified in production before this commit: a live project reply opens
"From vouch memory:", quotes four claims as blockquotes with ids, then
continues with fresh code-verified analysis in plain prose.
phase 1 of global vouch: the substrate that later phases (global install tier, scope stamping, federated recall) build on. kb identity: init mints a durable instance id into config.yaml (kb.id + display name); every new audit event and bundle manifest carries it, so history stays attributable once knowledge moves between kbs. existing kbs backfill on re-init or hub register (an additive kb.identity event, never a rewrite); pre-identity audit chains still verify, pinned by a hand-chained legacy-line test. minting never destroys user config: a corrupt config.yaml is refused untouched, and the common backfill appends the kb block textually so comments and formatting survive byte-for-byte. bundles move settings, never identity: exported config.yaml is identity-stripped, config is compared structurally modulo the kb block on both sides (so legacy or comment-bearing bundles converge instead of conflicting forever), an already-matching destination is never rewritten, an unparseable destination config is never overwritten, and the destination's kb block survives an overwrite import. machine registry: vouch hub register/list/unregister over ~/.config/vouch/registry.yaml (xdg-aware, VOUCH_REGISTRY_PATH override; flock-serialized read-modify-write, unique-tempfile atomic renames). advisory routing state only — authority stays in each kb's own .vouch/, and a corrupt or missing registry degrades to per-project behaviour. the local seed of the vouchhub registry. resolution hardening: the upward walk never ascends past $HOME, so a stray home kb can no longer silently capture every project below it (the recorded dorahack incident); starting in $HOME still resolves it, VOUCH_KB_PATH and global.allow_home_kb stay as deliberate escape hatches, and a home-less container falls back to the plain walk. a registry row with role personal adds a second belt: ambient capture into it from another directory is refused, while reads — including the per-prompt context-hook — warn on stderr and proceed, so recall never goes dark. adapters can pin the walk start with VOUCH_PROJECT_DIR; vouch discover and vouch status report the resolution why-chain and the kb's id/name.
vouch discover --path now resolves with respect_env=false so an exported VOUCH_KB_PATH / VOUCH_PROJECT_DIR cannot answer for a tree the user explicitly asked about (coderabbit review); the default invocation keeps mirroring exactly what servers and hooks resolve. schemas/audit-event.schema.json regenerated for the new kb_id field (ci schema-drift gate).
phase 1 of global vouch, part 2: knowledge records which project it belongs to at write time — scope cannot be retrofitted once kbs start sharing artifacts. every new claim and page proposal, and every captured session-answer source, is stamped with the kb's own project scope at the propose gate; the stamp rides the existing proposal payload through approve(), so the review gate is untouched and all three surfaces (mcp, jsonl, cli) inherit it from the one proposals.* path. explicit scope= overrides are accepted and validated at the gate — a malformed one is a ProposalError, and a malformed scope already on disk degrades to unscoped instead of crashing the audit read path. the stamp and the read-side viewer resolve through one chain (VOUCH_PROJECT > retrieval.scope > the durable kb.id), so what a kb writes it can always read back; kb.name stays display-only and a rename cannot orphan stamped knowledge (probed live: digest unchanged across a rename). pages join claims and sources as scoped kinds, closing a cross-kb leak channel: vault edits carry the durable page's scope through instead of being restamped, and hand-edited legacy scope frontmatter degrades to unscoped rather than making the page unreadable. recall.build_digest is viewer-filtered like every other retrieval surface (it used to inject every live claim regardless of scope, the hijack failure mode reproduced in-process) and reports on stderr how many artifacts the filter hid — never silent; vouch recall also moves to the read-plane resolver so it warns instead of going dark under the personal-role guard. the salience sidebar honours the same filter. existing unscoped artifacts behave exactly as before — the full suite passes unchanged.
feat(hub): kb identity, machine registry, hijack-proof resolution
feat(scope): stamp project scope at capture; viewer-filter the digest
feat(hooks): render recalled memory as blockquotes in replies
phase 2 of global vouch: install once, every project gets capture and recall — while the data stays strictly per project. --global writes the user-level wiring under ~/.claude/ (hooks, /vouch-* commands, a machine-wide-worded CLAUDE.md fence) and registers vouch as a user-scope mcp server (top-level mcpServers in ~/.claude.json). declared by a manifest global: block, so other hosts opt in as pure manifest work. no kb is ever bootstrapped by a global install: each session resolves the nearest project .vouch/, and a folder without one never captures anywhere — its session opens with a one-line "run vouch init" note from the session-start banner, and vouch serve now starts without a kb on the stdio transport (per-tool-call errors instead of a machine-wide failed server in every non-vouch folder). coexistence with per-project installs is guarded three ways: the global settings template is byte-for-byte the project one (claude code collapses duplicate hook commands; a sync test freezes the pairing), capture dedups on the event's tool_use_id (exact, window-free), and every hook command (capture observe / answer / finalize / finalize-all / banner, context-hook, recall, ingest-codex) resolves the kb from the hook payload's cwd — VOUCH_PROJECT_DIR keeps precedence, and a payload naming a nonexistent cwd refuses capture rather than falling back to the process cwd and landing in the wrong kb. installer hardening from review: manifest dst containment is now lexical, so a dotfiles-managed symlinked ~/.claude (or CLAUDE.md) is written through instead of aborting; a global target of "." is rejected; a regular file squatting ~/.claude is a clean error; a malformed existing settings.json reports as failed (vouch is not wired) instead of "already present".
feat(install): vouch install-mcp claude-code --global
bump the version in all four sites (pyproject.toml, openclaw.plugin.json, package.json, src/vouch/__init__.py — the manifest parity test ties them) and date the changelog's unreleased block as 1.5.0 / 2026-07-20. the release: visible recall (instructional "From vouch memory" banners, blockquote rendering, opt-in confidence short-circuit), receipt auto-approve polish, and the global-vouch substrate — kb instance identity stamped into audit events and bundle manifests, the machine registry (vouch hub), hijack-proof kb resolution with the $HOME walk-stop, project scope stamped at capture with a viewer-filtered digest, and vouch install-mcp claude-code --global for install-once machine-wide wiring. all additive; no breaking changes.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthroughv1.5.0 adds durable KB identity, scoped artifact storage and recall, registry-aware resolution, global Claude Code installation, payload-aware capture routing, improved prompt-hook contracts, tool-use deduplication, identity-preserving bundle handling, and related tests and documentation. ChangesIdentity and artifact scoping
Registry and resolution
Global installation
Hooks and capture
Release metadata
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
README.md (1)
130-132: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrefix the blank line with
>to fix the blockquote formatting.The static analysis tool
markdownlint-cli2flagged a blank line inside a blockquote at line 131. To maintain a continuous blockquote and resolve the warning, prefix the blank line with>.🛠️ Proposed fix to format blockquote properly
> **What you'll see.** Every prompt is checked against the KB first. When vouch knows something relevant, the answer opens with **"From vouch memory:"**, grounded in the cited items; when it doesn't, it opens with *"Nothing in vouch on this."* — recall is visible on every turn, never silent. (A fresh KB knows almost nothing yet: work a session or two so capture fills it, then ask about the project again.) - +> > **Prefer one install for every project?** `vouch install-mcp claude-code --global` wires vouch once, machine-wide: user-level hooks and commands in `~/.claude/` plus a user-scope MCP server in `~/.claude.json`. Every Claude session in every folder then captures + recalls into *that folder's own* `.vouch/` — data stays per project. Run `vouch init` once in each project you want vouch in; a folder without a KB never captures anywhere — its session opens with a one-line "run `vouch init` to enable durable memory here" note and the `kb_*` tools say the same. Safe next to existing per-project installs: duplicate hooks collapse and capture dedups by event id.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 130 - 132, Update the blank line between the two quoted README paragraphs by prefixing it with “>”, preserving the continuous blockquote formatting without changing the paragraph content.Source: Linters/SAST tools
src/vouch/hooks.py (1)
114-121: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueAction gate misses common lead-ins.
_looks_like_actiononly inspects the first alphabetic token, so imperative prompts prefixed with filler ("please fix …", "can you refactor …", "let's implement …") are not detected as actions and become short-circuit-eligible. The escape hatch keeps this safe in practice, but consider skipping a small set of politeness/filler tokens before the verb check to make the gate match its stated intent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/vouch/hooks.py` around lines 114 - 121, Update _looks_like_action to skip a small, explicit set of leading politeness and filler tokens such as “please,” “can you,” and “let’s” before checking _ACTION_VERBS, while retaining punctuation/emoji skipping and the existing false result when no action verb is found.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/vouch/storage.py`:
- Around line 383-386: Update kb.ensure_identity() to serialize its config.yaml
read, identity mint, and rewrite using the same cross-process lock pattern as
audit.log_event(). Hold the lock across the entire read-mint-write sequence so
concurrent initialization or backfill cannot mint competing IDs, while
preserving the existing identity behavior when an ID already exists.
---
Nitpick comments:
In `@README.md`:
- Around line 130-132: Update the blank line between the two quoted README
paragraphs by prefixing it with “>”, preserving the continuous blockquote
formatting without changing the paragraph content.
In `@src/vouch/hooks.py`:
- Around line 114-121: Update _looks_like_action to skip a small, explicit set
of leading politeness and filler tokens such as “please,” “can you,” and “let’s”
before checking _ACTION_VERBS, while retaining punctuation/emoji skipping and
the existing false result when no action verb is found.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 26962063-c99d-43f5-a6f5-f3b19299a885
📒 Files selected for processing (34)
CHANGELOG.mdREADME.mdadapters/claude-code/CLAUDE.md.global.snippetadapters/claude-code/README.mdadapters/claude-code/install.yamlopenclaw.plugin.jsonpackage.jsonpyproject.tomlschemas/audit-event.schema.jsonschemas/page.schema.jsonsrc/vouch/__init__.pysrc/vouch/audit.pysrc/vouch/bundle.pysrc/vouch/capture.pysrc/vouch/cli.pysrc/vouch/extract.pysrc/vouch/health.pysrc/vouch/hooks.pysrc/vouch/hub.pysrc/vouch/install_adapter.pysrc/vouch/models.pysrc/vouch/proposals.pysrc/vouch/recall.pysrc/vouch/salience.pysrc/vouch/scoping.pysrc/vouch/storage.pysrc/vouch/vault_sync.pytests/test_audit_scoping.pytests/test_capture.pytests/test_capture_scope.pytests/test_hooks.pytests/test_hub.pytests/test_install_adapter.pytests/test_vault_sync.py
ensure_identity's read-mint-write on config.yaml was unserialized: two processes racing on a legacy kb (e.g. two session hooks backfilling at once) could both observe "no id", mint different ids, and last-writer-wins — every artifact stamped with the losing id becomes unreachable under the kb's surviving identity (coderabbit review on the 1.5.0 release pr). reuse the kb's existing cross-process lock (the audit sidecar) with a re-check inside the critical section, so the race loser adopts the winner's id instead of minting a second one. pinned by a six-process race test.
release prep:
test+ the 1.5.0 version bump, intomain. merging this also puts the--globalinstall section on the github front-page readme, together with the code it documents.what ships in 1.5.0 (all additive, no breaking changes):
capture answerno longer strands re-captured duplicates (feat(review): receipt auto-approve on by default, duplicate-safe drain #522, released partially in 1.4.0, completed here).vouch hub register/list/unregister); hijack-proof resolution (the upward walk never ascends past$HOME; personal-role registry guard;VOUCH_PROJECT_DIR); bundles move settings, never identity (feat(hub): kb identity, machine registry, hijack-proof resolution #530). project scope stamped at write time through one stamp/viewer resolver keyed on the durablekb.id; pages join the scoped kinds; the sessionstart digest is viewer-filtered and reports what it hides (feat(scope): stamp project scope at capture; viewer-filter the digest #531).vouch install-mcp claude-code --global: install once, every project gets capture + recall into its own.vouch/; kb-less folders never capture and get avouch inithint;vouch servestarts kb-less on stdio; three double-capture guards for coexistence with per-project installs (feat(install): vouch install-mcp claude-code --global #532).version bumped in all four sites (parity test green); changelog's unreleased block dated as
[1.5.0] — 2026-07-20. full gate green on the branch: 1550 passed, mypy clean, ruff clean;vouch --versionself-reports 1.5.0.after merge, the tag push is the publish step:
git tag v1.5.0 && git push --tags(release.yml → pypi trusted publishing), then draft the github release with the 1.5.0 changelog section as the body.🤖 Generated with Claude Code
Summary by CodeRabbit
--global) with user-scope MCP setup and project-stable knowledge.cwd), addedtool_use_iddedup, and added optional high-confidence retrieval short-circuit.