Skip to content

Fix capture hook dropping drafts and leaking injected context - #5

Merged
dimittal merged 1 commit into
mainfrom
fix/capture-hook-dedupe-and-context
Nov 2, 2026
Merged

dimittal merged 1 commit into
mainfrom
fix/capture-hook-dedupe-and-context

Conversation

@dimittal

@dimittal dimittal commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Two bugs in automatic (hook) capture, found while running a real Claude Code (Opus 5.5) session against a local Hindsight.

1. Every hook capture after the first was dropped

Without an extraction model, hook captures all send the placeholder summary "Captured agent evidence; requires human review." The duplicate fingerprint covered only the summary, so the server returned extraction_state: duplicate for every capture after the first in a scope. Automatic capture effectively saved one draft, ever.

Fix: hook payloads set evidence_only: true; those drafts are fingerprinted on summary + redacted excerpt. Explicitly proposed facts (MCP propose_clue, CLI) still dedupe on the fact alone, so rejection suppression is unchanged.

2. Harness-injected context leaked into clue evidence

Current Claude Code transcripts contain api-request-blob records that repeat each user turn together with injected <system-reminder> context (account email, workspace details). The hook read them as user messages, so drafts contained that context (the email was redacted, but other workspace details need not be) and each prompt appeared twice.

Fix: the Claude reader keeps only user/assistant records, skips isMeta, and strips <system-reminder> blocks. The server also strips them from captured summaries and excerpts, since any client can send them.

Tests

  • New: test_transcript_drafts_dedupe_on_evidence_and_drop_injected_context (integration) and test_claude_capture_skips_request_copies_and_injected_context (agent contract). Both fail on main and pass here.
  • Updated the incremental-checkpoint fixture to use real Claude record shape (type: "assistant").
  • pytest (87), ruff check, ruff format --check, mypy pass.
  • Manual: image built from this branch, Stop hook active, two real Opus 5.5 sessions → two distinct drafts, no injected context, each prompt once.

🤖 Generated with Claude Code

- Without an extraction model every hook capture used the same placeholder
  summary, and the duplicate fingerprint covered only that summary, so every
  capture after the first in a scope was dropped as a duplicate. Hook payloads
  now mark themselves evidence_only, and those drafts are fingerprinted on the
  summary plus the redacted excerpt. Explicitly proposed facts still dedupe on
  the fact alone.
- Claude Code transcripts include api-request-blob records that repeat each
  user turn together with harness-injected <system-reminder> context (account
  email, workspace details). The Claude reader now keeps only user and
  assistant turns, skips isMeta records, and strips system-reminder blocks; the
  server strips them from captured summaries and excerpts as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dimittal
dimittal merged commit c2249f7 into main Nov 2, 2026
4 checks passed
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.

1 participant