Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion crates/tui/src/compaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,36 @@ pub(crate) fn is_compaction_checkpoint_message(message: &Message) -> bool {
|| user_text_of(message).is_some_and(|text| is_legacy_compaction_summary_text(&text))
}

/// Whether this history already carries a provenance-stamped checkpoint.
///
/// A stamped carrier postdates stamping, so within that history only the
/// stamped form is a checkpoint: a user turn whose text merely starts with a
/// legacy summary header (a pasted transcript, for example) is content. A
/// history without one predates the stamp — there the pasted header is
/// indistinguishable from the saved bare carrier, so the loose form keeps
/// applying. The signal is the history's content, not the session's age: it
/// is one-way and destructible (`/edit` or a host rewind can truncate away
/// the only stamped carrier), and typed input cannot forge the two-block
/// form.
#[must_use]
pub(crate) fn history_is_post_provenance(messages: &[Message]) -> bool {
messages.iter().any(is_wire_compaction_checkpoint_message)
}

/// Era-aware checkpoint recognition for the recompaction family: the loose
/// legacy fallback applies only in a history with no stamped carrier.
#[must_use]
pub(crate) fn is_compaction_checkpoint_message_in_era(
message: &Message,
post_provenance: bool,
) -> bool {
if post_provenance {
is_wire_compaction_checkpoint_message(message)
} else {
is_compaction_checkpoint_message(message)
}
}

/// Request-time recognition: exactly the header text block plus the
/// provenance block. User text merely quoting a marker keeps its original
/// wire position. Checkpoints saved before the handoff note still pass, so
Expand Down Expand Up @@ -1540,7 +1570,23 @@ fn is_orphaned_result_block(block: &ContentBlock) -> bool {
)
}

/// Test convenience: derive the era from the slice itself. Production
/// callers pass [`retained_user_messages_in_era`] the era of the history the
/// slice belongs to — retention runs on the pre-round prefix, whose carrier
/// may sit inside the round.
#[cfg(test)]
pub(crate) fn retained_user_messages(messages: &[Message], max_tokens: usize) -> Vec<Message> {
retained_user_messages_in_era(history_is_post_provenance(messages), messages, max_tokens)
}

/// `post_provenance` must be derived from the history the slice belongs to,
/// not from the slice itself: retention runs on the pre-round prefix, whose
/// carrier may sit inside the round.
pub(crate) fn retained_user_messages_in_era(
post_provenance: bool,
messages: &[Message],
max_tokens: usize,
) -> Vec<Message> {
let mut selected: Vec<Message> = Vec::new();
let mut remaining = max_tokens;
for msg in messages.iter().rev() {
Expand All @@ -1557,7 +1603,7 @@ pub(crate) fn retained_user_messages(messages: &[Message], max_tokens: usize) ->
{
continue;
}
if is_compaction_checkpoint_message(msg) {
if is_compaction_checkpoint_message_in_era(msg, post_provenance) {
continue;
}
let tokens: usize = msg
Expand Down
11 changes: 11 additions & 0 deletions crates/tui/src/compaction/SURVIVAL_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ Rust now:
- `validate_survival_contract` also refuses a missing checkpoint receipt,
duplicated prior summaries, dropped `/anchor` text, or a placeholder-only
checkpoint.
- Checkpoint recognition in the recompaction family is era-scoped. A history
that already carries a provenance-stamped carrier (header block plus the
provenance block) recognizes only stamped carriers as checkpoints, so a
user turn that pastes a bare legacy summary header stays content: it
anchors the round, is retained verbatim, and does not count as a duplicated
summary. A history without a stamped carrier predates stamping — there the
pasted header is indistinguishable from the saved bare carrier, so the
loose legacy matching keeps applying. The receipt count reads the
replacement in its own era, except that a post-provenance original raises
the bar to a stamped carrier: the engine stamps every replacement it
builds, and the stamp is the only form request rewriting relocates.
- `compact_messages_safe` never mutates the caller's live history; the host
commits only after `Ok`.

Expand Down
5 changes: 4 additions & 1 deletion crates/tui/src/compaction/fixtures/matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
{"id":"continuous-round-must-keep-post-checkpoint-results","expect":"fail","original":[{"role":"user","content":[{"type":"text","text":"Continue this task without publishing."}]},{"role":"assistant","content":[{"type":"tool_use","id":"old","name":"File","input":{"path":"old"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"old","content":"evidence old"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem. Old step completed; latest checks remain."}]},{"role":"assistant","content":[{"type":"tool_use","id":"new-a","name":"File","input":{"path":"new-a"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"new-a","content":"evidence new-a"}]},{"role":"assistant","content":[{"type":"tool_use","id":"new-b","name":"File","input":{"path":"new-b"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"new-b","content":"evidence new-b"}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Continue this task without publishing."}]},{"role":"assistant","content":[{"type":"tool_use","id":"old","name":"File","input":{"path":"old"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"old","content":"evidence old"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem. Old step completed; latest checks remain."}]}]},
{"id":"continuous-round-must-keep-tool-pairs","expect":"fail","original":[{"role":"user","content":[{"type":"text","text":"Continue this task without publishing."}]},{"role":"assistant","content":[{"type":"tool_use","id":"old","name":"File","input":{"path":"old"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"old","content":"evidence old"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem. Old step completed; latest checks remain."}]},{"role":"assistant","content":[{"type":"tool_use","id":"new-a","name":"File","input":{"path":"new-a"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"new-a","content":"evidence new-a"}]},{"role":"assistant","content":[{"type":"tool_use","id":"new-b","name":"File","input":{"path":"new-b"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"new-b","content":"evidence new-b"}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Continue this task without publishing."}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"new-a","content":"evidence new-a"}]},{"role":"assistant","content":[{"type":"tool_use","id":"new-b","name":"File","input":{"path":"new-b"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"new-b","content":"evidence new-b"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem. Old step completed; latest checks remain."}]}]},
{"id":"legacy-v2-checkpoint-replaced-by-handoff-note","expect":"pass","last_round_start":0,"original":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"test session_store::roundtrip ... FAILED"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem and produced a summary.\n\nfirst pass"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"test session_store::roundtrip ... FAILED"}]},{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nfix the failing test"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]}]},
{"id":"quoted-handoff-marker-is-user-text","expect":"fail","last_round_start":0,"original":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"test session_store::roundtrip ... FAILED"}]},{"role":"user","content":[{"type":"text","text":"What is in the Codewhale handoff note?"}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"test session_store::roundtrip ... FAILED"}]},{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nfix the failing test"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]}]}
{"id":"quoted-handoff-marker-is-user-text","expect":"fail","last_round_start":0,"original":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"test session_store::roundtrip ... FAILED"}]},{"role":"user","content":[{"type":"text","text":"What is in the Codewhale handoff note?"}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"test session_store::roundtrip ... FAILED"}]},{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nfix the failing test"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]}]},
{"id":"pasted-legacy-header-survives-post-provenance","expect":"pass","last_round_start":0,"original":[{"role":"user","content":[{"type":"text","text":"Run the suite now."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"ok"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem and produced a summary.\n\nsuite finished"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]},{"role":"assistant","content":[{"type":"text","text":"done"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem\n\nEarlier turns of another session, pasted verbatim."}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nrun the suite"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]},{"role":"user","content":[{"type":"text","text":"Run the suite now."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"ok"}]},{"role":"assistant","content":[{"type":"text","text":"done"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem\n\nEarlier turns of another session, pasted verbatim."}]}]},
{"id":"pasted-legacy-header-dropped-post-provenance","expect":"fail","last_round_start":0,"original":[{"role":"user","content":[{"type":"text","text":"Run the suite now."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"ok"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem and produced a summary.\n\nsuite finished"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]},{"role":"assistant","content":[{"type":"text","text":"done"}]},{"role":"user","content":[{"type":"text","text":"Another language model started to solve this problem\n\nEarlier turns of another session, pasted verbatim."}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nrun the suite"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]},{"role":"user","content":[{"type":"text","text":"Run the suite now."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"ok"}]},{"role":"assistant","content":[{"type":"text","text":"done"}]}]},
{"id":"pasted-modern-header-dropped-post-provenance","expect":"fail","last_round_start":0,"original":[{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"ok"}]},{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nfix the failing test"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]},{"role":"assistant","content":[{"type":"text","text":"done"}]},{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nfix the failing test"}]}],"replacement":[{"role":"user","content":[{"type":"text","text":"Codewhale handoff note. Earlier turns of this session were condensed to make room.\n\n## Objective\nfix the failing test"},{"type":"text","text":"<!-- codewhale.compaction-checkpoint.v1 -->"}]},{"role":"user","content":[{"type":"text","text":"Run the failing test."}]},{"role":"assistant","content":[{"type":"tool_use","id":"live","name":"Bash","input":{"command":"cargo test"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"live","content":"ok"}]},{"role":"assistant","content":[{"type":"text","text":"done"}]}]}
]
}
Loading
Loading