helixevo 0.9.0 → 0.10.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.
@@ -9,6 +9,7 @@ import { PageHero } from '@/components/page-hero'
9
9
  import { SectionFrame } from '@/components/section-frame'
10
10
  import { SurfaceJumpLinks } from '@/components/surface-jump-links'
11
11
  import type { ProofDashboardSummary, ProofOutcomeState, ProofReviewDecisionStatus, ProofTargetType } from '@/lib/proof'
12
+ import type { TheoryConformanceRunResult } from '@/lib/theory'
12
13
 
13
14
  type RunState = 'idle' | 'running' | 'success' | 'error'
14
15
 
@@ -46,6 +47,14 @@ function toneForSteeringTier(tier: 'trusted' | 'caution' | 'bounded' | 'candidat
46
47
  return 'neutral'
47
48
  }
48
49
 
50
+ function toneForClosureState(state: ProofDashboardSummary['records'][number]['closureState'] | ProofDashboardSummary['steering']['routeLanes'][number]['closureState']) {
51
+ if (state === 'trusted-with-debt') return 'yellow'
52
+ if (state === 'stalled') return 'yellow'
53
+ if (state === 'needs-review') return 'blue'
54
+ if (state === 'needs-evidence') return 'neutral'
55
+ return 'green'
56
+ }
57
+
49
58
  function labelForSteeringLane(lane: ProofDashboardSummary['steering']['routeLanes'][number] | ProofDashboardSummary['steering']['semanticLanes'][number]) {
50
59
  return lane.route ? lane.route.replace(/-/g, ' ') : lane.conceptId ?? lane.laneKey
51
60
  }
@@ -62,7 +71,64 @@ function consoleTone(state: RunState): 'neutral' | 'green' | 'red' | 'yellow' {
62
71
  return 'neutral'
63
72
  }
64
73
 
74
+ function toneForConformance(verdict: TheoryConformanceRunResult['verdict']) {
75
+ if (verdict === 'pass') return 'green'
76
+ if (verdict === 'bounded-pass') return 'yellow'
77
+ if (verdict === 'fail') return 'red'
78
+ return 'neutral'
79
+ }
80
+
81
+ function getConformanceHeadline(result: TheoryConformanceRunResult | null) {
82
+ if (!result) {
83
+ return {
84
+ label: 'Not run yet',
85
+ title: 'No automated brain verification recorded',
86
+ copy: 'Run helixevo verify-brain to generate the first contract-backed theory-conformance verdict for this installation.',
87
+ }
88
+ }
89
+
90
+ const failing = result.scenarios.find((scenario) => scenario.verdict === 'fail')
91
+ if (failing) {
92
+ return {
93
+ label: 'Failing scenario',
94
+ title: `${failing.scenarioId} · ${failing.title}`,
95
+ copy: failing.summary,
96
+ }
97
+ }
98
+
99
+ const bounded = result.scenarios.find((scenario) => scenario.verdict === 'bounded-pass' || scenario.verdict === 'inconclusive')
100
+ if (bounded) {
101
+ return {
102
+ label: 'Bounded scenario',
103
+ title: `${bounded.scenarioId} · ${bounded.title}`,
104
+ copy: bounded.summary,
105
+ }
106
+ }
107
+
108
+ return {
109
+ label: 'Latest run',
110
+ title: 'All executed theory scenarios passed',
111
+ copy: result.summary,
112
+ }
113
+ }
114
+
65
115
  function getRecommendedProofMove(dashboard: ProofDashboardSummary) {
116
+ const stalledGroup = dashboard.closureDebtGroups.find((group) => group.closureState === 'stalled')
117
+ if (stalledGroup) {
118
+ return {
119
+ label: 'Resolve stalled debt',
120
+ title: stalledGroup.title,
121
+ copy: 'Some proof debt has aged long enough that it now needs explicit revisit instead of passive waiting. Clear the stalled group before treating the proof layer as healthy.',
122
+ }
123
+ }
124
+ const trustedWithDebt = dashboard.steering.routeLanes.find((lane) => lane.trustedWithDebt)
125
+ if (trustedWithDebt) {
126
+ return {
127
+ label: 'Trusted, but not closed',
128
+ title: labelForSteeringLane(trustedWithDebt),
129
+ copy: trustedWithDebt.debtSummary ?? 'A trusted lane still carries unresolved debt behind it. Review the debt before treating the lane as fully settled.',
130
+ }
131
+ }
66
132
  const cautionLane = dashboard.steering.routeLanes.find((lane) => lane.evidenceTier === 'caution')
67
133
  if (cautionLane) {
68
134
  return {
@@ -79,6 +145,14 @@ function getRecommendedProofMove(dashboard: ProofDashboardSummary) {
79
145
  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.',
80
146
  }
81
147
  }
148
+ const evidenceDebt = dashboard.closureDebtGroups.find((group) => group.closureState === 'needs-evidence')
149
+ if (evidenceDebt) {
150
+ return {
151
+ label: 'Harvest missing evidence',
152
+ title: evidenceDebt.title,
153
+ copy: evidenceDebt.summary,
154
+ }
155
+ }
82
156
  if (dashboard.summary.measuring > 0) {
83
157
  return {
84
158
  label: 'Let evidence mature',
@@ -86,13 +160,6 @@ function getRecommendedProofMove(dashboard: ProofDashboardSummary) {
86
160
  copy: 'A measuring record is active but still too recent or incomplete for a stronger claim. Let downstream evidence accumulate before over-interpreting it.',
87
161
  }
88
162
  }
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
- }
96
163
  return {
97
164
  label: 'Seed proof',
98
165
  title: 'No proof targets yet',
@@ -100,12 +167,15 @@ function getRecommendedProofMove(dashboard: ProofDashboardSummary) {
100
167
  }
101
168
  }
102
169
 
103
- export default function ProofClient({ initialDashboard }: { initialDashboard: ProofDashboardSummary }) {
170
+ export default function ProofClient({ initialDashboard, initialConformance }: { initialDashboard: ProofDashboardSummary; initialConformance: TheoryConformanceRunResult | null }) {
104
171
  const [dashboard, setDashboard] = useState(initialDashboard)
105
172
  const [runState, setRunState] = useState<RunState>('idle')
106
173
  const [output, setOutput] = useState('')
107
174
  const [pendingKey, setPendingKey] = useState<string | null>(null)
108
175
  const recommendedMove = getRecommendedProofMove(dashboard)
176
+ const conformanceHeadline = getConformanceHeadline(initialConformance)
177
+ const evidenceDebtGroups = dashboard.closureDebtGroups.filter((group) => group.closureState === 'needs-evidence')
178
+ const stalledDebtGroups = dashboard.closureDebtGroups.filter((group) => group.closureState === 'stalled')
109
179
 
110
180
  const runReview = async (recordId: string, decision: ProofReviewDecisionStatus, label: string) => {
111
181
  setPendingKey(recordId)
@@ -148,10 +218,10 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
148
218
  chips={[
149
219
  { label: `${dashboard.summary.total} proof records`, tone: 'blue' },
150
220
  { 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' },
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' },
154
- { label: `${dashboard.summary.verified} verified`, tone: dashboard.summary.verified > 0 ? 'green' : 'neutral' },
221
+ { label: `${dashboard.steering.trustedWithDebtLanes} trusted with debt`, tone: dashboard.steering.trustedWithDebtLanes > 0 ? 'yellow' : 'neutral' },
222
+ { label: `${dashboard.summary.needsReview} need review`, tone: dashboard.summary.needsReview > 0 ? 'blue' : 'neutral' },
223
+ { label: `${dashboard.summary.needsEvidence} need evidence`, tone: dashboard.summary.needsEvidence > 0 ? 'neutral' : 'green' },
224
+ { label: `${dashboard.summary.stalled} stalled`, tone: dashboard.summary.stalled > 0 ? 'yellow' : 'neutral' },
155
225
  ]}
156
226
  actions={
157
227
  <div style={{ display: 'grid', gap: 12 }}>
@@ -169,12 +239,46 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
169
239
 
170
240
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 16 }}>
171
241
  <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="!" />
173
- <MetricCard label="Measuring" value={dashboard.summary.measuring} sublabel={`${dashboard.summary.insufficientEvidence} insufficient-evidence`} tone={dashboard.summary.measuring > 0 ? 'blue' : 'neutral'} icon="" />
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="" />
242
+ <MetricCard label="Trusted with debt" value={dashboard.steering.trustedWithDebtLanes} sublabel="lanes that look strong on top but still carry unresolved closure debt" tone={dashboard.steering.trustedWithDebtLanes > 0 ? 'yellow' : 'neutral'} icon="!" />
243
+ <MetricCard label="Needs review" value={dashboard.summary.needsReview} sublabel={`${dashboard.reviewQueue.length} high-leverage queue items`} tone={dashboard.summary.needsReview > 0 ? 'blue' : 'green'} icon="" />
244
+ <MetricCard label="Needs evidence" value={dashboard.summary.needsEvidence} sublabel={`${evidenceDebtGroups.length} grouped debt area${evidenceDebtGroups.length === 1 ? '' : 's'}`} tone={dashboard.summary.needsEvidence > 0 ? 'neutral' : 'green'} icon="◌" />
245
+ <MetricCard label="Stalled debt" value={dashboard.summary.stalled} sublabel={`${stalledDebtGroups.length} stalled group${stalledDebtGroups.length === 1 ? '' : 's'}`} tone={dashboard.summary.stalled > 0 ? 'yellow' : 'green'} icon="" />
176
246
  </div>
177
247
 
248
+ <SectionFrame
249
+ eyebrow="Automated brain verification"
250
+ title="Latest theory-conformance verdict"
251
+ description="The prove layer is now complemented by an explicit contract-backed verification run. This does not replace proof review; it checks whether the current brain still behaves according to the bounded theory contract."
252
+ tone="blue"
253
+ >
254
+ {initialConformance ? (
255
+ <div className="grid-2" style={{ gap: 16 }}>
256
+ <div className="hero-note-card">
257
+ <div className="hero-note-label">{conformanceHeadline.label}</div>
258
+ <div className="hero-note-title">{conformanceHeadline.title}</div>
259
+ <div className="hero-note-copy">{conformanceHeadline.copy}</div>
260
+ {initialConformance.reportPath ? (
261
+ <div className="signal-text" style={{ marginTop: 10 }}>report · {initialConformance.reportPath}</div>
262
+ ) : null}
263
+ </div>
264
+ <div style={{ display: 'grid', gap: 12 }}>
265
+ <MetricCard label="Verdict" value={initialConformance.verdict} sublabel={`${initialConformance.totals.passed} pass • ${initialConformance.totals.boundedPass} bounded • ${initialConformance.totals.failed} fail • ${initialConformance.totals.inconclusive} inconclusive`} tone={toneForConformance(initialConformance.verdict)} icon="◎" />
266
+ <MetricCard label="Scenarios" value={initialConformance.totals.scenarios} sublabel={`${initialConformance.totals.assertions} assertions across isolated + live suites`} tone="blue" icon="◇" />
267
+ <MetricCard label="Latest mode" value={initialConformance.mode} sublabel={initialConformance.releaseMode ? 'release-grade handling enabled' : 'standard operator run'} tone="purple" icon="⇄" />
268
+ <div className="signal-text">{initialConformance.nextActions[0] ?? 'Run helixevo verify-brain --verbose to inspect the full latest result.'}</div>
269
+ </div>
270
+ </div>
271
+ ) : (
272
+ <NextStepEmptyState
273
+ title="No automated verification run yet"
274
+ description="Run helixevo verify-brain to generate the first contract-backed theory-conformance verdict for this installation."
275
+ command="helixevo verify-brain --verbose"
276
+ pageLink={{ label: 'Open Commands', href: '/commands', tone: 'blue' }}
277
+ guideLink={{ label: 'Guide · Surface Map', anchor: 'surfaces', tone: 'purple' }}
278
+ />
279
+ )}
280
+ </SectionFrame>
281
+
178
282
  <SectionFrame
179
283
  eyebrow="Meaning"
180
284
  title="What these proof states mean operationally"
@@ -210,7 +314,7 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
210
314
  <div className="summary-row-main">
211
315
  <div className="summary-row-title">{labelForSteeringLane(lane)}</div>
212
316
  <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>
317
+ <div className="summary-row-meta" style={{ marginTop: 6 }}>{lane.debtSummary ?? lane.reasons[0] ?? 'Proof steering keeps this lane bounded.'}</div>
214
318
  </div>
215
319
  <span className={`hero-chip hero-chip-${toneForSteeringTier(lane.evidenceTier)}`}>{lane.evidenceTier}</span>
216
320
  </div>
@@ -219,8 +323,9 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
219
323
  </div>
220
324
  <div style={{ display: 'grid', gap: 12 }}>
221
325
  <MetricCard label="Priority review" value={dashboard.steering.priorityReview} sublabel={`${dashboard.reviewQueue.length} high-leverage queue items`} tone={dashboard.steering.priorityReview > 0 ? 'yellow' : 'green'} icon="◇" />
326
+ <MetricCard label="Evidence debt" value={dashboard.summary.needsEvidence} sublabel={`${evidenceDebtGroups.length} grouped area${evidenceDebtGroups.length === 1 ? '' : 's'} still need stronger downstream evidence`} tone={dashboard.summary.needsEvidence > 0 ? 'neutral' : 'green'} icon="◌" />
222
327
  <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>
328
+ <div className="signal-text">High-priority review and evidence debt are now separate concepts: some records already deserve review, while others still need more live downstream evidence first.</div>
224
329
  </div>
225
330
  </div>
226
331
  </SectionFrame>
@@ -235,7 +340,7 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
235
340
  <div key={entry.targetType} className="guide-dimension-card" style={{ borderLeftColor: `var(--${toneForTarget(entry.targetType) === 'neutral' ? 'text-muted' : toneForTarget(entry.targetType)})` }}>
236
341
  <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--text)' }}>{labelForTarget(entry.targetType)}</div>
237
342
  <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 8, lineHeight: 1.7 }}>
238
- {entry.total} total • {entry.effective} effective • {entry.mixed} mixed • {entry.regressed} regressed • {entry.measuring} measuring
343
+ {entry.total} total • {entry.effective} effective • {entry.mixed} mixed • {entry.regressed} regressed • {entry.needsEvidence} need evidence • {entry.needsReview} need review • {entry.stalled} stalled
239
344
  </div>
240
345
  </div>
241
346
  )) : (
@@ -281,6 +386,8 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
281
386
  {record.reasons.slice(0, 3).map((reason, idx) => (
282
387
  <div key={`${record.id}-${idx}`} className="signal-text">• {reason}</div>
283
388
  ))}
389
+ <div className="signal-text">closure · {record.closureState} · {record.closureSummary}</div>
390
+ {record.closureNeeds[0] ? <div className="signal-text">needs · {record.closureNeeds[0]}</div> : null}
284
391
  {record.recommendedAction ? <div className="signal-text">→ {record.recommendedAction}</div> : null}
285
392
  </div>
286
393
 
@@ -303,27 +410,55 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
303
410
  </SectionFrame>
304
411
 
305
412
  <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."
413
+ eyebrow="Evidence debt"
414
+ title="What proof still needs stronger evidence"
415
+ description="Repeated dry-run and low-closure records stay visible here as grouped debt areas. They should not compete with high-leverage review as if they were unrelated proof units."
309
416
  >
310
417
  <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)' }}>
418
+ {evidenceDebtGroups.length > 0 ? evidenceDebtGroups.map((group) => (
419
+ <div key={group.groupKey} style={{ padding: '14px 16px', borderRadius: 18, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.72)' }}>
313
420
  <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>
421
+ <div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{group.title}</div>
422
+ <span className="badge badge-gray">{group.recordCount} record{group.recordCount === 1 ? '' : 's'}</span>
423
+ </div>
424
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, lineHeight: 1.6 }}>{group.summary}</div>
425
+ <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>
426
+ {group.route ? <span className="badge badge-purple">{group.route}</span> : null}
427
+ {group.relatedCapabilities.slice(0, 2).map((capability) => <span key={`${group.groupKey}-${capability}`} className="badge badge-gray">{capability}</span>)}
428
+ {group.relatedMotifIds.slice(0, 2).map((motifId) => <span key={`${group.groupKey}-${motifId}`} className="badge badge-gray">{motifId.replace(/^motif_/, '')}</span>)}
316
429
  </div>
317
- <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, lineHeight: 1.6 }}>{record.summary}</div>
318
430
  <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}
431
+ {group.needs.slice(0, 2).map((need, idx) => <div key={`${group.groupKey}-need-${idx}`} className="signal-text">• {need}</div>)}
432
+ {group.examples.length > 0 ? <div className="signal-text">examples · {group.examples.join(' • ')}</div> : null}
321
433
  </div>
322
434
  </div>
323
- )) : <div className="signal-text">No candidate-only proof records right now.</div>}
435
+ )) : <div className="signal-text">No current evidence debt groups. The proof layer is either empty or stronger records are already moving into review/settled paths.</div>}
324
436
  </div>
325
437
  </SectionFrame>
326
438
 
439
+ {stalledDebtGroups.length > 0 ? (
440
+ <SectionFrame
441
+ eyebrow="Stalled debt"
442
+ title="Proof that is aging without closure"
443
+ description="These debt groups have remained open long enough that the operator should explicitly revisit them instead of assuming more time alone will improve the proof state."
444
+ >
445
+ <div style={{ display: 'grid', gap: 10 }}>
446
+ {stalledDebtGroups.map((group) => (
447
+ <div key={group.groupKey} style={{ padding: '14px 16px', borderRadius: 18, border: '1px solid var(--border)', background: 'rgba(255,255,255,0.72)' }}>
448
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
449
+ <div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{group.title}</div>
450
+ <span className="badge badge-yellow">stalled</span>
451
+ </div>
452
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, lineHeight: 1.6 }}>{group.summary}</div>
453
+ <div style={{ display: 'grid', gap: 6, marginTop: 10 }}>
454
+ {group.needs.slice(0, 2).map((need, idx) => <div key={`${group.groupKey}-stalled-${idx}`} className="signal-text">• {need}</div>)}
455
+ </div>
456
+ </div>
457
+ ))}
458
+ </div>
459
+ </SectionFrame>
460
+ ) : null}
461
+
327
462
  <div className="grid-2">
328
463
  <SectionFrame
329
464
  eyebrow="Verified"
@@ -389,8 +524,11 @@ export default function ProofClient({ initialDashboard }: { initialDashboard: Pr
389
524
  <span className={`badge badge-${toneForTarget(record.targetType)}`}>{labelForTarget(record.targetType)}</span>
390
525
  <span className={`badge badge-${toneForOutcome(record.outcomeState)}`}>{labelForOutcome(record.outcomeState)}</span>
391
526
  <span className="badge badge-gray">{record.reviewStatus}</span>
527
+ <span className={`badge badge-${toneForClosureState(record.closureState)}`}>{record.closureState}</span>
392
528
  </div>
393
529
  </div>
530
+ <div className="signal-text" style={{ marginTop: 10 }}>closure · {record.closureSummary}</div>
531
+ {record.closureNeeds[0] ? <div className="signal-text" style={{ marginTop: 6 }}>needs · {record.closureNeeds[0]}</div> : null}
394
532
  {record.latestReview?.rationale ? <div className="signal-text" style={{ marginTop: 10 }}>review rationale · {record.latestReview.rationale}</div> : null}
395
533
  </div>
396
534
  )) : null}
@@ -1,9 +1,11 @@
1
1
  import ProofClient from './client'
2
2
  import { loadProofDashboardSummary } from '@/lib/proof'
3
+ import { loadLatestTheoryConformanceResult } from '@/lib/theory'
3
4
 
4
5
  export const dynamic = 'force-dynamic'
5
6
 
6
7
  export default function ProofPage() {
7
8
  const dashboard = loadProofDashboardSummary()
8
- return <ProofClient initialDashboard={dashboard} />
9
+ const conformance = loadLatestTheoryConformanceResult()
10
+ return <ProofClient initialDashboard={dashboard} initialConformance={conformance} />
9
11
  }
@@ -199,6 +199,8 @@ export interface PressureRouteRecommendation {
199
199
  proofSummary?: string
200
200
  proofReasons?: string[]
201
201
  proofLaneKeys?: string[]
202
+ proofClosureState?: import('./proof').ProofLaneClosureState
203
+ proofDebtSummary?: string
202
204
  }
203
205
 
204
206
  export interface PressureIntervention {
@@ -1442,7 +1444,7 @@ export function loadResolvedTopologyApplyPlans(): ResolvedTopologyApplyPlan[] {
1442
1444
  const existing = latestByPlan.get(record.planId)
1443
1445
  const recordAt = record.executedAt ?? record.rolledBackAt ?? record.createdAt
1444
1446
  const existingAt = existing ? (existing.executedAt ?? existing.rolledBackAt ?? existing.createdAt) : ''
1445
- if (!existing || recordAt > existingAt) latestByPlan.set(record.planId, record)
1447
+ if (!existing || recordAt >= existingAt) latestByPlan.set(record.planId, record)
1446
1448
  }
1447
1449
  return plans
1448
1450
  .map((plan) => {
@@ -2054,6 +2056,19 @@ function strongerProofTier(current: ProofSteeringTier | undefined, next: ProofSt
2054
2056
  return proofTierWeight(next) > proofTierWeight(current) ? next : current
2055
2057
  }
2056
2058
 
2059
+ function proofClosureWeight(state: import('./proof').ProofLaneClosureState | undefined): number {
2060
+ if (state === 'trusted-with-debt') return 5
2061
+ if (state === 'stalled') return 4
2062
+ if (state === 'needs-review') return 3
2063
+ if (state === 'needs-evidence') return 2
2064
+ return 1
2065
+ }
2066
+
2067
+ function strongerProofClosureState(current: import('./proof').ProofLaneClosureState | undefined, next: import('./proof').ProofLaneClosureState): import('./proof').ProofLaneClosureState {
2068
+ if (!current) return next
2069
+ return proofClosureWeight(next) > proofClosureWeight(current) ? next : current
2070
+ }
2071
+
2057
2072
  function applyProofInfluenceToRoute(params: {
2058
2073
  recommendation: PressureRouteRecommendation
2059
2074
  signal: PressureSignal
@@ -2071,6 +2086,8 @@ function applyProofInfluenceToRoute(params: {
2071
2086
  const proofLaneKeys: string[] = []
2072
2087
  let proofSummary: string | undefined
2073
2088
  let proofTier: ProofSteeringTier | undefined
2089
+ let proofClosureState: import('./proof').ProofLaneClosureState | undefined
2090
+ let proofDebtSummary: string | undefined
2074
2091
  let proofInfluence: 'none' | 'explanatory' | 'weighted' = 'none'
2075
2092
 
2076
2093
  const routeLane = proofSteering.byRoute[recommendation.route]
@@ -2079,11 +2096,14 @@ function applyProofInfluenceToRoute(params: {
2079
2096
  proofReasons.push(...routeLane.reasons.slice(0, 2))
2080
2097
  proofSummary = proofSummary ?? routeLane.summary
2081
2098
  proofTier = strongerProofTier(proofTier, routeLane.evidenceTier)
2099
+ proofClosureState = strongerProofClosureState(proofClosureState, routeLane.closureState)
2100
+ proofDebtSummary = proofDebtSummary ?? routeLane.debtSummary
2082
2101
 
2083
2102
  if (routeLane.evidenceTier === 'trusted') {
2084
- confidence = Math.min(0.95, confidence + (routeLane.score >= 4 ? 0.06 : 0.04))
2103
+ confidence = Math.min(0.95, confidence + (routeLane.trustedWithDebt ? 0.04 : routeLane.score >= 4 ? 0.06 : 0.04))
2085
2104
  proofInfluence = 'weighted'
2086
2105
  reasons.push(`Proof steering: ${routeLane.summary}`)
2106
+ if (routeLane.debtSummary) reasons.push(`Proof debt: ${routeLane.debtSummary}`)
2087
2107
  } else if (routeLane.evidenceTier === 'caution') {
2088
2108
  if (recommendation.route !== 'manual-review' && routeLane.score <= -3 && (recommendation.route === 'generalize' || recommendation.route === 'evolve')) {
2089
2109
  route = 'manual-review'
@@ -2091,14 +2111,17 @@ function applyProofInfluenceToRoute(params: {
2091
2111
  confidence = Math.max(0.66, confidence - 0.02)
2092
2112
  proofInfluence = 'weighted'
2093
2113
  reasons.push(`Proof steering: ${routeLane.summary} Governance now prefers explicit operator review before retrying ${recommendation.route}.`)
2114
+ if (routeLane.debtSummary) reasons.push(`Proof debt: ${routeLane.debtSummary}`)
2094
2115
  } else {
2095
2116
  confidence = Math.max(0.4, confidence - 0.08)
2096
2117
  proofInfluence = 'weighted'
2097
2118
  reasons.push(`Proof steering: ${routeLane.summary}`)
2119
+ if (routeLane.debtSummary) reasons.push(`Proof debt: ${routeLane.debtSummary}`)
2098
2120
  }
2099
2121
  } else {
2100
2122
  if (proofInfluence === 'none') proofInfluence = 'explanatory'
2101
2123
  reasons.push(`Proof steering: ${routeLane.summary}`)
2124
+ if (routeLane.debtSummary) reasons.push(`Proof debt: ${routeLane.debtSummary}`)
2102
2125
  }
2103
2126
  }
2104
2127
 
@@ -2111,10 +2134,13 @@ function applyProofInfluenceToRoute(params: {
2111
2134
  proofReasons.push(...strongestConceptLane.reasons.slice(0, 2))
2112
2135
  proofSummary = proofSummary ?? strongestConceptLane.summary
2113
2136
  proofTier = strongerProofTier(proofTier, strongestConceptLane.evidenceTier)
2137
+ proofClosureState = strongerProofClosureState(proofClosureState, strongestConceptLane.closureState)
2138
+ proofDebtSummary = proofDebtSummary ?? strongestConceptLane.debtSummary
2114
2139
  if (strongestConceptLane.evidenceTier === 'trusted') {
2115
- confidence = Math.min(0.95, confidence + 0.02)
2140
+ confidence = Math.min(0.95, confidence + (strongestConceptLane.trustedWithDebt ? 0.01 : 0.02))
2116
2141
  proofInfluence = 'weighted'
2117
2142
  reasons.push(`Proof steering: ${strongestConceptLane.summary}`)
2143
+ if (strongestConceptLane.debtSummary) reasons.push(`Proof debt: ${strongestConceptLane.debtSummary}`)
2118
2144
  } else if (strongestConceptLane.evidenceTier === 'caution') {
2119
2145
  confidence = Math.max(0.4, confidence - 0.03)
2120
2146
  if (proofInfluence === 'none') proofInfluence = 'weighted'
@@ -2137,6 +2163,8 @@ function applyProofInfluenceToRoute(params: {
2137
2163
  proofSummary,
2138
2164
  proofReasons: [...new Set(proofReasons)].slice(0, 4),
2139
2165
  proofLaneKeys: [...new Set(proofLaneKeys)],
2166
+ proofClosureState,
2167
+ proofDebtSummary,
2140
2168
  }
2141
2169
  }
2142
2170