fix: log paused cancel lifecycle explicitly

This commit is contained in:
2026-06-23 22:48:21 +09:00
parent 90b1a1fccb
commit 8c8fb01426
4 changed files with 67 additions and 7 deletions
+3 -5
View File
@@ -1868,8 +1868,8 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
/// This uses the same explicit interrupt preparation as the next fresh
/// `run` would have used, then clears the worker's interrupted marker so
/// future input is treated as a normal new turn instead of a resume.
/// The `RunCompleted` marker is a state-reset record for session replay;
/// no provider stream is resumed or mutated here.
/// The explicit `PausedTurnAbandoned` marker preserves durable lifecycle
/// semantics without claiming another `run` / `resume` completed.
pub fn cancel_paused_turn(&mut self) -> Result<(), PodError> {
if !self.worker().last_run_interrupted() {
return Ok(());
@@ -1877,10 +1877,8 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
self.apply_interrupt_prep()?;
self.worker_mut().set_last_run_interrupted(false);
self.commit_entry(LogEntry::RunCompleted {
self.commit_entry(LogEntry::PausedTurnAbandoned {
ts: segment_log::now_millis(),
result: WorkerResult::Finished,
interrupted: false,
})?;
Ok(())
}
+2 -2
View File
@@ -94,8 +94,8 @@ impl SegmentLogSink {
/// - `LogEntry::SystemItem` → `Event::SystemItem`.
/// - `LogEntry::Invoke` → `Event::InvokeStart`.
/// Everything else (AssistantItem, ToolResult, TurnEnd,
/// RunCompleted, RunErrored, LlmUsage, Extension, ConfigChanged) is
/// reflected in the mirror so reconnect snapshots stay accurate,
/// RunCompleted, RunErrored, PausedTurnAbandoned, LlmUsage, Extension,
/// ConfigChanged) is reflected in the mirror so reconnect snapshots stay accurate,
/// but is not sent live — the streaming events (TextDelta /
/// ToolCallStart / ToolResult / TurnEnd / etc.) already provide
/// that data, and re-broadcasting it as a typed entry would just
+18
View File
@@ -1998,6 +1998,24 @@ async fn paused_cancel_abandons_resume_and_next_input_is_fresh_run() {
handle.send(Method::Cancel).await.unwrap();
wait_for_status(&handle, PodStatus::Idle).await;
let (entries_after_cancel, _rx_after_cancel) = handle.sink.subscribe_with_snapshot();
assert!(
entries_after_cancel
.iter()
.any(|entry| matches!(entry, LogEntry::PausedTurnAbandoned { .. })),
"paused cancel should have an explicit lifecycle log entry: {entries_after_cancel:?}"
);
assert!(
!entries_after_cancel.iter().any(|entry| matches!(
entry,
LogEntry::RunCompleted {
result: llm_worker::WorkerResult::Finished,
interrupted: false,
..
}
)),
"paused cancel must not be logged as a normal finished run: {entries_after_cancel:?}"
);
assert_eq!(
client_for_assert.captured_requests().len(),
1,