helixevo 0.2.40 → 0.3.0

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 CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  All notable changes to HelixEvo are documented here.
4
4
 
5
+ ## [0.3.0] - 2026-03-23
6
+
7
+ ### Added
8
+ - Ontology foundation for skills, projects, tasks, capabilities, relations, operations, invariants, and ontology-aware graph summaries
9
+ - Native and derived evolution evidence artifacts with provenance-aware persistence in `~/.helix/evolution-artifacts.jsonl`
10
+ - Native and derived activation traces with provenance-aware persistence in `~/.helix/activation-traces.jsonl`
11
+ - Native and derived pressure signals with provenance-aware persistence in `~/.helix/pressure-signals.jsonl`
12
+ - Co-evolution dashboard summaries that surface project hotspots, role pressure, recurring gap motifs, and routed recommendation counts
13
+ - Premium dashboard brain views across Overview, Evolution, Skill Network, Projects, and Research
14
+
15
+ ### Changed
16
+ - HelixEvo is now documented and surfaced more explicitly as a co-evolving skill and project brain rather than only a skill manager
17
+ - README and dashboard Guide now document the ontology / activation / artifact / pressure model and updated dashboard surfaces
18
+ - Projects page now shows project pressure hotspots and per-project capability pressure context
19
+ - Research page now includes a "Current pressure handoff" view so discovery work is grounded in current adaptation demand
20
+ - Skill Network page now includes a compact co-evolution pressure summary panel
21
+
22
+ ### Fixed
23
+ - Claude invocation now retries without an inherited `CLAUDE_CODE_OAUTH_TOKEN` when that override is stale but local Claude auth is valid
24
+ - Local runtime `events.jsonl` is now ignored to keep mutable telemetry out of normal product commits
25
+
26
+ ## [0.2.41] - 2026-03-23
27
+
28
+ ### Added
29
+ - `helixevo dashboard` now checks npm for a newer HelixEvo release before launch and automatically updates itself before opening the dashboard
30
+ - New `helixevo dashboard --no-auto-update` flag for users who want to skip the automatic update check
31
+
32
+ ### Changed
33
+ - Dashboard launch messages now use the resolved current version more consistently after updates or relaunches
34
+ - Commands and Guide reference pages now document the dashboard auto-update behavior and opt-out flag
35
+
5
36
  ## [0.2.40] - 2026-03-23
6
37
 
7
38
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # HelixEvo
2
2
 
3
- Self-evolving skill ecosystem for AI agents. Captures failures, evolves skills through multi-judge evaluation, and maintains a Pareto frontier of optimal skill configurations.
3
+ Co-evolving skill and project brain for AI agents. HelixEvo captures failures, traces activations, models pressure, evolves skills through multi-judge evaluation, and maintains a Pareto frontier of optimal skill configurations.
4
4
 
5
5
  ## How it works
6
6
 
@@ -22,6 +22,8 @@ Every proposed change goes through:
22
22
  - **[Claude CLI](https://docs.anthropic.com/en/docs/claude-code)** — installed and authenticated
23
23
  - Requires a **Claude Max plan** subscription
24
24
  - HelixEvo uses `claude --print` for all LLM operations (no API key needed)
25
+ - Prefer `claude auth login` managed credentials over exporting a hardcoded `CLAUDE_CODE_OAUTH_TOKEN`
26
+ - HelixEvo now retries once without an inherited `CLAUDE_CODE_OAUTH_TOKEN` if that override is stale but local Claude auth is valid
25
27
 
26
28
  Verify prerequisites:
27
29
  ```bash
@@ -82,6 +84,7 @@ helixevo dashboard
82
84
  | `helixevo health` | Network health: cohesion, coverage, balance, transfer |
83
85
  | `helixevo init` | Import existing skills + generate skill tests |
84
86
  | `helixevo capture <session>` | Extract failures from a session file |
87
+ | `helixevo project-setup <path>` | Analyze a project, match skills, and surface capability gaps |
85
88
  | `helixevo evolve` | Evolve skills from captured failures |
86
89
  | `helixevo generalize` | Promote cross-project patterns ↑ |
87
90
  | `helixevo specialize --project <name>` | Create project-specific skills ↓ |
@@ -124,10 +127,13 @@ All data is stored in `~/.helix/`:
124
127
  ~/.helix/
125
128
  ├── config.json # Configuration
126
129
  ├── failures.jsonl # Captured failures
130
+ ├── activation-traces.jsonl # Native + derived activation traces
131
+ ├── pressure-signals.jsonl # Native + derived adaptation pressure
132
+ ├── evolution-artifacts.jsonl # Evolution evidence artifacts per proposal/iteration
127
133
  ├── frontier.json # Pareto frontier (top-k configurations)
128
134
  ├── evolution-history.json # All evolution runs + proposals
129
135
  ├── skill-tests.jsonl # Regression test cases
130
- ├── skill-graph.json # Cached network (nodes + edges)
136
+ ├── skill-graph.json # Cached network (nodes + edges + ontology version)
131
137
  ├── canary-registry.json # Active canary deployments
132
138
  ├── knowledge-buffer.json # Research discoveries + drafts
133
139
  ├── general/ # Skills (SKILL.md files)
@@ -147,10 +153,11 @@ helixevo dashboard
147
153
  ```
148
154
 
149
155
  **Tabs:**
150
- - **Overview** — Stats, frontier programs, recent evolution
151
- - **Skill Network** — Interactive graph + skill cards + project view + co-evolution analysis
152
- - **Evolution** — Timeline of all evolution runs with judge scores
153
- - **Research** — Knowledge buffer: discoveries and drafts
156
+ - **Overview** — Premium control cockpit with frontier signals, brain foundation, semantic backbone, and pressure counts
157
+ - **Skill Network** — Interactive graph, premium inspector, and co-evolution pressure routing signals
158
+ - **Projects** — Project intake studio, live project analysis, gap routing, and per-project pressure hotspots
159
+ - **Evolution** — Timeline of evolution runs with judge scores, artifact provenance, and activation-aware context
160
+ - **Research** — Knowledge buffer plus a live “why research now” handoff from current pressure and recurring gaps
154
161
  - **Frontier** — Pareto frontier with 4-dimension scores + canary status
155
162
 
156
163
  The dashboard requires Next.js dependencies. On first run:
@@ -183,6 +190,12 @@ Failures → Cluster → Propose → Replay → Multi-Judge → Regression → C
183
190
  (discoveries + drafts from rejected proposals)
184
191
  ```
185
192
 
193
+ **Brain foundation:**
194
+ - **Ontology** defines the stable semantic kernel for skills, projects, tasks, capabilities, artifacts, and mutations.
195
+ - **Activation traces** record which skills and gaps were active during capture and project analysis.
196
+ - **Pressure signals** turn failures and project gaps into explicit adaptation demand.
197
+ - **Evolution artifacts** preserve proposal-level evidence so the dashboard can show what changed, why, and with what provenance.
198
+
186
199
  **Three-layer hierarchy:**
187
200
  - **System** — Global agent behaviors
188
201
  - **Domain** — Cross-project patterns (generalized skills)
@@ -223,16 +223,40 @@ const COMMANDS: CommandInfo[] = [
223
223
  needsLLM: true,
224
224
  note: 'Typically not needed if using "watch" mode, which captures automatically.',
225
225
  },
226
+ {
227
+ name: 'project-setup',
228
+ description: 'Analyze a local project, match it against your current skills, identify capability gaps, persist a project profile, and emit activation traces plus pressure signals for the dashboard brain surfaces.',
229
+ usage: 'helixevo project-setup <path> [options]',
230
+ examples: [
231
+ { cmd: 'helixevo project-setup .', desc: 'Analyze the current repository and persist a project profile' },
232
+ { cmd: 'helixevo project-setup ~/myapp', desc: 'Analyze a local project folder by path' },
233
+ { cmd: 'helixevo project-setup ~/myapp --dry-run', desc: 'Preview the analysis without saving profile data' },
234
+ ],
235
+ options: [
236
+ { flag: '--dry-run', desc: 'Run analysis without saving the project profile or pressure data' },
237
+ { flag: '--verbose', desc: 'Show additional context and matched-skill reasoning' },
238
+ ],
239
+ category: 'system',
240
+ needsLLM: true,
241
+ note: 'This powers the Projects intake workflow and now feeds activation traces plus project-analysis pressure into the dashboard.',
242
+ },
226
243
  {
227
244
  name: 'dashboard',
228
- description: 'Launch the web dashboard at http://localhost:3847. Provides a visual interface for monitoring skills, evolution, frontier, and network health.',
229
- usage: 'helixevo dashboard',
245
+ description: 'Launch the web dashboard at http://localhost:3847. When a newer npm version is available, HelixEvo now auto-updates itself before opening the dashboard unless you opt out.',
246
+ usage: 'helixevo dashboard [options]',
230
247
  examples: [
231
- { cmd: 'helixevo dashboard', desc: 'Open the dashboard in your browser' },
248
+ { cmd: 'helixevo dashboard', desc: 'Auto-update to the latest version if needed, then open the dashboard' },
249
+ { cmd: 'helixevo dashboard --background', desc: 'Run the dashboard in the background after the same update check' },
250
+ { cmd: 'helixevo dashboard --no-auto-update', desc: 'Open the dashboard immediately without checking npm for updates' },
251
+ ],
252
+ options: [
253
+ { flag: '--background', desc: 'Run the dashboard detached from the terminal' },
254
+ { flag: '--stop', desc: 'Stop a background dashboard process' },
255
+ { flag: '--no-auto-update', desc: 'Skip the automatic update check before launch' },
232
256
  ],
233
257
  category: 'system',
234
258
  needsLLM: false,
235
- note: 'You are currently using the dashboard!',
259
+ note: 'You are currently using the dashboard. By default it now upgrades itself first when a newer release is available.',
236
260
  },
237
261
  ]
238
262
 
@@ -1,4 +1,4 @@
1
- import { loadHistory } from '@/lib/data'
1
+ import { loadEvolutionArtifacts, loadHistory } from '@/lib/data'
2
2
  import { MetricCard } from '@/components/metric-card'
3
3
  import { PageHero } from '@/components/page-hero'
4
4
  import { SectionFrame } from '@/components/section-frame'
@@ -7,11 +7,15 @@ export const dynamic = 'force-dynamic'
7
7
 
8
8
  export default function EvolutionPage() {
9
9
  const history = loadHistory()
10
+ const artifacts = loadEvolutionArtifacts()
10
11
  const iterations = [...history.iterations].reverse()
11
12
  const totalProposals = iterations.flatMap((iteration) => iteration.proposals)
12
13
  const accepted = totalProposals.filter((proposal) => proposal.outcome === 'accepted').length
13
14
  const rejected = totalProposals.filter((proposal) => proposal.outcome === 'rejected').length
14
15
  const avgAcceptance = totalProposals.length > 0 ? Math.round((accepted / totalProposals.length) * 100) : 0
16
+ const nativeArtifacts = artifacts.filter((artifact) => artifact.provenance === 'native-evolution').length
17
+ const derivedArtifacts = artifacts.filter((artifact) => artifact.provenance === 'derived-history').length
18
+ const artifactByProposal = new Map(artifacts.map((artifact) => [artifact.proposalId, artifact]))
15
19
 
16
20
  return (
17
21
  <div style={{ display: 'grid', gap: 22 }}>
@@ -23,15 +27,15 @@ export default function EvolutionPage() {
23
27
  { label: `${iterations.length} runs`, tone: 'purple' },
24
28
  { label: `${accepted} accepted`, tone: 'green' },
25
29
  { label: `${rejected} rejected`, tone: 'red' },
26
- { label: `${avgAcceptance}% acceptance rate`, tone: 'blue' },
30
+ { label: `${artifacts.length} evidence artifacts`, tone: 'blue' },
27
31
  ]}
28
32
  />
29
33
 
30
34
  <div className="grid-4">
31
35
  <MetricCard label="Runs" value={iterations.length} sublabel="Completed evolution loops" tone="purple" icon="◎" />
36
+ <MetricCard label="Native artifacts" value={nativeArtifacts} sublabel={`${derivedArtifacts} compatibility-derived`} tone="blue" icon="◇" />
32
37
  <MetricCard label="Accepted" value={accepted} sublabel="Promotions that survived judging" tone="green" icon="✓" />
33
- <MetricCard label="Rejected" value={rejected} sublabel="Proposals blocked by quality gates" tone="red" icon="" />
34
- <MetricCard label="Acceptance rate" value={`${avgAcceptance}%`} sublabel="Across all recorded proposals" tone="blue" icon="↗" />
38
+ <MetricCard label="Acceptance rate" value={`${avgAcceptance}%`} sublabel="Across all recorded proposals" tone="yellow" icon="" />
35
39
  </div>
36
40
 
37
41
  <SectionFrame
@@ -78,47 +82,64 @@ export default function EvolutionPage() {
78
82
  </div>
79
83
  ) : null}
80
84
 
81
- {iteration.proposals.map((proposal) => (
82
- <div key={proposal.id} className="proposal-card" style={{ borderLeft: `3px solid ${proposal.outcome === 'accepted' ? 'var(--green)' : 'var(--red)'}` }}>
83
- <div style={{ padding: '14px 16px' }}>
84
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12, marginBottom: 10 }}>
85
- <div>
86
- <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
87
- <span className={`badge ${proposal.outcome === 'accepted' ? 'badge-green' : 'badge-red'}`}>{proposal.outcome}</span>
88
- <span style={{ fontSize: 15, fontWeight: 800, letterSpacing: '-0.02em' }}>{proposal.targetSkill}</span>
89
- <span className="badge badge-gray">{proposal.action}</span>
85
+ {iteration.proposals.map((proposal) => {
86
+ const artifact = artifactByProposal.get(proposal.id)
87
+
88
+ return (
89
+ <div key={proposal.id} className="proposal-card" style={{ borderLeft: `3px solid ${proposal.outcome === 'accepted' ? 'var(--green)' : 'var(--red)'}` }}>
90
+ <div style={{ padding: '14px 16px' }}>
91
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12, marginBottom: 10 }}>
92
+ <div>
93
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
94
+ <span className={`badge ${proposal.outcome === 'accepted' ? 'badge-green' : 'badge-red'}`}>{proposal.outcome}</span>
95
+ <span style={{ fontSize: 15, fontWeight: 800, letterSpacing: '-0.02em' }}>{proposal.targetSkill}</span>
96
+ <span className="badge badge-gray">{proposal.action}</span>
97
+ {artifact ? (
98
+ <span className={`badge ${artifact.provenance === 'native-evolution' ? 'badge-blue' : 'badge-gray'}`}>
99
+ {artifact.provenance === 'native-evolution' ? 'native artifact' : 'derived artifact'}
100
+ </span>
101
+ ) : null}
102
+ </div>
103
+ <div style={{ marginTop: 8, color: 'var(--text-secondary)', fontSize: 12.5, lineHeight: 1.65 }}>
104
+ {proposal.description.slice(0, 260)}
105
+ {proposal.description.length > 260 ? '…' : ''}
106
+ </div>
90
107
  </div>
91
- <div style={{ marginTop: 8, color: 'var(--text-secondary)', fontSize: 12.5, lineHeight: 1.65 }}>
92
- {proposal.description.slice(0, 260)}
93
- {proposal.description.length > 260 ? '' : ''}
108
+ <div style={{ minWidth: 92, textAlign: 'right' }}>
109
+ <div style={{ fontSize: 11, color: 'var(--text-muted)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.08em' }}>Regression</div>
110
+ <div style={{ marginTop: 6, fontSize: 22, fontWeight: 850, lineHeight: 1, color: proposal.regressionResult.total > 0 && proposal.regressionResult.passed === proposal.regressionResult.total ? 'var(--green)' : 'var(--text)' }}>
111
+ {proposal.regressionResult.total > 0 ? `${proposal.regressionResult.passed}/${proposal.regressionResult.total}` : '—'}
112
+ </div>
94
113
  </div>
95
114
  </div>
96
- <div style={{ minWidth: 92, textAlign: 'right' }}>
97
- <div style={{ fontSize: 11, color: 'var(--text-muted)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.08em' }}>Regression</div>
98
- <div style={{ marginTop: 6, fontSize: 22, fontWeight: 850, lineHeight: 1, color: proposal.regressionResult.total > 0 && proposal.regressionResult.passed === proposal.regressionResult.total ? 'var(--green)' : 'var(--text)' }}>
99
- {proposal.regressionResult.total > 0 ? `${proposal.regressionResult.passed}/${proposal.regressionResult.total}` : ''}
100
- </div>
115
+
116
+ <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 10 }}>
117
+ {[
118
+ { label: 'Task', score: proposal.judges.taskCompletion.score, color: 'var(--green)' },
119
+ { label: 'Align', score: proposal.judges.correctionAlignment.score, color: 'var(--blue)' },
120
+ { label: 'Side-effects', score: proposal.judges.sideEffectCheck.score, color: 'var(--purple)' },
121
+ ].map((judge) => (
122
+ <span key={judge.label} className="score-pill" style={{ color: judge.score >= 7 ? judge.color : 'var(--red)' }}>
123
+ {judge.label} {judge.score}/10
124
+ </span>
125
+ ))}
101
126
  </div>
102
- </div>
103
127
 
104
- <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 10 }}>
105
- {[
106
- { label: 'Task', score: proposal.judges.taskCompletion.score, color: 'var(--green)' },
107
- { label: 'Align', score: proposal.judges.correctionAlignment.score, color: 'var(--blue)' },
108
- { label: 'Side-effects', score: proposal.judges.sideEffectCheck.score, color: 'var(--purple)' },
109
- ].map((judge) => (
110
- <span key={judge.label} className="score-pill" style={{ color: judge.score >= 7 ? judge.color : 'var(--red)' }}>
111
- {judge.label} {judge.score}/10
112
- </span>
113
- ))}
114
- </div>
128
+ {artifact ? (
129
+ <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 10 }}>
130
+ {artifact.clusterType ? <span className="badge badge-gray">cluster {artifact.clusterType}</span> : null}
131
+ {artifact.trigger ? <span className="badge badge-gray">trigger {artifact.trigger}</span> : null}
132
+ {artifact.iterationId ? <span className="badge badge-gray">{artifact.iterationId}</span> : null}
133
+ </div>
134
+ ) : null}
115
135
 
116
- <div style={{ color: 'var(--text-dim)', fontSize: 11.5, lineHeight: 1.55 }}>
117
- {proposal.outcomeReason}
136
+ <div style={{ color: 'var(--text-dim)', fontSize: 11.5, lineHeight: 1.55 }}>
137
+ {proposal.outcomeReason}
138
+ </div>
118
139
  </div>
119
140
  </div>
120
- </div>
121
- ))}
141
+ )
142
+ })}
122
143
  </div>
123
144
  </article>
124
145
  </div>
@@ -340,6 +340,11 @@ export default function GuidePage() {
340
340
  </div>
341
341
  </div>
342
342
  </div>
343
+ <Callout type="tip">
344
+ HelixEvo now exposes a visible <strong>brain foundation</strong> in the dashboard: ontology-backed summaries,
345
+ activation traces, evolution artifacts, and pressure signals all feed the Overview, Skill Network, Projects,
346
+ Research, and Evolution surfaces.
347
+ </Callout>
343
348
  </Section>
344
349
 
345
350
  {/* ─── Quick Start ─── */}
@@ -347,6 +352,7 @@ export default function GuidePage() {
347
352
  <Callout type="info">
348
353
  <strong>Prerequisites:</strong> Node.js 18+, <a href="https://bun.sh">Bun</a> (for building),
349
354
  and <a href="https://docs.anthropic.com/en/docs/claude-code">Claude CLI</a> with a Claude Max plan.
355
+ Prefer <code>claude auth login</code> managed credentials over exporting a hardcoded <code>CLAUDE_CODE_OAUTH_TOKEN</code>.
350
356
  </Callout>
351
357
 
352
358
  <Step n={1} title="Install HelixEvo">
@@ -450,8 +456,8 @@ helixevo status`}</Code>
450
456
  },
451
457
  {
452
458
  cmd: 'helixevo dashboard',
453
- desc: 'Open the interactive web dashboard at localhost:3847. Shows overview, skill network, evolution timeline, research, and frontier.',
454
- flags: [],
459
+ desc: 'Open the interactive web dashboard at localhost:3847. Before launch, HelixEvo checks npm for a newer version and auto-updates itself unless you opt out.',
460
+ flags: ['--background', '--stop', '--no-auto-update'],
455
461
  },
456
462
  {
457
463
  cmd: 'helixevo status',
@@ -491,6 +497,26 @@ helixevo status`}</Code>
491
497
  </p>
492
498
  <ArchitectureDiagram />
493
499
 
500
+ <h3 className="guide-h3">Brain Foundation</h3>
501
+ <div className="grid-2" style={{ gap: 12, marginBottom: 20 }}>
502
+ <div className="guide-dimension-card" style={{ borderLeftColor: 'var(--blue)' }}>
503
+ <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--blue)', textTransform: 'uppercase', letterSpacing: 1 }}>Ontology</div>
504
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 4 }}>Defines the stable semantic kernel for skills, projects, tasks, capabilities, artifacts, and mutations.</div>
505
+ </div>
506
+ <div className="guide-dimension-card" style={{ borderLeftColor: 'var(--green)' }}>
507
+ <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--green)', textTransform: 'uppercase', letterSpacing: 1 }}>Activation traces</div>
508
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 4 }}>Capture which skills and gaps were active during failure analysis and project analysis.</div>
509
+ </div>
510
+ <div className="guide-dimension-card" style={{ borderLeftColor: 'var(--purple)' }}>
511
+ <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--purple)', textTransform: 'uppercase', letterSpacing: 1 }}>Evolution artifacts</div>
512
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 4 }}>Preserve proposal-level evidence so the dashboard can show what changed, why, and with which provenance.</div>
513
+ </div>
514
+ <div className="guide-dimension-card" style={{ borderLeftColor: 'var(--yellow)' }}>
515
+ <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--yellow)', textTransform: 'uppercase', letterSpacing: 1 }}>Pressure signals</div>
516
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 4 }}>Turn failures and project gaps into explicit adaptation demand, routing attention into Network, Projects, and Research.</div>
517
+ </div>
518
+ </div>
519
+
494
520
  <h3 className="guide-h3">Three-Layer Hierarchy</h3>
495
521
  <p className="guide-text">
496
522
  Skills are organized into three layers. The <code>generalize</code> command promotes patterns upward,
@@ -874,10 +900,13 @@ generation: 3
874
900
  <Code title="~/.helix/ directory structure">{`~/.helix/
875
901
  ├── config.json # Configuration
876
902
  ├── failures.jsonl # Captured failure records (append-only)
903
+ ├── activation-traces.jsonl # Native + derived activation traces
904
+ ├── pressure-signals.jsonl # Native + derived adaptation pressure
905
+ ├── evolution-artifacts.jsonl # Proposal/iteration evidence artifacts
877
906
  ├── frontier.json # Pareto frontier (top-K programs)
878
907
  ├── evolution-history.json # All evolution iterations + proposals
879
908
  ├── skill-tests.jsonl # Regression test cases (append-only)
880
- ├── skill-graph.json # Cached network (nodes + edges)
909
+ ├── skill-graph.json # Cached network (nodes + edges + ontology version)
881
910
  ├── canary-registry.json # Active canary deployments
882
911
  ├── knowledge-buffer.json # Research discoveries + drafts
883
912
  ├── general/ # Skills (SKILL.md files)
@@ -984,6 +1013,11 @@ generation: 3
984
1013
  HelixEvo uses <code>claude --print</code> with configurable models (default: <code>sonnet</code>).
985
1014
  No API key is needed — it requires a Claude Max plan subscription. Judges and proposals can use different models.
986
1015
  </FAQItem>
1016
+ <FAQItem q="What if Claude says my OAuth token expired?">
1017
+ First run <code>claude auth login</code> to refresh local Claude credentials. Avoid exporting a hardcoded
1018
+ <code> CLAUDE_CODE_OAUTH_TOKEN</code> in your shell profile. HelixEvo also retries once without an inherited
1019
+ token override when local Claude auth is healthy.
1020
+ </FAQItem>
987
1021
  <FAQItem q="Can I use HelixEvo with other AI agents?">
988
1022
  Yes. HelixEvo manages standard SKILL.md files with YAML frontmatter. Any agent that reads SKILL.md
989
1023
  files can benefit from HelixEvo&apos;s evolution pipeline.
@@ -12,6 +12,7 @@ import {
12
12
  } from '@xyflow/react'
13
13
  import '@xyflow/react/dist/style.css'
14
14
  import SkillFlowNode from '@/components/SkillFlowNode'
15
+ import { SectionFrame } from '@/components/section-frame'
15
16
 
16
17
  // ─── Types ──────────────────────────────────────────────────────
17
18
 
@@ -33,6 +34,23 @@ interface ProjectData {
33
34
  name: string; failures: any[]; skills: string[]
34
35
  }
35
36
 
37
+ interface ProjectPressureSummary {
38
+ projectId: string
39
+ totalSignals: number
40
+ nativeSignals: number
41
+ derivedSignals: number
42
+ highPrioritySignals: number
43
+ topCapabilities: string[]
44
+ }
45
+
46
+ interface CoEvolutionSummary {
47
+ pressureSignals: { total: number; native: number; derived: number }
48
+ topProjects: ProjectPressureSummary[]
49
+ rolePressure: { generalist: number; specialist: number; hybrid: number }
50
+ crossProjectGapAreas: { area: string; projects: string[]; count: number }[]
51
+ activeRecommendations: { action: 'research' | 'specialize' | 'create'; count: number }[]
52
+ }
53
+
36
54
  interface Props {
37
55
  allNodes: SkillNode[]
38
56
  generalized: SkillNode[]
@@ -42,6 +60,7 @@ interface Props {
42
60
  evolutionBySkill: Record<string, EvolutionEntry[]>
43
61
  skillContents: Record<string, string>
44
62
  projects: ProjectData[]
63
+ coevolution: CoEvolutionSummary
45
64
  stats: { nodes: number; edges: number; clusters: number; generalized: number; evolved: number; original: number }
46
65
  }
47
66
 
@@ -84,7 +103,7 @@ function actionBtnStyle(color?: string): React.CSSProperties {
84
103
  // ─── Main Component ─────────────────────────────────────────────
85
104
 
86
105
  export default function NetworkClient({
87
- allNodes, generalized, evolved, original, edges: graphEdges, evolutionBySkill, skillContents, projects, stats
106
+ allNodes, generalized, evolved, original, edges: graphEdges, evolutionBySkill, skillContents, projects, coevolution, stats
88
107
  }: Props) {
89
108
  const [view, setView] = useState<SubView>('graph')
90
109
  const [selectedSkill, setSelectedSkill] = useState<string | null>(null)
@@ -264,6 +283,111 @@ export default function NetworkClient({
264
283
  </div>
265
284
  </div>
266
285
 
286
+ <SectionFrame
287
+ eyebrow="Co-evolution signals"
288
+ title="Pressure and transfer foundation"
289
+ description="A compact view of where current project demand is pushing on the network, which cognitive roles are implicated, and which gap motifs are repeating across projects."
290
+ tone="blue"
291
+ >
292
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16, marginBottom: 16 }}>
293
+ <div className="metric-card metric-card-blue">
294
+ <div className="metric-card-header">
295
+ <div>
296
+ <div className="metric-card-label">Pressure signals</div>
297
+ <div className="metric-card-value">{coevolution.pressureSignals.total}</div>
298
+ </div>
299
+ <div className="metric-card-icon">◎</div>
300
+ </div>
301
+ <div className="metric-card-sublabel">{coevolution.pressureSignals.native} native • {coevolution.pressureSignals.derived} derived</div>
302
+ </div>
303
+ <div className="metric-card metric-card-purple">
304
+ <div className="metric-card-header">
305
+ <div>
306
+ <div className="metric-card-label">Generalist pressure</div>
307
+ <div className="metric-card-value">{coevolution.rolePressure.generalist}</div>
308
+ </div>
309
+ <div className="metric-card-icon">◎</div>
310
+ </div>
311
+ <div className="metric-card-sublabel">Pressure touching reusable abstractions</div>
312
+ </div>
313
+ <div className="metric-card metric-card-green">
314
+ <div className="metric-card-header">
315
+ <div>
316
+ <div className="metric-card-label">Specialist pressure</div>
317
+ <div className="metric-card-value">{coevolution.rolePressure.specialist}</div>
318
+ </div>
319
+ <div className="metric-card-icon">◉</div>
320
+ </div>
321
+ <div className="metric-card-sublabel">Project-local demand pushing on specialist skills</div>
322
+ </div>
323
+ <div className="metric-card metric-card-yellow">
324
+ <div className="metric-card-header">
325
+ <div>
326
+ <div className="metric-card-label">Cross-project gap motifs</div>
327
+ <div className="metric-card-value">{coevolution.crossProjectGapAreas.length}</div>
328
+ </div>
329
+ <div className="metric-card-icon">⇄</div>
330
+ </div>
331
+ <div className="metric-card-sublabel">Recurring gap areas spanning multiple projects</div>
332
+ </div>
333
+ </div>
334
+
335
+ <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.4fr) minmax(0, 1fr)', gap: 16 }}>
336
+ <div style={{ padding: '16px 18px', borderRadius: 20, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.72)' }}>
337
+ <div className="section-label" style={{ marginBottom: 10 }}>Top project hotspots</div>
338
+ {coevolution.topProjects.length === 0 ? (
339
+ <div className="signal-text">No project pressure signals yet — pressure will appear here once failures and project analysis records accumulate.</div>
340
+ ) : (
341
+ <div style={{ display: 'grid', gap: 10 }}>
342
+ {coevolution.topProjects.map((project) => (
343
+ <div key={project.projectId} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'flex-start', padding: '12px 14px', borderRadius: 16, background: 'rgba(97,93,86,0.06)', border: '1px solid var(--border)' }}>
344
+ <div>
345
+ <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)' }}>{project.projectId}</div>
346
+ <div style={{ fontSize: 11.5, color: 'var(--text-dim)', marginTop: 4 }}>
347
+ {project.highPrioritySignals} high-priority • {project.nativeSignals} native • {project.derivedSignals} derived
348
+ </div>
349
+ {project.topCapabilities.length > 0 ? (
350
+ <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 8 }}>
351
+ {project.topCapabilities.map((capability) => (
352
+ <span key={capability} className="badge badge-gray">{capability}</span>
353
+ ))}
354
+ </div>
355
+ ) : null}
356
+ </div>
357
+ <div style={{ fontSize: 24, fontWeight: 850, color: project.highPrioritySignals > 0 ? 'var(--red)' : 'var(--blue)' }}>{project.totalSignals}</div>
358
+ </div>
359
+ ))}
360
+ </div>
361
+ )}
362
+ </div>
363
+
364
+ <div style={{ padding: '16px 18px', borderRadius: 20, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.72)' }}>
365
+ <div className="section-label" style={{ marginBottom: 10 }}>Emergent routing signals</div>
366
+ <div style={{ display: 'grid', gap: 10 }}>
367
+ <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
368
+ {coevolution.activeRecommendations.length > 0 ? coevolution.activeRecommendations.map((entry) => (
369
+ <span key={entry.action} className={`hero-chip hero-chip-${entry.action === 'research' ? 'blue' : entry.action === 'specialize' ? 'green' : 'purple'}`}>
370
+ {entry.action} × {entry.count}
371
+ </span>
372
+ )) : <span className="badge badge-gray">No routed actions yet</span>}
373
+ </div>
374
+ {coevolution.crossProjectGapAreas.length > 0 ? (
375
+ <div style={{ display: 'grid', gap: 8 }}>
376
+ {coevolution.crossProjectGapAreas.slice(0, 4).map((entry) => (
377
+ <div key={entry.area} style={{ padding: '12px 14px', borderRadius: 16, background: 'rgba(97,93,86,0.06)', border: '1px solid var(--border)' }}>
378
+ <div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{entry.area}</div>
379
+ <div style={{ fontSize: 11.5, color: 'var(--text-dim)', marginTop: 4 }}>{entry.count} projects • {entry.projects.join(', ')}</div>
380
+ </div>
381
+ ))}
382
+ </div>
383
+ ) : (
384
+ <div className="signal-text">Cross-project gap motifs will appear here when the same capability pressure is seen across multiple projects.</div>
385
+ )}
386
+ </div>
387
+ </div>
388
+ </div>
389
+ </SectionFrame>
390
+
267
391
  {/* Create Skill Panel */}
268
392
  {creating && (
269
393
  <div className="card" style={{ marginBottom: 20 }}>
@@ -1,4 +1,4 @@
1
- import { loadGraph, loadSkillContent, loadHistory, listProjects, getProjectSkills } from '@/lib/data'
1
+ import { loadCoEvolutionSummary, loadGraph, loadSkillContent, loadHistory, listProjects, getProjectSkills } from '@/lib/data'
2
2
  import NetworkClient 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 SkillNetworkPage() {
7
7
  const graph = loadGraph()
8
8
  const history = loadHistory()
9
+ const coevolution = loadCoEvolutionSummary()
9
10
  const projects = listProjects()
10
11
 
11
12
  const generalized = graph.nodes.filter(n =>
@@ -62,6 +63,7 @@ export default function SkillNetworkPage() {
62
63
  evolutionBySkill={evolutionBySkill}
63
64
  skillContents={skillContents}
64
65
  projects={projectData}
66
+ coevolution={coevolution}
65
67
  stats={{
66
68
  nodes: graph.nodes.length,
67
69
  edges: graph.edges.length,