From e5ffcd6535f8c55622019e1cce13e3bc380c88b9 Mon Sep 17 00:00:00 2001 From: master <> Date: Thu, 6 Nov 2025 19:18:34 +0000 Subject: [PATCH] CLI entry trace warning capture and sprint status sync --- docs/implplan/SPRINTS.md | 3 + .../SPRINT_150_scheduling_automation.md | 2 +- docs/implplan/SPRINT_180_experience_sdks.md | 2 +- .../SPRINT_200_documentation_process.md | 10 +- .../StellaOps.Cli/Commands/CommandHandlers.cs | 111 ++++++++++-------- src/Cli/StellaOps.Cli/TASKS.md | 3 +- .../Commands/CommandHandlersTests.cs | 93 +++++++++++++-- src/TaskRunner/StellaOps.TaskRunner/TASKS.md | 3 +- 8 files changed, 157 insertions(+), 70 deletions(-) diff --git a/docs/implplan/SPRINTS.md b/docs/implplan/SPRINTS.md index 0d21030f9..48c0279c6 100644 --- a/docs/implplan/SPRINTS.md +++ b/docs/implplan/SPRINTS.md @@ -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. diff --git a/docs/implplan/SPRINT_150_scheduling_automation.md b/docs/implplan/SPRINT_150_scheduling_automation.md index 92f55c8c6..aa893b23e 100644 --- a/docs/implplan/SPRINT_150_scheduling_automation.md +++ b/docs/implplan/SPRINT_150_scheduling_automation.md @@ -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) diff --git a/docs/implplan/SPRINT_180_experience_sdks.md b/docs/implplan/SPRINT_180_experience_sdks.md index 23ae7e193..6f3af4123 100644 --- a/docs/implplan/SPRINT_180_experience_sdks.md +++ b/docs/implplan/SPRINT_180_experience_sdks.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) diff --git a/docs/implplan/SPRINT_200_documentation_process.md b/docs/implplan/SPRINT_200_documentation_process.md index 40108f45e..02d6e3eb6 100644 --- a/docs/implplan/SPRINT_200_documentation_process.md +++ b/docs/implplan/SPRINT_200_documentation_process.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 diff --git a/src/Cli/StellaOps.Cli/Commands/CommandHandlers.cs b/src/Cli/StellaOps.Cli/Commands/CommandHandlers.cs index 13eb91711..4fd32a16b 100644 --- a/src/Cli/StellaOps.Cli/Commands/CommandHandlers.cs +++ b/src/Cli/StellaOps.Cli/Commands/CommandHandlers.cs @@ -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( diff --git a/src/Cli/StellaOps.Cli/TASKS.md b/src/Cli/StellaOps.Cli/TASKS.md index 3ccb8553b..37899240e 100644 --- a/src/Cli/StellaOps.Cli/TASKS.md +++ b/src/Cli/StellaOps.Cli/TASKS.md @@ -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. | diff --git a/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs b/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs index 20ab1b4d4..1b2005015 100644 --- a/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs +++ b/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs @@ -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(_ => LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Debug))); + services.AddSingleton(_ => 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 CaptureTestConsoleAsync(Func 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 _entries = new(); + + public IReadOnlyList 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 _entries; + + public TestLogger(string category, List entries) + { + _category = category; + _entries = entries; + } + + public IDisposable? BeginScope(TState state) => null; + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func 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(); diff --git a/src/TaskRunner/StellaOps.TaskRunner/TASKS.md b/src/TaskRunner/StellaOps.TaskRunner/TASKS.md index 48de9e04d..e23807551 100644 --- a/src/TaskRunner/StellaOps.TaskRunner/TASKS.md +++ b/src/TaskRunner/StellaOps.TaskRunner/TASKS.md @@ -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 |