@validation-os/dashboard 0.15.3 → 0.15.5
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.d.ts +2 -0
- package/dist/index.js +335 -170
- package/dist/index.js.map +1 -1
- package/dist/styles.css +170 -58
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,14 +9,14 @@ var REGISTER_LABEL = {
|
|
|
9
9
|
// One container-agnostic lens now Goal is unified into Experiment (OPS-1299 /
|
|
10
10
|
// OPS-1287 story 22): all plans browse in one place under this label.
|
|
11
11
|
experiments: "Evidence plans",
|
|
12
|
-
readings: "
|
|
12
|
+
readings: "Evidence",
|
|
13
13
|
decisions: "Decisions",
|
|
14
14
|
glossary: "Glossary"
|
|
15
15
|
};
|
|
16
16
|
var REGISTER_SINGULAR = {
|
|
17
17
|
assumptions: "Assumption",
|
|
18
18
|
experiments: "Evidence plan",
|
|
19
|
-
readings: "
|
|
19
|
+
readings: "Evidence",
|
|
20
20
|
decisions: "Decision",
|
|
21
21
|
glossary: "Glossary term"
|
|
22
22
|
};
|
|
@@ -37,7 +37,7 @@ var REGISTER_SUBTITLE = {
|
|
|
37
37
|
var REGISTER_ICON = {
|
|
38
38
|
assumptions: "\u25CE",
|
|
39
39
|
experiments: "\u2697",
|
|
40
|
-
readings: "\
|
|
40
|
+
readings: "\u2726",
|
|
41
41
|
decisions: "\xA7",
|
|
42
42
|
glossary: "A"
|
|
43
43
|
};
|
|
@@ -50,7 +50,7 @@ var REGISTER_GROUPS = [
|
|
|
50
50
|
var WORKFLOW_NAV = [
|
|
51
51
|
{ route: "assumptions", label: "Assumptions", icon: "\u25CE", isDefault: true },
|
|
52
52
|
{ route: "experiments", label: "Experiments", icon: "\u2697" },
|
|
53
|
-
{ route: "readings", label: "
|
|
53
|
+
{ route: "readings", label: "Evidence", icon: "\u2726" }
|
|
54
54
|
];
|
|
55
55
|
|
|
56
56
|
// src/assumption-detail.tsx
|
|
@@ -218,6 +218,47 @@ function buildEvidenceComposition(assumption, readings) {
|
|
|
218
218
|
totalContribution: Math.round((total + Number.EPSILON) * 100) / 100
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
|
+
function readingContributions(assumption, readings) {
|
|
222
|
+
const id = str(assumption.id) ?? "";
|
|
223
|
+
const inputs = [];
|
|
224
|
+
for (const r of readings) {
|
|
225
|
+
const belief2 = readingBeliefFor(r, id);
|
|
226
|
+
if (!belief2) continue;
|
|
227
|
+
const result = str(belief2.Result) ?? "Inconclusive";
|
|
228
|
+
if (result === "Inconclusive") continue;
|
|
229
|
+
const rung = str(r.Rung) ?? "Talk";
|
|
230
|
+
inputs.push({
|
|
231
|
+
id: str(r.id) ?? "",
|
|
232
|
+
source: str(r.Source) ?? null,
|
|
233
|
+
rung,
|
|
234
|
+
result,
|
|
235
|
+
representativeness: Number(r.Representativeness) || 1,
|
|
236
|
+
credibility: Number(r.Credibility) || 1,
|
|
237
|
+
date: str(r.Date),
|
|
238
|
+
magnitudeBand: r.magnitudeBand,
|
|
239
|
+
experimentId: str(r.experimentId)
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
const winners = scoreAndDedupe(inputs);
|
|
243
|
+
const winnerIds = new Set(winners.map((w) => w.input.id));
|
|
244
|
+
const rungsPresent = new Set(winners.map((x) => x.input.rung));
|
|
245
|
+
let den = 0;
|
|
246
|
+
for (const rung of rungsPresent) den += w0ForRung(rung);
|
|
247
|
+
for (const x of winners) den += x.weight;
|
|
248
|
+
return inputs.map((input) => {
|
|
249
|
+
const w = winners.find((x) => x.input.id === input.id);
|
|
250
|
+
const used = winnerIds.has(input.id);
|
|
251
|
+
const strength = w ? w.strength : (input.result === "Validated" ? 1 : input.result === "Invalidated" ? -1 : 0) * (RUNG_CAPS[input.rung] ?? 0);
|
|
252
|
+
const weight = w ? w.weight : 0;
|
|
253
|
+
return {
|
|
254
|
+
id: input.id,
|
|
255
|
+
contribution: w && den > 0 ? Math.round(w.weight * w.strength / den * 100) / 100 : 0,
|
|
256
|
+
weight,
|
|
257
|
+
strength,
|
|
258
|
+
used
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
}
|
|
221
262
|
|
|
222
263
|
// src/confidence-explainer.ts
|
|
223
264
|
import { RUNG_ANCHOR, W0_BY_RUNG } from "@validation-os/core/derivation";
|
|
@@ -1004,10 +1045,26 @@ function readingBeliefVerdicts(reading, assumptions = []) {
|
|
|
1004
1045
|
linked: hit != null,
|
|
1005
1046
|
result: b.Result ?? null,
|
|
1006
1047
|
strength,
|
|
1007
|
-
justification: typeof b["Grading justification"] === "string" ? b["Grading justification"] : ""
|
|
1048
|
+
justification: typeof b["Grading justification"] === "string" ? b["Grading justification"] : "",
|
|
1049
|
+
excerpt: typeof b.excerpt === "string" && b.excerpt !== "" ? b.excerpt : snippetFromBody(String(reading.body ?? ""), b.assumptionId)
|
|
1008
1050
|
};
|
|
1009
1051
|
});
|
|
1010
1052
|
}
|
|
1053
|
+
function snippetFromBody(body, cue) {
|
|
1054
|
+
if (!body) return "";
|
|
1055
|
+
const quoteMatch = body.match(/## Quote\n+([\s\S]*?)(?=\n## |\n##$|$)/i);
|
|
1056
|
+
if (quoteMatch) {
|
|
1057
|
+
const q = quoteMatch[1].trim();
|
|
1058
|
+
return q.length > 220 ? q.slice(0, 217).trim() + "\u2026" : q;
|
|
1059
|
+
}
|
|
1060
|
+
const sentences = body.split(/(?<=[.!?])\s+/);
|
|
1061
|
+
const cueLower = cue.toLowerCase();
|
|
1062
|
+
for (const s of sentences) {
|
|
1063
|
+
if (s.toLowerCase().includes(cueLower)) return s.trim();
|
|
1064
|
+
}
|
|
1065
|
+
const first = sentences[0]?.trim() ?? "";
|
|
1066
|
+
return first.length > 220 ? first.slice(0, 217).trim() + "\u2026" : first;
|
|
1067
|
+
}
|
|
1011
1068
|
function readingBeliefSummary(reading, assumptions = []) {
|
|
1012
1069
|
const verdicts = readingBeliefVerdicts(reading, assumptions);
|
|
1013
1070
|
let validated = 0;
|
|
@@ -1554,64 +1611,118 @@ function AssumptionDetail({
|
|
|
1554
1611
|
);
|
|
1555
1612
|
})
|
|
1556
1613
|
] }) : null,
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1614
|
+
/* @__PURE__ */ jsx4(
|
|
1615
|
+
EvidenceList,
|
|
1616
|
+
{
|
|
1617
|
+
assumptionId,
|
|
1618
|
+
readings: readings.records ?? [],
|
|
1619
|
+
onNavigate
|
|
1620
|
+
}
|
|
1621
|
+
)
|
|
1622
|
+
] });
|
|
1623
|
+
}
|
|
1624
|
+
function EvidenceList({
|
|
1625
|
+
assumptionId,
|
|
1626
|
+
readings,
|
|
1627
|
+
onNavigate
|
|
1628
|
+
}) {
|
|
1629
|
+
const linkedReadings = readings.filter((r) => readingBeliefs(r).some((b) => b.assumptionId === assumptionId)).sort((a, b) => String(b.Date ?? "").localeCompare(String(a.Date ?? "")));
|
|
1630
|
+
const contribById = useMemo(() => {
|
|
1631
|
+
const rec = readings.find((a) => String(a.id) === assumptionId);
|
|
1632
|
+
if (!rec) return /* @__PURE__ */ new Map();
|
|
1633
|
+
const rows = readingContributions(rec, readings);
|
|
1634
|
+
return new Map(rows.map((r) => [r.id, r]));
|
|
1635
|
+
}, [readings, assumptionId]);
|
|
1636
|
+
if (linkedReadings.length === 0) return null;
|
|
1637
|
+
return /* @__PURE__ */ jsxs4("div", { className: "vos-card vos-detail-section", children: [
|
|
1638
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-detail-section-label", children: [
|
|
1639
|
+
"Evidence \xB7 ",
|
|
1640
|
+
linkedReadings.length,
|
|
1641
|
+
" piece",
|
|
1642
|
+
linkedReadings.length === 1 ? "" : "s",
|
|
1643
|
+
" of evidence"
|
|
1644
|
+
] }),
|
|
1645
|
+
linkedReadings.map((r) => {
|
|
1646
|
+
const id = String(r.id ?? "");
|
|
1647
|
+
const belief2 = readingBeliefFor(r, assumptionId);
|
|
1648
|
+
if (!belief2) return null;
|
|
1649
|
+
const result = String(belief2.Result ?? "Inconclusive");
|
|
1650
|
+
const justification = String(belief2["Grading justification"] ?? "");
|
|
1651
|
+
const excerpt = typeof belief2.excerpt === "string" && belief2.excerpt !== "" ? belief2.excerpt : snippetFromBody2(String(r.body ?? ""), assumptionId);
|
|
1652
|
+
const rung = String(r.Rung ?? "");
|
|
1653
|
+
const source = String(r.Source ?? "");
|
|
1654
|
+
const expId = r.experimentId ? String(r.experimentId) : null;
|
|
1655
|
+
const c = contribById.get(id);
|
|
1656
|
+
return /* @__PURE__ */ jsxs4(
|
|
1657
|
+
"button",
|
|
1658
|
+
{
|
|
1659
|
+
type: "button",
|
|
1660
|
+
className: `vos-evidence-row vos-verdict-${verdictTone(result)}`,
|
|
1661
|
+
onClick: () => onNavigate({ name: "reading", id }),
|
|
1662
|
+
children: [
|
|
1663
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-evidence-row-head", children: [
|
|
1664
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-evidence-date vos-num", children: String(r.Date ?? "") }),
|
|
1665
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-evidence-title", children: String(r.Title ?? id) }),
|
|
1666
|
+
/* @__PURE__ */ jsx4("span", { className: `vos-pill vos-pill-${verdictTone(result)}`, children: result }),
|
|
1667
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-rung-tag", children: rung }),
|
|
1668
|
+
c && c.used ? /* @__PURE__ */ jsxs4("span", { className: `vos-evidence-score vos-num vos-text-${contributionTone(c.contribution)}`, children: [
|
|
1669
|
+
formatSigned(c.contribution),
|
|
1670
|
+
" confidence"
|
|
1671
|
+
] }) : null
|
|
1672
|
+
] }),
|
|
1673
|
+
excerpt ? /* @__PURE__ */ jsxs4("div", { className: "vos-evidence-excerpt", children: [
|
|
1674
|
+
"\u201C",
|
|
1675
|
+
excerpt,
|
|
1676
|
+
"\u201D"
|
|
1677
|
+
] }) : null,
|
|
1678
|
+
justification ? /* @__PURE__ */ jsxs4("div", { className: `vos-belief-rationale vos-verdict-border-${verdictTone(result)}`, children: [
|
|
1679
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-belief-rationale-label", children: "grading rationale:" }),
|
|
1680
|
+
justification
|
|
1681
|
+
] }) : null,
|
|
1682
|
+
/* @__PURE__ */ jsxs4("div", { className: "vos-evidence-source", children: [
|
|
1683
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-evidence-source-link", title: source, children: source }),
|
|
1684
|
+
expId ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1685
|
+
" \xB7 from experiment ",
|
|
1686
|
+
/* @__PURE__ */ jsx4(
|
|
1687
|
+
"span",
|
|
1688
|
+
{
|
|
1689
|
+
className: "vos-link",
|
|
1690
|
+
onClick: (ev) => {
|
|
1691
|
+
ev.stopPropagation();
|
|
1692
|
+
onNavigate({ name: "experiment", id: expId });
|
|
1693
|
+
},
|
|
1694
|
+
children: expId
|
|
1695
|
+
}
|
|
1696
|
+
)
|
|
1697
|
+
] }) : null
|
|
1698
|
+
] })
|
|
1699
|
+
]
|
|
1700
|
+
},
|
|
1701
|
+
id
|
|
1702
|
+
);
|
|
1703
|
+
})
|
|
1613
1704
|
] });
|
|
1614
1705
|
}
|
|
1706
|
+
function contributionTone(v) {
|
|
1707
|
+
if (v > 0) return "good";
|
|
1708
|
+
if (v < 0) return "crit";
|
|
1709
|
+
return "neutral";
|
|
1710
|
+
}
|
|
1711
|
+
function snippetFromBody2(body, cue) {
|
|
1712
|
+
if (!body) return "";
|
|
1713
|
+
const quoteMatch = body.match(/## Quote\n+([\s\S]*?)(?=\n## |\n##$|$)/i);
|
|
1714
|
+
if (quoteMatch) {
|
|
1715
|
+
const q = quoteMatch[1].trim();
|
|
1716
|
+
return q.length > 220 ? q.slice(0, 217).trim() + "\u2026" : q;
|
|
1717
|
+
}
|
|
1718
|
+
const sentences = body.split(/(?<=[.!?])\s+/);
|
|
1719
|
+
const cueLower = cue.toLowerCase();
|
|
1720
|
+
for (const s of sentences) {
|
|
1721
|
+
if (s.toLowerCase().includes(cueLower)) return s.trim();
|
|
1722
|
+
}
|
|
1723
|
+
const first = sentences[0]?.trim() ?? "";
|
|
1724
|
+
return first.length > 220 ? first.slice(0, 217).trim() + "\u2026" : first;
|
|
1725
|
+
}
|
|
1615
1726
|
function ScoreCard({
|
|
1616
1727
|
label,
|
|
1617
1728
|
value,
|
|
@@ -1781,16 +1892,24 @@ function EvidenceCompositionView({
|
|
|
1781
1892
|
" (adds to Confidence)"
|
|
1782
1893
|
] }),
|
|
1783
1894
|
comp.rungs.length === 0 ? /* @__PURE__ */ jsx4("div", { className: "vos-muted", children: "No lens set \u2014 evidence composition needs a lens." }) : comp.rungs.map((r) => {
|
|
1784
|
-
const
|
|
1895
|
+
const abs = Math.abs(r.contribution);
|
|
1896
|
+
const pct2 = r.cap > 0 ? Math.min(100, abs / r.cap * 100) : 0;
|
|
1785
1897
|
const isEmpty = r.count === 0;
|
|
1898
|
+
const tone = r.contribution > 0 ? "good" : r.contribution < 0 ? "crit" : "accent";
|
|
1786
1899
|
return /* @__PURE__ */ jsxs4("div", { className: "vos-comp-row", children: [
|
|
1787
1900
|
/* @__PURE__ */ jsx4("span", { className: `vos-comp-rung ${isEmpty ? "is-empty" : ""}`, children: r.rung }),
|
|
1788
|
-
/* @__PURE__ */ jsx4("div", { className: "vos-comp-bar", children: /* @__PURE__ */ jsx4("i", { className:
|
|
1789
|
-
/* @__PURE__ */ jsx4("span", { className: "vos-comp-val vos-num", children: isEmpty ? "\u2014" :
|
|
1901
|
+
/* @__PURE__ */ jsx4("div", { className: "vos-comp-bar", children: /* @__PURE__ */ jsx4("i", { className: `vos-comp-fill vos-fill-${tone}`, style: { width: `${isEmpty ? 0 : Math.max(4, pct2)}%` } }) }),
|
|
1902
|
+
/* @__PURE__ */ jsx4("span", { className: "vos-comp-val vos-num", children: isEmpty ? "\u2014" : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1903
|
+
/* @__PURE__ */ jsx4("span", { className: `vos-text-${tone}`, children: formatSigned(r.contribution) }),
|
|
1904
|
+
/* @__PURE__ */ jsxs4("span", { style: { color: "var(--vos-faint)" }, children: [
|
|
1905
|
+
" \xB7 cap ",
|
|
1906
|
+
r.cap
|
|
1907
|
+
] })
|
|
1908
|
+
] }) }),
|
|
1790
1909
|
/* @__PURE__ */ jsxs4("span", { className: "vos-comp-count vos-num", children: [
|
|
1791
1910
|
r.count,
|
|
1792
|
-
"
|
|
1793
|
-
r.count === 1 ? "" : "
|
|
1911
|
+
" ",
|
|
1912
|
+
r.count === 1 ? "source" : "sources"
|
|
1794
1913
|
] })
|
|
1795
1914
|
] }, r.rung);
|
|
1796
1915
|
})
|
|
@@ -2099,9 +2218,14 @@ function weekOverWeekDelta(assumptions, readings, now) {
|
|
|
2099
2218
|
}
|
|
2100
2219
|
|
|
2101
2220
|
// src/recommended-experiments.ts
|
|
2102
|
-
var MAX_RECOMMENDED =
|
|
2221
|
+
var MAX_RECOMMENDED = 3;
|
|
2103
2222
|
var MAX_CLUSTER_SIZE = 3;
|
|
2104
|
-
var MAX_NEEDS_FRAMING =
|
|
2223
|
+
var MAX_NEEDS_FRAMING = 3;
|
|
2224
|
+
var LENS_COLOUR = {
|
|
2225
|
+
Consumer: "#8b83f5",
|
|
2226
|
+
Commercial: "#38c793",
|
|
2227
|
+
Investor: "#e6a23c"
|
|
2228
|
+
};
|
|
2105
2229
|
function buildNeedsFraming(assumptions) {
|
|
2106
2230
|
const live = assumptions.filter((a) => {
|
|
2107
2231
|
const status = str(a.Status);
|
|
@@ -2116,9 +2240,17 @@ function buildNeedsFraming(assumptions) {
|
|
|
2116
2240
|
const stage = str(a.Stage) ?? "\u2014";
|
|
2117
2241
|
const title = str(a.Title) ?? id;
|
|
2118
2242
|
const hint = framingHint(a, completeness);
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2243
|
+
const lensColour = LENS_COLOUR[lens] ?? LENS_COLOUR["Investor"] ?? "#6b7484";
|
|
2244
|
+
return { id, title, risk, completeness, lens, stage, hint, lensColour };
|
|
2245
|
+
}).filter((a) => a.completeness < 100);
|
|
2246
|
+
const byLens = /* @__PURE__ */ new Map();
|
|
2247
|
+
for (const item of items) {
|
|
2248
|
+
const existing = byLens.get(item.lens);
|
|
2249
|
+
if (!existing || item.risk > existing.risk) {
|
|
2250
|
+
byLens.set(item.lens, item);
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
return [...byLens.values()].sort((a, b) => b.risk - a.risk).slice(0, MAX_NEEDS_FRAMING);
|
|
2122
2254
|
}
|
|
2123
2255
|
function framingHint(a, completeness) {
|
|
2124
2256
|
const hasScoring = Boolean(str(a["Scoring justification"]));
|
|
@@ -2159,22 +2291,28 @@ function buildRecommendedExperiments(assumptions, experiments) {
|
|
|
2159
2291
|
if (bucket) bucket.push(a);
|
|
2160
2292
|
else clusters.set(key, [a]);
|
|
2161
2293
|
}
|
|
2162
|
-
const
|
|
2294
|
+
const rankedClusters = [...clusters.entries()].map(([key, cluster]) => {
|
|
2163
2295
|
const ranked = cluster.sort((a, b) => (derivedNum(b, "risk") ?? 0) - (derivedNum(a, "risk") ?? 0)).slice(0, MAX_CLUSTER_SIZE);
|
|
2164
2296
|
const maxRisk = Math.max(...ranked.map((a) => derivedNum(a, "risk") ?? 0), 0);
|
|
2165
2297
|
return { key, cluster: ranked, maxRisk };
|
|
2166
|
-
}).sort((a, b) => b.maxRisk - a.maxRisk)
|
|
2298
|
+
}).sort((a, b) => b.maxRisk - a.maxRisk);
|
|
2299
|
+
const byLens = /* @__PURE__ */ new Map();
|
|
2300
|
+
for (const entry of rankedClusters) {
|
|
2301
|
+
const lens = entry.key.split("\xD7")[0] ?? "\u2014";
|
|
2302
|
+
if (!byLens.has(lens)) byLens.set(lens, entry);
|
|
2303
|
+
}
|
|
2304
|
+
const clusterEntries = [...byLens.values()].sort((a, b) => b.maxRisk - a.maxRisk).slice(0, MAX_RECOMMENDED);
|
|
2167
2305
|
const recs = [];
|
|
2168
2306
|
for (const { key, cluster, maxRisk } of clusterEntries) {
|
|
2169
2307
|
const lens = key.split("\xD7")[0] ?? "\u2014";
|
|
2170
2308
|
const stage = key.split("\xD7")[1] ?? "\u2014";
|
|
2171
2309
|
const assumptionIds = cluster.map((a) => str(a.id) ?? "").filter(Boolean).sort();
|
|
2172
2310
|
const type = LENS_TO_TYPE[lens ?? ""] ?? "Desk research";
|
|
2173
|
-
const titles = cluster.map((a) => str(a.Title) ?? str(a.id) ?? "");
|
|
2174
2311
|
const title = cluster.length === 1 ? `Test ${assumptionIds[0]}` : `Test ${cluster.length} ${lens} \xB7 ${stage} beliefs`;
|
|
2175
2312
|
const rationale = cluster.length === 1 ? `One belief (${assumptionIds[0]}) at ${Math.round(maxRisk)} risk with no live test. Designing an experiment here would buy down the most risk.` : `${cluster.length} beliefs share ${lens} \xB7 ${stage}, the riskiest at ${Math.round(maxRisk)} risk. One experiment can address them all.`;
|
|
2176
2313
|
const barPreview = `The riskiest belief moves out of the kill zone, or stays in it.`;
|
|
2177
2314
|
const body = generateExperimentBody(type, lens, stage, cluster, maxRisk);
|
|
2315
|
+
const lensColour = LENS_COLOUR[lens] ?? LENS_COLOUR["Investor"] ?? "#6b7484";
|
|
2178
2316
|
recs.push({
|
|
2179
2317
|
id: assumptionIds.join("+"),
|
|
2180
2318
|
type,
|
|
@@ -2183,7 +2321,9 @@ function buildRecommendedExperiments(assumptions, experiments) {
|
|
|
2183
2321
|
maxRisk,
|
|
2184
2322
|
rationale,
|
|
2185
2323
|
barPreview,
|
|
2186
|
-
body
|
|
2324
|
+
body,
|
|
2325
|
+
lens,
|
|
2326
|
+
lensColour
|
|
2187
2327
|
});
|
|
2188
2328
|
}
|
|
2189
2329
|
recs.sort(
|
|
@@ -2672,10 +2812,7 @@ function NextMovesSection({
|
|
|
2672
2812
|
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-head", children: "Next moves" }),
|
|
2673
2813
|
/* @__PURE__ */ jsxs5("div", { className: "vos-next-moves-cols", children: [
|
|
2674
2814
|
/* @__PURE__ */ jsxs5("div", { className: "vos-card vos-next-moves-col", children: [
|
|
2675
|
-
/* @__PURE__ */
|
|
2676
|
-
"Needs framing \xB7 top ",
|
|
2677
|
-
needsFraming.length
|
|
2678
|
-
] }),
|
|
2815
|
+
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-col-label", children: "Needs framing \xB7 one per lens" }),
|
|
2679
2816
|
needsFraming.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "vos-muted vos-next-moves-empty", children: "Every belief is fully framed." }) : needsFraming.map((a) => /* @__PURE__ */ jsxs5(
|
|
2680
2817
|
"button",
|
|
2681
2818
|
{
|
|
@@ -2684,13 +2821,24 @@ function NextMovesSection({
|
|
|
2684
2821
|
onClick: () => onOpenAssumption(a.id),
|
|
2685
2822
|
children: [
|
|
2686
2823
|
/* @__PURE__ */ jsxs5("div", { className: "vos-next-moves-item-head", children: [
|
|
2687
|
-
/* @__PURE__ */ jsx5(
|
|
2824
|
+
/* @__PURE__ */ jsx5(
|
|
2825
|
+
"span",
|
|
2826
|
+
{
|
|
2827
|
+
className: "vos-next-moves-lens",
|
|
2828
|
+
style: { background: `${a.lensColour}20`, color: a.lensColour, borderColor: `${a.lensColour}40` },
|
|
2829
|
+
children: a.lens
|
|
2830
|
+
}
|
|
2831
|
+
),
|
|
2688
2832
|
/* @__PURE__ */ jsxs5("span", { className: `vos-next-moves-item-risk vos-num vos-text-${riskToneClass(a.risk)}`, children: [
|
|
2689
2833
|
Math.round(a.risk),
|
|
2690
2834
|
" risk"
|
|
2691
2835
|
] })
|
|
2692
2836
|
] }),
|
|
2693
|
-
/* @__PURE__ */
|
|
2837
|
+
/* @__PURE__ */ jsxs5("div", { className: "vos-next-moves-item-title", children: [
|
|
2838
|
+
/* @__PURE__ */ jsx5("span", { className: "vos-next-moves-item-id vos-num", children: a.id }),
|
|
2839
|
+
" \xB7 ",
|
|
2840
|
+
a.title
|
|
2841
|
+
] }),
|
|
2694
2842
|
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-item-hint", children: a.hint })
|
|
2695
2843
|
]
|
|
2696
2844
|
},
|
|
@@ -2698,39 +2846,36 @@ function NextMovesSection({
|
|
|
2698
2846
|
))
|
|
2699
2847
|
] }),
|
|
2700
2848
|
/* @__PURE__ */ jsxs5("div", { className: "vos-card vos-next-moves-col", children: [
|
|
2701
|
-
/* @__PURE__ */
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2849
|
+
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-col-label", children: "Proposed experiments \xB7 one per lens" }),
|
|
2850
|
+
recs.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "vos-muted vos-next-moves-empty", children: "Every risk has a live test." }) : recs.map((rec) => /* @__PURE__ */ jsxs5("div", { className: "vos-next-moves-rec", children: [
|
|
2851
|
+
/* @__PURE__ */ jsxs5("div", { className: "vos-next-moves-rec-head", children: [
|
|
2852
|
+
/* @__PURE__ */ jsx5(
|
|
2853
|
+
"span",
|
|
2854
|
+
{
|
|
2855
|
+
className: "vos-next-moves-lens",
|
|
2856
|
+
style: { background: `${rec.lensColour}20`, color: rec.lensColour, borderColor: `${rec.lensColour}40` },
|
|
2857
|
+
children: rec.lens
|
|
2858
|
+
}
|
|
2859
|
+
),
|
|
2860
|
+
/* @__PURE__ */ jsx5("span", { className: "vos-next-moves-rec-type", children: rec.type }),
|
|
2861
|
+
/* @__PURE__ */ jsxs5("span", { className: "vos-next-moves-rec-risk vos-num", children: [
|
|
2710
2862
|
Math.round(rec.maxRisk),
|
|
2711
2863
|
" risk"
|
|
2712
2864
|
] })
|
|
2713
2865
|
] }),
|
|
2714
|
-
/* @__PURE__ */
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
/* @__PURE__ */ jsx5("strong", { children: "Right if:" }),
|
|
2728
|
-
" ",
|
|
2729
|
-
rec.barPreview
|
|
2730
|
-
] }),
|
|
2731
|
-
/* @__PURE__ */ jsx5("div", { className: "vos-pipe-rec-body", children: /* @__PURE__ */ jsx5(EvidenceBody, { text: rec.body }) }),
|
|
2732
|
-
/* @__PURE__ */ jsx5("div", { className: "vos-pipe-rec-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", className: "vos-btn vos-btn-sm vos-btn-accent", children: "Accept & create experiment" }) })
|
|
2733
|
-
] })
|
|
2866
|
+
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-rec-title", children: rec.title }),
|
|
2867
|
+
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-rec-rationale", children: rec.rationale }),
|
|
2868
|
+
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-rec-chips", children: rec.assumptionIds.map((id) => /* @__PURE__ */ jsx5(
|
|
2869
|
+
"button",
|
|
2870
|
+
{
|
|
2871
|
+
type: "button",
|
|
2872
|
+
className: "vos-next-moves-rec-chip",
|
|
2873
|
+
onClick: () => onOpenAssumption(id),
|
|
2874
|
+
children: id
|
|
2875
|
+
},
|
|
2876
|
+
id
|
|
2877
|
+
)) }),
|
|
2878
|
+
/* @__PURE__ */ jsx5("div", { className: "vos-next-moves-rec-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", className: "vos-btn vos-btn-sm", children: "Accept & create experiment" }) })
|
|
2734
2879
|
] }, rec.id))
|
|
2735
2880
|
] })
|
|
2736
2881
|
] })
|
|
@@ -2759,15 +2904,14 @@ function ConfidenceDonut({
|
|
|
2759
2904
|
value,
|
|
2760
2905
|
size = 56
|
|
2761
2906
|
}) {
|
|
2762
|
-
const
|
|
2907
|
+
const stroke = size > 60 ? 4 : 3;
|
|
2908
|
+
const r = (size - stroke * 3) / 2;
|
|
2763
2909
|
const cx = size / 2;
|
|
2764
2910
|
const cy = size / 2;
|
|
2911
|
+
const circumference = 2 * Math.PI * r;
|
|
2765
2912
|
const pct2 = Math.max(0, Math.min(100, value)) / 100;
|
|
2913
|
+
const dash = pct2 * circumference;
|
|
2766
2914
|
const color = value >= 67 ? "var(--vos-good)" : value >= 33 ? "var(--vos-warn)" : "var(--vos-crit)";
|
|
2767
|
-
const endAngle = -Math.PI / 2 + pct2 * 2 * Math.PI;
|
|
2768
|
-
const x2 = cx + r * Math.cos(endAngle);
|
|
2769
|
-
const y2 = cy + r * Math.sin(endAngle);
|
|
2770
|
-
const largeArc = pct2 > 0.5 ? 1 : 0;
|
|
2771
2915
|
return /* @__PURE__ */ jsxs6("div", { className: "vos-donut", style: { width: size, height: size }, children: [
|
|
2772
2916
|
/* @__PURE__ */ jsxs6("svg", { width: size, height: size, "aria-hidden": "true", children: [
|
|
2773
2917
|
/* @__PURE__ */ jsx6(
|
|
@@ -2777,22 +2921,34 @@ function ConfidenceDonut({
|
|
|
2777
2921
|
cy,
|
|
2778
2922
|
r,
|
|
2779
2923
|
fill: "none",
|
|
2780
|
-
stroke: "var(--vos-
|
|
2781
|
-
strokeWidth:
|
|
2924
|
+
stroke: "var(--vos-border)",
|
|
2925
|
+
strokeWidth: stroke
|
|
2782
2926
|
}
|
|
2783
2927
|
),
|
|
2784
2928
|
value > 0 ? /* @__PURE__ */ jsx6(
|
|
2785
|
-
"
|
|
2929
|
+
"circle",
|
|
2786
2930
|
{
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2931
|
+
cx,
|
|
2932
|
+
cy,
|
|
2933
|
+
r,
|
|
2934
|
+
fill: "none",
|
|
2790
2935
|
stroke: color,
|
|
2791
|
-
strokeWidth:
|
|
2936
|
+
strokeWidth: stroke,
|
|
2937
|
+
strokeDasharray: `${dash} ${circumference - dash}`,
|
|
2938
|
+
strokeDashoffset: 0,
|
|
2939
|
+
strokeLinecap: "round",
|
|
2940
|
+
transform: `rotate(-90 ${cx} ${cy})`
|
|
2792
2941
|
}
|
|
2793
2942
|
) : null
|
|
2794
2943
|
] }),
|
|
2795
|
-
/* @__PURE__ */ jsx6(
|
|
2944
|
+
/* @__PURE__ */ jsx6(
|
|
2945
|
+
"span",
|
|
2946
|
+
{
|
|
2947
|
+
className: "vos-donut-num vos-num",
|
|
2948
|
+
style: { fontSize: size > 60 ? 22 : 15 },
|
|
2949
|
+
children: Math.round(value)
|
|
2950
|
+
}
|
|
2951
|
+
)
|
|
2796
2952
|
] });
|
|
2797
2953
|
}
|
|
2798
2954
|
|
|
@@ -2930,11 +3086,11 @@ function ExperimentDetail({
|
|
|
2930
3086
|
/* @__PURE__ */ jsxs7("div", { className: "vos-detail-section-label", children: [
|
|
2931
3087
|
"Evidence \xB7 ",
|
|
2932
3088
|
expReadings.length,
|
|
2933
|
-
"
|
|
3089
|
+
" piece",
|
|
2934
3090
|
expReadings.length === 1 ? "" : "s",
|
|
2935
3091
|
" from this experiment"
|
|
2936
3092
|
] }),
|
|
2937
|
-
expReadings.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "vos-muted vos-empty", children: "No
|
|
3093
|
+
expReadings.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "vos-muted vos-empty", children: "No evidence yet \u2014 experiment is running." }) : expReadings.map((r) => {
|
|
2938
3094
|
const beliefs = readingBeliefs(r);
|
|
2939
3095
|
const rDate = String(r.Date ?? "");
|
|
2940
3096
|
const rTitle = String(r.Title ?? r.id);
|
|
@@ -2962,35 +3118,10 @@ function ExperimentDetail({
|
|
|
2962
3118
|
}
|
|
2963
3119
|
)
|
|
2964
3120
|
] }),
|
|
2965
|
-
beliefs.length > 0 ? /* @__PURE__ */ jsx7("div", { className: "vos-reading-quotes", children: beliefs.map((b) => {
|
|
2966
|
-
const justification = String(b["Grading justification"] ?? "");
|
|
2967
|
-
if (!justification) return null;
|
|
2968
|
-
return /* @__PURE__ */ jsxs7(
|
|
2969
|
-
"div",
|
|
2970
|
-
{
|
|
2971
|
-
className: `vos-reading-rationale vos-verdict-border-${verdictTone2(b.Result)}`,
|
|
2972
|
-
children: [
|
|
2973
|
-
/* @__PURE__ */ jsxs7("span", { className: "vos-reading-quote-id vos-num", children: [
|
|
2974
|
-
b.assumptionId,
|
|
2975
|
-
" \xB7"
|
|
2976
|
-
] }),
|
|
2977
|
-
/* @__PURE__ */ jsx7("span", { className: "vos-reading-rationale-label", children: "grading rationale:" }),
|
|
2978
|
-
justification
|
|
2979
|
-
]
|
|
2980
|
-
},
|
|
2981
|
-
b.assumptionId
|
|
2982
|
-
);
|
|
2983
|
-
}) }) : null,
|
|
2984
|
-
/* @__PURE__ */ jsxs7("div", { className: "vos-reading-beliefs-label", children: [
|
|
2985
|
-
"ADDRESSES ",
|
|
2986
|
-
beliefs.length,
|
|
2987
|
-
" BELIEF",
|
|
2988
|
-
beliefs.length === 1 ? "" : "S",
|
|
2989
|
-
":"
|
|
2990
|
-
] }),
|
|
2991
3121
|
beliefs.map((b) => {
|
|
2992
3122
|
const bl = barLines.find((x) => x.assumptionId === b.assumptionId);
|
|
2993
3123
|
const a = (assumptions.records ?? []).find((x) => String(x.id) === b.assumptionId);
|
|
3124
|
+
const justification = String(b["Grading justification"] ?? "");
|
|
2994
3125
|
return /* @__PURE__ */ jsxs7("div", { className: `vos-belief-card vos-verdict-border-${verdictTone2(b.Result)}`, children: [
|
|
2995
3126
|
/* @__PURE__ */ jsxs7("div", { className: "vos-belief-head", children: [
|
|
2996
3127
|
/* @__PURE__ */ jsx7(
|
|
@@ -3006,7 +3137,22 @@ function ExperimentDetail({
|
|
|
3006
3137
|
/* @__PURE__ */ jsx7("span", { className: `vos-pill vos-pill-${verdictTone2(b.Result)}`, children: b.Result }),
|
|
3007
3138
|
/* @__PURE__ */ jsx7("span", { className: "vos-rung-tag", children: String(r.Rung ?? "") })
|
|
3008
3139
|
] }),
|
|
3140
|
+
typeof b.excerpt === "string" && b.excerpt !== "" ? /* @__PURE__ */ jsxs7("div", { className: `vos-belief-excerpt vos-verdict-border-${verdictTone2(b.Result)}`, children: [
|
|
3141
|
+
"\u201C",
|
|
3142
|
+
b.excerpt,
|
|
3143
|
+
"\u201D"
|
|
3144
|
+
] }) : justification ? /* @__PURE__ */ jsxs7(
|
|
3145
|
+
"div",
|
|
3146
|
+
{
|
|
3147
|
+
className: `vos-belief-rationale vos-verdict-border-${verdictTone2(b.Result)}`,
|
|
3148
|
+
children: [
|
|
3149
|
+
/* @__PURE__ */ jsx7("span", { className: "vos-belief-rationale-label", children: "grading rationale:" }),
|
|
3150
|
+
justification
|
|
3151
|
+
]
|
|
3152
|
+
}
|
|
3153
|
+
) : null,
|
|
3009
3154
|
bl ? /* @__PURE__ */ jsxs7("div", { className: "vos-belief-bar", children: [
|
|
3155
|
+
/* @__PURE__ */ jsx7("div", { className: "vos-belief-bar-label", children: "Pre-registered bar" }),
|
|
3010
3156
|
/* @__PURE__ */ jsxs7("div", { children: [
|
|
3011
3157
|
/* @__PURE__ */ jsx7("strong", { children: "Right if:" }),
|
|
3012
3158
|
" ",
|
|
@@ -3021,8 +3167,7 @@ function ExperimentDetail({
|
|
|
3021
3167
|
"Bar verdict: ",
|
|
3022
3168
|
/* @__PURE__ */ jsx7("strong", { children: bl.barVerdict })
|
|
3023
3169
|
] }) : null
|
|
3024
|
-
] }) : null
|
|
3025
|
-
/* @__PURE__ */ jsx7("div", { className: "vos-belief-why", children: String(b["Grading justification"] ?? "") })
|
|
3170
|
+
] }) : null
|
|
3026
3171
|
] }, b.assumptionId);
|
|
3027
3172
|
})
|
|
3028
3173
|
] })
|
|
@@ -3035,7 +3180,7 @@ function ExperimentDetail({
|
|
|
3035
3180
|
unstartedBars.length,
|
|
3036
3181
|
" bar",
|
|
3037
3182
|
unstartedBars.length === 1 ? "" : "s",
|
|
3038
|
-
" with no
|
|
3183
|
+
" with no evidence"
|
|
3039
3184
|
] }),
|
|
3040
3185
|
unstartedBars.map((bl) => {
|
|
3041
3186
|
const a = (assumptions.records ?? []).find((x) => String(x.id) === bl.assumptionId);
|
|
@@ -3052,7 +3197,7 @@ function ExperimentDetail({
|
|
|
3052
3197
|
),
|
|
3053
3198
|
/* @__PURE__ */ jsx7("span", { className: "vos-belief-title", children: String(a?.Title ?? bl.assumptionId) }),
|
|
3054
3199
|
/* @__PURE__ */ jsx7("span", { className: "vos-rung-tag", children: String(bl.plannedRung ?? "") }),
|
|
3055
|
-
/* @__PURE__ */ jsx7("span", { className: "vos-muted", children: "\u25CC no
|
|
3200
|
+
/* @__PURE__ */ jsx7("span", { className: "vos-muted", children: "\u25CC no evidence" })
|
|
3056
3201
|
] }),
|
|
3057
3202
|
/* @__PURE__ */ jsxs7("div", { className: "vos-belief-bar", children: [
|
|
3058
3203
|
/* @__PURE__ */ jsxs7("div", { children: [
|
|
@@ -3171,15 +3316,15 @@ function ReadingDetail({
|
|
|
3171
3316
|
);
|
|
3172
3317
|
if (loading) {
|
|
3173
3318
|
return /* @__PURE__ */ jsxs9("div", { children: [
|
|
3174
|
-
/* @__PURE__ */ jsx9(Breadcrumb, { trail: [{ label: "
|
|
3175
|
-
/* @__PURE__ */ jsx9("p", { className: "vos-muted", children: "Loading
|
|
3319
|
+
/* @__PURE__ */ jsx9(Breadcrumb, { trail: [{ label: "Evidence", route: { name: "readings" } }], onNavigate }),
|
|
3320
|
+
/* @__PURE__ */ jsx9("p", { className: "vos-muted", children: "Loading evidence\u2026" })
|
|
3176
3321
|
] });
|
|
3177
3322
|
}
|
|
3178
3323
|
if (!reading) {
|
|
3179
3324
|
return /* @__PURE__ */ jsxs9("div", { children: [
|
|
3180
|
-
/* @__PURE__ */ jsx9(Breadcrumb, { trail: [{ label: "
|
|
3325
|
+
/* @__PURE__ */ jsx9(Breadcrumb, { trail: [{ label: "Evidence", route: { name: "readings" } }], onNavigate }),
|
|
3181
3326
|
/* @__PURE__ */ jsxs9("p", { className: "vos-error", children: [
|
|
3182
|
-
"
|
|
3327
|
+
"Evidence not found: ",
|
|
3183
3328
|
readingId
|
|
3184
3329
|
] })
|
|
3185
3330
|
] });
|
|
@@ -3196,7 +3341,7 @@ function ReadingDetail({
|
|
|
3196
3341
|
Breadcrumb,
|
|
3197
3342
|
{
|
|
3198
3343
|
trail: [
|
|
3199
|
-
{ label: "
|
|
3344
|
+
{ label: "Evidence", route: { name: "readings" } },
|
|
3200
3345
|
{ label: readingId, route: { name: "reading", id: readingId } }
|
|
3201
3346
|
],
|
|
3202
3347
|
onNavigate
|
|
@@ -3220,7 +3365,7 @@ function ReadingDetail({
|
|
|
3220
3365
|
beliefs.length === 1 ? "" : "s",
|
|
3221
3366
|
" \xB7 each with its own quote"
|
|
3222
3367
|
] }),
|
|
3223
|
-
beliefs.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "vos-muted", children: "No beliefs scored in this
|
|
3368
|
+
beliefs.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "vos-muted", children: "No beliefs scored in this evidence." }) : beliefs.map((b) => {
|
|
3224
3369
|
const a = (assumptions.records ?? []).find((x) => String(x.id) === b.assumptionId);
|
|
3225
3370
|
const bl = experiment && Array.isArray(experiment.barLines) ? experiment.barLines.find((x) => x?.assumptionId === b.assumptionId) : null;
|
|
3226
3371
|
const result = String(b.Result ?? "Inconclusive");
|
|
@@ -3240,6 +3385,15 @@ function ReadingDetail({
|
|
|
3240
3385
|
/* @__PURE__ */ jsx9("span", { className: `vos-pill vos-pill-${verdictTone3(result)}`, children: result }),
|
|
3241
3386
|
/* @__PURE__ */ jsx9("span", { className: "vos-rung-tag", children: rung })
|
|
3242
3387
|
] }),
|
|
3388
|
+
typeof b.excerpt === "string" && b.excerpt !== "" ? /* @__PURE__ */ jsxs9("div", { className: `vos-belief-excerpt vos-verdict-border-${verdictTone3(result)}`, children: [
|
|
3389
|
+
"\u201C",
|
|
3390
|
+
b.excerpt,
|
|
3391
|
+
"\u201D"
|
|
3392
|
+
] }) : body ? /* @__PURE__ */ jsxs9("div", { className: `vos-belief-excerpt vos-verdict-border-${verdictTone3(result)}`, children: [
|
|
3393
|
+
"\u201C",
|
|
3394
|
+
snippetFromReadingBody(body, b.assumptionId),
|
|
3395
|
+
"\u201D"
|
|
3396
|
+
] }) : null,
|
|
3243
3397
|
justification ? /* @__PURE__ */ jsxs9("div", { className: `vos-belief-rationale vos-verdict-border-${verdictTone3(result)}`, children: [
|
|
3244
3398
|
/* @__PURE__ */ jsx9("span", { className: "vos-belief-rationale-label", children: "grading rationale:" }),
|
|
3245
3399
|
justification
|
|
@@ -3290,6 +3444,21 @@ function verdictTone3(verdict) {
|
|
|
3290
3444
|
if (verdict === "Invalidated") return "crit";
|
|
3291
3445
|
return "neutral";
|
|
3292
3446
|
}
|
|
3447
|
+
function snippetFromReadingBody(body, cue) {
|
|
3448
|
+
if (!body) return "";
|
|
3449
|
+
const quoteMatch = body.match(/## Quote\n+([\s\S]*?)(?=\n## |\n##$|$)/i);
|
|
3450
|
+
if (quoteMatch) {
|
|
3451
|
+
const q = quoteMatch[1].trim();
|
|
3452
|
+
return q.length > 220 ? q.slice(0, 217).trim() + "\u2026" : q;
|
|
3453
|
+
}
|
|
3454
|
+
const sentences = body.split(/(?<=[.!?])\s+/);
|
|
3455
|
+
const cueLower = cue.toLowerCase();
|
|
3456
|
+
for (const s of sentences) {
|
|
3457
|
+
if (s.toLowerCase().includes(cueLower)) return s.trim();
|
|
3458
|
+
}
|
|
3459
|
+
const first = sentences[0]?.trim() ?? "";
|
|
3460
|
+
return first.length > 220 ? first.slice(0, 217).trim() + "\u2026" : first;
|
|
3461
|
+
}
|
|
3293
3462
|
|
|
3294
3463
|
// src/readings-surface.tsx
|
|
3295
3464
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
@@ -5121,6 +5290,11 @@ function BeliefVerdicts({
|
|
|
5121
5290
|
"Strength ",
|
|
5122
5291
|
formatSigned(v.strength)
|
|
5123
5292
|
] }) }) : null,
|
|
5293
|
+
v.excerpt ? /* @__PURE__ */ jsxs17("p", { className: "vos-verdict-quote", children: [
|
|
5294
|
+
"\u201C",
|
|
5295
|
+
v.excerpt,
|
|
5296
|
+
"\u201D"
|
|
5297
|
+
] }) : null,
|
|
5124
5298
|
v.justification ? /* @__PURE__ */ jsx17("p", { className: "vos-verdict-why", children: v.justification }) : null
|
|
5125
5299
|
]
|
|
5126
5300
|
},
|
|
@@ -7037,15 +7211,6 @@ function ValidationOSDashboard({ config = {} }) {
|
|
|
7037
7211
|
brandName
|
|
7038
7212
|
] }),
|
|
7039
7213
|
/* @__PURE__ */ jsxs25("div", { className: "vos-topbar", children: [
|
|
7040
|
-
backendLabel ? /* @__PURE__ */ jsxs25("div", { className: "vos-backend", children: [
|
|
7041
|
-
/* @__PURE__ */ jsx25("span", { className: "vos-live-dot" }),
|
|
7042
|
-
" Backend: ",
|
|
7043
|
-
/* @__PURE__ */ jsx25("b", { children: backendLabel })
|
|
7044
|
-
] }) : null,
|
|
7045
|
-
agentLabel ? /* @__PURE__ */ jsxs25("span", { className: "vos-hint", children: [
|
|
7046
|
-
"Agent: ",
|
|
7047
|
-
/* @__PURE__ */ jsx25("b", { style: { color: "var(--vos-text)" }, children: agentLabel })
|
|
7048
|
-
] }) : null,
|
|
7049
7214
|
/* @__PURE__ */ jsx25("div", { className: "vos-spacer" }),
|
|
7050
7215
|
/* @__PURE__ */ jsx25("button", { type: "button", className: "vos-iconbtn", onClick: toggleTheme, children: "\u25D0 Theme" }),
|
|
7051
7216
|
user?.name ? /* @__PURE__ */ jsxs25("div", { className: "vos-user", children: [
|