fix(compat): CC 2.1.166 compatibility#81
Open
tombelieber wants to merge 2 commits into
Open
Conversation
CC elides the paste body for large pastes, persisting only a contentHash with no `content` field. PasteContent.content lacked #[serde(default)], so serde rejected the whole PromptEntry and parse_history silently dropped the entire line — ~2.4% of a real history.jsonl corpus (490/20343), undercounting prompt stats and making those prompts unsearchable. Add #[serde(default)] to every PromptEntry/PasteContent field per the External-data boundary-normalization mandate: a missing/renamed field now degrades per-field instead of dropping the line. Deserialize-only internal types (no TS/utoipa derive) → no codegen. +2 regression tests; 13/13 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scan_file only collected top-level message.content[] block types, treating tool_result as a leaf. But tool_reference appears ONLY nested inside tool_result.content[] (815x in real data, 0x top-level), so the drift gate was structurally blind to it — reporting unhandled_content_block_types: [] while the type is genuinely dropped by the parsers. Descend exactly ONE level into tool_result.content[] (mirroring extract_tool_results), never a deep walk (which over-collects junk type keys from tool_use.input). Oracle now correctly surfaces unhandled=[tool_reference]. Isolated to the standalone diagnostic binary; no parser/export/live impact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CC 2.1.166 compatibility audit — SAFE fixes + RISKY findings for review
Automated
cc-compat-patchrun. Gate fired on a real version bump (baseline2.1.162→ newest2.1.166in local CC data); CHANGELOG for(2.1.162, 2.1.166]read in full. The version delta itself was transcript-shape-clean (settings/permissions/CLI/hook-output/runtime only), but the full 3-dimension regression sweep surfaced 7 confirmed findings (0 rejected). None were introduced by the 2.1.x bump — they are pre-existing gaps the sweep quantified against real data.✅ SAFE — applied in this PR (verified)
1.
fix(history)— recover ~2.4% of silently-dropped history.jsonl lines (203ebd8c){"id":1,"type":"text","contentHash":"…"}with nocontentfield.PasteContent.contentlacked#[serde(default)], so serde rejected the wholePromptEntryandparse_historysilently dropped the entire line (debug!("skipping malformed history line")).#[serde(default)]on everyPromptEntry/PasteContentfield (External-data boundary-normalization mandate). Deserialize-only internal types (noTS/utoipaderive) → no codegen. +2 regression tests.cq check✅ ·cq clippy -D warnings✅ ·prompt_historytests 13/13 ✅ · real-file parse 19853→20343 (0 dropped).2.
fix(cc-compat)— oracle now censuses nestedtool_result.content[](b3fba699)cc_compat_oracle::scan_fileonly collected top-levelmessage.content[]types, treatingtool_resultas a leaf. Buttool_referenceappears only nested (815× in real data, 0× top-level), so the drift gate was structurally blind to it — it reportedunhandled_content_block_types: []while the type is genuinely dropped by the parsers. This is why this run's initial drift signal looked clean.tool_result.content[](mirrorsextract_tool_results); never a deep walk (a deep walk over-collects 9 junktypekeys fromtool_use.input). Isolated to the standalone diagnostic binary — no parser/export/live/frontend impact.unhandled_content_block_types[]→['tool_reference'](true-positive).cq check/clippy -D warnings✅.🔧 RISKY — needs human (full evidence below; not auto-applied)
These are real, data-proven Zero-Data-Loss issues but require multi-crate data-model changes, codegen, and/or UI/UX decisions — out of scope for additive auto-apply.
R1 (high) — Nested
tool_result.content[]image +tool_referencedropped on the main timeline path.crates/core/src/block_accumulator/content.rsextract_tool_resultsdescends one level but filters totextonly.ToolResultBlockhas no carrier for images ortool_reference. Real data: nestedtext923 /tool_reference815 /image454 (still present at 2.1.165/166:tool_reference13,image9).tool_referenceis always ToolSearch output (matched/loaded tool names) — so every ToolSearch tool-result currently renders blank; computer-use/browser/Read-of-image screenshots render empty.Fix spans:
block_accumulator/{content,assistant,handlers}.rs(+images: Vec<ImageContent>,tool_refs: Vec<String>onToolResultBlock/ToolResult),crates/types/src/block_types.rs, ts-rs regen + OpenAPI regen (new fields),ToolDetail.tsx(render thumbnails + matched-tools chips — base64-thumbnail-vs-inline is a UX call). Add"tool_reference"tohandled_content_block_types()only once actually surfaced.R2 (high) — Same drop on the simple-parser export/share path (
/parsed→ Markdown/PDF/HTML/share).crates/core/src/parser/content.rsextract_tool_result_contentjoins only nestedtext;crates/core/src/parser/session.rsextract_imagesscans top-level only (returns 0 for the 454 nested images). Image portion is purely additive (reuses the existingMessage.imageschannel — no codegen);tool_referenceportion changes the result string that feeds the server-side share serializer + the byte-identical block-pipeline export oracle, so it must be validated against that oracle first. Fix both render paths together (the "two render paths" drift rule).R3 (high) —
modeSystemVariant renders nothing in BOTH chat & dev timelines (2,033 real records).Backend correctly emits
SystemVariant::Modeand the generatedSystemVariant.tshas'mode', but the hand-writtenpackages/shared/src/types/blocks.tsunion is missing'mode', so the_exhaustive: neverguards in both dispatchers compile as if the switch were exhaustive and both fall todefault → null. Classic ts-rs-regen hand-type drift (introduced 2026-06-02 whenModewas added Rust-side). Fix: add'mode'to the union (this intentionally breaks the two exhaustiveness guards, surfacing the missing arms), add aModePillreadingdata.mode(notdata.permissionMode) + a dev arm, +frontend tests. Hardening: deriveblocks.tsunion from generatedSystemVariantso this can't silently recur.bun typecheck+ shared vitest; no Rust/codegen.R6 (low) — Simple parser drops 9/15 record types on the export/share path (
mode,permission-mode,attachment,pr-link,worktree-state,ai-title,custom-title,agent-name,last-prompt).crates/core/src/parser/session.rsmatches only 6 types; the rest hit_ => debug!("Ignoring …"). The main timeline (?format=block, block_accumulator) handles all 15 — asymmetric fidelity ("share path is lossy"). Mostly session metadata (conversation turns are preserved). Preferred systemic fix: route export/share through the block_accumulator (single source of truth) so exports become byte-equivalent to the timeline; smaller fix: add the 9 missing arms + a parser-parity guard test. Both need a shape/UX decision (e.g. avoid cluttering exports with 81kattachmentblocks).Baseline
Baseline bumped
2.1.162 → 2.1.167viacc-compat-oracle --update-baseline(all gaps are either applied here or captured above, per the skill's Step 5). The audit covered the(2.1.162, 2.1.166]delta; 2.1.167 landed mid-run and was confirmed transcript-shape-clean (changelog: "bug fixes and reliability"; empirical scan of 216,744 records including 2.1.167 → 0 unhandled record types, unchanged 16-type/5-block inventory) — so it is not an unaudited blind bump. This stops the version-gate from re-auditing the same delta. See the merge-ordering note re: branch-2 re-fires after #2 merges.Drift report (oracle)
version_changed: true(2.1.162→2.1.166)unhandled_record_types: [],unhandled_content_block_types: [](the latter was a false negative — see SAFE feat(ui): semantic card components for conversation UI redesign #2)🤖 Generated with Claude Code