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