helixevo 0.2.39 → 0.2.41
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/CHANGELOG.md +26 -0
- package/dashboard/app/changelog/page.tsx +179 -54
- package/dashboard/app/commands/page.tsx +243 -159
- package/dashboard/app/evolution/page.tsx +105 -102
- package/dashboard/app/frontier/page.tsx +103 -100
- package/dashboard/app/globals.css +1105 -403
- package/dashboard/app/guide/page.tsx +48 -4
- package/dashboard/app/layout.tsx +28 -57
- package/dashboard/app/network/client.tsx +453 -269
- package/dashboard/app/network/page.tsx +12 -2
- package/dashboard/app/page.tsx +166 -185
- package/dashboard/app/projects/client.tsx +891 -509
- package/dashboard/app/research/client.tsx +180 -248
- package/dashboard/components/SkillFlowNode.tsx +86 -128
- package/dashboard/components/console-panel.tsx +25 -0
- package/dashboard/components/metric-card.tsx +45 -0
- package/dashboard/components/overview-actions.tsx +29 -40
- package/dashboard/components/page-hero.tsx +44 -0
- package/dashboard/components/quick-actions.tsx +93 -167
- package/dashboard/components/section-frame.tsx +35 -0
- package/dashboard/components/sidebar-nav.tsx +75 -0
- package/dashboard/components/update-banner.tsx +101 -145
- package/dashboard/lib/data.ts +2 -2
- package/dist/cli.js +225 -156
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to HelixEvo are documented here.
|
|
4
4
|
|
|
5
|
+
## [0.2.41] - 2026-03-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `helixevo dashboard` now checks npm for a newer HelixEvo release before launch and automatically updates itself before opening the dashboard
|
|
9
|
+
- New `helixevo dashboard --no-auto-update` flag for users who want to skip the automatic update check
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Dashboard launch messages now use the resolved current version more consistently after updates or relaunches
|
|
13
|
+
- Commands and Guide reference pages now document the dashboard auto-update behavior and opt-out flag
|
|
14
|
+
|
|
15
|
+
## [0.2.40] - 2026-03-23
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Premium dashboard shell with new shared UI primitives for sidebar navigation, page heroes, metric cards, section frames, and console panels
|
|
19
|
+
- Rebuilt Overview, Evolution, Frontier, Research, Projects, and Skill Network surfaces with stronger hierarchy, warmer premium styling, and more flow-oriented layouts
|
|
20
|
+
- Upgraded Project Setup into a full intake studio with improved local/GitHub setup, polished folder browser, richer streamed analysis console, and cleaner project portfolio cards
|
|
21
|
+
- Redesigned Commands and Changelog pages with richer release/command summaries and premium reference layouts
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Skill Network now has premium graph nodes, stronger graph framing, descriptive sub-view tabs, and a dedicated inspector sidebar for navigation and skill management
|
|
25
|
+
- Guide page hero and table of contents were refined for better scanning, quick routing, and visual consistency with the dashboard shell
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Strict typing issues in dashboard network/data code paths uncovered during production build validation
|
|
29
|
+
- Cleaned and revalidated production dashboard build behavior after the large redesign pass
|
|
30
|
+
|
|
5
31
|
## [0.2.39] - 2026-03-23
|
|
6
32
|
|
|
7
33
|
### Added
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from 'fs'
|
|
2
2
|
import { join } from 'path'
|
|
3
3
|
import { homedir } from 'os'
|
|
4
|
+
import { MetricCard } from '@/components/metric-card'
|
|
5
|
+
import { PageHero } from '@/components/page-hero'
|
|
6
|
+
import { SectionFrame } from '@/components/section-frame'
|
|
4
7
|
import { VERSION } from '@/lib/version'
|
|
5
8
|
|
|
6
9
|
export const dynamic = 'force-dynamic'
|
|
@@ -11,7 +14,6 @@ function findChangelog(): string {
|
|
|
11
14
|
join(homedir(), 'Documents', 'GitHub', 'helixevo', 'CHANGELOG.md'),
|
|
12
15
|
]
|
|
13
16
|
|
|
14
|
-
// Also check npm global install
|
|
15
17
|
try {
|
|
16
18
|
const { execSync } = require('child_process')
|
|
17
19
|
const globalPrefix = execSync('npm prefix -g', { encoding: 'utf-8' }).trim()
|
|
@@ -19,10 +21,8 @@ function findChangelog(): string {
|
|
|
19
21
|
candidates.push(join(globalPrefix, 'node_modules', 'helixevo', 'CHANGELOG.md'))
|
|
20
22
|
} catch {}
|
|
21
23
|
|
|
22
|
-
for (const
|
|
23
|
-
if (existsSync(
|
|
24
|
-
return readFileSync(p, 'utf-8')
|
|
25
|
-
}
|
|
24
|
+
for (const path of candidates) {
|
|
25
|
+
if (existsSync(path)) return readFileSync(path, 'utf-8')
|
|
26
26
|
}
|
|
27
27
|
return ''
|
|
28
28
|
}
|
|
@@ -47,12 +47,14 @@ function parseChangelog(md: string): ChangelogEntry[] {
|
|
|
47
47
|
currentSection = null
|
|
48
48
|
continue
|
|
49
49
|
}
|
|
50
|
+
|
|
50
51
|
const sectionMatch = line.match(/^### (.+)/)
|
|
51
52
|
if (sectionMatch && current) {
|
|
52
53
|
currentSection = { title: sectionMatch[1], items: [] }
|
|
53
54
|
current.sections.push(currentSection)
|
|
54
55
|
continue
|
|
55
56
|
}
|
|
57
|
+
|
|
56
58
|
if (line.startsWith('- ') && current) {
|
|
57
59
|
if (!currentSection) {
|
|
58
60
|
currentSection = { title: 'Changes', items: [] }
|
|
@@ -61,82 +63,205 @@ function parseChangelog(md: string): ChangelogEntry[] {
|
|
|
61
63
|
currentSection.items.push(line.slice(2))
|
|
62
64
|
}
|
|
63
65
|
}
|
|
66
|
+
|
|
64
67
|
if (current) entries.push(current)
|
|
65
68
|
return entries
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
export default function ChangelogPage() {
|
|
69
|
-
const
|
|
70
|
-
const entries = parseChangelog(
|
|
72
|
+
const markdown = findChangelog()
|
|
73
|
+
const entries = parseChangelog(markdown)
|
|
74
|
+
const latestEntry = entries[0]
|
|
75
|
+
const installedEntry = entries.find(entry => entry.version === VERSION)
|
|
76
|
+
const totalItems = entries.reduce((sum, entry) => sum + entry.sections.reduce((sectionSum, section) => sectionSum + section.items.length, 0), 0)
|
|
71
77
|
|
|
72
78
|
return (
|
|
73
79
|
<div>
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
<PageHero
|
|
81
|
+
eyebrow="Release history"
|
|
82
|
+
title="Changelog"
|
|
83
|
+
description={`A version-by-version ledger of what changed in HelixEvo. You are currently running v${VERSION}.`}
|
|
84
|
+
chips={[
|
|
85
|
+
{ label: `${entries.length} release${entries.length === 1 ? '' : 's'}`, tone: 'blue' },
|
|
86
|
+
{ label: `${totalItems} logged changes`, tone: 'purple' },
|
|
87
|
+
{ label: `installed v${VERSION}`, tone: 'green' },
|
|
88
|
+
latestEntry ? { label: `latest v${latestEntry.version}`, tone: latestEntry.version === VERSION ? 'green' : 'yellow' } : { label: 'changelog unavailable', tone: 'red' },
|
|
89
|
+
]}
|
|
90
|
+
actions={
|
|
91
|
+
latestEntry ? (
|
|
92
|
+
<div className="hero-note-card">
|
|
93
|
+
<div className="hero-note-label">Current release lens</div>
|
|
94
|
+
<div className="hero-note-title">Latest published version: v{latestEntry.version}</div>
|
|
95
|
+
<div className="hero-note-copy">Use this page to compare the installed version against recent releases and scan the release narrative over time.</div>
|
|
96
|
+
</div>
|
|
97
|
+
) : null
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<div className="grid-4" style={{ marginBottom: 24 }}>
|
|
102
|
+
<MetricCard label="Release entries" value={entries.length} sublabel="Parsed from CHANGELOG.md across the local package or repository." tone="blue" />
|
|
103
|
+
<MetricCard label="Installed version" value={`v${VERSION}`} sublabel={installedEntry ? `Found in changelog dated ${installedEntry.date || 'undated'}.` : 'Current version is not present in the parsed changelog.'} tone="green" />
|
|
104
|
+
<MetricCard label="Latest release" value={latestEntry ? `v${latestEntry.version}` : '—'} sublabel={latestEntry?.date || 'No changelog date available'} tone={latestEntry?.version === VERSION ? 'green' : 'yellow'} />
|
|
105
|
+
<MetricCard label="Tracked changes" value={totalItems} sublabel="Bulleted items parsed across every changelog section." tone="purple" />
|
|
79
106
|
</div>
|
|
80
107
|
|
|
81
108
|
{entries.length === 0 ? (
|
|
82
|
-
<
|
|
109
|
+
<SectionFrame
|
|
110
|
+
eyebrow="Missing release log"
|
|
111
|
+
title="No changelog found"
|
|
112
|
+
description="CHANGELOG.md was not found in the current package installation or repository checkout."
|
|
113
|
+
tone="red"
|
|
114
|
+
>
|
|
83
115
|
<div className="empty-state">
|
|
84
116
|
<div className="empty-state-title">No changelog found</div>
|
|
85
117
|
<div className="empty-state-desc">
|
|
86
|
-
CHANGELOG.md
|
|
118
|
+
Ensure <code>CHANGELOG.md</code> is bundled with the package or available in the working repository.
|
|
87
119
|
</div>
|
|
88
120
|
</div>
|
|
89
|
-
</
|
|
121
|
+
</SectionFrame>
|
|
90
122
|
) : (
|
|
91
|
-
|
|
92
|
-
{
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
<>
|
|
124
|
+
{latestEntry ? (
|
|
125
|
+
<SectionFrame
|
|
126
|
+
eyebrow="Release spotlight"
|
|
127
|
+
title={`v${latestEntry.version}`}
|
|
128
|
+
description={latestEntry.date || 'Current top entry in the parsed release history.'}
|
|
129
|
+
tone={latestEntry.version === VERSION ? 'green' : 'yellow'}
|
|
130
|
+
>
|
|
131
|
+
<div className="grid-2" style={{ alignItems: 'start' }}>
|
|
132
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
133
|
+
{latestEntry.sections.map((section, index) => (
|
|
134
|
+
<div key={`${latestEntry.version}-${section.title}-${index}`} style={{
|
|
135
|
+
padding: '16px 18px',
|
|
136
|
+
borderRadius: 20,
|
|
137
|
+
border: '1px solid var(--border)',
|
|
138
|
+
background: 'rgba(255,255,255,0.76)',
|
|
139
|
+
}}>
|
|
140
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'center', marginBottom: 10, flexWrap: 'wrap' }}>
|
|
141
|
+
<div style={{ fontSize: 12, fontWeight: 800, color: 'var(--text)', textTransform: 'uppercase', letterSpacing: 0.7 }}>
|
|
142
|
+
{section.title}
|
|
143
|
+
</div>
|
|
144
|
+
<span className="hero-chip hero-chip-neutral">{section.items.length} item{section.items.length === 1 ? '' : 's'}</span>
|
|
145
|
+
</div>
|
|
146
|
+
<div style={{ display: 'grid', gap: 8 }}>
|
|
147
|
+
{section.items.map((item, itemIndex) => (
|
|
148
|
+
<div key={`${latestEntry.version}-${section.title}-${itemIndex}`} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
|
|
149
|
+
<span style={{ color: 'var(--green)', fontWeight: 800, fontSize: 14 }}>•</span>
|
|
150
|
+
<span style={{ fontSize: 12.5, color: 'var(--text-secondary)', lineHeight: 1.65 }}>{item}</span>
|
|
151
|
+
</div>
|
|
152
|
+
))}
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
))}
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div style={{
|
|
159
|
+
padding: '18px 20px',
|
|
160
|
+
borderRadius: 22,
|
|
161
|
+
border: '1px solid var(--border)',
|
|
162
|
+
background: 'linear-gradient(180deg, rgba(255,255,255,0.92), rgba(246,242,236,0.96))',
|
|
163
|
+
boxShadow: 'var(--shadow-sm)',
|
|
164
|
+
}}>
|
|
165
|
+
<div style={{ fontSize: 11, fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.7, marginBottom: 8 }}>
|
|
166
|
+
Release context
|
|
167
|
+
</div>
|
|
168
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 12 }}>
|
|
169
|
+
<span className={`hero-chip hero-chip-${latestEntry.version === VERSION ? 'green' : 'yellow'}`}>{latestEntry.version === VERSION ? 'Installed now' : 'Ahead of installed version'}</span>
|
|
170
|
+
{latestEntry.date ? <span className="hero-chip hero-chip-blue">{latestEntry.date}</span> : null}
|
|
171
|
+
</div>
|
|
172
|
+
<div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.7, marginBottom: 12 }}>
|
|
173
|
+
The spotlight release gives you the fastest read on the current product narrative: what changed most recently, how many grouped sections shipped, and whether your installed build matches the latest logged release.
|
|
174
|
+
</div>
|
|
175
|
+
<div className="grid-2" style={{ gap: 10 }}>
|
|
176
|
+
<div style={{ padding: '12px 14px', borderRadius: 16, background: 'rgba(16,185,129,0.08)', border: '1px solid rgba(16,185,129,0.16)' }}>
|
|
177
|
+
<div style={{ fontSize: 10, color: 'var(--green)', textTransform: 'uppercase', fontWeight: 700, letterSpacing: 0.5, marginBottom: 4 }}>Sections</div>
|
|
178
|
+
<div style={{ fontSize: 24, fontWeight: 800, color: 'var(--green)' }}>{latestEntry.sections.length}</div>
|
|
179
|
+
</div>
|
|
180
|
+
<div style={{ padding: '12px 14px', borderRadius: 16, background: 'rgba(107,73,223,0.08)', border: '1px solid rgba(107,73,223,0.16)' }}>
|
|
181
|
+
<div style={{ fontSize: 10, color: 'var(--purple)', textTransform: 'uppercase', fontWeight: 700, letterSpacing: 0.5, marginBottom: 4 }}>Items</div>
|
|
182
|
+
<div style={{ fontSize: 24, fontWeight: 800, color: 'var(--purple)' }}>{latestEntry.sections.reduce((sum, section) => sum + section.items.length, 0)}</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
113
185
|
</div>
|
|
186
|
+
</div>
|
|
187
|
+
</SectionFrame>
|
|
188
|
+
) : null}
|
|
189
|
+
|
|
190
|
+
<SectionFrame
|
|
191
|
+
eyebrow="Release ledger"
|
|
192
|
+
title="Version history"
|
|
193
|
+
description="A clean timeline of every parsed release entry, with the newest releases first."
|
|
194
|
+
tone="blue"
|
|
195
|
+
>
|
|
196
|
+
<div style={{ display: 'grid', gap: 14 }}>
|
|
197
|
+
{entries.map((entry, index) => {
|
|
198
|
+
const isLatest = index === 0
|
|
199
|
+
const isInstalled = entry.version === VERSION
|
|
200
|
+
const itemCount = entry.sections.reduce((sum, section) => sum + section.items.length, 0)
|
|
114
201
|
|
|
115
|
-
|
|
116
|
-
<
|
|
202
|
+
return (
|
|
203
|
+
<article key={entry.version} className="card" style={{
|
|
204
|
+
overflow: 'hidden',
|
|
205
|
+
borderColor: isLatest ? 'rgba(16,185,129,0.22)' : isInstalled ? 'rgba(59,130,246,0.22)' : undefined,
|
|
206
|
+
}}>
|
|
117
207
|
<div style={{
|
|
118
|
-
|
|
119
|
-
|
|
208
|
+
padding: '16px 18px',
|
|
209
|
+
borderBottom: '1px solid var(--border-subtle)',
|
|
210
|
+
background: isLatest
|
|
211
|
+
? 'linear-gradient(135deg, rgba(16,185,129,0.08), rgba(255,255,255,0.88))'
|
|
212
|
+
: isInstalled
|
|
213
|
+
? 'linear-gradient(135deg, rgba(59,130,246,0.08), rgba(255,255,255,0.88))'
|
|
214
|
+
: 'linear-gradient(180deg, rgba(255,255,255,0.86), rgba(245,241,236,0.82))',
|
|
120
215
|
}}>
|
|
121
|
-
{
|
|
216
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 14, alignItems: 'flex-start', flexWrap: 'wrap' }}>
|
|
217
|
+
<div>
|
|
218
|
+
<div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 }}>
|
|
219
|
+
<code style={{ fontFamily: 'var(--font-mono)', fontSize: 15, fontWeight: 800, color: 'var(--text)' }}>v{entry.version}</code>
|
|
220
|
+
{isLatest ? <span className="hero-chip hero-chip-green">latest</span> : null}
|
|
221
|
+
{isInstalled ? <span className="hero-chip hero-chip-blue">installed</span> : null}
|
|
222
|
+
</div>
|
|
223
|
+
<div style={{ fontSize: 12.5, color: 'var(--text-dim)' }}>{entry.date || 'Undated release entry'}</div>
|
|
224
|
+
</div>
|
|
225
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
226
|
+
<span className="hero-chip hero-chip-neutral">{entry.sections.length} section{entry.sections.length === 1 ? '' : 's'}</span>
|
|
227
|
+
<span className="hero-chip hero-chip-purple">{itemCount} item{itemCount === 1 ? '' : 's'}</span>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
122
230
|
</div>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
231
|
+
|
|
232
|
+
<div className="card-body" style={{ display: 'grid', gap: 14 }}>
|
|
233
|
+
{entry.sections.map((section, sectionIndex) => (
|
|
234
|
+
<div key={`${entry.version}-${section.title}-${sectionIndex}`} style={{
|
|
235
|
+
padding: '14px 16px',
|
|
236
|
+
borderRadius: 18,
|
|
237
|
+
background: 'rgba(255,255,255,0.72)',
|
|
238
|
+
border: '1px solid var(--border)',
|
|
129
239
|
}}>
|
|
130
|
-
{
|
|
240
|
+
<div style={{ fontSize: 11, fontWeight: 800, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.7, marginBottom: 8 }}>
|
|
241
|
+
{section.title}
|
|
242
|
+
</div>
|
|
243
|
+
<div style={{ display: 'grid', gap: 8 }}>
|
|
244
|
+
{section.items.map((item, itemIndex) => (
|
|
245
|
+
<div key={`${entry.version}-${section.title}-${itemIndex}`} style={{
|
|
246
|
+
paddingLeft: 12,
|
|
247
|
+
borderLeft: '2px solid var(--border)',
|
|
248
|
+
fontSize: 12.5,
|
|
249
|
+
color: 'var(--text-secondary)',
|
|
250
|
+
lineHeight: 1.65,
|
|
251
|
+
}}>
|
|
252
|
+
{item}
|
|
253
|
+
</div>
|
|
254
|
+
))}
|
|
255
|
+
</div>
|
|
131
256
|
</div>
|
|
132
257
|
))}
|
|
133
258
|
</div>
|
|
134
|
-
</
|
|
135
|
-
)
|
|
136
|
-
|
|
259
|
+
</article>
|
|
260
|
+
)
|
|
261
|
+
})}
|
|
137
262
|
</div>
|
|
138
|
-
|
|
139
|
-
|
|
263
|
+
</SectionFrame>
|
|
264
|
+
</>
|
|
140
265
|
)}
|
|
141
266
|
</div>
|
|
142
267
|
)
|