partly or unimplemented features - now implemented

This commit is contained in:
master
2026-02-09 08:53:51 +02:00
parent 1bf6bbf395
commit 4bdc298ec1
674 changed files with 90194 additions and 2271 deletions

View File

@@ -0,0 +1,174 @@
using System.Security.Cryptography;
using System.Text;
namespace StellaOps.AdvisoryAI.Explanation;
/// <summary>
/// Runtime signal emitted by Zastava or compatible observers.
/// </summary>
public sealed record CompanionRuntimeSignal
{
public required string Source { get; init; }
public required string Signal { get; init; }
public required string Value { get; init; }
public string? Path { get; init; }
public double Confidence { get; init; }
}
/// <summary>
/// Request for Codex/Zastava companion explanation composition.
/// </summary>
public sealed record CodexCompanionRequest
{
public required ExplanationRequest ExplanationRequest { get; init; }
public IReadOnlyList<CompanionRuntimeSignal> RuntimeSignals { get; init; } = Array.Empty<CompanionRuntimeSignal>();
}
/// <summary>
/// Response containing base explanation plus deterministic runtime highlights.
/// </summary>
public sealed record CodexCompanionResponse
{
public required string CompanionId { get; init; }
public required string CompanionHash { get; init; }
public required ExplanationResult Explanation { get; init; }
public required ExplanationSummary CompanionSummary { get; init; }
public required IReadOnlyList<CompanionRuntimeSignal> RuntimeHighlights { get; init; }
}
/// <summary>
/// Service that combines explanation output with Zastava runtime signals.
/// </summary>
public interface ICodexCompanionService
{
Task<CodexCompanionResponse> GenerateAsync(
CodexCompanionRequest request,
CancellationToken cancellationToken = default);
}
/// <summary>
/// Deterministic implementation of the Codex/Zastava companion.
/// </summary>
public sealed class CodexZastavaCompanionService : ICodexCompanionService
{
private readonly IExplanationGenerator _explanationGenerator;
public CodexZastavaCompanionService(IExplanationGenerator explanationGenerator)
{
_explanationGenerator = explanationGenerator ?? throw new ArgumentNullException(nameof(explanationGenerator));
}
public async Task<CodexCompanionResponse> GenerateAsync(
CodexCompanionRequest request,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(request);
ArgumentNullException.ThrowIfNull(request.ExplanationRequest);
var explanation = await _explanationGenerator
.GenerateAsync(request.ExplanationRequest, cancellationToken)
.ConfigureAwait(false);
var highlights = NormalizeSignals(request.RuntimeSignals)
.Take(5)
.ToArray();
var companionSummary = BuildCompanionSummary(explanation.Summary, highlights);
var companionHash = ComputeCompanionHash(explanation.OutputHash, highlights);
return new CodexCompanionResponse
{
CompanionId = $"companion:{companionHash}",
CompanionHash = companionHash,
Explanation = explanation,
CompanionSummary = companionSummary,
RuntimeHighlights = highlights,
};
}
private static IReadOnlyList<CompanionRuntimeSignal> NormalizeSignals(
IReadOnlyList<CompanionRuntimeSignal> signals)
{
if (signals.Count == 0)
{
return Array.Empty<CompanionRuntimeSignal>();
}
var deduplicated = new Dictionary<string, CompanionRuntimeSignal>(StringComparer.Ordinal);
foreach (var signal in signals)
{
if (string.IsNullOrWhiteSpace(signal.Source) ||
string.IsNullOrWhiteSpace(signal.Signal) ||
string.IsNullOrWhiteSpace(signal.Value))
{
continue;
}
var normalized = new CompanionRuntimeSignal
{
Source = signal.Source.Trim(),
Signal = signal.Signal.Trim(),
Value = signal.Value.Trim(),
Path = string.IsNullOrWhiteSpace(signal.Path) ? null : signal.Path.Trim(),
Confidence = Math.Clamp(signal.Confidence, 0, 1),
};
var key = string.Join("|", normalized.Source, normalized.Signal, normalized.Value, normalized.Path ?? string.Empty);
if (deduplicated.TryGetValue(key, out var existing))
{
deduplicated[key] = normalized.Confidence >= existing.Confidence
? normalized
: existing;
}
else
{
deduplicated[key] = normalized;
}
}
return deduplicated.Values
.OrderByDescending(static value => value.Confidence)
.ThenBy(static value => value.Source, StringComparer.Ordinal)
.ThenBy(static value => value.Signal, StringComparer.Ordinal)
.ThenBy(static value => value.Value, StringComparer.Ordinal)
.ThenBy(static value => value.Path, StringComparer.Ordinal)
.ToArray();
}
private static ExplanationSummary BuildCompanionSummary(
ExplanationSummary baseSummary,
IReadOnlyList<CompanionRuntimeSignal> highlights)
{
var line2 = highlights.Count == 0
? "No Zastava runtime signals were provided; verdict is based on static evidence."
: $"Runtime signal {highlights[0].Source}/{highlights[0].Signal} indicates '{highlights[0].Value}'.";
return new ExplanationSummary
{
Line1 = $"Companion: {baseSummary.Line1}",
Line2 = line2,
Line3 = baseSummary.Line3,
};
}
private static string ComputeCompanionHash(
string explanationOutputHash,
IReadOnlyList<CompanionRuntimeSignal> highlights)
{
var builder = new StringBuilder();
builder.Append(explanationOutputHash).Append('\n');
foreach (var highlight in highlights)
{
builder.Append(highlight.Source).Append('|')
.Append(highlight.Signal).Append('|')
.Append(highlight.Value).Append('|')
.Append(highlight.Path ?? string.Empty).Append('|')
.Append(highlight.Confidence.ToString("F4", System.Globalization.CultureInfo.InvariantCulture))
.Append('\n');
}
var hash = SHA256.HashData(Encoding.UTF8.GetBytes(builder.ToString()));
return Convert.ToHexString(hash).ToLowerInvariant();
}
}

View File

@@ -11,3 +11,6 @@ Source of truth: `docs/implplan/SPRINT_20260113_005_ADVISORYAI_controlled_conver
| AIAI-CHAT-AUDIT-0001 | DONE | Persist chat audit tables and logger. |
| AUDIT-TESTGAP-ADVISORYAI-0001 | DONE | Added worker and unified plugin adapter tests. |
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
| SPRINT_20260208_003-CORE | DONE | Codex/Zastava companion core service for deterministic runtime-aware explanation composition. |