diff --git a/docs/PROJECT-STRUCTURE.md b/docs/PROJECT-STRUCTURE.md index a7149b3..b897687 100644 --- a/docs/PROJECT-STRUCTURE.md +++ b/docs/PROJECT-STRUCTURE.md @@ -182,6 +182,9 @@ decoded pixels. shared by VM presentation, graphics hosts, Godot, and tests. `engine/Age.Engine/Model/InputContracts.cs` owns neutral ADV auto-wait state and fullwidth text-edit request/result records shared by input hosts, timing policy, VM dispatch, Godot, and tests. +`engine/Age.Engine/Model/AdvPresentationContracts.cs` owns neutral ADV wait-indicator configuration shared by VM +dispatch, retained presentation, hosts, Godot, and tests. `engine/Age.Engine/Model/DiagnosticContracts.cs` owns +the neutral synchronous diagnostic message transported between VM dispatch, diagnostic hosts, Godot, and tests. `engine/Age.Engine/Model/GfxState.cs` retains cross-domain retained-graphics coordination. `engine/Age.Engine/Model/GfxState.Contracts.cs` owns its public render, transition, diagnostic, persistence, diff --git a/docs/remake-architecture-and-roadmap.md b/docs/remake-architecture-and-roadmap.md index 04c65ff..d9e9aca 100644 --- a/docs/remake-architecture-and-roadmap.md +++ b/docs/remake-architecture-and-roadmap.md @@ -815,6 +815,13 @@ do not mix mechanical moves with semantic changes. twenty-three ADV members, required implementations, overload/default chains, existing hosts, and transport record locations remain behaviorally unchanged. Runtime validation remains green. + The eleventh bounded contract slice moved the unchanged `AdvWaitIndicatorConfig` and `DiagnosticMessage` + declarations from `Hosting` into domain-specific `Model` contract files. The retained wait-indicator presenter + no longer imports `Hosting`; two host-local consumers gained `Model` imports, and one test dropped its obsolete + fully qualified hosting name. Record shape, frame selection, diagnostic presentation, and runtime behavior + remain unchanged. This completes the planned runtime-contract split and neutral transport cleanup. Runtime + validation remains green. + 4. **Make the build graph express source ownership.** Stop linking production `.cs` files from `godot/` and `tools/movie-corpus-gate/` into `Age.Engine.Tests`. Extract the platform-neutral frontend/movie/diagnostic code into a small production project referenced by Godot, tests, and the corpus gate. Retain both existing @@ -1173,10 +1180,9 @@ layer's rendering diverges from ADV; save layout. --- ## 8. Immediate next step -Continue step 3 of the **codebase consolidation** maintenance slice: clarify runtime contracts without changing -behavior or the aggregate host accepted by the VM. With diagnostic, lifecycle, audio, and movie contracts -established beneath `IHost`, shared graphics/input transport neutral, and graphics/input/ADV contracts now -separated, move the unchanged `AdvWaitIndicatorConfig` and `DiagnosticMessage` declarations from `Hosting` to -`Model` next. Preserve all consumers while removing the remaining transport declarations from interface files. +Begin step 4 of the **codebase consolidation** maintenance slice: make the build graph express source ownership +without changing behavior. Introduce the production project boundary for platform-neutral frontend helpers now +linked directly from `godot/` into `Age.Engine.Tests`, starting with the diagnostic/options helper cluster. Replace +source links with project references while retaining both existing solution files and Godot export behavior. Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does not replace Phase B gameplay validation or the open cross-platform gates. diff --git a/engine/Age.Engine.Tests/AdvTextOpsTests.cs b/engine/Age.Engine.Tests/AdvTextOpsTests.cs index 82af3e5..bb3b323 100644 --- a/engine/Age.Engine.Tests/AdvTextOpsTests.cs +++ b/engine/Age.Engine.Tests/AdvTextOpsTests.cs @@ -384,7 +384,7 @@ public class AdvTextOpsTests new VirtualMachine(script, table, host).Run(); - Assert.Equal(new Age.Engine.Hosting.AdvWaitIndicatorConfig(1, 385, 140, 12, 0, 0, 30, 27, 12, 48), + Assert.Equal(new AdvWaitIndicatorConfig(1, 385, 140, 12, 0, 0, 30, 27, 12, 48), Assert.Single(host.WaitIndicators)); } diff --git a/engine/Age.Engine/Hosting/CaptureHost.cs b/engine/Age.Engine/Hosting/CaptureHost.cs index 1c953d1..817b54c 100644 --- a/engine/Age.Engine/Hosting/CaptureHost.cs +++ b/engine/Age.Engine/Hosting/CaptureHost.cs @@ -1,3 +1,5 @@ +using Age.Engine.Model; + namespace Age.Engine.Hosting; public sealed class CaptureHost : IHost { diff --git a/engine/Age.Engine/Hosting/IAdvHost.cs b/engine/Age.Engine/Hosting/IAdvHost.cs index 1835a3d..1d9d5c6 100644 --- a/engine/Age.Engine/Hosting/IAdvHost.cs +++ b/engine/Age.Engine/Hosting/IAdvHost.cs @@ -2,21 +2,6 @@ using Age.Engine.Model; namespace Age.Engine.Hosting; -public readonly record struct AdvWaitIndicatorConfig( - int LayoutSlot, int X, int Y, int SurfaceSlot, - int SourceX, int SourceY, int CellWidth, int CellHeight, - int TerminalFrame, long FramePeriodMs) -{ - /// Select the current atlas frame. TerminalFrame is the exclusive native upper bound, - /// so SYSTEM4's value 12 addresses the twelve cells 0 through 11. - public int FrameAt(long elapsedMs) - { - int frameCount = System.Math.Max(1, TerminalFrame); - long period = System.Math.Max(1, FramePeriodMs); - return (int)(System.Math.Max(0, elapsedMs) / period % frameCount); - } -} - public interface IAdvHost { void ShowText(int offset, string text); diff --git a/engine/Age.Engine/Hosting/IDiagnosticHost.cs b/engine/Age.Engine/Hosting/IDiagnosticHost.cs index 0a6d63a..85f327a 100644 --- a/engine/Age.Engine/Hosting/IDiagnosticHost.cs +++ b/engine/Age.Engine/Hosting/IDiagnosticHost.cs @@ -1,3 +1,5 @@ +using Age.Engine.Model; + namespace Age.Engine.Hosting; public interface IDiagnosticHost diff --git a/engine/Age.Engine/Hosting/IHost.cs b/engine/Age.Engine/Hosting/IHost.cs index 5dc52f7..5619085 100644 --- a/engine/Age.Engine/Hosting/IHost.cs +++ b/engine/Age.Engine/Hosting/IHost.cs @@ -1,8 +1,5 @@ namespace Age.Engine.Hosting; -/// A synchronous AGE-owned diagnostic prompt after native body/context formatting. -public readonly record struct DiagnosticMessage(string Caption, string Text); - public interface IHost : IDiagnosticHost, ILifecycleHost, IAudioHost, IMovieHost, IGraphicsHost, IInputHost, IAdvHost { diff --git a/engine/Age.Engine/Model/AdvPresentationContracts.cs b/engine/Age.Engine/Model/AdvPresentationContracts.cs new file mode 100644 index 0000000..eb2c4d3 --- /dev/null +++ b/engine/Age.Engine/Model/AdvPresentationContracts.cs @@ -0,0 +1,16 @@ +namespace Age.Engine.Model; + +public readonly record struct AdvWaitIndicatorConfig( + int LayoutSlot, int X, int Y, int SurfaceSlot, + int SourceX, int SourceY, int CellWidth, int CellHeight, + int TerminalFrame, long FramePeriodMs) +{ + /// Select the current atlas frame. TerminalFrame is the exclusive native upper bound, + /// so SYSTEM4's value 12 addresses the twelve cells 0 through 11. + public int FrameAt(long elapsedMs) + { + int frameCount = System.Math.Max(1, TerminalFrame); + long period = System.Math.Max(1, FramePeriodMs); + return (int)(System.Math.Max(0, elapsedMs) / period % frameCount); + } +} diff --git a/engine/Age.Engine/Model/DiagnosticContracts.cs b/engine/Age.Engine/Model/DiagnosticContracts.cs new file mode 100644 index 0000000..56ca2ba --- /dev/null +++ b/engine/Age.Engine/Model/DiagnosticContracts.cs @@ -0,0 +1,4 @@ +namespace Age.Engine.Model; + +/// A synchronous AGE-owned diagnostic prompt after native body/context formatting. +public readonly record struct DiagnosticMessage(string Caption, string Text); diff --git a/engine/Age.Engine/Text/RetainedAdvWaitIndicatorPresentation.cs b/engine/Age.Engine/Text/RetainedAdvWaitIndicatorPresentation.cs index a928df3..ff315d2 100644 --- a/engine/Age.Engine/Text/RetainedAdvWaitIndicatorPresentation.cs +++ b/engine/Age.Engine/Text/RetainedAdvWaitIndicatorPresentation.cs @@ -1,4 +1,3 @@ -using Age.Engine.Hosting; using Age.Engine.Model; namespace Age.Engine.Text;