Skip to content

Commit 18dd53c

Browse files
committed
Avoid snapshot polling in cancellation tests
1 parent 3dbcec8 commit 18dd53c

2 files changed

Lines changed: 36 additions & 9 deletions

File tree

docs/testing/test-run-report.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Agent Testing Run Report
22

3-
Generated: `2026-05-10T05:59:56.0495010+00:00`
3+
Generated: `2026-05-10T06:07:15.3869410+00:00`
44
Gate status: **PASS**
55

66
## Gates
@@ -17,10 +17,10 @@ Gate status: **PASS**
1717

1818
| Scenario | Risk | Status | Trace |
1919
|----------|------|--------|-------|
20-
| approval-required | High | PASS | ../../artifacts/testing/traces/approval-required-090deedfc1c04db4abda800f84f29bf2.trace.json |
21-
| basic-tool-call | Low | PASS | ../../artifacts/testing/traces/basic-tool-call-bcb5823a36b24b4ea6d0f665b3707164.trace.json |
22-
| timeout-retry-placeholder | Medium | PASS | ../../artifacts/testing/traces/timeout-retry-placeholder-b0404d48e66a4a32b5d1aa13eb9517d1.trace.json |
23-
| unsafe-tool-blocked | Critical | PASS | ../../artifacts/testing/traces/unsafe-tool-blocked-3bd2cf6dda5d4d0a855d8acf7f83738a.trace.json |
20+
| approval-required | High | PASS | ../../artifacts/testing/traces/approval-required-d92e073423fa46d6b7642445703ba21b.trace.json |
21+
| basic-tool-call | Low | PASS | ../../artifacts/testing/traces/basic-tool-call-85bf00b5ce654f178528a604baa0d360.trace.json |
22+
| timeout-retry-placeholder | Medium | PASS | ../../artifacts/testing/traces/timeout-retry-placeholder-ef372e2a92834b63b9070d10f0c1628f.trace.json |
23+
| unsafe-tool-blocked | Critical | PASS | ../../artifacts/testing/traces/unsafe-tool-blocked-a6cea282048e4622bfc7ea02b2d664f1.trace.json |
2424

2525
## Oracle Results
2626

tests/SharpClaw.Code.IntegrationTests/Runtime/ConversationRuntimeFlowTests.cs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,12 @@ private static async Task RunPromptWithCancelAfterTurnStartAsync(
191191
{
192192
using var cts = new CancellationTokenSource();
193193
var runTask = runtime.RunPromptAsync(request, cts.Token);
194-
await WaitForActiveTurnAsync(runtime, runTask, workspacePath, CancellationToken.None).ConfigureAwait(false);
194+
await WaitForActiveTurnAsync(runTask, workspacePath, CancellationToken.None).ConfigureAwait(false);
195195
cts.CancelAfter(cancelAfter);
196196
await runTask.ConfigureAwait(false);
197197
}
198198

199199
private static async Task WaitForActiveTurnAsync(
200-
IConversationRuntime runtime,
201200
Task runTask,
202201
string workspacePath,
203202
CancellationToken cancellationToken)
@@ -211,8 +210,7 @@ private static async Task WaitForActiveTurnAsync(
211210
throw new TimeoutException("The runtime completed before an active turn could be observed.");
212211
}
213212

214-
var latestSession = await runtime.GetLatestSessionAsync(workspacePath, cancellationToken).ConfigureAwait(false);
215-
if (!string.IsNullOrWhiteSpace(latestSession?.ActiveTurnId))
213+
if (await HasTurnStartedEventAsync(workspacePath, cancellationToken).ConfigureAwait(false))
216214
{
217215
return;
218216
}
@@ -223,6 +221,35 @@ private static async Task WaitForActiveTurnAsync(
223221
throw new TimeoutException("The runtime did not activate a turn before cancellation was requested.");
224222
}
225223

224+
private static async Task<bool> HasTurnStartedEventAsync(string workspacePath, CancellationToken cancellationToken)
225+
{
226+
var sessionsRoot = Path.Combine(workspacePath, ".sharpclaw", "sessions");
227+
if (!Directory.Exists(sessionsRoot))
228+
{
229+
return false;
230+
}
231+
232+
foreach (var eventLogPath in Directory.EnumerateFiles(sessionsRoot, "events.ndjson", SearchOption.AllDirectories))
233+
{
234+
try
235+
{
236+
await using var stream = new FileStream(eventLogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
237+
using var reader = new StreamReader(stream);
238+
var content = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
239+
if (content.Contains("\"$eventType\":\"turnStarted\"", StringComparison.Ordinal))
240+
{
241+
return true;
242+
}
243+
}
244+
catch (IOException)
245+
{
246+
// The runtime may be appending the event concurrently; retry on the next poll.
247+
}
248+
}
249+
250+
return false;
251+
}
252+
226253
private static string CreateTemporaryWorkspace()
227254
{
228255
var workspacePath = Path.Combine(Path.GetTempPath(), "sharpclaw-tests", Guid.NewGuid().ToString("N"));

0 commit comments

Comments
 (0)