@validation-os/dashboard 0.16.0 → 0.16.1
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/dist/index.js +99 -22
- package/dist/index.js.map +1 -1
- package/dist/styles.css +130 -9
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
QUESTION_TYPES,
|
|
60
60
|
STAGES
|
|
61
61
|
} from "@validation-os/core";
|
|
62
|
-
import { isNonEvidence, riskThresholdForStage } from "@validation-os/core/derivation";
|
|
62
|
+
import { confidenceFloorForStage, isNonEvidence, riskThresholdForStage } from "@validation-os/core/derivation";
|
|
63
63
|
|
|
64
64
|
// src/breadcrumb.tsx
|
|
65
65
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1518,7 +1518,8 @@ function AssumptionDetail({
|
|
|
1518
1518
|
const framed = derived.completeness ?? 0;
|
|
1519
1519
|
const stageKey = STAGES.find((s) => s === stage);
|
|
1520
1520
|
const riskThreshold = stageKey ? riskThresholdForStage(stageKey) : null;
|
|
1521
|
-
const
|
|
1521
|
+
const confFloor = stageKey ? confidenceFloorForStage(stageKey) : null;
|
|
1522
|
+
const clearedThreshold = riskThreshold != null && confFloor != null ? risk <= riskThreshold && confidence2 >= confFloor : null;
|
|
1522
1523
|
const nextMove2 = nextMoveFor(record, experiments.records ?? []);
|
|
1523
1524
|
const linkedExperiments = liveExperiments(experiments.records ?? []).filter((e) => {
|
|
1524
1525
|
const ids = Array.isArray(e.barLineAssumptionIds) ? e.barLineAssumptionIds : [];
|
|
@@ -1560,24 +1561,17 @@ function AssumptionDetail({
|
|
|
1560
1561
|
/* @__PURE__ */ jsx4(ScoreCard, { label: "Confidence", value: formatSigned(confidence2) }),
|
|
1561
1562
|
/* @__PURE__ */ jsx4(ScoreCard, { label: "Framed", value: `${Math.round(framed)}%` })
|
|
1562
1563
|
] }),
|
|
1563
|
-
riskThreshold != null ? /* @__PURE__ */
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
className: `vos-threshold-status ${clearedThreshold ? "vos-threshold-cleared" : "vos-threshold-needs"}`,
|
|
1575
|
-
children: clearedThreshold ? "Cleared for this stage" : "Needs evidence"
|
|
1576
|
-
}
|
|
1577
|
-
)
|
|
1578
|
-
] }),
|
|
1579
|
-
/* @__PURE__ */ jsx4("div", { className: "vos-threshold-hint", children: clearedThreshold ? `Risk at or below the ${stage} threshold \u2014 de-prioritized.` : `Risk above the ${stage} threshold \u2014 testing-priority.` })
|
|
1580
|
-
] }) : null,
|
|
1564
|
+
riskThreshold != null ? /* @__PURE__ */ jsx4(
|
|
1565
|
+
ThresholdBar,
|
|
1566
|
+
{
|
|
1567
|
+
risk,
|
|
1568
|
+
threshold: riskThreshold,
|
|
1569
|
+
confidence: confidence2,
|
|
1570
|
+
confFloor: confFloor ?? 0,
|
|
1571
|
+
stage,
|
|
1572
|
+
cleared: clearedThreshold ?? false
|
|
1573
|
+
}
|
|
1574
|
+
) : null,
|
|
1581
1575
|
/* @__PURE__ */ jsx4(EvidenceCompositionView, { assumption: record, readings: readings.records ?? [] }),
|
|
1582
1576
|
/* @__PURE__ */ jsx4(ConfidenceExplainerView, { assumption: record, readings: readings.records ?? [] }),
|
|
1583
1577
|
statement ? /* @__PURE__ */ jsxs4("div", { className: "vos-card vos-detail-section", children: [
|
|
@@ -1800,6 +1794,88 @@ function ScoreCard({
|
|
|
1800
1794
|
/* @__PURE__ */ jsx4("div", { className: "vos-score-label", children: label })
|
|
1801
1795
|
] });
|
|
1802
1796
|
}
|
|
1797
|
+
function ThresholdBar({
|
|
1798
|
+
risk,
|
|
1799
|
+
threshold,
|
|
1800
|
+
confidence: confidence2,
|
|
1801
|
+
confFloor,
|
|
1802
|
+
stage,
|
|
1803
|
+
cleared
|
|
1804
|
+
}) {
|
|
1805
|
+
const riskTrackMax = Math.max(risk, threshold) * 1.25;
|
|
1806
|
+
const riskPct = Math.min(100, risk / riskTrackMax * 100);
|
|
1807
|
+
const thresholdPct = Math.min(100, threshold / riskTrackMax * 100);
|
|
1808
|
+
const confPct = Math.min(100, Math.abs(confidence2));
|
|
1809
|
+
const confFloorPct = Math.min(100, confFloor);
|
|
1810
|
+
const riskBelow = risk <= threshold;
|
|
1811
|
+
const confAbove = confidence2 >= confFloor;
|
|
1812
|
+
const tone = cleared ? "good" : !riskBelow && !confAbove ? "crit" : "warn";
|
|
1813
|
+
return /* @__PURE__ */ jsxs4("div", { className: "vos-card vos-threshold-bar-card", children: [
|
|
1814
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-header", children: [
|
|
1815
|
+
/* @__PURE__ */ jsxs4("span", { className: "vos-threshold-bar-title", children: [
|
|
1816
|
+
stage,
|
|
1817
|
+
" evidence bar",
|
|
1818
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-threshold-bar-stage-tag", children: stage })
|
|
1819
|
+
] }),
|
|
1820
|
+
/* @__PURE__ */ jsx4("span", { className: `vos-threshold-bar-status vos-threshold-bar-${tone}`, children: cleared ? "Cleared" : "Needs evidence" })
|
|
1821
|
+
] }),
|
|
1822
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-section", children: [
|
|
1823
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-section-label", children: [
|
|
1824
|
+
/* @__PURE__ */ jsx4("span", { children: "Risk" }),
|
|
1825
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-num vos-threshold-bar-section-val", children: Math.round(risk) }),
|
|
1826
|
+
/* @__PURE__ */ jsxs4("span", { className: "vos-threshold-bar-section-target", children: [
|
|
1827
|
+
"bar \u2264 ",
|
|
1828
|
+
threshold
|
|
1829
|
+
] })
|
|
1830
|
+
] }),
|
|
1831
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-track", children: [
|
|
1832
|
+
/* @__PURE__ */ jsx4(
|
|
1833
|
+
"div",
|
|
1834
|
+
{
|
|
1835
|
+
className: `vos-threshold-bar-fill vos-fill-${riskBelow ? "good" : tone}`,
|
|
1836
|
+
style: { width: `${riskPct}%` }
|
|
1837
|
+
}
|
|
1838
|
+
),
|
|
1839
|
+
/* @__PURE__ */ jsx4(
|
|
1840
|
+
"div",
|
|
1841
|
+
{
|
|
1842
|
+
className: "vos-threshold-bar-marker",
|
|
1843
|
+
style: { left: `${thresholdPct}%` },
|
|
1844
|
+
title: `Risk threshold: ${threshold}`
|
|
1845
|
+
}
|
|
1846
|
+
)
|
|
1847
|
+
] })
|
|
1848
|
+
] }),
|
|
1849
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-section", children: [
|
|
1850
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-section-label", children: [
|
|
1851
|
+
/* @__PURE__ */ jsx4("span", { children: "Confidence" }),
|
|
1852
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-num vos-threshold-bar-section-val", children: formatSigned(confidence2) }),
|
|
1853
|
+
/* @__PURE__ */ jsxs4("span", { className: "vos-threshold-bar-section-target", children: [
|
|
1854
|
+
"floor \u2265 ",
|
|
1855
|
+
confFloor
|
|
1856
|
+
] })
|
|
1857
|
+
] }),
|
|
1858
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-threshold-bar-track vos-threshold-bar-track-conf", children: [
|
|
1859
|
+
/* @__PURE__ */ jsx4(
|
|
1860
|
+
"div",
|
|
1861
|
+
{
|
|
1862
|
+
className: `vos-threshold-bar-fill vos-fill-${confAbove ? "good" : tone}`,
|
|
1863
|
+
style: { width: `${confPct}%` }
|
|
1864
|
+
}
|
|
1865
|
+
),
|
|
1866
|
+
/* @__PURE__ */ jsx4(
|
|
1867
|
+
"div",
|
|
1868
|
+
{
|
|
1869
|
+
className: "vos-threshold-bar-marker vos-threshold-bar-marker-conf",
|
|
1870
|
+
style: { left: `${confFloorPct}%` },
|
|
1871
|
+
title: `Confidence floor: ${confFloor}`
|
|
1872
|
+
}
|
|
1873
|
+
)
|
|
1874
|
+
] })
|
|
1875
|
+
] }),
|
|
1876
|
+
/* @__PURE__ */ jsx4("div", { className: "vos-threshold-bar-hint", children: cleared ? `Risk ${Math.round(risk)} \u2264 ${threshold} and Confidence ${formatSigned(confidence2)} \u2265 ${confFloor} \u2014 cleared for ${stage}.` : `Risk ${Math.round(risk)} ${riskBelow ? "\u2264" : ">"} ${threshold}, Confidence ${formatSigned(confidence2)} ${confAbove ? "\u2265" : "<"} ${confFloor} \u2014 needs ${!riskBelow ? "lower Risk" : ""}${!riskBelow && !confAbove ? " + " : ""}${!confAbove ? "higher Confidence" : ""}.` })
|
|
1877
|
+
] });
|
|
1878
|
+
}
|
|
1803
1879
|
function riskTone(risk) {
|
|
1804
1880
|
if (risk >= 70) return "crit";
|
|
1805
1881
|
if (risk >= 40) return "warn";
|
|
@@ -2134,7 +2210,7 @@ import {
|
|
|
2134
2210
|
assumptionCompleteness,
|
|
2135
2211
|
readingBeliefInputs
|
|
2136
2212
|
} from "@validation-os/core";
|
|
2137
|
-
import { riskThresholdForStage as riskThresholdForStage2 } from "@validation-os/core/derivation";
|
|
2213
|
+
import { confidenceFloorForStage as confidenceFloorForStage2, riskThresholdForStage as riskThresholdForStage2 } from "@validation-os/core/derivation";
|
|
2138
2214
|
|
|
2139
2215
|
// src/stage-grid-model.ts
|
|
2140
2216
|
var STAGE_ORDER = [
|
|
@@ -2334,6 +2410,7 @@ function buildPipeline(assumptions, experiments) {
|
|
|
2334
2410
|
const stageName = str3(a.Stage);
|
|
2335
2411
|
const stageKey = stageName && STAGE_ORDER.includes(stageName) ? stageName : null;
|
|
2336
2412
|
const riskThreshold = stageKey ? riskThresholdForStage2(stageKey) : null;
|
|
2413
|
+
const confFloor = stageKey ? confidenceFloorForStage2(stageKey) : null;
|
|
2337
2414
|
rows.push({
|
|
2338
2415
|
id: a.id,
|
|
2339
2416
|
statement: str3(a.Title),
|
|
@@ -2350,7 +2427,7 @@ function buildPipeline(assumptions, experiments) {
|
|
|
2350
2427
|
questionType,
|
|
2351
2428
|
stage: stageName,
|
|
2352
2429
|
riskThreshold,
|
|
2353
|
-
clearedThreshold: riskThreshold != null ? d.risk <= riskThreshold : null
|
|
2430
|
+
clearedThreshold: riskThreshold != null ? d.risk <= riskThreshold && (confFloor == null || stage.confidence >= confFloor) : null
|
|
2354
2431
|
});
|
|
2355
2432
|
}
|
|
2356
2433
|
rows.sort(
|