< Summary

Information
Class: Orchestrator.Program
Assembly: Orchestrator
File(s): /home/runner/work/KicktippAi/KicktippAi/src/Orchestrator/Program.cs
Line coverage
100%
Covered lines: 284
Uncovered lines: 0
Coverable lines: 284
Total lines: 334
Line coverage: 100%
Branch coverage
100%
Covered branches: 10
Total branches: 10
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Main()100%22100%

File(s)

/home/runner/work/KicktippAi/KicktippAi/src/Orchestrator/Program.cs

#LineLine coverage
 1using Microsoft.Extensions.DependencyInjection;
 2using Spectre.Console;
 3using Spectre.Console.Cli;
 4using Orchestrator.Commands.Operations.Dev;
 5using Orchestrator.Commands.Operations.Matchday;
 6using Orchestrator.Commands.Operations.RandomMatch;
 7using Orchestrator.Commands.Operations.Bonus;
 8using Orchestrator.Commands.Operations.CollectContext;
 9using Orchestrator.Commands.Operations.Wm26RecentHistory;
 10using Orchestrator.Commands.Operations.Verify;
 11using Orchestrator.Commands.Observability.AnalyzeMatch;
 12using Orchestrator.Commands.Observability.ContextChanges;
 13using Orchestrator.Commands.Observability.Cost;
 14using Orchestrator.Commands.Observability.Experiments;
 15using Orchestrator.Commands.Observability.ExportExperimentAnalysis;
 16using Orchestrator.Commands.Observability.ExportExperimentItem;
 17using Orchestrator.Commands.Observability.PrepareCommunityToDate;
 18using Orchestrator.Commands.Observability.PrepareRepeatedMatch;
 19using Orchestrator.Commands.Observability.PrepareRepeatedMatchSlice;
 20using Orchestrator.Commands.Observability.PrepareSlice;
 21using Orchestrator.Commands.Observability.ReconstructPrompt;
 22using Orchestrator.Commands.Observability.SyncDataset;
 23using Orchestrator.Commands.Utility.UploadKpi;
 24using Orchestrator.Commands.Utility.UploadContext;
 25using Orchestrator.Commands.Utility.UploadTransfers;
 26using Orchestrator.Commands.Utility.CopyFirestoreContext;
 27using Orchestrator.Commands.Utility.ListKpi;
 28using Orchestrator.Commands.Utility.Snapshots;
 29using Orchestrator.Infrastructure;
 30
 31namespace Orchestrator;
 32
 33public class Program
 34{
 35    public static async Task<int> Main(string[] args)
 36    {
 137        var minimumLogLevel = LoggingConfiguration.GetMinimumLevelForCommandLine(args);
 38
 39        // Load environment variables once at startup
 140        var startupLogger = LoggingConfiguration.CreateLogger<Program>(minimumLogLevel);
 141        EnvironmentHelper.LoadEnvironmentVariables(startupLogger);
 42
 43        // Dependency Injection setup follows Spectre.Console.Cli patterns:
 44        // - Tutorial: https://github.com/spectreconsole/website/blob/main/Spectre.Docs/Content/cli/tutorials/dependency
 45        // - Testing: https://github.com/spectreconsole/website/blob/main/Spectre.Docs/Content/cli/how-to/testing-comman
 146        var services = new ServiceCollection();
 47
 48        // Register IAnsiConsole for dependency injection into commands
 149        services.AddSingleton<IAnsiConsole>(AnsiConsole.Console);
 50
 51        // Register all command services (factories and shared infrastructure)
 152        services.AddAllCommandServices(minimumLogLevel);
 53
 154        var registrar = new TypeRegistrar(services);
 155        var app = new CommandApp(registrar);
 56
 157        app.Configure(config =>
 158        {
 159            config.SetApplicationName("Orchestrator");
 160            config.SetApplicationVersion("1.0.0");
 161
 162            config.AddCommand<MatchdayCommand>("matchday")
 163                .WithDescription("Generate predictions for the current matchday")
 164                .WithExample("matchday", "gpt-4o-2024-08-06", "--community", "ehonda-test-buli");
 165
 166            config.AddCommand<MatchdayDevCommand>("matchday-dev")
 167                .WithDescription("Generate and post matchday predictions using guarded development-community defaults")
 168                .WithExample("matchday-dev", "--community", "ehonda-dev-wm26");
 169
 170            config.AddCommand<CollectContextDevCommand>("collect-context-dev")
 171                .WithDescription("Collect Kicktipp, FIFA ranking, and lineup context using guarded development-community
 172                .WithExample("collect-context-dev", "--community", "ehonda-dev-wm26", "--verbose");
 173
 174            config.AddCommand<RandomMatchCommand>("random-match")
 175                .WithDescription("Generate a prediction for a random match from the current matchday (useful for testing
 176                .WithExample("random-match", "gpt-5-nano", "--community", "ehonda-test-buli");
 177
 178            config.AddBranch("analyze-match", analyzeMatch =>
 179            {
 180                analyzeMatch.SetDescription("Analyze prediction distributions for a single match without persisting resu
 181
 182                analyzeMatch.AddCommand<AnalyzeMatchDetailedCommand>("detailed")
 183                    .WithDescription("Detailed analysis with justification output and live estimates")
 184                    .WithExample(
 185                        "analyze-match",
 186                        "detailed",
 187                        "gpt-5-nano",
 188                        "--community-context",
 189                        "ehonda-test-buli",
 190                        "--home",
 191                        "FC Bayern München",
 192                        "--away",
 193                        "RB Leipzig",
 194                        "--matchday",
 195                        "1",
 196                        "--runs",
 197                        "5");
 198
 199                analyzeMatch.AddCommand<AnalyzeMatchComparisonCommand>("comparison")
 1100                    .WithDescription("Compare predictions generated with and without justification")
 1101                    .WithExample(
 1102                        "analyze-match",
 1103                        "comparison",
 1104                        "gpt-5-nano",
 1105                        "--community-context",
 1106                        "ehonda-test-buli",
 1107                        "--home",
 1108                        "FC Bayern München",
 1109                        "--away",
 1110                        "RB Leipzig",
 1111                        "--matchday",
 1112                        "1",
 1113                        "--runs",
 1114                        "5");
 1115            });
 1116
 1117            config.AddCommand<BonusCommand>("bonus")
 1118                .WithDescription("Generate bonus predictions")
 1119                .WithExample("bonus", "gpt-4o-2024-08-06", "--community", "ehonda-test-buli");
 1120
 1121            config.AddCommand<BonusDevCommand>("bonus-dev")
 1122                .WithDescription("Generate and post bonus predictions using guarded development-community defaults")
 1123                .WithExample("bonus-dev", "--community", "ehonda-dev-wm26");
 1124
 1125            config.AddBranch<CollectContextSettings>("collect-context", collectContext =>
 1126            {
 1127                collectContext.SetDescription("Collect context documents and store them in database");
 1128                collectContext.AddCommand<CollectContextKicktippCommand>("kicktipp")
 1129                    .WithDescription("Collect context from Kicktipp")
 1130                    .WithExample("collect-context", "kicktipp", "--community-context", "ehonda-test-buli", "--dry-run");
 1131                collectContext.AddCommand<CollectContextFifaCommand>("fifa")
 1132                    .WithDescription("Fetch and upload WM26 FIFA ranking context and KPI documents")
 1133                    .WithExample("collect-context", "fifa", "--community-context", "ehonda-dev-wm26", "--dry-run");
 1134                collectContext.AddCommand<CollectContextLineupsCommand>("lineups")
 1135                    .WithDescription("Refresh and upload WM26 lineup context and KPI documents")
 1136                    .WithExample("collect-context", "lineups", "--community-context", "ehonda-dev-wm26", "--dry-run");
 1137            });
 1138
 1139            config.AddBranch<Wm26RecentHistorySettings>("wm26-recent-history", wm26RecentHistory =>
 1140            {
 1141                wm26RecentHistory.SetDescription("Export and apply exact played dates for WM26 recent-history context do
 1142                wm26RecentHistory.AddCommand<Wm26RecentHistoryExportDateMapCommand>("export-date-map")
 1143                    .WithDescription("Export recent-history rows to the canonical WM26 played-date map")
 1144                    .WithExample(
 1145                        "wm26-recent-history",
 1146                        "export-date-map",
 1147                        "--community-context",
 1148                        "ehonda-dev-wm26",
 1149                        "--competition",
 1150                        "fifa-world-cup-2026",
 1151                        "--output",
 1152                        "data/wm26/recent-history/recent-history-match-dates.csv");
 1153                wm26RecentHistory.AddCommand<Wm26RecentHistoryApplyDateMapCommand>("apply-date-map")
 1154                    .WithDescription("Apply the canonical WM26 played-date map to recent-history documents")
 1155                    .WithExample(
 1156                        "wm26-recent-history",
 1157                        "apply-date-map",
 1158                        "--community-context",
 1159                        "ehonda-dev-wm26",
 1160                        "--competition",
 1161                        "fifa-world-cup-2026",
 1162                        "--input",
 1163                        "data/wm26/recent-history/recent-history-match-dates.csv",
 1164                        "--dry-run");
 1165                wm26RecentHistory.AddCommand<Wm26RecentHistoryProbePredictionLookupCommand>("probe-prediction-lookup")
 1166                    .WithDescription("Probe the DB-side latest predicted-match lookup used for WM26 tournament Played_At
 1167                    .WithExample(
 1168                        "wm26-recent-history",
 1169                        "probe-prediction-lookup",
 1170                        "--community-context",
 1171                        "ehonda-dev-wm26",
 1172                        "--competition",
 1173                        "fifa-world-cup-2026",
 1174                        "--home-team",
 1175                        "Mexiko",
 1176                        "--away-team",
 1177                        "Südafrika",
 1178                        "--verbose");
 1179            });
 1180
 1181            config.AddCommand<VerifyMatchdayCommand>("verify")
 1182                .WithDescription("Verify that database predictions have been successfully posted to Kicktipp")
 1183                .WithExample("verify", "gpt-4o-2024-08-06", "--community", "ehonda-test-buli");
 1184
 1185            config.AddCommand<VerifyBonusCommand>("verify-bonus")
 1186                .WithDescription("Verify that database bonus predictions are valid and complete")
 1187                .WithExample("verify-bonus", "gpt-4o-2024-08-06", "--community", "ehonda-test-buli");
 1188
 1189            config.AddCommand<UploadKpiCommand>("upload-kpi")
 1190                .WithDescription("Upload a KPI context document to Firebase")
 1191                .WithExample("upload-kpi", "team-data", "--community", "ehonda-test-buli");
 1192
 1193            config.AddCommand<UploadContextCommand>("upload-context")
 1194                .WithDescription("Upload a generic context document JSON to Firebase")
 1195                .WithExample("upload-context", "--input", "lineup-exampleland.csv.json", "--competition", "fifa-world-cu
 1196
 1197            config.AddCommand<CopyFirestoreContextCommand>("copy-firestore-context")
 1198                .WithDescription("Copy Firestore context and KPI documents between community contexts")
 1199                .WithExample(
 1200                    "copy-firestore-context",
 1201                    "--source-community-context",
 1202                    "ehonda-dev-wm26",
 1203                    "--target-community-context",
 1204                    "new-wm26-community",
 1205                    "--competition",
 1206                    "fifa-world-cup-2026",
 1207                    "--context-prefix",
 1208                    "lineup-",
 1209                    "--kpi-document",
 1210                    "lineups");
 1211
 1212            config.AddCommand<UploadTransfersCommand>("upload-transfers")
 1213                .WithDescription("Upload a transfers context document to Firebase (team transfers CSV)")
 1214                .WithExample("upload-transfers", "fcb", "--community-context", "ehonda-test-buli");
 1215
 1216            config.AddCommand<ListKpiCommand>("list-kpi")
 1217                .WithDescription("List KPI context documents from Firebase")
 1218                .WithExample("list-kpi", "--community", "ehonda-test-buli");
 1219
 1220            config.AddCommand<ContextChangesCommand>("context-changes")
 1221                .WithDescription("Show changes between latest and previous versions of context documents")
 1222                .WithExample("context-changes", "--community-context", "ehonda-test-buli", "--count", "5")
 1223                .WithExample("context-changes", "--community-context", "ehonda-test-buli", "--seed", "42");
 1224
 1225            config.AddCommand<ReconstructPromptCommand>("reconstruct-prompt")
 1226                .WithDescription("Reconstruct the historical prompt inputs for a stored match prediction")
 1227                .WithExample("reconstruct-prompt", "o4-mini", "--community-context", "pes-squad", "--home", "VfB Stuttga
 1228                .WithExample("reconstruct-prompt", "o4-mini", "--community-context", "pes-squad", "--home", "VfB Stuttga
 1229                .WithExample("reconstruct-prompt", "o4-mini", "--community-context", "pes-squad", "--home", "VfB Stuttga
 1230
 1231            config.AddCommand<ExportExperimentItemCommand>("export-experiment-item")
 1232                .WithDescription("Export a single historical match experiment item for runner testing")
 1233                .WithExample("export-experiment-item", "o4-mini", "--community-context", "pes-squad", "--home", "VfB Stu
 1234                .WithExample("export-experiment-item", "o4-mini", "--community-context", "pes-squad", "--home", "VfB Stu
 1235                .WithExample("export-experiment-item", "o4-mini", "--community-context", "pes-squad", "--home", "VfB Stu
 1236
 1237            config.AddCommand<ExportExperimentAnalysisCommand>("export-experiment-analysis")
 1238                .WithDescription("Export a normalized analysis bundle for comparable Langfuse experiment runs")
 1239                .WithExample(
 1240                    "export-experiment-analysis",
 1241                    "--dataset-name",
 1242                    "match-predictions/bundesliga-2025-26/pes-squad/slices/all-matchdays/random-16-seed-20260403",
 1243                    "--run-names",
 1244                    "slice__pes-squad__o3__prompt-v1__random-16-seed-20260403__startsat-12h__2026-04-03t12-00-00z,slice_
 1245                .WithExample(
 1246                    "export-experiment-analysis",
 1247                    "--dataset-name",
 1248                    "match-predictions/bundesliga-2025-26/pes-squad/repeated-match/md26-vfb-stuttgart-vs-rb-leipzig/repe
 1249                    "--run-names",
 1250                    "repeated-match__pes-squad__o3__prompt-v1__repeat-16__exact-time__2026-03-15t12-00-00z,repeated-matc
 1251                    "--output",
 1252                    "artifacts/langfuse-experiments/analysis/repeated-match/pes-squad-repeat-16.json");
 1253
 1254            config.AddCommand<PublishExperimentAnalysisCommand>("publish-experiment-analysis")
 1255                .WithDescription("Publish an existing analysis bundle as Langfuse Experiments Beta-visible run aliases")
 1256                .WithExample(
 1257                    "publish-experiment-analysis",
 1258                    "--input",
 1259                    "artifacts/langfuse-experiments/analysis/task-5/match-predictions/bundesliga-2025-26/pes-squad/slice
 1260                    "--replace-runs");
 1261
 1262            config.AddCommand<PrepareSliceCommand>("prepare-slice")
 1263                .WithDescription("Create a reusable sampled slice artifact and manifest directly from completed historic
 1264                .WithExample("prepare-slice", "--community-context", "pes-squad", "--sample-size", "16", "--sample-seed"
 1265                .WithExample("prepare-slice", "--community-context", "pes-squad", "--matchdays", "26", "--sample-size", 
 1266                .WithExample("prepare-slice", "--community-context", "pes-squad", "--sample-size", "10", "--starts-after
 1267
 1268            config.AddCommand<PrepareRepeatedMatchCommand>("prepare-repeated-match")
 1269                .WithDescription("Create a repeated-match dataset and manifest for a single historical fixture")
 1270                .WithExample("prepare-repeated-match", "--community-context", "pes-squad", "--home", "VfB Stuttgart", "-
 1271                .WithExample("prepare-repeated-match", "--community-context", "pes-squad", "--home", "VfB Stuttgart", "-
 1272
 1273            config.AddCommand<PrepareRepeatedMatchSliceCommand>("prepare-repeated-match-slice")
 1274                .WithDescription("Create a repeated-match slice dataset and manifest from random historical fixtures")
 1275                .WithExample("prepare-repeated-match-slice", "--community-context", "pes-squad", "--match-count", "15", 
 1276                .WithExample("prepare-repeated-match-slice", "--community-context", "pes-squad", "--matchdays", "1,2,3",
 1277
 1278            config.AddCommand<PrepareCommunityToDateCommand>("prepare-community-to-date")
 1279                .WithDescription("Create a Kicktipp community-to-date dataset and manifest from finished tippuebersicht 
 1280                .WithExample("prepare-community-to-date", "--community-context", "ehonda-ai-arena", "--cutoff-matchday",
 1281                .WithExample("prepare-community-to-date", "--community-context", "ehonda-ai-arena", "--output-directory"
 1282
 1283            config.AddCommand<SyncDatasetCommand>("sync-dataset")
 1284                .WithDescription("Sync an exported hosted experiment dataset artifact to Langfuse via the public API")
 1285                .WithExample("sync-dataset", "--input", "artifacts/langfuse-experiments/slices/pes-squad/all-matchdays/r
 1286
 1287            config.AddCommand<RunSliceCommand>("run-slice")
 1288                .WithDescription("Run a prepared slice dataset directly via IPredictionService and the Langfuse public A
 1289                .WithExample("run-slice", "gpt-5-nano", "--manifest", "artifacts/langfuse-experiments/slices/pes-squad/a
 1290                .WithExample("run-slice", "o3", "--manifest", "artifacts/langfuse-experiments/slices/pes-squad/matchdays
 1291
 1292            config.AddCommand<RunRepeatedMatchCommand>("run-repeated-match")
 1293                .WithDescription("Run a prepared repeated-match dataset with warmup-plus-batches execution")
 1294                .WithExample("run-repeated-match", "o3", "--manifest", "artifacts/langfuse-experiments/repeated-match/pe
 1295
 1296            config.AddCommand<RunRepeatedMatchSliceCommand>("run-repeated-match-slice")
 1297                .WithDescription("Run a prepared repeated-match slice dataset with per-fixture warmup-plus-batches execu
 1298                .WithExample("run-repeated-match-slice", "gpt-5.4-nano", "--manifest", "artifacts/langfuse-experiments/r
 1299
 1300            config.AddCommand<RunCommunityToDateCommand>("run-community-to-date")
 1301                .WithDescription("Run a prepared community-to-date dataset as one Langfuse dataset run per participant")
 1302                .WithExample("run-community-to-date", "--manifest", "artifacts/langfuse-experiments/community-to-date/eh
 1303                .WithExample("run-community-to-date", "--manifest", "artifacts/langfuse-experiments/community-to-date/eh
 1304
 1305            config.AddCommand<CostCommand>("cost")
 1306                .WithDescription("Calculate aggregate costs for predictions")
 1307                .WithExample("cost", "--all")
 1308                .WithExample("cost", "--matchdays", "1,2,3")
 1309                .WithExample("cost", "--models", "gpt-4o,o1-mini", "--bonus");
 1310
 1311            config.AddBranch("snapshots", snapshots =>
 1312            {
 1313                snapshots.SetDescription("Generate and encrypt HTML snapshots from Kicktipp for test fixtures");
 1314
 1315                snapshots.AddCommand<SnapshotsFetchCommand>("fetch")
 1316                    .WithDescription("Fetch HTML snapshots from Kicktipp")
 1317                    .WithExample("snapshots", "fetch", "--community", "ehonda-test-buli")
 1318                    .WithExample("snapshots", "fetch", "--community", "ehonda-test-buli", "--output", "my-snapshots");
 1319
 1320                snapshots.AddCommand<SnapshotsEncryptCommand>("encrypt")
 1321                    .WithDescription("Encrypt HTML snapshots for safe committing")
 1322                    .WithExample("snapshots", "encrypt")
 1323                    .WithExample("snapshots", "encrypt", "--input", "my-snapshots", "--output", "tests/KicktippIntegrati
 1324
 1325                snapshots.AddCommand<SnapshotsAllCommand>("all")
 1326                    .WithDescription("Fetch and encrypt snapshots in one step")
 1327                    .WithExample("snapshots", "all", "--community", "ehonda-test-buli")
 1328                    .WithExample("snapshots", "all", "--community", "ehonda-test-buli", "--keep-originals");
 1329            });
 1330        });
 331
 1332        return await app.RunAsync(args);
 1333    }
 334}

Methods/Properties

Main()