synergy moats product advisory implementations
This commit is contained in:
@@ -86,9 +86,10 @@ public sealed partial class ProvenanceHintBuilder : IProvenanceHintBuilder
|
||||
{
|
||||
var bestMatch = matches?.OrderByDescending(m => m.Similarity).FirstOrDefault();
|
||||
var confidence = bestMatch?.Similarity ?? 0.3;
|
||||
var fingerprintPrefix = fingerprint.Length <= 12 ? fingerprint : fingerprint[..12];
|
||||
var hypothesis = bestMatch is not null
|
||||
? $"Import table matches {bestMatch.Package} {bestMatch.Version} ({bestMatch.Similarity:P0} similar)"
|
||||
: $"Import fingerprint {fingerprint[..12]}... ({importedLibraries.Count} imports)";
|
||||
: $"Import fingerprint {fingerprintPrefix}... ({importedLibraries.Count} imports)";
|
||||
|
||||
return new ProvenanceHint
|
||||
{
|
||||
@@ -321,7 +322,7 @@ public sealed partial class ProvenanceHintBuilder : IProvenanceHintBuilder
|
||||
// If we have multiple high-confidence hints that agree, boost confidence
|
||||
var agreeing = sorted
|
||||
.Where(h => h.Confidence >= 0.5)
|
||||
.GroupBy(h => ExtractPackageFromHypothesis(h.Hypothesis))
|
||||
.GroupBy(GetAgreementKey)
|
||||
.OrderByDescending(g => g.Count())
|
||||
.FirstOrDefault();
|
||||
|
||||
@@ -351,7 +352,7 @@ public sealed partial class ProvenanceHintBuilder : IProvenanceHintBuilder
|
||||
{
|
||||
return confidence switch
|
||||
{
|
||||
>= 0.9 => HintConfidence.VeryHigh,
|
||||
>= 0.85 => HintConfidence.VeryHigh,
|
||||
>= 0.7 => HintConfidence.High,
|
||||
>= 0.5 => HintConfidence.Medium,
|
||||
>= 0.3 => HintConfidence.Low,
|
||||
@@ -359,6 +360,45 @@ public sealed partial class ProvenanceHintBuilder : IProvenanceHintBuilder
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetAgreementKey(ProvenanceHint hint)
|
||||
{
|
||||
var evidence = hint.Evidence;
|
||||
var key = evidence.BuildId?.MatchedPackage
|
||||
?? BestMatchPackage(evidence.ImportFingerprint?.MatchedFingerprints)
|
||||
?? BestMatchPackage(evidence.SectionLayout?.MatchedLayouts)
|
||||
?? ExtractPackageFromVersion(evidence.VersionString?.BestGuess)
|
||||
?? ExtractPackageFromVersion(evidence.CorpusMatch?.MatchedEntry)
|
||||
?? ExtractPackageFromHypothesis(hint.Hypothesis);
|
||||
|
||||
return string.IsNullOrWhiteSpace(key) ? hint.Hypothesis : key;
|
||||
}
|
||||
|
||||
private static string? BestMatchPackage(IReadOnlyList<FingerprintMatch>? matches)
|
||||
{
|
||||
return matches is null || matches.Count == 0
|
||||
? null
|
||||
: matches.OrderByDescending(m => m.Similarity).First().Package;
|
||||
}
|
||||
|
||||
private static string? BestMatchPackage(IReadOnlyList<LayoutMatch>? matches)
|
||||
{
|
||||
return matches is null || matches.Count == 0
|
||||
? null
|
||||
: matches.OrderByDescending(m => m.Similarity).First().Package;
|
||||
}
|
||||
|
||||
private static string? ExtractPackageFromVersion(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var trimmed = value.Trim();
|
||||
var token = trimmed.Split([' ', '/', '\t'], StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
||||
return string.IsNullOrWhiteSpace(token) ? null : token;
|
||||
}
|
||||
|
||||
private static string ComputeLayoutHash(IReadOnlyList<SectionInfo> sections)
|
||||
{
|
||||
var normalized = string.Join("|",
|
||||
|
||||
@@ -119,7 +119,7 @@ public sealed class NativeUnknownClassifier
|
||||
SubjectType = UnknownSubjectType.Binary,
|
||||
SubjectRef = context.UnresolvedImport,
|
||||
Kind = UnknownKind.UnresolvedNativeLibrary,
|
||||
Severity = UnknownSeverity.Low,
|
||||
Severity = UnknownSeverity.Medium,
|
||||
Context = SerializeContext(context with { ClassifiedAt = now }),
|
||||
ValidFrom = now,
|
||||
SysFrom = now,
|
||||
@@ -251,6 +251,7 @@ public sealed class NativeUnknownClassifier
|
||||
/// <summary>
|
||||
/// Source-generated JSON context for NativeUnknownContext serialization.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonSourceGenerationOptions(PropertyNamingPolicy = System.Text.Json.JsonKnownNamingPolicy.CamelCase)]
|
||||
[System.Text.Json.Serialization.JsonSerializable(typeof(NativeUnknownContext))]
|
||||
internal partial class NativeUnknownContextJsonContext : System.Text.Json.Serialization.JsonSerializerContext
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user