From ebb9a6f1355bd7ca0c3ccf1138459fc280cb02e7 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 2 Aug 2026 16:53:14 +0200 Subject: [PATCH] Renamed VisualBriefingJson options --- .../VisualBriefingArtifactService.cs | 4 +- .../VisualBriefingAssistant.razor.Projects.cs | 2 +- ...sualBriefingBuildOrchestrator.Recompile.cs | 6 +-- .../VisualBriefingBuildProgressService.cs | 4 +- .../VisualBriefingChartCompiler.cs | 2 +- .../VisualBriefingContentStage.cs | 38 +++++++++---------- .../VisualBriefing/VisualBriefingData.cs | 2 +- .../VisualBriefingEvidenceStage.cs | 14 +++---- .../VisualBriefingInteractionCompiler.cs | 2 +- .../VisualBriefing/VisualBriefingJson.cs | 18 ++++----- .../VisualBriefingLayoutCompiler.cs | 2 +- .../VisualBriefingOperationDiagnostics.cs | 2 +- .../VisualBriefing/VisualBriefingPlanStage.cs | 4 +- .../VisualBriefingPresentationStage.cs | 12 +++--- .../VisualBriefingStore.Builds.cs | 30 +++++++-------- .../VisualBriefingStore.Versions.cs | 10 ++--- .../VisualBriefing/VisualBriefingStore.cs | 2 +- ...sualBriefingStructuredResponseProcessor.cs | 2 +- .../VisualBriefingValidation.cs | 2 +- 19 files changed, 79 insertions(+), 79 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingArtifactService.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingArtifactService.cs index d6aa34ee..c10e448a 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingArtifactService.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingArtifactService.cs @@ -30,9 +30,9 @@ public sealed partial class VisualBriefingArtifactService private const string DATA_ELEMENT_ID = "mwai-briefing-data"; /// - /// Gets the shared compact JSON configuration. + /// Gets the frozen JSON configuration whose bytes the document hash covers. /// - private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Compact; + private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Canonical; /// /// Defines HtmlLanguageTagRegex for the visual briefing feature. diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs index fb3f6432..72790559 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs @@ -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); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildOrchestrator.Recompile.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildOrchestrator.Recompile.cs index f0ea4323..c2b670ab 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildOrchestrator.Recompile.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildOrchestrator.Recompile.cs @@ -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), diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildProgressService.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildProgressService.cs index bea95b37..295ed162 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildProgressService.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingBuildProgressService.cs @@ -21,8 +21,8 @@ public sealed class VisualBriefingBuildProgressService public void Publish(VisualBriefingBuildRecord build) { var snapshot = JsonSerializer.Deserialize( - 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); diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingChartCompiler.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingChartCompiler.cs index b38a5204..17f398aa 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingChartCompiler.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingChartCompiler.cs @@ -125,7 +125,7 @@ internal static class VisualBriefingChartCompiler : series, }; - return JsonSerializer.SerializeToElement(option, VisualBriefingJson.Compact); + return JsonSerializer.SerializeToElement(option, VisualBriefingJson.Canonical); } /// diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingContentStage.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingContentStage.cs index 519757a2..a7bfb80c 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingContentStage.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingContentStage.cs @@ -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, }; } diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingData.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingData.cs index 0325555c..e8dc4360 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingData.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingData.cs @@ -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); } /// diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingEvidenceStage.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingEvidenceStage.cs index f1cd0fea..4d59927c 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingEvidenceStage.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingEvidenceStage.cs @@ -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)} """; } diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingInteractionCompiler.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingInteractionCompiler.cs index 4f2da84d..f53286a1 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingInteractionCompiler.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingInteractionCompiler.cs @@ -32,7 +32,7 @@ internal static class VisualBriefingInteractionCompiler controls, state, formulas = formulaMap, - }, VisualBriefingJson.Compact); + }, VisualBriefingJson.Canonical); } /// diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingJson.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingJson.cs index 1db7191f..6bc98462 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingJson.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingJson.cs @@ -16,27 +16,27 @@ namespace AIStudio.Assistants.VisualBriefing; internal static class VisualBriefingJson { /// - /// Gets compact canonical JSON options. + /// Gets the frozen options whose byte output is hashed into stored briefings. /// /// /// 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. /// - internal static JsonSerializerOptions Compact { get; } = Create(writeIndented: false, enumsAsText: false); + internal static JsonSerializerOptions Canonical { get; } = Create(writeIndented: false, enumsAsText: false); /// - /// Gets indented persistence JSON options. + /// Gets the options for files that are read back by name rather than by hash. /// /// /// 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. /// - internal static JsonSerializerOptions Indented { get; } = Create(writeIndented: true, enumsAsText: true); + internal static JsonSerializerOptions Persistence { get; } = Create(writeIndented: true, enumsAsText: true); /// /// Creates the shared JSON configuration. diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingLayoutCompiler.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingLayoutCompiler.cs index ec962dd5..7334e34d 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingLayoutCompiler.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingLayoutCompiler.cs @@ -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); diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingOperationDiagnostics.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingOperationDiagnostics.cs index 1fd66cf2..f4bc98e3 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingOperationDiagnostics.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingOperationDiagnostics.cs @@ -132,5 +132,5 @@ public sealed class VisualBriefingOperationDiagnostics /// Serializes the diagnostics without user content. /// /// A compact JSON document suitable for the clipboard. - public string ToClipboardText() => JsonSerializer.Serialize(this, VisualBriefingJson.Indented); + public string ToClipboardText() => JsonSerializer.Serialize(this, VisualBriefingJson.Persistence); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPlanStage.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPlanStage.cs index f28584c9..0b7d7fca 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPlanStage.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPlanStage.cs @@ -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)} """; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPresentationStage.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPresentationStage.cs index febfb462..a4846a08 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPresentationStage.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingPresentationStage.cs @@ -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} """; diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Builds.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Builds.cs index 58e2bfb6..e1076672 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Builds.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Builds.cs @@ -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); diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Versions.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Versions.cs index 1c18ba68..fa0dad9b 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Versions.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.Versions.cs @@ -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), diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.cs index 6b95d06a..1510f32a 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStore.cs @@ -45,7 +45,7 @@ public sealed partial class VisualBriefingStore( private const string TRANSCRIPTS_DIRECTORY_NAME = "transcripts"; /// Gets the shared persistence JSON options. - private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Indented; + private static readonly JsonSerializerOptions JSON_OPTIONS = VisualBriefingJson.Persistence; /// Stores per-project process locks. private readonly ConcurrentDictionary briefingLocks = []; diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStructuredResponseProcessor.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStructuredResponseProcessor.cs index 446a9ebe..e27d4bca 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStructuredResponseProcessor.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingStructuredResponseProcessor.cs @@ -184,7 +184,7 @@ internal static partial class VisualBriefingStructuredResponseProcessor T? parsed; try { - parsed = JsonSerializer.Deserialize(candidate.Json, VisualBriefingJson.Compact); + parsed = JsonSerializer.Deserialize(candidate.Json, VisualBriefingJson.Canonical); } catch (JsonException exception) { diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingValidation.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingValidation.cs index 886a6e2f..0ee79252 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingValidation.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingValidation.cs @@ -685,7 +685,7 @@ internal static partial class VisualBriefingValidation private static bool ContainsForbidden(T value) { - var json = JsonSerializer.SerializeToElement(value, VisualBriefingJson.Compact); + var json = JsonSerializer.SerializeToElement(value, VisualBriefingJson.Canonical); return ContainsForbiddenElement(json); }