helixevo 0.7.0 → 0.8.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 +14 -0
- package/README.md +14 -6
- package/dashboard/app/api/run/route.ts +19 -1
- package/dashboard/app/commands/page.tsx +28 -4
- package/dashboard/app/guide/page.tsx +44 -5
- package/dashboard/app/page.tsx +166 -6
- package/dashboard/app/proof/client.tsx +56 -3
- package/dashboard/app/topology/client.tsx +39 -0
- package/dashboard/lib/data.ts +177 -0
- package/dashboard/lib/release-spotlight.ts +10 -10
- package/dist/cli.js +1249 -225
- package/package.json +2 -2
|
@@ -56,6 +56,12 @@ function toneForChange(changeType: string): 'blue' | 'green' | 'purple' | 'yello
|
|
|
56
56
|
return 'neutral'
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
function toneForOptimizeStatus(status: TopologyDashboardSummary['optimizeStatus']['status']): 'green' | 'yellow' | 'neutral' {
|
|
60
|
+
if (status === 'healthy') return 'green'
|
|
61
|
+
if (status === 'partial' || status === 'failed') return 'yellow'
|
|
62
|
+
return 'neutral'
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
function consoleTone(state: RunState): 'neutral' | 'green' | 'red' | 'yellow' {
|
|
60
66
|
if (state === 'success') return 'green'
|
|
61
67
|
if (state === 'error') return 'red'
|
|
@@ -247,6 +253,7 @@ export default function TopologyClient({
|
|
|
247
253
|
{ label: `${dashboard.summary.open} open reviews`, tone: dashboard.summary.open > 0 ? 'yellow' : 'green' },
|
|
248
254
|
{ label: `${dashboard.execution.prepared} prepared`, tone: dashboard.execution.prepared > 0 ? 'blue' : 'neutral' },
|
|
249
255
|
{ label: `${dashboard.execution.applied} applied`, tone: dashboard.execution.applied > 0 ? 'green' : 'neutral' },
|
|
256
|
+
{ label: `optimize: ${dashboard.optimizeStatus.status}`, tone: toneForOptimizeStatus(dashboard.optimizeStatus.status) },
|
|
250
257
|
{ label: `${proof.summary.reviewOpen} proof review`, tone: proof.summary.reviewOpen > 0 ? 'yellow' : proof.summary.effective > 0 ? 'green' : 'neutral' },
|
|
251
258
|
{ label: formatMode(dashboard.governance.activeMode), tone: toneForMode(dashboard.governance.activeMode) },
|
|
252
259
|
{ label: dashboard.governance.source === 'operator-selected' ? 'operator-steered' : 'derived mode', tone: dashboard.governance.source === 'operator-selected' ? 'purple' : 'neutral' },
|
|
@@ -258,9 +265,15 @@ export default function TopologyClient({
|
|
|
258
265
|
<div className="hero-note-title">{formatMode(dashboard.governance.activeMode)}</div>
|
|
259
266
|
<div className="hero-note-copy">{dashboard.governance.profile.explanation}</div>
|
|
260
267
|
<div style={{ marginTop: 8, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
|
268
|
+
<span className={`badge badge-${dashboard.optimizeStatus.status === 'healthy' ? 'green' : dashboard.optimizeStatus.status === 'idle' ? 'gray' : 'yellow'}`}>optimize {dashboard.optimizeStatus.status}</span>
|
|
261
269
|
<span className="badge badge-gray">{proof.summary.effective} effective records</span>
|
|
262
270
|
<Link href="/proof" className="badge badge-gray" style={{ textDecoration: 'none' }}>open proof</Link>
|
|
263
271
|
</div>
|
|
272
|
+
{dashboard.optimizeStatus.status !== 'idle' ? (
|
|
273
|
+
<div style={{ marginTop: 10, fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.6 }}>
|
|
274
|
+
{dashboard.optimizeStatus.summary}
|
|
275
|
+
</div>
|
|
276
|
+
) : null}
|
|
264
277
|
</div>
|
|
265
278
|
<div style={{ display: 'grid', gap: 10 }}>
|
|
266
279
|
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
|
@@ -284,6 +297,32 @@ export default function TopologyClient({
|
|
|
284
297
|
<MetricCard label="Snapshots" value={dashboard.execution.snapshots} sublabel="before/after state preserved for reviewed execution" tone="purple" icon="◎" />
|
|
285
298
|
</div>
|
|
286
299
|
|
|
300
|
+
<SectionFrame
|
|
301
|
+
eyebrow="Latest optimize run"
|
|
302
|
+
title="Full vs partial structural refresh is now explicit"
|
|
303
|
+
description="Queue refresh and conflict enrichment are tracked separately so a degraded optimize run can still expose a real review queue without pretending the full enrichment pass succeeded."
|
|
304
|
+
tone={toneForOptimizeStatus(dashboard.optimizeStatus.status)}
|
|
305
|
+
>
|
|
306
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
307
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
308
|
+
<span className={`badge badge-${dashboard.optimizeStatus.status === 'healthy' ? 'green' : dashboard.optimizeStatus.status === 'idle' ? 'gray' : 'yellow'}`}>{dashboard.optimizeStatus.status}</span>
|
|
309
|
+
<span className="badge badge-gray">queue {dashboard.optimizeStatus.queue.total} total • {dashboard.optimizeStatus.queue.open} open</span>
|
|
310
|
+
<span className="badge badge-gray">created {dashboard.optimizeStatus.queue.created} • updated {dashboard.optimizeStatus.queue.updated}</span>
|
|
311
|
+
<span className="badge badge-gray">enrichment {dashboard.optimizeStatus.enrichment.resolved} resolved • {dashboard.optimizeStatus.enrichment.failed} failed • {dashboard.optimizeStatus.enrichment.skipped} skipped</span>
|
|
312
|
+
{dashboard.optimizeStatus.ranAt ? <span className="badge badge-gray">ran {formatDate(dashboard.optimizeStatus.ranAt)}</span> : null}
|
|
313
|
+
</div>
|
|
314
|
+
<div className="signal-text">{dashboard.optimizeStatus.summary}</div>
|
|
315
|
+
{dashboard.optimizeStatus.nextStep ? <div className="signal-text">→ {dashboard.optimizeStatus.nextStep}</div> : null}
|
|
316
|
+
{dashboard.optimizeStatus.notices.length > 0 ? (
|
|
317
|
+
<div style={{ display: 'grid', gap: 4 }}>
|
|
318
|
+
{dashboard.optimizeStatus.notices.slice(0, 3).map((notice, index) => (
|
|
319
|
+
<div key={`${dashboard.optimizeStatus.status}-${index}`} className="signal-text">• {notice}</div>
|
|
320
|
+
))}
|
|
321
|
+
</div>
|
|
322
|
+
) : null}
|
|
323
|
+
</div>
|
|
324
|
+
</SectionFrame>
|
|
325
|
+
|
|
287
326
|
<SectionFrame
|
|
288
327
|
eyebrow="Execution pipeline"
|
|
289
328
|
title="Accepted review can now become prepared and applied structure"
|
package/dashboard/lib/data.ts
CHANGED
|
@@ -512,10 +512,94 @@ export interface CoEvolutionDashboardSummary {
|
|
|
512
512
|
recentTopologyDecisions: ResolvedTopologyReviewCandidate[]
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
+
export type TopologyOptimizeStatusKind = 'idle' | 'healthy' | 'partial' | 'failed'
|
|
516
|
+
export type TopologyOptimizeFailureKind = 'auth' | 'timeout' | 'spawn' | 'llm' | 'unknown'
|
|
517
|
+
|
|
518
|
+
export interface TopologyOptimizeStatus {
|
|
519
|
+
command: 'graph-optimize'
|
|
520
|
+
status: TopologyOptimizeStatusKind
|
|
521
|
+
ranAt?: string
|
|
522
|
+
summary: string
|
|
523
|
+
nextStep?: string
|
|
524
|
+
notices: string[]
|
|
525
|
+
queue: {
|
|
526
|
+
total: number
|
|
527
|
+
open: number
|
|
528
|
+
created: number
|
|
529
|
+
updated: number
|
|
530
|
+
}
|
|
531
|
+
enrichment: {
|
|
532
|
+
attempted: number
|
|
533
|
+
resolved: number
|
|
534
|
+
failed: number
|
|
535
|
+
skipped: number
|
|
536
|
+
degraded: boolean
|
|
537
|
+
failureKind?: TopologyOptimizeFailureKind
|
|
538
|
+
warning?: string
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export type LLMProviderId = 'claude-code' | 'codex' | 'ollama'
|
|
543
|
+
export type LLMFallbackPolicy = 'disabled' | 'on-failure'
|
|
544
|
+
export type LLMProviderHealthStatus = 'healthy' | 'degraded' | 'unavailable' | 'unknown'
|
|
545
|
+
export type LLMProviderFailureKind = 'auth' | 'timeout' | 'spawn' | 'network' | 'not-installed' | 'not-configured' | 'model-missing' | 'unknown'
|
|
546
|
+
export type LLMCapability = 'chat' | 'json' | 'judge' | 'web-search'
|
|
547
|
+
|
|
548
|
+
export interface LLMProviderSnapshot {
|
|
549
|
+
provider: LLMProviderId
|
|
550
|
+
configured: boolean
|
|
551
|
+
enabled: boolean
|
|
552
|
+
installed: boolean
|
|
553
|
+
available: boolean
|
|
554
|
+
loggedIn?: boolean
|
|
555
|
+
authMethod?: string
|
|
556
|
+
apiProvider?: string
|
|
557
|
+
status: LLMProviderHealthStatus
|
|
558
|
+
model?: string
|
|
559
|
+
judgeModel?: string
|
|
560
|
+
summary: string
|
|
561
|
+
nextStep?: string
|
|
562
|
+
failureKind?: LLMProviderFailureKind
|
|
563
|
+
warning?: string
|
|
564
|
+
notices: string[]
|
|
565
|
+
lastCheckedAt?: string
|
|
566
|
+
lastSelectedAt?: string
|
|
567
|
+
lastUsedAt?: string
|
|
568
|
+
lastSucceededAt?: string
|
|
569
|
+
lastFailedAt?: string
|
|
570
|
+
lastFailureMessage?: string
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
export interface LLMExecutionRecord {
|
|
574
|
+
capability: LLMCapability
|
|
575
|
+
scope: 'shared' | 'claude-only'
|
|
576
|
+
selectionMode: 'default' | 'explicit'
|
|
577
|
+
selectedProvider: LLMProviderId
|
|
578
|
+
attemptedProviders: LLMProviderId[]
|
|
579
|
+
usedProvider?: LLMProviderId
|
|
580
|
+
fallbackUsed: boolean
|
|
581
|
+
success: boolean
|
|
582
|
+
ranAt: string
|
|
583
|
+
summary: string
|
|
584
|
+
nextStep?: string
|
|
585
|
+
failureKind?: LLMProviderFailureKind
|
|
586
|
+
warning?: string
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export interface LLMRuntimeState {
|
|
590
|
+
updatedAt: string
|
|
591
|
+
defaultProvider: LLMProviderId
|
|
592
|
+
fallbackPolicy: LLMFallbackPolicy
|
|
593
|
+
fallbackOrder: LLMProviderId[]
|
|
594
|
+
lastExecution?: LLMExecutionRecord
|
|
595
|
+
providers: Record<LLMProviderId, LLMProviderSnapshot>
|
|
596
|
+
}
|
|
597
|
+
|
|
515
598
|
export interface TopologyDashboardSummary {
|
|
516
599
|
governance: ActiveGovernanceSummary
|
|
517
600
|
summary: CoEvolutionDashboardSummary['topologyReviews']
|
|
518
601
|
execution: CoEvolutionDashboardSummary['topologyExecution']
|
|
602
|
+
optimizeStatus: TopologyOptimizeStatus
|
|
519
603
|
backlog: ResolvedTopologyReviewCandidate[]
|
|
520
604
|
recentDecisions: ResolvedTopologyReviewCandidate[]
|
|
521
605
|
acceptedReady: ResolvedTopologyReviewCandidate[]
|
|
@@ -1407,15 +1491,108 @@ export function getTopologyReviewSummary() {
|
|
|
1407
1491
|
}
|
|
1408
1492
|
}
|
|
1409
1493
|
|
|
1494
|
+
const DEFAULT_TOPOLOGY_OPTIMIZE_STATUS: TopologyOptimizeStatus = {
|
|
1495
|
+
command: 'graph-optimize',
|
|
1496
|
+
status: 'idle',
|
|
1497
|
+
summary: 'No optimize run recorded yet.',
|
|
1498
|
+
notices: [],
|
|
1499
|
+
queue: {
|
|
1500
|
+
total: 0,
|
|
1501
|
+
open: 0,
|
|
1502
|
+
created: 0,
|
|
1503
|
+
updated: 0,
|
|
1504
|
+
},
|
|
1505
|
+
enrichment: {
|
|
1506
|
+
attempted: 0,
|
|
1507
|
+
resolved: 0,
|
|
1508
|
+
failed: 0,
|
|
1509
|
+
skipped: 0,
|
|
1510
|
+
degraded: false,
|
|
1511
|
+
},
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
export function loadTopologyOptimizeStatus(): TopologyOptimizeStatus {
|
|
1515
|
+
return readJson<TopologyOptimizeStatus>('topology-optimize-status.json', DEFAULT_TOPOLOGY_OPTIMIZE_STATUS)
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
const DEFAULT_LLM_RUNTIME_STATE: LLMRuntimeState = {
|
|
1519
|
+
updatedAt: new Date(0).toISOString(),
|
|
1520
|
+
defaultProvider: 'claude-code',
|
|
1521
|
+
fallbackPolicy: 'disabled',
|
|
1522
|
+
fallbackOrder: [],
|
|
1523
|
+
providers: {
|
|
1524
|
+
'claude-code': {
|
|
1525
|
+
provider: 'claude-code',
|
|
1526
|
+
configured: true,
|
|
1527
|
+
enabled: true,
|
|
1528
|
+
installed: false,
|
|
1529
|
+
available: false,
|
|
1530
|
+
status: 'unknown',
|
|
1531
|
+
model: 'sonnet',
|
|
1532
|
+
judgeModel: 'sonnet',
|
|
1533
|
+
summary: 'No Claude provider health has been recorded yet.',
|
|
1534
|
+
notices: [],
|
|
1535
|
+
},
|
|
1536
|
+
codex: {
|
|
1537
|
+
provider: 'codex',
|
|
1538
|
+
configured: false,
|
|
1539
|
+
enabled: false,
|
|
1540
|
+
installed: false,
|
|
1541
|
+
available: false,
|
|
1542
|
+
status: 'unknown',
|
|
1543
|
+
model: 'gpt-5-codex',
|
|
1544
|
+
judgeModel: 'gpt-5-codex',
|
|
1545
|
+
summary: 'No Codex provider health has been recorded yet.',
|
|
1546
|
+
notices: [],
|
|
1547
|
+
},
|
|
1548
|
+
ollama: {
|
|
1549
|
+
provider: 'ollama',
|
|
1550
|
+
configured: false,
|
|
1551
|
+
enabled: false,
|
|
1552
|
+
installed: false,
|
|
1553
|
+
available: false,
|
|
1554
|
+
status: 'unknown',
|
|
1555
|
+
model: 'qwen3-coder:latest',
|
|
1556
|
+
judgeModel: 'qwen3-coder:latest',
|
|
1557
|
+
summary: 'No Ollama provider health has been recorded yet.',
|
|
1558
|
+
notices: [],
|
|
1559
|
+
},
|
|
1560
|
+
},
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
export function loadLlmRuntimeState(): LLMRuntimeState {
|
|
1564
|
+
const state = readJson<LLMRuntimeState>('llm-runtime-state.json', DEFAULT_LLM_RUNTIME_STATE)
|
|
1565
|
+
return {
|
|
1566
|
+
...DEFAULT_LLM_RUNTIME_STATE,
|
|
1567
|
+
...state,
|
|
1568
|
+
providers: {
|
|
1569
|
+
'claude-code': {
|
|
1570
|
+
...DEFAULT_LLM_RUNTIME_STATE.providers['claude-code'],
|
|
1571
|
+
...(state.providers?.['claude-code'] ?? {}),
|
|
1572
|
+
},
|
|
1573
|
+
codex: {
|
|
1574
|
+
...DEFAULT_LLM_RUNTIME_STATE.providers.codex,
|
|
1575
|
+
...(state.providers?.codex ?? {}),
|
|
1576
|
+
},
|
|
1577
|
+
ollama: {
|
|
1578
|
+
...DEFAULT_LLM_RUNTIME_STATE.providers.ollama,
|
|
1579
|
+
...(state.providers?.ollama ?? {}),
|
|
1580
|
+
},
|
|
1581
|
+
},
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1410
1585
|
export function loadTopologyDashboardSummary(): TopologyDashboardSummary {
|
|
1411
1586
|
const governance = getActiveGovernanceSummary()
|
|
1412
1587
|
const summary = getTopologyReviewSummary()
|
|
1413
1588
|
const execution = getTopologyExecutionSummary()
|
|
1589
|
+
const optimizeStatus = loadTopologyOptimizeStatus()
|
|
1414
1590
|
const candidates = loadResolvedTopologyReviewCandidates()
|
|
1415
1591
|
return {
|
|
1416
1592
|
governance,
|
|
1417
1593
|
summary,
|
|
1418
1594
|
execution,
|
|
1595
|
+
optimizeStatus,
|
|
1419
1596
|
backlog: summary.backlog,
|
|
1420
1597
|
recentDecisions: summary.recentDecisions,
|
|
1421
1598
|
acceptedReady: execution.acceptedReady,
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
export const CURRENT_RELEASE_SPOTLIGHT = {
|
|
2
|
-
version: '0.
|
|
3
|
-
title: 'What changed in 0.
|
|
2
|
+
version: '0.8.0',
|
|
3
|
+
title: 'What changed in 0.8.0',
|
|
4
4
|
summary:
|
|
5
|
-
'This release
|
|
5
|
+
'This grouped release hardens HelixEvo’s actuation layer and makes provider control explicit: optimize/reporting is more truthful under degraded conditions, Claude Code stays the default provider, and Codex plus Ollama become optional backends for supported shared paths.',
|
|
6
6
|
bullets: [
|
|
7
|
-
'HelixEvo now
|
|
8
|
-
'Overview,
|
|
9
|
-
'
|
|
10
|
-
'
|
|
7
|
+
'HelixEvo now preserves useful topology review refreshes even when conflict enrichment degrades, and it records the difference explicitly instead of hiding it behind brittle failure.',
|
|
8
|
+
'Provider control is now first-class: status and Overview show default provider, degraded state, last execution truth, and fallback usage instead of treating backend execution as a hidden monolith.',
|
|
9
|
+
'Claude Code remains the default provider, while GPT Codex and Ollama are available as optional providers for shared prompt-in / text-out operations.',
|
|
10
|
+
'Claude-backed web search and research remain explicitly Claude-scoped, preserving capability truth instead of pretending full provider symmetry where it does not exist yet.',
|
|
11
11
|
],
|
|
12
12
|
nextActions: [
|
|
13
|
-
{ label: '
|
|
14
|
-
{ label: '
|
|
15
|
-
{ label: 'Read
|
|
13
|
+
{ label: 'Inspect backend truth', href: '/commands', tone: 'blue' as const },
|
|
14
|
+
{ label: 'Review topology state', href: '/topology', tone: 'purple' as const },
|
|
15
|
+
{ label: 'Read provider guide', href: '/guide#config', tone: 'green' as const },
|
|
16
16
|
],
|
|
17
17
|
} as const
|