helixevo 0.6.0 → 0.6.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 +9 -0
- package/dashboard/app/coevolution/client.tsx +54 -30
- package/dashboard/app/ontology/client.tsx +31 -16
- package/dashboard/app/page.tsx +28 -0
- package/dashboard/app/projects/client.tsx +13 -19
- package/dashboard/app/research/client.tsx +29 -8
- package/dashboard/app/topology/client.tsx +51 -29
- package/dashboard/components/guide-deep-link.tsx +22 -0
- package/dashboard/components/next-step-empty-state.tsx +53 -0
- package/dashboard/components/operator-loop-trail.tsx +46 -0
- package/dashboard/components/surface-jump-links.tsx +69 -0
- package/dashboard/lib/loop-map.ts +190 -0
- package/dashboard/lib/release-spotlight.ts +17 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@ All notable changes to HelixEvo are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.6.1] - 2026-03-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Shared dashboard operator-flow helpers for loop-stage breadcrumbs, contextual surface handoffs, curated release spotlight content, and guide deep-link integration
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Overview, Projects, Research, Co-Evolution, Ontology, and Topology now expose clearer operator breadcrumbs, adjacent control links, and stronger next-step empty-state onboarding
|
|
14
|
+
- Overview release spotlight is now curated through a dedicated helper so post-release guidance stays easy to update and does not silently drift stale
|
|
15
|
+
|
|
7
16
|
## [0.6.0] - 2026-03-24
|
|
8
17
|
|
|
9
18
|
### Added
|
|
@@ -6,6 +6,9 @@ import { ConsolePanel } from '@/components/console-panel'
|
|
|
6
6
|
import { MetricCard } from '@/components/metric-card'
|
|
7
7
|
import { PageHero } from '@/components/page-hero'
|
|
8
8
|
import { SectionFrame } from '@/components/section-frame'
|
|
9
|
+
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
10
|
+
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
11
|
+
import { NextStepEmptyState } from '@/components/next-step-empty-state'
|
|
9
12
|
|
|
10
13
|
type RunState = 'idle' | 'running' | 'success' | 'error' | 'stopped'
|
|
11
14
|
type CommandName = 'evolve' | 'research' | 'generalize'
|
|
@@ -283,17 +286,20 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
283
286
|
<span className="badge badge-gray">review threshold {(summary.governance.profile.reviewThreshold * 100).toFixed(0)}%</span>
|
|
284
287
|
</div>
|
|
285
288
|
</div>
|
|
286
|
-
<div style={{ display: '
|
|
287
|
-
<
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
<div style={{ display: 'grid', gap: 10 }}>
|
|
290
|
+
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
291
|
+
<button onClick={() => handleRun('research')} disabled={runState === 'running'} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Run research</button>
|
|
292
|
+
<button onClick={() => handleRun('evolve')} disabled={runState === 'running'} className="badge badge-green" style={{ border: 'none', cursor: 'pointer' }}>Run evolve</button>
|
|
293
|
+
<button onClick={() => handleRun('generalize')} disabled={runState === 'running'} className="badge badge-purple" style={{ border: 'none', cursor: 'pointer' }}>Run generalize</button>
|
|
294
|
+
</div>
|
|
295
|
+
<SurfaceJumpLinks surface="coevolution" variant="compact" title="Response handoffs" />
|
|
292
296
|
</div>
|
|
293
297
|
</div>
|
|
294
298
|
}
|
|
295
299
|
/>
|
|
296
300
|
|
|
301
|
+
<OperatorLoopTrail surface="coevolution" />
|
|
302
|
+
|
|
297
303
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
298
304
|
<MetricCard label="Open pressure" value={summary.pressureLifecycle.open} sublabel={`${summary.pressureLifecycle.highPriorityOpen} high-priority waiting for response`} tone={summary.pressureLifecycle.open > 0 ? 'yellow' : 'green'} icon="!" />
|
|
299
305
|
<MetricCard label="Promotion-ready motifs" value={summary.pressureMotifs.promotionReady} sublabel={`${summary.pressureMotifs.total} recurring motifs tracked`} tone="purple" icon="⇄" />
|
|
@@ -403,10 +409,13 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
403
409
|
</div>
|
|
404
410
|
</div>
|
|
405
411
|
)) : (
|
|
406
|
-
<
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
412
|
+
<NextStepEmptyState
|
|
413
|
+
title="No promotion-ready motifs yet"
|
|
414
|
+
description="Recurring cross-project demand will appear here once the same pressure region repeats often enough to justify generalization instead of one-off local response."
|
|
415
|
+
command="helixevo project-setup <path>"
|
|
416
|
+
pageLink={{ label: 'Open Projects', href: '/projects', tone: 'blue' }}
|
|
417
|
+
guideLink={{ label: 'Guide · Adaptation Loop', anchor: 'loop', tone: 'purple' }}
|
|
418
|
+
/>
|
|
410
419
|
)}
|
|
411
420
|
</div>
|
|
412
421
|
</SectionFrame>
|
|
@@ -430,10 +439,13 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
430
439
|
<div className="metric-card-sublabel">{lane.resolving} resolving • {lane.exploratory} exploratory • {lane.none} non-resolving</div>
|
|
431
440
|
</div>
|
|
432
441
|
)) : (
|
|
433
|
-
<
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
442
|
+
<NextStepEmptyState
|
|
443
|
+
title="No intervention records yet"
|
|
444
|
+
description="The governed response ledger will start populating once pressure is routed into live research, evolve, or generalize work."
|
|
445
|
+
command="helixevo evolve"
|
|
446
|
+
pageLink={{ label: 'Open Research', href: '/research', tone: 'blue' }}
|
|
447
|
+
guideLink={{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'purple' }}
|
|
448
|
+
/>
|
|
437
449
|
)}
|
|
438
450
|
</div>
|
|
439
451
|
</SectionFrame>
|
|
@@ -472,10 +484,13 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
472
484
|
</div>
|
|
473
485
|
</div>
|
|
474
486
|
)) : (
|
|
475
|
-
<
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
487
|
+
<NextStepEmptyState
|
|
488
|
+
title="No project response hotspots yet"
|
|
489
|
+
description="Project-linked pressure will appear here once failures and project analysis produce current demand for the response loop to act on."
|
|
490
|
+
command="helixevo project-setup <path>"
|
|
491
|
+
pageLink={{ label: 'Open Projects', href: '/projects', tone: 'blue' }}
|
|
492
|
+
guideLink={{ label: 'Guide · Quick Start', anchor: 'quickstart', tone: 'purple' }}
|
|
493
|
+
/>
|
|
479
494
|
)}
|
|
480
495
|
</div>
|
|
481
496
|
</SectionFrame>
|
|
@@ -501,10 +516,13 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
501
516
|
</div>
|
|
502
517
|
</div>
|
|
503
518
|
)) : (
|
|
504
|
-
<
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
519
|
+
<NextStepEmptyState
|
|
520
|
+
title="No transfer evidence yet"
|
|
521
|
+
description="Transfer evidence appears after recurring pressure is promoted into reusable generalized knowledge rather than staying trapped in local fixes."
|
|
522
|
+
command="helixevo generalize"
|
|
523
|
+
pageLink={{ label: 'Open Ontology', href: '/ontology', tone: 'green' }}
|
|
524
|
+
guideLink={{ label: 'Guide · Semantic Control', anchor: 'semanticcontrol', tone: 'purple' }}
|
|
525
|
+
/>
|
|
508
526
|
)}
|
|
509
527
|
</div>
|
|
510
528
|
</SectionFrame>
|
|
@@ -548,10 +566,13 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
548
566
|
</div>
|
|
549
567
|
</div>
|
|
550
568
|
)) : (
|
|
551
|
-
<
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
569
|
+
<NextStepEmptyState
|
|
570
|
+
title="No open pressure backlog"
|
|
571
|
+
description="Open and in-progress pressure will queue here once HelixEvo is observing real demand from projects, failures, or recurring motifs."
|
|
572
|
+
command="helixevo watch --project <name>"
|
|
573
|
+
pageLink={{ label: 'Open Projects', href: '/projects', tone: 'blue' }}
|
|
574
|
+
guideLink={{ label: 'Guide · Adaptation Loop', anchor: 'loop', tone: 'purple' }}
|
|
575
|
+
/>
|
|
555
576
|
)}
|
|
556
577
|
</div>
|
|
557
578
|
</SectionFrame>
|
|
@@ -578,10 +599,13 @@ export default function CoEvolutionClient({ summary, ontology }: Props) {
|
|
|
578
599
|
</div>
|
|
579
600
|
</div>
|
|
580
601
|
)) : (
|
|
581
|
-
<
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
602
|
+
<NextStepEmptyState
|
|
603
|
+
title="No response records yet"
|
|
604
|
+
description="Command-level intervention records will appear here once the response loop starts operating across research, evolve, generalize, or manual review."
|
|
605
|
+
command="helixevo research"
|
|
606
|
+
pageLink={{ label: 'Open Ontology', href: '/ontology', tone: 'green' }}
|
|
607
|
+
guideLink={{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'purple' }}
|
|
608
|
+
/>
|
|
585
609
|
)}
|
|
586
610
|
</div>
|
|
587
611
|
</SectionFrame>
|
|
@@ -6,6 +6,9 @@ import { ConsolePanel } from '@/components/console-panel'
|
|
|
6
6
|
import { MetricCard } from '@/components/metric-card'
|
|
7
7
|
import { PageHero } from '@/components/page-hero'
|
|
8
8
|
import { SectionFrame } from '@/components/section-frame'
|
|
9
|
+
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
10
|
+
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
11
|
+
import { NextStepEmptyState } from '@/components/next-step-empty-state'
|
|
9
12
|
import type { OntologyControlDashboardSummary, OntologyReviewDecisionStatus } from '@/lib/data'
|
|
10
13
|
|
|
11
14
|
type RunState = 'idle' | 'running' | 'success' | 'error'
|
|
@@ -86,15 +89,18 @@ export default function OntologyClient({ initialDashboard }: { initialDashboard:
|
|
|
86
89
|
<div className="hero-note-title">Kernel + review + semantic adoption</div>
|
|
87
90
|
<div className="hero-note-copy">Use this surface to move from frontier hypotheses into approved extensions, inspect active semantic consumers, and manage deprecation with operator-visible risk rather than hidden drift.</div>
|
|
88
91
|
</div>
|
|
89
|
-
<div style={{ display: '
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
<div style={{ display: 'grid', gap: 10 }}>
|
|
93
|
+
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
94
|
+
<button onClick={() => runAction('refresh', {}, 'ontology refresh')} disabled={runState === 'running'} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Refresh ontology frontier</button>
|
|
95
|
+
</div>
|
|
96
|
+
<SurfaceJumpLinks surface="ontology" variant="compact" title="Semantic handoffs" />
|
|
93
97
|
</div>
|
|
94
98
|
</div>
|
|
95
99
|
}
|
|
96
100
|
/>
|
|
97
101
|
|
|
102
|
+
<OperatorLoopTrail surface="ontology" />
|
|
103
|
+
|
|
98
104
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
99
105
|
<MetricCard label="Kernel concepts" value={dashboard.summary.kernelConcepts} sublabel={`${dashboard.kernel.relationFamilies.length} relation families`} tone="purple" icon="◎" />
|
|
100
106
|
<MetricCard label="Frontier hypotheses" value={dashboard.summary.frontier} sublabel={`${dashboard.summary.reviewOpen} open • ${dashboard.summary.deferred} deferred`} tone={dashboard.summary.reviewOpen > 0 ? 'yellow' : 'neutral'} icon="◇" />
|
|
@@ -198,10 +204,13 @@ export default function OntologyClient({ initialDashboard }: { initialDashboard:
|
|
|
198
204
|
</div>
|
|
199
205
|
</div>
|
|
200
206
|
)) : (
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
<NextStepEmptyState
|
|
208
|
+
title="No ontology frontier concepts yet"
|
|
209
|
+
description="Run a frontier refresh after pressure motifs, project gaps, or topology review patterns accumulate. Frontier creation is the first step before any concept can become active semantic control."
|
|
210
|
+
command="helixevo ontology --refresh"
|
|
211
|
+
pageLink={{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple' }}
|
|
212
|
+
guideLink={{ label: 'Guide · Semantic Control', anchor: 'semanticcontrol', tone: 'green' }}
|
|
213
|
+
/>
|
|
205
214
|
)}
|
|
206
215
|
</div>
|
|
207
216
|
</SectionFrame>
|
|
@@ -240,10 +249,13 @@ export default function OntologyClient({ initialDashboard }: { initialDashboard:
|
|
|
240
249
|
{concept.warning ? <div className="signal-text" style={{ marginTop: 10 }}>• {concept.warning}</div> : null}
|
|
241
250
|
</div>
|
|
242
251
|
)) : (
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
252
|
+
<NextStepEmptyState
|
|
253
|
+
title="No approved extensions yet"
|
|
254
|
+
description="Approved extensions appear after frontier concepts pass semantic review. Promotion is what turns reviewed ontology into live semantic adoption."
|
|
255
|
+
command="helixevo ontology --review <conceptId> --decision promote"
|
|
256
|
+
pageLink={{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple' }}
|
|
257
|
+
guideLink={{ label: 'Guide · Semantic Control', anchor: 'semanticcontrol', tone: 'green' }}
|
|
258
|
+
/>
|
|
247
259
|
)}
|
|
248
260
|
</div>
|
|
249
261
|
</SectionFrame>
|
|
@@ -267,10 +279,13 @@ export default function OntologyClient({ initialDashboard }: { initialDashboard:
|
|
|
267
279
|
</div>
|
|
268
280
|
</div>
|
|
269
281
|
)) : (
|
|
270
|
-
<
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
<NextStepEmptyState
|
|
283
|
+
title="No ontology changes logged yet"
|
|
284
|
+
description="Refresh the frontier or review a concept to create the first native ontology events and start a visible semantic history instead of hidden drift."
|
|
285
|
+
command="helixevo ontology --refresh"
|
|
286
|
+
pageLink={{ label: 'Open Topology', href: '/topology', tone: 'yellow' }}
|
|
287
|
+
guideLink={{ label: 'Guide · Semantic Control', anchor: 'semanticcontrol', tone: 'green' }}
|
|
288
|
+
/>
|
|
274
289
|
)}
|
|
275
290
|
</div>
|
|
276
291
|
</SectionFrame>
|
package/dashboard/app/page.tsx
CHANGED
|
@@ -4,6 +4,9 @@ import { OverviewActions } from '@/components/overview-actions'
|
|
|
4
4
|
import { PageHero } from '@/components/page-hero'
|
|
5
5
|
import { MetricCard } from '@/components/metric-card'
|
|
6
6
|
import { SectionFrame } from '@/components/section-frame'
|
|
7
|
+
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
8
|
+
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
9
|
+
import { CURRENT_RELEASE_SPOTLIGHT } from '@/lib/release-spotlight'
|
|
7
10
|
|
|
8
11
|
export const dynamic = 'force-dynamic'
|
|
9
12
|
|
|
@@ -57,6 +60,8 @@ export default function Overview() {
|
|
|
57
60
|
}
|
|
58
61
|
/>
|
|
59
62
|
|
|
63
|
+
<OperatorLoopTrail surface="overview" />
|
|
64
|
+
|
|
60
65
|
<div className="grid-5">
|
|
61
66
|
<MetricCard label="Total skills" value={summary.skills.total} sublabel={`${summary.skills.evolved} evolved • ${summary.skillTests} skill tests`} tone="purple" href="/network" icon="◆" />
|
|
62
67
|
<MetricCard label="Accepted proposals" value={summary.evolution.accepted} sublabel={`${summary.evolution.rejected} rejected`} tone="green" href="/evolution" icon="✓" />
|
|
@@ -65,6 +70,29 @@ export default function Overview() {
|
|
|
65
70
|
<MetricCard label="Frontier candidates" value={frontier.programs.length} sublabel={`${summary.canaries} active canaries`} tone="neutral" href="/frontier" icon="▲" />
|
|
66
71
|
</div>
|
|
67
72
|
|
|
73
|
+
<SectionFrame
|
|
74
|
+
eyebrow={`Release spotlight · v${CURRENT_RELEASE_SPOTLIGHT.version}`}
|
|
75
|
+
title={CURRENT_RELEASE_SPOTLIGHT.title}
|
|
76
|
+
description={CURRENT_RELEASE_SPOTLIGHT.summary}
|
|
77
|
+
tone="blue"
|
|
78
|
+
>
|
|
79
|
+
<div className="grid-2" style={{ gap: 16 }}>
|
|
80
|
+
<div style={{ display: 'grid', gap: 10 }}>
|
|
81
|
+
{CURRENT_RELEASE_SPOTLIGHT.bullets.map((item) => (
|
|
82
|
+
<div key={item} className="signal-text">• {item}</div>
|
|
83
|
+
))}
|
|
84
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 4 }}>
|
|
85
|
+
{CURRENT_RELEASE_SPOTLIGHT.nextActions.map((action) => (
|
|
86
|
+
<Link key={action.href} href={action.href} className={`hero-chip hero-chip-${action.tone}`} style={{ textDecoration: 'none' }}>
|
|
87
|
+
{action.label}
|
|
88
|
+
</Link>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<SurfaceJumpLinks surface="overview" variant="panel" title="Jump into the updated loop" />
|
|
93
|
+
</div>
|
|
94
|
+
</SectionFrame>
|
|
95
|
+
|
|
68
96
|
<SectionFrame
|
|
69
97
|
eyebrow="Execution layer"
|
|
70
98
|
title="Quick actions"
|
|
@@ -6,6 +6,9 @@ import { ConsolePanel } from '@/components/console-panel'
|
|
|
6
6
|
import { MetricCard } from '@/components/metric-card'
|
|
7
7
|
import { PageHero } from '@/components/page-hero'
|
|
8
8
|
import { SectionFrame } from '@/components/section-frame'
|
|
9
|
+
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
10
|
+
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
11
|
+
import { NextStepEmptyState } from '@/components/next-step-empty-state'
|
|
9
12
|
import type { ProjectProfile } from '@/lib/data'
|
|
10
13
|
|
|
11
14
|
type SetupState = 'idle' | 'analyzing' | 'done' | 'error' | 'cancelled'
|
|
@@ -364,18 +367,13 @@ export default function ProjectsClient({ profiles, skillCount, projectAnalysisTr
|
|
|
364
367
|
<div className="hero-note-title">Analyze → Match → Gap scan → Action</div>
|
|
365
368
|
<div className="hero-note-copy">Run a profile, review the skill fit, then send uncovered needs into Research or the Skill Network.</div>
|
|
366
369
|
</div>
|
|
367
|
-
<
|
|
368
|
-
<Link href="/network" style={buttonStyle('purple')}>
|
|
369
|
-
Open Skill Network
|
|
370
|
-
</Link>
|
|
371
|
-
<Link href="/research" style={buttonStyle('blue')}>
|
|
372
|
-
Open Research
|
|
373
|
-
</Link>
|
|
374
|
-
</div>
|
|
370
|
+
<SurfaceJumpLinks surface="projects" variant="compact" title="Observation handoffs" />
|
|
375
371
|
</div>
|
|
376
372
|
}
|
|
377
373
|
/>
|
|
378
374
|
|
|
375
|
+
<OperatorLoopTrail surface="projects" />
|
|
376
|
+
|
|
379
377
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16, marginBottom: 24 }}>
|
|
380
378
|
<MetricCard
|
|
381
379
|
label="Portfolio"
|
|
@@ -764,17 +762,13 @@ export default function ProjectsClient({ profiles, skillCount, projectAnalysisTr
|
|
|
764
762
|
tone="yellow"
|
|
765
763
|
>
|
|
766
764
|
{profiles.length === 0 ? (
|
|
767
|
-
<
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
<div className="empty-state-desc">
|
|
775
|
-
Start with a local folder or GitHub repository. The resulting profile will show matched skills, uncovered gaps, and recommended next steps.
|
|
776
|
-
</div>
|
|
777
|
-
</div>
|
|
765
|
+
<NextStepEmptyState
|
|
766
|
+
title="No analyzed projects yet"
|
|
767
|
+
description={`Start with a local folder or GitHub repository. The resulting profile will show matched skills, uncovered gaps, activation traces, and the next routed action against your ${skillCount} current skills.`}
|
|
768
|
+
command="helixevo project-setup <path>"
|
|
769
|
+
pageLink={{ label: 'Open Research', href: '/research', tone: 'blue' }}
|
|
770
|
+
guideLink={{ label: 'Guide · Quick Start', anchor: 'quickstart', tone: 'purple' }}
|
|
771
|
+
/>
|
|
778
772
|
) : (
|
|
779
773
|
<div style={{ display: 'grid', gap: 18 }}>
|
|
780
774
|
{profiles.map(profile => {
|
|
@@ -5,6 +5,9 @@ import { ConsolePanel } from '@/components/console-panel'
|
|
|
5
5
|
import { MetricCard } from '@/components/metric-card'
|
|
6
6
|
import { PageHero } from '@/components/page-hero'
|
|
7
7
|
import { SectionFrame } from '@/components/section-frame'
|
|
8
|
+
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
9
|
+
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
10
|
+
import { NextStepEmptyState } from '@/components/next-step-empty-state'
|
|
8
11
|
|
|
9
12
|
interface Discovery {
|
|
10
13
|
id: string
|
|
@@ -190,8 +193,20 @@ export default function ResearchClient({ buffer, projects, coevolution }: Props)
|
|
|
190
193
|
{ label: `${buffer.drafts.length} drafts`, tone: 'yellow' },
|
|
191
194
|
{ label: `${nearPass.length} near-pass drafts`, tone: 'green' },
|
|
192
195
|
]}
|
|
196
|
+
actions={
|
|
197
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
198
|
+
<div className="hero-note-card">
|
|
199
|
+
<div className="hero-note-label">Discovery handoff</div>
|
|
200
|
+
<div className="hero-note-title">Observe gaps → research patterns → draft reusable skills</div>
|
|
201
|
+
<div className="hero-note-copy">Use Research when recurring project demand needs external evidence before it can become a stronger response or semantic pattern.</div>
|
|
202
|
+
</div>
|
|
203
|
+
<SurfaceJumpLinks surface="research" variant="compact" title="Discovery handoffs" />
|
|
204
|
+
</div>
|
|
205
|
+
}
|
|
193
206
|
/>
|
|
194
207
|
|
|
208
|
+
<OperatorLoopTrail surface="research" />
|
|
209
|
+
|
|
195
210
|
<SectionFrame
|
|
196
211
|
eyebrow="Why research now"
|
|
197
212
|
title="Current pressure handoff"
|
|
@@ -371,10 +386,13 @@ export default function ResearchClient({ buffer, projects, coevolution }: Props)
|
|
|
371
386
|
tone="blue"
|
|
372
387
|
>
|
|
373
388
|
{buffer.discoveries.length === 0 ? (
|
|
374
|
-
<
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
389
|
+
<NextStepEmptyState
|
|
390
|
+
title="No discoveries yet"
|
|
391
|
+
description="Run research to search the web for techniques your skill network does not cover yet, then compare those discoveries against the current routed pressure picture."
|
|
392
|
+
command="helixevo research"
|
|
393
|
+
pageLink={{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'green' }}
|
|
394
|
+
guideLink={{ label: 'Guide · Adaptation Loop', anchor: 'loop', tone: 'purple' }}
|
|
395
|
+
/>
|
|
378
396
|
) : (
|
|
379
397
|
<div className="summary-list">
|
|
380
398
|
{buffer.discoveries.sort((a, b) => b.score - a.score).map((discovery) => (
|
|
@@ -400,10 +418,13 @@ export default function ResearchClient({ buffer, projects, coevolution }: Props)
|
|
|
400
418
|
tone="yellow"
|
|
401
419
|
>
|
|
402
420
|
{buffer.drafts.length === 0 ? (
|
|
403
|
-
<
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
421
|
+
<NextStepEmptyState
|
|
422
|
+
title="No drafts yet"
|
|
423
|
+
description="Once research has enough evidence, it will generate the first draft skills and evaluate them against the current thresholds before they enter the wider loop."
|
|
424
|
+
command="helixevo research --verbose"
|
|
425
|
+
pageLink={{ label: 'Open Projects', href: '/projects', tone: 'blue' }}
|
|
426
|
+
guideLink={{ label: 'Guide · Quick Start', anchor: 'quickstart', tone: 'purple' }}
|
|
427
|
+
/>
|
|
407
428
|
) : (
|
|
408
429
|
<div className="summary-list">
|
|
409
430
|
{buffer.drafts.sort((a, b) => b.avgScore - a.avgScore).map((draft) => (
|
|
@@ -6,6 +6,9 @@ import { ConsolePanel } from '@/components/console-panel'
|
|
|
6
6
|
import { MetricCard } from '@/components/metric-card'
|
|
7
7
|
import { PageHero } from '@/components/page-hero'
|
|
8
8
|
import { SectionFrame } from '@/components/section-frame'
|
|
9
|
+
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
10
|
+
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
11
|
+
import { NextStepEmptyState } from '@/components/next-step-empty-state'
|
|
9
12
|
import type { GovernanceModeName, GovernanceState, TopologyDashboardSummary, TopologyReviewDecisionStatus, TopologyReviewStatus } from '@/lib/data'
|
|
10
13
|
|
|
11
14
|
type RunState = 'idle' | 'running' | 'success' | 'error' | 'stopped'
|
|
@@ -251,16 +254,18 @@ export default function TopologyClient({
|
|
|
251
254
|
<div className="hero-note-title">{formatMode(dashboard.governance.activeMode)}</div>
|
|
252
255
|
<div className="hero-note-copy">{dashboard.governance.profile.explanation}</div>
|
|
253
256
|
</div>
|
|
254
|
-
<div style={{ display: '
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
<
|
|
257
|
+
<div style={{ display: 'grid', gap: 10 }}>
|
|
258
|
+
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
259
|
+
<button onClick={handleOptimize} disabled={runState === 'running'} className="badge badge-blue" style={{ border: 'none', cursor: 'pointer' }}>Run graph optimize</button>
|
|
260
|
+
</div>
|
|
261
|
+
<SurfaceJumpLinks surface="topology" variant="compact" title="Structural handoffs" />
|
|
259
262
|
</div>
|
|
260
263
|
</div>
|
|
261
264
|
}
|
|
262
265
|
/>
|
|
263
266
|
|
|
267
|
+
<OperatorLoopTrail surface="topology" />
|
|
268
|
+
|
|
264
269
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
265
270
|
<MetricCard label="Open review items" value={dashboard.summary.open} sublabel={`${dashboard.summary.deferred} deferred • ${dashboard.summary.accepted} accepted`} tone={dashboard.summary.open > 0 ? 'yellow' : 'green'} icon="⇄" />
|
|
266
271
|
<MetricCard label="Accepted ready" value={dashboard.acceptedReady.length} sublabel="accepted candidates not yet prepared for execution" tone={dashboard.acceptedReady.length > 0 ? 'blue' : 'neutral'} icon="✓" />
|
|
@@ -300,10 +305,13 @@ export default function TopologyClient({
|
|
|
300
305
|
</div>
|
|
301
306
|
</div>
|
|
302
307
|
)) : (
|
|
303
|
-
<
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
308
|
+
<NextStepEmptyState
|
|
309
|
+
title="No accepted candidates waiting for preparation"
|
|
310
|
+
description="Accept a topology review item first, then it can enter the reviewed execution pipeline and become a prepared apply plan."
|
|
311
|
+
command="helixevo graph --optimize"
|
|
312
|
+
pageLink={{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple' }}
|
|
313
|
+
guideLink={{ label: 'Guide · Maturity & Safety', anchor: 'maturity', tone: 'yellow' }}
|
|
314
|
+
/>
|
|
307
315
|
)}
|
|
308
316
|
</div>
|
|
309
317
|
|
|
@@ -342,10 +350,13 @@ export default function TopologyClient({
|
|
|
342
350
|
</div>
|
|
343
351
|
</div>
|
|
344
352
|
)) : (
|
|
345
|
-
<
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
353
|
+
<NextStepEmptyState
|
|
354
|
+
title="No prepared plans yet"
|
|
355
|
+
description="Prepared plans will appear here after an accepted review candidate is converted into an explicit apply plan with snapshot-backed safety."
|
|
356
|
+
command="helixevo topology --prepare <candidateId>"
|
|
357
|
+
pageLink={{ label: 'Open Ontology', href: '/ontology', tone: 'green' }}
|
|
358
|
+
guideLink={{ label: 'Guide · Maturity & Safety', anchor: 'maturity', tone: 'yellow' }}
|
|
359
|
+
/>
|
|
349
360
|
)}
|
|
350
361
|
</div>
|
|
351
362
|
</div>
|
|
@@ -426,10 +437,13 @@ export default function TopologyClient({
|
|
|
426
437
|
</div>
|
|
427
438
|
</div>
|
|
428
439
|
)) : (
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
440
|
+
<NextStepEmptyState
|
|
441
|
+
title="No topology decisions yet"
|
|
442
|
+
description="Run graph optimize to populate the queue, then accept, defer, or reject structural candidates from this page so the review memory becomes explicit."
|
|
443
|
+
command="helixevo graph --optimize"
|
|
444
|
+
pageLink={{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple' }}
|
|
445
|
+
guideLink={{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'blue' }}
|
|
446
|
+
/>
|
|
433
447
|
)}
|
|
434
448
|
</div>
|
|
435
449
|
</SectionFrame>
|
|
@@ -491,10 +505,13 @@ export default function TopologyClient({
|
|
|
491
505
|
</div>
|
|
492
506
|
</div>
|
|
493
507
|
)) : (
|
|
494
|
-
<
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
508
|
+
<NextStepEmptyState
|
|
509
|
+
title="No topology backlog yet"
|
|
510
|
+
description="Refresh structural review candidates from this page to turn manual-review into a populated operator lane instead of a placeholder route label."
|
|
511
|
+
command="helixevo graph --optimize"
|
|
512
|
+
pageLink={{ label: 'Open Ontology', href: '/ontology', tone: 'green' }}
|
|
513
|
+
guideLink={{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'blue' }}
|
|
514
|
+
/>
|
|
498
515
|
)}
|
|
499
516
|
</div>
|
|
500
517
|
</SectionFrame>
|
|
@@ -539,10 +556,12 @@ export default function TopologyClient({
|
|
|
539
556
|
</div>
|
|
540
557
|
</div>
|
|
541
558
|
)) : (
|
|
542
|
-
<
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
559
|
+
<NextStepEmptyState
|
|
560
|
+
title="No applied topology history yet"
|
|
561
|
+
description="Applied topology history will appear here once a prepared safe plan is executed and snapshot-backed rollback continuity becomes relevant."
|
|
562
|
+
command="helixevo topology --apply <planId>"
|
|
563
|
+
guideLink={{ label: 'Guide · Maturity & Safety', anchor: 'maturity', tone: 'yellow' }}
|
|
564
|
+
/>
|
|
546
565
|
)}
|
|
547
566
|
</div>
|
|
548
567
|
</SectionFrame>
|
|
@@ -567,10 +586,13 @@ export default function TopologyClient({
|
|
|
567
586
|
</div>
|
|
568
587
|
</div>
|
|
569
588
|
)) : (
|
|
570
|
-
<
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
589
|
+
<NextStepEmptyState
|
|
590
|
+
title="No structural candidates stored yet"
|
|
591
|
+
description="The structural review ledger will populate after the first topology refresh and then persist reviewed intent across decisions and execution."
|
|
592
|
+
command="helixevo graph --optimize"
|
|
593
|
+
pageLink={{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple' }}
|
|
594
|
+
guideLink={{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'blue' }}
|
|
595
|
+
/>
|
|
574
596
|
)}
|
|
575
597
|
</div>
|
|
576
598
|
</SectionFrame>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Link from 'next/link'
|
|
2
|
+
import { guideHref, type GuideAnchorId, type SurfaceTone } from '@/lib/loop-map'
|
|
3
|
+
|
|
4
|
+
function toneClass(tone: SurfaceTone) {
|
|
5
|
+
return `hero-chip hero-chip-${tone}`
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function GuideDeepLink({
|
|
9
|
+
anchor,
|
|
10
|
+
label,
|
|
11
|
+
tone = 'neutral',
|
|
12
|
+
}: {
|
|
13
|
+
anchor: GuideAnchorId
|
|
14
|
+
label: string
|
|
15
|
+
tone?: SurfaceTone
|
|
16
|
+
}) {
|
|
17
|
+
return (
|
|
18
|
+
<Link href={guideHref(anchor)} className={toneClass(tone)} style={{ textDecoration: 'none' }}>
|
|
19
|
+
{label}
|
|
20
|
+
</Link>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import Link from 'next/link'
|
|
2
|
+
import { GuideDeepLink } from '@/components/guide-deep-link'
|
|
3
|
+
import type { GuideAnchorId, SurfaceTone } from '@/lib/loop-map'
|
|
4
|
+
|
|
5
|
+
export function NextStepEmptyState({
|
|
6
|
+
title,
|
|
7
|
+
description,
|
|
8
|
+
command,
|
|
9
|
+
pageLink,
|
|
10
|
+
guideLink,
|
|
11
|
+
}: {
|
|
12
|
+
title: string
|
|
13
|
+
description: string
|
|
14
|
+
command?: string
|
|
15
|
+
pageLink?: { label: string; href: string; tone?: SurfaceTone }
|
|
16
|
+
guideLink?: { label: string; anchor: GuideAnchorId; tone?: SurfaceTone }
|
|
17
|
+
}) {
|
|
18
|
+
return (
|
|
19
|
+
<div className="empty-state" style={{ padding: 24 }}>
|
|
20
|
+
<div className="empty-state-title">{title}</div>
|
|
21
|
+
<div className="empty-state-desc" style={{ maxWidth: 680 }}>{description}</div>
|
|
22
|
+
{command ? (
|
|
23
|
+
<div
|
|
24
|
+
style={{
|
|
25
|
+
marginTop: 14,
|
|
26
|
+
padding: '12px 14px',
|
|
27
|
+
borderRadius: 16,
|
|
28
|
+
border: '1px solid var(--border)',
|
|
29
|
+
background: 'rgba(255,255,255,0.76)',
|
|
30
|
+
display: 'inline-grid',
|
|
31
|
+
gap: 6,
|
|
32
|
+
textAlign: 'left',
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
<div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.9 }}>Try next</div>
|
|
36
|
+
<code style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5, color: 'var(--text)' }}>$ {command}</code>
|
|
37
|
+
</div>
|
|
38
|
+
) : null}
|
|
39
|
+
{(pageLink || guideLink) ? (
|
|
40
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'center', marginTop: 14 }}>
|
|
41
|
+
{pageLink ? (
|
|
42
|
+
<Link href={pageLink.href} className={`hero-chip hero-chip-${pageLink.tone ?? 'blue'}`} style={{ textDecoration: 'none' }}>
|
|
43
|
+
{pageLink.label}
|
|
44
|
+
</Link>
|
|
45
|
+
) : null}
|
|
46
|
+
{guideLink ? (
|
|
47
|
+
<GuideDeepLink anchor={guideLink.anchor} label={guideLink.label} tone={guideLink.tone ?? 'purple'} />
|
|
48
|
+
) : null}
|
|
49
|
+
</div>
|
|
50
|
+
) : null}
|
|
51
|
+
</div>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import Link from 'next/link'
|
|
2
|
+
import { LOOP_STAGES, getSurfaceLoopConfig, type SurfaceKey } from '@/lib/loop-map'
|
|
3
|
+
|
|
4
|
+
export function OperatorLoopTrail({ surface }: { surface: SurfaceKey }) {
|
|
5
|
+
const config = getSurfaceLoopConfig(surface)
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
style={{
|
|
10
|
+
padding: '14px 16px',
|
|
11
|
+
borderRadius: 20,
|
|
12
|
+
border: '1px solid var(--border)',
|
|
13
|
+
background: 'linear-gradient(180deg, rgba(255,255,255,0.82), rgba(245,241,236,0.72))',
|
|
14
|
+
boxShadow: 'var(--shadow-xs)',
|
|
15
|
+
display: 'grid',
|
|
16
|
+
gap: 10,
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
|
|
20
|
+
<div>
|
|
21
|
+
<div className="section-label">Operator loop</div>
|
|
22
|
+
<div style={{ fontSize: 12.5, color: 'var(--text-dim)', marginTop: 4, lineHeight: 1.55 }}>{config.context}</div>
|
|
23
|
+
</div>
|
|
24
|
+
<span className="badge badge-gray">
|
|
25
|
+
{config.stage ? `Current stage · ${LOOP_STAGES.find((stage) => stage.id === config.stage)?.label}` : 'Cockpit view'}
|
|
26
|
+
</span>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
30
|
+
{LOOP_STAGES.map((stage) => {
|
|
31
|
+
const active = config.stage === stage.id
|
|
32
|
+
return (
|
|
33
|
+
<Link
|
|
34
|
+
key={stage.id}
|
|
35
|
+
href={stage.href}
|
|
36
|
+
className={`hero-chip hero-chip-${active ? stage.tone : 'neutral'}`}
|
|
37
|
+
style={{ textDecoration: 'none' }}
|
|
38
|
+
>
|
|
39
|
+
{stage.label}
|
|
40
|
+
</Link>
|
|
41
|
+
)
|
|
42
|
+
})}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import Link from 'next/link'
|
|
2
|
+
import { getSurfaceLoopConfig, guideHref, type SurfaceKey } from '@/lib/loop-map'
|
|
3
|
+
|
|
4
|
+
export function SurfaceJumpLinks({
|
|
5
|
+
surface,
|
|
6
|
+
title = 'Next hops',
|
|
7
|
+
variant = 'compact',
|
|
8
|
+
}: {
|
|
9
|
+
surface: SurfaceKey
|
|
10
|
+
title?: string
|
|
11
|
+
variant?: 'compact' | 'panel'
|
|
12
|
+
}) {
|
|
13
|
+
const config = getSurfaceLoopConfig(surface)
|
|
14
|
+
|
|
15
|
+
if (variant === 'compact') {
|
|
16
|
+
return (
|
|
17
|
+
<div style={{ display: 'grid', gap: 8 }}>
|
|
18
|
+
<div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--text-muted)', letterSpacing: 0.9, textTransform: 'uppercase' }}>{title}</div>
|
|
19
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
20
|
+
{config.adjacentLinks.map((link) => (
|
|
21
|
+
<Link key={link.href} href={link.href} className={`badge badge-${link.tone === 'neutral' ? 'gray' : link.tone}`} style={{ textDecoration: 'none' }}>
|
|
22
|
+
{link.label}
|
|
23
|
+
</Link>
|
|
24
|
+
))}
|
|
25
|
+
{config.guideLinks.map((link) => (
|
|
26
|
+
<Link key={link.anchor} href={guideHref(link.anchor)} className={`hero-chip hero-chip-${link.tone}`} style={{ textDecoration: 'none' }}>
|
|
27
|
+
{link.label}
|
|
28
|
+
</Link>
|
|
29
|
+
))}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
37
|
+
<div>
|
|
38
|
+
<div className="section-label">{title}</div>
|
|
39
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, lineHeight: 1.6 }}>
|
|
40
|
+
Move deliberately into the next most relevant surface instead of backing out to Overview every time.
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div className="grid-2" style={{ gap: 12 }}>
|
|
45
|
+
{config.adjacentLinks.map((link) => (
|
|
46
|
+
<Link
|
|
47
|
+
key={link.href}
|
|
48
|
+
href={link.href}
|
|
49
|
+
className="card"
|
|
50
|
+
style={{ padding: '14px 16px', textDecoration: 'none', display: 'grid', gap: 6 }}
|
|
51
|
+
>
|
|
52
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
|
|
53
|
+
<span className={`hero-chip hero-chip-${link.tone}`}>{link.label}</span>
|
|
54
|
+
</div>
|
|
55
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.6 }}>{link.description}</div>
|
|
56
|
+
</Link>
|
|
57
|
+
))}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
61
|
+
{config.guideLinks.map((link) => (
|
|
62
|
+
<Link key={link.anchor} href={guideHref(link.anchor)} className={`hero-chip hero-chip-${link.tone}`} style={{ textDecoration: 'none' }}>
|
|
63
|
+
{link.label}
|
|
64
|
+
</Link>
|
|
65
|
+
))}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
export type LoopStageId = 'observe' | 'route' | 'adopt' | 'restructure' | 'prove'
|
|
2
|
+
export type SurfaceKey = 'overview' | 'projects' | 'research' | 'coevolution' | 'ontology' | 'topology'
|
|
3
|
+
export type SurfaceTone = 'blue' | 'green' | 'purple' | 'yellow' | 'neutral'
|
|
4
|
+
export type GuideAnchorId = 'quickstart' | 'brainstack' | 'loop' | 'semanticcontrol' | 'surfaces' | 'commands' | 'maturity' | 'metrics'
|
|
5
|
+
|
|
6
|
+
export interface LoopStageMeta {
|
|
7
|
+
id: LoopStageId
|
|
8
|
+
label: string
|
|
9
|
+
href: string
|
|
10
|
+
tone: SurfaceTone
|
|
11
|
+
description: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SurfaceJumpLink {
|
|
15
|
+
label: string
|
|
16
|
+
href: string
|
|
17
|
+
tone: SurfaceTone
|
|
18
|
+
description: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface GuideDeepLinkDef {
|
|
22
|
+
label: string
|
|
23
|
+
anchor: GuideAnchorId
|
|
24
|
+
tone: SurfaceTone
|
|
25
|
+
description: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SurfaceLoopConfig {
|
|
29
|
+
key: SurfaceKey
|
|
30
|
+
label: string
|
|
31
|
+
context: string
|
|
32
|
+
stage?: LoopStageId
|
|
33
|
+
adjacentLinks: SurfaceJumpLink[]
|
|
34
|
+
guideLinks: GuideDeepLinkDef[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const LOOP_STAGES: LoopStageMeta[] = [
|
|
38
|
+
{
|
|
39
|
+
id: 'observe',
|
|
40
|
+
label: 'Observe',
|
|
41
|
+
href: '/projects',
|
|
42
|
+
tone: 'blue',
|
|
43
|
+
description: 'Project intake, pressure discovery, and activation-aware observation.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'route',
|
|
47
|
+
label: 'Route',
|
|
48
|
+
href: '/coevolution',
|
|
49
|
+
tone: 'purple',
|
|
50
|
+
description: 'Governed response selection across research, evolve, generalize, and review lanes.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'adopt',
|
|
54
|
+
label: 'Adopt',
|
|
55
|
+
href: '/ontology',
|
|
56
|
+
tone: 'green',
|
|
57
|
+
description: 'Promote approved concepts into active semantic consumers inside the live loop.',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'restructure',
|
|
61
|
+
label: 'Restructure',
|
|
62
|
+
href: '/topology',
|
|
63
|
+
tone: 'yellow',
|
|
64
|
+
description: 'Turn reviewed structural intent into prepared, applied, and rollbackable change.',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'prove',
|
|
68
|
+
label: 'Prove',
|
|
69
|
+
href: '/guide#metrics',
|
|
70
|
+
tone: 'neutral',
|
|
71
|
+
description: 'Check evidence, metrics, and guide-backed operator understanding.',
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
export const GUIDE_ANCHOR_LABELS: Record<GuideAnchorId, string> = {
|
|
76
|
+
quickstart: 'Quick Start',
|
|
77
|
+
brainstack: 'Brain Stack',
|
|
78
|
+
loop: 'Adaptation Loop',
|
|
79
|
+
semanticcontrol: 'Semantic Control',
|
|
80
|
+
surfaces: 'Surface Map',
|
|
81
|
+
commands: 'Commands',
|
|
82
|
+
maturity: 'Maturity & Safety',
|
|
83
|
+
metrics: 'Closed-Loop Metrics',
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function guideHref(anchor: GuideAnchorId) {
|
|
87
|
+
return `/guide#${anchor}`
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const SURFACE_LOOP_CONFIG: Record<SurfaceKey, SurfaceLoopConfig> = {
|
|
91
|
+
overview: {
|
|
92
|
+
key: 'overview',
|
|
93
|
+
label: 'Overview',
|
|
94
|
+
context: 'Use Overview as the cockpit entry into the full loop, then jump into the stage that currently needs attention.',
|
|
95
|
+
adjacentLinks: [
|
|
96
|
+
{ label: 'Open Projects', href: '/projects', tone: 'blue', description: 'Start from project intake, gap discovery, and observation.' },
|
|
97
|
+
{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple', description: 'Inspect governed routing and the active response backlog.' },
|
|
98
|
+
{ label: 'Open Ontology', href: '/ontology', tone: 'green', description: 'Inspect semantic adoption, frontier review, and concept consumers.' },
|
|
99
|
+
{ label: 'Open Topology', href: '/topology', tone: 'yellow', description: 'Review structural candidates, preparation, and rollbackable execution.' },
|
|
100
|
+
],
|
|
101
|
+
guideLinks: [
|
|
102
|
+
{ label: 'Read Quick Start', anchor: 'quickstart', tone: 'blue', description: 'See the shortest operator path into the live brain loop.' },
|
|
103
|
+
{ label: 'Read Surface Map', anchor: 'surfaces', tone: 'purple', description: 'Understand how each dashboard surface fits together.' },
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
projects: {
|
|
107
|
+
key: 'projects',
|
|
108
|
+
label: 'Projects',
|
|
109
|
+
stage: 'observe',
|
|
110
|
+
context: 'Projects is where local context becomes explicit observation: capabilities, gaps, activation traces, and pressure feeders.',
|
|
111
|
+
adjacentLinks: [
|
|
112
|
+
{ label: 'Open Research', href: '/research', tone: 'purple', description: 'Turn uncovered project gaps into discovery work.' },
|
|
113
|
+
{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'green', description: 'See how project pressure is being routed into response.' },
|
|
114
|
+
{ label: 'Open Ontology', href: '/ontology', tone: 'blue', description: 'Check whether recurring project demand is becoming semantic adoption.' },
|
|
115
|
+
{ label: 'Open Skill Network', href: '/network', tone: 'neutral', description: 'Inspect the skills that were matched or may need specialization.' },
|
|
116
|
+
],
|
|
117
|
+
guideLinks: [
|
|
118
|
+
{ label: 'Guide · Quick Start', anchor: 'quickstart', tone: 'blue', description: 'Follow the operator path from project intake to response.' },
|
|
119
|
+
{ label: 'Guide · Adaptation Loop', anchor: 'loop', tone: 'purple', description: 'Trace how project observation becomes routed adaptation.' },
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
research: {
|
|
123
|
+
key: 'research',
|
|
124
|
+
label: 'Research',
|
|
125
|
+
stage: 'observe',
|
|
126
|
+
context: 'Research extends observation into discovery by turning recurring capability pressure into external evidence and candidate skills.',
|
|
127
|
+
adjacentLinks: [
|
|
128
|
+
{ label: 'Open Projects', href: '/projects', tone: 'blue', description: 'Return to the project contexts that produced the gaps.' },
|
|
129
|
+
{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'green', description: 'Check how governed routing is prioritizing research pressure.' },
|
|
130
|
+
{ label: 'Open Ontology', href: '/ontology', tone: 'purple', description: 'Inspect whether recurring research demand is becoming active semantics.' },
|
|
131
|
+
],
|
|
132
|
+
guideLinks: [
|
|
133
|
+
{ label: 'Guide · Quick Start', anchor: 'quickstart', tone: 'blue', description: 'See how research fits the current operator path.' },
|
|
134
|
+
{ label: 'Guide · Adaptation Loop', anchor: 'loop', tone: 'purple', description: 'Connect discovery work back to the broader loop.' },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
coevolution: {
|
|
138
|
+
key: 'coevolution',
|
|
139
|
+
label: 'Co-Evolution',
|
|
140
|
+
stage: 'route',
|
|
141
|
+
context: 'Co-Evolution is the response cockpit where observed demand is routed under governance into the next adaptation lane.',
|
|
142
|
+
adjacentLinks: [
|
|
143
|
+
{ label: 'Open Ontology', href: '/ontology', tone: 'green', description: 'Inspect which approved concepts are influencing current route rationale.' },
|
|
144
|
+
{ label: 'Open Topology', href: '/topology', tone: 'yellow', description: 'Escalate mixed-signal structural demand into review and execution.' },
|
|
145
|
+
{ label: 'Open Research', href: '/research', tone: 'blue', description: 'Run or inspect the discovery lane when research is the governed response.' },
|
|
146
|
+
],
|
|
147
|
+
guideLinks: [
|
|
148
|
+
{ label: 'Guide · Semantic Control', anchor: 'semanticcontrol', tone: 'green', description: 'See how semantic adoption shapes route explanation without bypassing governance.' },
|
|
149
|
+
{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'purple', description: 'Compare the response cockpit with the nearby control surfaces.' },
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
ontology: {
|
|
153
|
+
key: 'ontology',
|
|
154
|
+
label: 'Ontology',
|
|
155
|
+
stage: 'adopt',
|
|
156
|
+
context: 'Ontology is where reviewed concepts become approved extensions and then become visible as active semantic consumers.',
|
|
157
|
+
adjacentLinks: [
|
|
158
|
+
{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple', description: 'See where active concepts are influencing current route rationale.' },
|
|
159
|
+
{ label: 'Open Topology', href: '/topology', tone: 'yellow', description: 'Compare semantic adoption with structural review and execution.' },
|
|
160
|
+
{ label: 'Open Skill Network', href: '/network', tone: 'blue', description: 'Inspect semantic context alongside graph relationships and inspector detail.' },
|
|
161
|
+
],
|
|
162
|
+
guideLinks: [
|
|
163
|
+
{ label: 'Guide · Semantic Control', anchor: 'semanticcontrol', tone: 'green', description: 'Read the post-M8 / post-M9 ontology lifecycle and operator playbooks.' },
|
|
164
|
+
{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'purple', description: 'See where ontology sits relative to Co-Evolution and Topology.' },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
topology: {
|
|
168
|
+
key: 'topology',
|
|
169
|
+
label: 'Topology',
|
|
170
|
+
stage: 'restructure',
|
|
171
|
+
context: 'Topology is the structural handoff where reviewed intent becomes prepared, applied, and rollbackable graph change.',
|
|
172
|
+
adjacentLinks: [
|
|
173
|
+
{ label: 'Open Ontology', href: '/ontology', tone: 'green', description: 'Check the semantic families clustering around current structural candidates.' },
|
|
174
|
+
{ label: 'Open Co-Evolution', href: '/coevolution', tone: 'purple', description: 'Return to the governed response backlog feeding structural review.' },
|
|
175
|
+
{ label: 'Open Skill Network', href: '/network', tone: 'blue', description: 'Inspect the graph context around the candidates being reviewed or applied.' },
|
|
176
|
+
],
|
|
177
|
+
guideLinks: [
|
|
178
|
+
{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'purple', description: 'See how topology fits the rest of the dashboard operator loop.' },
|
|
179
|
+
{ label: 'Guide · Maturity & Safety', anchor: 'maturity', tone: 'yellow', description: 'Review the current bounded-safe-execution limits before structural action.' },
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function getSurfaceLoopConfig(surface: SurfaceKey) {
|
|
185
|
+
return SURFACE_LOOP_CONFIG[surface]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function getLoopStage(stageId: LoopStageId) {
|
|
189
|
+
return LOOP_STAGES.find((stage) => stage.id === stageId)
|
|
190
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const CURRENT_RELEASE_SPOTLIGHT = {
|
|
2
|
+
version: '0.6.1',
|
|
3
|
+
title: 'What changed in 0.6.1',
|
|
4
|
+
summary:
|
|
5
|
+
'This patch turns the dashboard into a more connected operator system: the major control surfaces now show where they sit in the live loop, where to jump next, and what to do when the system is still cold.',
|
|
6
|
+
bullets: [
|
|
7
|
+
'Overview, Projects, Research, Co-Evolution, Ontology, and Topology now show a shared operator-loop trail.',
|
|
8
|
+
'Each major surface now exposes contextual handoffs instead of isolated one-off page links.',
|
|
9
|
+
'Cold-state pages now provide command-level next steps, relevant adjacent pages, and direct Guide anchors.',
|
|
10
|
+
'Overview now includes a curated release spotlight so operators can immediately see what this patch added.',
|
|
11
|
+
],
|
|
12
|
+
nextActions: [
|
|
13
|
+
{ label: 'Open the operator loop', href: '/', tone: 'blue' as const },
|
|
14
|
+
{ label: 'Inspect semantic control', href: '/ontology', tone: 'green' as const },
|
|
15
|
+
{ label: 'Read dashboard handoffs', href: '/guide#surfaces', tone: 'purple' as const },
|
|
16
|
+
],
|
|
17
|
+
} as const
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helixevo",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Co-evolving skill and project brain for AI agents, with ontology-aware learning, governed response, rollbackable topology control, and a premium dashboard.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|