返回 DeepSeek-Reasonix
timeline.go
根目录 / cmd / e2ebench / timeline.go
1 package main
2
3 import (
4 "fmt"
5 "strings"
6 )
7
8 const timelineWidth = 48
9
10 // renderTimelines draws each checkpointed run's lifecycle as the argument-
11 // ending picture: start → first useful mutation → CORRECT → final, with the
12 // before/after-correct tallies underneath.
13 func renderTimelines(results []result) string {
14 var b strings.Builder
15 for _, r := range results {
16 if len(r.Checkpoints) == 0 || r.WallMs == 0 {
17 continue
18 }
19 if b.Len() == 0 {
20 b.WriteString("### Timelines\n\n")
21 }
22 fmt.Fprintf(&b, "`%s`\n\n```\n%s```\n\n", r.ID, taskTimeline(r))
23 }
24 return b.String()
25 }
26
27 func taskTimeline(r result) string {
28 pos := func(ms int64) int {
29 p := int(ms * timelineWidth / r.WallMs)
30 return min(max(p, 0), timelineWidth)
31 }
32 markers := []struct {
33 at int
34 label string
35 }{{0, "start"}}
36 if r.FirstUsefulMs > 0 {
37 markers = append(markers, struct {
38 at int
39 label string
40 }{pos(r.FirstUsefulMs), "useful mutation " + dur(r.FirstUsefulMs)})
41 }
42 if r.FirstCorrectMs > 0 {
43 markers = append(markers, struct {
44 at int
45 label string
46 }{pos(r.FirstCorrectMs), "CORRECT " + dur(r.FirstCorrectMs)})
47 }
48 markers = append(markers, struct {
49 at int
50 label string
51 }{timelineWidth, "final " + dur(r.WallMs)})
52
53 bar := []rune(strings.Repeat("─", timelineWidth+1))
54 for _, m := range markers {
55 bar[m.at] = '│'
56 }
57 var out strings.Builder
58 out.WriteString(string(bar) + "\n")
59 for _, m := range markers {
60 out.WriteString(strings.Repeat(" ", m.at) + "^ " + m.label + "\n")
61 }
62 if r.Passed && r.PostSolveWasteMs > 0 {
63 fmt.Fprintf(&out, "post-solve waste %s (%s of wall)\n", dur(r.PostSolveWasteMs), pct(int(r.PostSolveWasteMs), int(r.WallMs)))
64 }
65 if r.FirstCorrectMs > 0 {
66 fmt.Fprintf(&out, "rounds %d→%d · calls %d→%d · after correct: verifications %d · reviews %d · mutations %d\n",
67 r.RoundsBeforeCorrect, r.RoundsAfterCorrect,
68 r.CallsBeforeCorrect, r.CallsAfterCorrect,
69 r.VerifyAfterCorrect, r.ReviewsAfterCorrect, r.MutationsAfterCorrect)
70 }
71 return out.String()
72 }
73
74 // renderDiagnosis applies the decide-then-optimize tree to the measured
75 // signals and names the knife, in priority order: capability first (you
76 // cannot stop what never solves), damage second (safety bounds any stop
77 // policy), then the bigger of the termination tail and the exploration road.
78 func renderDiagnosis(results []result) string {
79 var wall, waste, ttfum int64
80 checkpointed, neverCorrect, damaged, withCorrect := 0, 0, 0, 0
81 for _, r := range results {
82 if len(r.Checkpoints) == 0 {
83 continue
84 }
85 checkpointed++
86 wall += r.WallMs
87 if r.FirstCorrectMs == 0 && !r.Passed {
88 neverCorrect++
89 continue
90 }
91 withCorrect++
92 if r.RegressedAfterCorrect {
93 damaged++
94 }
95 waste += r.PostSolveWasteMs
96 ttfum += r.FirstUsefulMs
97 }
98 if checkpointed == 0 || wall == 0 {
99 return ""
100 }
101 verdict := ""
102 switch {
103 case neverCorrect*100 >= checkpointed*30:
104 verdict = fmt.Sprintf("**never-correct dominates** (%s of runs) → reasoning quality: better verifier, subagent specialization, or a better model — latency work is premature", pct(neverCorrect, checkpointed))
105 case withCorrect > 0 && damaged*100 >= withCorrect*10:
106 verdict = fmt.Sprintf("**correct→incorrect regressions** (%s) → conservative stop policy plus a mutation-after-pass guard before anything else", pct(damaged, withCorrect))
107 case waste >= ttfum:
108 verdict = fmt.Sprintf("**post-solve waste dominates** (%s of wall vs TTFUM %s) → TaskContract + evidence graph + early termination", pct(int(waste), int(wall)), pct(int(ttfum), int(wall)))
109 default:
110 verdict = fmt.Sprintf("**exploration dominates** (TTFUM %s of wall vs waste %s) → fault localization, context retrieval, planner and tool choice", pct(int(ttfum), int(wall)), pct(int(waste), int(wall)))
111 }
112 return "**Diagnosis**: " + verdict + "\n\n"
113 }
114
114 lines GO