commit 6bc0ac427c4a9ee19ec553c4faedfa250054ed10 from: Isaac Meerleo date: Fri Jul 17 21:59:48 2026 UTC Recover trusted Compaction prose commit - c46c1d5a37ed2a2f3626a2b10708eab0864e4795 commit + 6bc0ac427c4a9ee19ec553c4faedfa250054ed10 blob - b012d04b45716766ba498dbcbe70907eb721c37a blob + f0042f1656fb29b448bd76ea3c06fe318fff02b3 --- regress/compaction/compaction_test.c +++ regress/compaction/compaction_test.c @@ -926,6 +926,48 @@ test_compaction_estimate_overflow(void) msglist_free(&messages); } +static void +test_summary_prose_restore(void) +{ + static const char prose[] = { 'n', 'o', 't', 'e', '\0', 's' }; + static const char unmatched[] = "legacy notes without generated blocks"; + struct compaction_files *files; + struct buf summary, out, blocks; + + files = compaction_files_new(); + CHECK(compaction_files_add(files, COMPACTION_FILE_READ, + "src/a.c", 7) == 0); + CHECK(compaction_files_add(files, COMPACTION_FILE_MODIFIED, + "src/b.c", 7) == 0); + buf_init(&summary); + buf_init(&out); + buf_init(&blocks); + buf_add(&summary, prose, sizeof(prose)); + CHECK(compaction_files_append(&summary, files, SIZE_MAX) == 0); + CHECK(compaction_summary_prose(&out, summary.data, summary.len, + files) == 0); + CHECK(buf_is(&out, prose, sizeof(prose))); + + buf_reset(&out); + CHECK(compaction_summary_prose(&out, unmatched, + sizeof(unmatched) - 1, files) == 0); + CHECK(buf_is(&out, unmatched, sizeof(unmatched) - 1)); + + CHECK(compaction_files_append(&blocks, files, SIZE_MAX) == 0); + buf_reset(&out); + CHECK(compaction_summary_prose(&out, blocks.data, blocks.len, + files) == 0); + CHECK(out.len == 0); + + buf_addstr(&out, "sentinel"); + CHECK(compaction_summary_prose(&out, NULL, 1, files) == -1); + CHECK(out.len == 0); + buf_free(&blocks); + buf_free(&out); + buf_free(&summary); + compaction_files_free(files); +} + int main(void) { @@ -948,6 +990,7 @@ main(void) test_cut_plan_turn_boundaries(); test_cut_plan_tool_pairs_and_steers(); test_compaction_estimate_overflow(); + test_summary_prose_restore(); REGRESS_END(); } blob - 3d59370f3ab1d0dd03277436d94b589ac3d858e3 blob + a1f1e0d4295718f3f1f6680ef6ab275e8dff11ed --- src/common/compaction.c +++ src/common/compaction.c @@ -879,6 +879,50 @@ fail: return (-1); } +int +compaction_summary_prose(struct buf *out, const void *summary, + size_t summary_len, const struct compaction_files *files) +{ + const unsigned char *bytes = summary; + struct buf blocks, restored; + size_t suffix; + + if (out == NULL) + return (-1); + buf_reset(out); + if ((summary == NULL && summary_len != 0) || files == NULL) + return (-1); + buf_init(&blocks); + buf_init(&restored); + if (compaction_files_append(&blocks, files, SIZE_MAX) == -1) + goto fail; + if (summary_len == blocks.len && + (summary_len == 0 || memcmp(summary, blocks.data, blocks.len) == 0)) + goto publish; + if (summary_len >= blocks.len + 2) { + suffix = summary_len - blocks.len; + if (bytes[suffix - 2] == '\n' && bytes[suffix - 1] == '\n' && + memcmp(bytes + suffix, blocks.data, blocks.len) == 0) { + buf_add(&restored, bytes, suffix - 2); + goto publish; + } + } + if (summary_len > 0) + buf_add(&restored, summary, summary_len); + +publish: + if (restored.len > 0) + buf_add(out, restored.data, restored.len); + buf_free(&restored); + buf_free(&blocks); + return (0); + +fail: + buf_free(&restored); + buf_free(&blocks); + return (-1); +} + static int tool_value_add(struct compact_writer *w, const struct json *json, int value) { blob - 8db76b21a3e3a15dd2517608e8ecdc9bff2359eb blob + f131b52c05193b6703c061a7f65141b11f2e762d --- src/common/compaction.h +++ src/common/compaction.h @@ -97,6 +97,10 @@ int compaction_files_get(const struct compaction_files int compaction_files_append(struct buf *, const struct compaction_files *, size_t); +/* Recover model prose without parsing model text or trusting generated tags. */ +int compaction_summary_prose(struct buf *, const void *, size_t, + const struct compaction_files *); + /* Estimate one prospective provider request without provider-wire encoding. */ int compaction_estimate_request(const void *, size_t, const struct msglist *, const struct tool_def *, size_t, size_t *);