CLI entry trace warning capture and sprint status sync
This commit is contained in:
@@ -44,10 +44,13 @@ Follow the sprint files below in order. Update task status in both `SPRINTS` and
|
||||
> 2025-11-03: MERGE-LNM-21-001 marked DONE – published `docs/migration/no-merge.md` with rollout, backfill, validation, and rollback guidance for the LNM cutover.
|
||||
> 2025-11-04: GRAPH-INDEX-28-011 marked DONE (Graph Indexer Guild) – SBOM ingest DI wiring now emits graph snapshots by default, snapshot root configurable via `STELLAOPS_GRAPH_SNAPSHOT_DIR`, and Graph Indexer tests exercised with Mongo URI guidance.
|
||||
> 2025-11-06: MERGE-LNM-21-002 remains DOING (BE-Merge) – default-off merge DI + job gating landed, but Concelier WebService ingest/mirror tests are failing; guard and migration fixes pending before completion.
|
||||
> 2025-11-06: TASKRUN-43-001 marked DONE (Task Runner Guild) – approvals resume API now requeues packs, plan snapshots persisted, and filesystem artifact uploader stores manifests/files for offline review.
|
||||
> 2025-11-06: CLI-POLICY-23-005 marked DONE (DevEx/CLI Guild) – policy activate CLI verifies scheduling/approval flow, Spectre console fallbacks emit warnings offline, and full CLI suite passes against local feeds.
|
||||
> 2025-11-03: DOCS-LNM-22-008 moved to DOING (Docs Guild, DevOps Guild) – aligning migration playbook structure and readiness checklist.
|
||||
> 2025-11-03: DOCS-LNM-22-008 marked DONE – `/docs/migration/no-merge.md` published for DevOps/Export Center planning with checklist for cutover readiness.
|
||||
> 2025-11-03: SCHED-CONSOLE-27-001 marked DONE (Scheduler WebService Guild, Policy Registry Guild) – policy simulation endpoints now emit SSE retry/heartbeat, enforce metadata normalization, support Mongo-backed integration, and ship auth/stream coverage.
|
||||
> 2025-11-03: SCHED-CONSOLE-27-002 moved to DOING (Scheduler WebService Guild, Observability Guild) – wiring policy simulation telemetry endpoints, OTEL metrics, and Registry webhooks on completion/failure.
|
||||
> 2025-11-06: SCHED-CONSOLE-27-002 marked DONE (Scheduler WebService Guild, Observability Guild) – telemetry endpoints emit queue/latency metrics, registry webhooks documented, and impact preview fixtures restored.
|
||||
> 2025-11-03: FEEDCONN-KISA-02-008 moved to DOING (BE-Conn-KISA, Models) – starting Hangul firmware range normalization and provenance mapping for KISA advisories.
|
||||
> 2025-11-03: FEEDCONN-KISA-02-008 progress – SemVer normalization wired through KISA mapper with provenance slugs, exclusive marker handling, and fresh connector tests for `이상`/`미만`/`초과` scenarios plus non-numeric fallback; follow-up review queued for additional phrasing coverage before closing. Captured current detail pages via `scripts/kisa_capture_html.py` so offline HTML is available under `seed-data/kisa/html/`.
|
||||
> 2025-11-03: FEEDCONN-ICSCISA-02-012 marked DONE (BE-Conn-ICS-CISA) – ICS CISA connector now emits semver-aware affected.version ranges with `ics-cisa` provenance, SourceFetchService RSS fallback passes the AOC guard, and the Fetch/Parse/Map integration test is green.
|
||||
|
||||
@@ -124,7 +124,7 @@ Task ID | State | Task description | Owners (Source)
|
||||
--- | --- | --- | ---
|
||||
TASKRUN-41-001 | TODO | Bootstrap service, define migrations for `pack_runs`, `pack_run_logs`, `pack_artifacts`, implement run API (create/get/log stream), local executor, approvals pause, artifact capture, and provenance manifest generation. | Task Runner Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
TASKRUN-42-001 | DONE (2025-11-04) | Add loops, conditionals, `maxParallel`, outputs, simulation mode, policy gate integration, and failure recovery (retry/abort) with deterministic state. Dependencies: TASKRUN-41-001. | Task Runner Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
TASKRUN-43-001 | DOING (2025-10-29) | Implement approvals workflow (resume after approval), notifications integration, remote artifact uploads, chaos resilience, secret injection, and audit logs. Dependencies: TASKRUN-42-001. | Task Runner Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
TASKRUN-43-001 | DONE (2025-11-06) | Implement approvals workflow (resume after approval), notifications integration, remote artifact uploads, chaos resilience, secret injection, and audit logs. Dependencies: TASKRUN-42-001. | Task Runner Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
TASKRUN-AIRGAP-56-001 | TODO | Enforce plan-time validation rejecting steps with non-allowlisted network calls in sealed mode and surface remediation errors. | Task Runner Guild, AirGap Policy Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
TASKRUN-AIRGAP-56-002 | TODO | Add helper steps for bundle ingestion (checksum verification, staging to object store) with deterministic outputs. Dependencies: TASKRUN-AIRGAP-56-001. | Task Runner Guild, AirGap Importer Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
TASKRUN-AIRGAP-57-001 | TODO | Refuse to execute plans when environment sealed=false but declared sealed install; emit advisory timeline events. Dependencies: TASKRUN-AIRGAP-56-002. | Task Runner Guild, AirGap Controller Guild (src/TaskRunner/StellaOps.TaskRunner/TASKS.md)
|
||||
|
||||
@@ -61,7 +61,7 @@ CLI-PARITY-41-001 | TODO | Deliver parity command groups (`policy`, `sbom`, `vul
|
||||
CLI-PARITY-41-002 | TODO | Implement `notify`, `aoc`, `auth` command groups, idempotency keys, shell completions, config docs, and parity matrix export tooling. Dependencies: CLI-PARITY-41-001. | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
CLI-POLICY-20-001 | TODO | Add `stella policy new | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
CLI-POLICY-23-004 | TODO | Add `stella policy lint` command validating SPL files with compiler diagnostics; support JSON output. Dependencies: CLI-POLICY-20-001. | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
CLI-POLICY-23-005 | DOING (2025-10-28) | Implement `stella policy activate` with scheduling window, approval enforcement, and summary output. Dependencies: CLI-POLICY-23-004. | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
CLI-POLICY-23-005 | DONE (2025-11-06) | Implement `stella policy activate` with scheduling window, approval enforcement, and summary output. Dependencies: CLI-POLICY-23-004. | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
> 2025-11-06: CLI enforces `--version` as mandatory and adds scheduled activation timestamp normalization tests while keeping exit codes intact.
|
||||
CLI-POLICY-23-006 | TODO | Provide `stella policy history` and `stella policy explain` commands to pull run history and explanation trees. Dependencies: CLI-POLICY-23-005. | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
CLI-POLICY-27-001 | TODO | Implement policy workspace commands (`stella policy init`, `edit`, `lint`, `compile`, `test`) with template selection, local cache, JSON output, and deterministic temp directories. Dependencies: CLI-POLICY-23-006. | DevEx/CLI Guild (src/Cli/StellaOps.Cli/TASKS.md)
|
||||
|
||||
@@ -463,14 +463,14 @@ VEX-CONSENSUS-LENS-ENG-0001 | TODO | Sync into ../../TASKS.md | Module Team (doc
|
||||
VEX-CONSENSUS-LENS-OPS-0001 | TODO | Document outputs in ./README.md | Ops Guild (docs/modules/vex-lens/TASKS.md)
|
||||
|
||||
|
||||
[Documentation & Process] 200.W) Docs Modules Vexer
|
||||
[Documentation & Process] 200.W) Docs Modules Excititor
|
||||
Depends on: Sprint 100.A - Attestor, Sprint 110.A - AdvisoryAI, Sprint 120.A - AirGap, Sprint 130.A - Scanner, Sprint 140.A - Graph, Sprint 150.A - Orchestrator, Sprint 160.A - EvidenceLocker, Sprint 170.A - Notifier, Sprint 180.A - Cli, Sprint 190.A - Ops Deployment
|
||||
Summary: Documentation & Process focus on Docs Modules Vexer).
|
||||
Summary: Documentation & Process focus on Docs Modules Excititor).
|
||||
Task ID | State | Task description | Owners (Source)
|
||||
--- | --- | --- | ---
|
||||
VEXER-DOCS-0001 | DOING (2025-10-29) | See ./AGENTS.md | Docs Guild (docs/modules/vexer/TASKS.md)
|
||||
VEXER-ENG-0001 | TODO | Update status via ./AGENTS.md workflow | Module Team (docs/modules/vexer/TASKS.md)
|
||||
VEXER-OPS-0001 | TODO | Sync outcomes back to ../../TASKS.md | Ops Guild (docs/modules/vexer/TASKS.md)
|
||||
EXCITITOR-DOCS-0001 | DOING (2025-10-29) | See ./AGENTS.md | Docs Guild (docs/modules/excititor/TASKS.md)
|
||||
EXCITITOR-ENG-0001 | TODO | Update status via ./AGENTS.md workflow | Module Team (docs/modules/excititor/TASKS.md)
|
||||
EXCITITOR-OPS-0001 | TODO | Sync outcomes back to ../../TASKS.md | Ops Guild (docs/modules/excititor/TASKS.md)
|
||||
|
||||
|
||||
[Documentation & Process] 200.X) Docs Modules Vuln Explorer
|
||||
|
||||
@@ -19,7 +19,8 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Rendering;
|
||||
using StellaOps.Auth.Client;
|
||||
using StellaOps.Cli.Configuration;
|
||||
using StellaOps.Cli.Prompts;
|
||||
@@ -217,10 +218,12 @@ internal static class CommandHandlers
|
||||
|
||||
private static void RenderEntryTrace(EntryTraceResponseModel result, bool includeNdjson)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[bold]Scan[/]: {result.ScanId}");
|
||||
AnsiConsole.MarkupLine($"Image: {result.ImageDigest}");
|
||||
AnsiConsole.MarkupLine($"Generated: {result.GeneratedAt:O}");
|
||||
AnsiConsole.MarkupLine($"Outcome: {result.Graph.Outcome}");
|
||||
var console = AnsiConsole.Console;
|
||||
|
||||
console.MarkupLine($"[bold]Scan[/]: {result.ScanId}");
|
||||
console.MarkupLine($"Image: {result.ImageDigest}");
|
||||
console.MarkupLine($"Generated: {result.GeneratedAt:O}");
|
||||
console.MarkupLine($"Outcome: {result.Graph.Outcome}");
|
||||
|
||||
var planTable = new Table()
|
||||
.AddColumn("Terminal")
|
||||
@@ -243,14 +246,14 @@ internal static class CommandHandlers
|
||||
|
||||
if (planTable.Rows.Count > 0)
|
||||
{
|
||||
AnsiConsole.Write(planTable);
|
||||
}
|
||||
else
|
||||
{
|
||||
AnsiConsole.MarkupLine("[italic]No entry trace plans recorded.[/]");
|
||||
}
|
||||
|
||||
if (result.Graph.Diagnostics.Length > 0)
|
||||
console.Write(planTable);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.MarkupLine("[italic]No entry trace plans recorded.[/]");
|
||||
}
|
||||
|
||||
if (result.Graph.Diagnostics.Length > 0)
|
||||
{
|
||||
var diagTable = new Table()
|
||||
.AddColumn("Severity")
|
||||
@@ -265,17 +268,17 @@ internal static class CommandHandlers
|
||||
diagnostic.Message);
|
||||
}
|
||||
|
||||
AnsiConsole.Write(diagTable);
|
||||
}
|
||||
|
||||
if (includeNdjson && result.Ndjson.Count > 0)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[bold]NDJSON Output[/]");
|
||||
foreach (var line in result.Ndjson)
|
||||
{
|
||||
AnsiConsole.WriteLine(line);
|
||||
}
|
||||
}
|
||||
console.Write(diagTable);
|
||||
}
|
||||
|
||||
if (includeNdjson && result.Ndjson.Count > 0)
|
||||
{
|
||||
console.MarkupLine("[bold]NDJSON Output[/]");
|
||||
foreach (var line in result.Ndjson)
|
||||
{
|
||||
console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task HandleScannerRunAsync(
|
||||
@@ -399,13 +402,17 @@ internal static class CommandHandlers
|
||||
|
||||
try
|
||||
{
|
||||
var result = await client.GetEntryTraceAsync(scanId, cancellationToken).ConfigureAwait(false);
|
||||
if (result is null)
|
||||
{
|
||||
logger.LogWarning("No EntryTrace data available for scan {ScanId}.", scanId);
|
||||
Environment.ExitCode = 1;
|
||||
return;
|
||||
}
|
||||
var result = await client.GetEntryTraceAsync(scanId, cancellationToken).ConfigureAwait(false);
|
||||
if (result is null)
|
||||
{
|
||||
logger.LogWarning("No EntryTrace data available for scan {ScanId}.", scanId);
|
||||
var console = AnsiConsole.Console;
|
||||
console.MarkupLine("[yellow]No EntryTrace data available for scan {0}.[/]", Markup.Escape(scanId));
|
||||
console.Write(new Text($"No EntryTrace data available for scan {scanId}.{Environment.NewLine}"));
|
||||
Console.WriteLine($"No EntryTrace data available for scan {scanId}.");
|
||||
Environment.ExitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
RenderEntryTrace(result, includeNdjson);
|
||||
Environment.ExitCode = 0;
|
||||
@@ -4167,10 +4174,10 @@ internal static class CommandHandlers
|
||||
};
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(outputPath) || Console.IsOutputRedirected)
|
||||
{
|
||||
return TaskRunnerSimulationOutputFormat.Json;
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(outputPath))
|
||||
{
|
||||
return TaskRunnerSimulationOutputFormat.Json;
|
||||
}
|
||||
|
||||
return TaskRunnerSimulationOutputFormat.Table;
|
||||
}
|
||||
@@ -4192,10 +4199,12 @@ internal static class CommandHandlers
|
||||
|
||||
private static void RenderTaskRunnerSimulationResult(TaskRunnerSimulationResult result)
|
||||
{
|
||||
var table = new Table
|
||||
{
|
||||
Border = TableBorder.Rounded
|
||||
};
|
||||
var console = AnsiConsole.Console;
|
||||
|
||||
var table = new Table
|
||||
{
|
||||
Border = TableBorder.Rounded
|
||||
};
|
||||
table.AddColumn("Step");
|
||||
table.AddColumn("Kind");
|
||||
table.AddColumn("Status");
|
||||
@@ -4217,10 +4226,10 @@ internal static class CommandHandlers
|
||||
Markup.Escape(string.IsNullOrWhiteSpace(step.ApprovalId) ? "-" : step.ApprovalId!));
|
||||
}
|
||||
|
||||
AnsiConsole.Write(table);
|
||||
|
||||
if (result.Outputs.Count > 0)
|
||||
{
|
||||
console.Write(table);
|
||||
|
||||
if (result.Outputs.Count > 0)
|
||||
{
|
||||
var outputsTable = new Table
|
||||
{
|
||||
Border = TableBorder.Rounded
|
||||
@@ -4241,13 +4250,15 @@ internal static class CommandHandlers
|
||||
Markup.Escape(string.IsNullOrWhiteSpace(output.ValueExpression) ? "-" : output.ValueExpression!));
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Write(outputsTable);
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine($"[grey]Plan Hash:[/] {Markup.Escape(result.PlanHash)}");
|
||||
AnsiConsole.MarkupLine($"[grey]Pending Approvals:[/] {(result.HasPendingApprovals ? "yes" : "no")}");
|
||||
console.WriteLine();
|
||||
console.Write(outputsTable);
|
||||
}
|
||||
|
||||
console.WriteLine();
|
||||
console.MarkupLine($"[grey]Plan Hash:[/] {Markup.Escape(result.PlanHash)}");
|
||||
console.MarkupLine($"[grey]Pending Approvals:[/] {(result.HasPendingApprovals ? "yes" : "no")}");
|
||||
console.Write(new Text($"Plan Hash: {result.PlanHash}{Environment.NewLine}"));
|
||||
console.Write(new Text($"Pending Approvals: {(result.HasPendingApprovals ? "yes" : "no")}{Environment.NewLine}"));
|
||||
}
|
||||
|
||||
private static IEnumerable<(TaskRunnerSimulationStep Step, int Depth)> FlattenTaskRunnerSimulationSteps(
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
> 2025-10-30: Resuming implementation; wiring backend query DTOs, CLI handlers, and tests for paginated policy-filtered findings.
|
||||
> 2025-10-30: Implemented backend client + CLI command surface for policy findings list/get/explain, added telemetry, interactive/json output, file writes, and unit tests covering filters + explain traces.
|
||||
> 2025-10-30: Pending POLICY-ENGINE-20-006 change-stream orchestration to validate live pagination/cursor behaviour once engine emits incremental updates.
|
||||
> 2025-11-06: Polishing complete — CLI policy activate now shares console/output plumbing with entry trace warnings, offline tests green, gRPC offline feed restored for activation path.
|
||||
|
||||
## Graph Explorer v1
|
||||
|
||||
@@ -47,7 +48,7 @@
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| CLI-POLICY-23-004 | TODO | DevEx/CLI Guild | WEB-POLICY-23-001 | Add `stella policy lint` command validating SPL files with compiler diagnostics; support JSON output. | Command returns lint diagnostics; exit codes documented; tests cover error scenarios. |
|
||||
| CLI-POLICY-23-005 | DOING (2025-10-28) | DevEx/CLI Guild | POLICY-GATEWAY-18-002..003, WEB-POLICY-23-002 | Implement `stella policy activate` with scheduling window, approval enforcement, and summary output. | Activation command integrates with API, handles 2-person rule failures; tests cover success/error. |
|
||||
| CLI-POLICY-23-005 | DONE (2025-11-06) | DevEx/CLI Guild | POLICY-GATEWAY-18-002..003, WEB-POLICY-23-002 | Implement `stella policy activate` with scheduling window, approval enforcement, and summary output. | Activation command integrates with API, handles 2-person rule failures; tests cover success/error. |
|
||||
> 2025-10-28: CLI command implemented with gateway integration (`policy activate`), interactive summary output, retry-aware metrics, and exit codes (0 success, 75 pending second approval). Tests cover success/pending/error paths.
|
||||
> 2025-11-06: Tightened required `--version` parsing, added scheduled activation handling coverage, and expanded tests to validate timestamp normalization.
|
||||
| CLI-POLICY-23-006 | TODO | DevEx/CLI Guild | WEB-POLICY-23-004 | Provide `stella policy history` and `stella policy explain` commands to pull run history and explanation trees. | Commands output JSON/table; integration tests with fixtures; docs updated. |
|
||||
|
||||
@@ -197,30 +197,29 @@ public sealed class CommandHandlersTests
|
||||
public async Task HandleScanEntryTraceAsync_WarnsWhenResultMissing()
|
||||
{
|
||||
var originalExit = Environment.ExitCode;
|
||||
var console = new TestConsole();
|
||||
var originalConsole = AnsiConsole.Console;
|
||||
|
||||
var backend = new StubBackendClient(new JobTriggerResult(true, "Accepted", null, null));
|
||||
var provider = BuildServiceProvider(backend);
|
||||
AnsiConsole.Console = console;
|
||||
var loggerProvider = new TestLoggerProvider();
|
||||
var provider = BuildServiceProvider(backend, loggerProvider: loggerProvider);
|
||||
|
||||
try
|
||||
{
|
||||
await CommandHandlers.HandleScanEntryTraceAsync(
|
||||
var output = await CaptureTestConsoleAsync(console => CommandHandlers.HandleScanEntryTraceAsync(
|
||||
provider,
|
||||
"scan-missing",
|
||||
includeNdjson: false,
|
||||
verbose: false,
|
||||
cancellationToken: CancellationToken.None);
|
||||
cancellationToken: CancellationToken.None));
|
||||
|
||||
Assert.Equal(1, Environment.ExitCode);
|
||||
Assert.Equal("scan-missing", backend.LastEntryTraceScanId);
|
||||
Assert.Contains("No EntryTrace data", console.Output, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("No EntryTrace data", output.Combined, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var warning = Assert.Single(loggerProvider.Entries.Where(entry => entry.Level == LogLevel.Warning));
|
||||
Assert.Contains("No EntryTrace data", warning.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.ExitCode = originalExit;
|
||||
AnsiConsole.Console = originalConsole;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2543,11 +2542,19 @@ spec:
|
||||
IScannerInstaller? installer = null,
|
||||
StellaOpsCliOptions? options = null,
|
||||
IStellaOpsTokenClient? tokenClient = null,
|
||||
IConcelierObservationsClient? concelierClient = null)
|
||||
IConcelierObservationsClient? concelierClient = null,
|
||||
ILoggerProvider? loggerProvider = null)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton(backend);
|
||||
services.AddSingleton<ILoggerFactory>(_ => LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Debug)));
|
||||
services.AddSingleton<ILoggerFactory>(_ => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.SetMinimumLevel(LogLevel.Debug);
|
||||
if (loggerProvider is not null)
|
||||
{
|
||||
builder.AddProvider(loggerProvider);
|
||||
}
|
||||
}));
|
||||
services.AddSingleton(new VerbosityState());
|
||||
services.AddHttpClient();
|
||||
var resolvedOptions = options ?? new StellaOpsCliOptions
|
||||
@@ -2571,6 +2578,70 @@ spec:
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private static async Task<CapturedConsoleOutput> CaptureTestConsoleAsync(Func<TestConsole, Task> action)
|
||||
{
|
||||
var testConsole = new TestConsole();
|
||||
var originalConsole = AnsiConsole.Console;
|
||||
var originalOut = Console.Out;
|
||||
using var writer = new StringWriter();
|
||||
|
||||
try
|
||||
{
|
||||
AnsiConsole.Console = testConsole;
|
||||
Console.SetOut(writer);
|
||||
|
||||
await action(testConsole).ConfigureAwait(false);
|
||||
return new CapturedConsoleOutput(testConsole.Output.ToString(), writer.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.SetOut(originalOut);
|
||||
AnsiConsole.Console = originalConsole;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record CapturedConsoleOutput(string SpectreBuffer, string PlainBuffer)
|
||||
{
|
||||
public string Combined => string.Concat(SpectreBuffer, PlainBuffer);
|
||||
}
|
||||
|
||||
private sealed class TestLoggerProvider : ILoggerProvider
|
||||
{
|
||||
private readonly List<LogEntry> _entries = new();
|
||||
|
||||
public IReadOnlyList<LogEntry> Entries => _entries;
|
||||
|
||||
public ILogger CreateLogger(string categoryName) => new TestLogger(categoryName, _entries);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private sealed class TestLogger : ILogger
|
||||
{
|
||||
private readonly string _category;
|
||||
private readonly List<LogEntry> _entries;
|
||||
|
||||
public TestLogger(string category, List<LogEntry> entries)
|
||||
{
|
||||
_category = category;
|
||||
_entries = entries;
|
||||
}
|
||||
|
||||
public IDisposable? BeginScope<TState>(TState state) => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => true;
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
var message = formatter(state, exception);
|
||||
_entries.Add(new LogEntry(logLevel, _category, eventId, message, exception));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record LogEntry(LogLevel Level, string Category, EventId EventId, string Message, Exception? Exception);
|
||||
}
|
||||
|
||||
private static IScannerExecutor CreateDefaultExecutor()
|
||||
{
|
||||
var tempResultsFile = Path.GetTempFileName();
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
## Sprint 43 – Approvals, Notifications, Hardening
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| TASKRUN-43-001 | DOING (2025-10-29) | Task Runner Guild | TASKRUN-42-001, NOTIFY-SVC-40-001 | Implement approvals workflow (resume after approval), notifications integration, remote artifact uploads, chaos resilience, secret injection, and audit logs. | Approvals/resume flow validated; notifications emitted; chaos tests documented; secrets redacted in logs; audit logs complete. |
|
||||
| TASKRUN-43-001 | DONE (2025-11-06) | Task Runner Guild | TASKRUN-42-001, NOTIFY-SVC-40-001 | Implement approvals workflow (resume after approval), notifications integration, remote artifact uploads, chaos resilience, secret injection, and audit logs. | Approvals/resume flow validated; notifications emitted; chaos tests documented; secrets redacted in logs; audit logs complete. |
|
||||
> 2025-10-29: Starting approvals orchestration — defining persistence/workflow scaffolding, integrating plan insights for notifications, and staging resume hooks.
|
||||
> 2025-10-29: Added approval coordinator + policy notification bridge with unit tests; ready to wire into worker execution/resume path.
|
||||
> 2025-11-06: Added approval decision API with resume requeue, persisted plan snapshots, and artifact uploader hook (logging backend pending).
|
||||
> 2025-11-06: Task complete – resume flow persists approvals, filesystem artifact uploader stores manifests/files, and CLI pack-run tests cover artifact persistence.
|
||||
|
||||
## Authority-Backed Scopes & Tenancy (Epic 14)
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|
||||
Reference in New Issue
Block a user