From fd01d446776dee4dad8eea96cd8a8571d9452e17 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 26 May 2026 16:44:24 +0100 Subject: [PATCH] Plan Mimir spectrum intents as resource-backed packets --- docs/fensalir-rendering-rebuild-migration.md | 16 +++++ docs/implementation-plan.md | 12 +++- notes/current-system-map.md | 6 ++ src/Mimir.BufferSmoke/Program.cs | 59 ++++++++++++++++++- .../MimirFensalirFieldLowering.cs | 30 +++++++++- state/evidence.jsonl | 1 + state/map.yaml | 14 ++++- 7 files changed, 127 insertions(+), 11 deletions(-) diff --git a/docs/fensalir-rendering-rebuild-migration.md b/docs/fensalir-rendering-rebuild-migration.md index 0f78d31..dbf4d0a 100644 --- a/docs/fensalir-rendering-rebuild-migration.md +++ b/docs/fensalir-rendering-rebuild-migration.md @@ -186,6 +186,22 @@ bare string as payload truth. If the resource contract is absent, expired, CPU-only, or incompatible with the selected backend, lowering must defer instead of rendering a lie with nice lighting. +Current proof surface: + +- `Mimir.BufferSmoke --fensalir-field-evidence-smoke` maps a Mimir rolling + window/observation/spectrum intent into one declared resource, three claims, + one planned resource-backed `TubeField` packet, and two deferred non-backend + claims. +- `Mimir.BufferSmoke --fensalir-field-dsl-resource-smoke` uses Fensalir's field + evidence DSL to bind the declared resource directly and produce one planned + `TubeField` packet with no deferred requests. + +Current blocker for visible rendering is below this contract: Fensalir still +needs a D3D12 packet/resource resolver that imports or aliases GPU-resident +structured buffers, textures, meshes, surface pages, and volumes and binds them +to the selected shader lowering. That is engine ownership, not a reason for +Mimir to create a parallel renderer. + ### 3. Calibration Constraint Calibration and sync become explicit constraints: diff --git a/docs/implementation-plan.md b/docs/implementation-plan.md index 424ccda..927f17b 100644 --- a/docs/implementation-plan.md +++ b/docs/implementation-plan.md @@ -154,8 +154,11 @@ a named invariant that the native runtime cannot protect yet. `mimir:resource:*` keys, and Fensalir validation/planning can reject or defer packets whose resources are missing, CPU-only, or backend-incompatible. `Mimir.BufferSmoke --fensalir-field-evidence-smoke` proves the first - hardware-free receipt with one declared resource, three claims, three pending - lowering requests, and zero backend packets. + hardware-free receipt with one declared resource, three claims, one planned + resource-backed `TubeField` packet, and two deferred non-backend claims. + `Mimir.BufferSmoke --fensalir-field-dsl-resource-smoke` proves Fensalir's DSL + evidence compiler can bind a declared resource and produce one planned + `TubeField` packet with no deferred requests. - `MimirRuntime` queues bioacoustic timeline PCM through Fensalir audio when the active timing witness is allowed. `MimirAudioSynchronizationSettings.Mode` selects `chirp-only`, `passive`, or `hybrid`; passive disables active @@ -294,7 +297,10 @@ a named invariant that the native runtime cannot protect yet. accumulation from stable frame budgets. Do not route this dashboard back through fractal point splats. 8. Move GPU feature extraction, fusion, material fitting, render budgeting, and - Spout2 publication into Fensalir. + Spout2 publication into Fensalir. The next unresolved engine cut is the + D3D12 packet/resource resolver: planned field packets need imported + GPU-resident resource bindings for structured buffers, textures, meshes, + surface pages, and volumes before they can become shader dispatch/draw work. 9. Move mic alignment, room suppression, voice separation, spatialization, and stem generation into Faust/native DSP. 10. Keep the OBS bridge witness ledger as evidence before expanding receiver diff --git a/notes/current-system-map.md b/notes/current-system-map.md index 5081645..dea5849 100644 --- a/notes/current-system-map.md +++ b/notes/current-system-map.md @@ -322,6 +322,12 @@ residency, shader access, format, shape, valid time range, version, and native handle metadata. Field claims and lowering requests reference those `mimir:resource:*` keys. The handle string is only a name; Fensalir validation and planning own typed resource resolution before shader lowering. +The current smokes prove planning, not visible packet rendering: +`--fensalir-field-evidence-smoke` now produces one planned resource-backed +`TubeField` packet from Mimir's spectrum intent, and +`--fensalir-field-dsl-resource-smoke` proves the Fensalir DSL can bind the same +kind of declared resource directly. The next blocker is engine-side D3D12 +packet/resource binding for structured buffers/textures/meshes/pages/volumes. The current teardown/migration map is `docs/fensalir-rendering-rebuild-migration.md`, paired with Fensalir's diff --git a/src/Mimir.BufferSmoke/Program.cs b/src/Mimir.BufferSmoke/Program.cs index c5ca1b2..4ecdc76 100644 --- a/src/Mimir.BufferSmoke/Program.cs +++ b/src/Mimir.BufferSmoke/Program.cs @@ -95,6 +95,11 @@ if (args.Any(arg => string.Equals(arg, "--fensalir-field-evidence-smoke", String return RunFensalirFieldEvidenceSmoke(); } +if (args.Any(arg => string.Equals(arg, "--fensalir-field-dsl-resource-smoke", StringComparison.OrdinalIgnoreCase))) +{ + return RunFensalirFieldDslResourceSmoke(); +} + if (args.Any(arg => string.Equals(arg, "--perfect-machine-contract-smoke", StringComparison.OrdinalIgnoreCase))) { return await RunPerfectMachineContractSmokeAsync( @@ -534,9 +539,10 @@ static int RunFensalirFieldEvidenceSmoke() [intent]); var validation = AquariumFieldEvidenceValidator.Validate(frame); var requests = AquariumFieldEvidenceNormalizer.BuildLoweringRequests(frame); + var plan = AquariumFieldLoweringPlanner.Plan(frame); Console.WriteLine( - $"fensalir-field-evidence-smoke domains={frame.Domains.Count} resources={frame.Resources.Count} claims={frame.Claims.Count} candidates={frame.Candidates.Count} packets={frame.BackendPackets.Count} requests={requests.Count} errors={validation.HasErrors}"); + $"fensalir-field-evidence-smoke domains={frame.Domains.Count} resources={frame.Resources.Count} claims={frame.Claims.Count} candidates={frame.Candidates.Count} packets={frame.BackendPackets.Count} requests={requests.Count} planned={plan.Packets.Count} deferred={plan.DeferredRequests.Count} errors={validation.HasErrors}"); if (validation.HasErrors) { @@ -553,7 +559,56 @@ static int RunFensalirFieldEvidenceSmoke() frame.Claims.Count == 3 && frame.Claims.Any(claim => claim.PayloadHandle == frame.Resources[0].ResourceKey) && requests.Count == 3 && - requests.All(static request => request.IsPendingBackendSelection) + requests.All(static request => request.IsPendingBackendSelection) && + plan.Packets.Count == 1 && + plan.Packets[0].Backend == AquariumFieldBackendKind.TubeField && + plan.Packets[0].PayloadHandle == frame.Resources[0].ResourceKey && + plan.DeferredRequests.Count == 2 + ? 0 + : 1; +} + +static int RunFensalirFieldDslResourceSmoke() +{ + var resource = new AquariumFieldResourceDeclaration( + ResourceKey: "mimir:resource:native-ring:1234", + Kind: AquariumFieldResourceKind.StructuredBuffer, + Residency: AquariumFieldResourceResidency.SharedGpu, + Access: AquariumFieldShaderAccess.ShaderResource, + Format: "Float32", + Width: 192, + Height: 1, + DepthOrCount: 192, + StrideBytes: 4, + ValidFromNs: 0, + ValidUntilNs: 1_000_000_000, + Version: 42, + NativeHandle: new IntPtr(0x1234), + NativeHandleKind: "native-ring"); + const string source = """ +resource id=spectrum key=mimir:resource:native-ring:1234 +domain id=mimir:domain:spectrum kind=RollingBuffer min=0,0,0 max=192,1,5 owner=Mimir.Runtime +tubeclaim id=spectrum-trail resource=spectrum domain=mimir:domain:spectrum confidence=0.94 radius=0.02 support=0.02,0.02,5 +"""; + var frame = AquariumFieldScriptCompiler.CompileEvidence( + source, + new Dictionary(StringComparer.Ordinal) + { + [resource.ResourceKey] = resource, + }); + var plan = AquariumFieldLoweringPlanner.Plan(frame); + var validation = AquariumFieldEvidenceValidator.Validate(frame); + + Console.WriteLine( + $"fensalir-field-dsl-resource-smoke resources={frame.Resources.Count} claims={frame.Claims.Count} requests={AquariumFieldEvidenceNormalizer.BuildLoweringRequests(frame).Count} planned={plan.Packets.Count} deferred={plan.DeferredRequests.Count} errors={validation.HasErrors}"); + + return !validation.HasErrors && + frame.Resources.Count == 1 && + frame.Claims.Count == 1 && + plan.Packets.Count == 1 && + plan.Packets[0].Backend == AquariumFieldBackendKind.TubeField && + plan.Packets[0].PayloadHandle == resource.ResourceKey && + plan.DeferredRequests.Count == 0 ? 0 : 1; } diff --git a/src/Mimir.Runtime/Synchronization/MimirFensalirFieldLowering.cs b/src/Mimir.Runtime/Synchronization/MimirFensalirFieldLowering.cs index d7552e0..fa74bbf 100644 --- a/src/Mimir.Runtime/Synchronization/MimirFensalirFieldLowering.cs +++ b/src/Mimir.Runtime/Synchronization/MimirFensalirFieldLowering.cs @@ -19,6 +19,7 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt IEnumerable calibrationConstraints, IEnumerable surfaceIntents) { + var observationByKey = observations.ToDictionary(static observation => observation.ObservationKey, StringComparer.Ordinal); var domains = new List(); var claims = new List(); var candidates = new List(); @@ -59,7 +60,7 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt var domain = DomainForSurfaceIntent(intent); AddDomain(domains, seenDomains, domain); - var claim = ClaimForSurfaceIntent(intent, domain.DomainKey); + var claim = ClaimForSurfaceIntent(intent, domain.DomainKey, observationByKey); claims.Add(claim); var guide = AquariumFieldGuide.Valid( @@ -397,7 +398,10 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt Confidence: confidence); } - private AquariumFieldClaim ClaimForSurfaceIntent(MimirSurfaceIntent intent, string domainKey) + private AquariumFieldClaim ClaimForSurfaceIntent( + MimirSurfaceIntent intent, + string domainKey, + IReadOnlyDictionary observationByKey) { var confidence = Clamp01((float)intent.MaterialGraph.Confidence); var proposal = new AquariumFieldProposalPolicy( @@ -415,7 +419,7 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt Encoding: EncodingForSurfaceIntent(intent.Domain), Support: SupportForSurfaceIntent(intent), Proposal: proposal, - PayloadHandle: intent.SupportPolicy.PolicyId, + PayloadHandle: PayloadHandleForSurfaceIntent(intent, observationByKey), ObservedTimeNs: 0, Confidence: confidence); } @@ -514,6 +518,7 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt private static AquariumFieldEncoding EncodingForSurfaceIntent(MimirSurfaceDomain domain) => domain switch { + MimirSurfaceDomain.AudioSpectrum or MimirSurfaceDomain.AudioWaveform => AquariumFieldEncoding.Tube, MimirSurfaceDomain.Timing => AquariumFieldEncoding.Phase, MimirSurfaceDomain.AcousticResponse => AquariumFieldEncoding.Confidence, _ => AquariumFieldEncoding.Feature, @@ -535,6 +540,25 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt return MimirFensalirBridgeMapper.ResourceKeyForPayload(payload); } + private static string PayloadHandleForSurfaceIntent( + MimirSurfaceIntent intent, + IReadOnlyDictionary observationByKey) + { + foreach (var observationKey in intent.SourceObservationKeys) + { + if (observationByKey.TryGetValue(observationKey, out var observation)) + { + var resourceKey = PayloadHandle(observation.Payload); + if (!string.IsNullOrWhiteSpace(resourceKey)) + { + return resourceKey; + } + } + } + + return intent.SupportPolicy.PolicyId; + } + private static AquariumFieldResourceKind ResourceKindForDescriptor( MimirBridgeSampleDescriptor descriptor, string nativeHandleKind) diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 027f1f8..2626a64 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -139,3 +139,4 @@ {"ts": "2026-05-26T14:44:02+01:00", "type": "implementation", "status": "ok", "note": "Added BufferSmoke --fensalir-field-evidence-smoke as a hardware-free contract receipt. It builds a synthetic rolling audio window, observation, bioacoustic calibration constraint, and audio-spectrum surface intent, lowers them through MimirFensalirFieldLowering, validates with AquariumFieldEvidenceValidator, and verifies Fensalir receives three pending lowering requests and zero backend packets. Smoke passed: domains=4 claims=3 candidates=3 packets=0 requests=3 errors=False."} {"ts": "2026-05-26T14:50:33+01:00", "type": "implementation", "status": "ok", "note": "MimirRuntime now publishes AquariumFieldEvidenceFrame on every AquariumSceneState from live rolling buffers, latest observations, audio sync calibration constraints, and per-source surface intent. Existing direct spectrum splines remain diagnostic; Fensalir receives backend-neutral domains/claims/candidates through FieldEvidenceFrame. dotnet build Mimir.slnx --no-restore passed with the pre-existing EveRelay CA2024 warning, and --fensalir-field-evidence-smoke still passes."} {"ts": "2026-05-26T16:21:31+01:00", "type": "implementation", "status": "ok", "note": "Added the typed Fensalir resource boundary for field evidence. AquariumFieldEvidenceFrame now carries AquariumFieldResourceDeclaration rows; claims/packets that use mimir:resource:* handles validate against declared resources, and the lowering planner defers missing, CPU-only, or backend-incompatible resource requests. MimirFensalirFieldLowering emits resource declarations from live MimirBridgePayloadView/native handles, and observation claims reference those resource keys instead of bare kind:handle strings. dotnet build Mimir.slnx passed with the pre-existing EveRelay CA2024 warning; BufferSmoke --fensalir-field-evidence-smoke passed with domains=4 resources=1 claims=3 candidates=3 packets=0 requests=3 errors=False."} +{"ts": "2026-05-26T16:42:17+01:00", "type": "implementation", "status": "blocked", "note": "Resource-backed Fensalir lowering now reaches planned packets but not visible rendering. Mimir audio spectrum/waveform surface intents use the source observation's mimir:resource:* key, so --fensalir-field-evidence-smoke produces one planned TubeField packet and two deferred non-backend claims. Fensalir's AquariumFieldScriptCompiler.CompileEvidence can bind declared resources in DSL; --fensalir-field-dsl-resource-smoke produces one planned TubeField packet with no deferred requests. The next blocker is engine-side D3D12 packet/resource resolution: Fensalir must import/alias GPU-resident structured buffers, textures, meshes, surface pages, and volumes and bind them to selected shader lowerings before planned packets can render visibly."} diff --git a/state/map.yaml b/state/map.yaml index a4bf216..013f18d 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -291,9 +291,17 @@ accepted_design: rows for live payload views. Observation claims reference `mimir:resource:*` keys, and Fensalir validation/planning can reject or defer packets whose resource declaration is missing, CPU-only, or - backend-incompatible. `Mimir.BufferSmoke --fensalir-field-evidence-smoke` - proves the current receipt: one declared resource, three claims, three - pending lowering requests, zero backend packets, and no validation errors. + backend-incompatible. Audio spectrum/waveform surface intents now use the + source observation resource key and plan as `TubeField` packets when the + resource is compatible. `Mimir.BufferSmoke --fensalir-field-evidence-smoke` + proves one declared resource, three claims, one planned resource-backed + `TubeField` packet, two deferred non-backend claims, and no validation + errors. `--fensalir-field-dsl-resource-smoke` proves Fensalir's field + evidence DSL can bind a declared resource directly and produce one planned + `TubeField` packet with no deferred requests. Visible packet rendering is + blocked on a Fensalir D3D12 packet/resource resolver that imports/binds + structured buffers, textures, meshes, surface pages, and volumes to selected + shader lowerings. - `config/perfect-machine.example.json` declares live owners, sensors, reservoir views, and runtime policy. - `src/Mimir.Runtime/Synchronization` now includes the Perfect Machine module