fix(cli): resolve CLI-008..013 — format validation, exit-code semantics, debug-stream cancellation/disposal, test coverage

This commit is contained in:
Joseph Doherty
2026-05-16 22:04:21 -04:00
parent bc88a36435
commit 404216b4ee
12 changed files with 593 additions and 19 deletions
+18 -3
View File
@@ -94,7 +94,8 @@ public static class DebugCommands
.WithAutomaticReconnect()
.Build();
var cts = new CancellationTokenSource();
// CLI-011: CancellationTokenSource owns a WaitHandle and must be disposed.
using var cts = new CancellationTokenSource();
var exitTcs = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
Console.CancelKeyPress += (_, e) =>
@@ -192,8 +193,18 @@ public static class DebugCommands
}
catch (Exception ex)
{
// CLI-010: Ctrl+C during connect throws OperationCanceledException — that is
// a graceful user cancellation, not a connection failure.
var failure = DebugStreamHelpers.ClassifyConnectFailure(ex, cts.IsCancellationRequested);
if (failure.IsCancellation)
{
await connection.DisposeAsync();
return failure.ExitCode;
}
OutputFormatter.WriteError($"Connection failed: {ex.Message}", "CONNECTION_FAILED");
return 1;
await connection.DisposeAsync();
return failure.ExitCode;
}
try
@@ -232,7 +243,11 @@ public static class DebugCommands
}
await connection.DisposeAsync();
return exitTcs.Task.IsCompletedSuccessfully ? exitTcs.Task.Result : 0;
// CLI-012: resolve the exit code from a single authoritative source. A result
// set by OnStreamTerminated/Closed always wins; a brief grace period covers a
// termination racing with Ctrl+C. Pure Ctrl+C (no result) is a graceful exit 0.
return await DebugStreamHelpers.ResolveStreamExitCodeAsync(exitTcs.Task);
}
private static void PrintSnapshotTable(JsonElement snapshot)