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/dashboard/lib/proof.ts
CHANGED
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
loadResolvedTopologyReviewCandidates,
|
|
11
11
|
loadResolvedOntologyExtensions,
|
|
12
12
|
type PressureIntervention,
|
|
13
|
+
type PressureInterventionType,
|
|
14
|
+
type ProofSteeringInfluence,
|
|
15
|
+
type ProofSteeringTier,
|
|
13
16
|
type ResolvedPressureSignal,
|
|
14
17
|
type ResolvedPressureMotif,
|
|
15
18
|
type ResolvedTransferEvent,
|
|
@@ -58,6 +61,8 @@ export interface ResolvedProofRecord {
|
|
|
58
61
|
relatedMotifIds?: string[]
|
|
59
62
|
relatedTransferEventIds?: string[]
|
|
60
63
|
semanticConceptIds?: string[]
|
|
64
|
+
steeringRoutes?: PressureInterventionType[]
|
|
65
|
+
steeringConceptIds?: string[]
|
|
61
66
|
recommendedAction?: string
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -85,10 +90,43 @@ export interface ProofTargetBreakdown {
|
|
|
85
90
|
insufficientEvidence: number
|
|
86
91
|
}
|
|
87
92
|
|
|
93
|
+
export interface ProofSteeringLaneSummary {
|
|
94
|
+
laneKey: string
|
|
95
|
+
laneKind: 'route' | 'semantic'
|
|
96
|
+
route?: PressureInterventionType
|
|
97
|
+
conceptId?: string
|
|
98
|
+
targetTypes: ProofTargetType[]
|
|
99
|
+
evidenceTier: ProofSteeringTier
|
|
100
|
+
score: number
|
|
101
|
+
summary: string
|
|
102
|
+
reasons: string[]
|
|
103
|
+
recordIds: string[]
|
|
104
|
+
trustedCount: number
|
|
105
|
+
cautionCount: number
|
|
106
|
+
boundedCount: number
|
|
107
|
+
candidateCount: number
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface ProofSteeringSummary {
|
|
111
|
+
trustedLanes: number
|
|
112
|
+
cautionLanes: number
|
|
113
|
+
boundedLanes: number
|
|
114
|
+
candidateLanes: number
|
|
115
|
+
priorityReview: number
|
|
116
|
+
routeLanes: ProofSteeringLaneSummary[]
|
|
117
|
+
semanticLanes: ProofSteeringLaneSummary[]
|
|
118
|
+
byRoute: Partial<Record<PressureInterventionType, ProofSteeringLaneSummary>>
|
|
119
|
+
byConceptId: Record<string, ProofSteeringLaneSummary>
|
|
120
|
+
highestPriority: ResolvedProofRecord[]
|
|
121
|
+
candidateEvidence: ResolvedProofRecord[]
|
|
122
|
+
}
|
|
123
|
+
|
|
88
124
|
export interface ProofDashboardSummary {
|
|
89
125
|
summary: ProofSummary
|
|
126
|
+
steering: ProofSteeringSummary
|
|
90
127
|
records: ResolvedProofRecord[]
|
|
91
128
|
reviewQueue: ResolvedProofRecord[]
|
|
129
|
+
candidateQueue: ResolvedProofRecord[]
|
|
92
130
|
recentVerified: ResolvedProofRecord[]
|
|
93
131
|
recentContested: ResolvedProofRecord[]
|
|
94
132
|
byTargetType: ProofTargetBreakdown[]
|
|
@@ -186,8 +224,8 @@ function latestReviewByRecord(): Map<string, ProofReviewRecord> {
|
|
|
186
224
|
}
|
|
187
225
|
|
|
188
226
|
function buildInterventionProofRecords(): ResolvedProofRecord[] {
|
|
189
|
-
const signals = loadResolvedPressureSignals()
|
|
190
|
-
const motifs = loadPressureMotifs()
|
|
227
|
+
const signals = loadResolvedPressureSignals({ includeProofSteering: false })
|
|
228
|
+
const motifs = loadPressureMotifs({ includeProofSteering: false })
|
|
191
229
|
|
|
192
230
|
return loadPressureInterventions().map((intervention) => {
|
|
193
231
|
const linkedSignals = signals.filter((signal) =>
|
|
@@ -236,6 +274,7 @@ function buildInterventionProofRecords(): ResolvedProofRecord[] {
|
|
|
236
274
|
linkedSignals: linkedSignals.length,
|
|
237
275
|
linkedMotifs: linkedMotifs.length,
|
|
238
276
|
addressed: lifecycleItems.filter((item) => item.lifecycle === 'addressed').length,
|
|
277
|
+
dryRun: intervention.status === 'dry-run' ? 1 : 0,
|
|
239
278
|
},
|
|
240
279
|
relatedProjectIds: uniqueStrings([intervention.projectId, ...linkedSignals.map((signal) => signal.projectId), ...linkedMotifs.flatMap((motif) => motif.projectIds)]),
|
|
241
280
|
relatedSignalIds: linkedSignals.map((signal) => signal.id),
|
|
@@ -245,6 +284,7 @@ function buildInterventionProofRecords(): ResolvedProofRecord[] {
|
|
|
245
284
|
...linkedSignals.flatMap((signal) => signal.semanticConceptIds ?? []),
|
|
246
285
|
...linkedMotifs.flatMap((motif) => motif.semanticConceptIds ?? []),
|
|
247
286
|
]),
|
|
287
|
+
steeringRoutes: [intervention.interventionType],
|
|
248
288
|
recommendedAction: outcomeState === 'effective'
|
|
249
289
|
? 'Verify if this resolving pattern should remain a trusted lane.'
|
|
250
290
|
: outcomeState === 'mixed'
|
|
@@ -259,8 +299,8 @@ function buildInterventionProofRecords(): ResolvedProofRecord[] {
|
|
|
259
299
|
}
|
|
260
300
|
|
|
261
301
|
function buildTransferProofRecords(): ResolvedProofRecord[] {
|
|
262
|
-
const motifs = loadPressureMotifs()
|
|
263
|
-
const signals = loadResolvedPressureSignals()
|
|
302
|
+
const motifs = loadPressureMotifs({ includeProofSteering: false })
|
|
303
|
+
const signals = loadResolvedPressureSignals({ includeProofSteering: false })
|
|
264
304
|
|
|
265
305
|
return loadTransferEvents()
|
|
266
306
|
.filter((event) => event.status === 'realized')
|
|
@@ -306,6 +346,7 @@ function buildTransferProofRecords(): ResolvedProofRecord[] {
|
|
|
306
346
|
...linkedSignals.flatMap((signal) => signal.semanticConceptIds ?? []),
|
|
307
347
|
...linkedMotifs.flatMap((motif) => motif.semanticConceptIds ?? []),
|
|
308
348
|
]),
|
|
349
|
+
steeringRoutes: ['generalize'],
|
|
309
350
|
recommendedAction: outcomeState === 'effective'
|
|
310
351
|
? 'Verify whether this transfer pattern should be treated as proven reusable evidence.'
|
|
311
352
|
: outcomeState === 'mixed'
|
|
@@ -319,8 +360,8 @@ function buildTransferProofRecords(): ResolvedProofRecord[] {
|
|
|
319
360
|
|
|
320
361
|
function buildTopologyProofRecords(): ResolvedProofRecord[] {
|
|
321
362
|
const candidatesById = new Map(loadResolvedTopologyReviewCandidates().map((candidate) => [candidate.id, candidate]))
|
|
322
|
-
const signals = loadResolvedPressureSignals()
|
|
323
|
-
const motifs = loadPressureMotifs()
|
|
363
|
+
const signals = loadResolvedPressureSignals({ includeProofSteering: false })
|
|
364
|
+
const motifs = loadPressureMotifs({ includeProofSteering: false })
|
|
324
365
|
|
|
325
366
|
return loadResolvedTopologyApplyPlans().map((plan) => {
|
|
326
367
|
const candidate = candidatesById.get(plan.candidateId)
|
|
@@ -372,6 +413,7 @@ function buildTopologyProofRecords(): ResolvedProofRecord[] {
|
|
|
372
413
|
...linkedSignals.flatMap((signal) => signal.semanticConceptIds ?? []),
|
|
373
414
|
...linkedMotifs.flatMap((motif) => motif.semanticConceptIds ?? []),
|
|
374
415
|
]),
|
|
416
|
+
steeringRoutes: ['manual-review'],
|
|
375
417
|
recommendedAction: outcomeState === 'effective'
|
|
376
418
|
? 'Verify this topology change if the structural relief looks durable.'
|
|
377
419
|
: outcomeState === 'mixed'
|
|
@@ -386,12 +428,12 @@ function buildTopologyProofRecords(): ResolvedProofRecord[] {
|
|
|
386
428
|
}
|
|
387
429
|
|
|
388
430
|
function buildOntologyProofRecords(): ResolvedProofRecord[] {
|
|
389
|
-
const signals = loadResolvedPressureSignals()
|
|
390
|
-
const motifs = loadPressureMotifs()
|
|
431
|
+
const signals = loadResolvedPressureSignals({ includeProofSteering: false })
|
|
432
|
+
const motifs = loadPressureMotifs({ includeProofSteering: false })
|
|
391
433
|
const transfers = loadTransferEvents()
|
|
392
434
|
const topologyCandidates = loadResolvedTopologyReviewCandidates()
|
|
393
435
|
|
|
394
|
-
return loadResolvedOntologyExtensions()
|
|
436
|
+
return loadResolvedOntologyExtensions({ includeProofSteering: false })
|
|
395
437
|
.filter((concept) => concept.status === 'active')
|
|
396
438
|
.map((concept) => {
|
|
397
439
|
const boundSignals = signals.filter((signal) => signal.semanticConceptIds?.includes(concept.id))
|
|
@@ -437,6 +479,7 @@ function buildOntologyProofRecords(): ResolvedProofRecord[] {
|
|
|
437
479
|
relatedMotifIds: boundMotifs.map((motif) => motif.id),
|
|
438
480
|
relatedTransferEventIds: boundTransfers.map((event) => event.id),
|
|
439
481
|
semanticConceptIds: [concept.id],
|
|
482
|
+
steeringConceptIds: [concept.id],
|
|
440
483
|
recommendedAction: outcomeState === 'effective'
|
|
441
484
|
? 'Verify this concept if semantic adoption looks stable enough to trust.'
|
|
442
485
|
: outcomeState === 'mixed'
|
|
@@ -490,6 +533,7 @@ function buildEvolutionProofRecords(): ResolvedProofRecord[] {
|
|
|
490
533
|
samplesBefore: impact.samplesBefore,
|
|
491
534
|
samplesAfter: impact.samplesAfter,
|
|
492
535
|
},
|
|
536
|
+
steeringRoutes: ['evolve'],
|
|
493
537
|
recommendedAction: outcomeState === 'effective'
|
|
494
538
|
? 'Verify this evolution result if the lower correction rate looks durable.'
|
|
495
539
|
: outcomeState === 'regressed'
|
|
@@ -501,6 +545,216 @@ function buildEvolutionProofRecords(): ResolvedProofRecord[] {
|
|
|
501
545
|
})
|
|
502
546
|
}
|
|
503
547
|
|
|
548
|
+
|
|
549
|
+
function routeLabel(route: PressureInterventionType): string {
|
|
550
|
+
return route.replace(/-/g, ' ')
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function steeringMetaForRecord(record: ResolvedProofRecord): { tier: ProofSteeringTier; score: number; summary: string } {
|
|
554
|
+
const dryRun = record.metrics?.dryRun === 1
|
|
555
|
+
if (dryRun) {
|
|
556
|
+
return {
|
|
557
|
+
tier: 'candidate',
|
|
558
|
+
score: 0,
|
|
559
|
+
summary: 'Dry-run proof remains candidate-only evidence until live downstream effects exist.',
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (record.reviewStatus === 'contested' && record.outcomeState === 'regressed') {
|
|
563
|
+
return {
|
|
564
|
+
tier: 'caution',
|
|
565
|
+
score: -4,
|
|
566
|
+
summary: 'Contested regressed proof strongly increases caution and review bias on this lane.',
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (record.reviewStatus === 'verified' && record.outcomeState === 'regressed') {
|
|
570
|
+
return {
|
|
571
|
+
tier: 'caution',
|
|
572
|
+
score: -4,
|
|
573
|
+
summary: 'Verified regressed proof strongly increases caution on this lane.',
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (record.reviewStatus === 'contested') {
|
|
577
|
+
return {
|
|
578
|
+
tier: 'caution',
|
|
579
|
+
score: -3,
|
|
580
|
+
summary: 'Contested proof should bias the system toward caution and re-review.',
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (record.outcomeState === 'regressed') {
|
|
584
|
+
return {
|
|
585
|
+
tier: 'caution',
|
|
586
|
+
score: -3,
|
|
587
|
+
summary: 'Regressed proof should make this lane less trusted until it is re-evaluated.',
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (record.reviewStatus === 'verified' && record.outcomeState === 'effective') {
|
|
591
|
+
return {
|
|
592
|
+
tier: 'trusted',
|
|
593
|
+
score: 4,
|
|
594
|
+
summary: 'Verified effective proof can strengthen trust in this lane.',
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (record.reviewStatus === 'verified' && record.outcomeState === 'mixed') {
|
|
598
|
+
return {
|
|
599
|
+
tier: 'bounded',
|
|
600
|
+
score: 1,
|
|
601
|
+
summary: 'Verified mixed proof adds signal, but still keeps steering bounded.',
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (record.outcomeState === 'effective') {
|
|
605
|
+
return {
|
|
606
|
+
tier: 'bounded',
|
|
607
|
+
score: 1,
|
|
608
|
+
summary: 'Effective evidence exists, but remains bounded until review strengthens trust.',
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (record.reviewStatus === 'deferred' || record.outcomeState === 'mixed' || record.outcomeState === 'measuring') {
|
|
612
|
+
return {
|
|
613
|
+
tier: 'bounded',
|
|
614
|
+
score: 0,
|
|
615
|
+
summary: 'This proof remains bounded and should guide review more than lane trust.',
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
tier: 'candidate',
|
|
620
|
+
score: 0,
|
|
621
|
+
summary: 'Insufficient-evidence proof stays candidate-only until stronger downstream evidence appears.',
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
type MutableProofLane = {
|
|
626
|
+
laneKey: string
|
|
627
|
+
laneKind: 'route' | 'semantic'
|
|
628
|
+
route?: PressureInterventionType
|
|
629
|
+
conceptId?: string
|
|
630
|
+
targetTypes: Set<ProofTargetType>
|
|
631
|
+
recordIds: string[]
|
|
632
|
+
reasons: string[]
|
|
633
|
+
summaries: string[]
|
|
634
|
+
score: number
|
|
635
|
+
trustedCount: number
|
|
636
|
+
cautionCount: number
|
|
637
|
+
boundedCount: number
|
|
638
|
+
candidateCount: number
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function laneTierWeight(tier: ProofSteeringTier): number {
|
|
642
|
+
return tier === 'caution' ? 4 : tier === 'trusted' ? 3 : tier === 'bounded' ? 2 : 1
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function finalizeProofLane(lane: MutableProofLane): ProofSteeringLaneSummary {
|
|
646
|
+
const evidenceTier: ProofSteeringTier = lane.cautionCount > 0 && lane.score <= -2
|
|
647
|
+
? 'caution'
|
|
648
|
+
: lane.trustedCount > 0 && lane.score >= 3
|
|
649
|
+
? 'trusted'
|
|
650
|
+
: lane.candidateCount > 0 && lane.trustedCount === 0 && lane.cautionCount === 0 && lane.boundedCount === 0
|
|
651
|
+
? 'candidate'
|
|
652
|
+
: 'bounded'
|
|
653
|
+
const label = lane.route ? routeLabel(lane.route) : lane.conceptId ?? lane.laneKey
|
|
654
|
+
const summary = evidenceTier === 'caution'
|
|
655
|
+
? `${label} now carries regressed or contested proof and should be treated more cautiously.`
|
|
656
|
+
: evidenceTier === 'trusted'
|
|
657
|
+
? `${label} now carries verified/effective proof that can strengthen trust modestly.`
|
|
658
|
+
: evidenceTier === 'candidate'
|
|
659
|
+
? `${label} currently has only dry-run or insufficient evidence and should stay bounded.`
|
|
660
|
+
: `${label} has some proof history, but steering should remain bounded.`
|
|
661
|
+
return {
|
|
662
|
+
laneKey: lane.laneKey,
|
|
663
|
+
laneKind: lane.laneKind,
|
|
664
|
+
route: lane.route,
|
|
665
|
+
conceptId: lane.conceptId,
|
|
666
|
+
targetTypes: [...lane.targetTypes.values()].sort(),
|
|
667
|
+
evidenceTier,
|
|
668
|
+
score: lane.score,
|
|
669
|
+
summary,
|
|
670
|
+
reasons: [...new Set([...lane.summaries, ...lane.reasons])].slice(0, 4),
|
|
671
|
+
recordIds: lane.recordIds,
|
|
672
|
+
trustedCount: lane.trustedCount,
|
|
673
|
+
cautionCount: lane.cautionCount,
|
|
674
|
+
boundedCount: lane.boundedCount,
|
|
675
|
+
candidateCount: lane.candidateCount,
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
export function loadProofSteeringSummary(records = loadResolvedProofRecords()): ProofSteeringSummary {
|
|
680
|
+
const routeMap = new Map<string, MutableProofLane>()
|
|
681
|
+
const conceptMap = new Map<string, MutableProofLane>()
|
|
682
|
+
const openRecords = records.filter((record) => record.reviewStatus === 'open')
|
|
683
|
+
const priorityReview = openRecords.filter((record) => steeringMetaForRecord(record).tier !== 'candidate')
|
|
684
|
+
const candidateEvidence = openRecords.filter((record) => steeringMetaForRecord(record).tier === 'candidate')
|
|
685
|
+
|
|
686
|
+
function applyToLane(lane: MutableProofLane, record: ResolvedProofRecord) {
|
|
687
|
+
const meta = steeringMetaForRecord(record)
|
|
688
|
+
lane.targetTypes.add(record.targetType)
|
|
689
|
+
lane.recordIds.push(record.id)
|
|
690
|
+
lane.score += meta.score
|
|
691
|
+
lane.reasons.push(...record.reasons.slice(0, 2))
|
|
692
|
+
lane.summaries.push(meta.summary)
|
|
693
|
+
if (meta.tier === 'trusted') lane.trustedCount += 1
|
|
694
|
+
else if (meta.tier === 'caution') lane.cautionCount += 1
|
|
695
|
+
else if (meta.tier === 'bounded') lane.boundedCount += 1
|
|
696
|
+
else lane.candidateCount += 1
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
for (const record of records) {
|
|
700
|
+
for (const route of record.steeringRoutes ?? []) {
|
|
701
|
+
const laneKey = `route:${route}`
|
|
702
|
+
const lane = routeMap.get(laneKey) ?? {
|
|
703
|
+
laneKey,
|
|
704
|
+
laneKind: 'route',
|
|
705
|
+
route,
|
|
706
|
+
targetTypes: new Set<ProofTargetType>(),
|
|
707
|
+
recordIds: [],
|
|
708
|
+
reasons: [],
|
|
709
|
+
summaries: [],
|
|
710
|
+
score: 0,
|
|
711
|
+
trustedCount: 0,
|
|
712
|
+
cautionCount: 0,
|
|
713
|
+
boundedCount: 0,
|
|
714
|
+
candidateCount: 0,
|
|
715
|
+
}
|
|
716
|
+
applyToLane(lane, record)
|
|
717
|
+
routeMap.set(laneKey, lane)
|
|
718
|
+
}
|
|
719
|
+
for (const conceptId of record.steeringConceptIds ?? []) {
|
|
720
|
+
const laneKey = `semantic:${conceptId}`
|
|
721
|
+
const lane = conceptMap.get(laneKey) ?? {
|
|
722
|
+
laneKey,
|
|
723
|
+
laneKind: 'semantic',
|
|
724
|
+
conceptId,
|
|
725
|
+
targetTypes: new Set<ProofTargetType>(),
|
|
726
|
+
recordIds: [],
|
|
727
|
+
reasons: [],
|
|
728
|
+
summaries: [],
|
|
729
|
+
score: 0,
|
|
730
|
+
trustedCount: 0,
|
|
731
|
+
cautionCount: 0,
|
|
732
|
+
boundedCount: 0,
|
|
733
|
+
candidateCount: 0,
|
|
734
|
+
}
|
|
735
|
+
applyToLane(lane, record)
|
|
736
|
+
conceptMap.set(laneKey, lane)
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const routeLanes = [...routeMap.values()].map(finalizeProofLane).sort((a, b) => laneTierWeight(b.evidenceTier) - laneTierWeight(a.evidenceTier) || Math.abs(b.score) - Math.abs(a.score) || a.laneKey.localeCompare(b.laneKey))
|
|
741
|
+
const semanticLanes = [...conceptMap.values()].map(finalizeProofLane).sort((a, b) => laneTierWeight(b.evidenceTier) - laneTierWeight(a.evidenceTier) || Math.abs(b.score) - Math.abs(a.score) || a.laneKey.localeCompare(b.laneKey))
|
|
742
|
+
|
|
743
|
+
return {
|
|
744
|
+
trustedLanes: [...routeLanes, ...semanticLanes].filter((lane) => lane.evidenceTier === 'trusted').length,
|
|
745
|
+
cautionLanes: [...routeLanes, ...semanticLanes].filter((lane) => lane.evidenceTier === 'caution').length,
|
|
746
|
+
boundedLanes: [...routeLanes, ...semanticLanes].filter((lane) => lane.evidenceTier === 'bounded').length,
|
|
747
|
+
candidateLanes: [...routeLanes, ...semanticLanes].filter((lane) => lane.evidenceTier === 'candidate').length,
|
|
748
|
+
priorityReview: priorityReview.length,
|
|
749
|
+
routeLanes,
|
|
750
|
+
semanticLanes,
|
|
751
|
+
byRoute: Object.fromEntries(routeLanes.filter((lane) => lane.route).map((lane) => [lane.route!, lane])) as Partial<Record<PressureInterventionType, ProofSteeringLaneSummary>>,
|
|
752
|
+
byConceptId: Object.fromEntries(semanticLanes.filter((lane) => lane.conceptId).map((lane) => [lane.conceptId!, lane])),
|
|
753
|
+
highestPriority: priorityReview.slice(0, 8),
|
|
754
|
+
candidateEvidence: candidateEvidence.slice(0, 8),
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
504
758
|
export function loadResolvedProofRecords(): ResolvedProofRecord[] {
|
|
505
759
|
const latestReviews = latestReviewByRecord()
|
|
506
760
|
const records = [
|
|
@@ -566,10 +820,13 @@ function buildTargetBreakdown(records: ResolvedProofRecord[]): ProofTargetBreakd
|
|
|
566
820
|
|
|
567
821
|
export function loadProofDashboardSummary(): ProofDashboardSummary {
|
|
568
822
|
const records = loadResolvedProofRecords()
|
|
823
|
+
const steering = loadProofSteeringSummary(records)
|
|
569
824
|
return {
|
|
570
825
|
summary: getProofSummary(records),
|
|
826
|
+
steering,
|
|
571
827
|
records,
|
|
572
|
-
reviewQueue:
|
|
828
|
+
reviewQueue: steering.highestPriority,
|
|
829
|
+
candidateQueue: steering.candidateEvidence,
|
|
573
830
|
recentVerified: records.filter((record) => record.reviewStatus === 'verified').slice(0, 8),
|
|
574
831
|
recentContested: records.filter((record) => record.reviewStatus === 'contested').slice(0, 8),
|
|
575
832
|
byTargetType: buildTargetBreakdown(records),
|