helixevo 0.8.0 → 0.9.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 +19 -0
- package/README.md +5 -5
- package/dashboard/app/coevolution/client.tsx +23 -1
- package/dashboard/app/page.tsx +179 -181
- package/dashboard/app/proof/client.tsx +84 -15
- package/dashboard/lib/data.ts +130 -12
- package/dashboard/lib/proof.ts +267 -10
- package/dist/cli.js +1645 -1332
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ All notable changes to HelixEvo are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.0] - 2026-03-25
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Proof steering summaries with explicit evidence tiers — `trusted`, `caution`, `bounded`, and `candidate` — so proved outcomes can be surfaced as route-level and semantic-control influence instead of remaining only a descriptive ledger
|
|
11
|
+
- Candidate-vs-priority proof queue separation so dry-run and insufficient-evidence records stay visible without crowding higher-leverage review
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Pressure route recommendations now consume bounded proof steering after semantic influence, allowing weak evidence to stay bounded, cautionary evidence to bias toward review, and verified/effective evidence to strengthen trust modestly
|
|
15
|
+
- Overview, Proof, and Co-Evolution now expose prove-to-steer closure directly, including trusted/caution lane visibility and proof-aware route rationale
|
|
16
|
+
- `status`, `proof --status --verbose`, and the public README now describe Proof as a bounded steering input into the next governed loop rather than only a post-action review surface
|
|
17
|
+
|
|
18
|
+
## [0.8.1] - 2026-03-25
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- Overview now behaves more like an essential operator cockpit and gives higher priority to live operator state over release/reference framing
|
|
22
|
+
- Unresolved corrections now surface earlier in the landing flow when active, ahead of quick actions and semantic summary content
|
|
23
|
+
- Healthy provider state remains compact on Overview while fallback/deviation cases are explained more explicitly and truthfully
|
|
24
|
+
- Semantic backbone now reads as a compact brain summary instead of a dense secondary dashboard, with direct control links into co-evolution, ontology, topology, and proof
|
|
25
|
+
|
|
7
26
|
## [0.8.0] - 2026-03-25
|
|
8
27
|
|
|
9
28
|
### Added
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# HelixEvo
|
|
2
2
|
|
|
3
|
-
Co-evolving skill and project brain for AI agents. HelixEvo captures failures, traces activations, models pressure, routes governed responses, promotes cross-project transfer, reviews structural topology changes, safely executes accepted topology transitions with rollback, lets approved ontology concepts become active semantic consumers inside the live control loop, and now
|
|
3
|
+
Co-evolving skill and project brain for AI agents. HelixEvo captures failures, traces activations, models pressure, routes governed responses, promotes cross-project transfer, reviews structural topology changes, safely executes accepted topology transitions with rollback, lets approved ontology concepts become active semantic consumers inside the live control loop, and now turns Proof into a bounded steering input for future control instead of a descriptive layer alone.
|
|
4
4
|
|
|
5
5
|
## How it works
|
|
6
6
|
|
|
@@ -87,7 +87,7 @@ helixevo dashboard
|
|
|
87
87
|
|---------|-------------|
|
|
88
88
|
| `helixevo watch` | Always-on learning: auto-capture + auto-evolve |
|
|
89
89
|
| `helixevo metrics` | Correction rates, skill trends, evolution impact |
|
|
90
|
-
| `helixevo proof` | Outcome attribution
|
|
90
|
+
| `helixevo proof` | Outcome attribution, proof review, and steering summaries across interventions, transfer, topology, ontology, and evolution |
|
|
91
91
|
| `helixevo health` | Network health: cohesion, coverage, balance, transfer |
|
|
92
92
|
| `helixevo init` | Import existing skills + generate skill tests |
|
|
93
93
|
| `helixevo capture <session>` | Extract failures from a session file |
|
|
@@ -199,10 +199,10 @@ helixevo dashboard --port 3900
|
|
|
199
199
|
**Tabs:**
|
|
200
200
|
- **Overview** — Premium control cockpit with frontier signals, brain foundation, provider-control truth, semantic backbone, ontology adoption visibility, proof review visibility, pressure counts, topology review visibility, and prepared/applied structural state
|
|
201
201
|
- **Skill Network** — Interactive graph, premium inspector, co-evolution routing signals, and topology review/execution handoff links
|
|
202
|
-
- **Co-Evolution** — Operator cockpit for routed pressure response, governance mode visibility, promotion queues, transfer evidence, semantic route influence, and topology handoff
|
|
202
|
+
- **Co-Evolution** — Operator cockpit for routed pressure response, governance mode visibility, promotion queues, transfer evidence, semantic route influence, proof-aware route rationale, and topology handoff
|
|
203
203
|
- **Ontology** — Semantic control surface for kernel visibility, frontier concept review, approved ontology extensions, adoption coverage, deprecation risk, and native ontology change events
|
|
204
204
|
- **Topology** — Governance steering plus a persistent operator pipeline for review → prepare → apply → rollback across merge / split / promote / rewire / consolidate candidates
|
|
205
|
-
- **Proof** — Outcome-attribution and proof-
|
|
205
|
+
- **Proof** — Outcome-attribution, review, and proof-steering cockpit for bounded effectiveness across interventions, transfer, topology execution, semantic adoption, and evolution impact
|
|
206
206
|
- **Projects** — Project intake studio, live project analysis, gap routing, per-project pressure hotspots, and promotion feeders
|
|
207
207
|
- **Evolution** — Timeline of evolution runs with judge scores, artifact provenance, and activation-aware context
|
|
208
208
|
- **Research** — Knowledge buffer plus a live “why research now” handoff from current pressure, governed routing, and recurring gaps
|
|
@@ -249,7 +249,7 @@ Failures → Cluster → Propose → Replay → Multi-Judge → Regression → C
|
|
|
249
249
|
- **Governance steering** lets the operator pin or release the active adaptation mode rather than relying only on derived routing.
|
|
250
250
|
- **Topology review** persists merge / split / promote / rewire / consolidate candidates so manual review is a real workflow.
|
|
251
251
|
- **Reviewed topology execution** turns accepted safe candidates into prepared plans, snapshot-backed applies, and rollbackable structural transitions.
|
|
252
|
-
- **Proof control** turns bounded outcome attribution into an explicit operator layer where interventions, transfer, topology execution, semantic adoption, and evolution impact can be verified, deferred, or contested.
|
|
252
|
+
- **Proof control** turns bounded outcome attribution into an explicit operator layer where interventions, transfer, topology execution, semantic adoption, and evolution impact can be verified, deferred, or contested, then fed back into future control through bounded proof steering.
|
|
253
253
|
- **Evolution artifacts** preserve proposal-level evidence so the dashboard can show what changed, why, and with what provenance.
|
|
254
254
|
|
|
255
255
|
**Three-layer hierarchy:**
|
|
@@ -78,6 +78,11 @@ type Summary = {
|
|
|
78
78
|
reasons: string[]
|
|
79
79
|
semanticInfluence?: 'none' | 'explanatory' | 'weighted'
|
|
80
80
|
semanticConceptIds?: string[]
|
|
81
|
+
proofInfluence?: 'none' | 'explanatory' | 'weighted'
|
|
82
|
+
proofTier?: 'trusted' | 'caution' | 'bounded' | 'candidate'
|
|
83
|
+
proofSummary?: string
|
|
84
|
+
proofReasons?: string[]
|
|
85
|
+
proofLaneKeys?: string[]
|
|
81
86
|
}
|
|
82
87
|
semanticConceptIds?: string[]
|
|
83
88
|
}[]
|
|
@@ -103,6 +108,11 @@ type Summary = {
|
|
|
103
108
|
reasons: string[]
|
|
104
109
|
semanticInfluence?: 'none' | 'explanatory' | 'weighted'
|
|
105
110
|
semanticConceptIds?: string[]
|
|
111
|
+
proofInfluence?: 'none' | 'explanatory' | 'weighted'
|
|
112
|
+
proofTier?: 'trusted' | 'caution' | 'bounded' | 'candidate'
|
|
113
|
+
proofSummary?: string
|
|
114
|
+
proofReasons?: string[]
|
|
115
|
+
proofLaneKeys?: string[]
|
|
106
116
|
}
|
|
107
117
|
semanticConceptIds?: string[]
|
|
108
118
|
}[]
|
|
@@ -153,6 +163,14 @@ function toneForRoute(route: PressureInterventionType) {
|
|
|
153
163
|
return 'gray'
|
|
154
164
|
}
|
|
155
165
|
|
|
166
|
+
function toneForProofTier(tier: 'trusted' | 'caution' | 'bounded' | 'candidate' | undefined) {
|
|
167
|
+
if (tier === 'trusted') return 'green'
|
|
168
|
+
if (tier === 'caution') return 'yellow'
|
|
169
|
+
if (tier === 'bounded') return 'blue'
|
|
170
|
+
if (tier === 'candidate') return 'gray'
|
|
171
|
+
return 'gray'
|
|
172
|
+
}
|
|
173
|
+
|
|
156
174
|
function toneForMode(mode: Summary['governance']['activeMode']): 'blue' | 'green' | 'purple' | 'yellow' | 'neutral' {
|
|
157
175
|
if (mode === 'transfer-focused') return 'purple'
|
|
158
176
|
if (mode === 'project-critical') return 'yellow'
|
|
@@ -311,7 +329,7 @@ export default function CoEvolutionClient({ summary, ontology, proof }: Props) {
|
|
|
311
329
|
<MetricCard label="Prepared topology" value={summary.topologyExecution.prepared} sublabel={`${summary.topologyExecution.applied} applied • ${summary.topologyExecution.rolledBack} rolled back`} tone={summary.topologyExecution.prepared > 0 ? 'blue' : summary.topologyExecution.applied > 0 ? 'green' : 'neutral'} icon="↑" />
|
|
312
330
|
<MetricCard label="Active semantics" value={ontology.ontologyLoop.adoption.activeConcepts} sublabel={`${ontology.ontologyLoop.adoption.totalBindings} bindings • ${ontology.ontologyLoop.adoption.routesInfluenced} influenced routes`} tone={ontology.ontologyLoop.adoption.activeConcepts > 0 ? 'green' : 'neutral'} icon="◎" />
|
|
313
331
|
<MetricCard label="Recorded interventions" value={summary.pressureInterventions.total} sublabel={`${summary.pressureInterventions.completed} completed • ${summary.pressureInterventions.dryRun} dry-run`} tone="blue" icon="↺" />
|
|
314
|
-
<MetricCard label="Proof
|
|
332
|
+
<MetricCard label="Proof steering" value={proof.steering.priorityReview} sublabel={`${proof.steering.trustedLanes} trusted • ${proof.steering.cautionLanes} caution`} tone={proof.steering.cautionLanes > 0 ? 'yellow' : proof.steering.trustedLanes > 0 ? 'green' : proof.summary.reviewOpen > 0 ? 'blue' : 'neutral'} icon="◇" />
|
|
315
333
|
<MetricCard label="Realized transfers" value={summary.recentTransfers.filter((event) => event.status === 'realized').length} sublabel={`${summary.pressureMotifs.addressed} motifs now addressed`} tone="green" icon="↑" />
|
|
316
334
|
</div>
|
|
317
335
|
|
|
@@ -402,6 +420,7 @@ export default function CoEvolutionClient({ summary, ontology, proof }: Props) {
|
|
|
402
420
|
<span className={`badge badge-${toneForLifecycle(motif.lifecycle)}`}>{motif.lifecycle}</span>
|
|
403
421
|
<span className="badge badge-purple">recommend {motif.suggestedRoute.route}</span>
|
|
404
422
|
<span className="badge badge-gray">confidence {(motif.suggestedRoute.confidence * 100).toFixed(0)}%</span>
|
|
423
|
+
{motif.suggestedRoute.proofTier ? <span className={`badge badge-${toneForProofTier(motif.suggestedRoute.proofTier)}`}>proof {motif.suggestedRoute.proofTier}</span> : null}
|
|
405
424
|
{motif.suggestedRoute.semanticInfluence && motif.suggestedRoute.semanticInfluence !== 'none' ? <span className="badge badge-green">semantic {motif.suggestedRoute.semanticInfluence}</span> : null}
|
|
406
425
|
{(motif.semanticConceptIds ?? []).slice(0, 2).map((conceptId) => <span key={`${motif.id}-${conceptId}`} className="badge badge-gray">{conceptId}</span>)}
|
|
407
426
|
{motif.projectIds.slice(0, 3).map((projectId) => <span key={`${motif.id}-${projectId}`} className="badge badge-gray">{projectId}</span>)}
|
|
@@ -410,6 +429,7 @@ export default function CoEvolutionClient({ summary, ontology, proof }: Props) {
|
|
|
410
429
|
{motif.suggestedRoute.reasons.slice(0, 2).map((reason, index) => (
|
|
411
430
|
<div key={`${motif.id}-reason-${index}`} className="signal-text">• {reason}</div>
|
|
412
431
|
))}
|
|
432
|
+
{motif.suggestedRoute.proofSummary ? <div className="signal-text">→ {motif.suggestedRoute.proofSummary}</div> : null}
|
|
413
433
|
</div>
|
|
414
434
|
</div>
|
|
415
435
|
</div>
|
|
@@ -551,6 +571,7 @@ export default function CoEvolutionClient({ summary, ontology, proof }: Props) {
|
|
|
551
571
|
{signal.projectId ? <span className="badge badge-gray">{signal.projectId}</span> : null}
|
|
552
572
|
{signal.routeRecommendation ? <span className={`badge badge-${toneForRoute(signal.routeRecommendation.route)}`}>recommend {signal.routeRecommendation.route}</span> : null}
|
|
553
573
|
{signal.routeRecommendation ? <span className="badge badge-gray">{signal.routeRecommendation.scope}</span> : null}
|
|
574
|
+
{signal.routeRecommendation?.proofTier ? <span className={`badge badge-${toneForProofTier(signal.routeRecommendation.proofTier)}`}>proof {signal.routeRecommendation.proofTier}</span> : null}
|
|
554
575
|
{signal.routeRecommendation?.semanticInfluence && signal.routeRecommendation.semanticInfluence !== 'none' ? <span className="badge badge-green">semantic {signal.routeRecommendation.semanticInfluence}</span> : null}
|
|
555
576
|
{(signal.semanticConceptIds ?? []).slice(0, 2).map((conceptId) => <span key={`${signal.id}-${conceptId}`} className="badge badge-gray">{conceptId}</span>)}
|
|
556
577
|
{signal.interventionTypes.map((type) => <span key={`${signal.id}-${type}`} className="badge badge-gray">{type}</span>)}
|
|
@@ -560,6 +581,7 @@ export default function CoEvolutionClient({ summary, ontology, proof }: Props) {
|
|
|
560
581
|
{signal.routeRecommendation.reasons.slice(0, 2).map((reason, index) => (
|
|
561
582
|
<div key={`${signal.id}-reason-${index}`} className="signal-text">• {reason}</div>
|
|
562
583
|
))}
|
|
584
|
+
{signal.routeRecommendation.proofSummary ? <div className="signal-text">→ {signal.routeRecommendation.proofSummary}</div> : null}
|
|
563
585
|
</div>
|
|
564
586
|
) : null}
|
|
565
587
|
</div>
|
package/dashboard/app/page.tsx
CHANGED
|
@@ -6,8 +6,6 @@ import { PageHero } from '@/components/page-hero'
|
|
|
6
6
|
import { MetricCard } from '@/components/metric-card'
|
|
7
7
|
import { SectionFrame } from '@/components/section-frame'
|
|
8
8
|
import { OperatorLoopTrail } from '@/components/operator-loop-trail'
|
|
9
|
-
import { SurfaceJumpLinks } from '@/components/surface-jump-links'
|
|
10
|
-
import { CURRENT_RELEASE_SPOTLIGHT } from '@/lib/release-spotlight'
|
|
11
9
|
|
|
12
10
|
export const dynamic = 'force-dynamic'
|
|
13
11
|
|
|
@@ -33,6 +31,7 @@ function providerTone(status: 'healthy' | 'degraded' | 'unavailable' | 'unknown'
|
|
|
33
31
|
function getPriorityActions(params: {
|
|
34
32
|
unresolved: number
|
|
35
33
|
proofOpen: number
|
|
34
|
+
proofCaution: number
|
|
36
35
|
topologyOpen: number
|
|
37
36
|
optimizeStatus: 'idle' | 'healthy' | 'partial' | 'failed'
|
|
38
37
|
optimizeNextStep?: string
|
|
@@ -60,6 +59,15 @@ function getPriorityActions(params: {
|
|
|
60
59
|
})
|
|
61
60
|
}
|
|
62
61
|
|
|
62
|
+
if (params.proofCaution > 0) {
|
|
63
|
+
actions.push({
|
|
64
|
+
href: '/proof',
|
|
65
|
+
title: 'Inspect cautionary proof steering',
|
|
66
|
+
description: `${params.proofCaution} proof lane${params.proofCaution === 1 ? '' : 's'} currently reduce trust or increase review bias for the next control step.`,
|
|
67
|
+
tone: 'yellow',
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
63
71
|
if (params.proofOpen > 0) {
|
|
64
72
|
actions.push({
|
|
65
73
|
href: '/proof',
|
|
@@ -114,9 +122,29 @@ export default function Overview() {
|
|
|
114
122
|
const recentRuns = history.iterations.slice(-4).reverse()
|
|
115
123
|
const topSkills = [...graph.nodes].sort((a, b) => b.score - a.score).slice(0, 10)
|
|
116
124
|
const defaultProvider = llmRuntime.providers[llmRuntime.defaultProvider]
|
|
125
|
+
const lastExecutionUsedFallback = Boolean(llmRuntime.lastExecution?.fallbackUsed)
|
|
126
|
+
const isProviderDegraded =
|
|
127
|
+
defaultProvider.status === 'degraded' ||
|
|
128
|
+
defaultProvider.status === 'unavailable'
|
|
129
|
+
const showProviderAttention = isProviderDegraded || lastExecutionUsedFallback
|
|
130
|
+
const providerAttentionTone = defaultProvider.status === 'unavailable' ? 'red' : 'yellow'
|
|
131
|
+
const providerAttentionEyebrow = isProviderDegraded ? 'Provider attention' : 'Recent provider deviation'
|
|
132
|
+
const providerAttentionTitle = defaultProvider.status === 'unavailable'
|
|
133
|
+
? 'Backend recovery needed'
|
|
134
|
+
: isProviderDegraded
|
|
135
|
+
? 'Live backend truth'
|
|
136
|
+
: 'Fallback used recently'
|
|
137
|
+
const providerAttentionDescription = isProviderDegraded
|
|
138
|
+
? lastExecutionUsedFallback
|
|
139
|
+
? 'The default provider currently needs attention and a recent provider-backed run used explicit fallback. Review runtime health before treating execution as fully healthy or default-aligned.'
|
|
140
|
+
: 'The default provider currently needs attention. Review runtime health before treating provider-backed execution as fully healthy.'
|
|
141
|
+
: llmRuntime.lastExecution?.usedProvider
|
|
142
|
+
? `A recent provider-backed run did not stay on the selected default provider. The default remained ${providerLabel(llmRuntime.defaultProvider)}, but the last successful execution used ${providerLabel(llmRuntime.lastExecution.usedProvider)}. Review provider health and fallback policy before assuming default-provider execution.`
|
|
143
|
+
: 'A recent provider-backed run used explicit fallback instead of staying on the selected default provider. Review provider health and fallback policy before assuming default-provider execution.'
|
|
117
144
|
const priorityActions = getPriorityActions({
|
|
118
145
|
unresolved: summary.failures.unresolved,
|
|
119
146
|
proofOpen: proof.summary.reviewOpen,
|
|
147
|
+
proofCaution: proof.steering.cautionLanes,
|
|
120
148
|
topologyOpen: topologyControl.summary.open,
|
|
121
149
|
optimizeStatus: topologyControl.optimizeStatus.status,
|
|
122
150
|
optimizeNextStep: topologyControl.optimizeStatus.nextStep,
|
|
@@ -133,14 +161,9 @@ export default function Overview() {
|
|
|
133
161
|
title="Dashboard"
|
|
134
162
|
description="Monitor the live state of your self-evolving skill ecosystem, launch high-value actions, and trace how failures turn into frontier-worthy improvements."
|
|
135
163
|
chips={[
|
|
136
|
-
{ label: `${summary.skills.total} skills`, tone: 'purple' },
|
|
137
164
|
{ label: `${summary.failures.unresolved} unresolved corrections`, tone: summary.failures.unresolved > 0 ? 'yellow' : 'green' },
|
|
138
|
-
{ label: `${summary.evolution.runs} evolution runs`, tone: 'blue' },
|
|
139
|
-
{ label: `${frontier.programs.length}/${frontier.capacity} frontier slots`, tone: 'green' },
|
|
140
|
-
{ label: `${coevolution.pressureMotifs.promotionReady} promotion-ready motifs`, tone: coevolution.pressureMotifs.promotionReady > 0 ? 'purple' : 'neutral' },
|
|
141
|
-
{ label: `${coevolution.topologyReviews.open} topology reviews`, tone: coevolution.topologyReviews.open > 0 ? 'yellow' : 'green' },
|
|
142
|
-
{ label: `${coevolution.topologyExecution.prepared} prepared structural plans`, tone: coevolution.topologyExecution.prepared > 0 ? 'blue' : 'neutral' },
|
|
143
165
|
{ label: `${proof.summary.reviewOpen} proof reviews`, tone: proof.summary.reviewOpen > 0 ? 'yellow' : proof.summary.effective > 0 ? 'green' : 'neutral' },
|
|
166
|
+
{ label: `${coevolution.topologyReviews.open} topology reviews`, tone: coevolution.topologyReviews.open > 0 ? 'yellow' : 'green' },
|
|
144
167
|
{ label: `${providerLabel(llmRuntime.defaultProvider)} ${defaultProvider.status}`, tone: providerTone(defaultProvider.status) },
|
|
145
168
|
{ label: `mode: ${coevolution.governance.activeMode.replace(/-/g, ' ')}`, tone: coevolution.governance.activeMode === 'transfer-focused' ? 'purple' : coevolution.governance.activeMode === 'project-critical' ? 'yellow' : 'blue' },
|
|
146
169
|
]}
|
|
@@ -162,38 +185,98 @@ export default function Overview() {
|
|
|
162
185
|
|
|
163
186
|
<OperatorLoopTrail surface="overview" />
|
|
164
187
|
|
|
165
|
-
<div
|
|
166
|
-
<MetricCard label="Total skills" value={summary.skills.total} sublabel={`${summary.skills.evolved} evolved • ${summary.skillTests} skill tests`} tone="purple" href="/network" icon="◆" />
|
|
167
|
-
<MetricCard label="Accepted proposals" value={summary.evolution.accepted} sublabel={`${summary.evolution.rejected} rejected`} tone="green" href="/evolution" icon="✓" />
|
|
188
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
168
189
|
<MetricCard label="Unresolved corrections" value={summary.failures.unresolved} sublabel={`out of ${summary.failures.total} captured failures`} tone={summary.failures.unresolved > 0 ? 'yellow' : 'green'} href={summary.failures.unresolved > 0 ? '#attention' : '/evolution'} icon="!" />
|
|
169
|
-
<MetricCard label="
|
|
170
|
-
<MetricCard
|
|
171
|
-
|
|
190
|
+
<MetricCard label="Proof review" value={proof.summary.reviewOpen} sublabel={`${proof.steering.trustedLanes} trusted lanes • ${proof.steering.cautionLanes} caution`} tone={proof.summary.reviewOpen > 0 ? 'yellow' : proof.steering.trustedLanes > 0 ? 'green' : proof.steering.cautionLanes > 0 ? 'yellow' : 'neutral'} href="/proof" icon="◇" />
|
|
191
|
+
<MetricCard
|
|
192
|
+
label="Open pressure"
|
|
193
|
+
value={ontology.pressureLifecycle.open}
|
|
194
|
+
sublabel={`${ontology.pressureLifecycle.inProgress} in progress • ${ontology.pressureLifecycle.addressed} addressed`}
|
|
195
|
+
tone={ontology.pressureLifecycle.open > 0 ? 'yellow' : 'green'}
|
|
196
|
+
href="/coevolution"
|
|
197
|
+
icon="!"
|
|
198
|
+
/>
|
|
199
|
+
<MetricCard
|
|
200
|
+
label="Topology review"
|
|
201
|
+
value={ontology.topologyReviews.open}
|
|
202
|
+
sublabel={`${ontology.topologyExecution.prepared} prepared • ${ontology.topologyExecution.applied} applied`}
|
|
203
|
+
tone={ontology.topologyReviews.open > 0 ? 'yellow' : ontology.topologyExecution.applied > 0 ? 'green' : 'blue'}
|
|
204
|
+
href="/topology"
|
|
205
|
+
icon="⇄"
|
|
206
|
+
/>
|
|
207
|
+
<MetricCard
|
|
208
|
+
label="Ontology frontier"
|
|
209
|
+
value={ontology.ontologyLoop.frontier}
|
|
210
|
+
sublabel={`${ontology.ontologyLoop.reviewOpen} open • ${ontology.ontologyLoop.extensions} approved extensions`}
|
|
211
|
+
tone={ontology.ontologyLoop.reviewOpen > 0 ? 'yellow' : ontology.ontologyLoop.extensions > 0 ? 'blue' : 'neutral'}
|
|
212
|
+
href="/ontology"
|
|
213
|
+
icon="◎"
|
|
214
|
+
/>
|
|
215
|
+
<MetricCard
|
|
216
|
+
label="Active semantic concepts"
|
|
217
|
+
value={ontology.ontologyLoop.adoption.activeConcepts}
|
|
218
|
+
sublabel={`${ontology.ontologyLoop.adoption.totalBindings} bindings • ${ontology.ontologyLoop.adoption.routesInfluenced} influenced routes`}
|
|
219
|
+
tone={ontology.ontologyLoop.adoption.activeConcepts > 0 ? 'green' : 'neutral'}
|
|
220
|
+
href="/ontology"
|
|
221
|
+
icon="⇄"
|
|
222
|
+
/>
|
|
172
223
|
</div>
|
|
173
224
|
|
|
174
225
|
<SectionFrame
|
|
175
|
-
eyebrow=
|
|
176
|
-
title=
|
|
177
|
-
description=
|
|
226
|
+
eyebrow="Priority now"
|
|
227
|
+
title="Top ranked next actions"
|
|
228
|
+
description="This layer compresses the live loop into the most important operator moves right now instead of leaving everything as flat dashboard signal."
|
|
178
229
|
tone="blue"
|
|
179
230
|
>
|
|
180
|
-
<div className="
|
|
181
|
-
|
|
182
|
-
{
|
|
183
|
-
<div
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
))}
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
<SurfaceJumpLinks surface="overview" variant="panel" title="Jump into the updated loop" />
|
|
231
|
+
<div className="summary-list">
|
|
232
|
+
{priorityActions.map((action, index) => (
|
|
233
|
+
<Link key={`${action.href}-${index}`} href={action.href} className="summary-row">
|
|
234
|
+
<div className="summary-row-main">
|
|
235
|
+
<div className="summary-row-title">{index + 1}. {action.title}</div>
|
|
236
|
+
<div className="summary-row-meta">{action.description}</div>
|
|
237
|
+
</div>
|
|
238
|
+
<span className={`hero-chip hero-chip-${action.tone}`}>open</span>
|
|
239
|
+
</Link>
|
|
240
|
+
))}
|
|
194
241
|
</div>
|
|
195
242
|
</SectionFrame>
|
|
196
243
|
|
|
244
|
+
{unresolved.length > 0 ? (
|
|
245
|
+
<SectionFrame
|
|
246
|
+
eyebrow="Attention"
|
|
247
|
+
title="Unresolved corrections"
|
|
248
|
+
description="These user corrections have been captured but not yet folded back into the skill network."
|
|
249
|
+
tone="yellow"
|
|
250
|
+
className="anchor-target"
|
|
251
|
+
>
|
|
252
|
+
<div id="attention" className="signal-list">
|
|
253
|
+
{unresolved.slice(0, 5).map((failure, index) => (
|
|
254
|
+
<div key={`${failure.id}-${index}`} className="signal-row signal-row-attention">
|
|
255
|
+
<div className="signal-dot" />
|
|
256
|
+
<div style={{ flex: 1 }}>
|
|
257
|
+
<div className="signal-title">
|
|
258
|
+
{failure.userRequest.slice(0, 120)}
|
|
259
|
+
{failure.userRequest.length > 120 ? '…' : ''}
|
|
260
|
+
</div>
|
|
261
|
+
<div className="signal-text">
|
|
262
|
+
Correction: {failure.correction.slice(0, 180)}
|
|
263
|
+
{failure.correction.length > 180 ? '…' : ''}
|
|
264
|
+
</div>
|
|
265
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>
|
|
266
|
+
<span className="badge badge-yellow">{failure.correctionType}</span>
|
|
267
|
+
{failure.project ? <span className="badge badge-gray">{failure.project}</span> : null}
|
|
268
|
+
<span className="badge badge-gray">{new Date(failure.timestamp).toLocaleDateString()}</span>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
272
|
+
))}
|
|
273
|
+
{unresolved.length > 5 ? (
|
|
274
|
+
<div className="signal-text" style={{ textAlign: 'center' }}>+{unresolved.length - 5} more unresolved corrections</div>
|
|
275
|
+
) : null}
|
|
276
|
+
</div>
|
|
277
|
+
</SectionFrame>
|
|
278
|
+
) : null}
|
|
279
|
+
|
|
197
280
|
<SectionFrame
|
|
198
281
|
eyebrow="Execution layer"
|
|
199
282
|
title="Quick actions"
|
|
@@ -209,100 +292,88 @@ export default function Overview() {
|
|
|
209
292
|
/>
|
|
210
293
|
</SectionFrame>
|
|
211
294
|
|
|
295
|
+
{showProviderAttention ? (
|
|
296
|
+
<SectionFrame
|
|
297
|
+
eyebrow={providerAttentionEyebrow}
|
|
298
|
+
title={providerAttentionTitle}
|
|
299
|
+
description={providerAttentionDescription}
|
|
300
|
+
tone={providerAttentionTone}
|
|
301
|
+
actions={<Link href="/commands" className="badge badge-gray">Open commands</Link>}
|
|
302
|
+
>
|
|
303
|
+
<div className="grid-2" style={{ gap: 16 }}>
|
|
304
|
+
<div className="summary-list">
|
|
305
|
+
{(['claude-code', 'codex', 'ollama'] as const).map((provider) => {
|
|
306
|
+
const snapshot = llmRuntime.providers[provider]
|
|
307
|
+
return (
|
|
308
|
+
<div key={provider} className="summary-row">
|
|
309
|
+
<div className="summary-row-main">
|
|
310
|
+
<div className="summary-row-title">{providerLabel(provider)}</div>
|
|
311
|
+
<div className="summary-row-meta">{snapshot.summary}</div>
|
|
312
|
+
{snapshot.nextStep ? <div className="summary-row-meta" style={{ marginTop: 6 }}>Next: {snapshot.nextStep}</div> : null}
|
|
313
|
+
</div>
|
|
314
|
+
<span className={`hero-chip hero-chip-${providerTone(snapshot.status)}`}>{snapshot.status}</span>
|
|
315
|
+
</div>
|
|
316
|
+
)
|
|
317
|
+
})}
|
|
318
|
+
</div>
|
|
319
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
320
|
+
<MetricCard
|
|
321
|
+
label="Default provider"
|
|
322
|
+
value={providerLabel(llmRuntime.defaultProvider)}
|
|
323
|
+
sublabel={`fallback: ${llmRuntime.fallbackPolicy}${llmRuntime.fallbackOrder.length > 0 ? ` • ${llmRuntime.fallbackOrder.map((provider) => providerLabel(provider)).join(' → ')}` : ''}`}
|
|
324
|
+
tone={providerTone(defaultProvider.status)}
|
|
325
|
+
href="/commands"
|
|
326
|
+
icon="☍"
|
|
327
|
+
/>
|
|
328
|
+
<MetricCard
|
|
329
|
+
label="Last provider run"
|
|
330
|
+
value={llmRuntime.lastExecution?.usedProvider ? providerLabel(llmRuntime.lastExecution.usedProvider) : 'None'}
|
|
331
|
+
sublabel={llmRuntime.lastExecution ? llmRuntime.lastExecution.summary : 'No provider-backed execution has been recorded yet.'}
|
|
332
|
+
tone={llmRuntime.lastExecution?.success ? 'green' : llmRuntime.lastExecution ? 'yellow' : 'neutral'}
|
|
333
|
+
href="/commands"
|
|
334
|
+
icon="↺"
|
|
335
|
+
/>
|
|
336
|
+
<div className="signal-text">Commands, status, and dashboard surfaces now track whether execution stayed on the selected provider, degraded, or used an explicit fallback path.</div>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
</SectionFrame>
|
|
340
|
+
) : null}
|
|
341
|
+
|
|
212
342
|
<SectionFrame
|
|
213
|
-
eyebrow="
|
|
214
|
-
title="
|
|
215
|
-
description="
|
|
343
|
+
eyebrow="Proof steering"
|
|
344
|
+
title="What proved outcomes are changing now"
|
|
345
|
+
description="Proof now separates trusted, cautionary, bounded, and candidate evidence so the next governed loop can steer more honestly instead of treating every proof record as equally strong."
|
|
216
346
|
tone="blue"
|
|
347
|
+
actions={<Link href="/proof" className="badge badge-gray">Open proof control</Link>}
|
|
217
348
|
>
|
|
218
349
|
<div className="grid-2" style={{ gap: 16 }}>
|
|
219
350
|
<div className="summary-list">
|
|
220
|
-
{(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
<div className="summary-row-
|
|
225
|
-
<div className="summary-row-title">{providerLabel(provider)}</div>
|
|
226
|
-
<div className="summary-row-meta">{snapshot.summary}</div>
|
|
227
|
-
{snapshot.nextStep ? <div className="summary-row-meta" style={{ marginTop: 6 }}>Next: {snapshot.nextStep}</div> : null}
|
|
228
|
-
</div>
|
|
229
|
-
<span className={`hero-chip hero-chip-${providerTone(snapshot.status)}`}>{snapshot.status}</span>
|
|
351
|
+
{proof.steering.routeLanes.slice(0, 3).map((lane) => (
|
|
352
|
+
<div key={lane.laneKey} className="summary-row">
|
|
353
|
+
<div className="summary-row-main">
|
|
354
|
+
<div className="summary-row-title">{lane.route ? lane.route.replace(/-/g, ' ') : lane.conceptId ?? lane.laneKey}</div>
|
|
355
|
+
<div className="summary-row-meta">{lane.summary}</div>
|
|
230
356
|
</div>
|
|
231
|
-
|
|
232
|
-
|
|
357
|
+
<span className={`hero-chip hero-chip-${lane.evidenceTier === 'trusted' ? 'green' : lane.evidenceTier === 'caution' ? 'yellow' : lane.evidenceTier === 'bounded' ? 'blue' : 'neutral'}`}>{lane.evidenceTier}</span>
|
|
358
|
+
</div>
|
|
359
|
+
))}
|
|
360
|
+
{proof.steering.routeLanes.length === 0 ? <div className="signal-text">No route-level proof steering yet.</div> : null}
|
|
233
361
|
</div>
|
|
234
362
|
<div style={{ display: 'grid', gap: 12 }}>
|
|
235
|
-
<MetricCard
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
sublabel={`fallback: ${llmRuntime.fallbackPolicy}${llmRuntime.fallbackOrder.length > 0 ? ` • ${llmRuntime.fallbackOrder.map((provider) => providerLabel(provider)).join(' → ')}` : ''}`}
|
|
239
|
-
tone={providerTone(defaultProvider.status)}
|
|
240
|
-
href="/commands"
|
|
241
|
-
icon="☍"
|
|
242
|
-
/>
|
|
243
|
-
<MetricCard
|
|
244
|
-
label="Last provider run"
|
|
245
|
-
value={llmRuntime.lastExecution?.usedProvider ? providerLabel(llmRuntime.lastExecution.usedProvider) : 'None'}
|
|
246
|
-
sublabel={llmRuntime.lastExecution ? llmRuntime.lastExecution.summary : 'No provider-backed execution has been recorded yet.'}
|
|
247
|
-
tone={llmRuntime.lastExecution?.success ? 'green' : llmRuntime.lastExecution ? 'yellow' : 'neutral'}
|
|
248
|
-
href="/commands"
|
|
249
|
-
icon="↺"
|
|
250
|
-
/>
|
|
251
|
-
<div className="signal-text">Commands, status, and dashboard surfaces now track whether execution stayed on the selected provider, degraded, or used an explicit fallback path.</div>
|
|
363
|
+
<MetricCard label="Trusted lanes" value={proof.steering.trustedLanes} sublabel={`${proof.summary.verified} verified records reinforce future trust`} tone={proof.steering.trustedLanes > 0 ? 'green' : 'neutral'} href="/proof" icon="✓" />
|
|
364
|
+
<MetricCard label="Caution lanes" value={proof.steering.cautionLanes} sublabel={`${proof.summary.regressed} regressed • ${proof.summary.contested} contested`} tone={proof.steering.cautionLanes > 0 ? 'yellow' : 'neutral'} href="/proof" icon="!" />
|
|
365
|
+
<div className="signal-text">Candidate evidence stays visible in Proof, but no longer dominates the highest-value steering surface.</div>
|
|
252
366
|
</div>
|
|
253
367
|
</div>
|
|
254
368
|
</SectionFrame>
|
|
255
369
|
|
|
256
370
|
<SectionFrame
|
|
257
|
-
eyebrow="
|
|
258
|
-
title="Top ranked next actions"
|
|
259
|
-
description="This layer compresses the live loop into the most important operator moves right now instead of leaving everything as flat dashboard signal."
|
|
260
|
-
tone="blue"
|
|
261
|
-
>
|
|
262
|
-
<div className="summary-list">
|
|
263
|
-
{priorityActions.map((action, index) => (
|
|
264
|
-
<Link key={`${action.href}-${index}`} href={action.href} className="summary-row">
|
|
265
|
-
<div className="summary-row-main">
|
|
266
|
-
<div className="summary-row-title">{index + 1}. {action.title}</div>
|
|
267
|
-
<div className="summary-row-meta">{action.description}</div>
|
|
268
|
-
</div>
|
|
269
|
-
<span className={`hero-chip hero-chip-${action.tone}`}>open</span>
|
|
270
|
-
</Link>
|
|
271
|
-
))}
|
|
272
|
-
</div>
|
|
273
|
-
</SectionFrame>
|
|
274
|
-
|
|
275
|
-
<SectionFrame
|
|
276
|
-
eyebrow="Brain foundation"
|
|
371
|
+
eyebrow="Brain summary"
|
|
277
372
|
title="Semantic backbone"
|
|
278
|
-
description="
|
|
373
|
+
description="Compact summary of pressure, response, structural review, ontology growth, and semantic adoption across the living brain."
|
|
279
374
|
actions={<span className="badge badge-gray">{ontology.source === 'hybrid-native-derived' ? `Ontology ${ontology.specVersion} · hybrid native + derived` : ontology.source === 'graph' ? `Ontology ${ontology.specVersion}` : 'Compatibility-derived'}</span>}
|
|
280
375
|
>
|
|
281
376
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
282
|
-
<MetricCard
|
|
283
|
-
label="Generalist skills"
|
|
284
|
-
value={ontology.skillRoles.generalist}
|
|
285
|
-
sublabel={`${ontology.stabilityStates.stable} stable abstractions`}
|
|
286
|
-
tone="purple"
|
|
287
|
-
href="/network"
|
|
288
|
-
icon="◎"
|
|
289
|
-
/>
|
|
290
|
-
<MetricCard
|
|
291
|
-
label="Project specialists"
|
|
292
|
-
value={ontology.skillRoles.specialist}
|
|
293
|
-
sublabel={`${ontology.plasticityStates.candidate} candidate rewires`}
|
|
294
|
-
tone="blue"
|
|
295
|
-
href="/projects"
|
|
296
|
-
icon="◉"
|
|
297
|
-
/>
|
|
298
|
-
<MetricCard
|
|
299
|
-
label="Hybrid bridges"
|
|
300
|
-
value={ontology.skillRoles.hybrid}
|
|
301
|
-
sublabel={`${ontology.plasticityStates.volatile} volatile transitions`}
|
|
302
|
-
tone="green"
|
|
303
|
-
href="/network"
|
|
304
|
-
icon="⇄"
|
|
305
|
-
/>
|
|
306
377
|
<MetricCard
|
|
307
378
|
label="Open pressure"
|
|
308
379
|
value={ontology.pressureLifecycle.open}
|
|
@@ -319,14 +390,6 @@ export default function Overview() {
|
|
|
319
390
|
href="/coevolution"
|
|
320
391
|
icon="↺"
|
|
321
392
|
/>
|
|
322
|
-
<MetricCard
|
|
323
|
-
label="Pressure motifs"
|
|
324
|
-
value={ontology.pressureMotifs.total}
|
|
325
|
-
sublabel={`${ontology.pressureMotifs.promotionReady} promotion-ready • ${ontology.transferEvents.realized} realized transfers`}
|
|
326
|
-
tone="purple"
|
|
327
|
-
href="/coevolution"
|
|
328
|
-
icon="⇄"
|
|
329
|
-
/>
|
|
330
393
|
<MetricCard
|
|
331
394
|
label="Topology review"
|
|
332
395
|
value={ontology.topologyReviews.open}
|
|
@@ -351,81 +414,16 @@ export default function Overview() {
|
|
|
351
414
|
href="/ontology"
|
|
352
415
|
icon="⇄"
|
|
353
416
|
/>
|
|
354
|
-
<MetricCard
|
|
355
|
-
label="Observed mutation verbs"
|
|
356
|
-
value={ontology.mutationOperationsObserved}
|
|
357
|
-
sublabel={ontology.observedMutationActions.length > 0 ? ontology.observedMutationActions.join(' • ') : 'Waiting for evolution history'}
|
|
358
|
-
tone="yellow"
|
|
359
|
-
href="/evolution"
|
|
360
|
-
icon="◇"
|
|
361
|
-
/>
|
|
362
417
|
</div>
|
|
363
418
|
|
|
364
419
|
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 16 }}>
|
|
365
|
-
<span className="badge badge-gray">{ontology.relationFamiliesObserved} relation families live in the graph</span>
|
|
366
|
-
<span className="badge badge-gray">{ontology.evidenceBackedProposals} proposals already carry judge + regression evidence</span>
|
|
367
|
-
<span className="badge badge-gray">{ontology.artifacts.total} evolution artifacts ({ontology.artifacts.native} native • {ontology.artifacts.derived} derived)</span>
|
|
368
|
-
<span className="badge badge-gray">{ontology.activationTraces.total} activation traces ({ontology.activationTraces.native} native • {ontology.activationTraces.derived} derived)</span>
|
|
369
|
-
<span className="badge badge-gray">{ontology.pressureSignals.total} pressure signals ({ontology.pressureSignals.native} native • {ontology.pressureSignals.derived} derived)</span>
|
|
370
|
-
<span className="badge badge-gray">{ontology.pressureInterventions.total} response interventions logged</span>
|
|
371
|
-
<span className="badge badge-gray">{ontology.pressureLifecycle.open} open • {ontology.pressureLifecycle.inProgress} in progress • {ontology.pressureLifecycle.addressed} addressed</span>
|
|
372
420
|
<Link href="/coevolution" className="badge badge-blue" style={{ textDecoration: 'none' }}>Open co-evolution control</Link>
|
|
373
|
-
<span className="badge badge-gray">{coevolution.topProjects.length} pressured project hotspots</span>
|
|
374
|
-
<span className="badge badge-gray">{coevolution.crossProjectGapAreas.length} cross-project gap motifs</span>
|
|
375
|
-
<span className="badge badge-gray">{ontology.pressureMotifs.promotionReady} motifs currently recommend generalize</span>
|
|
376
|
-
<span className="badge badge-gray">{ontology.transferEvents.total} transfer events logged ({ontology.transferEvents.realized} realized)</span>
|
|
377
|
-
<span className="badge badge-gray">ontology → {ontology.ontologyLoop.frontier} frontier • {ontology.ontologyLoop.extensions} extensions • {ontology.ontologyLoop.changeEvents} changes</span>
|
|
378
|
-
<span className="badge badge-gray">semantic adoption → {ontology.ontologyLoop.adoption.activeConcepts} active concepts • {ontology.ontologyLoop.adoption.totalBindings} bindings • {ontology.ontologyLoop.adoption.routesInfluenced} influenced routes</span>
|
|
379
|
-
<span className="badge badge-gray">deprecation risk → {ontology.ontologyLoop.adoption.conceptsAtDeprecationRisk} concepts • {ontology.ontologyLoop.adoption.unusedExtensions} unused extensions</span>
|
|
380
|
-
<span className="badge badge-gray">topology → {ontology.topologyReviews.open} open • {ontology.topologyReviews.accepted} accepted • {ontology.topologyReviews.generatedFromManualReview} manual-route</span>
|
|
381
|
-
<span className="badge badge-gray">execution → {ontology.topologyExecution.prepared} prepared • {ontology.topologyExecution.applied} applied • {ontology.topologyExecution.rolledBack} rolled back</span>
|
|
382
|
-
<span className="badge badge-gray">proof → {proof.summary.total} total • {proof.summary.effective} effective • {proof.summary.reviewOpen} open review</span>
|
|
383
421
|
<Link href="/ontology" className="badge badge-blue" style={{ textDecoration: 'none' }}>Open ontology control</Link>
|
|
384
422
|
<Link href="/topology" className="badge badge-blue" style={{ textDecoration: 'none' }}>Open topology control</Link>
|
|
385
423
|
<Link href="/proof" className="badge badge-blue" style={{ textDecoration: 'none' }}>Open proof control</Link>
|
|
386
|
-
<span className="badge badge-gray">governance: {ontology.governance.activeMode.replace(/-/g, ' ')} ({ontology.governance.source})</span>
|
|
387
|
-
<span className="badge badge-gray">routes → research {ontology.governedRoutes.research} • specialize {ontology.governedRoutes.specialize} • evolve {ontology.governedRoutes.evolve} • generalize {ontology.governedRoutes.generalize} • manual-review {ontology.governedRoutes['manual-review']}</span>
|
|
388
|
-
<span className="badge badge-gray">{ontology.enrichedSkillNodes} skills carry explicit brain metadata</span>
|
|
389
|
-
<span className="badge badge-gray">{ontology.annotatedFailures.pressureSignals} failures annotated with pressure signals</span>
|
|
390
424
|
</div>
|
|
391
425
|
</SectionFrame>
|
|
392
426
|
|
|
393
|
-
{unresolved.length > 0 ? (
|
|
394
|
-
<SectionFrame
|
|
395
|
-
eyebrow="Attention"
|
|
396
|
-
title="Unresolved corrections"
|
|
397
|
-
description="These user corrections have been captured but not yet folded back into the skill network."
|
|
398
|
-
tone="yellow"
|
|
399
|
-
className="anchor-target"
|
|
400
|
-
>
|
|
401
|
-
<div id="attention" className="signal-list">
|
|
402
|
-
{unresolved.slice(0, 5).map((failure, index) => (
|
|
403
|
-
<div key={`${failure.id}-${index}`} className="signal-row signal-row-attention">
|
|
404
|
-
<div className="signal-dot" />
|
|
405
|
-
<div style={{ flex: 1 }}>
|
|
406
|
-
<div className="signal-title">
|
|
407
|
-
{failure.userRequest.slice(0, 120)}
|
|
408
|
-
{failure.userRequest.length > 120 ? '…' : ''}
|
|
409
|
-
</div>
|
|
410
|
-
<div className="signal-text">
|
|
411
|
-
Correction: {failure.correction.slice(0, 180)}
|
|
412
|
-
{failure.correction.length > 180 ? '…' : ''}
|
|
413
|
-
</div>
|
|
414
|
-
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>
|
|
415
|
-
<span className="badge badge-yellow">{failure.correctionType}</span>
|
|
416
|
-
{failure.project ? <span className="badge badge-gray">{failure.project}</span> : null}
|
|
417
|
-
<span className="badge badge-gray">{new Date(failure.timestamp).toLocaleDateString()}</span>
|
|
418
|
-
</div>
|
|
419
|
-
</div>
|
|
420
|
-
</div>
|
|
421
|
-
))}
|
|
422
|
-
{unresolved.length > 5 ? (
|
|
423
|
-
<div className="signal-text" style={{ textAlign: 'center' }}>+{unresolved.length - 5} more unresolved corrections</div>
|
|
424
|
-
) : null}
|
|
425
|
-
</div>
|
|
426
|
-
</SectionFrame>
|
|
427
|
-
) : null}
|
|
428
|
-
|
|
429
427
|
<div className="grid-2">
|
|
430
428
|
<SectionFrame
|
|
431
429
|
eyebrow="Frontier"
|