Skip to content

chore(release): prepare 1.5.0#533

Merged
plind-junior merged 15 commits into
mainfrom
release/1.5.0
Jul 20, 2026
Merged

chore(release): prepare 1.5.0#533
plind-junior merged 15 commits into
mainfrom
release/1.5.0

Conversation

@plind-junior

@plind-junior plind-junior commented Jul 20, 2026

Copy link
Copy Markdown
Member

release prep: test + the 1.5.0 version bump, into main. merging this also puts the --global install section on the github front-page readme, together with the code it documents.

what ships in 1.5.0 (all additive, no breaking changes):

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 --version self-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

  • New Features
    • Added machine-wide Claude Code install (--global) with user-scope MCP setup and project-stable knowledge.
    • Introduced KB identity + registry with guard-aware discovery and traceable “why” resolution.
    • Added artifact/page visibility scopes with scope-stamped proposals, scoped recall/search, and scope-aware audit visibility.
    • Improved capture routing (payload cwd), added tool_use_id dedup, and added optional high-confidence retrieval short-circuit.
  • Bug Fixes
    • Bundle imports now preserve destination identity and safely handle malformed configs/legacy scope data.
  • Documentation
    • Updated install/recall guidance and added release notes for v1.5.0.

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.
@github-actions github-actions Bot added docs documentation, specs, examples, and repo guidance cli command line interface adapters agent host adapters and install manifests openclaw openclaw integration storage kb storage, migrations, schemas, and proposals retrieval context, search, synthesis, and evaluation sync sync, vault mirror, and diff flows schemas json schemas and generated schema assets packaging packaging, build metadata, and make targets tests tests and fixtures size: XL 1000 or more changed non-doc lines labels Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d4840fb2-24fa-4986-9c63-5476ff0bcad7

📥 Commits

Reviewing files that changed from the base of the PR and between aa63424 and 60a326f.

📒 Files selected for processing (2)
  • src/vouch/storage.py
  • tests/test_hub.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/vouch/storage.py

Walkthrough

v1.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.

Changes

Identity and artifact scoping

Layer / File(s) Summary
Identity and scoped artifact lifecycle
schemas/*, src/vouch/models.py, src/vouch/storage.py, src/vouch/proposals.py, src/vouch/recall.py, src/vouch/scoping.py, src/vouch/bundle.py, tests/test_capture_scope.py, tests/test_hub.py
KBs receive durable identities; proposals and ingested artifacts are scope-stamped; recall, search, salience, audit, and bundles apply identity-aware scoping and preserve destination identity during import.

Registry and resolution

Layer / File(s) Summary
Registry and payload-aware resolution
src/vouch/hub.py, src/vouch/storage.py, src/vouch/cli.py, tests/test_hub.py, tests/test_capture.py, tests/test_hooks.py
A machine-local KB registry, resolution trace, personal-KB capture guard, and hook-payload cwd routing are added across CLI and capture flows.

Global installation

Layer / File(s) Summary
Global Claude Code installation
adapters/claude-code/*, src/vouch/install_adapter.py, src/vouch/cli.py, tests/test_install_adapter.py
install-mcp claude-code --global installs user-level hooks, commands, settings, and MCP registration without bootstrapping a project KB.

Hooks and capture

Layer / File(s) Summary
Capture deduplication and prompt hooks
src/vouch/capture.py, src/vouch/hooks.py, src/vouch/cli.py, tests/test_capture.py, tests/test_hooks.py
Capture deduplicates repeated tool-use IDs, while prompt hooks emit explicit grounding/no-hit instructions and optionally short-circuit high-confidence retrieval responses.

Release metadata

Layer / File(s) Summary
Release metadata and documentation
CHANGELOG.md, README.md, package.json, pyproject.toml, openclaw.plugin.json, src/vouch/__init__.py, schemas/*
Version metadata is updated to 1.5.0 and documentation describes global installation, recall behavior, and the new scoped and identity-aware features.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • vouchdev/vouch#530: Shares the KB identity, audit, bundle, registry, and resolution plumbing.
  • vouchdev/vouch#525: Directly relates to the Claude Code install-mcp and MCP registration flow.
  • vouchdev/vouch#529: Relates to prompt-hook recall formatting and injected memory instructions.

Suggested labels: mcp

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the release-prep changes for version 1.5.0.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/1.5.0

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the ci: passing ci is green label Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
README.md (1)

130-132: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefix the blank line with > to fix the blockquote formatting.

The static analysis tool markdownlint-cli2 flagged 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 value

Action gate misses common lead-ins. _looks_like_action only 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

📥 Commits

Reviewing files that changed from the base of the PR and between d1a0dee and aa63424.

📒 Files selected for processing (34)
  • CHANGELOG.md
  • README.md
  • adapters/claude-code/CLAUDE.md.global.snippet
  • adapters/claude-code/README.md
  • adapters/claude-code/install.yaml
  • openclaw.plugin.json
  • package.json
  • pyproject.toml
  • schemas/audit-event.schema.json
  • schemas/page.schema.json
  • src/vouch/__init__.py
  • src/vouch/audit.py
  • src/vouch/bundle.py
  • src/vouch/capture.py
  • src/vouch/cli.py
  • src/vouch/extract.py
  • src/vouch/health.py
  • src/vouch/hooks.py
  • src/vouch/hub.py
  • src/vouch/install_adapter.py
  • src/vouch/models.py
  • src/vouch/proposals.py
  • src/vouch/recall.py
  • src/vouch/salience.py
  • src/vouch/scoping.py
  • src/vouch/storage.py
  • src/vouch/vault_sync.py
  • tests/test_audit_scoping.py
  • tests/test_capture.py
  • tests/test_capture_scope.py
  • tests/test_hooks.py
  • tests/test_hub.py
  • tests/test_install_adapter.py
  • tests/test_vault_sync.py

Comment thread src/vouch/storage.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.
@plind-junior
plind-junior merged commit f12cf4c into main Jul 20, 2026
21 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adapters agent host adapters and install manifests ci: passing ci is green cli command line interface docs documentation, specs, examples, and repo guidance openclaw openclaw integration packaging packaging, build metadata, and make targets retrieval context, search, synthesis, and evaluation schemas json schemas and generated schema assets size: XL 1000 or more changed non-doc lines storage kb storage, migrations, schemas, and proposals sync sync, vault mirror, and diff flows tests tests and fixtures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant