Skip to content

Commit 5be3797

Browse files
committed
Implement embedded runtime epic
1 parent 1838661 commit 5be3797

28 files changed

+1589
-101
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ For this app:
153153
- keep the Uno app project presentation-only; domain, runtime host, orchestration, integrations, and persistence code must live in separate class-library projects so UI composition does not mix with feature implementation
154154
- when the user asks to implement an epic, the delivery branch and PR must cover all of that epic's direct child issues that belong to the requested scope, not just one child issue with a partial close-out
155155
- epic implementation PRs must include automated tests for every direct child issue they claim to cover, plus the broader runtime and UI regressions required by the touched flows
156+
- do not claim an epic is implemented unless every direct child issue in the requested scope is both realized in code and covered by automated tests; partial coverage is not an acceptable close-out
156157
- structure both `DotPilot.Tests` and `DotPilot.UITests` by vertical slice and explicit harness boundaries; do not keep test files in one flat project-root pile
157158
- the first embedded Orleans runtime cut must use `UseLocalhostClustering` together with in-memory Orleans grain storage and in-memory reminders; do not introduce remote clustering or external durable stores until a later backlog item explicitly requires them, and keep durable resume/replay outside Orleans storage until the cluster topology is intentionally upgraded
158159
- GitHub is the backlog, not the product: use issues and PRs only to drive task scope and traceability, and never copy GitHub issue text, labels, workflow language, or tracker metadata into production code, runtime snapshots, or user-facing UI

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<PackageVersion Include="coverlet.collector" Version="8.0.0" />
1313
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
1414
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
15+
<PackageVersion Include="Microsoft.Agents.AI.Workflows" Version="1.0.0-rc4" />
1516
<PackageVersion Include="Microsoft.Orleans.Core.Abstractions" Version="10.0.1" />
1617
<PackageVersion Include="Microsoft.Orleans.Persistence.Memory" Version="10.0.1" />
1718
<PackageVersion Include="Microsoft.Orleans.Reminders" Version="10.0.1" />

DotPilot.Core/Features/RuntimeCommunication/RuntimeCommunicationProblemCode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ public enum RuntimeCommunicationProblemCode
1010
RuntimeHostUnavailable,
1111
OrchestrationUnavailable,
1212
PolicyRejected,
13+
SessionArchiveMissing,
14+
ResumeCheckpointMissing,
15+
SessionArchiveCorrupted,
1316
}

DotPilot.Core/Features/RuntimeCommunication/RuntimeCommunicationProblems.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public static class RuntimeCommunicationProblems
1616
private const string RuntimeHostUnavailableDetail = "The embedded runtime host is unavailable for the requested operation.";
1717
private const string OrchestrationUnavailableDetail = "The orchestration runtime is unavailable for the requested operation.";
1818
private const string PolicyRejectedFormat = "The requested action was rejected by policy: {0}.";
19+
private const string SessionArchiveMissingFormat = "No persisted runtime session archive exists for session {0}.";
20+
private const string ResumeCheckpointMissingFormat = "Session {0} does not have a checkpoint that can be resumed.";
21+
private const string SessionArchiveCorruptedFormat = "Session {0} has corrupted persisted runtime state.";
1922

2023
public static Problem InvalidPrompt()
2124
{
@@ -86,6 +89,33 @@ public static Problem PolicyRejected(string policyName)
8689
HttpStatusCode.Forbidden);
8790
}
8891

92+
public static Problem SessionArchiveMissing(SessionId sessionId)
93+
{
94+
return CreateProblem(
95+
RuntimeCommunicationProblemCode.SessionArchiveMissing,
96+
SessionArchiveMissingFormat,
97+
sessionId.ToString(),
98+
HttpStatusCode.NotFound);
99+
}
100+
101+
public static Problem ResumeCheckpointMissing(SessionId sessionId)
102+
{
103+
return CreateProblem(
104+
RuntimeCommunicationProblemCode.ResumeCheckpointMissing,
105+
ResumeCheckpointMissingFormat,
106+
sessionId.ToString(),
107+
HttpStatusCode.Conflict);
108+
}
109+
110+
public static Problem SessionArchiveCorrupted(SessionId sessionId)
111+
{
112+
return CreateProblem(
113+
RuntimeCommunicationProblemCode.SessionArchiveCorrupted,
114+
SessionArchiveCorruptedFormat,
115+
sessionId.ToString(),
116+
HttpStatusCode.InternalServerError);
117+
}
118+
89119
private static Problem CreateProblem(
90120
RuntimeCommunicationProblemCode code,
91121
string detailFormat,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace DotPilot.Core.Features.RuntimeFoundation;
2+
3+
public sealed record EmbeddedRuntimeTrafficTransitionDescriptor(
4+
string Source,
5+
string Target,
6+
IReadOnlyList<string> SourceMethods,
7+
IReadOnlyList<string> TargetMethods,
8+
bool IsReentrant);
9+
10+
public sealed record EmbeddedRuntimeTrafficPolicySnapshot(
11+
int IssueNumber,
12+
string IssueLabel,
13+
string Summary,
14+
string MermaidDiagram,
15+
IReadOnlyList<EmbeddedRuntimeTrafficTransitionDescriptor> AllowedTransitions);
16+
17+
public sealed record EmbeddedRuntimeTrafficProbe(
18+
Type SourceGrainType,
19+
string SourceMethod,
20+
Type TargetGrainType,
21+
string TargetMethod);
22+
23+
public sealed record EmbeddedRuntimeTrafficDecision(
24+
bool IsAllowed,
25+
string MermaidDiagram);
26+
27+
public interface IEmbeddedRuntimeTrafficPolicyCatalog
28+
{
29+
EmbeddedRuntimeTrafficPolicySnapshot GetSnapshot();
30+
31+
EmbeddedRuntimeTrafficDecision Evaluate(EmbeddedRuntimeTrafficProbe probe);
32+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
using DotPilot.Core.Features.ControlPlaneDomain;
12
using ManagedCode.Communication;
23

34
namespace DotPilot.Core.Features.RuntimeFoundation;
45

56
public interface IAgentRuntimeClient
67
{
78
ValueTask<Result<AgentTurnResult>> ExecuteAsync(AgentTurnRequest request, CancellationToken cancellationToken);
9+
10+
ValueTask<Result<AgentTurnResult>> ResumeAsync(AgentTurnResumeRequest request, CancellationToken cancellationToken);
11+
12+
ValueTask<Result<RuntimeSessionArchive>> GetSessionArchiveAsync(SessionId sessionId, CancellationToken cancellationToken);
813
}

DotPilot.Core/Features/RuntimeFoundation/RuntimeFoundationIssues.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ public static class RuntimeFoundationIssues
99
public const int CommunicationContracts = 23;
1010
public const int EmbeddedOrleansHost = 24;
1111
public const int AgentFrameworkRuntime = 25;
12+
public const int GrainTrafficPolicy = 26;
13+
public const int SessionPersistence = 27;
1214

1315
public static string FormatIssueLabel(int issueNumber) => string.Concat(IssuePrefix, issueNumber);
1416
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using DotPilot.Core.Features.ControlPlaneDomain;
2+
3+
namespace DotPilot.Core.Features.RuntimeFoundation;
4+
5+
public sealed record AgentTurnResumeRequest(
6+
SessionId SessionId,
7+
ApprovalState ApprovalState,
8+
string Summary);
9+
10+
public sealed record RuntimeSessionReplayEntry(
11+
string Kind,
12+
string Summary,
13+
SessionPhase Phase,
14+
ApprovalState ApprovalState,
15+
DateTimeOffset RecordedAt);
16+
17+
public sealed record RuntimeSessionArchive(
18+
SessionId SessionId,
19+
string WorkflowSessionId,
20+
SessionPhase Phase,
21+
ApprovalState ApprovalState,
22+
DateTimeOffset UpdatedAt,
23+
string? CheckpointId,
24+
IReadOnlyList<RuntimeSessionReplayEntry> Replay,
25+
IReadOnlyList<ArtifactDescriptor> Artifacts);

DotPilot.Runtime.Host/Features/RuntimeFoundation/EmbeddedRuntimeHostBuilderExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public static IHostBuilder UseDotPilotEmbeddedRuntime(
2020
services.AddSingleton(resolvedOptions);
2121
services.AddSingleton<EmbeddedRuntimeHostCatalog>();
2222
services.AddSingleton<IEmbeddedRuntimeHostCatalog>(serviceProvider => serviceProvider.GetRequiredService<EmbeddedRuntimeHostCatalog>());
23+
services.AddSingleton<IEmbeddedRuntimeTrafficPolicyCatalog, EmbeddedRuntimeTrafficPolicyCatalog>();
2324
services.AddHostedService<EmbeddedRuntimeHostLifecycleService>();
2425
});
2526

DotPilot.Runtime.Host/Features/RuntimeFoundation/EmbeddedRuntimeHostNames.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ internal static class EmbeddedRuntimeHostNames
77
public const int DefaultSiloPort = 11_111;
88
public const int DefaultGatewayPort = 30_000;
99
public const string GrainStorageProviderName = "runtime-foundation-memory";
10+
public const string ClientSourceName = "Client";
11+
public const string ClientSourceMethodName = "Invoke";
1012
public const string SessionStateName = "session";
1113
public const string WorkspaceStateName = "workspace";
1214
public const string FleetStateName = "fleet";

0 commit comments

Comments
 (0)