Renamed VisualBriefingJson options

This commit is contained in:
Thorsten Sommer 2026-08-02 16:53:14 +02:00
parent c2d3b410f2
commit ebb9a6f135
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
19 changed files with 79 additions and 79 deletions

View File

@ -30,9 +30,9 @@ public sealed partial class VisualBriefingArtifactService
private const string DATA_ELEMENT_ID = "mwai-briefing-data";
/// <summary>
/// Gets the shared compact JSON configuration.
/// Gets the frozen JSON configuration whose bytes the document hash covers.
/// </summary>
private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Compact;
private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Canonical;
/// <summary>
/// Defines <c>HtmlLanguageTagRegex</c> for the visual briefing feature.

View File

@ -380,5 +380,5 @@ public partial class VisualBriefingAssistant
this.editor.Author,
Settings = this.editor.ToSettings(),
Sources = this.editor.ToSources().Select(source => new { source.Path, source.Kind }).ToArray(),
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
}

View File

@ -135,12 +135,12 @@ internal sealed partial class VisualBriefingBuildOrchestrator
authors = "validation",
protection = "validation",
},
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
VisualBriefingCompilerInvariant.Guard(
VisualBriefingBuildStage.COMPILATION,
VisualBriefingArtifactService.ValidateGeneratedParts(manifest,
JsonSerializer.SerializeToElement(validationDataProperties, VisualBriefingJson.Compact),
JsonSerializer.SerializeToElement(validationDataProperties, VisualBriefingJson.Canonical),
compiled.TemplateHtml, compiled.Css,
content.Charts.Count > 0));
@ -151,7 +151,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
ArtifactId = Guid.NewGuid(),
CreatedAtUtc = DateTimeOffset.UtcNow,
PayloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(previousPresentation.Layout, VisualBriefingJson.Compact),
JsonSerializer.Serialize(previousPresentation.Layout, VisualBriefingJson.Canonical),
previousPresentation.Profile.ToString(),
compiled.TemplateHash,
compiled.CssHash),

View File

@ -21,8 +21,8 @@ public sealed class VisualBriefingBuildProgressService
public void Publish(VisualBriefingBuildRecord build)
{
var snapshot = JsonSerializer.Deserialize<VisualBriefingBuildRecord>(
JsonSerializer.Serialize(build, VisualBriefingJson.Compact),
VisualBriefingJson.Compact)!;
JsonSerializer.Serialize(build, VisualBriefingJson.Canonical),
VisualBriefingJson.Canonical)!;
snapshot.Instruction = string.Empty;
this.latest[build.BriefingId] = snapshot;
this.Changed?.Invoke(build.BriefingId);

View File

@ -125,7 +125,7 @@ internal static class VisualBriefingChartCompiler
: series,
};
return JsonSerializer.SerializeToElement(option, VisualBriefingJson.Compact);
return JsonSerializer.SerializeToElement(option, VisualBriefingJson.Canonical);
}
/// <summary>

View File

@ -65,19 +65,19 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
reset = artifact.ResetLabel,
brand = "MindWork AI Studio",
},
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
// Keep in sync with the verification in VisualBriefingStore.ReadContentArtifactAsync:
artifact.PayloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(artifact.Slots, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Charts, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Controls, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Formulas, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.AccessibilityTexts, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.SourceReferences, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Slots, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Charts, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Controls, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Formulas, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.AccessibilityTexts, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.SourceReferences, VisualBriefingJson.Canonical),
artifact.ResetLabel,
JsonSerializer.Serialize(artifact.SourceCoverage, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.AssetPlan, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.SourceCoverage, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.AssetPlan, VisualBriefingJson.Canonical),
artifact.StructuralSignature);
await store.WriteContentArtifactAsync(manifest.BriefingId, artifact, token);
@ -170,13 +170,13 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
Target language: {manifest.Settings.TargetLanguage.PromptGeneralPurpose(manifest.Settings.CustomTargetLanguage)}
Audience: {manifest.Settings.AudienceProfile}; {manifest.Settings.AudienceAgeGroup}; {manifest.Settings.AudienceOrganizationalLevel}; {manifest.Settings.AudienceExpertise}
Scope instruction: {manifest.Settings.Instruction}
Exact planned component IDs: {JsonSerializer.Serialize(componentIds, VisualBriefingJson.Compact)}
Exact keys of accessibilityTexts, no others: {JsonSerializer.Serialize(accessibilityTextKeys, VisualBriefingJson.Compact)}
Exact required slot IDs with their semantic role and declared type, each to be returned exactly once: {JsonSerializer.Serialize(requiredSlots, VisualBriefingJson.Compact)}
Exact chart component IDs, each to receive exactly one chart: {JsonSerializer.Serialize(chartComponentIds, VisualBriefingJson.Compact)}
Exact control and formula requirements, no controls for any other component: {JsonSerializer.Serialize(controlRequirements, VisualBriefingJson.Compact)}
Plan: {JsonSerializer.Serialize(plan.Sections, VisualBriefingJson.Compact)}
Evidence: {JsonSerializer.Serialize(new { evidence.Facts, evidence.Metrics, evidence.Tables, evidence.AssetPlan }, VisualBriefingJson.Compact)}
Exact planned component IDs: {JsonSerializer.Serialize(componentIds, VisualBriefingJson.Canonical)}
Exact keys of accessibilityTexts, no others: {JsonSerializer.Serialize(accessibilityTextKeys, VisualBriefingJson.Canonical)}
Exact required slot IDs with their semantic role and declared type, each to be returned exactly once: {JsonSerializer.Serialize(requiredSlots, VisualBriefingJson.Canonical)}
Exact chart component IDs, each to receive exactly one chart: {JsonSerializer.Serialize(chartComponentIds, VisualBriefingJson.Canonical)}
Exact control and formula requirements, no controls for any other component: {JsonSerializer.Serialize(controlRequirements, VisualBriefingJson.Canonical)}
Plan: {JsonSerializer.Serialize(plan.Sections, VisualBriefingJson.Canonical)}
Evidence: {JsonSerializer.Serialize(new { evidence.Facts, evidence.Metrics, evidence.Tables, evidence.AssetPlan }, VisualBriefingJson.Canonical)}
""";
}
@ -257,9 +257,9 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
authors = "validation",
protection = "validation",
},
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
var validationData = JsonSerializer.SerializeToElement(data, VisualBriefingJson.Compact);
var validationData = JsonSerializer.SerializeToElement(data, VisualBriefingJson.Canonical);
VisualBriefingCompilerInvariant.Guard(VisualBriefingBuildStage.CONTENT,
VisualBriefingArtifactService.ValidateGeneratedParts(
manifest,
@ -353,7 +353,7 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
ControlId = $"mwai-filter-{index}",
ComponentId = component.ComponentId,
Kind = VisualBriefingControlKind.FILTER,
InitialValue = JsonSerializer.SerializeToElement(SHOW_ALL_VALUE, VisualBriefingJson.Compact),
InitialValue = JsonSerializer.SerializeToElement(SHOW_ALL_VALUE, VisualBriefingJson.Canonical),
Options = options,
};
}

View File

@ -17,7 +17,7 @@ internal static class VisualBriefingData
var dictionary = data.EnumerateObject()
.Where(property => property.Name is not "_mwai")
.ToDictionary(property => property.Name, property => property.Value.Clone(), StringComparer.Ordinal);
return JsonSerializer.SerializeToElement(dictionary, VisualBriefingJson.Compact);
return JsonSerializer.SerializeToElement(dictionary, VisualBriefingJson.Canonical);
}
/// <summary>

View File

@ -47,11 +47,11 @@ internal sealed class VisualBriefingEvidenceStage(StructuredLlmStageRunner stage
var response = run.Response!;
var payloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(response.Facts, VisualBriefingJson.Compact),
JsonSerializer.Serialize(response.Metrics, VisualBriefingJson.Compact),
JsonSerializer.Serialize(response.Tables, VisualBriefingJson.Compact),
JsonSerializer.Serialize(response.SourceCoverage, VisualBriefingJson.Compact),
JsonSerializer.Serialize(response.AssetPlan, VisualBriefingJson.Compact));
JsonSerializer.Serialize(response.Facts, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(response.Metrics, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(response.Tables, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(response.SourceCoverage, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(response.AssetPlan, VisualBriefingJson.Canonical));
var artifact = new VisualBriefingEvidenceArtifact
{
@ -124,8 +124,8 @@ internal sealed class VisualBriefingEvidenceStage(StructuredLlmStageRunner stage
return $"""
Target language: {manifest.Settings.TargetLanguage.PromptGeneralPurpose(manifest.Settings.CustomTargetLanguage)}
Scope instruction: {manifest.Settings.Instruction}
Sources, in the same order as the attached files: {JsonSerializer.Serialize(sources, VisualBriefingJson.Compact)}
Media transcripts: {JsonSerializer.Serialize(transcripts, VisualBriefingJson.Compact)}
Sources, in the same order as the attached files: {JsonSerializer.Serialize(sources, VisualBriefingJson.Canonical)}
Media transcripts: {JsonSerializer.Serialize(transcripts, VisualBriefingJson.Canonical)}
""";
}

View File

@ -32,7 +32,7 @@ internal static class VisualBriefingInteractionCompiler
controls,
state,
formulas = formulaMap,
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
}
/// <summary>

View File

@ -16,27 +16,27 @@ namespace AIStudio.Assistants.VisualBriefing;
internal static class VisualBriefingJson
{
/// <summary>
/// Gets compact canonical JSON options.
/// Gets the frozen options whose byte output is hashed into stored briefings.
/// </summary>
/// <remarks>
/// Treat these options as frozen. Their exact bytes are hashed into stored briefings: the artifact
/// header is serialized into the briefing document, and reading that document back re-serializes the
/// header to recompute the document hash. Every build stage likewise hashes its serialized output to
/// decide what a later build may reuse. Any change here — a converter, a naming policy, an encoder —
/// therefore invalidates every briefing that was ever written, which surfaces as a failed integrity
/// check rather than as a build error. This is why enums stay numeric here even though the persisted
/// manifest writes their member names.
/// header to recompute the document hash. Every build stage likewise hashes its serialized output,
/// and a mismatch makes the store discard the stored artifact. Any change here — a converter, a
/// naming policy, an encoder — therefore invalidates every briefing that was ever written, which
/// surfaces as a failed integrity check rather than as a build error. This is why enums stay numeric
/// here even though the persisted manifest writes their member names.
/// </remarks>
internal static JsonSerializerOptions Compact { get; } = Create(writeIndented: false, enumsAsText: false);
internal static JsonSerializerOptions Canonical { get; } = Create(writeIndented: false, enumsAsText: false);
/// <summary>
/// Gets indented persistence JSON options.
/// Gets the options for files that are read back by name rather than by hash.
/// </summary>
/// <remarks>
/// These options are free to evolve, because nothing hashes their output. They write the briefing
/// manifest and the diagnostics clipboard text, where readable enum names are worth having.
/// </remarks>
internal static JsonSerializerOptions Indented { get; } = Create(writeIndented: true, enumsAsText: true);
internal static JsonSerializerOptions Persistence { get; } = Create(writeIndented: true, enumsAsText: true);
/// <summary>
/// Creates the shared JSON configuration.

View File

@ -61,7 +61,7 @@ internal sealed class VisualBriefingLayoutCompiler
reset = content.ResetLabel,
brand = "MindWork AI Studio",
},
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
var html = CompileNode(layout, sections, components, content, true);
var css = CompileCss(profile, layout);

View File

@ -132,5 +132,5 @@ public sealed class VisualBriefingOperationDiagnostics
/// Serializes the diagnostics without user content.
/// </summary>
/// <returns>A compact JSON document suitable for the clipboard.</returns>
public string ToClipboardText() => JsonSerializer.Serialize(this, VisualBriefingJson.Indented);
public string ToClipboardText() => JsonSerializer.Serialize(this, VisualBriefingJson.Persistence);
}

View File

@ -50,7 +50,7 @@ internal sealed class VisualBriefingPlanStage(StructuredLlmStageRunner stageRunn
await VisualBriefingEvidenceStage.FailAsync(store, build, stage, run, VisualBriefingValidationRule.REFERENCE_INVALID, token);
var sections = run.Response!.Sections;
var payload = JsonSerializer.Serialize(sections, VisualBriefingJson.Compact);
var payload = JsonSerializer.Serialize(sections, VisualBriefingJson.Canonical);
var structuralSignature = VisualBriefingHashing.Compute(string.Join('\u001f', sections.Select(section => $"{section.SectionId}:{section.Role}:{section.TitleSlotId}:{section.SummarySlotId}")
.Concat(sections.SelectMany(section => section.Components)
@ -113,6 +113,6 @@ internal sealed class VisualBriefingPlanStage(StructuredLlmStageRunner stageRunn
$"""
Audience: {manifest.Settings.AudienceProfile}; {manifest.Settings.AudienceAgeGroup}; {manifest.Settings.AudienceOrganizationalLevel}; {manifest.Settings.AudienceExpertise}
Scope instruction: {manifest.Settings.Instruction}
Evidence: {JsonSerializer.Serialize(new { evidence.Facts, evidence.Metrics, evidence.Tables, evidence.AssetPlan }, VisualBriefingJson.Compact)}
Evidence: {JsonSerializer.Serialize(new { evidence.Facts, evidence.Metrics, evidence.Tables, evidence.AssetPlan }, VisualBriefingJson.Canonical)}
""";
}

View File

@ -81,7 +81,7 @@ internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner s
var compiled = VisualBriefingLayoutCompiler.Compile(plan, content, run.Response.Layout, run.Response.Profile);
var payloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(run.Response.Layout, VisualBriefingJson.Compact),
JsonSerializer.Serialize(run.Response.Layout, VisualBriefingJson.Canonical),
run.Response.Profile.ToString(),
compiled.TemplateHash,
compiled.CssHash);
@ -114,7 +114,7 @@ internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner s
await store.SaveBuildAsync(build, token);
progressService.Publish(build);
logger.LogInformation("Visual briefing design completed. OperationId={OperationId} BuildId={BuildId} LayoutHash={LayoutHash} TemplateHash={TemplateHash} CssHash={CssHash}", build.OperationId, build.BuildId, VisualBriefingHashing.Compute(JsonSerializer.Serialize(artifact.Layout, VisualBriefingJson.Compact)), artifact.TemplateHash, artifact.CssHash);
logger.LogInformation("Visual briefing design completed. OperationId={OperationId} BuildId={BuildId} LayoutHash={LayoutHash} TemplateHash={TemplateHash} CssHash={CssHash}", build.OperationId, build.BuildId, VisualBriefingHashing.Compute(JsonSerializer.Serialize(artifact.Layout, VisualBriefingJson.Canonical)), artifact.TemplateHash, artifact.CssHash);
return artifact;
}
@ -150,9 +150,9 @@ internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner s
authors = "validation",
protection = "validation",
},
}, VisualBriefingJson.Compact);
}, VisualBriefingJson.Canonical);
var validationData = JsonSerializer.SerializeToElement(data, VisualBriefingJson.Compact);
var validationData = JsonSerializer.SerializeToElement(data, VisualBriefingJson.Canonical);
VisualBriefingCompilerInvariant.Guard(VisualBriefingBuildStage.DESIGN,
VisualBriefingArtifactService.ValidateGeneratedParts(manifest, validationData, compiled.TemplateHtml, compiled.Css, content.Charts.Count > 0));
@ -187,12 +187,12 @@ internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner s
private static string BuildPrompt(VisualBriefingManifest manifest, VisualBriefingPlanArtifact plan, VisualBriefingPresentationArtifact? parent)
{
var parentJson = parent is null ? "none" : JsonSerializer.Serialize(new { parent.Layout, parent.Profile }, VisualBriefingJson.Compact);
var parentJson = parent is null ? "none" : JsonSerializer.Serialize(new { parent.Layout, parent.Profile }, VisualBriefingJson.Canonical);
return $"""
Operation: {(parent is null ? "CREATE_DESIGN" : "CHANGE_DESIGN")}
Design instruction: {manifest.Settings.Instruction}
Planned sections and components:
{JsonSerializer.Serialize(plan.Sections, VisualBriefingJson.Compact)}
{JsonSerializer.Serialize(plan.Sections, VisualBriefingJson.Canonical)}
Parent design:
{parentJson}
""";

View File

@ -164,11 +164,11 @@ public sealed partial class VisualBriefingStore
return null;
var hash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(artifact.Facts, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Metrics, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Tables, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.SourceCoverage, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.AssetPlan, VisualBriefingJson.Compact));
JsonSerializer.Serialize(artifact.Facts, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Metrics, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Tables, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.SourceCoverage, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.AssetPlan, VisualBriefingJson.Canonical));
return string.Equals(hash, artifact.PayloadHash, StringComparison.Ordinal) ? artifact : null;
}
@ -217,7 +217,7 @@ public sealed partial class VisualBriefingStore
return null;
var hash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(artifact.Sections, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Sections, VisualBriefingJson.Canonical),
artifact.StructuralSignature);
return string.Equals(hash, artifact.PayloadHash, StringComparison.Ordinal) ? artifact : null;
@ -273,15 +273,15 @@ public sealed partial class VisualBriefingStore
return null;
var payloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(artifact.Slots, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Charts, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Controls, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Formulas, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.AccessibilityTexts, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.SourceReferences, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Slots, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Charts, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Controls, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.Formulas, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.AccessibilityTexts, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.SourceReferences, VisualBriefingJson.Canonical),
artifact.ResetLabel,
JsonSerializer.Serialize(artifact.SourceCoverage, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.AssetPlan, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.SourceCoverage, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(artifact.AssetPlan, VisualBriefingJson.Canonical),
artifact.StructuralSignature);
return string.Equals(payloadHash, artifact.PayloadHash, StringComparison.Ordinal) ? artifact : null;
@ -336,7 +336,7 @@ public sealed partial class VisualBriefingStore
return null;
var payloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(artifact.Layout, VisualBriefingJson.Compact),
JsonSerializer.Serialize(artifact.Layout, VisualBriefingJson.Canonical),
artifact.Profile.ToString(),
artifact.TemplateHash,
artifact.CssHash);

View File

@ -504,15 +504,15 @@ public sealed partial class VisualBriefingStore
// Section order and count must match ReadContentArtifactAsync exactly:
var contentHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(importedSlots, VisualBriefingJson.Compact),
JsonSerializer.Serialize(importedSlots, VisualBriefingJson.Canonical),
"[]",
"[]",
"[]",
"{}",
"{}",
"Reset",
JsonSerializer.Serialize(coverage, VisualBriefingJson.Compact),
JsonSerializer.Serialize(assetPlan, VisualBriefingJson.Compact),
JsonSerializer.Serialize(coverage, VisualBriefingJson.Canonical),
JsonSerializer.Serialize(assetPlan, VisualBriefingJson.Canonical),
structuralSignature);
var content = new VisualBriefingContentArtifact
@ -551,7 +551,7 @@ public sealed partial class VisualBriefingStore
ArtifactId = Guid.NewGuid(),
CreatedAtUtc = DateTimeOffset.UtcNow,
PayloadHash = VisualBriefingHashing.ComputeSections(
JsonSerializer.Serialize(importedLayout, VisualBriefingJson.Compact),
JsonSerializer.Serialize(importedLayout, VisualBriefingJson.Canonical),
VisualBriefingDesignProfile.EDITORIAL.ToString(),
templateHash,
cssHash),
@ -607,7 +607,7 @@ public sealed partial class VisualBriefingStore
var businessData = VisualBriefingHashing.CanonicalJson(VisualBriefingData.RemoveProtectedData(parts.Data));
var assets = JsonSerializer.Serialize(
VisualBriefingData.ExtractAssets(parts.Data),
VisualBriefingJson.Compact);
VisualBriefingJson.Canonical);
return new(
VisualBriefingHashing.Compute(businessData),

View File

@ -45,7 +45,7 @@ public sealed partial class VisualBriefingStore(
private const string TRANSCRIPTS_DIRECTORY_NAME = "transcripts";
/// <summary>Gets the shared persistence JSON options.</summary>
private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Indented;
private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Persistence;
/// <summary>Stores per-project process locks.</summary>
private readonly ConcurrentDictionary<Guid, SemaphoreSlim> briefingLocks = [];

View File

@ -184,7 +184,7 @@ internal static partial class VisualBriefingStructuredResponseProcessor
T? parsed;
try
{
parsed = JsonSerializer.Deserialize<T>(candidate.Json, VisualBriefingJson.Compact);
parsed = JsonSerializer.Deserialize<T>(candidate.Json, VisualBriefingJson.Canonical);
}
catch (JsonException exception)
{

View File

@ -685,7 +685,7 @@ internal static partial class VisualBriefingValidation
private static bool ContainsForbidden<T>(T value)
{
var json = JsonSerializer.SerializeToElement(value, VisualBriefingJson.Compact);
var json = JsonSerializer.SerializeToElement(value, VisualBriefingJson.Canonical);
return ContainsForbiddenElement(json);
}