helixevo 0.8.1 → 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 +11 -0
- package/README.md +5 -5
- package/dashboard/app/coevolution/client.tsx +23 -1
- package/dashboard/app/page.tsx +40 -1
- 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,17 @@ 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
|
+
|
|
7
18
|
## [0.8.1] - 2026-03-25
|
|
8
19
|
|
|
9
20
|
### Changed
|
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
|
@@ -31,6 +31,7 @@ function providerTone(status: 'healthy' | 'degraded' | 'unavailable' | 'unknown'
|
|
|
31
31
|
function getPriorityActions(params: {
|
|
32
32
|
unresolved: number
|
|
33
33
|
proofOpen: number
|
|
34
|
+
proofCaution: number
|
|
34
35
|
topologyOpen: number
|
|
35
36
|
optimizeStatus: 'idle' | 'healthy' | 'partial' | 'failed'
|
|
36
37
|
optimizeNextStep?: string
|
|
@@ -58,6 +59,15 @@ function getPriorityActions(params: {
|
|
|
58
59
|
})
|
|
59
60
|
}
|
|
60
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
|
+
|
|
61
71
|
if (params.proofOpen > 0) {
|
|
62
72
|
actions.push({
|
|
63
73
|
href: '/proof',
|
|
@@ -134,6 +144,7 @@ export default function Overview() {
|
|
|
134
144
|
const priorityActions = getPriorityActions({
|
|
135
145
|
unresolved: summary.failures.unresolved,
|
|
136
146
|
proofOpen: proof.summary.reviewOpen,
|
|
147
|
+
proofCaution: proof.steering.cautionLanes,
|
|
137
148
|
topologyOpen: topologyControl.summary.open,
|
|
138
149
|
optimizeStatus: topologyControl.optimizeStatus.status,
|
|
139
150
|
optimizeNextStep: topologyControl.optimizeStatus.nextStep,
|
|
@@ -176,7 +187,7 @@ export default function Overview() {
|
|
|
176
187
|
|
|
177
188
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
178
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="!" />
|
|
179
|
-
<MetricCard label="Proof review" value={proof.summary.reviewOpen} sublabel={`${proof.
|
|
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="◇" />
|
|
180
191
|
<MetricCard
|
|
181
192
|
label="Open pressure"
|
|
182
193
|
value={ontology.pressureLifecycle.open}
|
|
@@ -328,6 +339,34 @@ export default function Overview() {
|
|
|
328
339
|
</SectionFrame>
|
|
329
340
|
) : null}
|
|
330
341
|
|
|
342
|
+
<SectionFrame
|
|
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."
|
|
346
|
+
tone="blue"
|
|
347
|
+
actions={<Link href="/proof" className="badge badge-gray">Open proof control</Link>}
|
|
348
|
+
>
|
|
349
|
+
<div className="grid-2" style={{ gap: 16 }}>
|
|
350
|
+
<div className="summary-list">
|
|
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>
|
|
356
|
+
</div>
|
|
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}
|
|
361
|
+
</div>
|
|
362
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
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>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
</SectionFrame>
|
|
369
|
+
|
|
331
370
|
<SectionFrame
|
|
332
371
|
eyebrow="Brain summary"
|
|
333
372
|
title="Semantic backbone"
|
|
@@ -39,6 +39,17 @@ function labelForOutcome(outcome: ProofOutcomeState) {
|
|
|
39
39
|
return outcome.replace(/-/g, ' ')
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function toneForSteeringTier(tier: 'trusted' | 'caution' | 'bounded' | 'candidate') {
|
|
43
|
+
if (tier === 'trusted') return 'green'
|
|
44
|
+
if (tier === 'caution') return 'yellow'
|
|
45
|
+
if (tier === 'bounded') return 'blue'
|
|
46
|
+
return 'neutral'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function labelForSteeringLane(lane: ProofDashboardSummary['steering']['routeLanes'][number] | ProofDashboardSummary['steering']['semanticLanes'][number]) {
|
|
50
|
+
return lane.route ? lane.route.replace(/-/g, ' ') : lane.conceptId ?? lane.laneKey
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
function formatDate(value: string | undefined) {
|
|
43
54
|
if (!value) return '—'
|
|
44
55
|
return new Date(value).toLocaleString()
|
|
@@ -52,19 +63,20 @@ function consoleTone(state: RunState): 'neutral' | 'green' | 'red' | 'yellow' {
|
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
function getRecommendedProofMove(dashboard: ProofDashboardSummary) {
|
|
66
|
+
const cautionLane = dashboard.steering.routeLanes.find((lane) => lane.evidenceTier === 'caution')
|
|
67
|
+
if (cautionLane) {
|
|
68
|
+
return {
|
|
69
|
+
label: 'Caution first',
|
|
70
|
+
title: labelForSteeringLane(cautionLane),
|
|
71
|
+
copy: 'A cautionary proof lane should usually be reviewed before you trust that route again. Regressed or contested evidence now biases the next loop toward more care.',
|
|
72
|
+
}
|
|
73
|
+
}
|
|
55
74
|
const firstOpen = dashboard.reviewQueue[0]
|
|
56
75
|
if (firstOpen) {
|
|
57
76
|
return {
|
|
58
77
|
label: 'Review queue first',
|
|
59
78
|
title: firstOpen.title,
|
|
60
|
-
copy: '
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (dashboard.summary.regressed > 0) {
|
|
64
|
-
return {
|
|
65
|
-
label: 'Investigate regressed evidence',
|
|
66
|
-
title: 'A regressed outcome needs explanation before retry',
|
|
67
|
-
copy: 'Regressed records mean HelixEvo has explicit negative evidence. Inspect the linked structural or intervention path before repeating the same move.',
|
|
79
|
+
copy: 'High-leverage proof records should usually be resolved before you treat the prove layer as settled. Verify, defer, or contest the most important record first.',
|
|
68
80
|
}
|
|
69
81
|
}
|
|
70
82
|
if (dashboard.summary.measuring > 0) {
|
|
@@ -74,6 +86,13 @@ function getRecommendedProofMove(dashboard: ProofDashboardSummary) {
|
|
|
74
86
|
copy: 'A measuring record is active but still too recent or incomplete for a stronger claim. Let downstream evidence accumulate before over-interpreting it.',
|
|
75
87
|
}
|
|
76
88
|
}
|
|
89
|
+
if (dashboard.candidateQueue.length > 0) {
|
|
90
|
+
return {
|
|
91
|
+
label: 'Candidate evidence only',
|
|
92
|
+
title: 'Dry-run and insufficient evidence stay bounded',
|
|
93
|
+
copy: 'Candidate proof records should remain visible, but they should not steer the system strongly until stronger downstream evidence appears.',
|
|
94
|
+
}
|
|
95
|
+
}
|
|
77
96
|
return {
|
|
78
97
|
label: 'Seed proof',
|
|
79
98
|
title: 'No proof targets yet',
|
|
@@ -128,10 +147,10 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
|
|
|
128
147
|
description="Review whether interventions, transfers, topology changes, semantic adoption, and evolution effects actually appear to be working. Proof stays bounded and operator-governed rather than pretending to know more than the evidence supports."
|
|
129
148
|
chips={[
|
|
130
149
|
{ label: `${dashboard.summary.total} proof records`, tone: 'blue' },
|
|
131
|
-
{ label: `${dashboard.
|
|
132
|
-
{ label: `${dashboard.
|
|
133
|
-
{ label: `${dashboard.summary.regressed} regressed`, tone: dashboard.summary.regressed > 0 ? 'yellow' : 'neutral' },
|
|
150
|
+
{ label: `${dashboard.steering.trustedLanes} trusted lanes`, tone: dashboard.steering.trustedLanes > 0 ? 'green' : 'neutral' },
|
|
151
|
+
{ label: `${dashboard.steering.cautionLanes} caution lanes`, tone: dashboard.steering.cautionLanes > 0 ? 'yellow' : 'neutral' },
|
|
134
152
|
{ label: `${dashboard.summary.reviewOpen} open review`, tone: dashboard.summary.reviewOpen > 0 ? 'yellow' : 'green' },
|
|
153
|
+
{ label: `${dashboard.steering.candidateLanes} candidate lanes`, tone: dashboard.steering.candidateLanes > 0 ? 'neutral' : 'green' },
|
|
135
154
|
{ label: `${dashboard.summary.verified} verified`, tone: dashboard.summary.verified > 0 ? 'green' : 'neutral' },
|
|
136
155
|
]}
|
|
137
156
|
actions={
|
|
@@ -149,11 +168,11 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
|
|
|
149
168
|
<OperatorLoopTrail surface="proof" />
|
|
150
169
|
|
|
151
170
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
|
|
152
|
-
<MetricCard label="
|
|
153
|
-
<MetricCard label="
|
|
154
|
-
<MetricCard label="Regressed" value={dashboard.summary.regressed} sublabel={`${dashboard.summary.contested} contested • explicit failed or rolled-back cases`} tone={dashboard.summary.regressed > 0 ? 'yellow' : 'neutral'} icon="!" />
|
|
171
|
+
<MetricCard label="Trusted lanes" value={dashboard.steering.trustedLanes} sublabel={`${dashboard.summary.verified} verified records backing future trust`} tone={dashboard.steering.trustedLanes > 0 ? 'green' : 'neutral'} icon="✓" />
|
|
172
|
+
<MetricCard label="Caution lanes" value={dashboard.steering.cautionLanes} sublabel={`${dashboard.summary.regressed} regressed • ${dashboard.summary.contested} contested`} tone={dashboard.steering.cautionLanes > 0 ? 'yellow' : 'neutral'} icon="!" />
|
|
155
173
|
<MetricCard label="Measuring" value={dashboard.summary.measuring} sublabel={`${dashboard.summary.insufficientEvidence} insufficient-evidence`} tone={dashboard.summary.measuring > 0 ? 'blue' : 'neutral'} icon="◎" />
|
|
156
|
-
<MetricCard label="
|
|
174
|
+
<MetricCard label="Candidate evidence" value={dashboard.steering.candidateLanes} sublabel={`${dashboard.candidateQueue.length} open low-closure records`} tone={dashboard.steering.candidateLanes > 0 ? 'neutral' : 'green'} icon="◌" />
|
|
175
|
+
<MetricCard label="Open review" value={dashboard.summary.reviewOpen} sublabel={`${dashboard.steering.priorityReview} high-leverage • ${dashboard.summary.verified} verified`} tone={dashboard.summary.reviewOpen > 0 ? 'yellow' : 'green'} icon="◇" />
|
|
157
176
|
</div>
|
|
158
177
|
|
|
159
178
|
<SectionFrame
|
|
@@ -178,6 +197,34 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
|
|
|
178
197
|
</div>
|
|
179
198
|
</SectionFrame>
|
|
180
199
|
|
|
200
|
+
<SectionFrame
|
|
201
|
+
eyebrow="Steering"
|
|
202
|
+
title="What proof is changing about future control"
|
|
203
|
+
description="Proof now separates trusted, cautionary, bounded, and candidate evidence so the next governed loop can steer more honestly. Trusted lanes can strengthen confidence modestly, caution lanes bias toward more review, and candidate evidence stays bounded."
|
|
204
|
+
tone="blue"
|
|
205
|
+
>
|
|
206
|
+
<div className="grid-2" style={{ gap: 16 }}>
|
|
207
|
+
<div className="summary-list">
|
|
208
|
+
{dashboard.steering.routeLanes.slice(0, 4).map((lane) => (
|
|
209
|
+
<div key={lane.laneKey} className="summary-row">
|
|
210
|
+
<div className="summary-row-main">
|
|
211
|
+
<div className="summary-row-title">{labelForSteeringLane(lane)}</div>
|
|
212
|
+
<div className="summary-row-meta">{lane.summary}</div>
|
|
213
|
+
<div className="summary-row-meta" style={{ marginTop: 6 }}>{lane.reasons[0] ?? 'Proof steering keeps this lane bounded.'}</div>
|
|
214
|
+
</div>
|
|
215
|
+
<span className={`hero-chip hero-chip-${toneForSteeringTier(lane.evidenceTier)}`}>{lane.evidenceTier}</span>
|
|
216
|
+
</div>
|
|
217
|
+
))}
|
|
218
|
+
{dashboard.steering.routeLanes.length === 0 ? <div className="signal-text">No route-level steering evidence yet.</div> : null}
|
|
219
|
+
</div>
|
|
220
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
221
|
+
<MetricCard label="Priority review" value={dashboard.steering.priorityReview} sublabel={`${dashboard.reviewQueue.length} high-leverage queue items`} tone={dashboard.steering.priorityReview > 0 ? 'yellow' : 'green'} icon="◇" />
|
|
222
|
+
<MetricCard label="Semantic steering" value={dashboard.steering.semanticLanes.length} sublabel={`${dashboard.steering.semanticLanes.filter((lane) => lane.evidenceTier === 'trusted').length} trusted • ${dashboard.steering.semanticLanes.filter((lane) => lane.evidenceTier === 'caution').length} caution`} tone={dashboard.steering.semanticLanes.length > 0 ? 'purple' : 'neutral'} icon="◎" />
|
|
223
|
+
<div className="signal-text">Candidate evidence remains visible below, but it no longer dominates the highest-value proof review surface.</div>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</SectionFrame>
|
|
227
|
+
|
|
181
228
|
<SectionFrame
|
|
182
229
|
eyebrow="Coverage"
|
|
183
230
|
title="Proof now spans the live brain loop"
|
|
@@ -255,6 +302,28 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
|
|
|
255
302
|
</div>
|
|
256
303
|
</SectionFrame>
|
|
257
304
|
|
|
305
|
+
<SectionFrame
|
|
306
|
+
eyebrow="Candidate evidence"
|
|
307
|
+
title="Dry-run and low-closure proof"
|
|
308
|
+
description="These records remain visible, but they should not steer the system strongly until stronger downstream evidence or explicit operator review exists."
|
|
309
|
+
>
|
|
310
|
+
<div style={{ display: 'grid', gap: 10 }}>
|
|
311
|
+
{dashboard.candidateQueue.length > 0 ? dashboard.candidateQueue.map((record) => (
|
|
312
|
+
<div key={record.id} style={{ padding: '14px 16px', borderRadius: 18, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.72)' }}>
|
|
313
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
|
|
314
|
+
<div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{record.title}</div>
|
|
315
|
+
<span className="badge badge-gray">candidate</span>
|
|
316
|
+
</div>
|
|
317
|
+
<div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, lineHeight: 1.6 }}>{record.summary}</div>
|
|
318
|
+
<div style={{ display: 'grid', gap: 6, marginTop: 10 }}>
|
|
319
|
+
{record.reasons.slice(0, 2).map((reason, idx) => <div key={`${record.id}-candidate-${idx}`} className="signal-text">• {reason}</div>)}
|
|
320
|
+
{record.recommendedAction ? <div className="signal-text">→ {record.recommendedAction}</div> : null}
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
)) : <div className="signal-text">No candidate-only proof records right now.</div>}
|
|
324
|
+
</div>
|
|
325
|
+
</SectionFrame>
|
|
326
|
+
|
|
258
327
|
<div className="grid-2">
|
|
259
328
|
<SectionFrame
|
|
260
329
|
eyebrow="Verified"
|
package/dashboard/lib/data.ts
CHANGED
|
@@ -30,6 +30,8 @@ function readOntologyJsonl<T>(filename: string): T[] {
|
|
|
30
30
|
return raw.split('\n').filter(Boolean).map((l) => JSON.parse(l))
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
import { loadProofSteeringSummary } from './proof'
|
|
34
|
+
|
|
33
35
|
// ─── Types ──────────────────────────────────────────────────────
|
|
34
36
|
|
|
35
37
|
export type CognitiveRole = 'generalist' | 'specialist' | 'hybrid'
|
|
@@ -180,6 +182,8 @@ export type PressureInterventionImpact = 'exploratory' | 'structural' | 'resolvi
|
|
|
180
182
|
export type PressureLifecycleState = 'open' | 'in-progress' | 'addressed' | 'stale'
|
|
181
183
|
export type PressureRouteScope = 'local' | 'project' | 'network'
|
|
182
184
|
export type PressureRouteTrigger = 'high-priority-local-gap' | 'project-bounded-recurrence' | 'recurring-cross-project-gap' | 'overlapping-skills' | 'accepted-iteration-pattern' | 'insufficient-evidence' | 'mixed-signal'
|
|
185
|
+
export type ProofSteeringTier = 'trusted' | 'caution' | 'bounded' | 'candidate'
|
|
186
|
+
export type ProofSteeringInfluence = 'none' | 'explanatory' | 'weighted'
|
|
183
187
|
|
|
184
188
|
export interface PressureRouteRecommendation {
|
|
185
189
|
route: PressureInterventionType
|
|
@@ -190,6 +194,11 @@ export interface PressureRouteRecommendation {
|
|
|
190
194
|
reasons: string[]
|
|
191
195
|
semanticInfluence?: OntologySemanticInfluence
|
|
192
196
|
semanticConceptIds?: string[]
|
|
197
|
+
proofInfluence?: ProofSteeringInfluence
|
|
198
|
+
proofTier?: ProofSteeringTier
|
|
199
|
+
proofSummary?: string
|
|
200
|
+
proofReasons?: string[]
|
|
201
|
+
proofLaneKeys?: string[]
|
|
193
202
|
}
|
|
194
203
|
|
|
195
204
|
export interface PressureIntervention {
|
|
@@ -2036,6 +2045,105 @@ function matchTopologyOntologyBindings(candidate: ResolvedTopologyReviewCandidat
|
|
|
2036
2045
|
return dedupeOntologyBindings(bindings)
|
|
2037
2046
|
}
|
|
2038
2047
|
|
|
2048
|
+
function proofTierWeight(tier: ProofSteeringTier): number {
|
|
2049
|
+
return tier === 'caution' ? 4 : tier === 'trusted' ? 3 : tier === 'bounded' ? 2 : 1
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
function strongerProofTier(current: ProofSteeringTier | undefined, next: ProofSteeringTier): ProofSteeringTier {
|
|
2053
|
+
if (!current) return next
|
|
2054
|
+
return proofTierWeight(next) > proofTierWeight(current) ? next : current
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
function applyProofInfluenceToRoute(params: {
|
|
2058
|
+
recommendation: PressureRouteRecommendation
|
|
2059
|
+
signal: PressureSignal
|
|
2060
|
+
semanticBindings: ResolvedOntologyBinding[]
|
|
2061
|
+
proofSteering: import('./proof').ProofSteeringSummary | null
|
|
2062
|
+
}): PressureRouteRecommendation {
|
|
2063
|
+
const { recommendation, semanticBindings, proofSteering } = params
|
|
2064
|
+
if (!proofSteering) return recommendation
|
|
2065
|
+
|
|
2066
|
+
let route = recommendation.route
|
|
2067
|
+
let confidence = recommendation.confidence
|
|
2068
|
+
let triggeredBy = recommendation.triggeredBy
|
|
2069
|
+
const reasons = [...recommendation.reasons]
|
|
2070
|
+
const proofReasons: string[] = []
|
|
2071
|
+
const proofLaneKeys: string[] = []
|
|
2072
|
+
let proofSummary: string | undefined
|
|
2073
|
+
let proofTier: ProofSteeringTier | undefined
|
|
2074
|
+
let proofInfluence: 'none' | 'explanatory' | 'weighted' = 'none'
|
|
2075
|
+
|
|
2076
|
+
const routeLane = proofSteering.byRoute[recommendation.route]
|
|
2077
|
+
if (routeLane) {
|
|
2078
|
+
proofLaneKeys.push(routeLane.laneKey)
|
|
2079
|
+
proofReasons.push(...routeLane.reasons.slice(0, 2))
|
|
2080
|
+
proofSummary = proofSummary ?? routeLane.summary
|
|
2081
|
+
proofTier = strongerProofTier(proofTier, routeLane.evidenceTier)
|
|
2082
|
+
|
|
2083
|
+
if (routeLane.evidenceTier === 'trusted') {
|
|
2084
|
+
confidence = Math.min(0.95, confidence + (routeLane.score >= 4 ? 0.06 : 0.04))
|
|
2085
|
+
proofInfluence = 'weighted'
|
|
2086
|
+
reasons.push(`Proof steering: ${routeLane.summary}`)
|
|
2087
|
+
} else if (routeLane.evidenceTier === 'caution') {
|
|
2088
|
+
if (recommendation.route !== 'manual-review' && routeLane.score <= -3 && (recommendation.route === 'generalize' || recommendation.route === 'evolve')) {
|
|
2089
|
+
route = 'manual-review'
|
|
2090
|
+
triggeredBy = 'mixed-signal'
|
|
2091
|
+
confidence = Math.max(0.66, confidence - 0.02)
|
|
2092
|
+
proofInfluence = 'weighted'
|
|
2093
|
+
reasons.push(`Proof steering: ${routeLane.summary} Governance now prefers explicit operator review before retrying ${recommendation.route}.`)
|
|
2094
|
+
} else {
|
|
2095
|
+
confidence = Math.max(0.4, confidence - 0.08)
|
|
2096
|
+
proofInfluence = 'weighted'
|
|
2097
|
+
reasons.push(`Proof steering: ${routeLane.summary}`)
|
|
2098
|
+
}
|
|
2099
|
+
} else {
|
|
2100
|
+
if (proofInfluence === 'none') proofInfluence = 'explanatory'
|
|
2101
|
+
reasons.push(`Proof steering: ${routeLane.summary}`)
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
const conceptIds = uniqueStrings([...(recommendation.semanticConceptIds ?? []), ...semanticBindings.map((binding) => binding.conceptId)])
|
|
2106
|
+
const conceptLanes = conceptIds.map((conceptId) => proofSteering.byConceptId[conceptId]).filter(Boolean)
|
|
2107
|
+
if (conceptLanes.length > 0) {
|
|
2108
|
+
const strongestConceptLane = [...conceptLanes].sort((a, b) => proofTierWeight(b.evidenceTier) - proofTierWeight(a.evidenceTier) || Math.abs(b.score) - Math.abs(a.score))[0]
|
|
2109
|
+
if (strongestConceptLane) {
|
|
2110
|
+
proofLaneKeys.push(strongestConceptLane.laneKey)
|
|
2111
|
+
proofReasons.push(...strongestConceptLane.reasons.slice(0, 2))
|
|
2112
|
+
proofSummary = proofSummary ?? strongestConceptLane.summary
|
|
2113
|
+
proofTier = strongerProofTier(proofTier, strongestConceptLane.evidenceTier)
|
|
2114
|
+
if (strongestConceptLane.evidenceTier === 'trusted') {
|
|
2115
|
+
confidence = Math.min(0.95, confidence + 0.02)
|
|
2116
|
+
proofInfluence = 'weighted'
|
|
2117
|
+
reasons.push(`Proof steering: ${strongestConceptLane.summary}`)
|
|
2118
|
+
} else if (strongestConceptLane.evidenceTier === 'caution') {
|
|
2119
|
+
confidence = Math.max(0.4, confidence - 0.03)
|
|
2120
|
+
if (proofInfluence === 'none') proofInfluence = 'weighted'
|
|
2121
|
+
reasons.push(`Proof steering: ${strongestConceptLane.summary}`)
|
|
2122
|
+
} else {
|
|
2123
|
+
if (proofInfluence === 'none') proofInfluence = 'explanatory'
|
|
2124
|
+
reasons.push(`Proof steering: ${strongestConceptLane.summary}`)
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
return {
|
|
2130
|
+
...recommendation,
|
|
2131
|
+
route,
|
|
2132
|
+
confidence,
|
|
2133
|
+
triggeredBy,
|
|
2134
|
+
reasons: [...new Set(reasons)].slice(0, 8),
|
|
2135
|
+
proofInfluence,
|
|
2136
|
+
proofTier,
|
|
2137
|
+
proofSummary,
|
|
2138
|
+
proofReasons: [...new Set(proofReasons)].slice(0, 4),
|
|
2139
|
+
proofLaneKeys: [...new Set(proofLaneKeys)],
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
type ProofSteeringLoadOptions = {
|
|
2144
|
+
includeProofSteering?: boolean
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2039
2147
|
function applyOntologyInfluenceToRoute(params: {
|
|
2040
2148
|
recommendation: PressureRouteRecommendation
|
|
2041
2149
|
signal: PressureSignal
|
|
@@ -2088,8 +2196,9 @@ function buildRouteRecommendation(params: {
|
|
|
2088
2196
|
governanceMode: GovernanceModeName
|
|
2089
2197
|
governanceProfile: GovernanceProfile
|
|
2090
2198
|
semanticBindings: ResolvedOntologyBinding[]
|
|
2199
|
+
proofSteering: import('./proof').ProofSteeringSummary | null
|
|
2091
2200
|
}): PressureRouteRecommendation {
|
|
2092
|
-
const { signal, relatedSignals, linkedInterventions, governanceMode, governanceProfile, semanticBindings } = params
|
|
2201
|
+
const { signal, relatedSignals, linkedInterventions, governanceMode, governanceProfile, semanticBindings, proofSteering } = params
|
|
2093
2202
|
const projectSpread = new Set(relatedSignals.map((entry) => entry.projectId ?? entry.projectPath).filter(Boolean)).size
|
|
2094
2203
|
const recurrenceCount = relatedSignals.length
|
|
2095
2204
|
const activeTypes = [...new Set(linkedInterventions.map((intervention) => intervention.interventionType))]
|
|
@@ -2175,12 +2284,19 @@ function buildRouteRecommendation(params: {
|
|
|
2175
2284
|
}
|
|
2176
2285
|
}
|
|
2177
2286
|
|
|
2178
|
-
|
|
2287
|
+
const ontologyAware = applyOntologyInfluenceToRoute({
|
|
2179
2288
|
recommendation,
|
|
2180
2289
|
signal,
|
|
2181
2290
|
semanticBindings,
|
|
2182
2291
|
governanceProfile,
|
|
2183
2292
|
})
|
|
2293
|
+
|
|
2294
|
+
return applyProofInfluenceToRoute({
|
|
2295
|
+
recommendation: ontologyAware,
|
|
2296
|
+
signal,
|
|
2297
|
+
semanticBindings,
|
|
2298
|
+
proofSteering,
|
|
2299
|
+
})
|
|
2184
2300
|
}
|
|
2185
2301
|
|
|
2186
2302
|
function interventionEvidenceAccepted(
|
|
@@ -2206,7 +2322,7 @@ function interventionKeepsPressureActive(impact: PressureInterventionImpact, sta
|
|
|
2206
2322
|
return impact === 'exploratory' || impact === 'structural' || impact === 'resolving'
|
|
2207
2323
|
}
|
|
2208
2324
|
|
|
2209
|
-
export function loadResolvedPressureSignals(): ResolvedPressureSignal[] {
|
|
2325
|
+
export function loadResolvedPressureSignals(options: ProofSteeringLoadOptions = {}): ResolvedPressureSignal[] {
|
|
2210
2326
|
const pressureSignals = loadPressureSignals()
|
|
2211
2327
|
const interventions = loadPressureInterventions()
|
|
2212
2328
|
const transferEvents = loadTransferEvents()
|
|
@@ -2214,6 +2330,7 @@ export function loadResolvedPressureSignals(): ResolvedPressureSignal[] {
|
|
|
2214
2330
|
const artifacts = loadEvolutionArtifacts()
|
|
2215
2331
|
const governance = deriveGovernanceSummary(pressureSignals, interventions)
|
|
2216
2332
|
const concepts = activeOntologyExtensions()
|
|
2333
|
+
const proofSteering = options.includeProofSteering === false ? null : loadProofSteeringSummary()
|
|
2217
2334
|
const acceptedProposalIds = new Set(
|
|
2218
2335
|
history.iterations.flatMap((iteration) => iteration.proposals)
|
|
2219
2336
|
.filter((proposal) => proposal.outcome === 'accepted')
|
|
@@ -2259,6 +2376,7 @@ export function loadResolvedPressureSignals(): ResolvedPressureSignal[] {
|
|
|
2259
2376
|
governanceMode: governance.activeMode,
|
|
2260
2377
|
governanceProfile: governance.profile,
|
|
2261
2378
|
semanticBindings,
|
|
2379
|
+
proofSteering,
|
|
2262
2380
|
})
|
|
2263
2381
|
|
|
2264
2382
|
const lifecycle: PressureLifecycleState = addressingInterventions.length > 0 || signal.status === 'addressed'
|
|
@@ -2304,8 +2422,8 @@ function projectRoleForSkill(skillId: string, graph: SkillGraph): CognitiveRole
|
|
|
2304
2422
|
return inferCognitiveRole(node)
|
|
2305
2423
|
}
|
|
2306
2424
|
|
|
2307
|
-
export function loadPressureMotifs(): ResolvedPressureMotif[] {
|
|
2308
|
-
const resolvedSignals = loadResolvedPressureSignals()
|
|
2425
|
+
export function loadPressureMotifs(options: ProofSteeringLoadOptions = {}): ResolvedPressureMotif[] {
|
|
2426
|
+
const resolvedSignals = loadResolvedPressureSignals(options)
|
|
2309
2427
|
const interventions = loadPressureInterventions()
|
|
2310
2428
|
const transferEvents = loadTransferEvents()
|
|
2311
2429
|
const governance = deriveGovernanceSummary()
|
|
@@ -2419,7 +2537,7 @@ export function loadPressureMotifs(): ResolvedPressureMotif[] {
|
|
|
2419
2537
|
})
|
|
2420
2538
|
}
|
|
2421
2539
|
|
|
2422
|
-
function collectOntologyAdoptionState(): { summary: OntologyAdoptionSummary, consumerMap: Map<string, OntologyConsumerSummary> } {
|
|
2540
|
+
function collectOntologyAdoptionState(options: ProofSteeringLoadOptions = {}): { summary: OntologyAdoptionSummary, consumerMap: Map<string, OntologyConsumerSummary> } {
|
|
2423
2541
|
const extensions = loadOntologyExtensions()
|
|
2424
2542
|
const activeExtensions = extensions.filter((concept) => concept.status === 'active')
|
|
2425
2543
|
const byConceptKind = ontologyKindCounts()
|
|
@@ -2458,7 +2576,7 @@ function collectOntologyAdoptionState(): { summary: OntologyAdoptionSummary, con
|
|
|
2458
2576
|
byConceptKind[concept.conceptKind] = (byConceptKind[concept.conceptKind] ?? 0) + 1
|
|
2459
2577
|
}
|
|
2460
2578
|
|
|
2461
|
-
const signals = loadResolvedPressureSignals()
|
|
2579
|
+
const signals = loadResolvedPressureSignals(options)
|
|
2462
2580
|
for (const signal of signals) {
|
|
2463
2581
|
for (const binding of signal.semanticBindings ?? []) registerBinding(binding)
|
|
2464
2582
|
if (signal.routeRecommendation?.semanticConceptIds?.length) {
|
|
@@ -2478,7 +2596,7 @@ function collectOntologyAdoptionState(): { summary: OntologyAdoptionSummary, con
|
|
|
2478
2596
|
}
|
|
2479
2597
|
}
|
|
2480
2598
|
|
|
2481
|
-
for (const motif of loadPressureMotifs()) {
|
|
2599
|
+
for (const motif of loadPressureMotifs(options)) {
|
|
2482
2600
|
for (const binding of motif.semanticBindings ?? []) registerBinding(binding)
|
|
2483
2601
|
}
|
|
2484
2602
|
|
|
@@ -2517,13 +2635,13 @@ function collectOntologyAdoptionState(): { summary: OntologyAdoptionSummary, con
|
|
|
2517
2635
|
}
|
|
2518
2636
|
}
|
|
2519
2637
|
|
|
2520
|
-
export function getOntologyAdoptionSummary(): OntologyAdoptionSummary {
|
|
2521
|
-
return collectOntologyAdoptionState().summary
|
|
2638
|
+
export function getOntologyAdoptionSummary(options: ProofSteeringLoadOptions = {}): OntologyAdoptionSummary {
|
|
2639
|
+
return collectOntologyAdoptionState(options).summary
|
|
2522
2640
|
}
|
|
2523
2641
|
|
|
2524
|
-
export function loadResolvedOntologyExtensions(): ResolvedOntologyExtension[] {
|
|
2642
|
+
export function loadResolvedOntologyExtensions(options: ProofSteeringLoadOptions = {}): ResolvedOntologyExtension[] {
|
|
2525
2643
|
const extensions = loadOntologyExtensions()
|
|
2526
|
-
const { consumerMap } = collectOntologyAdoptionState()
|
|
2644
|
+
const { consumerMap } = collectOntologyAdoptionState(options)
|
|
2527
2645
|
return extensions
|
|
2528
2646
|
.map((concept) => {
|
|
2529
2647
|
const consumer = consumerMap.get(concept.id)
|