@@ -200,9 +200,9 @@ func TestRenderJourneyDeltaCommentShowsTokenClassBreakdown(t *testing.T) {
200200 t .Fatalf ("comment body missing the data row:\n %s" , body )
201201 }
202202 cells := strings .Split (row , "|" )
203- // | (empty) | Scenario | Runtime | Model | Turns Δ | Cache Read Δ | Cache Creation Δ | Tokens Δ (total) | Cost Δ (USD) | Baseline | (empty) |
204- if len (cells ) != 11 {
205- t .Fatalf ("data row has %d cells, want 11 (header shape changed?): %q" , len (cells ), row )
203+ // | (empty) | Scenario | Runtime | Model | Turns Δ | Cache Read Δ | Cache Creation Δ | Tokens Δ (total) | Cost Δ (USD) | Duration Δ (ms) | Baseline | (empty) |
204+ if len (cells ) != 12 {
205+ t .Fatalf ("data row has %d cells, want 12 (header shape changed?): %q" , len (cells ), row )
206206 }
207207 cacheReadCell := strings .TrimSpace (cells [5 ])
208208 cacheCreationCell := strings .TrimSpace (cells [6 ])
@@ -218,6 +218,57 @@ func TestRenderJourneyDeltaCommentShowsTokenClassBreakdown(t *testing.T) {
218218 }
219219}
220220
221+ // TestJourneyDeltaCommentShowsDurationDelta is the TDD proof for the
222+ // wallclock/duration delta: computes deltas from a baseline ledger and a
223+ // current PR run with distinct DurationMS values, then asserts both the
224+ // computed struct field and the rendered comment's Duration Δ column show the
225+ // exact millisecond delta (current - baseline), not a total or a placeholder.
226+ func TestJourneyDeltaCommentShowsDurationDelta (t * testing.T ) {
227+ baseline := journeymetrics.Ledger {
228+ Scenarios : []journeymetrics.ScenarioLedgerEntry {
229+ {
230+ ScenarioID : "shallow-boot-window" ,
231+ Observations : []journeymetrics.Record {
232+ {
233+ ScenarioID : "shallow-boot-window" , Runtime : "claude" , Model : "claude-sonnet-4-6" ,
234+ DurationMS : 12000 , CapturedAt : "2026-06-20T00:00:00Z" ,
235+ RunURL : "https://github.com/spacedock-dev/spacedock/actions/runs/27931963802" ,
236+ },
237+ },
238+ },
239+ },
240+ }
241+ current := []journeymetrics.Record {
242+ {
243+ ScenarioID : "shallow-boot-window" , Runtime : "claude" , Model : "claude-sonnet-4-6" ,
244+ DurationMS : 15500 ,
245+ },
246+ }
247+
248+ deltas := ComputeJourneyDeltas (baseline , current )
249+ if len (deltas ) != 1 {
250+ t .Fatalf ("deltas = %d, want 1" , len (deltas ))
251+ }
252+ if deltas [0 ].DurationMSDelta != 3500 {
253+ t .Fatalf ("DurationMSDelta = %d, want 3500 (15500-12000)" , deltas [0 ].DurationMSDelta )
254+ }
255+
256+ body := RenderJourneyDeltaComment (deltas )
257+ var row string
258+ for _ , line := range strings .Split (body , "\n " ) {
259+ if strings .HasPrefix (line , "| shallow-boot-window" ) {
260+ row = line
261+ break
262+ }
263+ }
264+ if row == "" {
265+ t .Fatalf ("comment body missing the data row:\n %s" , body )
266+ }
267+ if ! strings .Contains (row , "+3500" ) {
268+ t .Fatalf ("data row missing Duration Δ +3500(ms): %q" , row )
269+ }
270+ }
271+
221272// TestRenderJourneyDeltaCommentRendersNoBaselineAsNewNotSelfDelta proves a
222273// scenario/model with no matching baseline observation renders "n/a (new)" in
223274// its delta cells rather than a self-delta against an implicit zero baseline
0 commit comments