the claude-code adapter wires two hook events today — SessionStart (a once-per-session status + recall digest) and PostToolUse (passive capture) — in adapters/claude-code/.claude/settings.json. there is no per-turn injection point. that means approved knowledge relevant to this prompt only reaches the model if the agent remembers to call kb.context / kb.search itself. an operator who just told the agent a fact, or asked a question the kb already answers, gets nothing back unless the agent volunteers a lookup — the highest-value moment (the turn boundary) is unhooked.
the reflex to surface that context already exists server-side: salience.record_query buffers recent queries and salience.attach_salience prefetches the top-k matched entities/claims into _meta.vouch_salience (#223). what's missing is the adapter wiring that feeds the prompt into it every turn and injects the result before the model thinks.
proposed surface
a new read-only cli command that the hook shells to:
vouch auto-context "<prompt text>" [--budget-chars N] [--format text|json]
- runs entity-salience retrieval (
salience + context.build_context_pack) over approved artifacts only, viewer-scoped, returns a small budgeted block.
- writes nothing, proposes nothing, calls no
propose_* / approve path — it is a viewport over the same reads kb.context already does.
- latency-bounded: reuse the
retrieval.reflex.* config (enabled, window, top_k) and the salience path rather than a cold FTS query per turn.
then add the hook to the adapter templates so it's installed at T4:
"UserPromptSubmit": [
{ "hooks": [ { "type": "command",
"command": "vouch auto-context \"$CLAUDE_USER_PROMPT\" --format text" } ] }
]
the hook prints the block on stdout as additionalContext. it must be wired through the manifest-driven writer (install_adapter.py) and the T4 stanza in adapters/claude-code/install.yaml, then mirrored into adapters/cursor|codex|openclaw so all surfaces stay at parity (the invariant the openclaw manifest test already enforces for skills).
review gate & scope
read-only by construction — injection surfaces approved knowledge, it does not capture or write. nothing here can create or edit an artifact, so there is no proposal and no kb.approve step. because it reads the same viewer-scoped, approved corpus kb.context already exposes, it cannot leak across scopes any more than that path can (subject to the same filters). local-first: a shell command the host runs on the turn boundary, no daemon, no network.
acceptance criteria
related: #223 (the salience reflex this consumes), #236 (kb.volunteer_context push channel), #54 (friendlier out of the box).
the claude-code adapter wires two hook events today —
SessionStart(a once-per-session status + recall digest) andPostToolUse(passive capture) — inadapters/claude-code/.claude/settings.json. there is no per-turn injection point. that means approved knowledge relevant to this prompt only reaches the model if the agent remembers to callkb.context/kb.searchitself. an operator who just told the agent a fact, or asked a question the kb already answers, gets nothing back unless the agent volunteers a lookup — the highest-value moment (the turn boundary) is unhooked.the reflex to surface that context already exists server-side:
salience.record_querybuffers recent queries andsalience.attach_salienceprefetches the top-k matched entities/claims into_meta.vouch_salience(#223). what's missing is the adapter wiring that feeds the prompt into it every turn and injects the result before the model thinks.proposed surface
a new read-only cli command that the hook shells to:
salience+context.build_context_pack) over approved artifacts only, viewer-scoped, returns a small budgeted block.propose_*/approvepath — it is a viewport over the same readskb.contextalready does.retrieval.reflex.*config (enabled,window,top_k) and the salience path rather than a cold FTS query per turn.then add the hook to the adapter templates so it's installed at T4:
the hook prints the block on stdout as additionalContext. it must be wired through the manifest-driven writer (
install_adapter.py) and the T4 stanza inadapters/claude-code/install.yaml, then mirrored intoadapters/cursor|codex|openclawso all surfaces stay at parity (the invariant the openclaw manifest test already enforces for skills).review gate & scope
read-only by construction — injection surfaces approved knowledge, it does not capture or write. nothing here can create or edit an artifact, so there is no proposal and no
kb.approvestep. because it reads the same viewer-scoped, approved corpuskb.contextalready exposes, it cannot leak across scopes any more than that path can (subject to the same filters). local-first: a shell command the host runs on the turn boundary, no daemon, no network.acceptance criteria
vouch auto-context "<prompt>"runs read-only, surfaces approved-only context, writes nothing (no audit event, no proposal).retrieval.reflex.*config; a kb with the reflex disabled emits an empty block.UserPromptSubmithook to.claude/settings.jsonvia the manifest writer.tests/test_install_adapter.pyasserts the hook is written at T4; a test covers the read-only invariant ofauto-context.make checkgreen.related: #223 (the salience reflex this consumes), #236 (
kb.volunteer_contextpush channel), #54 (friendlier out of the box).