helixevo 0.2.41 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +19 -6
- package/dashboard/app/commands/page.tsx +17 -0
- package/dashboard/app/evolution/page.tsx +58 -37
- package/dashboard/app/guide/page.tsx +35 -1
- package/dashboard/app/network/client.tsx +125 -1
- package/dashboard/app/network/page.tsx +3 -1
- package/dashboard/app/page.tsx +57 -1
- package/dashboard/app/projects/client.tsx +21 -2
- package/dashboard/app/projects/page.tsx +29 -2
- package/dashboard/app/research/client.tsx +67 -1
- package/dashboard/app/research/page.tsx +3 -2
- package/dashboard/lib/data.ts +443 -1
- package/dist/cli.js +532 -109
- package/package.json +2 -2
package/dashboard/lib/data.ts
CHANGED
|
@@ -18,10 +18,16 @@ function readJsonl<T>(filename: string): T[] {
|
|
|
18
18
|
|
|
19
19
|
// ─── Types ──────────────────────────────────────────────────────
|
|
20
20
|
|
|
21
|
+
export type CognitiveRole = 'generalist' | 'specialist' | 'hybrid'
|
|
22
|
+
export type StabilityState = 'stable' | 'adaptive' | 'experimental'
|
|
23
|
+
export type PlasticityState = 'consolidated' | 'volatile' | 'candidate'
|
|
24
|
+
|
|
21
25
|
export interface SkillNode {
|
|
22
26
|
id: string; name: string; layer: string; score: number
|
|
23
27
|
generation: number; status: string; tags: string[]
|
|
24
28
|
failureCount: number; lastEvolved: string; project?: string
|
|
29
|
+
cognitiveRole?: CognitiveRole; stabilityState?: StabilityState; plasticityState?: PlasticityState
|
|
30
|
+
capabilities?: string[]; lineageId?: string
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
export interface SkillEdge {
|
|
@@ -31,7 +37,7 @@ export interface SkillEdge {
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
export interface SkillGraph {
|
|
34
|
-
updated: string; nodes: SkillNode[]; edges: SkillEdge[]
|
|
40
|
+
updated: string; ontologyVersion?: string; nodes: SkillNode[]; edges: SkillEdge[]
|
|
35
41
|
clusters: { id: string; name: string; skills: string[]; cohesion: number }[]
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -39,6 +45,7 @@ export interface Failure {
|
|
|
39
45
|
id: string; sessionId: string; timestamp: string; project: string | null
|
|
40
46
|
userRequest: string; agentAction: string; correction: string
|
|
41
47
|
correctionType: string; skillsActive: string[]; resolved?: boolean
|
|
48
|
+
pressureSignals?: string[]; capabilityGaps?: string[]; activationTraceId?: string
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
export interface Frontier {
|
|
@@ -71,6 +78,159 @@ export interface CanaryEntry {
|
|
|
71
78
|
skillSlug: string; version: string; deployedAt: string; expiresAt: string
|
|
72
79
|
}
|
|
73
80
|
|
|
81
|
+
export type ArtifactProvenance = 'native-evolution' | 'derived-history'
|
|
82
|
+
export type ActivationProvenance = 'capture-derived' | 'project-analysis' | 'derived-failure'
|
|
83
|
+
export type PressureProvenance = 'failure-native' | 'project-analysis-native' | 'failure-derived' | 'profile-gap-derived'
|
|
84
|
+
|
|
85
|
+
export interface EvidenceArtifact {
|
|
86
|
+
id: string
|
|
87
|
+
createdAt: string
|
|
88
|
+
artifactType: 'evolution' | 'replay' | 'regression' | 'canary' | 'project-analysis' | 'ontology-review'
|
|
89
|
+
provenance: ArtifactProvenance
|
|
90
|
+
title: string
|
|
91
|
+
summary: string
|
|
92
|
+
sourceId?: string
|
|
93
|
+
iterationId?: string
|
|
94
|
+
proposalId?: string
|
|
95
|
+
projectId?: string
|
|
96
|
+
targetSkill?: string
|
|
97
|
+
operation?: string
|
|
98
|
+
outcome?: 'accepted' | 'rejected' | 'canary'
|
|
99
|
+
clusterType?: string
|
|
100
|
+
trigger?: string
|
|
101
|
+
judgeScores?: {
|
|
102
|
+
taskCompletion: number
|
|
103
|
+
correctionAlignment: number
|
|
104
|
+
sideEffectCheck: number
|
|
105
|
+
}
|
|
106
|
+
regression?: {
|
|
107
|
+
total: number
|
|
108
|
+
passed: number
|
|
109
|
+
passRate: number
|
|
110
|
+
}
|
|
111
|
+
metrics?: Record<string, number>
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface ActivationTrace {
|
|
115
|
+
id: string
|
|
116
|
+
timestamp: string
|
|
117
|
+
provenance: ActivationProvenance
|
|
118
|
+
sourceId: string
|
|
119
|
+
projectId?: string
|
|
120
|
+
projectPath?: string
|
|
121
|
+
sessionId?: string
|
|
122
|
+
activatedSkillIds: string[]
|
|
123
|
+
relevantSkillIds?: string[]
|
|
124
|
+
reasonSummary: string
|
|
125
|
+
contextSummary?: string
|
|
126
|
+
gapAreas?: string[]
|
|
127
|
+
recommendations?: string[]
|
|
128
|
+
relatedFailureId?: string
|
|
129
|
+
traceVersion?: string
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface PressureSignal {
|
|
133
|
+
id: string
|
|
134
|
+
kind: string
|
|
135
|
+
provenance: PressureProvenance
|
|
136
|
+
sourceType: 'failure' | 'correction' | 'replay' | 'regression' | 'project-analysis' | 'research' | 'manual'
|
|
137
|
+
sourceId: string
|
|
138
|
+
projectId?: string
|
|
139
|
+
projectPath?: string
|
|
140
|
+
detectedAt: string
|
|
141
|
+
severity: number
|
|
142
|
+
priority?: 'high' | 'medium' | 'low'
|
|
143
|
+
capability?: string
|
|
144
|
+
region?: string
|
|
145
|
+
description?: string
|
|
146
|
+
suggestedAction?: 'research' | 'specialize' | 'create'
|
|
147
|
+
relatedFailureId?: string
|
|
148
|
+
relatedActivationTraceId?: string
|
|
149
|
+
skillIds?: string[]
|
|
150
|
+
status?: 'open' | 'addressed'
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface ProjectPressureSummary {
|
|
154
|
+
projectId: string
|
|
155
|
+
totalSignals: number
|
|
156
|
+
nativeSignals: number
|
|
157
|
+
derivedSignals: number
|
|
158
|
+
highPrioritySignals: number
|
|
159
|
+
topCapabilities: string[]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface CoEvolutionDashboardSummary {
|
|
163
|
+
pressureSignals: {
|
|
164
|
+
total: number
|
|
165
|
+
native: number
|
|
166
|
+
derived: number
|
|
167
|
+
}
|
|
168
|
+
topProjects: ProjectPressureSummary[]
|
|
169
|
+
rolePressure: Record<CognitiveRole, number>
|
|
170
|
+
crossProjectGapAreas: { area: string; projects: string[]; count: number }[]
|
|
171
|
+
activeRecommendations: { action: 'research' | 'specialize' | 'create'; count: number }[]
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface OntologyDashboardSummary {
|
|
175
|
+
specVersion: string
|
|
176
|
+
source: 'graph' | 'compat-derived'
|
|
177
|
+
skillRoles: Record<CognitiveRole, number>
|
|
178
|
+
stabilityStates: Record<StabilityState, number>
|
|
179
|
+
plasticityStates: Record<PlasticityState, number>
|
|
180
|
+
enrichedSkillNodes: number
|
|
181
|
+
relationFamiliesObserved: number
|
|
182
|
+
mutationOperationsObserved: number
|
|
183
|
+
observedMutationActions: string[]
|
|
184
|
+
evidenceBackedProposals: number
|
|
185
|
+
artifacts: {
|
|
186
|
+
total: number
|
|
187
|
+
native: number
|
|
188
|
+
derived: number
|
|
189
|
+
}
|
|
190
|
+
activationTraces: {
|
|
191
|
+
total: number
|
|
192
|
+
native: number
|
|
193
|
+
derived: number
|
|
194
|
+
}
|
|
195
|
+
pressureSignals: {
|
|
196
|
+
total: number
|
|
197
|
+
native: number
|
|
198
|
+
derived: number
|
|
199
|
+
}
|
|
200
|
+
annotatedFailures: {
|
|
201
|
+
pressureSignals: number
|
|
202
|
+
capabilityGaps: number
|
|
203
|
+
activationTraces: number
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const DASHBOARD_ONTOLOGY_SPEC_VERSION = '0.1.0'
|
|
208
|
+
|
|
209
|
+
function emptyCounts<T extends string>(values: readonly T[]): Record<T, number> {
|
|
210
|
+
return Object.fromEntries(values.map((value) => [value, 0])) as Record<T, number>
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function inferCognitiveRole(node: SkillNode): CognitiveRole {
|
|
214
|
+
if (node.cognitiveRole) return node.cognitiveRole
|
|
215
|
+
if (node.layer === 'project' || Boolean(node.project)) return 'specialist'
|
|
216
|
+
if (node.generation > 0 && node.failureCount > 0) return 'hybrid'
|
|
217
|
+
return 'generalist'
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function inferStabilityState(node: SkillNode): StabilityState {
|
|
221
|
+
if (node.stabilityState) return node.stabilityState
|
|
222
|
+
if (node.status === 'canary' || node.score < 0.55) return 'experimental'
|
|
223
|
+
if (inferCognitiveRole(node) === 'generalist' && node.generation > 0 && node.score >= 0.7) return 'stable'
|
|
224
|
+
return 'adaptive'
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function inferPlasticityState(node: SkillNode): PlasticityState {
|
|
228
|
+
if (node.plasticityState) return node.plasticityState
|
|
229
|
+
if (node.status === 'canary' || node.generation === 0) return 'candidate'
|
|
230
|
+
if (node.generation >= 2 || node.score >= 0.8) return 'consolidated'
|
|
231
|
+
return 'volatile'
|
|
232
|
+
}
|
|
233
|
+
|
|
74
234
|
// ─── Loaders ────────────────────────────────────────────────────
|
|
75
235
|
|
|
76
236
|
export function loadGraph(): SkillGraph {
|
|
@@ -109,6 +269,218 @@ export function loadSkillContent(slug: string): string {
|
|
|
109
269
|
return readFileSync(path, 'utf-8')
|
|
110
270
|
}
|
|
111
271
|
|
|
272
|
+
function buildDerivedEvolutionArtifact(iteration: Iteration, proposal: Proposal): EvidenceArtifact {
|
|
273
|
+
return {
|
|
274
|
+
id: `artifact_derived_${iteration.id}_${proposal.id}`,
|
|
275
|
+
createdAt: iteration.timestamp,
|
|
276
|
+
artifactType: 'evolution',
|
|
277
|
+
provenance: 'derived-history',
|
|
278
|
+
sourceId: iteration.id,
|
|
279
|
+
iterationId: iteration.id,
|
|
280
|
+
proposalId: proposal.id,
|
|
281
|
+
title: `${proposal.targetSkill} · ${proposal.action}`,
|
|
282
|
+
summary: proposal.description,
|
|
283
|
+
targetSkill: proposal.targetSkill,
|
|
284
|
+
operation: proposal.action,
|
|
285
|
+
outcome: proposal.outcome as 'accepted' | 'rejected' | 'canary',
|
|
286
|
+
trigger: iteration.trigger,
|
|
287
|
+
judgeScores: {
|
|
288
|
+
taskCompletion: proposal.judges.taskCompletion.score,
|
|
289
|
+
correctionAlignment: proposal.judges.correctionAlignment.score,
|
|
290
|
+
sideEffectCheck: proposal.judges.sideEffectCheck.score,
|
|
291
|
+
},
|
|
292
|
+
regression: proposal.regressionResult,
|
|
293
|
+
metrics: {
|
|
294
|
+
regressionPassRate: proposal.regressionResult.passRate,
|
|
295
|
+
proposalConsensus: proposal.consensus ? 1 : 0,
|
|
296
|
+
},
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function buildDerivedActivationTraceFromFailure(failure: Failure): ActivationTrace {
|
|
301
|
+
return {
|
|
302
|
+
id: failure.activationTraceId ?? `activation_derived_${failure.id}`,
|
|
303
|
+
timestamp: failure.timestamp,
|
|
304
|
+
provenance: 'derived-failure',
|
|
305
|
+
sourceId: failure.id,
|
|
306
|
+
projectId: failure.project ?? undefined,
|
|
307
|
+
sessionId: failure.sessionId,
|
|
308
|
+
activatedSkillIds: failure.skillsActive,
|
|
309
|
+
relevantSkillIds: failure.skillsActive,
|
|
310
|
+
reasonSummary: `${failure.correctionType} correction captured from failure`,
|
|
311
|
+
contextSummary: failure.correction,
|
|
312
|
+
relatedFailureId: failure.id,
|
|
313
|
+
traceVersion: '0.1.0',
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function loadEvolutionArtifacts(): EvidenceArtifact[] {
|
|
318
|
+
const nativeArtifacts = readJsonl<EvidenceArtifact>('evolution-artifacts.jsonl')
|
|
319
|
+
const history = loadHistory()
|
|
320
|
+
const derivedArtifacts = history.iterations.flatMap((iteration) => iteration.proposals.map((proposal) => buildDerivedEvolutionArtifact(iteration, proposal)))
|
|
321
|
+
const nativeProposalIds = new Set(nativeArtifacts.map((artifact) => artifact.proposalId).filter(Boolean))
|
|
322
|
+
return [
|
|
323
|
+
...nativeArtifacts,
|
|
324
|
+
...derivedArtifacts.filter((artifact) => !artifact.proposalId || !nativeProposalIds.has(artifact.proposalId)),
|
|
325
|
+
].sort((a, b) => b.createdAt.localeCompare(a.createdAt))
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function loadActivationTraces(): ActivationTrace[] {
|
|
329
|
+
const nativeTraces = readJsonl<ActivationTrace>('activation-traces.jsonl')
|
|
330
|
+
const failures = loadFailures()
|
|
331
|
+
const derivedTraces = failures
|
|
332
|
+
.filter((failure) => failure.skillsActive.length > 0)
|
|
333
|
+
.map(buildDerivedActivationTraceFromFailure)
|
|
334
|
+
const nativeSourceIds = new Set(nativeTraces.map((trace) => trace.sourceId))
|
|
335
|
+
return [
|
|
336
|
+
...nativeTraces,
|
|
337
|
+
...derivedTraces.filter((trace) => !nativeSourceIds.has(trace.sourceId)),
|
|
338
|
+
].sort((a, b) => b.timestamp.localeCompare(a.timestamp))
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function inferFailurePressurePriority(failure: Failure): 'high' | 'medium' | 'low' {
|
|
342
|
+
if (failure.correctionType === 'manual_edit' || failure.correctionType === 'mode_switch') return 'high'
|
|
343
|
+
if (failure.skillsActive.length === 0) return 'high'
|
|
344
|
+
if (failure.correctionType === 'retry') return 'medium'
|
|
345
|
+
return 'low'
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function inferFailurePressureSeverity(failure: Failure): number {
|
|
349
|
+
const base = failure.correctionType === 'manual_edit' ? 0.95
|
|
350
|
+
: failure.correctionType === 'mode_switch' ? 0.9
|
|
351
|
+
: failure.correctionType === 'retry' ? 0.72
|
|
352
|
+
: 0.65
|
|
353
|
+
return failure.skillsActive.length === 0 ? Math.min(1, base + 0.08) : base
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function buildDerivedPressureSignalFromFailure(failure: Failure): PressureSignal {
|
|
357
|
+
return {
|
|
358
|
+
id: `pressure_derived_${failure.id}`,
|
|
359
|
+
kind: `correction:${failure.correctionType}`,
|
|
360
|
+
provenance: 'failure-derived',
|
|
361
|
+
sourceType: 'failure',
|
|
362
|
+
sourceId: failure.id,
|
|
363
|
+
projectId: failure.project ?? undefined,
|
|
364
|
+
detectedAt: failure.timestamp,
|
|
365
|
+
severity: inferFailurePressureSeverity(failure),
|
|
366
|
+
priority: inferFailurePressurePriority(failure),
|
|
367
|
+
description: failure.correction,
|
|
368
|
+
relatedFailureId: failure.id,
|
|
369
|
+
relatedActivationTraceId: failure.activationTraceId,
|
|
370
|
+
skillIds: failure.skillsActive,
|
|
371
|
+
status: failure.resolved ? 'addressed' : 'open',
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function buildDerivedProfileGapPressureSignals(profile: ProjectProfile): PressureSignal[] {
|
|
376
|
+
return profile.gaps.map((gap, index) => ({
|
|
377
|
+
id: `pressure_profile_${profile.name}_${index}`,
|
|
378
|
+
kind: `gap:${gap.area}`,
|
|
379
|
+
provenance: 'profile-gap-derived',
|
|
380
|
+
sourceType: 'project-analysis',
|
|
381
|
+
sourceId: profile.path,
|
|
382
|
+
projectId: profile.name,
|
|
383
|
+
projectPath: profile.path,
|
|
384
|
+
detectedAt: profile.analyzedAt,
|
|
385
|
+
severity: gap.priority === 'high' ? 0.95 : gap.priority === 'medium' ? 0.75 : 0.55,
|
|
386
|
+
priority: gap.priority,
|
|
387
|
+
capability: gap.area,
|
|
388
|
+
description: gap.description,
|
|
389
|
+
suggestedAction: gap.suggestedAction,
|
|
390
|
+
status: 'open',
|
|
391
|
+
}))
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function loadPressureSignals(): PressureSignal[] {
|
|
395
|
+
const nativeSignals = readJsonl<PressureSignal>('pressure-signals.jsonl')
|
|
396
|
+
const failures = loadFailures()
|
|
397
|
+
const profiles = loadAllProjectProfiles()
|
|
398
|
+
const derivedFromFailures = failures.map(buildDerivedPressureSignalFromFailure)
|
|
399
|
+
const derivedFromProfiles = profiles.flatMap(buildDerivedProfileGapPressureSignals)
|
|
400
|
+
const nativeKeys = new Set(nativeSignals.map((signal) => `${signal.sourceId}:${signal.kind}`))
|
|
401
|
+
return [
|
|
402
|
+
...nativeSignals,
|
|
403
|
+
...derivedFromFailures.filter((signal) => !nativeKeys.has(`${signal.sourceId}:${signal.kind}`)),
|
|
404
|
+
...derivedFromProfiles.filter((signal) => !nativeKeys.has(`${signal.sourceId}:${signal.kind}`)),
|
|
405
|
+
].sort((a, b) => b.detectedAt.localeCompare(a.detectedAt))
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function projectRoleForSkill(skillId: string, graph: SkillGraph): CognitiveRole {
|
|
409
|
+
const node = graph.nodes.find((entry) => entry.id === skillId)
|
|
410
|
+
if (!node) return 'hybrid'
|
|
411
|
+
return inferCognitiveRole(node)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function loadCoEvolutionSummary(): CoEvolutionDashboardSummary {
|
|
415
|
+
const graph = loadGraph()
|
|
416
|
+
const pressureSignals = loadPressureSignals()
|
|
417
|
+
const rolePressure = emptyCounts(['generalist', 'specialist', 'hybrid'] as const)
|
|
418
|
+
const projectBuckets = new Map<string, ProjectPressureSummary>()
|
|
419
|
+
const areaProjects = new Map<string, Set<string>>()
|
|
420
|
+
const recommendationCounts = new Map<'research' | 'specialize' | 'create', number>()
|
|
421
|
+
|
|
422
|
+
for (const signal of pressureSignals) {
|
|
423
|
+
for (const skillId of signal.skillIds ?? []) {
|
|
424
|
+
rolePressure[projectRoleForSkill(skillId, graph)] += 1
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (signal.projectId) {
|
|
428
|
+
const existing = projectBuckets.get(signal.projectId) ?? {
|
|
429
|
+
projectId: signal.projectId,
|
|
430
|
+
totalSignals: 0,
|
|
431
|
+
nativeSignals: 0,
|
|
432
|
+
derivedSignals: 0,
|
|
433
|
+
highPrioritySignals: 0,
|
|
434
|
+
topCapabilities: [],
|
|
435
|
+
}
|
|
436
|
+
existing.totalSignals += 1
|
|
437
|
+
if (signal.provenance === 'failure-native' || signal.provenance === 'project-analysis-native') existing.nativeSignals += 1
|
|
438
|
+
else existing.derivedSignals += 1
|
|
439
|
+
if (signal.priority === 'high') existing.highPrioritySignals += 1
|
|
440
|
+
if (signal.capability && !existing.topCapabilities.includes(signal.capability) && existing.topCapabilities.length < 3) {
|
|
441
|
+
existing.topCapabilities.push(signal.capability)
|
|
442
|
+
}
|
|
443
|
+
projectBuckets.set(signal.projectId, existing)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if (signal.capability && signal.projectId) {
|
|
447
|
+
const projects = areaProjects.get(signal.capability) ?? new Set<string>()
|
|
448
|
+
projects.add(signal.projectId)
|
|
449
|
+
areaProjects.set(signal.capability, projects)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (signal.suggestedAction) {
|
|
453
|
+
recommendationCounts.set(signal.suggestedAction, (recommendationCounts.get(signal.suggestedAction) ?? 0) + 1)
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const topProjects = [...projectBuckets.values()]
|
|
458
|
+
.sort((a, b) => b.totalSignals - a.totalSignals || b.highPrioritySignals - a.highPrioritySignals)
|
|
459
|
+
.slice(0, 6)
|
|
460
|
+
|
|
461
|
+
const crossProjectGapAreas = [...areaProjects.entries()]
|
|
462
|
+
.filter(([, projects]) => projects.size >= 2)
|
|
463
|
+
.map(([area, projects]) => ({ area, projects: [...projects], count: projects.size }))
|
|
464
|
+
.sort((a, b) => b.count - a.count || a.area.localeCompare(b.area))
|
|
465
|
+
.slice(0, 6)
|
|
466
|
+
|
|
467
|
+
const activeRecommendations = [...recommendationCounts.entries()]
|
|
468
|
+
.map(([action, count]) => ({ action, count }))
|
|
469
|
+
.sort((a, b) => b.count - a.count)
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
pressureSignals: {
|
|
473
|
+
total: pressureSignals.length,
|
|
474
|
+
native: pressureSignals.filter((signal) => signal.provenance === 'failure-native' || signal.provenance === 'project-analysis-native').length,
|
|
475
|
+
derived: pressureSignals.filter((signal) => signal.provenance === 'failure-derived' || signal.provenance === 'profile-gap-derived').length,
|
|
476
|
+
},
|
|
477
|
+
topProjects,
|
|
478
|
+
rolePressure,
|
|
479
|
+
crossProjectGapAreas,
|
|
480
|
+
activeRecommendations,
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
112
484
|
export function listProjects(): string[] {
|
|
113
485
|
const failures = loadFailures()
|
|
114
486
|
const projects = [...new Set(failures.map(f => f.project).filter(Boolean))] as string[]
|
|
@@ -176,3 +548,73 @@ export function getDashboardSummary() {
|
|
|
176
548
|
skillTests: skillTests.length,
|
|
177
549
|
}
|
|
178
550
|
}
|
|
551
|
+
|
|
552
|
+
export function loadOntologySummary(): OntologyDashboardSummary {
|
|
553
|
+
const graph = loadGraph()
|
|
554
|
+
const history = loadHistory()
|
|
555
|
+
const failures = loadFailures()
|
|
556
|
+
const artifacts = loadEvolutionArtifacts()
|
|
557
|
+
const activationTraces = loadActivationTraces()
|
|
558
|
+
const pressureSignals = loadPressureSignals()
|
|
559
|
+
const skillRoles = emptyCounts(['generalist', 'specialist', 'hybrid'] as const)
|
|
560
|
+
const stabilityStates = emptyCounts(['stable', 'adaptive', 'experimental'] as const)
|
|
561
|
+
const plasticityStates = emptyCounts(['consolidated', 'volatile', 'candidate'] as const)
|
|
562
|
+
|
|
563
|
+
for (const node of graph.nodes) {
|
|
564
|
+
skillRoles[inferCognitiveRole(node)] += 1
|
|
565
|
+
stabilityStates[inferStabilityState(node)] += 1
|
|
566
|
+
plasticityStates[inferPlasticityState(node)] += 1
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const proposals = history.iterations.flatMap((iteration) => iteration.proposals)
|
|
570
|
+
const observedMutationActions = [...new Set(proposals.map((proposal) => proposal.action))].sort()
|
|
571
|
+
const evidenceBackedProposals = proposals.filter((proposal) => {
|
|
572
|
+
const judges = proposal.judges
|
|
573
|
+
const hasJudgeScores = [judges.taskCompletion, judges.correctionAlignment, judges.sideEffectCheck]
|
|
574
|
+
.every((judge) => Number.isFinite(judge.score))
|
|
575
|
+
return hasJudgeScores && proposal.regressionResult.total > 0
|
|
576
|
+
}).length
|
|
577
|
+
|
|
578
|
+
return {
|
|
579
|
+
specVersion: graph.ontologyVersion ?? DASHBOARD_ONTOLOGY_SPEC_VERSION,
|
|
580
|
+
source: graph.ontologyVersion ? 'graph' : 'compat-derived',
|
|
581
|
+
skillRoles,
|
|
582
|
+
stabilityStates,
|
|
583
|
+
plasticityStates,
|
|
584
|
+
enrichedSkillNodes: graph.nodes.filter((node) => Boolean(
|
|
585
|
+
node.cognitiveRole
|
|
586
|
+
|| node.stabilityState
|
|
587
|
+
|| node.plasticityState
|
|
588
|
+
|| node.capabilities?.length
|
|
589
|
+
|| node.lineageId,
|
|
590
|
+
)).length,
|
|
591
|
+
relationFamiliesObserved: new Set(graph.edges.map((edge) => edge.type)).size,
|
|
592
|
+
mutationOperationsObserved: observedMutationActions.length,
|
|
593
|
+
observedMutationActions,
|
|
594
|
+
evidenceBackedProposals,
|
|
595
|
+
artifacts: {
|
|
596
|
+
total: artifacts.length,
|
|
597
|
+
native: artifacts.filter((artifact) => artifact.provenance === 'native-evolution').length,
|
|
598
|
+
derived: artifacts.filter((artifact) => artifact.provenance === 'derived-history').length,
|
|
599
|
+
},
|
|
600
|
+
activationTraces: {
|
|
601
|
+
total: activationTraces.length,
|
|
602
|
+
native: activationTraces.filter((trace) => trace.provenance !== 'derived-failure').length,
|
|
603
|
+
derived: activationTraces.filter((trace) => trace.provenance === 'derived-failure').length,
|
|
604
|
+
},
|
|
605
|
+
pressureSignals: {
|
|
606
|
+
total: pressureSignals.length,
|
|
607
|
+
native: pressureSignals.filter((signal) => signal.provenance === 'failure-native' || signal.provenance === 'project-analysis-native').length,
|
|
608
|
+
derived: pressureSignals.filter((signal) => signal.provenance === 'failure-derived' || signal.provenance === 'profile-gap-derived').length,
|
|
609
|
+
},
|
|
610
|
+
annotatedFailures: {
|
|
611
|
+
pressureSignals: failures.filter((failure) => (failure.pressureSignals?.length ?? 0) > 0).length,
|
|
612
|
+
capabilityGaps: failures.filter((failure) => (failure.capabilityGaps?.length ?? 0) > 0).length,
|
|
613
|
+
activationTraces: failures.filter((failure) => Boolean(failure.activationTraceId)).length,
|
|
614
|
+
},
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
export function getOntologyDashboardSummary(): OntologyDashboardSummary {
|
|
619
|
+
return loadOntologySummary()
|
|
620
|
+
}
|