Merge hands/eureka-body-flush-keeps-unseen-revision: a flush spends no unseen revision (cut-flush-keeps-unseen-revision h1; Soul s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
ecf147dbd7
2 changed files with 29 additions and 2 deletions
|
|
@ -1856,8 +1856,8 @@ impl<C: ControlSource, S: ControlSource> SessionInbox for PersonaInbox<'_, C, S>
|
|||
// failed (a batch's third refusal leaves no retell to hold the ack back). Deliveries are
|
||||
// told in seq order, so while one is unanswered below an answered seq, everything
|
||||
// answered lies above it and nothing is acked; the ack follows its answer.
|
||||
// Her final answer lands after she took in every line, so a revision still waiting is answered by it and its note, that a send was not sent, would be false.
|
||||
let spent = if final_reply { self.revision.take().map(|revision| revision.batch) } else { None };
|
||||
// Only an answer to the revision line spends a waiting revision: a flush answer never saw it, so its batch stays unacked for the next process.
|
||||
let spent = if revised { self.revision.take().map(|revision| revision.batch) } else { None };
|
||||
self.answered_through = self.answered_through.max(batch.iter().chain(spent.iter().flatten()).map(|delivery| delivery.seq).max().unwrap_or(0));
|
||||
if self.progress.refused.as_ref().is_some_and(|refused| batch.iter().any(|delivery| delivery.seq == refused.lowest)) {
|
||||
self.progress.refused = None;
|
||||
|
|
|
|||
|
|
@ -6568,6 +6568,33 @@ fn a_process_that_ends_with_a_revision_waiting_leaves_the_batch_unacked() {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_flush_answer_does_not_spend_a_revision_she_was_never_told() {
|
||||
let rig = Rig::new(vec![], &[]);
|
||||
rig.clock.step.set(0);
|
||||
let (ask, answer) = (delivery(1, "swarm", "@op:chat", "question"), delivery(2, "swarm", "@libby:chat", "answer"));
|
||||
arrives(&rig, &ask);
|
||||
with_inbox(&rig, &config(), vec![ask.clone()], |inbox| {
|
||||
inbox.start_line().unwrap();
|
||||
inbox.echoed();
|
||||
arrives(&rig, &answer);
|
||||
inbox.result(&reply_result(&says(&[("swarm", "mine")])), true, false).unwrap();
|
||||
assert!(inbox.revision.is_some());
|
||||
inbox.flush_text(Why::Idle);
|
||||
inbox.echoed();
|
||||
inbox.result(&reply_result(&says(&[("swarm", "last words")])), true, false).unwrap();
|
||||
assert_eq!(rig.chat.sent.borrow().last().unwrap().basis, None, "a flush send is never refused");
|
||||
assert!(inbox.revision.is_some(), "the flush never showed her the revision line");
|
||||
});
|
||||
assert!(rig.chat.acked.borrow().is_empty());
|
||||
let next = next_batch(&config(), &[], rig.chat.pending(0).unwrap().deliveries, 0);
|
||||
assert_eq!(next.len(), 2);
|
||||
with_inbox(&rig, &config(), next, |inbox| {
|
||||
let line = inbox.start_line().unwrap();
|
||||
assert!(line.contains("question") && line.contains("answer") && !line.contains("was not sent"), "{line}");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_undecodable_revision_stays_final() {
|
||||
let rig = Rig::new(vec![], &[]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue