From e87abace8b7fc2c28a822e67f4909d1080dadb83 Mon Sep 17 00:00:00 2001 From: kevin9327 Date: Mon, 31 Aug 2026 19:20:30 +0900 Subject: [PATCH] fix(tests): acknowledge conversation Blob writes in the local rules test `local_markdown_rules_land_in_the_request_context_message` never finishes: `cargo test --workspace` fails on `main` with panicked at server\tests\local_rules_context.rs:64:14: run finishes within timeout: Elapsed(()) The Run publishes the conversation checkpoint by asking the client to write Blobs, and it does not continue until every `KvServerMessage` is answered with a `SetBlobResult`. The test drained the output stream without replying, so the Run stalled after the first frame, the provider was never invoked, and none of the assertions the test exists for were ever reached. Answer the Blob writes the way every other transport test already does (`error_lifecycle.rs`, `conversation_delivery.rs`, `interrupt.rs`). With the acknowledgement in place the Run reaches `EndStream` in ~0.3s and the original assertions run and pass, so `merge_local_rules` is now genuinely covered: exactly one `request-context:` message is projected and it carries `Always answer in haiku.`. No production code changes. Before: `cargo test -p cursor-server --test local_rules_context` -> FAILED (0 passed; 1 failed) after a 5s timeout After: `cargo test -p cursor-server --test local_rules_context` -> ok (1 passed; 0 failed) in 0.28s --- server/tests/local_rules_context.rs | 36 +++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/server/tests/local_rules_context.rs b/server/tests/local_rules_context.rs index 67d2bdc..fdc6e3c 100644 --- a/server/tests/local_rules_context.rs +++ b/server/tests/local_rules_context.rs @@ -16,6 +16,7 @@ use cursor_server::{ model::{ContentPart, ProjectedContent}, provider::{FinishReason, ModelEvent}, }; +use prost::Message; #[tokio::test] async fn local_markdown_rules_land_in_the_request_context_message() { @@ -58,18 +59,30 @@ async fn local_markdown_rules_land_in_the_request_context_message() { .await .unwrap(); + let mut append_seqno = 1; loop { let frame = tokio::time::timeout(std::time::Duration::from_secs(5), output.recv()) .await .expect("run finishes within timeout") .expect("output stays open until EndStream"); - let ended = connect::decode_frames(&frame) - .unwrap() - .iter() - .any(|(flags, _)| flags & connect::END_STREAM_FLAG != 0); - if ended { + let (flags, payload) = connect::decode_frames(&frame).unwrap().pop().unwrap(); + if flags & connect::END_STREAM_FLAG != 0 { break; } + // The Run waits for the client to confirm every conversation Blob write, + // so the stream only advances once each KvServerMessage is acknowledged. + if let Some(pb::agent_server_message::Message::KvServerMessage(kv)) = + pb::AgentServerMessage::decode(payload).unwrap().message + { + handle + .command(TransportCommand::Append { + seqno: append_seqno, + message: Box::new(set_blob_result(kv.id)), + }) + .await + .unwrap(); + append_seqno += 1; + } } let requests = provider.requests(); @@ -102,6 +115,19 @@ async fn local_markdown_rules_land_in_the_request_context_message() { registry.shutdown().await; } +fn set_blob_result(id: u32) -> pb::AgentClientMessage { + pb::AgentClientMessage { + message: Some(pb::agent_client_message::Message::KvClientMessage( + pb::KvClientMessage { + id, + message: Some(pb::kv_client_message::Message::SetBlobResult( + pb::SetBlobResult { error: None }, + )), + }, + )), + } +} + fn user_run() -> pb::AgentClientMessage { pb::AgentClientMessage { message: Some(pb::agent_client_message::Message::RunRequest(