diff --git a/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneDomainContractsTests.cs b/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneDomainContractsTests.cs index d285379..9e81cb0 100644 --- a/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneDomainContractsTests.cs +++ b/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneDomainContractsTests.cs @@ -101,7 +101,7 @@ private static ControlPlaneDomainEnvelope CreateEnvelope() Id = WorkspaceId.New(), Name = "dotPilot", RootPath = SyntheticWorkspaceRootPath, - BranchName = "codex/issue-22-domain-model", + BranchName = "main", }; var codingAgent = new AgentProfileDescriptor diff --git a/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneIdentifierContractTests.cs b/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneIdentifierContractTests.cs new file mode 100644 index 0000000..a9f4ed0 --- /dev/null +++ b/DotPilot.Tests/Features/ControlPlaneDomain/ControlPlaneIdentifierContractTests.cs @@ -0,0 +1,76 @@ +namespace DotPilot.Tests.Features.ControlPlaneDomain; + +public sealed class ControlPlaneIdentifierContractTests +{ + [Test] + public void NewlyCreatedIdentifiersUseVersionSevenTokens() + { + IReadOnlyList identifiers = + [ + WorkspaceId.New().ToString(), + AgentProfileId.New().ToString(), + SessionId.New().ToString(), + FleetId.New().ToString(), + ProviderId.New().ToString(), + ModelRuntimeId.New().ToString(), + ToolCapabilityId.New().ToString(), + ApprovalId.New().ToString(), + ArtifactId.New().ToString(), + TelemetryRecordId.New().ToString(), + EvaluationId.New().ToString(), + ]; + + identifiers.Should().OnlyContain(identifier => identifier.Length == 32); + identifiers.Should().OnlyContain(identifier => identifier[12] == '7'); + } + + [Test] + public void DefaultDescriptorsExposeSerializationSafeDefaults() + { + var workspace = new WorkspaceDescriptor(); + var agent = new AgentProfileDescriptor(); + var fleet = new FleetDescriptor(); + var tool = new ToolCapabilityDescriptor(); + var provider = new ProviderDescriptor(); + var runtime = new ModelRuntimeDescriptor(); + var session = new SessionDescriptor(); + var approval = new SessionApprovalRecord(); + var artifact = new ArtifactDescriptor(); + var telemetry = new TelemetryRecord(); + var evaluation = new EvaluationRecord(); + + workspace.Name.Should().BeEmpty(); + workspace.RootPath.Should().BeEmpty(); + workspace.BranchName.Should().BeEmpty(); + agent.Name.Should().BeEmpty(); + agent.ToolCapabilityIds.Should().BeEmpty(); + agent.Tags.Should().BeEmpty(); + fleet.Name.Should().BeEmpty(); + fleet.AgentProfileIds.Should().BeEmpty(); + tool.Name.Should().BeEmpty(); + tool.DisplayName.Should().BeEmpty(); + tool.Tags.Should().BeEmpty(); + provider.DisplayName.Should().BeEmpty(); + provider.CommandName.Should().BeEmpty(); + provider.StatusSummary.Should().BeEmpty(); + provider.Status.Should().Be(ProviderConnectionStatus.Unavailable); + provider.SupportedToolIds.Should().BeEmpty(); + runtime.DisplayName.Should().BeEmpty(); + runtime.EngineName.Should().BeEmpty(); + runtime.Status.Should().Be(ProviderConnectionStatus.Unavailable); + runtime.SupportedModelFamilies.Should().BeEmpty(); + session.Title.Should().BeEmpty(); + session.Phase.Should().Be(SessionPhase.Plan); + session.ApprovalState.Should().Be(ApprovalState.NotRequired); + session.AgentProfileIds.Should().BeEmpty(); + approval.State.Should().Be(ApprovalState.Pending); + approval.RequestedAction.Should().BeEmpty(); + approval.RequestedBy.Should().BeEmpty(); + artifact.Name.Should().BeEmpty(); + artifact.RelativePath.Should().BeEmpty(); + telemetry.Name.Should().BeEmpty(); + telemetry.Summary.Should().BeEmpty(); + evaluation.Outcome.Should().Be(EvaluationOutcome.NeedsReview); + evaluation.Summary.Should().BeEmpty(); + } +} diff --git a/DotPilot.Tests/Features/RuntimeCommunication/DeterministicAgentRuntimeClientContractTests.cs b/DotPilot.Tests/Features/RuntimeCommunication/DeterministicAgentRuntimeClientContractTests.cs new file mode 100644 index 0000000..3bfcfb3 --- /dev/null +++ b/DotPilot.Tests/Features/RuntimeCommunication/DeterministicAgentRuntimeClientContractTests.cs @@ -0,0 +1,82 @@ +namespace DotPilot.Tests.Features.RuntimeCommunication; + +public sealed class DeterministicAgentRuntimeClientContractTests +{ + private const string ApprovalPrompt = "Execute the local-first flow and request approval before changing files."; + + [Test] + public async Task ExecuteAsyncReturnsSucceededResultWithoutProblemForPlanMode() + { + var client = new DeterministicAgentRuntimeClient(); + + var result = await client.ExecuteAsync(CreateRequest("Plan the contract foundation rollout.", AgentExecutionMode.Plan), CancellationToken.None); + + result.IsSuccess.Should().BeTrue(); + result.IsFailed.Should().BeFalse(); + result.HasProblem.Should().BeFalse(); + result.Value.Should().NotBeNull(); + result.Value!.NextPhase.Should().Be(SessionPhase.Plan); + } + + [Test] + public async Task ExecuteAsyncTreatsApprovalPauseAsASuccessfulStateTransition() + { + var client = new DeterministicAgentRuntimeClient(); + + var result = await client.ExecuteAsync(CreateRequest(ApprovalPrompt, AgentExecutionMode.Execute), CancellationToken.None); + + result.IsSuccess.Should().BeTrue(); + result.HasProblem.Should().BeFalse(); + result.Value.Should().NotBeNull(); + result.Value!.NextPhase.Should().Be(SessionPhase.Paused); + result.Value.ApprovalState.Should().Be(ApprovalState.Pending); + } + + [TestCase(ProviderConnectionStatus.Unavailable, RuntimeCommunicationProblemCode.ProviderUnavailable, 503)] + [TestCase(ProviderConnectionStatus.RequiresAuthentication, RuntimeCommunicationProblemCode.ProviderAuthenticationRequired, 401)] + [TestCase(ProviderConnectionStatus.Misconfigured, RuntimeCommunicationProblemCode.ProviderMisconfigured, 424)] + [TestCase(ProviderConnectionStatus.Outdated, RuntimeCommunicationProblemCode.ProviderOutdated, 412)] + public async Task ExecuteAsyncMapsProviderStatesToTypedProblems( + ProviderConnectionStatus providerStatus, + RuntimeCommunicationProblemCode expectedCode, + int expectedStatusCode) + { + var client = new DeterministicAgentRuntimeClient(); + + var result = await client.ExecuteAsync( + CreateRequest("Run the provider-independent runtime flow.", AgentExecutionMode.Execute, providerStatus), + CancellationToken.None); + + result.IsFailed.Should().BeTrue(); + result.HasProblem.Should().BeTrue(); + result.Value.Should().BeNull(); + result.Problem.Should().NotBeNull(); + result.Problem!.HasErrorCode(expectedCode).Should().BeTrue(); + result.Problem.StatusCode.Should().Be(expectedStatusCode); + } + + [Test] + public async Task ExecuteAsyncReturnsOrchestrationProblemForUnsupportedExecutionModes() + { + var client = new DeterministicAgentRuntimeClient(); + + var result = await client.ExecuteAsync( + CreateRequest("Use an invalid execution mode.", (AgentExecutionMode)999), + CancellationToken.None); + + result.IsFailed.Should().BeTrue(); + result.HasProblem.Should().BeTrue(); + result.Value.Should().BeNull(); + result.Problem.Should().NotBeNull(); + result.Problem!.HasErrorCode(RuntimeCommunicationProblemCode.OrchestrationUnavailable).Should().BeTrue(); + result.Problem.StatusCode.Should().Be(503); + } + + private static AgentTurnRequest CreateRequest( + string prompt, + AgentExecutionMode mode, + ProviderConnectionStatus providerStatus = ProviderConnectionStatus.Available) + { + return new AgentTurnRequest(SessionId.New(), AgentProfileId.New(), prompt, mode, providerStatus); + } +} diff --git a/docs/ADR/ADR-0003-vertical-slices-and-ui-only-uno-app.md b/docs/ADR/ADR-0003-vertical-slices-and-ui-only-uno-app.md index 8a24476..2205bc3 100644 --- a/docs/ADR/ADR-0003-vertical-slices-and-ui-only-uno-app.md +++ b/docs/ADR/ADR-0003-vertical-slices-and-ui-only-uno-app.md @@ -33,7 +33,7 @@ We will use these architectural defaults for implementation work going forward: - `DotPilot.Runtime` for provider-independent runtime implementations and future host integration seams - `DotPilot.Runtime.Host` for the embedded Orleans silo and desktop-only runtime-host lifecycle 3. Feature code must be organized as vertical slices under `Features//...`, not as shared horizontal `Services`, `Models`, or `Helpers` buckets. -4. Epic `#12` starts with a `RuntimeFoundation` slice that sequences issues `#22`, `#23`, `#24`, and `#25` behind a stable contract surface. Issue `#24` is implemented through a desktop-only `DotPilot.Runtime.Host` project that uses localhost clustering plus in-memory storage/reminders before any remote or durable topology is introduced. +4. Epic `#11` establishes the shared `ControlPlaneDomain` and `RuntimeCommunication` slices, and epic `#12` builds on that foundation through the `RuntimeFoundation` slice. Issue `#24` is implemented through a desktop-only `DotPilot.Runtime.Host` project that uses localhost clustering plus in-memory storage/reminders before any remote or durable topology is introduced. 5. CI-safe agent-flow verification must use a deterministic in-repo runtime client as a first-class implementation of the same public contracts, not a mock or hand-wired test double. 6. Tests that require real `Codex`, `Claude Code`, or `GitHub Copilot` toolchains may run only when the corresponding toolchain is available; their absence must not weaken the provider-independent baseline. @@ -86,7 +86,7 @@ CI does not guarantee those toolchains, so the repo would lose an honest agent-f - The Uno app gets cleaner and stays focused on operator-facing concerns. - Future slices can land without merging unrelated feature logic into shared buckets. -- Contracts for `#12` become reusable across UI, runtime, and tests. +- Contracts from epic `#11` become reusable across UI, runtime, and tests before epic `#12` begins live runtime integration. - CI keeps a real provider-independent verification path through the deterministic runtime client. - The embedded Orleans host can evolve without leaking server-only dependencies into browserwasm or the presentation project. diff --git a/docs/Architecture.md b/docs/Architecture.md index 6da7703..019239c 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -1,6 +1,6 @@ # Architecture Overview -Goal: give humans and agents a fast map of the active `DotPilot` solution, the current `Uno Platform` shell, the workbench foundation for epic `#13`, the Toolchain Center for epic `#14`, and the local-first runtime foundation for epic `#12`. +Goal: give humans and agents a fast map of the active `DotPilot` solution, the current `Uno Platform` shell, the foundation contracts from epic `#11`, the workbench foundation for epic `#13`, the Toolchain Center for epic `#14`, and the local-first runtime foundation for epic `#12`. This file is the required start-here architecture map for non-trivial tasks. @@ -10,15 +10,16 @@ This file is the required start-here architecture map for non-trivial tasks. - **Presentation boundary:** [../DotPilot/](../DotPilot/) is now the presentation host only. It owns XAML, routing, desktop startup, and UI composition, while non-UI feature logic moves into separate DLLs. - **Workbench boundary:** epic [#13](https://github.com/managedcode/dotPilot/issues/13) is landing as a `Workbench` slice that will provide repository navigation, file inspection, artifact and log inspection, and a unified settings shell without moving that behavior into page code-behind. - **Toolchain Center boundary:** epic [#14](https://github.com/managedcode/dotPilot/issues/14) now lives as a `ToolchainCenter` slice. [../DotPilot.Core/Features/ToolchainCenter](../DotPilot.Core/Features/ToolchainCenter) defines the readiness, diagnostics, configuration, action, and polling contracts; [../DotPilot.Runtime/Features/ToolchainCenter](../DotPilot.Runtime/Features/ToolchainCenter) probes local provider CLIs for `Codex`, `Claude Code`, and `GitHub Copilot`; the Uno app surfaces the slice through the settings shell. +- **Foundation contract boundary:** epic [#11](https://github.com/managedcode/dotPilot/issues/11) is represented through [../DotPilot.Core/Features/ControlPlaneDomain](../DotPilot.Core/Features/ControlPlaneDomain) and [../DotPilot.Core/Features/RuntimeCommunication](../DotPilot.Core/Features/RuntimeCommunication). These slices define the shared agent/session/tool model and the `ManagedCode.Communication` result/problem language that later runtime work reuses. - **Runtime foundation boundary:** [../DotPilot.Core/](../DotPilot.Core/) owns issue-aligned contracts, typed identifiers, grain interfaces, traffic-policy snapshots, and session-archive contracts; [../DotPilot.Runtime/](../DotPilot.Runtime/) owns provider-independent runtime implementations such as the deterministic turn engine, `Microsoft Agent Framework` orchestration client, and local archive persistence; [../DotPilot.Runtime.Host/](../DotPilot.Runtime.Host/) owns the embedded Orleans host, explicit grain traffic policy, and initial grain implementations for desktop targets. - **Domain slice boundary:** issue [#22](https://github.com/managedcode/dotPilot/issues/22) now lives in `DotPilot.Core/Features/ControlPlaneDomain`, which defines the shared agent, session, fleet, provider, runtime, approval, artifact, telemetry, and evaluation model that later slices reuse. - **Communication slice boundary:** issue [#23](https://github.com/managedcode/dotPilot/issues/23) lives in `DotPilot.Core/Features/RuntimeCommunication`, which defines the shared `ManagedCode.Communication` result/problem language for runtime public boundaries. -- **First implementation slice:** epic [#12](https://github.com/managedcode/dotPilot/issues/12) is represented locally through the `RuntimeFoundation` slice, which now sequences issues `#22`, `#23`, `#24`, `#25`, `#26`, and `#27` behind a stable contract surface instead of mixing runtime work into the Uno app. +- **Runtime-host slice boundary:** epic [#12](https://github.com/managedcode/dotPilot/issues/12) now builds on the epic `#11` foundation contracts through the `RuntimeFoundation` slice, which sequences issues `#22`, `#23`, `#24`, `#25`, `#26`, and `#27` behind a stable contract surface instead of mixing runtime work into the Uno app. - **Automated verification:** [../DotPilot.Tests/](../DotPilot.Tests/) covers API-style and contract flows through the new DLL boundaries; [../DotPilot.UITests/](../DotPilot.UITests/) covers the visible workbench flow, Toolchain Center, and runtime-foundation UI surface. Provider-independent flows must pass in CI through deterministic or environment-agnostic checks, while provider-specific checks can run only when the matching toolchain is available. ## Scoping -- **In scope for the current repository state:** the Uno workbench shell, the `DotPilot.Core`, `DotPilot.Runtime`, and `DotPilot.Runtime.Host` libraries, the embedded Orleans host for local desktop runtime state, and the automated validation boundaries around them. +- **In scope for the current repository state:** the Uno workbench shell, the `DotPilot.Core`, `DotPilot.Runtime`, and `DotPilot.Runtime.Host` libraries, the epic `#11` foundation-contract slices, the embedded Orleans host for local desktop runtime state, and the automated validation boundaries around them. - **In scope for future implementation:** provider adapters, durable persistence beyond the current local session archive, telemetry, evaluation, Git tooling, and local runtimes. - **Out of scope in the current slice:** remote workers, remote clustering, external durable storage providers, and cloud-only control-plane services. @@ -126,11 +127,37 @@ flowchart TD RuntimeSlice --> UiSlice ``` +### Foundation contract slices for epic #11 + +```mermaid +flowchart TD + Epic["#11 Desktop control-plane foundation"] + Domain["#22 Domain contracts"] + Comm["#23 Communication contracts"] + DomainSlice["DotPilot.Core/Features/ControlPlaneDomain"] + CommunicationSlice["DotPilot.Core/Features/RuntimeCommunication"] + RuntimeContracts["DotPilot.Core/Features/RuntimeFoundation"] + DeterministicClient["DotPilot.Runtime/Features/RuntimeFoundation/DeterministicAgentRuntimeClient"] + Tests["DotPilot.Tests contract coverage"] + + Epic --> Domain + Epic --> Comm + Domain --> DomainSlice + Comm --> CommunicationSlice + DomainSlice --> RuntimeContracts + CommunicationSlice --> RuntimeContracts + CommunicationSlice --> DeterministicClient + DomainSlice --> DeterministicClient + DeterministicClient --> Tests + RuntimeContracts --> Tests +``` + ### Runtime foundation slice for epic #12 ```mermaid flowchart TD Epic["#12 Embedded agent runtime host"] + Foundation["#11 Foundation contracts"] Domain["#22 Domain contracts"] Comm["#23 Communication contracts"] Host["#24 Embedded Orleans host"] @@ -144,16 +171,16 @@ flowchart TD HostSlice["DotPilot.Runtime.Host/Features/RuntimeFoundation"] UiSlice["DotPilot runtime panel + banner"] - Epic --> Domain - Epic --> Comm + Foundation --> Domain + Foundation --> Comm + Domain --> DomainSlice + Comm --> CommunicationSlice + DomainSlice --> CommunicationSlice + CommunicationSlice --> CoreSlice Epic --> Host Epic --> MAF Epic --> Policy Epic --> Sessions - Domain --> DomainSlice - DomainSlice --> CommunicationSlice - CommunicationSlice --> CoreSlice - Comm --> CommunicationSlice Host --> HostSlice Policy --> HostSlice Policy --> CoreSlice @@ -208,7 +235,6 @@ flowchart LR ### Planning and decision docs - `Solution governance` — [../AGENTS.md](../AGENTS.md) -- `Task plan` — [../epic-12-embedded-runtime.plan.md](../epic-12-embedded-runtime.plan.md) - `Primary architecture decision` — [ADR-0001](./ADR/ADR-0001-agent-control-plane-architecture.md) - `Vertical-slice solution decision` — [ADR-0003](./ADR/ADR-0003-vertical-slices-and-ui-only-uno-app.md) - `Feature spec` — [Agent Control Plane Experience](./Features/agent-control-plane-experience.md) @@ -274,6 +300,7 @@ flowchart LR - The Uno app must remain a presentation-only host instead of becoming a dump for runtime logic. - Feature work should land as vertical slices with isolated contracts and implementations, not as shared horizontal folders. +- Epic `#11` establishes the reusable contract and communication foundation before epic `#12` begins embedded runtime-host work. - Epic `#12` now has a first local-first Orleans host cut in `DotPilot.Runtime.Host`, and it intentionally uses localhost clustering plus in-memory storage/reminders before any remote or durable runtime topology is introduced. - The desktop runtime path now uses `Microsoft Agent Framework` for orchestration, while the browser path keeps the deterministic in-repo client for CI-safe coverage. - `#26` currently uses an explicit traffic-policy catalog plus Mermaid graph output instead of `ManagedCode.Orleans.Graph`, because the public `ManagedCode.Orleans.Graph` package is pinned to Orleans `9.x` and is not compatible with this repository's Orleans `10.0.1` baseline. diff --git a/docs/Features/control-plane-domain-model.md b/docs/Features/control-plane-domain-model.md index 9e2bb31..e93d385 100644 --- a/docs/Features/control-plane-domain-model.md +++ b/docs/Features/control-plane-domain-model.md @@ -58,12 +58,13 @@ flowchart LR ## Verification +- `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --filter FullyQualifiedName~ControlPlaneDomain` - `dotnet test DotPilot.Tests/DotPilot.Tests.csproj` - `dotnet test DotPilot.slnx` ## Dependencies -- Parent epic: [#12](https://github.com/managedcode/dotPilot/issues/12) +- Parent epic: [#11](https://github.com/managedcode/dotPilot/issues/11) - Runtime communication follow-up: [#23](https://github.com/managedcode/dotPilot/issues/23) - Embedded host follow-up: [#24](https://github.com/managedcode/dotPilot/issues/24) - Agent Framework follow-up: [#25](https://github.com/managedcode/dotPilot/issues/25) diff --git a/docs/Features/runtime-communication-contracts.md b/docs/Features/runtime-communication-contracts.md index a2a920b..e8c2c7e 100644 --- a/docs/Features/runtime-communication-contracts.md +++ b/docs/Features/runtime-communication-contracts.md @@ -48,6 +48,7 @@ flowchart LR ## Verification +- `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --filter FullyQualifiedName~RuntimeCommunication` - `dotnet test DotPilot.Tests/DotPilot.Tests.csproj` - `dotnet test DotPilot.slnx` diff --git a/epic-11-foundation-contracts.plan.md b/epic-11-foundation-contracts.plan.md new file mode 100644 index 0000000..ff07b82 --- /dev/null +++ b/epic-11-foundation-contracts.plan.md @@ -0,0 +1,95 @@ +## Goal + +Implement epic `#11` on a dedicated branch by fully covering its direct child issues `#22` and `#23` with code, docs, and automated tests, then open one PR that closes the epic and both child issues automatically. + +## Scope + +In scope: +- issue `#22`: finalize the control-plane domain model for agents, sessions, fleets, tools, artifacts, telemetry, and evaluations +- issue `#23`: finalize `ManagedCode.Communication` usage for public runtime result and problem contracts +- fix any remaining gaps on `main` that keep the epic from being honestly closeable, including stale docs, issue references, and missing automated verification coverage +- keep the work inside `DotPilot.Core`, `DotPilot.Runtime`, `DotPilot.Tests`, and docs that describe these slices + +Out of scope: +- runtime host or orchestration implementation changes beyond what is strictly needed to prove the issue `#23` contract surface +- UI redesign or workbench behavior +- provider-specific adapter work from later epics + +## Constraints And Risks + +- The app remains presentation-only; this epic is contract and foundation work, not UI-first behavior. +- Do not claim the epic is complete unless both direct child issues are covered by real implementation and automated tests. +- Tests must stay realistic and exercise caller-visible flows through public contracts. +- Existing open issue state on GitHub may reflect missing PR closing refs rather than missing code; the branch must still produce real repository improvements before opening a new PR. +- Avoid user-specific local paths and workflow-specific branch names in durable test data and user-facing docs; task-local plan notes may still reference the active branch and PR. + +## Testing Methodology + +- Validate issue `#22` through serialization-safe contract round-trips, identifier behavior, and cross-record relationship assertions. +- Validate issue `#23` through deterministic runtime client success and failure flows that surface `ManagedCode.Communication` results and problems at the public runtime boundary. +- Keep verification layered: + - focused issue `#22/#23` tests + - full `DotPilot.Tests` + - full solution tests including `DotPilot.UITests` + - coverage for `DotPilot.Tests` +- Require changed production files to stay at or above the repo coverage bar. + +## Ordered Plan + +- [x] Confirm epic `#11` scope and direct child issues from GitHub. +- [x] Create a dedicated branch from clean `main`. +- [x] Audit `main` for remaining gaps in issue `#22/#23` implementation, docs, and tests. +- [x] Correct stale architecture and feature docs so epic `#11`, issue `#22`, and issue `#23` are referenced accurately. +- [x] Add or tighten automated tests for issue `#22` and issue `#23` in slice-aligned locations, including deterministic runtime result/problem coverage. +- [x] Run focused verification for the changed slice tests. +- [x] Run the full repo validation sequence: + - `dotnet build DotPilot.slnx -warnaserror -m:1 -p:BuildInParallel=false` + - `dotnet test DotPilot.slnx` + - `dotnet format DotPilot.slnx --verify-no-changes` + - `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --settings DotPilot.Tests/coverlet.runsettings --collect:"XPlat Code Coverage"` +- [x] Commit the epic `#11` work and open one PR with correct GitHub closing refs. + +## Full-Test Baseline + +- [x] `dotnet build DotPilot.slnx -warnaserror -m:1 -p:BuildInParallel=false` + - Passed with `0` warnings and `0` errors. +- [x] `dotnet test DotPilot.slnx` + - Passed with `61` unit tests and `22` UI tests. + +## Tracked Failing Tests + +- [x] No baseline failures in the repository state under serial execution. +- [x] Baseline note: a parallel local `build` + `test` attempt caused a self-inflicted file-lock on `DotPilot.Core/obj`; this was not a repository failure and was resolved by rerunning the required commands serially per root `AGENTS.md`. + +## Done Criteria + +- Epic `#11` has a real implementation close-out branch, not only issue closure metadata. +- Issue `#22` contracts are documented, serialization-safe, and covered by automated tests. +- Issue `#23` result/problem contracts are documented, exercised through public runtime flows, and covered by automated tests. +- Architecture and feature docs no longer misattribute issue `#22/#23` to epic `#12`. +- The final PR closes `#11`, `#22`, and `#23` automatically after merge. + +## Audit Notes + +- `main` already contained the bulk of the issue `#22/#23` implementation, but the close-out was incomplete: + - `docs/Features/control-plane-domain-model.md` incorrectly listed epic `#12` as the parent instead of epic `#11` + - `docs/Architecture.md` and `ADR-0003` treated issues `#22` and `#23` as if they belonged to epic `#12` + - domain-contract tests still embedded a user-specific local filesystem path and stale branch name + - issue `#23` lacked focused automated coverage that exercised `ManagedCode.Communication` through the public deterministic runtime client boundary + +## Final Validation Results + +- `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --filter "FullyQualifiedName~ControlPlaneDomain|FullyQualifiedName~RuntimeCommunication"` + - Passed with `23` tests. +- `dotnet build DotPilot.slnx -warnaserror -m:1 -p:BuildInParallel=false` + - Passed with `0` warnings and `0` errors. +- `dotnet test DotPilot.slnx` + - Passed with `61` unit tests and `22` UI tests. +- `dotnet format DotPilot.slnx --verify-no-changes` + - Passed with no formatting drift. +- `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --settings DotPilot.Tests/coverlet.runsettings --collect:"XPlat Code Coverage"` + - Passed with overall coverage `91.66%` line and `61.66%` branch. + - Changed production files met the repo bar: + - `RuntimeFoundationCatalog`: `100.00%` line / `100.00%` branch +- Pull request + - Opened [PR #82](https://github.com/managedcode/dotPilot/pull/82) from `codex/epic-11-foundation-contracts` to `main` with `Closes #11`, `Closes #22`, and `Closes #23`.