From 5e4f0de093fe58295afadf4e4c5a58c40e7f01d1 Mon Sep 17 00:00:00 2001 From: justrach <54503978+justrach@users.noreply.github.com> Date: Mon, 2 Nov 2026 09:17:40 +0800 Subject: [PATCH 1/2] test: Claude Agent compaction sends its summary request as the prompt Compaction runs on a fresh tools-off Claude Code process. Cut mid tool loop, its history ends on tool results (or a call) followed by the summary request. freshContent used to fold the request into the text checkpoint and add "Continue from where the checkpoint ends.", so the model carried on with the task or asked the user a question, and that reply was installed as the summary. #1792's change to freshContent fixed this; this pins both shapes. --- src/claude_agent_tests.zig | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/claude_agent_tests.zig b/src/claude_agent_tests.zig index c5e450c3..00f7a7c7 100644 --- a/src/claude_agent_tests.zig +++ b/src/claude_agent_tests.zig @@ -147,6 +147,38 @@ test "claude-agent version floor" { try std.testing.expect(wire.effortFlag("none") == null); } +test "claude-agent compaction mid tool loop: the summary request is the prompt, never checkpoint to continue" { + // Compaction runs on a fresh tools-off process. Cut mid loop, its history + // ends on tool results (or a call) and then the summary request. Folding + // the request into the checkpoint and adding "Continue from where the + // checkpoint ends." made the model carry on with the task, or ask the + // user a question, and that text was installed as the "summary". + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const a = arena.allocator(); + const request = "Write a handoff summary of the conversation so far."; + const shapes = [_][]const u8{ + \\[{"role":"user","content":"fix the bug"}, + \\ {"role":"assistant","content":[{"type":"tool_use","id":"t1","name":"read_file","input":{"path":"a.zig"}}]}, + \\ {"role":"user","content":[{"type":"tool_result","tool_use_id":"t1","content":"fn main() {}"}]}, + \\ {"role":"user","content":"Write a handoff summary of the conversation so far."}] + , + \\[{"role":"user","content":"fix the bug"}, + \\ {"role":"assistant","content":[{"type":"tool_use","id":"t1","name":"read_file","input":{"path":"a.zig"}}]}, + \\ {"role":"user","content":"Write a handoff summary of the conversation so far."}] + , + }; + for (shapes) |shape| { + const msgs = try parse(a, shape); + const blocks = (try history.freshContent(a, msgs.array.items)).array.items; + try std.testing.expectEqual(@as(usize, 2), blocks.len); + const cp = blocks[0].object.get("text").?.string; + try std.testing.expect(std.mem.indexOf(u8, cp, "read_file") != null); + try std.testing.expect(std.mem.indexOf(u8, cp, request) == null); + try std.testing.expectEqualStrings(request, blocks[1].object.get("text").?.string); + } +} + test "claude-agent fresh session: earlier history is a checkpoint, the prompt keeps its blocks" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); From e04741e5a5f0b7f2e166fb88f43dfa3d95945c6d Mon Sep 17 00:00:00 2001 From: justrach <54503978+justrach@users.noreply.github.com> Date: Mon, 2 Nov 2026 09:25:29 +0800 Subject: [PATCH 2/2] Prepare v0.302.68 release Changelog, release notes, and --version what's-new for v0.302.68, and ratchet the tier-1 test count baseline to 3587. --- CHANGELOG.md | 6 ++++++ docs/releases/v0.302.68.md | 8 ++++++++ scripts/eval/tier1-manifest.json | 2 +- src/cli_text_source.zig | 4 ++++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 docs/releases/v0.302.68.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 134d875c..9bb9be6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ The release workflow uses a tag's section here as its release notes (a hand-written `docs/releases/.md` wins if present), so keeping this file current is part of cutting a release. +## v0.302.68 + +- Claude Agent compaction sends its summary request as the request. Cut mid tool loop, the request was folded into the conversation checkpoint and followed by "Continue from where the checkpoint ends.", so in a long chat the model carried on with the task or asked a question, and that reply was installed as the summary (#1792, #1793, #1797). +- Claude Agent: a prompt sent after a turn that ended on a tool call keeps its text and images instead of joining the checkpoint as text (#1792, #1793). +- Retains all changes from v0.302.67. + ## v0.302.67 - Claude Agent refreshes a changed tool list in place. Removing and re-adding graff's tools (to make Claude Code re-read them) failed the `load_tool_schemas` call that caused the change with "Connection closed", and the model often ended its turn or got "No such tool available"; graff now sends `tools/list_changed` and keeps the connection (#1789, ADR 0311). diff --git a/docs/releases/v0.302.68.md b/docs/releases/v0.302.68.md new file mode 100644 index 00000000..d3b33208 --- /dev/null +++ b/docs/releases/v0.302.68.md @@ -0,0 +1,8 @@ +# v0.302.68 + +Claude Agent compaction writes a real summary again, and a prompt after a finished turn keeps its images. + +- **Compaction summarizes instead of carrying on.** Claude Agent runs compaction on a fresh Claude Code process. When it was cut in the middle of a tool loop, the summary request was folded into the conversation text and followed by "Continue from where the checkpoint ends." In a long chat the model kept working on the task, or asked you a question, and that reply was installed as the summary. The summary request is now always sent as the request. (#1792, #1793, #1797) +- **A prompt after a finished turn is read as a prompt.** The same fault hit a new message sent after a turn that ended on a tool call such as `attempt_completion`: it joined the old conversation as text, and its images arrived as "[image]". The message now reaches the model as itself, images included. (#1792, #1793) + +Includes all changes from v0.302.67. diff --git a/scripts/eval/tier1-manifest.json b/scripts/eval/tier1-manifest.json index 1fef3c9b..de3f3655 100644 --- a/scripts/eval/tier1-manifest.json +++ b/scripts/eval/tier1-manifest.json @@ -14,7 +14,7 @@ "src/main.zig", "src/repl.zig" ], - "test_count_baseline": 3585, + "test_count_baseline": 3587, "test_count_slack": 25, "required_invariants": [ { diff --git a/src/cli_text_source.zig b/src/cli_text_source.zig index 95ce7f34..04749f20 100644 --- a/src/cli_text_source.zig +++ b/src/cli_text_source.zig @@ -5,6 +5,10 @@ pub const changelog_text = \\What's new \\────────── + \\0.302.68 + \\ • Claude Agent: compaction writes a summary instead of continuing the task + \\ • Claude Agent: a prompt after a finished turn keeps its images + \\ \\0.302.67 \\ • Claude Agent: loading a tool no longer drops the call or ends the turn \\ • a finished task still hears peers who message it directly