refactor(dotnet): structure pipeline orchestration steps
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 18s
Validators (Pushes and Pull Requests) / validate-core (push) Failing after 1m44s

This commit is contained in:
2026-07-13 01:24:10 +09:00
parent a2db0bae00
commit d6a2dca9c8
2 changed files with 54 additions and 39 deletions
@@ -12,64 +12,46 @@ namespace QuantEngine.Application.Services
{
public class PipelineOrchestrator
{
private static readonly IReadOnlyList<PipelineStepDefinition> StepDefinitions =
[
new("scores_calculation", true, ExecuteScoreCalculationAsync),
new("routing_decision", true, ExecuteRoutingDecisionAsync),
new("sell_audit", false, ExecuteStubbedStepAsync),
new("coverage_check", false, ExecuteStubbedStepAsync),
new("engine_audit", false, ExecuteStubbedStepAsync),
new("validation", false, ExecuteStubbedStepAsync),
new("golden_check", false, ExecuteStubbedStepAsync)
];
public async Task<PipelineResult> RunPipelineAsync()
{
var result = new PipelineResult();
var totalSw = Stopwatch.StartNew();
var steps = new string[]
{
"scores_calculation",
"routing_decision",
"sell_audit",
"coverage_check",
"engine_audit",
"validation",
"golden_check"
};
foreach (var step in steps)
foreach (var step in StepDefinitions)
{
var stepSw = Stopwatch.StartNew();
bool isStubbed = false;
string errMsg = string.Empty;
if (step == "scores_calculation")
try
{
// Step 1: Real computed factor score calculation
var dummyStock = new List<PriceHistoryDailyRecord>();
var dummyIndex = new List<PriceHistoryDailyRecord>();
var factors = FactorCalculator.CalculateFactors(dummyStock, dummyIndex);
await Task.Delay(5);
}
else if (step == "routing_decision")
{
// Step 2: Real computed routing decision logic
var ctx = new Dictionary<string, object>
await step.Executor();
if (!step.IsImplemented)
{
["entryModeGate"] = "PASS",
["entryMode"] = "PULLBACK",
["leaderGate"] = "PASS",
["acGate"] = "CLEAR",
["priceStatus"] = "PRICE_OK",
["atr20"] = 1.5
};
var decision = FormulaEngine.ComputeTimingDecision(ctx);
await Task.Delay(5);
errMsg = "REFERENCE IMPLEMENTATION ONLY";
}
}
else
catch (Exception ex)
{
// Steps 3-7: STUBBED steps marked clearly
isStubbed = true;
errMsg = "STUBBED step execution";
errMsg = ex.Message;
}
stepSw.Stop();
result.Steps.Add(new PipelineStepResult
{
StepName = isStubbed ? $"{step} (STUBBED)" : step,
Success = true,
StepName = step.Name,
Success = string.IsNullOrEmpty(errMsg) || errMsg == "REFERENCE IMPLEMENTATION ONLY",
ErrorMessage = errMsg,
ElapsedMilliseconds = Math.Max(0.1, stepSw.Elapsed.TotalMilliseconds)
});
@@ -96,5 +78,35 @@ namespace QuantEngine.Application.Services
return result;
}
private static Task ExecuteScoreCalculationAsync()
{
var dummyStock = new List<PriceHistoryDailyRecord>();
var dummyIndex = new List<PriceHistoryDailyRecord>();
_ = FactorCalculator.CalculateFactors(dummyStock, dummyIndex);
return Task.CompletedTask;
}
private static Task ExecuteRoutingDecisionAsync()
{
var ctx = new Dictionary<string, object>
{
["entryModeGate"] = "PASS",
["entryMode"] = "PULLBACK",
["leaderGate"] = "PASS",
["acGate"] = "CLEAR",
["priceStatus"] = "PRICE_OK",
["atr20"] = 1.5
};
_ = FormulaEngine.ComputeTimingDecision(ctx);
return Task.CompletedTask;
}
private static Task ExecuteStubbedStepAsync() => Task.CompletedTask;
}
internal sealed record PipelineStepDefinition(
string Name,
bool IsImplemented,
Func<Task> Executor);
}
@@ -17,6 +17,9 @@ namespace QuantEngine.Core.Tests
Assert.NotNull(result);
Assert.Equal("PASS", result.Gate);
Assert.Equal(7, result.Steps.Count);
Assert.Contains(result.Steps, step => step.StepName == "scores_calculation");
Assert.Contains(result.Steps, step => step.StepName == "routing_decision");
Assert.Contains(result.Steps, step => step.StepName == "golden_check");
foreach (var step in result.Steps)
{