Built Word Documents (.docx):
Spensara Overview (.docx)
Capability Assessment (.docx)
Brink POS Ingestion Analysis (.docx)
The Borg Ingestion Architecture (.docx)
Categories
Implementation Specs (157)
Detailed engineering and feature implementation specifications.
- specs/AnomalyDetection/TASK1.1.md
- specs/AnomalyDetection/TASK1.2.md
- specs/AnomalyDetection/TASK1.3.md
- specs/AnomalyDetection/TASK1.4.md
- specs/AnomalyDetection/TASK2.1.md
- specs/AnomalyDetection/TASK2.2.md
- specs/AnomalyDetection/TASK3.1.md
- specs/AnomalyDetection/TASK3.2.md
- specs/AnomalyDetection/TASK3.3.md
- specs/AnomalyDetection/TASK4.1.md
- specs/AnomalyDetection/TASK4.2.md
- specs/AnomalyDetection/TASK4.3.md
- specs/AnomalyDetection/TASK4.4.md
- specs/AnomalyDetection/TASK5.1.md
- specs/AnomalyDetection/TASK5.2.md
- specs/AnomalyDetection/TASK5.3.md
- specs/AnomalyDetection/TASK6.1.md
- specs/AnomalyDetection/TASK6.2.md
- specs/AnomalyDetection/TASK6.3.md
- specs/AnomalyDetection/TASKS.md
- specs/ApiServicePostgresTestStability/TASK.md
- specs/BackendDatabaseConsolidation/TASK.md
- specs/BackendDatabaseConsolidation/TASK1.1.md
- specs/BackendDatabaseConsolidation/TASK1.2.md
- specs/BackendDatabaseConsolidation/TASK1.3.md
- specs/BackendDatabaseConsolidation/TASK2.1.md
- specs/BackendDatabaseConsolidation/TASK2.2.md
- specs/BackendDatabaseConsolidation/TASK2.3.md
- specs/BackendDatabaseConsolidation/TASK3.1.md
- specs/BackendDatabaseConsolidation/TASK3.2.md
- specs/BackendDatabaseConsolidation/TASK4.1.md
- specs/BackendDatabaseConsolidation/TASK4.2.md
- specs/BackendDatabaseConsolidation/TASK4.3.md
- specs/BackendDatabaseConsolidation/TASK5.1.md
- specs/BackendDatabaseConsolidation/TASK5.2.md
- specs/BrinkLaborGetShiftsStaging/TASK.md
- specs/BrinkPosOrdersFirstEtlJob/TASK.md
- specs/BrinkPosOrdersFirstEtlJob/TASK0.md
- specs/BrinkPosOrdersFirstEtlJob/TASK1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.md
- specs/BrinkPosOrdersFirstEtlJob/TASK7.md
- specs/BrinkPosOrdersFirstEtlJob/TASK8.md
- specs/BrinkPosOrdersFirstEtlJob/TASK9.md
- specs/BrinkSettings2ToStaging/TASK.MD
- specs/CuratedToS3Stage/TASK.md
- specs/CuratedToS3Stage/TASK0.md
- specs/CuratedToS3Stage/TASK1.md
- specs/CuratedToS3Stage/TASK2.md
- specs/CuratedToS3Stage/TASK3.md
- specs/CuratedToS3Stage/TASK4.md
- specs/CustomerCredentialCustomHeaders/TASK.md
- specs/CustomerCredentialCustomHeaders/TASK1.1.md
- specs/CustomerCredentialCustomHeaders/TASK1.2.md
- specs/CustomerCredentialCustomHeaders/TASK2.1.md
- specs/CustomerCredentialCustomHeaders/TASK2.2.md
- specs/CustomerCredentialCustomHeaders/TASK3.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK.md
- specs/CustomerCredentialTriggeredProvisioning/TASK1.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK1.2.md
- specs/CustomerCredentialTriggeredProvisioning/TASK2.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK2.2.md
- specs/CustomerCredentialTriggeredProvisioning/TASK3.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK3.2.md
- specs/CustomerCredentialTriggeredProvisioning/TASK4.1.md
- specs/EtlSourceAdapterFramework/TASK.md
- specs/EtlSourceAdapterFramework/TASK0.md
- specs/EtlSourceAdapterFramework/TASK1.md
- specs/EtlSourceAdapterFramework/TASK2.md
- specs/EtlSourceAdapterFramework/TASK3.md
- specs/EtlSourceAdapterFramework/TASK4.md
- specs/EtlSourceAdapterFramework/TASK5.md
- specs/EtlSourceAdapterFramework/TASK6.md
- specs/KdsCdcDebeziumIntegration/TASK.md
- specs/KdsCdcDebeziumIntegration/TASK1.md
- specs/KdsCdcDebeziumIntegration/TASK2.md
- specs/KdsCdcDebeziumIntegration/TASK3.md
- specs/KdsCdcDebeziumIntegration/TASK4.md
- specs/KdsCdcDebeziumIntegration/TASK5.md
- specs/KdsCdcDurableRelationRouting/TASK.md
- specs/KdsCdcDurableRelationRouting/TASK1.md
- specs/KdsCdcDurableRelationRouting/TASK2.md
- specs/KdsCdcDurableRelationRouting/TASK3.md
- specs/KdsCdcDurableRelationRouting/TASK4.md
- specs/KdsCdcDurableRelationRouting/TASK5.md
- specs/KdsCdcIngestion/TASK.md
- specs/KdsCdcIngestion/TASK1.md
- specs/KdsCdcIngestion/TASK2.md
- specs/KdsCdcIngestion/TASK3.md
- specs/KdsCdcIngestion/TASK4.md
- specs/KdsCdcIngestion/TASK5.md
- specs/KdsCdcIngestion/TASK6.md
- specs/KdsCdcIngestion/TASK7.md
- specs/KdsCdcIngestion/TASK8.md
- specs/KdsCdcIngestion/TASK9.md
- specs/KdsCdcReplayExecution/TASK.md
- specs/KdsCdcReplayExecution/TASK1.md
- specs/KdsCdcReplayExecution/TASK2.md
- specs/KdsCdcReplayExecution/TASK3.md
- specs/KdsCdcReplayExecution/TASK4.md
- specs/KdsMonitorServingContractMigration/TASK.md
- specs/KdsMonitorServingContractMigration/TASK1.1.md
- specs/KdsMonitorServingContractMigration/TASK1.2.md
- specs/KdsMonitorServingContractMigration/TASK2.1.md
- specs/KdsMonitorServingContractMigration/TASK2.2.md
- specs/KdsMonitorServingContractMigration/TASK3.1.md
- specs/KdsMonitorServingContractMigration/TASK3.2.md
- specs/RedshiftFoundation/TASK.md
- specs/RedshiftFoundation/TASK1.1.md
- specs/RedshiftFoundation/TASK1.2.md
- specs/RedshiftFoundation/TASK1.3.md
- specs/RedshiftFoundation/TASK1.4.md
- specs/RedshiftFoundation/TASK2.1.md
- specs/RedshiftFoundation/TASK2.2.md
- specs/RedshiftFoundation/TASK3.1.md
- specs/RedshiftFoundation/TASK3.2.md
- specs/RedshiftFoundation/TASK3.3.md
- specs/RedshiftSyntheticDataFeed/TASK.md
- specs/RedshiftSyntheticDataFeed/TASK1.1.md
- specs/RedshiftSyntheticDataFeed/TASK1.2.md
- specs/RedshiftSyntheticDataFeed/TASK1.3.md
- specs/RedshiftSyntheticDataFeed/TASK2.1.md
- specs/RedshiftSyntheticDataFeed/TASK2.2.md
- specs/RedshiftSyntheticDataFeed/TASK3.1.md
- specs/RedshiftSyntheticDataFeed/TASK3.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK1.1.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK1.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK2.1.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK2.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK2.3.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK3.1.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK3.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK4.1.md
TASK 4.2: Implement MonitorRunOrchestrator
Summary
Implement the main orchestrator that coordinates the complete anomaly detection flow: load spec, run agent, emit alerts, and record history.
Dependencies
- TASK 2.1 (IAnomalyDetectorAgent)
- TASK 2.2 (AnomalyDetectorAgent)
- TASK 3.1 (IMonitorSpecRepository)
- TASK 4.1 (IMonitorRunOrchestrator interface)
- TASK 4.3 (IAlertEmitter)
- TASK 4.4 (IMonitorRunRepository)
Files to Create
1. backend/Kds.Ai.AnomalyDetector/Orchestration/MonitorRunOrchestrator.cs
csharp
using System.Diagnostics;
using Kds.Ai.AnomalyDetector.Agents;
using Kds.Ai.AnomalyDetector.Alerts;
using Kds.Ai.Data.Entities;
using Kds.Ai.Data.Enums;
using Kds.Ai.Data.Repositories;
using Microsoft.Extensions.Logging;
namespace Kds.Ai.AnomalyDetector.Orchestration;
internal sealed class MonitorRunOrchestrator(
IMonitorSpecRepository specRepository,
IMonitorRunRepository runRepository,
IAnomalyDetectorAgent agent,
IAlertEmitter alertEmitter,
ILogger<MonitorRunOrchestrator> logger) : IMonitorRunOrchestrator
{
public async Task<MonitorRun> ExecuteAsync(
Guid monitorSpecId,
DateTimeOffset? analysisTime = null,
RunOptions? options = null,
CancellationToken ct = default)
{
options ??= RunOptions.Default;
ReportProgress(options, RunPhase.LoadingSpec, "Loading monitor specification...");
var spec = await specRepository.GetByIdAsync(monitorSpecId, ct);
if (spec is null)
{
throw new InvalidOperationException($"MonitorSpec {monitorSpecId} not found");
}
return await ExecuteAsync(spec, analysisTime, options, ct);
}
public async Task<MonitorRun> ExecuteAsync(
MonitorSpec spec,
DateTimeOffset? analysisTime = null,
RunOptions? options = null,
CancellationToken ct = default)
{
options ??= RunOptions.Default;
var time = analysisTime ?? DateTimeOffset.UtcNow;
var stopwatch = Stopwatch.StartNew();
logger.LogInformation(
"Starting monitor run for '{MonitorName}' at {AnalysisTime}",
spec.Name, time);
// Create run record
ReportProgress(options, RunPhase.Initializing, "Initializing monitor run...");
var run = new MonitorRun
{
Id = Guid.NewGuid(),
MonitorSpecId = spec.Id,
Status = MonitorRunStatus.Running,
StartedAt = DateTimeOffset.UtcNow,
AnalysisWindowStart = options.WindowStart ?? time.AddHours(-24),
AnalysisWindowEnd = options.WindowEnd ?? time
};
if (!options.DryRun)
{
run = await runRepository.CreateAsync(run, ct);
}
try
{
// Run detection (single generic agent, no factory)
ReportProgress(options, RunPhase.RunningAgent, "Running anomaly detection agent...");
using var timeoutCts = options.Timeout.HasValue
? new CancellationTokenSource(options.Timeout.Value)
: new CancellationTokenSource();
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ct, timeoutCts.Token);
var result = await agent.RunDetectionAsync(spec, time, linkedCts.Token);
// Update run with results
ReportProgress(options, RunPhase.AnalyzingResults, "Processing detection results...");
run.AnomaliesDetected = result.Findings.Count;
run.ResultSummary = SerializeResultSummary(result);
run.TokensUsed = result.TotalTokens;
// Emit alerts if anomalies detected
if (result.AnomalyDetected && !options.SuppressAlerts && !options.DryRun)
{
ReportProgress(options, RunPhase.EmittingAlerts, "Emitting alerts...");
var alert = await alertEmitter.EmitAsync(spec, result, ct);
if (alert.Id != Guid.Empty)
{
run.AlertEvents.Add(alert);
logger.LogInformation(
"Emitted {Severity} alert {AlertId} for monitor '{MonitorName}'",
result.Severity, alert.Id, spec.Name);
}
}
// Mark completed
run.Status = MonitorRunStatus.Completed;
run.CompletedAt = DateTimeOffset.UtcNow;
run.DurationMs = stopwatch.ElapsedMilliseconds;
// Save results
if (!options.DryRun)
{
ReportProgress(options, RunPhase.SavingResults, "Saving results...");
await runRepository.UpdateAsync(run, ct);
await specRepository.UpdateLastRunAsync(spec.Id, run.CompletedAt.Value, ct);
}
ReportProgress(options, RunPhase.Completed,
result.AnomalyDetected
? $"Completed: {result.Findings.Count} anomalies detected"
: "Completed: No anomalies detected");
logger.LogInformation(
"Monitor run {RunId} completed in {Duration}ms. Anomalies: {Count}",
run.Id, run.DurationMs, run.AnomaliesDetected);
return run;
}
catch (OperationCanceledException) when (options.Timeout.HasValue)
{
return await HandleFailure(run, "Execution timed out", options, ct);
}
catch (Exception ex)
{
logger.LogError(ex, "Monitor run failed for {MonitorSpecId}", spec.Id);
return await HandleFailure(run, ex.Message, options, ct);
}
}
public async Task<IReadOnlyList<MonitorRun>> ExecuteAllActiveAsync(
DateTimeOffset? analysisTime = null,
RunOptions? options = null,
CancellationToken ct = default)
{
var specs = await specRepository.GetActiveAsync(ct);
logger.LogInformation(
"Executing {Count} active monitors",
specs.Count);
var results = new List<MonitorRun>();
foreach (var spec in specs)
{
try
{
var run = await ExecuteAsync(spec, analysisTime, options, ct);
results.Add(run);
}
catch (Exception ex)
{
logger.LogError(ex,
"Failed to execute monitor '{MonitorName}' ({MonitorId})",
spec.Name, spec.Id);
// Continue with other monitors
}
}
return results;
}
private async Task<MonitorRun> HandleFailure(
MonitorRun run,
string error,
RunOptions options,
CancellationToken ct)
{
run.Status = MonitorRunStatus.Failed;
run.CompletedAt = DateTimeOffset.UtcNow;
run.ErrorMessage = error;
if (!options.DryRun)
{
await runRepository.UpdateAsync(run, ct);
}
ReportProgress(options, RunPhase.Failed, $"Failed: {error}");
return run;
}
private static void ReportProgress(RunOptions options, RunPhase phase, string message)
{
options.Progress?.Report(new RunProgress
{
Phase = phase,
Message = message
});
}
private static string SerializeResultSummary(AnomalyDetectionResult result)
{
return System.Text.Json.JsonSerializer.Serialize(new
{
anomalyDetected = result.AnomalyDetected,
severity = result.Severity?.ToString(),
summary = result.Summary,
findingsCount = result.Findings.Count,
findings = result.Findings.Take(10).Select(f => new
{
description = f.Description,
severity = f.Severity.ToString(),
period = f.AffectedPeriod,
evidence = f.Evidence
}),
warnings = result.Warnings
});
}
}Files to Modify
2. backend/Kds.Ai.AnomalyDetector/DependencyInjectionExtensions.cs
Add orchestrator registration:
csharp
// Register orchestrator
builder.Services.AddScoped<IMonitorRunOrchestrator, MonitorRunOrchestrator>();Execution Flow
ExecuteAsync(specId)
│
├── Load MonitorSpec from repository
│
├── Create MonitorRun record (status: Running)
│
├── Run agent.RunDetectionAsync(spec, time)
│ │
│ ├── Agent reads spec.SystemPrompt as instructions
│ ├── Agent queries data via MCP tools (mysql_query)
│ ├── Agent analyzes and reasons
│ └── Agent calls emit_conclusion → AnomalyDetectionResult
│
├── If anomaly detected:
│ └── alertEmitter.EmitAsync() → AlertEvent
│ └── run.AlertEvents.Add(alert)
│
├── Update MonitorRun (status: Completed)
│
└── Update MonitorSpec.LastRunAtChanges from Old Design
- Uses single
IAnomalyDetectorAgentdirectly (noIAnomalyDetectorAgentFactory, no.GetAgent(monitorType)) - Class is
internal sealedwith primary constructor (matching codebase pattern for implementations) - Logs
spec.Nameinstead ofspec.MonitorTypeandspec.StoreGuid - Uses
run.AlertEvents.Add(alert)instead ofrun.AlertEventId = alert.Id(collection, not single FK) - Uses
result.TotalTokensinstead ofresult.TokenUsage?.TotalTokens SerializeResultSummaryusesAnomalyFindingfields:Description,Severity,AffectedPeriod,EvidenceExecuteAllActiveAsyncreplaces bothExecuteAllByTypeAsyncandExecuteForStoreAsync- Class is
internal sealedwith primary constructor
Acceptance Criteria
- [ ]
MonitorRunOrchestratorclass created (internal sealedwith primary constructor) - [ ] All interface methods implemented (no
ExecuteAllByTypeAsyncorExecuteForStoreAsync) - [ ] Uses single
IAnomalyDetectorAgent(no factory) - [ ] Uses
IMonitorSpecRepositoryfromKds.Ai.Data.Repositories(notKds.Ai.AnomalyDetector.Repositories) - [ ] Alert stored via
run.AlertEventscollection (many-to-many) - [ ] Progress reporting integrated
- [ ] Timeout handling with CancellationTokenSource
- [ ] Error handling with proper run status updates
- [ ] Dry-run mode skips persistence
- [ ] Alert suppression option works
- [ ] Batch execution continues on individual failures
- [ ] Duration tracking accurate
- [ ] Token usage recorded via
result.TotalTokens - [ ] No references to
MonitorType,StoreGuid,IsEnabled, orAlertEventId - [ ] Orchestrator registered in DI
- [ ] Solution builds without errors
Notes
- The orchestrator doesn't parallelize batch runs by default (could add option later)
- Consider adding circuit breaker for repeated failures
- May want to add retry logic for transient errors
- Result summary is truncated (10 findings) to avoid huge DB entries