Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ The final state must satisfy both conditions:
- The original seven files remain below 5,136 lines and 373 control-flow lines.
- The complete changed production footprint has fewer lines and control-flow lines than the baseline.

## Direct-stage reduction slice

The merged corpus commit is `d2186d83e0ce2fe0d51ac67ea029eefa579abca3`.

This slice removes the delegate pipeline and its stage array. The coordinator now calls the same typed stages in one fixed order.

The slice removes 117 production lines and three control-flow lines. It also removes 257 stage-test lines for states that production cannot construct.

The expanded changed-file footprint now uses 7,240 baseline lines and 479 baseline control-flow lines. This set includes files changed after PR #1947.

The current slice uses 8,665 lines and 530 control-flow lines. The complete reduction gate remains open.

## Preliminary coverage and risk

The audit used `dotnet-coverage` 18.10.0 and `crap4dotnet` 0.1.1.
Expand Down
45 changes: 45 additions & 0 deletions src/Netclaw.Actors.Tests/Tools/DispatchingToolExecutorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1690,6 +1690,51 @@ public async Task Authorization_evaluation_denies_duplicate_actor_candidate_id()
Assert.Equal("internal_policy_failure", decision.DenyReason);
}

[Fact]
public async Task Authorization_evaluation_propagates_preexisting_cancellation_without_actor_contact()
{
var approvalService = GrantEveryShellCandidate();
var executor = CreateApprovalGatedShellExecutor(approvalService);
var call = new FunctionCallContent(
"call-preexisting-cancellation",
ShellTool.ToolName,
ToolInput.Create("Command", "git status"));
using var cancellation = new CancellationTokenSource();
await cancellation.CancelAsync();

await Assert.ThrowsAnyAsync<OperationCanceledException>(() =>
executor.EvaluateAuthorizationAsync(
call,
CreateInteractivePersonalContext("signalr/preexisting-cancellation"),
cancellation.Token));

Assert.Equal(0, approvalService.RequestCount);
}

[Fact]
public async Task Authorization_evaluation_propagates_actor_cancellation_before_an_ordinary_failure()
{
using var cancellation = new CancellationTokenSource();
var approvalService = new FixedShellApprovalService(_ =>
{
cancellation.Cancel();
throw new InvalidOperationException("actor failed after cancellation");
});
var executor = CreateApprovalGatedShellExecutor(approvalService);
var call = new FunctionCallContent(
"call-actor-cancellation",
ShellTool.ToolName,
ToolInput.Create("Command", "git status"));

await Assert.ThrowsAnyAsync<OperationCanceledException>(() =>
executor.EvaluateAuthorizationAsync(
call,
CreateInteractivePersonalContext("signalr/actor-cancellation"),
cancellation.Token));

Assert.Equal(1, approvalService.RequestCount);
}

[Fact]
public async Task Authorization_evaluation_denies_mismatched_actor_match()
{
Expand Down
Loading
Loading