Skip to content

feat(capture): correction-capture — auto-propose a draft claim when the user pushes back (#430)#458

Open
moorsecopers99 wants to merge 1 commit into
vouchdev:mainfrom
moorsecopers99:feat/correction-capture
Open

feat(capture): correction-capture — auto-propose a draft claim when the user pushes back (#430)#458
moorsecopers99 wants to merge 1 commit into
vouchdev:mainfrom
moorsecopers99:feat/correction-capture

Conversation

@moorsecopers99

Copy link
Copy Markdown

what changed

correction-capture: when the user pushes back on the agent ("no, we deploy from main not release"), that correction now becomes a PENDING claim proposal for review instead of evaporating. a new UserPromptSubmit hook (vouch capture correction) runs a cheap, no-llm heuristic on the turn — a pushback opener (no, / actually, / that's wrong…) or a corrective phrase — and, when it fires, files one draft claim quoting the correction, tagged auto:correction, citing the correction message as a content-addressed message source for evidence. core logic lives in the new src/vouch/correction.py; it's wired into the claude-code adapter's UserPromptSubmit hook alongside the existing context-hook.

why

capture.observe harvests tool outcomes passively, but the single highest-signal event in a session — the user correcting the agent — is invisible to it and is the knowledge most reliably lost. this turns that moment into a reviewable draft, automatically, without ever writing approved knowledge. closes #430.

proof

captured from the shipped cli against a fresh kb. a correction files a draft by auto:correction; a normal instruction is ignored; an exact repeat is deduped; the per-session cap (default 3) bounds the rest — and nothing crosses into approved claims:

$ vouch capture correction --prompt "no, we deploy from main not release" --session-id demo --json
{ "captured": true, "correction": "we deploy from main not release",
  "proposal_id": "20260710-143324-9eb472c2", "source_id": "91910e89…" }

$ echo '{"session_id":"demo","prompt":"actually, the retry limit is 5 not 3"}' | vouch capture correction --json
{ "captured": true, "correction": "the retry limit is 5 not 3", … }

$ vouch capture correction --prompt "please refactor the parser" --session-id demo --json
{ "captured": false, "skipped": "no-correction" }

$ vouch capture correction --prompt "no, we deploy from main not release" --session-id demo --json
{ "captured": false, "skipped": "duplicate" }

$ vouch pending
• 20260710-143324-9eb472c2  [claim]  by auto:correction   we deploy from main not release
• 20260710-143325-cc5026aa  [claim]  by auto:correction   the retry limit is 5 not 3

vouch list-claims still shows only the starter claim — nothing auto-proposed reached the approved store.

what might break

  • no surface change. no new kb.* method, no object-model / on-disk / bundle / audit change. this is a CLI capture subcommand (the sibling of vouch capture observe) plus a hook line — the same shape as the existing ambient capture, which is also CLI+hook, not a kb.* method.
  • new config key capture.correction (nested under the existing capture block); enabled defaults true, per_session_cap defaults 3. added to the starter config so new KBs carry the default explicitly; existing KBs pick up the defaults defensively (absent key → default). opt out with capture.correction.enabled: false.
  • the claude-code adapter's UserPromptSubmit hook gains a vouch capture correction || true entry. the hook prints nothing and exits 0 on any error, so it can never block the user's turn.
  • the review gate is intact: correction-capture has no code path to proposals.approve (a structural test asserts it imports/calls no approve), routes exclusively through proposals.propose_claim, and can only create pending drafts.

vep

not a surface change — no kb.* method, no object-model/on-disk/bundle/audit/transport change, and the new capture.correction config is additive with safe defaults. per proposals/README.md this is day-to-day code (a new capture path composed from existing propose_claim), so no vep. flagging for the record in case a maintainer reads the config addition differently.

tests

  • make check passes locally (lint + mypy + pytest) — pytest 1101 passed / 29 skipped, mypy clean (90 files), ruff clean. run with the [dev,web] extras to match ci.
  • new behaviour has a test — tests/test_capture_correction.py (21 cases): the propose-only invariant (pending claim filed, nothing approved) and a structural no-approve guard, the per-session cap (and that it's per-session), exact-repeat dedup, the capture.correction.enabled gate + config overrides, and the detection heuristic (positive/negative/marker-stripping).
  • CHANGELOG.md updated under ## [Unreleased].

detect a user correction ("no, we deploy from main not release") on the
UserPromptSubmit turn with a cheap no-llm heuristic and file it as a
PENDING claim proposal quoting the correction, tagged auto:correction
and citing the correction message as evidence.

proposes, never approves — there is no code path to proposals.approve,
so the pending queue is the draft state a human still drains. near-
duplicate corrections are suppressed via the vouchdev#147 similarity path plus a
cheap exact-repeat check, and capture.correction.per_session_cap
(default 3) bounds an over-eager heuristic.

driven by a new `vouch capture correction` subcommand wired into the
claude-code UserPromptSubmit hook; config capture.correction.{enabled,
per_session_cap} with defaults in the starter config. tests in
tests/test_capture_correction.py assert the propose-only invariant, the
cap, dedup, and config gating.

closes vouchdev#430
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@moorsecopers99, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 71d4643b-72e0-425a-a943-787c0c897cee

📥 Commits

Reviewing files that changed from the base of the PR and between 5c98a3a and 898f3e5.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • adapters/claude-code/.claude/settings.json
  • src/vouch/cli.py
  • src/vouch/correction.py
  • src/vouch/storage.py
  • tests/test_capture_correction.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(capture): correction-capture — auto-propose a draft claim when the user pushes back

2 participants