Conversation
`provider_history_messages_with_compaction` is the point where a compaction row stops being bookkeeping and becomes a real truncation of what the provider sees. It had no tests. Its neighbours in the module are well covered -- the size gates, the window selection, the summary clamping -- so the untested function was the one that decides what actually reaches the model. Eight tests, one per property of the translation: - the summary leads the view and the history up to the boundary is gone; - the boundary is inclusive, so the boundary message goes too; - the summary, which is always appended *after* its own boundary, is emitted once from the front rather than left in the tail; - with no compaction the history passes through, still minus any summary. A summary message can outlive every completed row: it is written before `complete_compaction` runs, and a `running` row is never returned by `latest_completed_compaction` and is never reaped; - an orphan summary in the retained tail is dropped. Same non-atomic pair, one compaction later: the orphan is durable, the previous compaction is still the latest completed one, and its older boundary leaves the orphan inside the retained tail where only the metadata filter catches it. Replaying it would hand the provider two abridgements of the same history, the stale one looking current; - all four unusable rows (either id NULL, either id dangling) fall back to the untruncated history rather than half-applying. None of the four is reachable today, and that is the point: both callers get their row from `latest_completed_compaction`, whose `WHERE` adds `IS NOT NULL` on both ids, and `ON DELETE SET NULL` plus the pool's `foreign_keys` means a deleted message nulls the column rather than leaving it dangling -- which that same filter then excludes. The guards here are one half of an invariant whose other half is a `WHERE` clause in another file, so this pins the half that lives here; - the view carries the stored summary text and keeps its metadata marker, which the next compaction keys off; - the cut happens exactly where the row says, even mid tool group: not re-checking the group boundary is `select_compaction_window`'s job, and this pins that division. Every test was mutation-checked: nine mutations of the function, eight killed, each surviving test killing at least one. The survivor is the `message.id != summary_message_id` half of the tail filter, which no fixture can reach because the one site that writes a summary message always sets the metadata marker the other half keys off. That is recorded as redundant defence at the test that would otherwise appear to cover it, rather than papered over -- an earlier draft of the orphan test was killed by the skip instead of by the filter it named, which the sweep caught. Also folds the module's two hand-rolled summary-message builders onto one `summary_msg` fixture. 1060 -> 1068 tests. No production code changes.
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 roadmap item R6.3. Sibling of #204 (which covered the compaction repository functions); this covers the function that turns one of those rows into an actual truncation of what the provider sees.
provider_history_messages_with_compactionhad zero tests, while everything around it incompaction.rsis well covered — the size gates, the window selection, the summary clamping. It is the function that decides what actually reaches the model.Eight tests, one per property: the summary leads the view; the boundary is inclusive; the summary is emitted once from the front rather than left in the tail it always falls inside; the no-compaction path still strips summaries; an orphan summary in the retained tail is dropped; all four unusable rows fall back to the untruncated history; the view carries the stored summary text and marker; the cut happens exactly where the row says, even mid tool group.
Two findings worth the reviewer's attention, both recorded in the test docs rather than acted on:
latest_completed_compaction, whoseWHEREaddsIS NOT NULLon both ids; andON DELETE SET NULLplus the pool'sforeign_keysmeans a deleted message nulls the column rather than leaving it dangling, which that same filter then excludes. The guards are one half of an invariant whose other half is aWHEREclause in another file, so the test pins the half that lives here.compact_session_historywrites the summary message beforecomplete_compaction, non-atomically. If the second call fails, the summary is durable while its row staysrunningforever — nothing writesCompactionStatus::Failedand nothing reaps a stalerunningrow. That is what makes the orphan-summary case reachable, and it is the metadata filter in the tail that saves it. Flagged for a follow-up; no production change here.Verification. Nine mutations of the function, eight killed, every test killing at least one. The survivor is the
message.id != summary_message_idhalf of the tail filter, unreachable because the one site that writes a summary always sets the marker the other half keys off — documented as redundant defence at the test that would otherwise appear to cover it. An earlier draft of the orphan test was killed by the skip rather than by the filter it named; the sweep caught that and the fixture was re-derived.A source-only adversarial review found five false claims in the first draft's doc comments (including the reachability story above, which was wrong in three separate ways) and one redundant test, since removed. All applied.
1060 → 1068 tests.
cargo fmtclean,cargo clippy --all-targetsclean,cargo test --lib1068/0,bindings.tsuntouched. No production code changes.