Files
git.stella-ops.org/src/Policy/StellaOps.PolicyDsl/AiCodeGuardSignalContextExtensions.cs

167 lines
6.8 KiB
C#

// -----------------------------------------------------------------------------
// AiCodeGuardSignalContextExtensions.cs
// Sprint: SPRINT_20260112_010_POLICY_ai_code_guard_policy
// Task: POLICY-AIGUARD-001/005 - AI Code Guard signal context integration
// -----------------------------------------------------------------------------
using StellaOps.Policy.AiCodeGuard;
namespace StellaOps.PolicyDsl;
/// <summary>
/// Extension methods for integrating AI Code Guard evidence with PolicyDsl SignalContext.
/// </summary>
public static class AiCodeGuardSignalContextExtensions
{
/// <summary>
/// Adds AI Code Guard evidence signals to the signal context.
/// </summary>
/// <param name="context">The signal context.</param>
/// <param name="evidenceContext">The AI Code Guard evidence context.</param>
/// <returns>The signal context for chaining.</returns>
public static SignalContext WithAiCodeGuardEvidence(
this SignalContext context,
AiCodeGuardEvidenceContext evidenceContext)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(evidenceContext);
// Add flat signals
var signals = AiCodeGuardSignalBinder.BindToSignals(evidenceContext);
foreach (var (name, value) in signals)
{
context.SetSignal(name, value);
}
// Add nested object for member access (guard.severity.high, etc.)
var nested = AiCodeGuardSignalBinder.BindToNestedObject(evidenceContext);
context.SetSignal("guard", nested);
// Add policy recommendation
context.SetSignal("guard.recommendation", AiCodeGuardSignalBinder.GetRecommendation(evidenceContext));
// Add explain trace for deterministic auditing
context.SetSignal("guard.explain_trace", AiCodeGuardSignalBinder.CreateExplainTrace(evidenceContext));
return context;
}
/// <summary>
/// Adds AI Code Guard evidence signals to the signal context builder.
/// </summary>
/// <param name="builder">The signal context builder.</param>
/// <param name="evidenceContext">The AI Code Guard evidence context.</param>
/// <returns>The builder for chaining.</returns>
public static SignalContextBuilder WithAiCodeGuardEvidence(
this SignalContextBuilder builder,
AiCodeGuardEvidenceContext evidenceContext)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(evidenceContext);
// Add flat signals
var signals = AiCodeGuardSignalBinder.BindToSignals(evidenceContext);
foreach (var (name, value) in signals)
{
builder.WithSignal(name, value);
}
// Add nested object for member access
var nested = AiCodeGuardSignalBinder.BindToNestedObject(evidenceContext);
builder.WithSignal("guard", nested);
// Add policy recommendation
builder.WithSignal("guard.recommendation", AiCodeGuardSignalBinder.GetRecommendation(evidenceContext));
// Add explain trace
builder.WithSignal("guard.explain_trace", AiCodeGuardSignalBinder.CreateExplainTrace(evidenceContext));
return builder;
}
/// <summary>
/// Adds AI Code Guard evidence signals from a provider.
/// </summary>
/// <param name="builder">The signal context builder.</param>
/// <param name="provider">The AI Code Guard evidence provider.</param>
/// <returns>The builder for chaining.</returns>
public static SignalContextBuilder WithAiCodeGuardEvidence(
this SignalContextBuilder builder,
IAiCodeGuardEvidenceProvider provider)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(provider);
var context = new AiCodeGuardEvidenceContext(provider);
return builder.WithAiCodeGuardEvidence(context);
}
/// <summary>
/// Creates a signal context builder with AI Code Guard evidence.
/// </summary>
/// <param name="evidenceContext">The AI Code Guard evidence context.</param>
/// <returns>A new builder with guard signals.</returns>
public static SignalContextBuilder CreateBuilderWithGuardEvidence(AiCodeGuardEvidenceContext evidenceContext)
{
return SignalContext.Builder().WithAiCodeGuardEvidence(evidenceContext);
}
/// <summary>
/// Creates a signal context with AI Code Guard evidence.
/// </summary>
/// <param name="evidenceContext">The AI Code Guard evidence context.</param>
/// <returns>A new signal context with guard signals.</returns>
public static SignalContext CreateContextWithGuardEvidence(AiCodeGuardEvidenceContext evidenceContext)
{
return CreateBuilderWithGuardEvidence(evidenceContext).Build();
}
/// <summary>
/// Adds simplified AI Code Guard result signals for quick checks.
/// This is useful when you have analysis results but not a full evidence provider.
/// </summary>
/// <param name="builder">The signal context builder.</param>
/// <param name="status">The verdict status.</param>
/// <param name="totalFindings">Total finding count.</param>
/// <param name="criticalCount">Critical severity count.</param>
/// <param name="highCount">High severity count.</param>
/// <param name="mediumCount">Medium severity count.</param>
/// <param name="aiPercentage">Optional AI-generated percentage.</param>
/// <returns>The builder for chaining.</returns>
public static SignalContextBuilder WithAiCodeGuardResult(
this SignalContextBuilder builder,
string status,
int totalFindings,
int criticalCount = 0,
int highCount = 0,
int mediumCount = 0,
double? aiPercentage = null)
{
ArgumentNullException.ThrowIfNull(builder);
builder.WithSignal("guard.verdict", status.ToLowerInvariant());
builder.WithSignal("guard.count", totalFindings);
builder.WithSignal("guard.has_finding", totalFindings > 0);
builder.WithSignal("guard.severity.critical", criticalCount > 0);
builder.WithSignal("guard.severity.critical_count", criticalCount);
builder.WithSignal("guard.severity.high", highCount > 0);
builder.WithSignal("guard.severity.high_count", highCount);
builder.WithSignal("guard.severity.medium", mediumCount > 0);
builder.WithSignal("guard.severity.medium_count", mediumCount);
builder.WithSignal("guard.ai_percentage", aiPercentage);
// Derive recommendation
var recommendation = status.ToLowerInvariant() switch
{
"pass" => "allow",
"passwithwarnings" or "pass_with_warnings" => "review",
"fail" => "block",
"error" => "block",
_ => "review"
};
builder.WithSignal("guard.recommendation", recommendation);
return builder;
}
}