diff --git a/src/data/vortexopedia.ts b/src/data/vortexopedia.ts index c0f236c..7884650 100644 --- a/src/data/vortexopedia.ts +++ b/src/data/vortexopedia.ts @@ -1209,6 +1209,37 @@ export const vortexopediaTerms: VortexopediaTerm[] = [ source: "Discussion", updated: "2025-12-04", }, + { + ref: 43.1, + id: "invision_band", + name: "Invision band", + category: "governance", + short: + "A readable health label for an Invision score, grouping the raw percentage into a low, medium, or high condition.", + long: [ + "Invision engines calculate raw scores for system dimensions such as decentralization and stability.", + "The band translates that percentage into a quick status label so a user can scan the system without interpreting every component immediately.", + "The band does not replace the score. The score is the numerical result; the band is the human-readable bucket for that result.", + ], + tags: ["invision", "system_health", "score", "status", "band"], + related: [ + "gradual_decentralization", + "constant_deterrence", + "legitimacy_referendum", + ], + examples: [ + "A stability score of 28% can sit in a low band, while a score near 80% can sit in a high band.", + ], + stages: ["global"], + links: [ + { + label: "Invision", + url: "/app/invision", + }, + ], + source: "App UX: Invision system health", + updated: "2026-06-19", + }, { ref: 44, id: "voter_apathy", diff --git a/src/pages/invision/Invision.tsx b/src/pages/invision/Invision.tsx index 349b059..b9c307c 100644 --- a/src/pages/invision/Invision.tsx +++ b/src/pages/invision/Invision.tsx @@ -32,14 +32,18 @@ function toneForScore(tone: InvisionStabilityComponentDto["tone"]) { return "ok"; } -function toneForConfidence(engine: EngineDto): StatusTone { - if (engine.confidenceBand === "High" || engine.confidence >= 75) return "ok"; - if (engine.confidenceBand === "Medium" || engine.confidence >= 50) { - return "warn"; - } +function toneForHealthScore(score: number): StatusTone { + if (score >= 67) return "ok"; + if (score >= 34) return "warn"; return "danger"; } +function toneForMetricValue(value: string): StatusTone { + const percentValue = Number(value.replace("%", "").trim()); + if (!Number.isFinite(percentValue)) return "neutral"; + return toneForHealthScore(percentValue); +} + function toneForRiskStatus(status: string) { const normalized = status.trim().toLowerCase(); if (normalized === "critical") return "danger"; @@ -56,12 +60,27 @@ function EngineSection({ }) { return ( - - + + + {engine.score}% + + } + /> Band} value={ - + + {engine.band} + + } + /> + {engine.confidence}% ยท {engine.confidenceBand} } @@ -197,7 +216,11 @@ const Invision: React.FC = () => { + {metric.value} + + } /> ))} diff --git a/src/types/api.ts b/src/types/api.ts index 5811815..529d38c 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -362,6 +362,9 @@ export type GetFormationResponse = { export type InvisionGovernanceMetricDto = { label: string; value: string }; export type InvisionGovernanceStateDto = { label: string; + tone?: "critical" | "watch" | "stable" | "strong" | "unknown"; + summary?: string; + drivers?: string[]; metrics: InvisionGovernanceMetricDto[]; }; export type InvisionStabilityComponentDto = { diff --git a/tests/unit/phase89-visual-contract.test.ts b/tests/unit/phase89-visual-contract.test.ts index 5c1b67d..e7a1442 100644 --- a/tests/unit/phase89-visual-contract.test.ts +++ b/tests/unit/phase89-visual-contract.test.ts @@ -46,7 +46,8 @@ test("Phase 89 static visual contract covers public entry routes", () => { assert.match(guide, /The two UX primitives: hints and stages/); assert.match(vortexopedia, /Search terms/); - assert.match(vortexopedia, /Showing 56 \/ 56 entries/); + assert.match(vortexopedia, /Showing 57 \/ 57 entries/); + assert.match(vortexopedia, /Invision band/); assert.match(vortexopedia, /Vortex/); });