Add Mimir Aquarium app scaffold
This commit is contained in:
parent
5960c700db
commit
075e8c3ddf
17 changed files with 305 additions and 4 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -11,6 +11,10 @@ tools/obs-spout2-plugin/
|
|||
tools/src/
|
||||
target/
|
||||
native/**/target/
|
||||
bin/
|
||||
obj/
|
||||
**/bin/
|
||||
**/obj/
|
||||
/.voidbot/birth/
|
||||
/.voidbot/logs/
|
||||
/.voidbot/**/*.lock
|
||||
|
|
|
|||
6
Mimir.slnx
Normal file
6
Mimir.slnx
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<Solution>
|
||||
<Folder Name="/src/">
|
||||
<Project Path="src/Mimir.App/Mimir.App.csproj" />
|
||||
<Project Path="src/Mimir.Runtime/Mimir.Runtime.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
7
NuGet.config
Normal file
7
NuGet.config
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="AquariumLocal" value="E:\Projects\Aquarium-Engine\packages" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -7,6 +7,26 @@
|
|||
"expiredSamplePolicy": "offline-calibration-only",
|
||||
"storageLayout": "single-native-rolling-buffer-with-typed-views"
|
||||
},
|
||||
"viableStreamApp": {
|
||||
"owner": "Aquarium",
|
||||
"solution": "Mimir.slnx",
|
||||
"appProject": "src/Mimir.App/Mimir.App.csproj",
|
||||
"runtimeProject": "src/Mimir.Runtime/Mimir.Runtime.csproj",
|
||||
"windowingRenderingLibrary": "Aquarium.Engine",
|
||||
"d3d12Bridge": "Aquarium.Engine",
|
||||
"defaultReservoirSeconds": 5.0,
|
||||
"runtimeState": "in-memory-localcast-runtime",
|
||||
"uiAuthority": "debug-settings-output-management",
|
||||
"ingest": {
|
||||
"videoFeeds": "local-or-networked-producers",
|
||||
"audioFeeds": "local-or-networked-producers",
|
||||
"networkFeedsAre": "producers-not-clock-authorities"
|
||||
},
|
||||
"outputs": {
|
||||
"video": "synchronized-program-video",
|
||||
"audio": "separately-controllable-synchronized-stems"
|
||||
}
|
||||
},
|
||||
"authorities": {
|
||||
"configurationCalibrationLaunchStatus": "Mimir",
|
||||
"denseVisualFusion": "Aquarium",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ The native reservoir is now one time-ordered rolling buffer with typed views.
|
|||
The previous shared-edge typed rings proved the retention invariant; the new
|
||||
shape removes independent per-kind storage from the live foundation.
|
||||
|
||||
The near-term viable stream app is Aquarium-hosted: it ingests local or
|
||||
networked video/audio feeds as producers into the same five-second in-memory
|
||||
`LocalcastRuntime`, exposes debug/settings/output control through Aquarium UI,
|
||||
and emits synchronized OBS program video plus separately controllable audio
|
||||
stems. Mimir now owns its own C# solution while referencing Aquarium Engine as
|
||||
the windowing/rendering library and D3D12 bridge. `docs/viable-stream-app.md`
|
||||
is the current cut line for that app.
|
||||
|
||||
The v1 OBS bridge is now gated by a bounded smoke-test witness ledger. No
|
||||
plugin/native receiver expansion is justified until
|
||||
`calibration/runs/obs-v1-smoke-ledger.json` records sender capture, SRT receive,
|
||||
|
|
@ -35,6 +43,13 @@ latency, and confidence.
|
|||
behavior, and inherited memories. VoidBot is only the mouth/scheduler.
|
||||
- Perfect Machine contract:
|
||||
- `docs/perfect-machine.md` defines the target native machine: one five-second spatiotemporal reservoir, Aquarium-owned dense visual fusion/material/brush rendering, Faust-owned hot audio DSP, OBS-owned broadcast controls, and Mimir-owned calibration/config/status.
|
||||
- `docs/viable-stream-app.md` defines the first useful application cut:
|
||||
Aquarium hosts the in-memory five-second runtime, owns runtime UI and
|
||||
output management, treats local/networked feeds as producers, and emits
|
||||
synchronized OBS program surfaces.
|
||||
- `Mimir.slnx` contains `src/Mimir.App` and `src/Mimir.Runtime`.
|
||||
`Mimir.App` launches `AquariumHost` from Aquarium Engine, and
|
||||
`Mimir.Runtime` supplies the Aquarium client runtime factory.
|
||||
- `config/perfect-machine.example.json` declares the contract shape for six cameras, six microphones, reservoir typed views, native authorities, outputs, and the demotion of bridge scripts to tooling.
|
||||
- `native/reservoir` is the first native Rust crate. It implements one
|
||||
shared-edge five-second rolling buffer with typed views and proves that
|
||||
|
|
|
|||
94
docs/viable-stream-app.md
Normal file
94
docs/viable-stream-app.md
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# Viable Stream App
|
||||
|
||||
## Objective
|
||||
|
||||
Build the smallest live Mimir application that can ingest multiple local or
|
||||
networked video and audio feeds, hold a short synchronized window in memory,
|
||||
and emit coherent OBS-facing program outputs while Aquarium provides the
|
||||
operator UI.
|
||||
|
||||
The default reservoir horizon is five seconds. That delay is not decoration. It
|
||||
is the budget that lets late network packets, independent capture clocks,
|
||||
audio/video alignment, and debug controls converge before OBS sees the result.
|
||||
|
||||
## Current Mechanism
|
||||
|
||||
Today the repo has two partial machines:
|
||||
|
||||
- FFmpeg/SRT bridge scripts can capture sender video/audio and expose stable OBS
|
||||
Media Source endpoints.
|
||||
- The native `LocalcastRuntime` reservoir ABI can hold typed live sample handles,
|
||||
and Aquarium can consume native render packets for GPU fusion.
|
||||
|
||||
Those parts are useful, but they are not yet the viable app. The viable app is
|
||||
the join: ingest workers append live sample handles into one Aquarium-hosted
|
||||
runtime window, Aquarium renders video from that window, Faust/native audio
|
||||
builds synchronized stems from the same window, and OBS receives only the
|
||||
program outputs.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["local camera workers"] --> R["Aquarium-hosted 5s LocalcastRuntime"]
|
||||
B["network video ingest workers"] --> R
|
||||
C["local mic/loopback workers"] --> R
|
||||
D["network audio ingest workers"] --> R
|
||||
R --> U["Aquarium debug/settings/output UI"]
|
||||
R --> V["Aquarium GPU video composition"]
|
||||
R --> F["Faust/native audio alignment + stems"]
|
||||
V --> O["OBS video output"]
|
||||
F --> P["OBS audio stem outputs"]
|
||||
```
|
||||
|
||||
## Invariants
|
||||
|
||||
- One in-memory reservoir owns the live timing edge and expiry.
|
||||
- Aquarium owns the running app, UI, debug state, settings changes, output
|
||||
management, GPU fusion/rendering, and Spout/video publication.
|
||||
- Faust/native DSP owns audio alignment, voice separation, suppression, stems,
|
||||
and spatial bed generation.
|
||||
- OBS receives synchronized program surfaces. Raw unsynchronized feeds may be
|
||||
diagnostic inputs, not broadcast truth.
|
||||
- Networked feeds are producers into the same reservoir. They do not own clocks,
|
||||
private buffers, or a parallel synchronization model.
|
||||
- Missing feeds become explicit absence or silent/blank placeholders inside the
|
||||
program model. Stale samples do not get stretched into looking current.
|
||||
- Python may inspect, calibrate, and test. It does not run the live hot path.
|
||||
|
||||
## First Viable Cut
|
||||
|
||||
The first cut should be deliberately boring:
|
||||
|
||||
1. Build Mimir as its own C# solution in this repo.
|
||||
2. Reference Aquarium Engine as the windowing/rendering library and D3D12
|
||||
bridge; do not copy engine host code into Mimir.
|
||||
3. Start an Aquarium `LocalCastRuntime` app with a five-second native runtime.
|
||||
4. Create one producer per configured feed using native source-id hashing.
|
||||
5. Ingest video feeds as timed camera-frame or render-packet handles.
|
||||
6. Ingest audio feeds as timed `LocalcastAudioBlockDescriptor` handles.
|
||||
7. Expose Aquarium UI readouts for reservoir edge, window start, per-kind
|
||||
counts, feed health, delay estimate, output status, and current settings.
|
||||
8. Render one synchronized program video output from the reservoir.
|
||||
9. Emit separately controllable OBS audio stems from the same reservoir window.
|
||||
10. Keep the existing FFmpeg/SRT scripts as edge utilities for network capture
|
||||
and OBS compatibility, not as the stream authority.
|
||||
|
||||
## Repo Shape
|
||||
|
||||
`Mimir.slnx` owns the Mimir app surface:
|
||||
|
||||
- `src/Mimir.App` launches Aquarium Engine and points it at the Mimir runtime
|
||||
assembly.
|
||||
- `src/Mimir.Runtime` implements the Aquarium client runtime factory and uses
|
||||
Aquarium's LocalCast runtime until Mimir-specific ingest workers replace the
|
||||
remaining diagnostic source.
|
||||
|
||||
## Cut Line
|
||||
|
||||
Do not add a new registry, bridge daemon, JSON live store, OBS plugin, or
|
||||
per-feed buffer manager to make this happen. If the app needs one of those,
|
||||
first move the missing authority into `LocalcastRuntime`, Aquarium, or
|
||||
Faust/native DSP.
|
||||
|
||||
The app exists to make the live system coherent, not to preserve every
|
||||
deadline-era surface. Deadline fossils may be used as diagnostic witnesses. They
|
||||
do not get promoted because they still twitch.
|
||||
|
|
@ -55,6 +55,17 @@ not pretend to own GPU image memory or Faust audio buffers. Edge JSON may
|
|||
declare schema or export diagnostics; live process/network data is typed
|
||||
CultNet documents.
|
||||
|
||||
## Viable Stream App
|
||||
|
||||
`docs/viable-stream-app.md` defines the near-term app target while full native
|
||||
capture work continues. Aquarium hosts the running Mimir app, keeps the default
|
||||
five-second reservoir in memory, exposes debug/settings/output controls, and
|
||||
emits synchronized OBS program video plus separately controllable audio stems.
|
||||
Local and networked video/audio feeds are producers into that one runtime
|
||||
window; they do not own clocks or private synchronization buffers. Mimir owns
|
||||
`Mimir.slnx`; `src/Mimir.App` references Aquarium Engine as the host/windowing
|
||||
and D3D12 bridge, while `src/Mimir.Runtime` provides the Aquarium client runtime.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["config/localcast.json"] --> B["sender-start.ps1"]
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@ Get-Content .\state\evidence.jsonl -Tail 8
|
|||
- The live synchronized program path is being rebuilt. The Python/OpenGL
|
||||
deadline Spout bridge has been deleted.
|
||||
- `docs/native-rebuild-plan.md` is the current cut plan.
|
||||
- `docs/viable-stream-app.md` is the near-term stream target: Aquarium hosts
|
||||
the in-memory five-second runtime and operator UI, local/networked feeds append
|
||||
as producers, and OBS receives synchronized program outputs rather than raw
|
||||
feed sync.
|
||||
- `Mimir.slnx` is the repo-owned C# app surface. `src/Mimir.App` references
|
||||
Aquarium Engine as the windowing/rendering/D3D12 host and loads
|
||||
`src/Mimir.Runtime` as the Aquarium client runtime assembly.
|
||||
- The reservoir is now one native time-ordered rolling buffer with typed
|
||||
indexes/views. The previous typed-ring crate is gone.
|
||||
- Native reservoir samples carry provenance flags; diagnostic/fallback samples
|
||||
|
|
|
|||
17
src/Mimir.App/Mimir.App.csproj
Normal file
17
src/Mimir.App/Mimir.App.csproj
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<AssemblyName>Mimir.App</AssemblyName>
|
||||
<RootNamespace>Mimir.App</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Mimir.Runtime\Mimir.Runtime.csproj" />
|
||||
<ProjectReference Include="..\..\..\Aquarium-Engine\src\Aquarium.Engine\Aquarium.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
26
src/Mimir.App/Program.cs
Normal file
26
src/Mimir.App/Program.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using Aquarium.Engine;
|
||||
|
||||
var hostArgs = args.ToList();
|
||||
if (!HasOption(hostArgs, "--client-assembly") && !HasOption(hostArgs, "--live-assembly"))
|
||||
{
|
||||
hostArgs.Add("--client-assembly");
|
||||
hostArgs.Add(ResolveRuntimeAssemblyPath());
|
||||
}
|
||||
|
||||
return AquariumHost.Run(hostArgs.ToArray());
|
||||
|
||||
static bool HasOption(IReadOnlyList<string> args, string option)
|
||||
{
|
||||
return args.Any(arg => string.Equals(arg, option, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
static string ResolveRuntimeAssemblyPath()
|
||||
{
|
||||
var configured = Environment.GetEnvironmentVariable("MIMIR_RUNTIME_ASSEMBLY");
|
||||
if (!string.IsNullOrWhiteSpace(configured))
|
||||
{
|
||||
return configured;
|
||||
}
|
||||
|
||||
return Path.Combine(AppContext.BaseDirectory, "Mimir.Runtime.dll");
|
||||
}
|
||||
17
src/Mimir.Runtime/Mimir.Runtime.csproj
Normal file
17
src/Mimir.Runtime/Mimir.Runtime.csproj
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<AssemblyName>Mimir.Runtime</AssemblyName>
|
||||
<RootNamespace>Mimir.Runtime</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Aquarium-Engine\src\Aquarium.Engine.Contracts\Aquarium.Engine.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\..\Aquarium-Engine\src\Aquarium.LocalCast\Aquarium.LocalCast.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
12
src/Mimir.Runtime/MimirRuntimeFactory.cs
Normal file
12
src/Mimir.Runtime/MimirRuntimeFactory.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using Aquarium.Engine;
|
||||
using Aquarium.LocalCast;
|
||||
|
||||
namespace Mimir.Runtime;
|
||||
|
||||
public sealed class MimirRuntimeFactory : IAquariumRuntimeFactory
|
||||
{
|
||||
public IAquariumRuntime Create(AquariumRuntimeOptions options)
|
||||
{
|
||||
return new LocalCastRuntime(options);
|
||||
}
|
||||
}
|
||||
|
|
@ -95,3 +95,5 @@
|
|||
{"ts": "2026-05-19T13:16:35+00:00", "type": "decision", "status": "ok", "note": "Mimir Face voice corrected from dry technical steward to mythological being first: Norse well-memory, lost eye, severed voice, roots/ravens/runes, trusted witnesses, and contempt for false coherence now belong to docs/mimir-face.md plus .voidbot Face state. Job jurisdiction remains realtime field stewardship, but personal values now explain why the work matters."}
|
||||
{"ts": "2026-05-21T09:18:48+00:00", "type": "decision", "status": "ok", "note": "V1 OBS receiver expansion is now gated on calibration/runs/obs-v1-smoke-ledger.json: scripts/obs_smoke_test.py and localcast.obs_smoke require sender_capture, srt_receive, and obs_present evidence per endpoint, with drift, end-to-end latency, and confidence before plugin/native receiver work proceeds."}
|
||||
{"ts": "2026-05-21T09:26:02+00:00", "type": "implementation", "status": "ok", "note": "Repository content now presents the public project as Mimir: prose/docs/config examples/OBS source names/default Spout sender/Faust metadata/tool descriptions migrated from LocalCastBridge branding, while lowercase localcast package/schema/ABI contracts remain until a deliberate code rename cut."}
|
||||
{"ts": "2026-05-21T12:09:51+00:00", "type": "decision", "status": "ok", "note": "Viable stream app cut pinned: Aquarium hosts one five-second in-memory LocalcastRuntime, local/networked feeds append as producers, Aquarium owns runtime UI/debug/settings/output management, Faust/native audio builds synchronized stems, and OBS receives program outputs rather than raw feed sync."}
|
||||
{"ts": "2026-05-21T12:14:26+00:00", "type": "implementation", "status": "ok", "note": "Mimir now owns a C# app solution: Mimir.slnx contains src/Mimir.App, which launches AquariumHost from Aquarium Engine, and src/Mimir.Runtime, which provides the Aquarium runtime factory over Aquarium.LocalCast. Aquarium Engine remains the windowing/rendering/D3D12 library reference."}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@ objective:
|
|||
current: >
|
||||
Carve out Python live producers, the OpenGL Spout sink, JSON live stores,
|
||||
and duplicated reservoir windows. Rebuild the live path around one native
|
||||
rolling buffer with typed indexes/views and CultNet typed documents.
|
||||
rolling buffer with typed indexes/views and CultNet typed documents. The
|
||||
immediate viable stream app is Aquarium-hosted: local and networked
|
||||
video/audio feeds append into one five-second in-memory runtime, Aquarium
|
||||
provides debug/settings/output UI, and OBS receives synchronized program
|
||||
outputs. Mimir owns its own C# solution and references Aquarium Engine as
|
||||
the windowing/rendering library and D3D12 bridge.
|
||||
|
||||
constraints:
|
||||
- Sender is Windows.
|
||||
|
|
@ -31,6 +36,8 @@ constraints:
|
|||
- No OpenGL production Spout sink.
|
||||
- Edge JSON is schema/diagnostic only; live network/process data is typed
|
||||
CultNet documents.
|
||||
- Networked feeds are producers into the live runtime, not independent clock
|
||||
or synchronization authorities.
|
||||
|
||||
invariants:
|
||||
- OBS composition authority stays in OBS.
|
||||
|
|
@ -44,6 +51,8 @@ invariants:
|
|||
retention.
|
||||
- Aquarium owns production Spout publication; Faust/native DSP owns hot audio.
|
||||
- Python and JSON may diagnose or test the machine, not run it.
|
||||
- Aquarium owns the viable stream app UI for runtime debugging, settings, and
|
||||
output management.
|
||||
|
||||
accepted_design:
|
||||
- `docs/mimir-face.md`, `.voidbot/voice/identity.json`, and
|
||||
|
|
@ -55,6 +64,13 @@ accepted_design:
|
|||
deadline Python/OpenGL bridge as a foundation and defines the next coherent
|
||||
rebuild target.
|
||||
- `docs/perfect-machine.md` and `config/perfect-machine.example.json` define the native target: one five-second spatiotemporal reservoir, Aquarium GPU fusion/rendering, Faust DSP, OBS output controls, and Mimir tooling.
|
||||
- `docs/viable-stream-app.md` defines the near-term application cut: Aquarium
|
||||
hosts the five-second in-memory `LocalcastRuntime`, local/networked feeds
|
||||
append as producers, Aquarium exposes debug/settings/output controls, and
|
||||
OBS receives synchronized program video plus controllable audio stems.
|
||||
- `Mimir.slnx` owns the app surface. `src/Mimir.App` launches Aquarium Engine
|
||||
as the host/window/D3D12 library, and `src/Mimir.Runtime` provides Mimir's
|
||||
Aquarium client runtime factory.
|
||||
- `native/reservoir` is the first native Rust crate. It now uses one
|
||||
time-ordered rolling buffer with typed views, so retention has exactly one
|
||||
owner while Aquarium/Faust still get kind-scoped queries.
|
||||
|
|
@ -93,6 +109,9 @@ accepted_design:
|
|||
- Persistence follows the active repo pattern: map, scratch, evidence, branches, handoff, system map, implementation plan, state helpers.
|
||||
|
||||
active_subgoals:
|
||||
- Build the viable Aquarium-hosted stream app around one five-second
|
||||
`LocalcastRuntime`: ingest local/networked video and audio producers,
|
||||
expose runtime UI, and emit synchronized OBS program outputs.
|
||||
- Bind Aquarium/Faust to the rolling-buffer `LocalcastRuntime` and
|
||||
`LocalcastProducer` C ABI described by
|
||||
`native/reservoir/include/localcast_reservoir.h`.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ No active scratch subgoal.
|
|||
|
||||
## Notes
|
||||
|
||||
- Viable stream app contract promoted to docs/map/evidence: Aquarium hosts one
|
||||
five-second in-memory runtime, local/networked feeds append as producers, and
|
||||
OBS receives synchronized program outputs.
|
||||
- Mimir app scaffold now lives in `Mimir.slnx` with `src/Mimir.App` and
|
||||
`src/Mimir.Runtime`; Aquarium Engine remains an external project reference.
|
||||
- Keep scratch short and disposable.
|
||||
- Promote only durable lessons into `state/evidence.jsonl` or the map.
|
||||
|
||||
|
|
|
|||
35
tests/test_mimir_app_contract.py
Normal file
35
tests/test_mimir_app_contract.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
class MimirAppContractTests(unittest.TestCase):
|
||||
def test_solution_owns_mimir_app_and_runtime_projects(self):
|
||||
solution = (ROOT / "Mimir.slnx").read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("src/Mimir.App/Mimir.App.csproj", solution)
|
||||
self.assertIn("src/Mimir.Runtime/Mimir.Runtime.csproj", solution)
|
||||
|
||||
def test_app_references_aquarium_engine_as_host_library(self):
|
||||
app_project = (ROOT / "src" / "Mimir.App" / "Mimir.App.csproj").read_text(encoding="utf-8-sig")
|
||||
program = (ROOT / "src" / "Mimir.App" / "Program.cs").read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("Aquarium.Engine.csproj", app_project)
|
||||
self.assertIn("Mimir.Runtime.csproj", app_project)
|
||||
self.assertIn("AquariumHost.Run", program)
|
||||
self.assertIn("--client-assembly", program)
|
||||
|
||||
def test_runtime_references_localcast_runtime_client(self):
|
||||
runtime_project = (ROOT / "src" / "Mimir.Runtime" / "Mimir.Runtime.csproj").read_text(encoding="utf-8-sig")
|
||||
factory = (ROOT / "src" / "Mimir.Runtime" / "MimirRuntimeFactory.cs").read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("Aquarium.Engine.Contracts.csproj", runtime_project)
|
||||
self.assertIn("Aquarium.LocalCast.csproj", runtime_project)
|
||||
self.assertIn("IAquariumRuntimeFactory", factory)
|
||||
self.assertIn("new LocalCastRuntime(options)", factory)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -8,16 +8,21 @@ ROOT = Path(__file__).resolve().parents[1]
|
|||
|
||||
class PerfectMachineContractTests(unittest.TestCase):
|
||||
def test_contract_declares_native_reservoir_authorities(self):
|
||||
data = json.loads((ROOT / "config" / "perfect-machine.example.json").read_text(encoding="utf-8"))
|
||||
data = json.loads((ROOT / "config" / "perfect-machine.example.json").read_text(encoding="utf-8-sig"))
|
||||
|
||||
self.assertEqual("gamecult.localcast.perfect_machine.v1", data["schema"])
|
||||
self.assertEqual(5.0, data["reservoir"]["durationSeconds"])
|
||||
self.assertEqual("Aquarium", data["viableStreamApp"]["owner"])
|
||||
self.assertEqual("Mimir.slnx", data["viableStreamApp"]["solution"])
|
||||
self.assertEqual("Aquarium.Engine", data["viableStreamApp"]["windowingRenderingLibrary"])
|
||||
self.assertEqual("in-memory-localcast-runtime", data["viableStreamApp"]["runtimeState"])
|
||||
self.assertEqual("producers-not-clock-authorities", data["viableStreamApp"]["ingest"]["networkFeedsAre"])
|
||||
self.assertEqual("Aquarium", data["authorities"]["denseVisualFusion"])
|
||||
self.assertEqual("Faust", data["authorities"]["hotAudioDsp"])
|
||||
self.assertEqual("Aquarium", data["outputs"]["video"]["owner"])
|
||||
|
||||
def test_contract_covers_six_cameras_six_mics_and_required_sample_views(self):
|
||||
data = json.loads((ROOT / "config" / "perfect-machine.example.json").read_text(encoding="utf-8"))
|
||||
data = json.loads((ROOT / "config" / "perfect-machine.example.json").read_text(encoding="utf-8-sig"))
|
||||
|
||||
self.assertEqual(6, len(data["visualSensors"]))
|
||||
self.assertEqual(6, len(data["audioSensors"]))
|
||||
|
|
|
|||
Loading…
Reference in a new issue