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.
package/dashboard/app/page.tsx
CHANGED
|
@@ -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 }: {
|
|
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
|
-
<
|
|
9
|
-
<div style={{
|
|
10
|
-
<div>
|
|
11
|
-
<div
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
</
|
|
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
|
-
<
|
|
114
|
-
<div className="card
|
|
115
|
-
<div className="card-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
{
|
|
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
|
-
|
|
139
|
-
|
|
145
|
+
))}
|
|
146
|
+
</div>
|
|
140
147
|
</div>
|
|
141
|
-
</
|
|
148
|
+
</Link>
|
|
142
149
|
|
|
143
150
|
{/* Recent Evolution */}
|
|
144
|
-
<
|
|
145
|
-
<div className="card
|
|
146
|
-
<div className="card-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
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
|
-
</
|
|
181
|
+
</Link>
|
|
173
182
|
</div>
|
|
174
183
|
|
|
175
184
|
{/* All Skills Summary */}
|
|
176
|
-
<
|
|
177
|
-
<div className="card
|
|
178
|
-
<div className="card-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
<div
|
|
191
|
-
<div className="score-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
201
|
-
|
|
211
|
+
))}
|
|
212
|
+
</div>
|
|
202
213
|
</div>
|
|
203
214
|
</div>
|
|
204
|
-
</
|
|
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
|
|
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
|
-
<
|
|
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' }}>→</span>
|
|
33
31
|
)}
|
|
34
32
|
</div>
|
|
35
33
|
))}
|
package/package.json
CHANGED