feat(truth): schema_version 2 read path, v2 only
Replaces the v1 shape rather than accepting both. `anneal_sec` and the top-level `sample_fps` are deleted, not zeroed; `extraction` and `cut` blocks arrive; `scenes` become objects carrying belief and route, so a window records how far to trust it instead of being a bare float pair. `TruthSchema.IsSupported` is the single gate and is applied on all four read paths — sidecar, managed store load, managed PUT, and converted manifest. Previously only the controller checked, so the version the plugin claimed to require and the one it would actually parse were free to drift. Rejections name the file and the version found, so an item that looks empty is distinguishable from one that was refused. `ManifestConverter` carries belief, route and both provenance blocks through: dropping them would silently downgrade every fetched manifest against a locally extracted one. TRACES: JR-002, JR-003 | SR-003
This commit is contained in:
@@ -39,11 +39,38 @@ public static class ManifestConverter
|
||||
|
||||
var truth = new TruthFile
|
||||
{
|
||||
SchemaVersion = 1,
|
||||
SchemaVersion = TruthSchema.SupportedVersion,
|
||||
Movie = mediaPath ?? string.Empty,
|
||||
SampleFps = manifest.Extraction?.SampleFps ?? 0,
|
||||
};
|
||||
|
||||
// Provenance is carried across rather than flattened. The two blocks
|
||||
// have the same shape by design (JR-002), so anything the server knew
|
||||
// about how a manifest was produced survives into the stored truth.
|
||||
if (manifest.Extraction is { } extraction)
|
||||
{
|
||||
truth.Extraction = new TruthExtraction
|
||||
{
|
||||
SampleFps = extraction.SampleFps,
|
||||
ExtinctionSec = extraction.ExtinctionSec,
|
||||
PipelineVersion = extraction.PipelineVersion,
|
||||
GallerySize = extraction.GallerySize,
|
||||
GalleryScope = extraction.GalleryScope,
|
||||
};
|
||||
}
|
||||
|
||||
// The cut is the *manifest's*, not the local file's: it records the
|
||||
// encode the timings were measured against, which is what makes the
|
||||
// applied offset interpretable later. Recording the local runtime here
|
||||
// instead would erase the very discrepancy the offset corrects.
|
||||
if (manifest.Cut is { } cut)
|
||||
{
|
||||
truth.Cut = new TruthCut
|
||||
{
|
||||
RuntimeSec = cut.RuntimeSec,
|
||||
AudioSignature = cut.AudioSignature,
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var actor in manifest.Actors)
|
||||
{
|
||||
var converted = new TruthActor
|
||||
@@ -60,7 +87,18 @@ public static class ManifestConverter
|
||||
// reader can index.
|
||||
var start = Math.Max(0, scene.Start + offsetSec);
|
||||
var end = Math.Max(start, scene.End + offsetSec);
|
||||
converted.Scenes.Add(new[] { start, end });
|
||||
converted.Scenes.Add(new TruthScene
|
||||
{
|
||||
Start = start,
|
||||
End = end,
|
||||
|
||||
// Belief and route survive the conversion. They are what a
|
||||
// consumer needs to know how far to trust a window, and
|
||||
// dropping them here would silently downgrade every fetched
|
||||
// manifest against a locally extracted one.
|
||||
Belief = scene.Belief,
|
||||
Route = scene.Route,
|
||||
});
|
||||
}
|
||||
|
||||
truth.Actors.Add(converted);
|
||||
|
||||
Reference in New Issue
Block a user