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
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-24 07:52:25 +02:00
parent 5970f0d9bd
commit 150b3730ef
215 changed files with 8119 additions and 740 deletions

View File

@@ -877,6 +877,202 @@ public sealed class CommandHandlersTests
}
}
[Fact]
public async Task HandleAdviseRunAsync_WritesMarkdownWithCitations_ForExplain()
{
var originalExit = Environment.ExitCode;
var originalConsole = AnsiConsole.Console;
var testConsole = new TestConsole();
try
{
Environment.ExitCode = 0;
AnsiConsole.Console = testConsole;
var planResponse = new AdvisoryPipelinePlanResponseModel
{
TaskType = "Conflict",
CacheKey = "plan-conflict",
PromptTemplate = "prompts/advisory/conflict.liquid",
Budget = new AdvisoryTaskBudgetModel
{
PromptTokens = 128,
CompletionTokens = 64
},
Chunks = Array.Empty<PipelineChunkSummaryModel>(),
Vectors = Array.Empty<PipelineVectorSummaryModel>(),
Metadata = new Dictionary<string, string>()
};
var outputResponse = new AdvisoryPipelineOutputModel
{
CacheKey = planResponse.CacheKey,
TaskType = planResponse.TaskType,
Profile = "default",
Prompt = "Sanitized prompt",
Response = "Rendered conflict body.",
Citations = new[]
{
new AdvisoryOutputCitationModel { Index = 1, DocumentId = "doc-42", ChunkId = "chunk-42" }
},
Metadata = new Dictionary<string, string>(),
Guardrail = new AdvisoryOutputGuardrailModel
{
Blocked = false,
SanitizedPrompt = "Sanitized prompt",
Violations = Array.Empty<AdvisoryOutputGuardrailViolationModel>(),
Metadata = new Dictionary<string, string>()
},
Provenance = new AdvisoryOutputProvenanceModel
{
InputDigest = "sha256:conflict-in",
OutputHash = "sha256:conflict-out",
Signatures = Array.Empty<string>()
},
GeneratedAtUtc = DateTimeOffset.Parse("2025-11-06T12:00:00Z", CultureInfo.InvariantCulture),
PlanFromCache = false
};
var backend = new StubBackendClient(new JobTriggerResult(true, "ok", null, null))
{
AdvisoryPlanResponse = planResponse,
AdvisoryOutputResponse = outputResponse
};
var provider = BuildServiceProvider(backend);
var outputPath = Path.GetTempFileName();
await CommandHandlers.HandleAdviseRunAsync(
provider,
AdvisoryAiTaskType.Conflict,
"ADV-42",
null,
null,
null,
"default",
Array.Empty<string>(),
forceRefresh: false,
timeoutSeconds: 0,
outputFormat: AdvisoryOutputFormat.Markdown,
outputPath: outputPath,
verbose: false,
cancellationToken: CancellationToken.None);
var markdown = await File.ReadAllTextAsync(outputPath);
Assert.Contains("Conflict", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("Rendered conflict body", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("doc-42", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("chunk-42", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("Citations", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Equal(0, Environment.ExitCode);
Assert.Contains("Conflict", testConsole.Output, StringComparison.OrdinalIgnoreCase);
Assert.Equal(AdvisoryAiTaskType.Conflict, backend.AdvisoryPlanRequests.Last().TaskType);
}
finally
{
AnsiConsole.Console = originalConsole;
Environment.ExitCode = originalExit;
}
}
[Fact]
public async Task HandleAdviseRunAsync_WritesMarkdownWithCitations_ForRemediation()
{
var originalExit = Environment.ExitCode;
var originalConsole = AnsiConsole.Console;
var testConsole = new TestConsole();
try
{
Environment.ExitCode = 0;
AnsiConsole.Console = testConsole;
var planResponse = new AdvisoryPipelinePlanResponseModel
{
TaskType = "Remediation",
CacheKey = "plan-remediation",
PromptTemplate = "prompts/advisory/remediation.liquid",
Budget = new AdvisoryTaskBudgetModel
{
PromptTokens = 192,
CompletionTokens = 96
},
Chunks = Array.Empty<PipelineChunkSummaryModel>(),
Vectors = Array.Empty<PipelineVectorSummaryModel>(),
Metadata = new Dictionary<string, string>()
};
var outputResponse = new AdvisoryPipelineOutputModel
{
CacheKey = planResponse.CacheKey,
TaskType = planResponse.TaskType,
Profile = "default",
Prompt = "Sanitized prompt",
Response = "Rendered remediation body.",
Citations = new[]
{
new AdvisoryOutputCitationModel { Index = 1, DocumentId = "doc-77", ChunkId = "chunk-77" }
},
Metadata = new Dictionary<string, string>(),
Guardrail = new AdvisoryOutputGuardrailModel
{
Blocked = false,
SanitizedPrompt = "Sanitized prompt",
Violations = Array.Empty<AdvisoryOutputGuardrailViolationModel>(),
Metadata = new Dictionary<string, string>()
},
Provenance = new AdvisoryOutputProvenanceModel
{
InputDigest = "sha256:remediation-in",
OutputHash = "sha256:remediation-out",
Signatures = Array.Empty<string>()
},
GeneratedAtUtc = DateTimeOffset.Parse("2025-11-06T12:00:00Z", CultureInfo.InvariantCulture),
PlanFromCache = false
};
var backend = new StubBackendClient(new JobTriggerResult(true, "ok", null, null))
{
AdvisoryPlanResponse = planResponse,
AdvisoryOutputResponse = outputResponse
};
var provider = BuildServiceProvider(backend);
var outputPath = Path.GetTempFileName();
await CommandHandlers.HandleAdviseRunAsync(
provider,
AdvisoryAiTaskType.Remediation,
"ADV-77",
null,
null,
null,
"default",
Array.Empty<string>(),
forceRefresh: false,
timeoutSeconds: 0,
outputFormat: AdvisoryOutputFormat.Markdown,
outputPath: outputPath,
verbose: false,
cancellationToken: CancellationToken.None);
var markdown = await File.ReadAllTextAsync(outputPath);
Assert.Contains("Remediation", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("Rendered remediation body", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("doc-77", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("chunk-77", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Contains("Citations", markdown, StringComparison.OrdinalIgnoreCase);
Assert.Equal(0, Environment.ExitCode);
Assert.Contains("Remediation", testConsole.Output, StringComparison.OrdinalIgnoreCase);
Assert.Equal(AdvisoryAiTaskType.Remediation, backend.AdvisoryPlanRequests.Last().TaskType);
}
finally
{
AnsiConsole.Console = originalConsole;
Environment.ExitCode = originalExit;
}
}
[Fact]
public async Task HandleAdviseRunAsync_ReturnsGuardrailExitCodeOnBlock()
{
@@ -3776,6 +3972,7 @@ spec:
Array.Empty<TaskRunnerSimulationOutput>(),
false);
public Exception? TaskRunnerSimulationException { get; set; }
public OfflineKitStatus? OfflineStatus { get; set; }
public PolicyActivationResult ActivationResult { get; set; } = new PolicyActivationResult(
"activated",
new PolicyActivationRevision(
@@ -3966,7 +4163,19 @@ spec:
=> throw new NotSupportedException();
public Task<OfflineKitStatus> GetOfflineKitStatusAsync(CancellationToken cancellationToken)
=> throw new NotSupportedException();
{
return Task.FromResult(OfflineStatus ?? new OfflineKitStatus(
null,
null,
null,
false,
null,
null,
null,
null,
null,
Array.Empty<OfflineKitComponentStatus>()));
}
public Task<EntryTraceResponseModel?> GetEntryTraceAsync(string scanId, CancellationToken cancellationToken)
{