up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-01 21:16:22 +02:00
parent c11d87d252
commit 909d9b6220
208 changed files with 860954 additions and 832 deletions

View File

@@ -96,7 +96,7 @@ public sealed class EntryTraceRuntimeReconciler
terminalBuilder[index] = terminalBuilder[index] with { Confidence = confidence.Score };
}
diagnostics.Add(BuildDiagnostic(confidence, plan.TerminalPath));
diagnostics.Add(BuildDiagnostic(confidence, plan.TerminalPath, procGraph, match?.Process));
}
// Update any terminals that were not tied to plans.
@@ -242,7 +242,7 @@ public sealed class EntryTraceRuntimeReconciler
return new ConfidenceResult(60d, ConfidenceLevel.Low, runtimePath);
}
private static EntryTraceDiagnostic BuildDiagnostic(ConfidenceResult result, string predictedPath)
private EntryTraceDiagnostic BuildDiagnostic(ConfidenceResult result, string predictedPath, ProcGraph procGraph, ProcProcess? process)
{
var runtimePath = string.IsNullOrWhiteSpace(result.RuntimePath) ? "<unknown>" : result.RuntimePath;
var severity = result.Level == ConfidenceLevel.High
@@ -251,10 +251,18 @@ public sealed class EntryTraceRuntimeReconciler
var reason = result.Level == ConfidenceLevel.High
? EntryTraceUnknownReason.RuntimeMatch
: EntryTraceUnknownReason.RuntimeMismatch;
var chain = process is null ? null : BuildProcessChain(procGraph, process.Value);
var message = result.Level == ConfidenceLevel.High
? $"Runtime process '{runtimePath}' matches EntryTrace prediction '{predictedPath}'."
: $"Runtime process '{runtimePath}' diverges from EntryTrace prediction '{predictedPath}'.";
if (!string.IsNullOrWhiteSpace(chain))
{
message += $" Runtime chain: {chain}.";
}
return new EntryTraceDiagnostic(
severity,
reason,
@@ -269,6 +277,50 @@ public sealed class EntryTraceRuntimeReconciler
return command.Length > 0 && WrapperNames.Contains(command);
}
private static string? BuildProcessChain(ProcGraph graph, ProcProcess process)
{
var chain = new List<string>();
var current = process;
while (true)
{
var display = string.IsNullOrWhiteSpace(current.ExecutablePath)
? current.CommandName
: current.ExecutablePath;
if (string.IsNullOrWhiteSpace(display))
{
display = current.CommandName;
}
chain.Add(display);
if (current.ParentPid == current.Pid || current.ParentPid == 0 || !graph.Processes.TryGetValue(current.ParentPid, out var parent))
{
break;
}
current = parent;
}
chain.Reverse();
// Collapse adjacent wrappers to a single token for readability.
var collapsed = new List<string>(chain.Count);
foreach (var segment in chain)
{
var name = Path.GetFileName(segment);
var isWrapper = WrapperNames.Contains(name);
if (isWrapper && collapsed.Count > 0 && WrapperNames.Contains(Path.GetFileName(collapsed[^1])))
{
continue; // skip duplicate adjacent wrapper entries
}
collapsed.Add(segment);
}
return collapsed.Count == 0 ? null : string.Join(" -> ", collapsed);
}
private static string GetCommandName(ProcProcess process)
{
if (!string.IsNullOrWhiteSpace(process.CommandName))