Plan Mimir spectrum intents as resource-backed packets
This commit is contained in:
parent
e75fc71211
commit
fd01d44677
7 changed files with 127 additions and 11 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<string, AquariumFieldResourceDeclaration>(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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ public sealed class MimirFensalirFieldLowering(MimirFensalirLoweringOptions? opt
|
|||
IEnumerable<MimirCalibrationConstraint> calibrationConstraints,
|
||||
IEnumerable<MimirSurfaceIntent> surfaceIntents)
|
||||
{
|
||||
var observationByKey = observations.ToDictionary(static observation => observation.ObservationKey, StringComparer.Ordinal);
|
||||
var domains = new List<AquariumFieldDomain>();
|
||||
var claims = new List<AquariumFieldClaim>();
|
||||
var candidates = new List<AquariumFieldCandidate>();
|
||||
|
|
@ -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<string, MimirObservation> 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<string, MimirObservation> 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)
|
||||
|
|
|
|||
|
|
@ -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."}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue