// Copyright (c) StellaOps. All rights reserved. // Licensed under BUSL-1.1. See LICENSE in the project root. using System.Text.Json.Serialization; namespace StellaOps.BinaryIndex.DeltaSig; /// /// Source file pair used to compute semantic edit scripts. /// public sealed record SourceFileDiff { /// /// Source file path (repository-relative). /// public required string Path { get; init; } /// /// Previous file content. /// public string? BeforeContent { get; init; } /// /// Current file content. /// public string? AfterContent { get; init; } } /// /// Source line span. /// public sealed record SourceSpan { /// /// 1-based start line. /// public required int StartLine { get; init; } /// /// 1-based end line. /// public required int EndLine { get; init; } } /// /// Deterministic semantic edit script. /// public sealed record SemanticEditScript { /// /// Schema version. /// public string SchemaVersion { get; init; } = "1.0.0"; /// /// Digest of the full source tree diff input. /// public required string SourceTreeDigest { get; init; } /// /// Deterministic ordered edits. /// public required IReadOnlyList Edits { get; init; } } /// /// Single semantic edit entry. /// public sealed record SemanticEdit { /// /// Stable digest-derived ID for dedupe and audit references. /// public required string StableId { get; init; } /// /// Edit type: add, remove, move, update, rename. /// public required string EditType { get; init; } /// /// Node kind: file, method, class, field, import, statement. /// public required string NodeKind { get; init; } /// /// Deterministic node path. /// public required string NodePath { get; init; } /// /// Symbol anchor used to link to binary symbols. /// public required string Anchor { get; init; } /// /// Pre-change source span. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public SourceSpan? PreSpan { get; init; } /// /// Post-change source span. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public SourceSpan? PostSpan { get; init; } /// /// Pre-change digest. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? PreDigest { get; init; } /// /// Post-change digest. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? PostDigest { get; init; } } /// /// Build-stage symbol map linked to build identity. /// public sealed record SymbolMap { /// /// Schema version. /// public string SchemaVersion { get; init; } = "1.0.0"; /// /// Build ID (ELF build-id, PDB GUID, or equivalent). /// public required string BuildId { get; init; } /// /// Optional binary digest for traceability. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? BinaryDigest { get; init; } /// /// Address derivation source (manifest, synthetic-signature). /// public string AddressSource { get; init; } = "manifest"; /// /// Ordered symbol entries. /// public required IReadOnlyList Symbols { get; init; } } /// /// Symbol map entry. /// public sealed record SymbolMapEntry { /// /// Symbol name. /// public required string Name { get; init; } /// /// Symbol kind: function, object, section. /// public string Kind { get; init; } = "function"; /// /// Start address. /// public required ulong AddressStart { get; init; } /// /// End address. /// public required ulong AddressEnd { get; init; } /// /// Containing section. /// public string Section { get; init; } = ".text"; /// /// Source ranges for this symbol. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IReadOnlyList? SourceRanges { get; init; } /// /// Symbol size derived from address range. /// [JsonIgnore] public long Size => checked((long)(AddressEnd >= AddressStart ? AddressEnd - AddressStart + 1UL : 0UL)); } /// /// Source range metadata. /// public sealed record SourceRange { /// /// Source file path. /// public required string File { get; init; } /// /// 1-based start line. /// public required int LineStart { get; init; } /// /// 1-based end line. /// public required int LineEnd { get; init; } } /// /// Join artifact linking semantic edits to symbol changes. /// public sealed record SymbolPatchPlan { /// /// Schema version. /// public string SchemaVersion { get; init; } = "1.0.0"; /// /// Build ID before patch. /// public required string BuildIdBefore { get; init; } /// /// Build ID after patch. /// public required string BuildIdAfter { get; init; } /// /// Semantic script digest. /// public required string EditsDigest { get; init; } /// /// Old symbol map digest. /// public required string SymbolMapDigestBefore { get; init; } /// /// New symbol map digest. /// public required string SymbolMapDigestAfter { get; init; } /// /// Ordered symbol changes. /// public required IReadOnlyList Changes { get; init; } } /// /// Single symbol patch plan entry. /// public sealed record SymbolPatchChange { /// /// Symbol name. /// public required string Symbol { get; init; } /// /// Change type: added, removed, modified, moved. /// public required string ChangeType { get; init; } /// /// Linked source anchors. /// public required IReadOnlyList AstAnchors { get; init; } /// /// Hash before. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? PreHash { get; init; } /// /// Hash after. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? PostHash { get; init; } /// /// Delta reference digest. /// public required string DeltaRef { get; init; } } /// /// Normalized patch manifest for per-symbol deltas. /// public sealed record PatchManifest { /// /// Schema version. /// public string SchemaVersion { get; init; } = "1.0.0"; /// /// Build ID. /// public required string BuildId { get; init; } /// /// Normalization recipe identifier. /// public required string NormalizationRecipeId { get; init; } /// /// Ordered patch entries. /// public required IReadOnlyList Patches { get; init; } /// /// Total delta bytes across symbols. /// [JsonIgnore] public long TotalDeltaBytes => Patches.Sum(p => p.DeltaSizeBytes); } /// /// Per-symbol patch artifact. /// public sealed record SymbolPatchArtifact { /// /// Symbol name. /// public required string Symbol { get; init; } /// /// Address range in hex format. /// public required string AddressRange { get; init; } /// /// Digest of patch payload. /// public required string DeltaDigest { get; init; } /// /// Pre-patch metrics. /// public required PatchSizeHash Pre { get; init; } /// /// Post-patch metrics. /// public required PatchSizeHash Post { get; init; } /// /// Absolute byte delta. /// [JsonIgnore] public long DeltaSizeBytes => Math.Abs(Post.Size - Pre.Size); } /// /// Size/hash tuple. /// public sealed record PatchSizeHash { /// /// Size in bytes. /// public required long Size { get; init; } /// /// Hash digest. /// public required string Hash { get; init; } } /// /// Full hybrid diff evidence bundle. /// public sealed record HybridDiffEvidence { /// /// Semantic edit script. /// public required SemanticEditScript SemanticEditScript { get; init; } /// /// Old symbol map. /// public required SymbolMap OldSymbolMap { get; init; } /// /// New symbol map. /// public required SymbolMap NewSymbolMap { get; init; } /// /// Symbol patch plan. /// public required SymbolPatchPlan SymbolPatchPlan { get; init; } /// /// Normalized patch manifest. /// public required PatchManifest PatchManifest { get; init; } /// /// Semantic edit script digest. /// public required string SemanticEditScriptDigest { get; init; } /// /// Old symbol map digest. /// public required string OldSymbolMapDigest { get; init; } /// /// New symbol map digest. /// public required string NewSymbolMapDigest { get; init; } /// /// Symbol patch plan digest. /// public required string SymbolPatchPlanDigest { get; init; } /// /// Patch manifest digest. /// public required string PatchManifestDigest { get; init; } }