sprints work
This commit is contained in:
153
src/__Libraries/StellaOps.Resolver/DeterministicResolver.cs
Normal file
153
src/__Libraries/StellaOps.Resolver/DeterministicResolver.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* DeterministicResolver - Core Implementation
|
||||
* Sprint: SPRINT_9100_0001_0001 (Core Resolver Package)
|
||||
* Tasks: RESOLVER-9100-010, RESOLVER-9100-011, RESOLVER-9100-012, RESOLVER-9100-013, RESOLVER-9100-014
|
||||
*
|
||||
* Main resolver implementation providing:
|
||||
* - Deterministic graph canonicalization
|
||||
* - Ordered traversal
|
||||
* - Per-node evaluation
|
||||
* - Digest computation
|
||||
*/
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace StellaOps.Resolver;
|
||||
|
||||
/// <summary>
|
||||
/// Deterministic resolver that guarantees reproducible results.
|
||||
/// </summary>
|
||||
public sealed class DeterministicResolver : IDeterministicResolver
|
||||
{
|
||||
private readonly Policy _policy;
|
||||
private readonly IGraphOrderer _orderer;
|
||||
private readonly ITrustLatticeEvaluator _evaluator;
|
||||
private readonly IFinalDigestComputer _digestComputer;
|
||||
private readonly IGraphValidator _validator;
|
||||
private readonly string _version;
|
||||
|
||||
public DeterministicResolver(
|
||||
Policy policy,
|
||||
IGraphOrderer orderer,
|
||||
ITrustLatticeEvaluator evaluator,
|
||||
IFinalDigestComputer? digestComputer = null,
|
||||
IGraphValidator? validator = null,
|
||||
string? version = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(policy);
|
||||
ArgumentNullException.ThrowIfNull(orderer);
|
||||
ArgumentNullException.ThrowIfNull(evaluator);
|
||||
|
||||
_policy = policy;
|
||||
_orderer = orderer;
|
||||
_evaluator = evaluator;
|
||||
_digestComputer = digestComputer ?? new Sha256FinalDigestComputer();
|
||||
_validator = validator ?? new DefaultGraphValidator();
|
||||
_version = version ?? "1.0.0";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ResolutionResult Run(EvidenceGraph graph)
|
||||
=> Run(graph, DateTimeOffset.UtcNow);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ResolutionResult Run(EvidenceGraph graph, DateTimeOffset resolvedAt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(graph);
|
||||
|
||||
// Phase 1: Validate graph
|
||||
var validationResult = _validator.Validate(graph);
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
throw new InvalidGraphException(validationResult);
|
||||
}
|
||||
|
||||
// Phase 2: Compute traversal order
|
||||
var traversalOrder = _orderer.OrderNodes(graph);
|
||||
|
||||
// Phase 3: Evaluate each node in order
|
||||
var verdicts = new Dictionary<NodeId, Verdict>();
|
||||
var verdictList = new List<Verdict>();
|
||||
|
||||
for (var i = 0; i < traversalOrder.Count; i++)
|
||||
{
|
||||
var nodeId = traversalOrder[i];
|
||||
var node = graph.GetNode(nodeId);
|
||||
|
||||
if (node is null)
|
||||
{
|
||||
// Node referenced but not in graph - this should be caught by validation
|
||||
continue;
|
||||
}
|
||||
|
||||
// Gather inbound evidence (edges where Dst == nodeId)
|
||||
var inboundEdges = GatherInboundEvidence(graph, nodeId);
|
||||
|
||||
// Build predecessor verdicts dictionary
|
||||
var predecessorVerdicts = new Dictionary<NodeId, Verdict>();
|
||||
foreach (var edge in inboundEdges)
|
||||
{
|
||||
if (verdicts.TryGetValue(edge.Src, out var srcVerdict))
|
||||
{
|
||||
predecessorVerdicts[edge.Src] = srcVerdict;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate pure (no IO)
|
||||
var verdict = EvaluatePure(node, inboundEdges, _policy, predecessorVerdicts, i);
|
||||
|
||||
verdicts[nodeId] = verdict;
|
||||
verdictList.Add(verdict);
|
||||
}
|
||||
|
||||
// Phase 4: Compute final digest
|
||||
var verdictEntries = verdictList
|
||||
.Select(v => new VerdictDigestEntry(v.Node.Value, v.VerdictDigest))
|
||||
.ToImmutableArray();
|
||||
|
||||
var digestInput = new DigestInput(
|
||||
graph.GraphDigest,
|
||||
_policy.Digest,
|
||||
verdictEntries);
|
||||
|
||||
var finalDigest = _digestComputer.Compute(digestInput);
|
||||
|
||||
return new ResolutionResult
|
||||
{
|
||||
TraversalSequence = traversalOrder.ToImmutableArray(),
|
||||
Verdicts = verdictList.ToImmutableArray(),
|
||||
GraphDigest = graph.GraphDigest,
|
||||
PolicyDigest = _policy.Digest,
|
||||
FinalDigest = finalDigest,
|
||||
ResolvedAt = resolvedAt,
|
||||
ResolverVersion = _version
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gathers all inbound edges for a node (edges where Dst == nodeId).
|
||||
/// </summary>
|
||||
private static IReadOnlyList<Edge> GatherInboundEvidence(EvidenceGraph graph, NodeId nodeId)
|
||||
{
|
||||
return graph.Edges
|
||||
.Where(e => e.Dst == nodeId)
|
||||
.OrderBy(e => e.Id) // Deterministic ordering
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pure evaluation function - no IO allowed.
|
||||
/// </summary>
|
||||
private Verdict EvaluatePure(
|
||||
Node node,
|
||||
IReadOnlyList<Edge> inboundEdges,
|
||||
Policy policy,
|
||||
IReadOnlyDictionary<NodeId, Verdict> predecessorVerdicts,
|
||||
int traversalIndex)
|
||||
{
|
||||
return _evaluator.Evaluate(node, inboundEdges, policy, predecessorVerdicts) with
|
||||
{
|
||||
TraversalIndex = traversalIndex
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user