feat: add audit-verified status updates with override tracking
Status updates (feature/test update and batch-update) now verify the requested status against Roslyn audit classification. Mismatches require --override "reason" to force. Overrides are logged to a new status_overrides table and reviewable via 'override list' command.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using NatsNet.PortTracker.Audit;
|
||||
using NatsNet.PortTracker.Data;
|
||||
|
||||
namespace NatsNet.PortTracker.Commands;
|
||||
@@ -89,18 +90,37 @@ public static class TestCommands
|
||||
// update
|
||||
var updateId = new Argument<int>("id") { Description = "Test ID" };
|
||||
var updateStatus = new Option<string>("--status") { Description = "New status", Required = true };
|
||||
var updateCmd = new Command("update", "Update test status");
|
||||
var updateOverride = new Option<string?>("--override") { Description = "Override audit mismatch with this comment" };
|
||||
var updateCmd = new Command("update", "Update test status (audit-verified)");
|
||||
updateCmd.Add(updateId);
|
||||
updateCmd.Add(updateStatus);
|
||||
updateCmd.Add(updateOverride);
|
||||
updateCmd.SetAction(parseResult =>
|
||||
{
|
||||
var dbPath = parseResult.GetValue(dbOption)!;
|
||||
var id = parseResult.GetValue(updateId);
|
||||
var status = parseResult.GetValue(updateStatus)!;
|
||||
var overrideComment = parseResult.GetValue(updateOverride);
|
||||
using var db = new Database(dbPath);
|
||||
|
||||
var indexer = AuditVerifier.BuildIndexer("unit_tests");
|
||||
var verifications = AuditVerifier.VerifyItems(db, indexer, "unit_tests",
|
||||
" WHERE id = @id", [("@id", (object?)id)], status);
|
||||
if (verifications.Count == 0)
|
||||
{
|
||||
Console.WriteLine($"Test {id} not found.");
|
||||
return;
|
||||
}
|
||||
if (!AuditVerifier.CheckAndReport(verifications, status, overrideComment))
|
||||
return;
|
||||
|
||||
var affected = db.Execute("UPDATE unit_tests SET status = @status WHERE id = @id",
|
||||
("@status", status), ("@id", id));
|
||||
Console.WriteLine(affected > 0 ? $"Test {id} updated to '{status}'." : $"Test {id} not found.");
|
||||
|
||||
var mismatches = verifications.Where(r => !r.Matches).ToList();
|
||||
if (mismatches.Count > 0 && overrideComment is not null)
|
||||
AuditVerifier.LogOverrides(db, "unit_tests", mismatches, status, overrideComment);
|
||||
});
|
||||
|
||||
// map
|
||||
@@ -139,13 +159,14 @@ public static class TestCommands
|
||||
|
||||
private static Command CreateBatchUpdate(Option<string> dbOption)
|
||||
{
|
||||
var cmd = new Command("batch-update", "Bulk update test status");
|
||||
var cmd = new Command("batch-update", "Bulk update test status (audit-verified)");
|
||||
var idsOpt = BatchFilters.IdsOption();
|
||||
var moduleOpt = BatchFilters.ModuleOption();
|
||||
var statusOpt = BatchFilters.StatusOption();
|
||||
var executeOpt = BatchFilters.ExecuteOption();
|
||||
var setStatus = new Option<string>("--set-status") { Description = "New status to set", Required = true };
|
||||
var setNotes = new Option<string?>("--set-notes") { Description = "Notes to set" };
|
||||
var overrideOpt = new Option<string?>("--override") { Description = "Override audit mismatches with this comment" };
|
||||
|
||||
cmd.Add(idsOpt);
|
||||
cmd.Add(moduleOpt);
|
||||
@@ -153,6 +174,7 @@ public static class TestCommands
|
||||
cmd.Add(executeOpt);
|
||||
cmd.Add(setStatus);
|
||||
cmd.Add(setNotes);
|
||||
cmd.Add(overrideOpt);
|
||||
|
||||
cmd.SetAction(parseResult =>
|
||||
{
|
||||
@@ -163,6 +185,7 @@ public static class TestCommands
|
||||
var execute = parseResult.GetValue(executeOpt);
|
||||
var newStatus = parseResult.GetValue(setStatus)!;
|
||||
var notes = parseResult.GetValue(setNotes);
|
||||
var overrideComment = parseResult.GetValue(overrideOpt);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ids) && module is null && string.IsNullOrWhiteSpace(status))
|
||||
{
|
||||
@@ -173,6 +196,12 @@ public static class TestCommands
|
||||
using var db = new Database(dbPath);
|
||||
var (whereClause, filterParams) = BatchFilters.BuildWhereClause(ids, module, status);
|
||||
|
||||
// Audit verification
|
||||
var indexer = AuditVerifier.BuildIndexer("unit_tests");
|
||||
var verifications = AuditVerifier.VerifyItems(db, indexer, "unit_tests", whereClause, filterParams, newStatus);
|
||||
if (!AuditVerifier.CheckAndReport(verifications, newStatus, overrideComment))
|
||||
return;
|
||||
|
||||
var setClauses = new List<string> { "status = @newStatus" };
|
||||
var updateParams = new List<(string, object?)> { ("@newStatus", newStatus) };
|
||||
if (notes is not null)
|
||||
@@ -185,6 +214,14 @@ public static class TestCommands
|
||||
"id, name, status, module_id, notes",
|
||||
string.Join(", ", setClauses), updateParams,
|
||||
whereClause, filterParams, execute);
|
||||
|
||||
// Log overrides after successful execute
|
||||
if (execute)
|
||||
{
|
||||
var mismatches = verifications.Where(r => !r.Matches).ToList();
|
||||
if (mismatches.Count > 0 && overrideComment is not null)
|
||||
AuditVerifier.LogOverrides(db, "unit_tests", mismatches, newStatus, overrideComment);
|
||||
}
|
||||
});
|
||||
|
||||
return cmd;
|
||||
|
||||
Reference in New Issue
Block a user