Skip to content

fix(observe): match interruption markers carried in text blocks - #46

Merged
theonly1me merged 1 commit into
mainfrom
fix/interruption-marker-in-text-blocks
Sep 6, 2026
Merged

fix(observe): match interruption markers carried in text blocks#46
theonly1me merged 1 commit into
mainfrom
fix/interruption-marker-in-text-blocks

Conversation

@theonly1me

Copy link
Copy Markdown
Owner

What changed

  • contentContainsMarker now reads a text block's text field, not only content, via a new blockText helper.
  • Added src/observe/adapters/claudeUser.test.ts covering all four markers in three real record shapes: plain string, text block, and tool_result block.

Why

Claude Code carries interruption markers in { type: "text", text: "..." } blocks and denial markers in { type: "tool_result", content: "..." } blocks. The matcher only inspected content, so denials were found and interruptions were not.

Measured on a real corpus of 461 transcripts: 1,033 interruption markers on disk, 4 reaching the index. Denials were unaffected at 447 of 465. The staleness guard in src/signal/health.ts cannot catch this because it requires interruptions and denials to both be zero.

The existing fixture in src/cli/learn.test.ts:56 uses a string content, which is the shape that already worked, so nothing covered the shape that actually occurs.

How to verify

bun run check
bun run cli learn --dry-run

--dry-run runs a full fresh scan into an in-memory database and writes nothing. On the same corpus the mirror goes from 4 interruptions to roughly 1,100, broken down by what was interrupted:

  You stop the agent most often
    while using Bash ................................ 392
    during an explanation ........................... 210
    while using ExitPlanMode ........................ 208
    while using AskUserQuestion ..................... 164
    while using shell_command ....................... 124

Data handling

  • Any new capture source has an opt-in flag and a README entry in this PR
  • Everything that reaches the network passes redactSecrets
  • No raw capture in a log line, an error message, or a test fixture
  • A test exercises the real entry point, not just the redaction function

No new source and no new read. This changes which field of an already-parsed record is inspected. Marker classification happens before any TextRef is resolved, so the redaction gate is untouched.

@theonly1me
theonly1me merged commit f99b051 into main Sep 6, 2026
7 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