Skip to content

Add a corpus-eval skill for evaluating parsing changes against real data - #320

Merged
xerhab merged 1 commit into
mainfrom
corpus-eval-skill
Jul 27, 2026
Merged

Add a corpus-eval skill for evaluating parsing changes against real data#320
xerhab merged 1 commit into
mainfrom
corpus-eval-skill

Conversation

@xerhab

@xerhab xerhab commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Documents the evaluation method the recent chat-fidelity work (#317, #318, #319) used, so the next parsing change doesn't rediscover it.

Why

agent/ parses two undocumented formats owned by someone else — Claude Code's transcript JSONL and its tmux pane. Unit tests can only assert what you already believed the format was, which is exactly the wrong instrument. This host happens to hold every transcript the fleet has ever written (~580, ~61k entries, spanning many Claude Code versions) and can produce real TUI dialogs on demand.

Leaning on that found things tests structurally cannot:

  • shapes occurring 5 times in 61k entries (ExitPlanMode) — real, and invisible to sampling;
  • a py-vs-js mirror divergence that turned out to predate the change being reviewed;
  • which fields were worth building for, by count rather than by guess.

What the skill covers

  1. Inventory before you design — count every entry type, block type, tool name and input key across the corpus first.
  2. Old-vs-new differential — load both module versions, run every entry through each in one pass, and classify each diff as identical / intended / regression in code.
  3. Mirror parity, baseline firsthub-agent.py vs tunnel-agent.js over the corpus, measured against the divergence that already exists.
  4. Measure the gain — count what the change surfaces ("2,381 Edit calls previously showed only a file path"), which falls out of the same pass.
  5. Capture pane fixtures, never write them — the wording, glyphs and blank-line placement are the contract.

Plus the traps that each cost real time. The two most valuable:

  • Comparing JSON.stringify output across the two languages reported 29,761 mismatches where there were 13 — key insertion order differs between the languages, so deep-equal the parsed structures instead.
  • Those 13 are not a mirror bug: _clip cuts at 2000 codepoints in Python and clip at 2000 UTF-16 units in JS, so a block whose first 2000 characters contain a non-BMP character (emoji) truncates one character apart. Confirmed by inspection — nonBMP=true, pyCodepoints=2000 vs jsCodepoints=1999, nothing but the cut point differing.

Verification

Both recipes were re-run as written while drafting, and reproduce the documented figures: 60,615 entries identical old-vs-new on a no-op branch, and 13 / 38,425 mirror mismatches with every one confirmed non-BMP.

Every count quoted was re-measured rather than copied from the earlier session — which surfaced something worth recording in the skill itself: the corpus is live and grows under you (577 transcripts where an earlier pass saw 559), so the counts are illustrative rather than fixtures, and a differential must read one snapshot for both sides or entries appearing mid-run show up as phantom diffs.

Notes

No code changes; docs only. CLAUDE.md is deliberately untouched — it doesn't reference the existing verify skill either (skills are auto-discovered from .claude/skills/), and it is currently over its own 150k budget.

The agent parses two undocumented formats owned by someone else — Claude
Code's transcript JSONL and its tmux pane — and this host happens to hold
every transcript the fleet has written plus a live Claude to produce real
dialogs. The recent chat-fidelity work (#317, #318, #319) leaned on that
corpus rather than on hand-written fixtures, and found things unit tests
structurally cannot: shapes occurring 5 times in 61k entries, and a
py-vs-js mirror divergence that turned out to predate the change.

Writes that method down so the next parsing change doesn't rediscover it:
inventory the shapes before designing, replay old-vs-new over one snapshot
classifying diffs into identical/intended/regression, measure the py/js
mirror parity against its PRE-EXISTING baseline, count what the change
actually surfaces, and capture pane fixtures from a live TUI instead of
inventing the glyphs.

Records the traps that each cost real time, including the two worth the
most: comparing JSON.stringify output across the two languages reports
~30k mismatches where there are 13 (key insertion order differs — deep-equal
the parsed structures), and those 13 are a codepoint-vs-UTF-16 clip-length
artifact on emoji-bearing entries, not a mirror bug.

Both recipes were re-run as written while drafting this, and reproduce the
documented figures (60,615 entries identical old-vs-new on a no-op branch;
13/38,425 mirror mismatches, each confirmed non-BMP).
@xerhab
xerhab merged commit 3fc6f82 into main Jul 27, 2026
@xerhab
xerhab deleted the corpus-eval-skill branch July 27, 2026 19:56
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