Conversation
`create_compaction`, `complete_compaction`, `get_compaction` and `latest_completed_compaction` had zero tests. The only thing that blocked them was the hand-written fixture, which never created `assistant_compactions`; `db::test_support::workspace_pool` (#200) does. `latest_completed_compaction` selects the row that decides which messages the provider is allowed to see. It is not the last line of defence — its one consumer, `provider_history_messages_with_compaction`, re-checks the same two nullable fields and falls back to the unfiltered history — but it is the first, and none of its four `WHERE`/`ORDER BY` terms had a test. Each now does: a compaction that is still running, that has no summary message, or that has no window end must stay invisible, and the row that wins is the last one *completed*, not the last one created, so a late-finishing re-run cannot be shadowed by a row created after it. Two of the three states those guards exclude are reachable from the UI, not hypothetical: `summary_message_id` and `source_to_message_id` are both `ON DELETE SET NULL`, and `delete_message` is called from both assistant drivers. So deleting the last compacted message, or the summary itself, silently un-compacts the session — the compaction row survives and the next request carries the full history again. The tests build those states through `delete_message` rather than raw SQL, which also pins two of the table's three FK actions; the third, the session cascade, gets its own test. One assertion is not about the database: `CompactionStatus::Completed`'s serialised form is hand-written into two places no compiler checks — the `'"completed"'` literal in the query, and the CHECK constraint in the migration. A rename fails loudly (the CHECK rejects the next completion, and `map_compaction_row` stops parsing old rows), but it fails at runtime, far from the rename. The assertion moves that to the rename. All fourteen tests were mutation-checked, and the table below is derived from thirteen runs, not asserted: each mutation fails exactly the named test, and nothing else. status filter dropped -> ignores_a_running_one summary guard dropped -> ignores_one_without_a_summary window-end guard dropped -> ignores_one_without_a_window_end + deleting_the_window_end_message_... ordering flipped to ASC -> picks_the_newest_completion ordering by created_at -> picks_the_newest_completion `error = NULL` dropped -> complete_compaction_sets_the_summary... touch_session, create side -> create_compaction_touches_the_session touch_session, complete -> complete_compaction_sets_the_summary... protocol/model binds swap -> round_trips_every_field summary/run-id binds swap -> round_trips_every_field session CASCADE dropped -> deleting_a_session_deletes_its_compactions window-end SET NULL dropped-> deleting_the_window_end_message_... summary SET NULL dropped -> ignores_one_without_a_summary Two gaps this exercise found and does not close, both noted for follow-up: `provider_history_messages_with_compaction` — the pure function that turns a compaction row into an actual truncation — still has no tests, and nothing ever writes `CompactionStatus::Failed`, so a compaction whose summary fails stays `running` forever with no sweep. 1060 -> 1074 tests, fmt and clippy --all-targets clean, bindings.ts untouched. Implements R6.2.
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.
Implements R6.2. Test-only: one file, +490, no production code changed.
What was missing
create_compaction,complete_compaction,get_compactionandlatest_completed_compaction(repository.rs:1171-1295) had zero tests. The blocker was the hand-written fixture, which never createdassistant_compactions;db::test_support::workspace_poolfrom #200 builds the real schema from the migrations, so the table is simply there now.What is actually load-bearing here
latest_completed_compactionselects the row that decides which messages the provider is allowed to see. It is not the last line of defence — I initially wrote that it was, and the review disproved it: the one consumer,provider_history_messages_with_compaction(compaction.rs:320-340), re-checks the same two nullable fields and falls back to the unfiltered history in every failure case. It is the first line, and none of its fourWHERE/ORDER BYterms had a test.Each now does. A compaction that is still running, that has no summary message, or that has no window end must stay invisible; and the row that wins is the last one completed, not the last one created.
Two of these states are reachable from the UI
summary_message_idandsource_to_message_idare bothON DELETE SET NULL, anddelete_messageis called from both assistant drivers (engine.rs:2254,local_agent.rs:2227). So deleting the last compacted message — or the summary itself — silently un-compacts the session: the compaction row survives, the summary message may survive, and the next request carries the full history again.The tests build those two states through
delete_messagerather than raw SQL. That makes the comments true rather than hypothetical, and pins two of the table's three FK actions for free; the third, the session cascade, gets its own test.Mutation table
Re-derived from thirteen runs after review, not asserted. Each mutation fails exactly the named test and nothing else.
status = '"completed"'droppedignores_a_running_onesummary_message_id IS NOT NULLdroppedignores_one_without_a_summarysource_to_message_id IS NOT NULLdroppedignores_one_without_a_window_end+deleting_the_window_end_message_…ASCpicks_the_newest_completioncreated_atpicks_the_newest_completionerror = NULLdroppedcomplete_compaction_sets_the_summary…touch_sessiondropped, create sidecreate_compaction_touches_the_sessiontouch_sessiondropped, complete sidecomplete_compaction_sets_the_summary…round_trips_every_fieldround_trips_every_fieldON DELETE CASCADEdroppeddeleting_a_session_deletes_its_compactionsON DELETE SET NULLdroppeddeleting_the_window_end_message_…ON DELETE SET NULLdroppedignores_one_without_a_summaryReview
Delegated adversarial pre-PR review against
d25e0c8: shapeship_with_changes, correctnessrework. Three must-fixes, all mine, all applied:ignores_a_running_onecould not fail with the status filter deleted — the row also had a NULL summary, so a second guard was doing the work. My own first mutation sweep never mutated that term, so I claimed a kill I had not observed. The row now carries a summary, making status the only excluding term, and the whole table was re-derived rather than patched.CompactionStatus::Completedwould silently make every compaction invisible was wrong: the CHECK constraint rejects the next completion andmap_compaction_rowstops parsing old rows — both loud. The assertion stays (it moves a runtime failure to the rename site) with an honest justification.ON DELETE SET NULLabove.All five should-fixes applied too: a weak
created_at/completed_atdiscrimination in the ordering test (both timestamps are now forced, with no ties, pointing the two orders in opposite directions), the speculative production story behind completion-ordering,created_run_idnever round-tripped non-NULL despite being the dangerous adjacent bind,complete_compaction's secondtouch_sessionuntested, and the inventedfailedstate. Nits folded in.Follow-ups this found and does not close
provider_history_messages_with_compaction— the pure function where a compaction row becomes an actual truncation — still has no tests. It takes a slice and is cheaper to test than anything here. This is the next item.CompactionStatus::Failed. A compaction whosesummarize_windowfails staysrunningforever, across restarts, andrecover_stale_runssweeps onlyassistant_runs/assistant_tool_calls. Nofail_compaction, no stale-compaction recovery.Gates
cargo fmt --checkclean ·cargo clippy --all-targets -- -D warningsclean (under #202's new policy) ·cargo test --lib1060 → 1074, 0 failed, verified by name-list diff — 14 added, none removed ·src/generated/bindings.tsuntouched.