save progress
This commit is contained in:
132
src/__Libraries/StellaOps.Facet/FacetDrift.cs
Normal file
132
src/__Libraries/StellaOps.Facet/FacetDrift.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
// <copyright file="FacetDrift.cs" company="StellaOps">
|
||||
// Copyright (c) StellaOps. Licensed under AGPL-3.0-or-later.
|
||||
// </copyright>
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace StellaOps.Facet;
|
||||
|
||||
/// <summary>
|
||||
/// Drift detection result for a single facet.
|
||||
/// </summary>
|
||||
public sealed record FacetDrift
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the facet this drift applies to.
|
||||
/// </summary>
|
||||
public required string FacetId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the files added since baseline.
|
||||
/// </summary>
|
||||
public required ImmutableArray<FacetFileEntry> Added { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the files removed since baseline.
|
||||
/// </summary>
|
||||
public required ImmutableArray<FacetFileEntry> Removed { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the files modified since baseline.
|
||||
/// </summary>
|
||||
public required ImmutableArray<FacetFileModification> Modified { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the drift score (0-100, higher = more drift).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The drift score weighs additions, removals, and modifications
|
||||
/// to produce a single measure of change magnitude.
|
||||
/// </remarks>
|
||||
public required decimal DriftScore { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the quota evaluation result.
|
||||
/// </summary>
|
||||
public required QuotaVerdict QuotaVerdict { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of files in baseline facet seal.
|
||||
/// </summary>
|
||||
public required int BaselineFileCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of changes (added + removed + modified).
|
||||
/// </summary>
|
||||
public int TotalChanges => Added.Length + Removed.Length + Modified.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the churn percentage = (changes / baseline count) * 100.
|
||||
/// </summary>
|
||||
public decimal ChurnPercent => BaselineFileCount > 0
|
||||
? TotalChanges / (decimal)BaselineFileCount * 100
|
||||
: Added.Length > 0 ? 100m : 0m;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this facet has any drift.
|
||||
/// </summary>
|
||||
public bool HasDrift => TotalChanges > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a no-drift instance for a facet.
|
||||
/// </summary>
|
||||
public static FacetDrift NoDrift(string facetId, int baselineFileCount) => new()
|
||||
{
|
||||
FacetId = facetId,
|
||||
Added = [],
|
||||
Removed = [],
|
||||
Modified = [],
|
||||
DriftScore = 0m,
|
||||
QuotaVerdict = QuotaVerdict.Ok,
|
||||
BaselineFileCount = baselineFileCount
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggregated drift report for all facets in an image.
|
||||
/// </summary>
|
||||
public sealed record FacetDriftReport
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the image digest analyzed.
|
||||
/// </summary>
|
||||
public required string ImageDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the baseline seal used for comparison.
|
||||
/// </summary>
|
||||
public required string BaselineSealId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets when the analysis was performed.
|
||||
/// </summary>
|
||||
public required DateTimeOffset AnalyzedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the per-facet drift results.
|
||||
/// </summary>
|
||||
public required ImmutableArray<FacetDrift> FacetDrifts { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the overall verdict (worst of all facets).
|
||||
/// </summary>
|
||||
public required QuotaVerdict OverallVerdict { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total files changed across all facets.
|
||||
/// </summary>
|
||||
public int TotalChangedFiles => FacetDrifts.Sum(d => d.TotalChanges);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the facets with any drift.
|
||||
/// </summary>
|
||||
public IEnumerable<FacetDrift> DriftedFacets => FacetDrifts.Where(d => d.HasDrift);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the facets with quota violations.
|
||||
/// </summary>
|
||||
public IEnumerable<FacetDrift> QuotaViolations =>
|
||||
FacetDrifts.Where(d => d.QuotaVerdict is QuotaVerdict.Warning
|
||||
or QuotaVerdict.Blocked
|
||||
or QuotaVerdict.RequiresVex);
|
||||
}
|
||||
Reference in New Issue
Block a user