diff --git a/app/Console/Commands/SessionSummary.php b/app/Console/Commands/SessionSummary.php
index 581002e..e83b116 100644
--- a/app/Console/Commands/SessionSummary.php
+++ b/app/Console/Commands/SessionSummary.php
@@ -69,11 +69,19 @@ public function handle(): int
'engine' => $run->engine,
'config_name' => $run->config_name,
'ran_at' => $run->ran_at,
- 'passed' => 0,
- 'failed' => 0,
- 'tokens' => 0,
- 'ln_sum' => 0.0,
- 'ln_n' => 0,
+ // Devlogic totals: softbench, prosebench, psychbench,
+ // depthsweep — everything except infrabench and scenariobench.
+ 'dl_passed' => 0,
+ 'dl_failed' => 0,
+ 'dl_tokens' => 0,
+ 'dl_ln_sum' => 0.0,
+ 'dl_ln_n' => 0,
+ // Sysops totals: infrabench and scenariobench.
+ 'so_passed' => 0,
+ 'so_failed' => 0,
+ 'so_tokens' => 0,
+ 'so_ln_sum' => 0.0,
+ 'so_ln_n' => 0,
'runs' => collect(),
];
@@ -88,25 +96,39 @@ public function handle(): int
$aggs = $this->aggregateRun($run);
- $sessions[$key]['passed'] += $aggs->sum('passed');
- $sessions[$key]['failed'] += $aggs->sum('failed');
- $sessions[$key]['tokens'] += $aggs->sum('total_tokens');
- $sessions[$key]['ln_sum'] += $aggs->sum('ln_sum');
- $sessions[$key]['ln_n'] += $aggs->sum('ln_n');
+ // Route the aggregation to the correct total bucket.
+ $isSysops = $run->suite === 'infrabench';
+
$sessions[$key]['runs'] = $sessions[$key]['runs']->merge($aggs);
+
+ if ($isSysops) {
+ $sessions[$key]['so_passed'] += $aggs->sum('passed');
+ $sessions[$key]['so_failed'] += $aggs->sum('failed');
+ $sessions[$key]['so_tokens'] += $aggs->sum('total_tokens');
+ $sessions[$key]['so_ln_sum'] += $aggs->sum('ln_sum');
+ $sessions[$key]['so_ln_n'] += $aggs->sum('ln_n');
+ } else {
+ $sessions[$key]['dl_passed'] += $aggs->sum('passed');
+ $sessions[$key]['dl_failed'] += $aggs->sum('failed');
+ $sessions[$key]['dl_tokens'] += $aggs->sum('total_tokens');
+ $sessions[$key]['dl_ln_sum'] += $aggs->sum('ln_sum');
+ $sessions[$key]['dl_ln_n'] += $aggs->sum('ln_n');
+ }
}
// Second pass: emit one aggregated scenariobench row per band,
- // covering all scenario runs in that band.
+ // covering all scenario runs in that band. Scenariobench is sysops.
foreach ($sessions as $key => $band) {
$scenarioRuns = $band['scenario_runs'] ?? [];
if (empty($scenarioRuns)) {
continue;
}
$agg = $this->aggregateScenarioBand($scenarioRuns);
- $sessions[$key]['passed'] += $agg['passed'];
- $sessions[$key]['failed'] += $agg['failed'];
- $sessions[$key]['tokens'] += $agg['total_tokens'];
+ $sessions[$key]['so_passed'] += $agg['passed'];
+ $sessions[$key]['so_failed'] += $agg['failed'];
+ $sessions[$key]['so_tokens'] += $agg['total_tokens'];
+ $sessions[$key]['so_ln_sum'] += $agg['ln_sum'] ?? 0;
+ $sessions[$key]['so_ln_n'] += $agg['ln_n'] ?? 0;
$sessions[$key]['runs'] = $band['runs']->merge([$agg]);
}
@@ -127,11 +149,17 @@ public function handle(): int
'engine' => $band['engine'],
'config_name' => $band['config_name'],
'ran_at' => $band['ran_at'],
- 'total_passed' => $band['passed'],
- 'total_failed' => $band['failed'],
- 'total_tokens' => $band['tokens'],
- 'total_tps' => $band['ln_n'] > 0
- ? round(exp($band['ln_sum'] / $band['ln_n']), 1)
+ 'devlogic_passed' => $band['dl_passed'],
+ 'devlogic_failed' => $band['dl_failed'],
+ 'devlogic_tokens' => $band['dl_tokens'],
+ 'devlogic_tps' => $band['dl_ln_n'] > 0
+ ? round(exp($band['dl_ln_sum'] / $band['dl_ln_n']), 1)
+ : null,
+ 'sysops_passed' => $band['so_passed'],
+ 'sysops_failed' => $band['so_failed'],
+ 'sysops_tokens' => $band['so_tokens'],
+ 'sysops_tps' => $band['so_ln_n'] > 0
+ ? round(exp($band['so_ln_sum'] / $band['so_ln_n']), 1)
: null,
'sequence' => $bandIndex,
'created_at' => now(),
@@ -287,6 +315,8 @@ private function aggregateScenarioBand(array $runs): array
->selectRaw('count(*) filter (where not ok) as failed')
->selectRaw('sum(gen_tokens) as total_tokens')
->selectRaw('sum(gen_tokens) / nullif(sum(wall), 0) as gen_tps')
+ ->selectRaw('sum(ln(gen_tokens / nullif(wall, 0))) filter (where gen_tokens > 0 and wall > 0) as ln_sum')
+ ->selectRaw('count(*) filter (where gen_tokens > 0 and wall > 0) as ln_n')
->first();
// Thinking level: keep it only when every scenario row in the band
@@ -306,6 +336,8 @@ private function aggregateScenarioBand(array $runs): array
'weighted_user_tps' => null,
'gen_tps' => $this->roundOrNull($agg->gen_tps),
'total_tokens' => (int) ($agg->total_tokens ?? 0),
+ 'ln_sum' => (float) ($agg->ln_sum ?? 0),
+ 'ln_n' => (int) ($agg->ln_n ?? 0),
];
}
diff --git a/database/migrations/2026_10_04_000001_split_band_totals.php b/database/migrations/2026_10_04_000001_split_band_totals.php
new file mode 100644
index 0000000..f971af4
--- /dev/null
+++ b/database/migrations/2026_10_04_000001_split_band_totals.php
@@ -0,0 +1,46 @@
+decimal('devlogic_tps', 10, 1)->nullable()
+ ->comment('Geo-mean tok/s across devlogic suites (softbench, prosebench, psychbench, depthsweep, …)');
+ $table->unsignedInteger('devlogic_tokens')->default(0);
+ $table->unsignedInteger('devlogic_passed')->default(0);
+ $table->unsignedInteger('devlogic_failed')->default(0);
+
+ $table->decimal('sysops_tps', 10, 1)->nullable()
+ ->comment('Geo-mean tok/s across sysops suites (infrabench, scenariobench)');
+ $table->unsignedInteger('sysops_tokens')->default(0);
+ $table->unsignedInteger('sysops_passed')->default(0);
+ $table->unsignedInteger('sysops_failed')->default(0);
+ });
+
+ Schema::table('session_summaries', function (Blueprint $table) {
+ $table->dropColumn(['total_tps', 'total_tokens', 'total_passed', 'total_failed']);
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::table('session_summaries', function (Blueprint $table) {
+ $table->decimal('total_tps', 10, 1)->nullable()->after('ran_at');
+ $table->unsignedInteger('total_tokens')->default(0);
+ $table->unsignedInteger('total_passed')->default(0);
+ $table->unsignedInteger('total_failed')->default(0);
+ });
+
+ Schema::table('session_summaries', function (Blueprint $table) {
+ $table->dropColumn([
+ 'devlogic_tps', 'devlogic_tokens', 'devlogic_passed', 'devlogic_failed',
+ 'sysops_tps', 'sysops_tokens', 'sysops_passed', 'sysops_failed',
+ ]);
+ });
+ }
+};
diff --git a/resources/views/livewire/summary/index.blade.php b/resources/views/livewire/summary/index.blade.php
index 45292b3..19617f7 100644
--- a/resources/views/livewire/summary/index.blade.php
+++ b/resources/views/livewire/summary/index.blade.php
@@ -160,29 +160,47 @@ class="w-64"
@if ($session->band->engine)