helixevo 0.2.41 → 0.3.1
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 +28 -0
- package/README.md +24 -8
- package/dashboard/app/commands/page.tsx +23 -4
- package/dashboard/app/evolution/page.tsx +58 -37
- package/dashboard/app/guide/page.tsx +43 -3
- package/dashboard/app/network/client.tsx +125 -1
- package/dashboard/app/network/page.tsx +3 -1
- package/dashboard/app/page.tsx +57 -1
- package/dashboard/app/projects/client.tsx +21 -2
- package/dashboard/app/projects/page.tsx +29 -2
- package/dashboard/app/research/client.tsx +67 -1
- package/dashboard/app/research/page.tsx +3 -2
- package/dashboard/lib/data.ts +443 -1
- package/dist/cli.js +734 -179
- package/package.json +2 -2
package/dashboard/app/page.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Link from 'next/link'
|
|
2
|
-
import { getDashboardSummary, loadFailures, loadFrontier, loadGraph, loadHistory, listProjects } from '@/lib/data'
|
|
2
|
+
import { getDashboardSummary, getOntologyDashboardSummary, loadCoEvolutionSummary, loadFailures, loadFrontier, loadGraph, loadHistory, listProjects } from '@/lib/data'
|
|
3
3
|
import { OverviewActions } from '@/components/overview-actions'
|
|
4
4
|
import { PageHero } from '@/components/page-hero'
|
|
5
5
|
import { MetricCard } from '@/components/metric-card'
|
|
@@ -15,6 +15,8 @@ function scoreColor(score: number) {
|
|
|
15
15
|
|
|
16
16
|
export default function Overview() {
|
|
17
17
|
const summary = getDashboardSummary()
|
|
18
|
+
const ontology = getOntologyDashboardSummary()
|
|
19
|
+
const coevolution = loadCoEvolutionSummary()
|
|
18
20
|
const frontier = loadFrontier()
|
|
19
21
|
const history = loadHistory()
|
|
20
22
|
const graph = loadGraph()
|
|
@@ -74,6 +76,60 @@ export default function Overview() {
|
|
|
74
76
|
/>
|
|
75
77
|
</SectionFrame>
|
|
76
78
|
|
|
79
|
+
<SectionFrame
|
|
80
|
+
eyebrow="Brain foundation"
|
|
81
|
+
title="Semantic backbone"
|
|
82
|
+
description="A compatibility-era view of the living brain, derived from the current skill graph, evolution history, and captured failures while native ontology events are being wired in."
|
|
83
|
+
actions={<span className="badge badge-gray">{ontology.source === 'graph' ? `Ontology ${ontology.specVersion}` : 'Compatibility-derived'}</span>}
|
|
84
|
+
>
|
|
85
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
86
|
+
<MetricCard
|
|
87
|
+
label="Generalist skills"
|
|
88
|
+
value={ontology.skillRoles.generalist}
|
|
89
|
+
sublabel={`${ontology.stabilityStates.stable} stable abstractions`}
|
|
90
|
+
tone="purple"
|
|
91
|
+
href="/network"
|
|
92
|
+
icon="◎"
|
|
93
|
+
/>
|
|
94
|
+
<MetricCard
|
|
95
|
+
label="Project specialists"
|
|
96
|
+
value={ontology.skillRoles.specialist}
|
|
97
|
+
sublabel={`${ontology.plasticityStates.candidate} candidate rewires`}
|
|
98
|
+
tone="blue"
|
|
99
|
+
href="/projects"
|
|
100
|
+
icon="◉"
|
|
101
|
+
/>
|
|
102
|
+
<MetricCard
|
|
103
|
+
label="Hybrid bridges"
|
|
104
|
+
value={ontology.skillRoles.hybrid}
|
|
105
|
+
sublabel={`${ontology.plasticityStates.volatile} volatile transitions`}
|
|
106
|
+
tone="green"
|
|
107
|
+
href="/network"
|
|
108
|
+
icon="⇄"
|
|
109
|
+
/>
|
|
110
|
+
<MetricCard
|
|
111
|
+
label="Observed mutation verbs"
|
|
112
|
+
value={ontology.mutationOperationsObserved}
|
|
113
|
+
sublabel={ontology.observedMutationActions.length > 0 ? ontology.observedMutationActions.join(' • ') : 'Waiting for evolution history'}
|
|
114
|
+
tone="yellow"
|
|
115
|
+
href="/evolution"
|
|
116
|
+
icon="◇"
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 16 }}>
|
|
121
|
+
<span className="badge badge-gray">{ontology.relationFamiliesObserved} relation families live in the graph</span>
|
|
122
|
+
<span className="badge badge-gray">{ontology.evidenceBackedProposals} proposals already carry judge + regression evidence</span>
|
|
123
|
+
<span className="badge badge-gray">{ontology.artifacts.total} evolution artifacts ({ontology.artifacts.native} native • {ontology.artifacts.derived} derived)</span>
|
|
124
|
+
<span className="badge badge-gray">{ontology.activationTraces.total} activation traces ({ontology.activationTraces.native} native • {ontology.activationTraces.derived} derived)</span>
|
|
125
|
+
<span className="badge badge-gray">{ontology.pressureSignals.total} pressure signals ({ontology.pressureSignals.native} native • {ontology.pressureSignals.derived} derived)</span>
|
|
126
|
+
<span className="badge badge-gray">{coevolution.topProjects.length} pressured project hotspots</span>
|
|
127
|
+
<span className="badge badge-gray">{coevolution.crossProjectGapAreas.length} cross-project gap motifs</span>
|
|
128
|
+
<span className="badge badge-gray">{ontology.enrichedSkillNodes} skills carry explicit brain metadata</span>
|
|
129
|
+
<span className="badge badge-gray">{ontology.annotatedFailures.pressureSignals} failures annotated with pressure signals</span>
|
|
130
|
+
</div>
|
|
131
|
+
</SectionFrame>
|
|
132
|
+
|
|
77
133
|
{unresolved.length > 0 ? (
|
|
78
134
|
<SectionFrame
|
|
79
135
|
eyebrow="Attention"
|
|
@@ -119,7 +119,7 @@ function formatDate(value: string) {
|
|
|
119
119
|
return new Date(value).toLocaleDateString()
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
export default function ProjectsClient({ profiles, skillCount }: { profiles: ProjectProfile[]; skillCount: number }) {
|
|
122
|
+
export default function ProjectsClient({ profiles, skillCount, projectAnalysisTraces, pressureByProject }: { profiles: ProjectProfile[]; skillCount: number; projectAnalysisTraces: number; pressureByProject: Record<string, { projectId: string; totalSignals: number; nativeSignals: number; derivedSignals: number; highPrioritySignals: number; topCapabilities: string[] }> }) {
|
|
123
123
|
const [inputMode, setInputMode] = useState<InputMode>('local')
|
|
124
124
|
const [projectPath, setProjectPath] = useState('')
|
|
125
125
|
const [githubUrl, setGithubUrl] = useState('')
|
|
@@ -338,7 +338,7 @@ export default function ProjectsClient({ profiles, skillCount }: { profiles: Pro
|
|
|
338
338
|
}
|
|
339
339
|
/>
|
|
340
340
|
|
|
341
|
-
<div
|
|
341
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16, marginBottom: 24 }}>
|
|
342
342
|
<MetricCard
|
|
343
343
|
label="Portfolio"
|
|
344
344
|
value={profiles.length}
|
|
@@ -351,6 +351,18 @@ export default function ProjectsClient({ profiles, skillCount }: { profiles: Pro
|
|
|
351
351
|
sublabel={`Average matched-skill coverage across ${profiles.length || 1} project${profiles.length === 1 ? '' : 's'}`}
|
|
352
352
|
tone="purple"
|
|
353
353
|
/>
|
|
354
|
+
<MetricCard
|
|
355
|
+
label="Project-analysis traces"
|
|
356
|
+
value={projectAnalysisTraces}
|
|
357
|
+
sublabel="Native activation snapshots captured from successful project analysis runs"
|
|
358
|
+
tone="green"
|
|
359
|
+
/>
|
|
360
|
+
<MetricCard
|
|
361
|
+
label="Project pressure hotspots"
|
|
362
|
+
value={Object.keys(pressureByProject).length}
|
|
363
|
+
sublabel="Projects currently carrying persisted or compatibility-derived pressure signals"
|
|
364
|
+
tone="blue"
|
|
365
|
+
/>
|
|
354
366
|
<MetricCard
|
|
355
367
|
label="High-priority gaps"
|
|
356
368
|
value={aggregate.totalHighGaps}
|
|
@@ -724,6 +736,7 @@ export default function ProjectsClient({ profiles, skillCount }: { profiles: Pro
|
|
|
724
736
|
{profiles.map(profile => {
|
|
725
737
|
const highGaps = profile.gaps.filter(gap => gap.priority === 'high')
|
|
726
738
|
const matchedPct = skillCount > 0 ? Math.round((profile.matchedSkills.length / skillCount) * 100) : 0
|
|
739
|
+
const projectPressure = pressureByProject[profile.name]
|
|
727
740
|
|
|
728
741
|
return (
|
|
729
742
|
<article key={profile.name} className="card" style={{ overflow: 'hidden' }}>
|
|
@@ -738,12 +751,18 @@ export default function ProjectsClient({ profiles, skillCount }: { profiles: Pro
|
|
|
738
751
|
<span className={`hero-chip hero-chip-${profile.status === 'active' ? 'green' : 'blue'}`}>{profile.status}</span>
|
|
739
752
|
<span className="hero-chip hero-chip-neutral">Analyzed {formatDate(profile.analyzedAt)}</span>
|
|
740
753
|
<span className={`hero-chip hero-chip-${highGaps.length > 0 ? 'red' : 'green'}`}>{highGaps.length} high-priority gap{highGaps.length === 1 ? '' : 's'}</span>
|
|
754
|
+
{projectPressure ? (
|
|
755
|
+
<span className={`hero-chip hero-chip-${projectPressure.highPrioritySignals > 0 ? 'red' : 'blue'}`}>
|
|
756
|
+
{projectPressure.totalSignals} pressure signal{projectPressure.totalSignals === 1 ? '' : 's'}
|
|
757
|
+
</span>
|
|
758
|
+
) : null}
|
|
741
759
|
</div>
|
|
742
760
|
<div style={{ fontSize: 24, fontWeight: 800, color: 'var(--text)', marginBottom: 8 }}>{profile.name}</div>
|
|
743
761
|
<div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.7, marginBottom: 12 }}>{profile.description}</div>
|
|
744
762
|
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
|
745
763
|
{profile.techStack.map(tech => <span key={tech} className="badge badge-gray">{tech}</span>)}
|
|
746
764
|
{profile.domains.map(domain => <span key={domain} className="badge badge-blue">{domain}</span>)}
|
|
765
|
+
{projectPressure?.topCapabilities.map((capability) => <span key={`${profile.name}-${capability}`} className="badge badge-yellow">{capability}</span>)}
|
|
747
766
|
</div>
|
|
748
767
|
</div>
|
|
749
768
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadAllProjectProfiles, loadGraph } from '@/lib/data'
|
|
1
|
+
import { loadActivationTraces, loadAllProjectProfiles, loadGraph, loadPressureSignals } from '@/lib/data'
|
|
2
2
|
import ProjectsClient from './client'
|
|
3
3
|
|
|
4
4
|
export const dynamic = 'force-dynamic'
|
|
@@ -6,7 +6,34 @@ export const dynamic = 'force-dynamic'
|
|
|
6
6
|
export default function ProjectsPage() {
|
|
7
7
|
const profiles = loadAllProjectProfiles()
|
|
8
8
|
const graph = loadGraph()
|
|
9
|
+
const activationTraces = loadActivationTraces()
|
|
10
|
+
const pressureSignals = loadPressureSignals()
|
|
9
11
|
const skillCount = graph.nodes.length
|
|
12
|
+
const projectAnalysisTraces = activationTraces.filter((trace) => trace.provenance === 'project-analysis').length
|
|
13
|
+
const pressureByProject = Object.fromEntries(
|
|
14
|
+
Object.entries(
|
|
15
|
+
pressureSignals.reduce<Record<string, { projectId: string; totalSignals: number; nativeSignals: number; derivedSignals: number; highPrioritySignals: number; topCapabilities: string[] }>>((acc, signal) => {
|
|
16
|
+
if (!signal.projectId) return acc
|
|
17
|
+
const existing = acc[signal.projectId] ?? {
|
|
18
|
+
projectId: signal.projectId,
|
|
19
|
+
totalSignals: 0,
|
|
20
|
+
nativeSignals: 0,
|
|
21
|
+
derivedSignals: 0,
|
|
22
|
+
highPrioritySignals: 0,
|
|
23
|
+
topCapabilities: [],
|
|
24
|
+
}
|
|
25
|
+
existing.totalSignals += 1
|
|
26
|
+
if (signal.provenance === 'failure-native' || signal.provenance === 'project-analysis-native') existing.nativeSignals += 1
|
|
27
|
+
else existing.derivedSignals += 1
|
|
28
|
+
if (signal.priority === 'high') existing.highPrioritySignals += 1
|
|
29
|
+
if (signal.capability && !existing.topCapabilities.includes(signal.capability) && existing.topCapabilities.length < 3) {
|
|
30
|
+
existing.topCapabilities.push(signal.capability)
|
|
31
|
+
}
|
|
32
|
+
acc[signal.projectId] = existing
|
|
33
|
+
return acc
|
|
34
|
+
}, {}),
|
|
35
|
+
),
|
|
36
|
+
)
|
|
10
37
|
|
|
11
|
-
return <ProjectsClient profiles={profiles} skillCount={skillCount} />
|
|
38
|
+
return <ProjectsClient profiles={profiles} skillCount={skillCount} projectAnalysisTraces={projectAnalysisTraces} pressureByProject={pressureByProject} />
|
|
12
39
|
}
|
|
@@ -32,6 +32,12 @@ interface KnowledgeBuffer {
|
|
|
32
32
|
interface Props {
|
|
33
33
|
buffer: KnowledgeBuffer
|
|
34
34
|
projects: string[]
|
|
35
|
+
coevolution: {
|
|
36
|
+
pressureSignals: { total: number; native: number; derived: number }
|
|
37
|
+
topProjects: { projectId: string; totalSignals: number; highPrioritySignals: number; topCapabilities: string[] }[]
|
|
38
|
+
crossProjectGapAreas: { area: string; projects: string[]; count: number }[]
|
|
39
|
+
activeRecommendations: { action: 'research' | 'specialize' | 'create'; count: number }[]
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
type RunState = 'idle' | 'running' | 'success' | 'error' | 'stopped'
|
|
@@ -78,7 +84,7 @@ function consoleTone(state: RunState): 'neutral' | 'green' | 'red' | 'yellow' {
|
|
|
78
84
|
return 'neutral'
|
|
79
85
|
}
|
|
80
86
|
|
|
81
|
-
export default function ResearchClient({ buffer, projects }: Props) {
|
|
87
|
+
export default function ResearchClient({ buffer, projects, coevolution }: Props) {
|
|
82
88
|
const [runState, setRunState] = useState<RunState>('idle')
|
|
83
89
|
const [output, setOutput] = useState('')
|
|
84
90
|
const abortRef = useRef<AbortController | null>(null)
|
|
@@ -178,6 +184,66 @@ export default function ResearchClient({ buffer, projects }: Props) {
|
|
|
178
184
|
]}
|
|
179
185
|
/>
|
|
180
186
|
|
|
187
|
+
<SectionFrame
|
|
188
|
+
eyebrow="Why research now"
|
|
189
|
+
title="Current pressure handoff"
|
|
190
|
+
description="Research becomes more valuable when recurring project pressure points to capability gaps that should generalize beyond one local context."
|
|
191
|
+
tone="blue"
|
|
192
|
+
>
|
|
193
|
+
<div className="grid-3">
|
|
194
|
+
<MetricCard
|
|
195
|
+
label="Pressure signals"
|
|
196
|
+
value={coevolution.pressureSignals.total}
|
|
197
|
+
sublabel={`${coevolution.pressureSignals.native} native • ${coevolution.pressureSignals.derived} derived`}
|
|
198
|
+
tone="blue"
|
|
199
|
+
icon="◎"
|
|
200
|
+
/>
|
|
201
|
+
<MetricCard
|
|
202
|
+
label="Pressured projects"
|
|
203
|
+
value={coevolution.topProjects.length}
|
|
204
|
+
sublabel="Projects currently producing the strongest adaptation demand"
|
|
205
|
+
tone="purple"
|
|
206
|
+
icon="◉"
|
|
207
|
+
/>
|
|
208
|
+
<MetricCard
|
|
209
|
+
label="Cross-project gap motifs"
|
|
210
|
+
value={coevolution.crossProjectGapAreas.length}
|
|
211
|
+
sublabel="Recurring capability gaps that research can help generalize"
|
|
212
|
+
tone="green"
|
|
213
|
+
icon="⇄"
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.2fr) minmax(0, 1fr)', gap: 16, marginTop: 16 }}>
|
|
218
|
+
<div style={{ padding: '14px 16px', borderRadius: 18, background: 'rgba(255,255,255,0.7)', border: '1px solid var(--border)' }}>
|
|
219
|
+
<div className="section-label" style={{ marginBottom: 10 }}>Top gap motifs</div>
|
|
220
|
+
{coevolution.crossProjectGapAreas.length === 0 ? (
|
|
221
|
+
<div className="signal-text">Recurring cross-project gap motifs will appear here once the same capability pressure shows up across multiple projects.</div>
|
|
222
|
+
) : (
|
|
223
|
+
<div style={{ display: 'grid', gap: 8 }}>
|
|
224
|
+
{coevolution.crossProjectGapAreas.slice(0, 4).map((entry) => (
|
|
225
|
+
<div key={entry.area} style={{ padding: '12px 14px', borderRadius: 16, background: 'rgba(97,93,86,0.06)', border: '1px solid var(--border)' }}>
|
|
226
|
+
<div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{entry.area}</div>
|
|
227
|
+
<div style={{ fontSize: 11.5, color: 'var(--text-dim)', marginTop: 4 }}>{entry.count} projects • {entry.projects.join(', ')}</div>
|
|
228
|
+
</div>
|
|
229
|
+
))}
|
|
230
|
+
</div>
|
|
231
|
+
)}
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
<div style={{ padding: '14px 16px', borderRadius: 18, background: 'rgba(255,255,255,0.7)', border: '1px solid var(--border)' }}>
|
|
235
|
+
<div className="section-label" style={{ marginBottom: 10 }}>Recommended routing pressure</div>
|
|
236
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
237
|
+
{coevolution.activeRecommendations.length > 0 ? coevolution.activeRecommendations.map((entry) => (
|
|
238
|
+
<span key={entry.action} className={`hero-chip hero-chip-${entry.action === 'research' ? 'blue' : entry.action === 'specialize' ? 'green' : 'purple'}`}>
|
|
239
|
+
{entry.action} × {entry.count}
|
|
240
|
+
</span>
|
|
241
|
+
)) : <span className="badge badge-gray">No routed action pressure yet</span>}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</SectionFrame>
|
|
246
|
+
|
|
181
247
|
<SectionFrame
|
|
182
248
|
eyebrow="Pipeline"
|
|
183
249
|
title="How research works"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadBuffer, listProjects } from '@/lib/data'
|
|
1
|
+
import { loadBuffer, loadCoEvolutionSummary, listProjects } from '@/lib/data'
|
|
2
2
|
import ResearchClient from './client'
|
|
3
3
|
|
|
4
4
|
export const dynamic = 'force-dynamic'
|
|
@@ -6,6 +6,7 @@ export const dynamic = 'force-dynamic'
|
|
|
6
6
|
export default function ResearchPage() {
|
|
7
7
|
const buffer = loadBuffer()
|
|
8
8
|
const projects = listProjects()
|
|
9
|
+
const coevolution = loadCoEvolutionSummary()
|
|
9
10
|
|
|
10
|
-
return <ResearchClient buffer={buffer} projects={projects} />
|
|
11
|
+
return <ResearchClient buffer={buffer} projects={projects} coevolution={coevolution} />
|
|
11
12
|
}
|