Expand multirun reporting: health summary, era durations, serving diagnostics, cash-flow detail
Balance Check / balance-simulation (push) Successful in 46s
Balance Check / multi-run-balance (push) Successful in 14m6s
CI / build-and-push (push) Successful in 46s

Propagate per-era duration/bottleneck, serving utilization, cash-flow nadir/peak,
and late-game revenue growth through the worker→CSV→interpret pipeline. Add
simulation health archetype classification, per-era bottleneck frequency,
unused-feature frequency table, failed-run AGI gate analysis, and log-scale
variance for exponential metrics. All new CSV columns parse defensively for
backward compatibility with older summary files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 20:55:49 -04:00
parent 62998d6cb2
commit 5aa9436368
3 changed files with 386 additions and 20 deletions
+32 -1
View File
@@ -66,8 +66,20 @@ interface WorkerResult {
connections: Array<{ from: string; to: string; score: number; evidence: string; diagnosis: string; events: number; eventLabel: string }>;
overallScore: number;
};
cashFlow: { bankruptcyRisks: number };
cashFlow: {
bankruptcyRisks: number;
minCash: { amount: number; tick: number };
peakCash: { amount: number; tick: number };
};
sanityChecks: { passed: boolean; errorCount: number };
perEraSummary: Array<{ era: string; durationTicks: number; bottleneckAtExit: string | null }>;
serving: {
meanUtilization: number;
pctOverloaded: number;
pctUnderloaded: number;
peakUtilization: number;
};
lateGameRevenueGrowthRate: number;
metrics: SimulationMetrics[];
}
@@ -119,6 +131,12 @@ function buildSummaryCsv(results: WorkerResult[]): string {
...interconnectionKeys,
'eraTransition_scaleup', 'eraTransition_bigtech', 'eraTransition_agi',
'bankruptcyRisks', 'sanityErrors', 'failureReasons',
'duration_startup', 'duration_scaleup', 'duration_bigtech', 'duration_agi',
'bottleneck_scaleup', 'bottleneck_bigtech', 'bottleneck_agi',
'servingMeanUtil', 'servingPctOverloaded', 'servingPctUnderloaded', 'servingPeakUtil',
'cashMinAmount', 'cashMinTick', 'cashPeakAmount', 'cashPeakTick',
'lateGameRevenueGrowthRate',
'unusedFeatures',
];
const rows = results.map(r => {
@@ -137,6 +155,13 @@ function buildSummaryCsv(results: WorkerResult[]): string {
const icScores = ic.connections.map(c => c.score);
const durationMap: Record<string, number | ''> = { startup: '', scaleup: '', bigtech: '', agi: '' };
const bottleneckMap: Record<string, string> = { scaleup: '', bigtech: '', agi: '' };
for (const es of r.perEraSummary) {
durationMap[es.era] = es.durationTicks;
if (es.bottleneckAtExit) bottleneckMap[es.era] = es.bottleneckAtExit;
}
return [
r.runId, r.seed, r.passed ? 1 : 0, r.wallTimeMs,
fm?.era ?? '', fm?.money ?? '', fm?.revenue ?? '', fm?.totalRevenue ?? '',
@@ -155,6 +180,12 @@ function buildSummaryCsv(results: WorkerResult[]): string {
r.cashFlow.bankruptcyRisks,
r.sanityChecks.errorCount,
`"${r.failureReasons.join('; ').replace(/"/g, '""')}"`,
durationMap.startup, durationMap.scaleup, durationMap.bigtech, durationMap.agi,
bottleneckMap.scaleup, bottleneckMap.bigtech, bottleneckMap.agi,
r.serving.meanUtilization, r.serving.pctOverloaded, r.serving.pctUnderloaded, r.serving.peakUtilization,
r.cashFlow.minCash.amount, r.cashFlow.minCash.tick, r.cashFlow.peakCash.amount, r.cashFlow.peakCash.tick,
r.lateGameRevenueGrowthRate,
`"${fu.unusedFeatures.join(';').replace(/"/g, '""')}"`,
].join(',');
});