Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
test(redis): cover side effect serialization and queries
  • Loading branch information
rian-be committed Jun 30, 2026
commit 0267129d4b4f608b5071b3c068931df8dd83da72
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using ModularityKit.Mutator.Abstractions.Context;
using ModularityKit.Mutator.Abstractions.Effects;
using ModularityKit.Mutator.Abstractions.Intent;
using ModularityKit.Mutator.Abstractions.Policies;
using ModularityKit.Mutator.Governance.Abstractions.Lifecycle.Model;
using ModularityKit.Mutator.Governance.Abstractions.Queries.Contracts;
using ModularityKit.Mutator.Governance.Abstractions.Queries.Model.Approvals;
using ModularityKit.Mutator.Governance.Abstractions.Queries.Model.Decisions;
using ModularityKit.Mutator.Governance.Abstractions.Queries.Model.Requests;
using ModularityKit.Mutator.Governance.Abstractions.Queries.Model.Requests.Filters;
using ModularityKit.Mutator.Governance.Abstractions.Requests.Decisions;
using ModularityKit.Mutator.Governance.Abstractions.Requests.Factory;
using ModularityKit.Mutator.Governance.Abstractions.Requests.Model;
Expand Down Expand Up @@ -50,6 +52,16 @@ public static async Task Run()
ApproverIds = new HashSet<string> { "security-lead" }
}));

PrintSection("Requests With Actionable Side Effects");
PrintRequests(await queryStore.QueryAsync(new MutationRequestQuery
{
SideEffects = new MutationRequestSideEffectFilter
{
DataContractTypes = new HashSet<string> { "examples.redis.execution-side-effect" },
RequiresAction = true
}
}));

PrintSection("Recent Execution Outcomes");
PrintDecisions(await queryStore.GetRecentDecisionsAsync(
MutationRequestDecisionQuery.RecentExecutionOutcomes(),
Expand Down Expand Up @@ -152,6 +164,16 @@ private static MutationRequest CreateExecutedRequest(
CreatedAt = executedAt.AddMinutes(-15),
UpdatedAt = executedAt,
ExecutedAt = executedAt,
SideEffects =
[
SideEffect.Critical(
type: "ExecutedRequestRequiresFollowUp",
description: "Executed request still requires manual follow-up",
data: new RedisExecutionSideEffectData
{
Ticket = "BILL-12"
})
],
Decisions =
[
MutationRequestDecision.Lifecycle(
Expand All @@ -178,6 +200,12 @@ private static MutationRequest CreateExecutedRequest(
]
};

[SideEffectDataContract("examples.redis.execution-side-effect", 1)]
private sealed record RedisExecutionSideEffectData
{
public required string Ticket { get; init; }
}

private static void PrintSection(string title)
{
Console.WriteLine();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ModularityKit.Mutator.Abstractions.Context;
using ModularityKit.Mutator.Abstractions.Effects;
using ModularityKit.Mutator.Abstractions.Intent;
using ModularityKit.Mutator.Abstractions.Policies;
using ModularityKit.Mutator.Governance.Abstractions.Lifecycle.Model;
Expand Down Expand Up @@ -61,7 +62,17 @@ public void Roundtrip_preserves_request_shape_needed_by_governance_runtime()
with
{
CreatedAt = new DateTimeOffset(2026, 6, 25, 9, 0, 0, TimeSpan.Zero),
UpdatedAt = new DateTimeOffset(2026, 6, 25, 9, 5, 0, TimeSpan.Zero)
UpdatedAt = new DateTimeOffset(2026, 6, 25, 9, 5, 0, TimeSpan.Zero),
SideEffects =
[
SideEffect.Critical(
type: "WorkflowRejected",
description: "Workflow rejection requires action",
data: new RedisGovernanceSideEffectData
{
Ticket = "INC-42"
})
]
};

var json = RedisMutationRequestSerializer.Serialize(request);
Expand All @@ -75,9 +86,20 @@ public void Roundtrip_preserves_request_shape_needed_by_governance_runtime()
Assert.Equal(BlastRadiusScope.Module, roundtrip.Intent.EstimatedBlastRadius?.Scope);
Assert.Equal("platform", roundtrip.Intent.Metadata["risk-owner"]);
Assert.Equal("security", roundtrip.Metadata["team"]);
Assert.Single(roundtrip.SideEffects);
Assert.Equal("WorkflowRejected", roundtrip.SideEffects[0].Type);
Assert.Equal("redis.governance.side-effect", roundtrip.SideEffects[0].DataContractType);
Assert.True(roundtrip.SideEffects[0].TryGetData<RedisGovernanceSideEffectData>(out var sideEffectData));
Assert.Equal("INC-42", sideEffectData!.Ticket);
Assert.Single(roundtrip.Requirements);
Assert.Single(roundtrip.ApprovalRequirements);
Assert.Equal("security-lead", roundtrip.ApprovalRequirements[0].ApproverId);
Assert.Equal(3, roundtrip.Decisions.Count);
}

[SideEffectDataContract("redis.governance.side-effect", 1)]
private sealed record RedisGovernanceSideEffectData
{
public required string Ticket { get; init; }
}
}