helixevo 0.2.23 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,26 +1,31 @@
1
+ import Link from 'next/link'
1
2
  import { getDashboardSummary, loadFrontier, loadHistory, loadGraph, loadFailures, listProjects } from '@/lib/data'
2
3
  import { OverviewActions } from '@/components/overview-actions'
3
4
 
4
5
  export const dynamic = 'force-dynamic'
5
6
 
6
- function StatCard({ value, label, color, sub, accent }: { value: string | number; label: string; color: string; sub?: string; accent?: string }) {
7
+ function StatCard({ value, label, color, sub, accent, href }: {
8
+ value: string | number; label: string; color: string; sub?: string; accent?: string; href: string
9
+ }) {
7
10
  return (
8
- <div className="stat-card">
9
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
10
- <div>
11
- <div className="stat-value" style={{ color }}>{value}</div>
12
- <div className="stat-label">{label}</div>
13
- {sub && <div style={{ fontSize: 10, color: 'var(--text-muted)', marginTop: 2 }}>{sub}</div>}
11
+ <Link href={href} style={{ textDecoration: 'none', color: 'inherit' }}>
12
+ <div className="stat-card" style={{ cursor: 'pointer' }}>
13
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
14
+ <div>
15
+ <div className="stat-value" style={{ color }}>{value}</div>
16
+ <div className="stat-label">{label}</div>
17
+ {sub && <div style={{ fontSize: 10, color: 'var(--text-muted)', marginTop: 2 }}>{sub}</div>}
18
+ </div>
19
+ {accent && (
20
+ <div style={{
21
+ width: 36, height: 36, borderRadius: 10,
22
+ background: `${color}12`, display: 'flex', alignItems: 'center', justifyContent: 'center',
23
+ color, fontSize: 16,
24
+ }}>{accent}</div>
25
+ )}
14
26
  </div>
15
- {accent && (
16
- <div style={{
17
- width: 36, height: 36, borderRadius: 10,
18
- background: `${color}12`, display: 'flex', alignItems: 'center', justifyContent: 'center',
19
- color, fontSize: 16,
20
- }}>{accent}</div>
21
- )}
22
27
  </div>
23
- </div>
28
+ </Link>
24
29
  )
25
30
  }
26
31
 
@@ -56,18 +61,18 @@ export default function Overview() {
56
61
  />
57
62
  </div>
58
63
 
59
- {/* Stats */}
64
+ {/* Stats — all clickable, linking to relevant pages */}
60
65
  <div className="grid-5" style={{ marginBottom: 28 }}>
61
- <StatCard value={s.skills.total} label="Total Skills" color="var(--purple)" sub={`${s.skills.evolved} evolved`} accent="◆" />
62
- <StatCard value={s.evolution.accepted} label="Accepted" color="var(--green)" sub={`${s.evolution.rejected} rejected`} accent="✓" />
63
- <StatCard value={s.failures.unresolved} label="Unresolved" color="var(--yellow)" sub={`of ${s.failures.total} total`} accent="!" />
64
- <StatCard value={s.buffer.discoveries} label="Discoveries" color="var(--blue)" sub={`${s.buffer.drafts} drafts`} accent="◎" />
65
- <StatCard value={frontier.programs.length} label="Frontier" color="var(--text-secondary)" sub={`/${frontier.capacity} capacity`} accent="▲" />
66
+ <StatCard value={s.skills.total} label="Total Skills" color="var(--purple)" sub={`${s.skills.evolved} evolved`} accent="◆" href="/network" />
67
+ <StatCard value={s.evolution.accepted} label="Accepted" color="var(--green)" sub={`${s.evolution.rejected} rejected`} accent="✓" href="/evolution" />
68
+ <StatCard value={s.failures.unresolved} label="Unresolved" color="var(--yellow)" sub={`of ${s.failures.total} total`} accent="!" href="#unresolved" />
69
+ <StatCard value={s.buffer.discoveries} label="Discoveries" color="var(--blue)" sub={`${s.buffer.drafts} drafts`} accent="◎" href="/research" />
70
+ <StatCard value={frontier.programs.length} label="Frontier" color="var(--text-secondary)" sub={`/${frontier.capacity} capacity`} accent="▲" href="/frontier" />
66
71
  </div>
67
72
 
68
73
  {/* Unresolved Failures */}
69
74
  {failures.filter(f => !f.resolved).length > 0 && (
70
- <div className="card" style={{ marginBottom: 20 }}>
75
+ <div id="unresolved" className="card" style={{ marginBottom: 20 }}>
71
76
  <div className="card-body">
72
77
  <div className="card-header-label">
73
78
  Unresolved Corrections ({failures.filter(f => !f.resolved).length})
@@ -110,98 +115,104 @@ export default function Overview() {
110
115
 
111
116
  <div className="grid-2">
112
117
  {/* Frontier */}
113
- <div className="card">
114
- <div className="card-body">
115
- <div className="card-header-label">Pareto Frontier</div>
116
- {frontier.programs.map((p, i) => (
117
- <div key={`${p.id}-${i}`} style={{
118
- padding: '12px 0',
119
- borderBottom: i < frontier.programs.length - 1 ? '1px solid var(--border-subtle)' : 'none',
120
- }}>
121
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
122
- <span style={{ fontSize: 13, fontWeight: 600 }}>{p.id}</span>
123
- <span style={{
124
- fontSize: 20, fontWeight: 800, lineHeight: 1,
125
- color: p.score >= 0.8 ? 'var(--green)' : 'var(--yellow)',
126
- }}>
127
- {(p.score * 100).toFixed(0)}
128
- </span>
129
- </div>
130
- <div style={{ display: 'flex', gap: 6, fontSize: 11 }}>
131
- <span className="score-pill" style={{ color: 'var(--green)' }}>T:{(p.scores.taskCompletion * 10).toFixed(0)}</span>
132
- <span className="score-pill" style={{ color: 'var(--blue)' }}>A:{(p.scores.correctionAlignment * 10).toFixed(0)}</span>
133
- <span className="score-pill" style={{ color: 'var(--purple)' }}>S:{(p.scores.sideEffectFree * 10).toFixed(0)}</span>
134
- </div>
135
- <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 4, lineHeight: 1.4 }}>
136
- {p.changesDescription.slice(0, 80)}
118
+ <Link href="/frontier" style={{ textDecoration: 'none', color: 'inherit' }}>
119
+ <div className="card" style={{ cursor: 'pointer', height: '100%' }}>
120
+ <div className="card-body">
121
+ <div className="card-header-label">Pareto Frontier</div>
122
+ {frontier.programs.map((p, i) => (
123
+ <div key={`${p.id}-${i}`} style={{
124
+ padding: '12px 0',
125
+ borderBottom: i < frontier.programs.length - 1 ? '1px solid var(--border-subtle)' : 'none',
126
+ }}>
127
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
128
+ <span style={{ fontSize: 13, fontWeight: 600 }}>{p.id}</span>
129
+ <span style={{
130
+ fontSize: 20, fontWeight: 800, lineHeight: 1,
131
+ color: p.score >= 0.8 ? 'var(--green)' : 'var(--yellow)',
132
+ }}>
133
+ {(p.score * 100).toFixed(0)}
134
+ </span>
135
+ </div>
136
+ <div style={{ display: 'flex', gap: 6, fontSize: 11 }}>
137
+ <span className="score-pill" style={{ color: 'var(--green)' }}>T:{(p.scores.taskCompletion * 10).toFixed(0)}</span>
138
+ <span className="score-pill" style={{ color: 'var(--blue)' }}>A:{(p.scores.correctionAlignment * 10).toFixed(0)}</span>
139
+ <span className="score-pill" style={{ color: 'var(--purple)' }}>S:{(p.scores.sideEffectFree * 10).toFixed(0)}</span>
140
+ </div>
141
+ <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 4, lineHeight: 1.4 }}>
142
+ {p.changesDescription.slice(0, 80)}
143
+ </div>
137
144
  </div>
138
- </div>
139
- ))}
145
+ ))}
146
+ </div>
140
147
  </div>
141
- </div>
148
+ </Link>
142
149
 
143
150
  {/* Recent Evolution */}
144
- <div className="card">
145
- <div className="card-body">
146
- <div className="card-header-label">Recent Evolution</div>
147
- {recent.map((iter, idx) => (
148
- <div key={`${iter.id}-${idx}`} style={{
149
- padding: '10px 0',
150
- borderBottom: '1px solid var(--border-subtle)',
151
- }}>
152
- <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, marginBottom: 8 }}>
153
- <span style={{ fontWeight: 600, color: 'var(--text)' }}>{iter.id}</span>
154
- <span style={{ color: 'var(--text-muted)' }}>{new Date(iter.timestamp).toLocaleDateString()}</span>
155
- </div>
156
- {iter.proposals.map(p => (
157
- <div key={p.id} style={{
158
- display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, marginBottom: 4,
159
- padding: '4px 0',
160
- }}>
161
- <span style={{
162
- width: 8, height: 8, borderRadius: '50%', flexShrink: 0,
163
- background: p.outcome === 'accepted' ? 'var(--green)' : 'var(--red)',
164
- }} />
165
- <span style={{ fontWeight: 500 }}>{p.targetSkill}</span>
166
- <span className="badge badge-gray" style={{ fontSize: 9 }}>{p.action}</span>
151
+ <Link href="/evolution" style={{ textDecoration: 'none', color: 'inherit' }}>
152
+ <div className="card" style={{ cursor: 'pointer', height: '100%' }}>
153
+ <div className="card-body">
154
+ <div className="card-header-label">Recent Evolution</div>
155
+ {recent.map((iter, idx) => (
156
+ <div key={`${iter.id}-${idx}`} style={{
157
+ padding: '10px 0',
158
+ borderBottom: '1px solid var(--border-subtle)',
159
+ }}>
160
+ <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, marginBottom: 8 }}>
161
+ <span style={{ fontWeight: 600, color: 'var(--text)' }}>{iter.id}</span>
162
+ <span style={{ color: 'var(--text-muted)' }}>{new Date(iter.timestamp).toLocaleDateString()}</span>
167
163
  </div>
168
- ))}
169
- </div>
170
- ))}
164
+ {iter.proposals.map(p => (
165
+ <div key={p.id} style={{
166
+ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, marginBottom: 4,
167
+ padding: '4px 0',
168
+ }}>
169
+ <span style={{
170
+ width: 8, height: 8, borderRadius: '50%', flexShrink: 0,
171
+ background: p.outcome === 'accepted' ? 'var(--green)' : 'var(--red)',
172
+ }} />
173
+ <span style={{ fontWeight: 500 }}>{p.targetSkill}</span>
174
+ <span className="badge badge-gray" style={{ fontSize: 9 }}>{p.action}</span>
175
+ </div>
176
+ ))}
177
+ </div>
178
+ ))}
179
+ </div>
171
180
  </div>
172
- </div>
181
+ </Link>
173
182
  </div>
174
183
 
175
184
  {/* All Skills Summary */}
176
- <div className="card" style={{ marginTop: 16 }}>
177
- <div className="card-body">
178
- <div className="card-header-label">All Skills</div>
179
- <div className="grid-2" style={{ gap: 6 }}>
180
- {graph.nodes.sort((a, b) => b.score - a.score).map(n => (
181
- <div key={n.id} style={{
182
- display: 'flex', alignItems: 'center', justifyContent: 'space-between',
183
- padding: '8px 12px', borderRadius: 8, background: 'var(--bg-section)',
184
- }}>
185
- <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
186
- <span style={{ fontSize: 13, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{n.name}</span>
187
- {n.generation > 0 && <span className="badge badge-green" style={{ fontSize: 9 }}>gen {n.generation}</span>}
188
- </div>
189
- <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 90, flexShrink: 0 }}>
190
- <div className="score-track" style={{ width: 50 }}>
191
- <div className="score-fill" style={{
192
- width: `${n.score * 100}%`,
193
- background: n.score >= 0.8 ? 'var(--green)' : n.score >= 0.6 ? 'var(--yellow)' : 'var(--red)',
194
- }} />
185
+ <Link href="/network" style={{ textDecoration: 'none', color: 'inherit' }}>
186
+ <div className="card" style={{ marginTop: 16, cursor: 'pointer' }}>
187
+ <div className="card-body">
188
+ <div className="card-header-label">All Skills</div>
189
+ <div className="grid-2" style={{ gap: 6 }}>
190
+ {graph.nodes.sort((a, b) => b.score - a.score).map(n => (
191
+ <div key={n.id} style={{
192
+ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
193
+ padding: '8px 12px', borderRadius: 8, background: 'var(--bg-section)',
194
+ }}>
195
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
196
+ <span style={{ fontSize: 13, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{n.name}</span>
197
+ {n.generation > 0 && <span className="badge badge-green" style={{ fontSize: 9 }}>gen {n.generation}</span>}
198
+ </div>
199
+ <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 90, flexShrink: 0 }}>
200
+ <div className="score-track" style={{ width: 50 }}>
201
+ <div className="score-fill" style={{
202
+ width: `${n.score * 100}%`,
203
+ background: n.score >= 0.8 ? 'var(--green)' : n.score >= 0.6 ? 'var(--yellow)' : 'var(--red)',
204
+ }} />
205
+ </div>
206
+ <span style={{ fontSize: 12, fontWeight: 600, color: n.score >= 0.8 ? 'var(--green)' : 'var(--yellow)' }}>
207
+ {(n.score * 100).toFixed(0)}
208
+ </span>
195
209
  </div>
196
- <span style={{ fontSize: 12, fontWeight: 600, color: n.score >= 0.8 ? 'var(--green)' : 'var(--yellow)' }}>
197
- {(n.score * 100).toFixed(0)}
198
- </span>
199
210
  </div>
200
- </div>
201
- ))}
211
+ ))}
212
+ </div>
202
213
  </div>
203
214
  </div>
204
- </div>
215
+ </Link>
205
216
  </div>
206
217
  )
207
218
  }
@@ -14,11 +14,11 @@ interface OverviewActionsProps {
14
14
  // Small inline SVG flow diagrams for each action
15
15
  function FlowDiagram({ steps, color }: { steps: string[]; color: string }) {
16
16
  return (
17
- <div style={{ display: 'flex', alignItems: 'center', gap: 0, marginTop: 8, marginBottom: 2 }}>
17
+ <div style={{ display: 'flex', alignItems: 'center', gap: 0, marginTop: 8, marginBottom: 2, flexWrap: 'wrap', rowGap: 4 }}>
18
18
  {steps.map((step, i) => (
19
19
  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
20
20
  <div style={{
21
- fontSize: 9, fontWeight: 600, padding: '2px 7px',
21
+ fontSize: 9, fontWeight: 600, padding: '2px 6px',
22
22
  background: i === steps.length - 1 ? `${color}18` : 'var(--bg-section)',
23
23
  color: i === steps.length - 1 ? color : 'var(--text-dim)',
24
24
  borderRadius: 4, whiteSpace: 'nowrap',
@@ -27,9 +27,7 @@ function FlowDiagram({ steps, color }: { steps: string[]; color: string }) {
27
27
  {step}
28
28
  </div>
29
29
  {i < steps.length - 1 && (
30
- <svg width="14" height="8" viewBox="0 0 14 8" style={{ flexShrink: 0 }}>
31
- <path d="M0 4h10M8 1l3 3-3 3" stroke={color} strokeWidth="1.2" fill="none" strokeLinecap="round" strokeLinejoin="round" opacity="0.5" />
32
- </svg>
30
+ <span style={{ fontSize: 9, color: 'var(--text-muted)', padding: '0 2px' }}>&rarr;</span>
33
31
  )}
34
32
  </div>
35
33
  ))}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helixevo",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "description": "Self-evolving skill ecosystem for AI agents. Skills and projects co-evolve through multi-judge evaluation and a Pareto frontier.",
5
5
  "type": "module",
6
6
  "bin": {