@validation-os/dashboard 0.8.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/dashboard-app.tsx
4
- import { useCallback as useCallback5, useEffect as useEffect6, useState as useState13 } from "react";
4
+ import { useCallback as useCallback5, useEffect as useEffect6, useState as useState14 } from "react";
5
5
 
6
6
  // src/labels.ts
7
7
  var REGISTER_LABEL = {
@@ -49,14 +49,63 @@ var REGISTER_GROUPS = [
49
49
  ];
50
50
  var WORKFLOW_NAV = [
51
51
  { route: "next", label: "Next move", icon: "\u25C8", isDefault: true },
52
- { route: "pipeline", label: "Pipeline", icon: "\u25A6" }
52
+ { route: "stage-grid", label: "Lens \xD7 Stage", icon: "\u25A6" },
53
+ { route: "pipeline", label: "Pipeline", icon: "\u25A4" }
53
54
  ];
54
55
 
55
56
  // src/next-move.ts
56
57
  import {
57
58
  isConcluded
58
59
  } from "@validation-os/core/derivation";
59
- function str(record, key) {
60
+
61
+ // src/derived-views.ts
62
+ var KILL_ZONE = -50;
63
+ function readingBeliefs(r) {
64
+ return Array.isArray(r.beliefs) ? r.beliefs : [];
65
+ }
66
+ function readingBeliefFor(r, assumptionId) {
67
+ return readingBeliefs(r).find((b) => b.assumptionId === assumptionId);
68
+ }
69
+ function readingGrades(r, assumptionId) {
70
+ return readingBeliefFor(r, assumptionId) !== void 0;
71
+ }
72
+ function isArchivedExperiment(e) {
73
+ return str(e.Status) === "Archived";
74
+ }
75
+ function liveExperiments(experiments) {
76
+ return experiments.filter((e) => !isArchivedExperiment(e));
77
+ }
78
+ function str(v) {
79
+ return typeof v === "string" && v !== "" ? v : null;
80
+ }
81
+ function derivedNum(r, key) {
82
+ const v = r.derived?.[key];
83
+ return typeof v === "number" ? v : null;
84
+ }
85
+ function strList(v) {
86
+ return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
87
+ }
88
+ function testsAssumption(exp, assumptionId) {
89
+ const bars = exp.barLines;
90
+ if (bars?.some((b) => b.assumptionId === assumptionId)) return true;
91
+ return strList(exp.barLineAssumptionIds).includes(assumptionId);
92
+ }
93
+ function hasOpenBarOn(exp, assumptionId) {
94
+ const bars = exp.barLines;
95
+ return bars?.some((b) => b.assumptionId === assumptionId && b.barVerdict == null) ?? false;
96
+ }
97
+ function inKillLane(a) {
98
+ return str(a.Status) === "Live" && (derivedNum(a, "confidence") ?? 0) <= KILL_ZONE;
99
+ }
100
+ function isTesting(a, experiments) {
101
+ if (str(a.Status) !== "Live") return false;
102
+ return experiments.some(
103
+ (e) => str(e.Status) === "Running" && hasOpenBarOn(e, a.id)
104
+ );
105
+ }
106
+
107
+ // src/next-move.ts
108
+ function str2(record, key) {
60
109
  const v = record[key];
61
110
  return typeof v === "string" ? v : null;
62
111
  }
@@ -71,13 +120,11 @@ function idList(record, key) {
71
120
  function toNextMoveInput(records) {
72
121
  const concludedByAssumption = /* @__PURE__ */ new Map();
73
122
  for (const r of records.readings) {
74
- const assumptionId = str(r, "assumptionId");
75
- if (!assumptionId) continue;
76
- const result = str(r, "Result");
77
- if (result && isConcluded(result)) {
123
+ for (const b of readingBeliefs(r)) {
124
+ if (!b.assumptionId || !isConcluded(b.Result)) continue;
78
125
  concludedByAssumption.set(
79
- assumptionId,
80
- (concludedByAssumption.get(assumptionId) ?? 0) + 1
126
+ b.assumptionId,
127
+ (concludedByAssumption.get(b.assumptionId) ?? 0) + 1
81
128
  );
82
129
  }
83
130
  }
@@ -86,8 +133,8 @@ function toNextMoveInput(records) {
86
133
  const derived = a.derived && typeof a.derived === "object" ? a.derived : {};
87
134
  return {
88
135
  id: a.id,
89
- title: str(a, "Title") ?? a.id,
90
- status: str(a, "Status") ?? "",
136
+ title: str2(a, "Title") ?? a.id,
137
+ status: str2(a, "Status") ?? "",
91
138
  impact: numOrNull(a, "Impact"),
92
139
  moot: a.moot === true,
93
140
  risk: typeof derived.risk === "number" ? derived.risk : 0,
@@ -96,12 +143,12 @@ function toNextMoveInput(records) {
96
143
  };
97
144
  }),
98
145
  experiments: records.experiments.map((e) => ({
99
- status: str(e, "Status") ?? "",
100
- feasibility: str(e, "Feasibility") ?? null,
146
+ status: str2(e, "Status") ?? "",
147
+ feasibility: str2(e, "Feasibility") ?? null,
101
148
  assumptionIds: idList(e, "barLineAssumptionIds")
102
149
  })),
103
150
  decisions: records.decisions.map((d) => ({
104
- status: str(d, "Status") ?? "",
151
+ status: str2(d, "Status") ?? "",
105
152
  assumptionIds: [...idList(d, "basedOnIds"), ...idList(d, "resolvesIds")]
106
153
  }))
107
154
  };
@@ -292,7 +339,7 @@ function sparklineY(value, height, lo, hi) {
292
339
  // src/pipeline.ts
293
340
  import {
294
341
  assumptionCompleteness,
295
- toReadingInput
342
+ readingBeliefInputs
296
343
  } from "@validation-os/core";
297
344
  import {
298
345
  beliefRisk,
@@ -306,7 +353,7 @@ function num(v) {
306
353
  const n = Number(v);
307
354
  return Number.isFinite(n) ? n : 0;
308
355
  }
309
- function str2(v) {
356
+ function str3(v) {
310
357
  return typeof v === "string" ? v : "";
311
358
  }
312
359
  function derivedOf(rec) {
@@ -346,7 +393,9 @@ function nextMove(stage, killZone) {
346
393
  }
347
394
  }
348
395
  function buildPipeline(assumptions, experiments) {
349
- const tests = beliefTestMeters(experiments.map(toStageExperimentInput));
396
+ const tests = beliefTestMeters(
397
+ liveExperiments(experiments).map(toStageExperimentInput)
398
+ );
350
399
  const rows = [];
351
400
  const resolved = [];
352
401
  const portfolioInput = [];
@@ -367,7 +416,7 @@ function buildPipeline(assumptions, experiments) {
367
416
  resolvedRetired += retired;
368
417
  resolved.push({
369
418
  id: a.id,
370
- statement: str2(a.Title),
419
+ statement: str3(a.Title),
371
420
  kind,
372
421
  retired
373
422
  });
@@ -382,7 +431,7 @@ function buildPipeline(assumptions, experiments) {
382
431
  const stage = deriveBeliefStage({ framed, confidence: d.confidence, test });
383
432
  rows.push({
384
433
  id: a.id,
385
- statement: str2(a.Title),
434
+ statement: str3(a.Title),
386
435
  impact: d.derivedImpact,
387
436
  risk: d.risk,
388
437
  riskTone: riskLevel(d.risk),
@@ -407,28 +456,27 @@ function buildPipeline(assumptions, experiments) {
407
456
  }
408
457
  function weekOverWeekDelta(assumptions, readings, now) {
409
458
  const anyDated = readings.some((r) => {
410
- const t2 = Date.parse(str2(r.Date));
459
+ const t2 = Date.parse(str3(r.Date));
411
460
  return !Number.isNaN(t2);
412
461
  });
413
462
  if (!anyDated) return null;
414
463
  const cutoff = now.getTime() - 7 * 24 * 60 * 60 * 1e3;
415
464
  const byAssumption = /* @__PURE__ */ new Map();
416
- for (const r of readings) {
417
- const id = str2(r.assumptionId);
418
- if (!id) continue;
419
- const arr = byAssumption.get(id);
420
- if (arr) arr.push(r);
421
- else byAssumption.set(id, [r]);
465
+ for (const input of readings.flatMap(readingBeliefInputs)) {
466
+ if (!input.assumptionId) continue;
467
+ const arr = byAssumption.get(input.assumptionId);
468
+ if (arr) arr.push(input);
469
+ else byAssumption.set(input.assumptionId, [input]);
422
470
  }
423
471
  const percentAsOf = (limit) => {
424
472
  const inputs = assumptions.map((a) => {
425
473
  const d = derivedOf(a);
426
- const mine = (byAssumption.get(a.id) ?? []).filter((r) => {
474
+ const mine = (byAssumption.get(a.id) ?? []).filter((i) => {
427
475
  if (limit === null) return true;
428
- const t2 = Date.parse(str2(r.Date));
476
+ const t2 = Date.parse(i.date ?? "");
429
477
  return !Number.isNaN(t2) && t2 <= limit;
430
478
  });
431
- const conf = confidence(mine.map(toReadingInput));
479
+ const conf = confidence(mine);
432
480
  return {
433
481
  id: a.id,
434
482
  derivedImpact: d.derivedImpact,
@@ -514,16 +562,6 @@ var num2 = (key, label, range = {}) => ({
514
562
  ...range
515
563
  });
516
564
  var sel = (key, label, options, nullable = false) => ({ key, label, kind: "select", options, nullable });
517
- var READING_RUNGS = [
518
- "Opinion",
519
- "Pitch-deck reaction",
520
- "Anecdotal",
521
- "Desk research",
522
- "Survey at scale",
523
- "Prototype usage",
524
- "Signed intent",
525
- "Paying users"
526
- ];
527
565
  var SOURCE_QUALITY = ["1", "0.7", "0.5"];
528
566
  var EDITORS = {
529
567
  assumptions: [
@@ -562,12 +600,14 @@ var EDITORS = {
562
600
  readings: [
563
601
  t("Title", "Reading"),
564
602
  t("Source", "Source"),
565
- sel("Rung", "Rung", READING_RUNGS),
566
- sel("Result", "Result", ["Validated", "Invalidated", "Inconclusive"]),
603
+ // Rung / Result / Magnitude band / Grading justification are PER BELIEF now
604
+ // (OPS-1305) they live in each entry of `beliefs[]`, not on the row, so
605
+ // they are deliberately absent here rather than writing dead row-level
606
+ // fields. Editing a reading's per-belief scores is a deferred follow-up (a
607
+ // `beliefs[]` editor); this form edits only the row-level fields that remain.
567
608
  sel("Representativeness", "Representativeness", SOURCE_QUALITY),
568
609
  sel("Credibility", "Credibility", SOURCE_QUALITY),
569
- sel("magnitudeBand", "Magnitude band", ["Low", "Typical", "High"], true),
570
- area("Grading justification", "Grading justification"),
610
+ area("body", "Quote"),
571
611
  t("Date", "Date")
572
612
  ],
573
613
  decisions: [
@@ -1062,14 +1102,16 @@ var COLUMNS = {
1062
1102
  ],
1063
1103
  readings: [
1064
1104
  { key: "Title", header: "Reading" },
1065
- { key: "Result", header: "Result" },
1066
- { key: "Rung", header: "Rung" },
1105
+ { key: "Source", header: "Source" },
1106
+ { key: "Date", header: "Date" },
1107
+ // The row's per-belief Result / Rung / Strength are gone (OPS-1305) — they
1108
+ // live in the reading detail's per-belief verdict list. The table instead
1109
+ // previews the quote (`body`) so a row is legible at a glance; assumption
1110
+ // chips (see `readingAssumptionChips`) disambiguate same-titled readings.
1067
1111
  {
1068
- key: "strength",
1069
- header: "Strength",
1070
- align: "right",
1071
- derived: true,
1072
- accessor: derivedField("strength")
1112
+ key: "body",
1113
+ header: "Quote",
1114
+ accessor: (r) => bodyPreview(r.body)
1073
1115
  }
1074
1116
  ],
1075
1117
  decisions: [
@@ -1084,6 +1126,16 @@ var COLUMNS = {
1084
1126
  function columnsFor(register) {
1085
1127
  return COLUMNS[register];
1086
1128
  }
1129
+ function bodyPreview(value, max = 80) {
1130
+ if (typeof value !== "string") return "";
1131
+ const oneLine = value.replace(/\s+/g, " ").trim();
1132
+ if (oneLine.length <= max) return oneLine;
1133
+ return `${oneLine.slice(0, max - 1).trimEnd()}\u2026`;
1134
+ }
1135
+ function readingAssumptionChips(record, titleById = /* @__PURE__ */ new Map()) {
1136
+ const ids = Array.isArray(record.assumptionIds) ? record.assumptionIds.filter((x) => typeof x === "string") : [];
1137
+ return ids.map((id) => titleById.get(id) ?? id);
1138
+ }
1087
1139
  function cellValue(column, record) {
1088
1140
  return column.accessor ? column.accessor(record) : record[column.key];
1089
1141
  }
@@ -1120,7 +1172,9 @@ var FIELD_LABEL = {
1120
1172
  contradictsIds: "Contradicts",
1121
1173
  readingIds: "Readings",
1122
1174
  assumptionId: "Assumption",
1123
- experimentId: "Experiment",
1175
+ assumptionIds: "Beliefs",
1176
+ experimentId: "Evidence plan",
1177
+ body: "Quote",
1124
1178
  contextLinks: "Context links",
1125
1179
  basedOnIds: "Based on",
1126
1180
  resolvesIds: "Resolves",
@@ -1148,13 +1202,22 @@ var META_FIELDS = /* @__PURE__ */ new Set([
1148
1202
  "updatedAt",
1149
1203
  "derived"
1150
1204
  ]);
1151
- var SUPPRESSED_FIELDS = /* @__PURE__ */ new Set(["barLineAssumptionIds"]);
1205
+ var SUPPRESSED_FIELDS = /* @__PURE__ */ new Set([
1206
+ "barLineAssumptionIds",
1207
+ // A reading's `beliefs[]` is rendered as the richer per-belief verdict list
1208
+ // (OPS-1305), never as raw JSON in the generic row list.
1209
+ "beliefs",
1210
+ // `body` (a reading's quote / an experiment's narrative) renders as Markdown
1211
+ // in its own block, not as a raw-text row.
1212
+ "body"
1213
+ ]);
1152
1214
  var RELATION_TARGET = {
1153
1215
  dependsOnIds: "assumptions",
1154
1216
  enablesIds: "assumptions",
1155
1217
  contradictsIds: "assumptions",
1156
1218
  readingIds: "readings",
1157
1219
  assumptionId: "assumptions",
1220
+ assumptionIds: "assumptions",
1158
1221
  experimentId: "experiments",
1159
1222
  basedOnIds: "assumptions",
1160
1223
  resolvesIds: "assumptions"
@@ -1203,7 +1266,13 @@ function detailRows(register, record, related = {}) {
1203
1266
  const label = fieldLabel(key);
1204
1267
  const target = RELATION_TARGET[key];
1205
1268
  if (target) {
1206
- const items = idsOf(value).map((id) => resolveItem(related, target, id));
1269
+ let items = idsOf(value).map((id) => resolveItem(related, target, id));
1270
+ if (target === "experiments") {
1271
+ const archived = new Set(
1272
+ (related.experiments ?? []).filter((e) => isArchivedExperiment(e)).map((e) => e.id)
1273
+ );
1274
+ items = items.filter((it) => !archived.has(it.id));
1275
+ }
1207
1276
  return { key, label, kind: "relation", items };
1208
1277
  }
1209
1278
  if (OWNER_FIELDS.has(key)) {
@@ -1436,7 +1505,7 @@ function TermLink({
1436
1505
  // src/journey.ts
1437
1506
  import {
1438
1507
  assumptionCompleteness as assumptionCompleteness2,
1439
- toReadingInput as toReadingInput3
1508
+ readingBeliefInputs as readingBeliefInputs3
1440
1509
  } from "@validation-os/core";
1441
1510
  import {
1442
1511
  assembleJourney,
@@ -1446,51 +1515,20 @@ import {
1446
1515
  rankNextMoves
1447
1516
  } from "@validation-os/core/derivation";
1448
1517
 
1449
- // src/derived-views.ts
1450
- var KILL_ZONE = -50;
1451
- function str3(v) {
1452
- return typeof v === "string" && v !== "" ? v : null;
1453
- }
1454
- function derivedNum(r, key) {
1455
- const v = r.derived?.[key];
1456
- return typeof v === "number" ? v : null;
1457
- }
1458
- function strList(v) {
1459
- return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
1460
- }
1461
- function testsAssumption(exp, assumptionId) {
1462
- const bars = exp.barLines;
1463
- if (bars?.some((b) => b.assumptionId === assumptionId)) return true;
1464
- return strList(exp.barLineAssumptionIds).includes(assumptionId);
1465
- }
1466
- function hasOpenBarOn(exp, assumptionId) {
1467
- const bars = exp.barLines;
1468
- return bars?.some((b) => b.assumptionId === assumptionId && b.barVerdict == null) ?? false;
1469
- }
1470
- function inKillLane(a) {
1471
- return str3(a.Status) === "Live" && (derivedNum(a, "confidence") ?? 0) <= KILL_ZONE;
1472
- }
1473
- function isTesting(a, experiments) {
1474
- if (str3(a.Status) !== "Live") return false;
1475
- return experiments.some(
1476
- (e) => str3(e.Status) === "Running" && hasOpenBarOn(e, a.id)
1477
- );
1478
- }
1479
-
1480
1518
  // src/cycles.ts
1481
1519
  import {
1482
- toReadingInput as toReadingInput2
1520
+ readingBeliefInputs as readingBeliefInputs2
1483
1521
  } from "@validation-os/core";
1484
1522
  import { confidenceAttribution } from "@validation-os/core/derivation";
1485
1523
  var DIRECT_CYCLE_KEY = "direct";
1486
1524
  function readingDate(r) {
1487
- return str3(r.Date);
1525
+ return str(r.Date);
1488
1526
  }
1489
- function toCycleReading(r) {
1527
+ function toCycleReading(r, assumptionId) {
1490
1528
  return {
1491
1529
  id: r.id,
1492
1530
  date: readingDate(r),
1493
- result: r.Result ?? null
1531
+ result: readingBeliefFor(r, assumptionId)?.Result ?? null
1494
1532
  };
1495
1533
  }
1496
1534
  function sortByDate(readings) {
@@ -1507,13 +1545,14 @@ function barVerdictFor(exp, assumptionId) {
1507
1545
  return line?.barVerdict ?? null;
1508
1546
  }
1509
1547
  function buildCycles(assumptionId, readings, experiments) {
1510
- const mine = readings.filter((r) => r.assumptionId === assumptionId);
1511
- const { movers } = confidenceAttribution(mine.map(toReadingInput2));
1548
+ const mine = readings.filter((r) => readingGrades(r, assumptionId));
1549
+ const inputs = readings.flatMap(readingBeliefInputs2).filter((i) => i.assumptionId === assumptionId);
1550
+ const { movers } = confidenceAttribution(inputs);
1512
1551
  const moverByKey = new Map(movers.map((m) => [m.key, m]));
1513
1552
  const byExperiment = /* @__PURE__ */ new Map();
1514
1553
  const direct = [];
1515
1554
  for (const r of mine) {
1516
- const expId = str3(r.experimentId);
1555
+ const expId = str(r.experimentId);
1517
1556
  if (expId) {
1518
1557
  const bucket = byExperiment.get(expId) ?? [];
1519
1558
  bucket.push(r);
@@ -1524,19 +1563,24 @@ function buildCycles(assumptionId, readings, experiments) {
1524
1563
  }
1525
1564
  const experimentsById = new Map(experiments.map((e) => [e.id, e]));
1526
1565
  const experimentIds = /* @__PURE__ */ new Set([
1527
- ...experiments.filter((e) => testsAssumption(e, assumptionId)).map((e) => e.id),
1528
- ...byExperiment.keys()
1566
+ ...liveExperiments(experiments).filter((e) => testsAssumption(e, assumptionId)).map((e) => e.id),
1567
+ ...[...byExperiment.keys()].filter((id) => {
1568
+ const e = experimentsById.get(id);
1569
+ return !e || !isArchivedExperiment(e);
1570
+ })
1529
1571
  ]);
1530
1572
  const cycles = [...experimentIds].map((id) => {
1531
1573
  const exp = experimentsById.get(id);
1532
- const readingViews = sortByDate((byExperiment.get(id) ?? []).map(toCycleReading));
1574
+ const readingViews = sortByDate(
1575
+ (byExperiment.get(id) ?? []).map((r) => toCycleReading(r, assumptionId))
1576
+ );
1533
1577
  const mover = moverByKey.get(id);
1534
- const date = (exp ? str3(exp.Date) : null) ?? readingViews[0]?.date ?? null;
1578
+ const date = (exp ? str(exp.Date) : null) ?? readingViews[0]?.date ?? null;
1535
1579
  return {
1536
1580
  key: id,
1537
1581
  kind: "experiment",
1538
- title: exp ? str3(exp.Title) : null,
1539
- status: exp ? str3(exp.Status) : null,
1582
+ title: exp ? str(exp.Title) : null,
1583
+ status: exp ? str(exp.Status) : null,
1540
1584
  date,
1541
1585
  barVerdict: exp ? barVerdictFor(exp, assumptionId) : null,
1542
1586
  readings: readingViews,
@@ -1545,7 +1589,9 @@ function buildCycles(assumptionId, readings, experiments) {
1545
1589
  };
1546
1590
  });
1547
1591
  if (direct.length > 0) {
1548
- const readingViews = sortByDate(direct.map(toCycleReading));
1592
+ const readingViews = sortByDate(
1593
+ direct.map((r) => toCycleReading(r, assumptionId))
1594
+ );
1549
1595
  const mover = moverByKey.get(DIRECT_CYCLE_KEY);
1550
1596
  cycles.push({
1551
1597
  key: DIRECT_CYCLE_KEY,
@@ -1620,21 +1666,18 @@ function buildJourney(assumptionId, records, now) {
1620
1666
  if (!belief2) return null;
1621
1667
  const derived = belief2.derived && typeof belief2.derived === "object" ? belief2.derived : {};
1622
1668
  const confidence2 = typeof derived.confidence === "number" ? derived.confidence : 0;
1623
- const test = beliefTestMeters2(records.experiments.map(toStageExperimentInput)).get(
1624
- assumptionId
1625
- ) ?? emptyTestMeter();
1669
+ const live = liveExperiments(records.experiments);
1670
+ const test = beliefTestMeters2(live.map(toStageExperimentInput)).get(assumptionId) ?? emptyTestMeter();
1626
1671
  const framed = assumptionCompleteness2(belief2);
1627
1672
  const stage = deriveBeliefStage2({ framed, confidence: confidence2, test });
1628
- const myReadings = records.readings.filter(
1629
- (r) => r.assumptionId === assumptionId
1630
- );
1631
- const myExperiments = records.experiments.filter((e) => testsAssumption(e, assumptionId)).map((e) => ({ id: e.id, date: str4(e.Date) || str4(e.createdAt) || null }));
1673
+ const myReadingInputs = records.readings.flatMap(readingBeliefInputs3).filter((i) => i.assumptionId === assumptionId);
1674
+ const myExperiments = live.filter((e) => testsAssumption(e, assumptionId)).map((e) => ({ id: e.id, date: str4(e.Date) || str4(e.createdAt) || null }));
1632
1675
  const events = assembleJourney({
1633
1676
  belief: {
1634
1677
  createdAt: str4(belief2.createdAt) || null,
1635
1678
  impactScored: belief2.Impact != null
1636
1679
  },
1637
- readings: myReadings.map(toReadingInput3),
1680
+ readings: myReadingInputs,
1638
1681
  experiments: myExperiments,
1639
1682
  now
1640
1683
  }).map((event) => ({ ...event, label: labelFor(event) }));
@@ -2221,7 +2264,7 @@ function StatTile({
2221
2264
 
2222
2265
  // src/understanding.ts
2223
2266
  import {
2224
- toReadingInput as toReadingInput4
2267
+ readingBeliefInputs as readingBeliefInputs4
2225
2268
  } from "@validation-os/core";
2226
2269
  import {
2227
2270
  confidenceAttribution as confidenceAttribution2,
@@ -2230,26 +2273,28 @@ import {
2230
2273
  isConcluded as isConcluded2
2231
2274
  } from "@validation-os/core/derivation";
2232
2275
  function buildUnderstanding(assumption, readings, experiments) {
2233
- const mine = readings.filter((r) => r.assumptionId === assumption.id);
2234
- const inputs = mine.map(toReadingInput4);
2276
+ const inputs = readings.flatMap(readingBeliefInputs4).filter((i) => i.assumptionId === assumption.id);
2235
2277
  const { confidence: confidence2, movers } = confidenceAttribution2(inputs);
2236
2278
  const experimentsById = new Map(experiments.map((e) => [e.id, e]));
2237
2279
  const moverByExperiment = new Map(
2238
2280
  movers.filter((m) => m.kind === "experiment").map((m) => [m.experimentId, m])
2239
2281
  );
2240
2282
  const experimentIds = /* @__PURE__ */ new Set([
2241
- ...experiments.filter((e) => testsAssumption(e, assumption.id)).map((e) => e.id),
2242
- ...moverByExperiment.keys()
2283
+ ...liveExperiments(experiments).filter((e) => testsAssumption(e, assumption.id)).map((e) => e.id),
2284
+ ...[...moverByExperiment.keys()].filter((id) => {
2285
+ const e = experimentsById.get(id);
2286
+ return !e || !isArchivedExperiment(e);
2287
+ })
2243
2288
  ]);
2244
2289
  const experimentViews = [...experimentIds].map((id) => {
2245
2290
  const exp = experimentsById.get(id);
2246
2291
  const mover = moverByExperiment.get(id);
2247
2292
  const bars = exp?.barLines ?? [];
2248
2293
  const progress = bars.length ? experimentProgress(bars) : null;
2249
- const status = exp ? str3(exp.Status) : null;
2294
+ const status = exp ? str(exp.Status) : null;
2250
2295
  return {
2251
2296
  experimentId: id,
2252
- title: exp ? str3(exp.Title) : null,
2297
+ title: exp ? str(exp.Title) : null,
2253
2298
  status,
2254
2299
  contribution: mover?.contribution ?? 0,
2255
2300
  magnitude: mover?.magnitude ?? 0,
@@ -2726,42 +2771,43 @@ function JourneyColdCard({
2726
2771
  }
2727
2772
 
2728
2773
  // src/list-surface.ts
2774
+ function hasConcludedBelief(r) {
2775
+ return readingBeliefs(r).some((b) => b.Result !== "Inconclusive");
2776
+ }
2729
2777
  function isProven(a, ctx) {
2730
- if (str3(a.Status) !== "Live") return false;
2731
- const mine = (ctx.readings ?? []).filter(
2732
- (r) => r.assumptionId === a.id && str3(r.Result) !== "Inconclusive"
2778
+ if (str(a.Status) !== "Live") return false;
2779
+ const scores = (ctx.readings ?? []).map((r) => readingBeliefFor(r, a.id)).filter((b) => b != null && b.Result !== "Inconclusive");
2780
+ if (scores.length === 0) return false;
2781
+ const strongest = scores.reduce(
2782
+ (best, b) => Math.abs(b.derived?.strength ?? 0) > Math.abs(best.derived?.strength ?? 0) ? b : best
2733
2783
  );
2734
- if (mine.length === 0) return false;
2735
- const strongest = mine.reduce(
2736
- (best, r) => Math.abs(derivedNum(r, "strength") ?? 0) > Math.abs(derivedNum(best, "strength") ?? 0) ? r : best
2737
- );
2738
- return str3(strongest.Result) === "Validated";
2784
+ return strongest.Result === "Validated";
2739
2785
  }
2740
2786
  function isOverdue(e, ctx) {
2741
- const deadline = str3(e.Deadline);
2742
- if (!ctx.asOf || !deadline || str3(e.Status) !== "Running") return false;
2787
+ const deadline = str(e.Deadline);
2788
+ if (!ctx.asOf || !deadline || str(e.Status) !== "Running") return false;
2743
2789
  return deadline < ctx.asOf;
2744
2790
  }
2745
2791
  function inTension(d, ctx) {
2746
- if (str3(d.Status) !== "Active") return false;
2792
+ if (str(d.Status) !== "Active") return false;
2747
2793
  const based = strList(d.basedOnIds);
2748
2794
  if (based.length === 0) return false;
2749
2795
  const byId = new Map((ctx.assumptions ?? []).map((a) => [a.id, a]));
2750
2796
  return based.some((id) => {
2751
2797
  const a = byId.get(id);
2752
2798
  if (!a) return false;
2753
- return str3(a.Status) === "Invalidated" || inKillLane(a);
2799
+ return str(a.Status) === "Invalidated" || inKillLane(a);
2754
2800
  });
2755
2801
  }
2756
2802
  var ALWAYS = () => true;
2757
- var byStatus = (...values) => (r) => values.includes(str3(r.Status) ?? "");
2803
+ var byStatus = (...values) => (r) => values.includes(str(r.Status) ?? "");
2758
2804
  var TAB_CATALOGUE = {
2759
2805
  assumptions: [
2760
2806
  {
2761
2807
  id: "live",
2762
2808
  label: "Live",
2763
2809
  isDefault: true,
2764
- predicate: (r) => str3(r.Status) === "Live" && r.moot !== true,
2810
+ predicate: (r) => str(r.Status) === "Live" && r.moot !== true,
2765
2811
  defaultSort: { key: "risk", dir: "desc" }
2766
2812
  },
2767
2813
  {
@@ -2814,12 +2860,12 @@ var TAB_CATALOGUE = {
2814
2860
  {
2815
2861
  id: "concluded",
2816
2862
  label: "\xB1 Concluded",
2817
- predicate: (r) => str3(r.Result) !== "Inconclusive"
2863
+ predicate: (r) => hasConcludedBelief(r)
2818
2864
  },
2819
2865
  {
2820
2866
  id: "inconclusive",
2821
2867
  label: "Inconclusive",
2822
- predicate: (r) => str3(r.Result) === "Inconclusive"
2868
+ predicate: (r) => !hasConcludedBelief(r)
2823
2869
  }
2824
2870
  ],
2825
2871
  decisions: [
@@ -2908,7 +2954,7 @@ function groupRecords(records, axis) {
2908
2954
  if (values.length === 0) push(emptyLabel, r);
2909
2955
  else for (const v of values) push(v, r);
2910
2956
  } else {
2911
- push(str3(r[axis]) ?? emptyLabel, r);
2957
+ push(str(r[axis]) ?? emptyLabel, r);
2912
2958
  }
2913
2959
  }
2914
2960
  return order.map((key) => ({ key, label: key, records: buckets.get(key) }));
@@ -2917,7 +2963,7 @@ function filterRecords(records, query) {
2917
2963
  const q = query.trim().toLowerCase();
2918
2964
  if (!q) return records;
2919
2965
  return records.filter((r) => {
2920
- const hay = `${str3(r.Title) ?? ""} ${str3(r.Description) ?? ""}`.toLowerCase();
2966
+ const hay = `${str(r.Title) ?? ""} ${str(r.Description) ?? ""} ${str(r.Source) ?? ""}`.toLowerCase();
2921
2967
  return hay.includes(q);
2922
2968
  });
2923
2969
  }
@@ -2943,11 +2989,11 @@ function sortRecords(records, sort) {
2943
2989
  }).map((x) => x.r);
2944
2990
  }
2945
2991
  function nestReadingsByPlan(readings, experiments) {
2946
- const titleById = new Map(experiments.map((e) => [e.id, str3(e.Title)]));
2992
+ const titleById = new Map(experiments.map((e) => [e.id, str(e.Title)]));
2947
2993
  const order = [];
2948
2994
  const groups = /* @__PURE__ */ new Map();
2949
2995
  for (const r of readings) {
2950
- const key = str3(r.experimentId);
2996
+ const key = str(r.experimentId);
2951
2997
  if (!groups.has(key)) {
2952
2998
  groups.set(key, []);
2953
2999
  order.push(key);
@@ -2991,6 +3037,149 @@ function needsHumanCounts(ctx) {
2991
3037
  };
2992
3038
  }
2993
3039
 
3040
+ // src/markdown.tsx
3041
+ import { jsx as jsx9 } from "react/jsx-runtime";
3042
+ function Markdown({ text }) {
3043
+ const trimmed = (text ?? "").trim();
3044
+ if (!trimmed) return null;
3045
+ return /* @__PURE__ */ jsx9("div", { className: "vos-md", children: renderBlocks(trimmed) });
3046
+ }
3047
+ function renderBlocks(text) {
3048
+ const lines = text.replace(/\r\n?/g, "\n").split("\n");
3049
+ const out = [];
3050
+ let i = 0;
3051
+ let key = 0;
3052
+ while (i < lines.length) {
3053
+ const line = lines[i];
3054
+ if (line.trim() === "") {
3055
+ i += 1;
3056
+ continue;
3057
+ }
3058
+ const fence = line.match(/^```/);
3059
+ if (fence) {
3060
+ const body = [];
3061
+ i += 1;
3062
+ while (i < lines.length && !/^```/.test(lines[i])) {
3063
+ body.push(lines[i]);
3064
+ i += 1;
3065
+ }
3066
+ i += 1;
3067
+ out.push(
3068
+ /* @__PURE__ */ jsx9("pre", { className: "vos-md-pre", children: /* @__PURE__ */ jsx9("code", { children: body.join("\n") }) }, key++)
3069
+ );
3070
+ continue;
3071
+ }
3072
+ const heading = line.match(/^(#{1,6})\s+(.*)$/);
3073
+ if (heading) {
3074
+ const level = heading[1].length;
3075
+ const Tag = `h${Math.min(level + 2, 6)}`;
3076
+ out.push(/* @__PURE__ */ jsx9(Tag, { children: renderInline(heading[2]) }, key++));
3077
+ i += 1;
3078
+ continue;
3079
+ }
3080
+ if (/^>\s?/.test(line)) {
3081
+ const quote = [];
3082
+ while (i < lines.length && /^>\s?/.test(lines[i])) {
3083
+ quote.push(lines[i].replace(/^>\s?/, ""));
3084
+ i += 1;
3085
+ }
3086
+ out.push(
3087
+ /* @__PURE__ */ jsx9("blockquote", { className: "vos-md-quote", children: renderBlocks(quote.join("\n")) }, key++)
3088
+ );
3089
+ continue;
3090
+ }
3091
+ if (/^[-*+]\s+/.test(line)) {
3092
+ const items = [];
3093
+ while (i < lines.length && /^[-*+]\s+/.test(lines[i])) {
3094
+ items.push(lines[i].replace(/^[-*+]\s+/, ""));
3095
+ i += 1;
3096
+ }
3097
+ out.push(
3098
+ /* @__PURE__ */ jsx9("ul", { className: "vos-md-ul", children: items.map((it, n) => /* @__PURE__ */ jsx9("li", { children: renderInline(it) }, n)) }, key++)
3099
+ );
3100
+ continue;
3101
+ }
3102
+ if (/^\d+\.\s+/.test(line)) {
3103
+ const items = [];
3104
+ while (i < lines.length && /^\d+\.\s+/.test(lines[i])) {
3105
+ items.push(lines[i].replace(/^\d+\.\s+/, ""));
3106
+ i += 1;
3107
+ }
3108
+ out.push(
3109
+ /* @__PURE__ */ jsx9("ol", { className: "vos-md-ol", children: items.map((it, n) => /* @__PURE__ */ jsx9("li", { children: renderInline(it) }, n)) }, key++)
3110
+ );
3111
+ continue;
3112
+ }
3113
+ const para = [];
3114
+ while (i < lines.length && lines[i].trim() !== "" && !/^```|^#{1,6}\s|^>\s?|^[-*+]\s+|^\d+\.\s+/.test(lines[i])) {
3115
+ para.push(lines[i]);
3116
+ i += 1;
3117
+ }
3118
+ out.push(/* @__PURE__ */ jsx9("p", { children: renderInline(para.join(" ")) }, key++));
3119
+ }
3120
+ return out;
3121
+ }
3122
+ function safeHref(href) {
3123
+ if (/^(https?:\/\/|mailto:)/i.test(href)) return href;
3124
+ if (/^[#/]/.test(href)) return href;
3125
+ return null;
3126
+ }
3127
+ var INLINE_RULES = [
3128
+ // Inline code first — its contents are literal.
3129
+ {
3130
+ re: /`([^`]+)`/,
3131
+ render: (m, key) => /* @__PURE__ */ jsx9("code", { className: "vos-md-code", children: m[1] }, key),
3132
+ recurse: false
3133
+ },
3134
+ // Links: [text](href)
3135
+ {
3136
+ re: /\[([^\]]+)\]\(([^)\s]+)\)/,
3137
+ render: (m, key) => {
3138
+ const href = safeHref(m[2]);
3139
+ if (!href) return /* @__PURE__ */ jsx9("span", { children: m[1] }, key);
3140
+ return /* @__PURE__ */ jsx9("a", { href, target: "_blank", rel: "noopener noreferrer", children: m[1] }, key);
3141
+ },
3142
+ recurse: false
3143
+ },
3144
+ // Bold: **text** or __text__
3145
+ {
3146
+ re: /\*\*([^*]+)\*\*|__([^_]+)__/,
3147
+ render: (m, key) => /* @__PURE__ */ jsx9("strong", { children: renderInline(m[1] ?? m[2] ?? "") }, key),
3148
+ recurse: true,
3149
+ inner: (m) => m[1] ?? m[2] ?? ""
3150
+ },
3151
+ // Italic: *text* or _text_
3152
+ {
3153
+ re: /\*([^*]+)\*|_([^_]+)_/,
3154
+ render: (m, key) => /* @__PURE__ */ jsx9("em", { children: renderInline(m[1] ?? m[2] ?? "") }, key),
3155
+ recurse: true,
3156
+ inner: (m) => m[1] ?? m[2] ?? ""
3157
+ }
3158
+ ];
3159
+ function renderInline(text) {
3160
+ const nodes = [];
3161
+ let rest = text;
3162
+ let key = 0;
3163
+ while (rest.length > 0) {
3164
+ let best = null;
3165
+ for (const rule2 of INLINE_RULES) {
3166
+ const m2 = new RegExp(rule2.re).exec(rest);
3167
+ if (m2 && (best === null || m2.index < best.m.index)) {
3168
+ best = { rule: rule2, m: m2 };
3169
+ }
3170
+ }
3171
+ if (!best) {
3172
+ nodes.push(rest);
3173
+ break;
3174
+ }
3175
+ const { rule, m } = best;
3176
+ if (m.index > 0) nodes.push(rest.slice(0, m.index));
3177
+ nodes.push(rule.render(m, key++));
3178
+ rest = rest.slice(m.index + m[0].length);
3179
+ }
3180
+ return nodes;
3181
+ }
3182
+
2994
3183
  // src/record-view.ts
2995
3184
  import { experimentProgress as experimentProgress2 } from "@validation-os/core/derivation";
2996
3185
  function byIds(records, ids) {
@@ -2999,7 +3188,7 @@ function byIds(records, ids) {
2999
3188
  }
3000
3189
  function headerPills(register, record, related = {}, options = {}) {
3001
3190
  const pills = [];
3002
- const status = str3(record.Status);
3191
+ const status = str(record.Status);
3003
3192
  if (status) pills.push({ label: status, tone: statusTone(status) });
3004
3193
  if (register === "assumptions") {
3005
3194
  if (record.moot === true) pills.push({ label: "Moot", tone: "neutral" });
@@ -3009,7 +3198,7 @@ function headerPills(register, record, related = {}, options = {}) {
3009
3198
  } else if (register === "experiments") {
3010
3199
  if (status === "Draft") pills.push({ label: "Test-next", tone: "accent" });
3011
3200
  if (status === "Closed") pills.push({ label: "Concluded", tone: "good" });
3012
- const deadline = str3(record.Deadline);
3201
+ const deadline = str(record.Deadline);
3013
3202
  if (options.asOf && deadline && status === "Running" && deadline < options.asOf)
3014
3203
  pills.push({ label: "Overdue", tone: "crit" });
3015
3204
  } else if (register === "decisions") {
@@ -3050,15 +3239,6 @@ function leadingMeters(register, record) {
3050
3239
  ];
3051
3240
  case "readings":
3052
3241
  return [
3053
- {
3054
- key: "strength",
3055
- label: "Strength",
3056
- kind: "signed",
3057
- value: derivedNum(record, "strength"),
3058
- tone: "neutral",
3059
- min: -100,
3060
- max: 100
3061
- },
3062
3242
  {
3063
3243
  key: "sourceQuality",
3064
3244
  label: "Source quality",
@@ -3067,13 +3247,6 @@ function leadingMeters(register, record) {
3067
3247
  value: derivedNum(record, "sourceQuality") === null ? null : Math.round((derivedNum(record, "sourceQuality") ?? 0) * 100),
3068
3248
  tone: "neutral",
3069
3249
  max: 100
3070
- },
3071
- {
3072
- key: "Result",
3073
- label: "Result",
3074
- kind: "pill",
3075
- value: str3(record.Result),
3076
- tone: statusTone(str3(record.Result) ?? "")
3077
3250
  }
3078
3251
  ];
3079
3252
  case "experiments": {
@@ -3092,7 +3265,7 @@ function leadingMeters(register, record) {
3092
3265
  key: "Feasibility",
3093
3266
  label: "Feasibility",
3094
3267
  kind: "pill",
3095
- value: str3(record.Feasibility),
3268
+ value: str(record.Feasibility),
3096
3269
  tone: "neutral"
3097
3270
  }
3098
3271
  ];
@@ -3103,8 +3276,8 @@ function leadingMeters(register, record) {
3103
3276
  key: "Status",
3104
3277
  label: "Status",
3105
3278
  kind: "pill",
3106
- value: str3(record.Status),
3107
- tone: statusTone(str3(record.Status) ?? "")
3279
+ value: str(record.Status),
3280
+ tone: statusTone(str(record.Status) ?? "")
3108
3281
  }
3109
3282
  ];
3110
3283
  case "glossary":
@@ -3113,8 +3286,8 @@ function leadingMeters(register, record) {
3113
3286
  key: "Status",
3114
3287
  label: "Status",
3115
3288
  kind: "pill",
3116
- value: str3(record.Status),
3117
- tone: statusTone(str3(record.Status) ?? "")
3289
+ value: str(record.Status),
3290
+ tone: statusTone(str(record.Status) ?? "")
3118
3291
  }
3119
3292
  ];
3120
3293
  }
@@ -3133,7 +3306,24 @@ var HUMAN_FIELDS = {
3133
3306
  ]
3134
3307
  };
3135
3308
  function humanInputFields(register, record) {
3136
- return HUMAN_FIELDS[register].map((f) => ({ key: f.key, label: f.label, text: str3(record[f.key]) ?? "" })).filter((f) => f.text !== "");
3309
+ return HUMAN_FIELDS[register].map((f) => ({ key: f.key, label: f.label, text: str(record[f.key]) ?? "" })).filter((f) => f.text !== "");
3310
+ }
3311
+ function readingBeliefVerdicts(reading, assumptions = []) {
3312
+ const byId = new Map(assumptions.map((a) => [a.id, a]));
3313
+ return readingBeliefs(reading).map((b) => {
3314
+ const hit = byId.get(b.assumptionId);
3315
+ const strength = b.derived && typeof b.derived.strength === "number" ? b.derived.strength : null;
3316
+ return {
3317
+ assumptionId: b.assumptionId,
3318
+ title: hit ? primaryLabel(hit) : b.assumptionId,
3319
+ linked: hit != null,
3320
+ rung: b.Rung ?? null,
3321
+ result: b.Result ?? null,
3322
+ strength,
3323
+ magnitudeBand: b.magnitudeBand ?? null,
3324
+ justification: typeof b["Grading justification"] === "string" ? b["Grading justification"] : ""
3325
+ };
3326
+ });
3137
3327
  }
3138
3328
  function scoreChip(register, record) {
3139
3329
  if (register === "assumptions") {
@@ -3141,14 +3331,14 @@ function scoreChip(register, record) {
3141
3331
  return { label: "Confidence", value: formatSigned(c), tone: confidenceTone(c) };
3142
3332
  }
3143
3333
  if (register === "readings") {
3144
- const s = derivedNum(record, "strength");
3334
+ const sq = derivedNum(record, "sourceQuality");
3145
3335
  return {
3146
- label: "Strength",
3147
- value: s === null ? "\u2014" : formatSigned(s),
3336
+ label: "Source quality",
3337
+ value: sq === null ? "\u2014" : String(Math.round(sq * 100)),
3148
3338
  tone: "neutral"
3149
3339
  };
3150
3340
  }
3151
- const status = str3(record.Status) ?? "\u2014";
3341
+ const status = str(record.Status) ?? "\u2014";
3152
3342
  return { label: "Status", value: status, tone: statusTone(status) };
3153
3343
  }
3154
3344
  var PANELS = {
@@ -3157,7 +3347,7 @@ var PANELS = {
3157
3347
  id: "readings",
3158
3348
  label: "Readings",
3159
3349
  register: "readings",
3160
- resolve: (r, rel) => (rel.readings ?? []).filter((x) => x.assumptionId === r.id)
3350
+ resolve: (r, rel) => (rel.readings ?? []).filter((x) => readingGrades(x, r.id))
3161
3351
  },
3162
3352
  {
3163
3353
  id: "depends-on",
@@ -3181,7 +3371,10 @@ var PANELS = {
3181
3371
  id: "tested-by",
3182
3372
  label: "Tested by",
3183
3373
  register: "experiments",
3184
- resolve: (r, rel) => (rel.experiments ?? []).filter((e) => testsAssumption(e, r.id))
3374
+ // Archived plans never surface as a relation (OPS-1305) live plans only.
3375
+ resolve: (r, rel) => liveExperiments(rel.experiments ?? []).filter(
3376
+ (e) => testsAssumption(e, r.id)
3377
+ )
3185
3378
  },
3186
3379
  {
3187
3380
  id: "decisions-based",
@@ -3199,15 +3392,20 @@ var PANELS = {
3199
3392
  readings: [
3200
3393
  {
3201
3394
  id: "assumption",
3202
- label: "Belief",
3395
+ label: "Beliefs",
3203
3396
  register: "assumptions",
3204
- resolve: (r, rel) => byIds(rel.assumptions, [str3(r.assumptionId) ?? ""].filter(Boolean))
3397
+ // A reading grades several beliefs now (OPS-1305) resolve them all.
3398
+ resolve: (r, rel) => byIds(rel.assumptions, strList(r.assumptionIds))
3205
3399
  },
3206
3400
  {
3207
3401
  id: "experiment",
3208
3402
  label: "Evidence plan",
3209
3403
  register: "experiments",
3210
- resolve: (r, rel) => byIds(rel.experiments, [str3(r.experimentId) ?? ""].filter(Boolean))
3404
+ // Only ever surface a NON-archived plan (OPS-1305): an archived origin
3405
+ // reads as no plan at all, never a leaked backlink.
3406
+ resolve: (r, rel) => byIds(rel.experiments, [str(r.experimentId) ?? ""].filter(Boolean)).filter(
3407
+ (e) => !isArchivedExperiment(e)
3408
+ )
3211
3409
  }
3212
3410
  ],
3213
3411
  experiments: [
@@ -3276,8 +3474,49 @@ function buildRecordPage(register, record, related = {}, options = {}) {
3276
3474
  };
3277
3475
  }
3278
3476
 
3477
+ // src/belief-verdicts.tsx
3478
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3479
+ function resultClass(result) {
3480
+ if (result === "Validated") return "vos-pill vos-pill-good";
3481
+ if (result === "Invalidated") return "vos-pill vos-pill-crit";
3482
+ return "vos-pill vos-pill-neutral";
3483
+ }
3484
+ function BeliefVerdicts({
3485
+ reading,
3486
+ assumptions,
3487
+ onOpenRecord
3488
+ }) {
3489
+ const verdicts = readingBeliefVerdicts(reading, assumptions);
3490
+ if (verdicts.length === 0) {
3491
+ return /* @__PURE__ */ jsx10("p", { className: "vos-hint", children: "This reading grades no beliefs yet." });
3492
+ }
3493
+ return /* @__PURE__ */ jsx10("ul", { className: "vos-verdicts", children: verdicts.map((v) => /* @__PURE__ */ jsxs9("li", { className: "vos-verdict", children: [
3494
+ /* @__PURE__ */ jsxs9("div", { className: "vos-verdict-head", children: [
3495
+ v.linked && onOpenRecord ? /* @__PURE__ */ jsx10(
3496
+ "button",
3497
+ {
3498
+ type: "button",
3499
+ className: "vos-inline-link",
3500
+ onClick: () => onOpenRecord(v.assumptionId),
3501
+ children: v.title
3502
+ }
3503
+ ) : /* @__PURE__ */ jsx10("span", { className: "vos-verdict-title", children: v.title }),
3504
+ /* @__PURE__ */ jsx10("span", { className: resultClass(v.result), children: v.result ?? "\u2014" })
3505
+ ] }),
3506
+ /* @__PURE__ */ jsxs9("div", { className: "vos-verdict-meta", children: [
3507
+ v.rung ? /* @__PURE__ */ jsx10("span", { className: "vos-chip vos-pill vos-pill-neutral", children: v.rung }) : null,
3508
+ v.magnitudeBand ? /* @__PURE__ */ jsx10("span", { className: "vos-chip vos-pill vos-pill-neutral", children: v.magnitudeBand }) : null,
3509
+ v.strength !== null ? /* @__PURE__ */ jsxs9("span", { className: "vos-verdict-strength", children: [
3510
+ "Strength ",
3511
+ formatSigned(v.strength)
3512
+ ] }) : null
3513
+ ] }),
3514
+ v.justification ? /* @__PURE__ */ jsx10("p", { className: "vos-verdict-why", children: v.justification }) : null
3515
+ ] }, v.assumptionId)) });
3516
+ }
3517
+
3279
3518
  // src/record-page.tsx
3280
- import { Fragment as Fragment8, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
3519
+ import { Fragment as Fragment8, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3281
3520
  var TAB_LABEL = {
3282
3521
  overview: "Overview",
3283
3522
  evidence: "Evidence",
@@ -3398,9 +3637,9 @@ function RecordPage({
3398
3637
  onReload: reloadLatest,
3399
3638
  onField: setField
3400
3639
  };
3401
- return /* @__PURE__ */ jsxs9("div", { children: [
3402
- /* @__PURE__ */ jsxs9("nav", { className: "vos-crumbs", "aria-label": "Breadcrumb", children: [
3403
- /* @__PURE__ */ jsx9(
3640
+ return /* @__PURE__ */ jsxs10("div", { children: [
3641
+ /* @__PURE__ */ jsxs10("nav", { className: "vos-crumbs", "aria-label": "Breadcrumb", children: [
3642
+ /* @__PURE__ */ jsx11(
3404
3643
  "button",
3405
3644
  {
3406
3645
  type: "button",
@@ -3408,14 +3647,14 @@ function RecordPage({
3408
3647
  children: REGISTER_LABEL[register ?? backRegister]
3409
3648
  }
3410
3649
  ),
3411
- /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: "\u203A" }),
3412
- /* @__PURE__ */ jsx9("span", { className: "vos-rid", children: record ? formatValue(record.Title) : recordId })
3650
+ /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: "\u203A" }),
3651
+ /* @__PURE__ */ jsx11("span", { className: "vos-rid", children: record ? formatValue(record.Title) : recordId })
3413
3652
  ] }),
3414
- anyLoading ? /* @__PURE__ */ jsx9("p", { className: "vos-muted", children: "Loading record\u2026" }) : !record || !register ? /* @__PURE__ */ jsxs9("div", { className: "vos-empty", children: [
3653
+ anyLoading ? /* @__PURE__ */ jsx11("p", { className: "vos-muted", children: "Loading record\u2026" }) : !record || !register ? /* @__PURE__ */ jsxs10("div", { className: "vos-empty", children: [
3415
3654
  "Couldn't find a record with id ",
3416
- /* @__PURE__ */ jsx9("b", { children: recordId }),
3655
+ /* @__PURE__ */ jsx11("b", { children: recordId }),
3417
3656
  "."
3418
- ] }) : /* @__PURE__ */ jsx9(
3657
+ ] }) : /* @__PURE__ */ jsx11(
3419
3658
  RecordBody,
3420
3659
  {
3421
3660
  register,
@@ -3455,20 +3694,21 @@ function RecordBody({
3455
3694
  const page = buildRecordPage(register, record, related, { asOf });
3456
3695
  const activeTab = page.tabs.includes(tab) ? tab : "overview";
3457
3696
  const description = typeof record.Description === "string" ? record.Description : "";
3697
+ const bodyText = typeof record.body === "string" ? record.body : "";
3458
3698
  const hasErrors = Object.keys(edit.errors).length > 0;
3459
- return /* @__PURE__ */ jsxs9(Fragment8, { children: [
3460
- /* @__PURE__ */ jsxs9("div", { className: "vos-head vos-record-head", children: [
3461
- /* @__PURE__ */ jsxs9("div", { children: [
3462
- /* @__PURE__ */ jsx9("p", { className: "vos-drawer-eyebrow", children: REGISTER_SINGULAR[register] }),
3463
- /* @__PURE__ */ jsx9("h1", { children: page.title }),
3464
- /* @__PURE__ */ jsx9("div", { className: "vos-pill-row", children: page.pills.map((p, i) => /* @__PURE__ */ jsx9(PillView, { pill: p }, i)) })
3699
+ return /* @__PURE__ */ jsxs10(Fragment8, { children: [
3700
+ /* @__PURE__ */ jsxs10("div", { className: "vos-head vos-record-head", children: [
3701
+ /* @__PURE__ */ jsxs10("div", { children: [
3702
+ /* @__PURE__ */ jsx11("p", { className: "vos-drawer-eyebrow", children: REGISTER_SINGULAR[register] }),
3703
+ /* @__PURE__ */ jsx11("h1", { children: page.title }),
3704
+ /* @__PURE__ */ jsx11("div", { className: "vos-pill-row", children: page.pills.map((p, i) => /* @__PURE__ */ jsx11(PillView, { pill: p }, i)) })
3465
3705
  ] }),
3466
- /* @__PURE__ */ jsx9("div", { className: "vos-spacer" }),
3467
- /* @__PURE__ */ jsxs9("span", { className: "vos-verbadge", children: [
3706
+ /* @__PURE__ */ jsx11("div", { className: "vos-spacer" }),
3707
+ /* @__PURE__ */ jsxs10("span", { className: "vos-verbadge", children: [
3468
3708
  "v",
3469
3709
  formatValue(record.version)
3470
3710
  ] }),
3471
- !edit.editing ? /* @__PURE__ */ jsx9(
3711
+ !edit.editing ? /* @__PURE__ */ jsx11(
3472
3712
  "button",
3473
3713
  {
3474
3714
  type: "button",
@@ -3478,7 +3718,7 @@ function RecordBody({
3478
3718
  }
3479
3719
  ) : null
3480
3720
  ] }),
3481
- /* @__PURE__ */ jsx9("div", { className: "vos-tabs", role: "tablist", "aria-label": "Record sections", children: page.tabs.map((t2) => /* @__PURE__ */ jsx9(
3721
+ /* @__PURE__ */ jsx11("div", { className: "vos-tabs", role: "tablist", "aria-label": "Record sections", children: page.tabs.map((t2) => /* @__PURE__ */ jsx11(
3482
3722
  "button",
3483
3723
  {
3484
3724
  type: "button",
@@ -3490,8 +3730,8 @@ function RecordBody({
3490
3730
  },
3491
3731
  t2
3492
3732
  )) }),
3493
- activeTab === "overview" ? /* @__PURE__ */ jsxs9("div", { className: "vos-record-cols", children: [
3494
- /* @__PURE__ */ jsx9("section", { className: "vos-meter-grid", children: page.meters.map((m) => /* @__PURE__ */ jsx9(
3733
+ activeTab === "overview" ? /* @__PURE__ */ jsxs10("div", { className: "vos-record-cols", children: [
3734
+ /* @__PURE__ */ jsx11("section", { className: "vos-meter-grid", children: page.meters.map((m) => /* @__PURE__ */ jsx11(
3495
3735
  MeterView,
3496
3736
  {
3497
3737
  meter: m,
@@ -3500,11 +3740,11 @@ function RecordBody({
3500
3740
  },
3501
3741
  m.key
3502
3742
  )) }),
3503
- edit.editing ? /* @__PURE__ */ jsxs9("section", { className: "vos-record-editor", children: [
3504
- /* @__PURE__ */ jsx9("h3", { className: "vos-section-title", children: "Edit" }),
3505
- edit.conflict ? /* @__PURE__ */ jsx9(ConflictBanner, { message: edit.conflict, onReload: edit.onReload }) : null,
3506
- edit.saveError ? /* @__PURE__ */ jsx9("p", { role: "alert", className: "vos-error", children: edit.saveError }) : null,
3507
- /* @__PURE__ */ jsx9(
3743
+ edit.editing ? /* @__PURE__ */ jsxs10("section", { className: "vos-record-editor", children: [
3744
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Edit" }),
3745
+ edit.conflict ? /* @__PURE__ */ jsx11(ConflictBanner, { message: edit.conflict, onReload: edit.onReload }) : null,
3746
+ edit.saveError ? /* @__PURE__ */ jsx11("p", { role: "alert", className: "vos-error", children: edit.saveError }) : null,
3747
+ /* @__PURE__ */ jsx11(
3508
3748
  EditFields,
3509
3749
  {
3510
3750
  register,
@@ -3513,8 +3753,8 @@ function RecordBody({
3513
3753
  onField: edit.onField
3514
3754
  }
3515
3755
  ),
3516
- /* @__PURE__ */ jsxs9("footer", { className: "vos-drawer-footer", children: [
3517
- /* @__PURE__ */ jsx9(
3756
+ /* @__PURE__ */ jsxs10("footer", { className: "vos-drawer-footer", children: [
3757
+ /* @__PURE__ */ jsx11(
3518
3758
  "button",
3519
3759
  {
3520
3760
  type: "button",
@@ -3524,7 +3764,7 @@ function RecordBody({
3524
3764
  children: "Cancel"
3525
3765
  }
3526
3766
  ),
3527
- /* @__PURE__ */ jsx9(
3767
+ /* @__PURE__ */ jsx11(
3528
3768
  "button",
3529
3769
  {
3530
3770
  type: "button",
@@ -3536,10 +3776,10 @@ function RecordBody({
3536
3776
  }
3537
3777
  )
3538
3778
  ] })
3539
- ] }) : /* @__PURE__ */ jsxs9(Fragment8, { children: [
3540
- description ? /* @__PURE__ */ jsxs9("section", { className: "vos-record-prose", children: [
3541
- /* @__PURE__ */ jsx9("h3", { className: "vos-section-title", children: "Description" }),
3542
- /* @__PURE__ */ jsx9("p", { children: /* @__PURE__ */ jsx9(
3779
+ ] }) : /* @__PURE__ */ jsxs10(Fragment8, { children: [
3780
+ description ? /* @__PURE__ */ jsxs10("section", { className: "vos-record-prose", children: [
3781
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Description" }),
3782
+ /* @__PURE__ */ jsx11("p", { children: /* @__PURE__ */ jsx11(
3543
3783
  GlossaryText,
3544
3784
  {
3545
3785
  text: description,
@@ -3549,14 +3789,29 @@ function RecordBody({
3549
3789
  }
3550
3790
  ) })
3551
3791
  ] }) : null,
3552
- page.humanText.length ? /* @__PURE__ */ jsxs9("section", { className: "vos-record-prose", children: [
3553
- /* @__PURE__ */ jsxs9("h3", { className: "vos-section-title", children: [
3792
+ bodyText ? /* @__PURE__ */ jsxs10("section", { className: "vos-record-prose", children: [
3793
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: register === "readings" ? "Quote" : "Narrative" }),
3794
+ /* @__PURE__ */ jsx11(Markdown, { text: bodyText })
3795
+ ] }) : null,
3796
+ register === "readings" ? /* @__PURE__ */ jsxs10("section", { className: "vos-record-prose", children: [
3797
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Per-belief verdicts" }),
3798
+ /* @__PURE__ */ jsx11(
3799
+ BeliefVerdicts,
3800
+ {
3801
+ reading: record,
3802
+ assumptions: related.assumptions ?? [],
3803
+ onOpenRecord
3804
+ }
3805
+ )
3806
+ ] }) : null,
3807
+ page.humanText.length ? /* @__PURE__ */ jsxs10("section", { className: "vos-record-prose", children: [
3808
+ /* @__PURE__ */ jsxs10("h3", { className: "vos-section-title", children: [
3554
3809
  "From a human ",
3555
- /* @__PURE__ */ jsx9("span", { className: "vos-hint", children: "\u2014 not computed" })
3810
+ /* @__PURE__ */ jsx11("span", { className: "vos-hint", children: "\u2014 not computed" })
3556
3811
  ] }),
3557
- page.humanText.map((h) => /* @__PURE__ */ jsxs9("div", { className: "vos-human-field", children: [
3558
- /* @__PURE__ */ jsx9("div", { className: "vos-detail-k", children: h.label }),
3559
- /* @__PURE__ */ jsx9("p", { children: /* @__PURE__ */ jsx9(
3812
+ page.humanText.map((h) => /* @__PURE__ */ jsxs10("div", { className: "vos-human-field", children: [
3813
+ /* @__PURE__ */ jsx11("div", { className: "vos-detail-k", children: h.label }),
3814
+ /* @__PURE__ */ jsx11("p", { children: /* @__PURE__ */ jsx11(
3560
3815
  GlossaryText,
3561
3816
  {
3562
3817
  text: h.text,
@@ -3569,7 +3824,7 @@ function RecordBody({
3569
3824
  ] }) : null
3570
3825
  ] })
3571
3826
  ] }) : null,
3572
- activeTab === "evidence" ? /* @__PURE__ */ jsx9(
3827
+ activeTab === "evidence" ? /* @__PURE__ */ jsx11(
3573
3828
  EvidenceTab,
3574
3829
  {
3575
3830
  register,
@@ -3579,25 +3834,25 @@ function RecordBody({
3579
3834
  basePath
3580
3835
  }
3581
3836
  ) : null,
3582
- activeTab === "connections" ? /* @__PURE__ */ jsx9("div", { className: "vos-panels", children: page.panels.map((panel) => /* @__PURE__ */ jsx9(PanelView, { panel, onOpenRecord }, panel.id)) }) : null,
3583
- activeTab === "history" ? /* @__PURE__ */ jsxs9("section", { className: "vos-detail-list", children: [
3584
- /* @__PURE__ */ jsxs9("div", { className: "vos-detail-row", children: [
3585
- /* @__PURE__ */ jsx9("span", { className: "vos-detail-k", children: "Created" }),
3586
- /* @__PURE__ */ jsx9("span", { className: "vos-detail-v", children: formatValue(record.createdAt) })
3837
+ activeTab === "connections" ? /* @__PURE__ */ jsx11("div", { className: "vos-panels", children: page.panels.map((panel) => /* @__PURE__ */ jsx11(PanelView, { panel, onOpenRecord }, panel.id)) }) : null,
3838
+ activeTab === "history" ? /* @__PURE__ */ jsxs10("section", { className: "vos-detail-list", children: [
3839
+ /* @__PURE__ */ jsxs10("div", { className: "vos-detail-row", children: [
3840
+ /* @__PURE__ */ jsx11("span", { className: "vos-detail-k", children: "Created" }),
3841
+ /* @__PURE__ */ jsx11("span", { className: "vos-detail-v", children: formatValue(record.createdAt) })
3587
3842
  ] }),
3588
- /* @__PURE__ */ jsxs9("div", { className: "vos-detail-row", children: [
3589
- /* @__PURE__ */ jsx9("span", { className: "vos-detail-k", children: "Last updated" }),
3590
- /* @__PURE__ */ jsx9("span", { className: "vos-detail-v", children: formatValue(record.updatedAt) })
3843
+ /* @__PURE__ */ jsxs10("div", { className: "vos-detail-row", children: [
3844
+ /* @__PURE__ */ jsx11("span", { className: "vos-detail-k", children: "Last updated" }),
3845
+ /* @__PURE__ */ jsx11("span", { className: "vos-detail-v", children: formatValue(record.updatedAt) })
3591
3846
  ] }),
3592
- /* @__PURE__ */ jsxs9("div", { className: "vos-detail-row", children: [
3593
- /* @__PURE__ */ jsx9("span", { className: "vos-detail-k", children: "Version" }),
3594
- /* @__PURE__ */ jsx9("span", { className: "vos-detail-v", children: formatValue(record.version) })
3847
+ /* @__PURE__ */ jsxs10("div", { className: "vos-detail-row", children: [
3848
+ /* @__PURE__ */ jsx11("span", { className: "vos-detail-k", children: "Version" }),
3849
+ /* @__PURE__ */ jsx11("span", { className: "vos-detail-v", children: formatValue(record.version) })
3595
3850
  ] }),
3596
- /* @__PURE__ */ jsx9("p", { className: "vos-hint", children: "The full change trail lands here as the API exposes version history; this absorbs the retired provenance prose." })
3851
+ /* @__PURE__ */ jsx11("p", { className: "vos-hint", children: "The full change trail lands here as the API exposes version history; this absorbs the retired provenance prose." })
3597
3852
  ] }) : null,
3598
- page.hasJourney && journey ? /* @__PURE__ */ jsxs9("section", { className: "vos-journey-host", children: [
3599
- /* @__PURE__ */ jsx9("h3", { className: "vos-section-title", children: "Validation journey" }),
3600
- /* @__PURE__ */ jsx9(
3853
+ page.hasJourney && journey ? /* @__PURE__ */ jsxs10("section", { className: "vos-journey-host", children: [
3854
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Validation journey" }),
3855
+ /* @__PURE__ */ jsx11(
3601
3856
  BeliefJourney,
3602
3857
  {
3603
3858
  journey,
@@ -3607,22 +3862,22 @@ function RecordBody({
3607
3862
  onChanged: onJourneyChanged
3608
3863
  }
3609
3864
  )
3610
- ] }) : page.hasJourney ? /* @__PURE__ */ jsxs9("section", { className: "vos-journey-host", children: [
3611
- /* @__PURE__ */ jsx9("h3", { className: "vos-section-title", children: "Validation journey" }),
3612
- /* @__PURE__ */ jsx9("p", { className: "vos-hint", children: "The per-belief journey (Framed \u2192 Planned \u2192 Tested \u2192 Known) mounts here \u2014 built by the workflow-first map (OPS-1289). This page is its host." })
3865
+ ] }) : page.hasJourney ? /* @__PURE__ */ jsxs10("section", { className: "vos-journey-host", children: [
3866
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Validation journey" }),
3867
+ /* @__PURE__ */ jsx11("p", { className: "vos-hint", children: "The per-belief journey (Framed \u2192 Planned \u2192 Tested \u2192 Known) mounts here \u2014 built by the workflow-first map (OPS-1289). This page is its host." })
3613
3868
  ] }) : null
3614
3869
  ] });
3615
3870
  }
3616
3871
  function PillView({ pill }) {
3617
- return /* @__PURE__ */ jsx9("span", { className: PILL_CLASS3[pill.tone], children: pill.label });
3872
+ return /* @__PURE__ */ jsx11("span", { className: PILL_CLASS3[pill.tone], children: pill.label });
3618
3873
  }
3619
3874
  function ConflictBanner({
3620
3875
  message,
3621
3876
  onReload
3622
3877
  }) {
3623
- return /* @__PURE__ */ jsxs9("div", { role: "alert", className: "vos-banner vos-banner-warn", children: [
3624
- /* @__PURE__ */ jsx9("div", { className: "vos-banner-body", children: /* @__PURE__ */ jsx9("span", { children: message }) }),
3625
- /* @__PURE__ */ jsx9("button", { type: "button", onClick: onReload, children: "Review the latest" })
3878
+ return /* @__PURE__ */ jsxs10("div", { role: "alert", className: "vos-banner vos-banner-warn", children: [
3879
+ /* @__PURE__ */ jsx11("div", { className: "vos-banner-body", children: /* @__PURE__ */ jsx11("span", { children: message }) }),
3880
+ /* @__PURE__ */ jsx11("button", { type: "button", onClick: onReload, children: "Review the latest" })
3626
3881
  ] });
3627
3882
  }
3628
3883
  function MeterView({
@@ -3632,10 +3887,10 @@ function MeterView({
3632
3887
  }) {
3633
3888
  const [why, setWhy] = useState5(false);
3634
3889
  const textTone = meter.tone === "crit" ? "vos-text-crit" : meter.tone === "warn" ? "vos-text-warn" : "";
3635
- return /* @__PURE__ */ jsxs9("div", { className: "vos-meter", children: [
3636
- /* @__PURE__ */ jsxs9("div", { className: "vos-meter-head", children: [
3637
- /* @__PURE__ */ jsx9("span", { className: "vos-meter-label", children: meter.label }),
3638
- meter.hasWhy && assumption ? /* @__PURE__ */ jsxs9(
3890
+ return /* @__PURE__ */ jsxs10("div", { className: "vos-meter", children: [
3891
+ /* @__PURE__ */ jsxs10("div", { className: "vos-meter-head", children: [
3892
+ /* @__PURE__ */ jsx11("span", { className: "vos-meter-label", children: meter.label }),
3893
+ meter.hasWhy && assumption ? /* @__PURE__ */ jsxs10(
3639
3894
  "button",
3640
3895
  {
3641
3896
  type: "button",
@@ -3649,12 +3904,12 @@ function MeterView({
3649
3904
  }
3650
3905
  ) : null
3651
3906
  ] }),
3652
- meter.value === null ? /* @__PURE__ */ jsx9("div", { className: "vos-meter-val vos-muted", children: "\u2014" }) : meter.kind === "pill" ? /* @__PURE__ */ jsx9("span", { className: PILL_CLASS3[meter.tone], children: meter.value }) : meter.kind === "signed" ? /* @__PURE__ */ jsxs9(Fragment8, { children: [
3653
- /* @__PURE__ */ jsx9("div", { className: `vos-meter-val ${textTone}`, children: formatSigned(Number(meter.value)) }),
3654
- /* @__PURE__ */ jsx9("span", { className: "vos-track vos-signed", children: /* @__PURE__ */ jsx9(SignedFill, { value: Number(meter.value), min: meter.min ?? -100, max: meter.max ?? 100 }) })
3655
- ] }) : /* @__PURE__ */ jsxs9(Fragment8, { children: [
3656
- /* @__PURE__ */ jsx9("div", { className: `vos-meter-val ${textTone}`, children: Math.round(Number(meter.value)) }),
3657
- /* @__PURE__ */ jsx9("span", { className: "vos-risk-bar", children: /* @__PURE__ */ jsx9(
3907
+ meter.value === null ? /* @__PURE__ */ jsx11("div", { className: "vos-meter-val vos-muted", children: "\u2014" }) : meter.kind === "pill" ? /* @__PURE__ */ jsx11("span", { className: PILL_CLASS3[meter.tone], children: meter.value }) : meter.kind === "signed" ? /* @__PURE__ */ jsxs10(Fragment8, { children: [
3908
+ /* @__PURE__ */ jsx11("div", { className: `vos-meter-val ${textTone}`, children: formatSigned(Number(meter.value)) }),
3909
+ /* @__PURE__ */ jsx11("span", { className: "vos-track vos-signed", children: /* @__PURE__ */ jsx11(SignedFill, { value: Number(meter.value), min: meter.min ?? -100, max: meter.max ?? 100 }) })
3910
+ ] }) : /* @__PURE__ */ jsxs10(Fragment8, { children: [
3911
+ /* @__PURE__ */ jsx11("div", { className: `vos-meter-val ${textTone}`, children: Math.round(Number(meter.value)) }),
3912
+ /* @__PURE__ */ jsx11("span", { className: "vos-risk-bar", children: /* @__PURE__ */ jsx11(
3658
3913
  "i",
3659
3914
  {
3660
3915
  className: meter.tone === "crit" ? "vos-fill-crit" : meter.tone === "warn" ? "vos-fill-warn" : "vos-fill-good",
@@ -3662,7 +3917,7 @@ function MeterView({
3662
3917
  }
3663
3918
  ) })
3664
3919
  ] }),
3665
- why && assumption ? /* @__PURE__ */ jsx9("div", { className: "vos-why-panel", children: /* @__PURE__ */ jsx9(UnderstandingPanel, { assumption, basePath }) }) : null
3920
+ why && assumption ? /* @__PURE__ */ jsx11("div", { className: "vos-why-panel", children: /* @__PURE__ */ jsx11(UnderstandingPanel, { assumption, basePath }) }) : null
3666
3921
  ] });
3667
3922
  }
3668
3923
  function SignedFill({ value, min, max }) {
@@ -3670,34 +3925,34 @@ function SignedFill({ value, min, max }) {
3670
3925
  const width = Math.round(Math.min(Math.abs(value), span) / span * 50);
3671
3926
  const up = value >= 0;
3672
3927
  const style = up ? { left: "50%", width: `${width}%`, background: "var(--vos-good)" } : { right: "50%", width: `${width}%`, background: "var(--vos-crit)" };
3673
- return width > 0 ? /* @__PURE__ */ jsx9("i", { style }) : null;
3928
+ return width > 0 ? /* @__PURE__ */ jsx11("i", { style }) : null;
3674
3929
  }
3675
3930
  function PanelView({
3676
3931
  panel,
3677
3932
  onOpenRecord
3678
3933
  }) {
3679
- return /* @__PURE__ */ jsxs9("section", { className: "vos-panel", children: [
3680
- /* @__PURE__ */ jsxs9("h3", { className: "vos-panel-head", children: [
3934
+ return /* @__PURE__ */ jsxs10("section", { className: "vos-panel", children: [
3935
+ /* @__PURE__ */ jsxs10("h3", { className: "vos-panel-head", children: [
3681
3936
  panel.label,
3682
- /* @__PURE__ */ jsx9("span", { className: "vos-group-n", children: panel.items.length })
3937
+ /* @__PURE__ */ jsx11("span", { className: "vos-group-n", children: panel.items.length })
3683
3938
  ] }),
3684
- panel.items.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "vos-hint", children: "None yet." }) : /* @__PURE__ */ jsx9("ul", { className: "vos-backlinks", children: panel.items.map((item) => /* @__PURE__ */ jsx9(BacklinkRow, { item, onOpenRecord }, item.id)) })
3939
+ panel.items.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "vos-hint", children: "None yet." }) : /* @__PURE__ */ jsx11("ul", { className: "vos-backlinks", children: panel.items.map((item) => /* @__PURE__ */ jsx11(BacklinkRow, { item, onOpenRecord }, item.id)) })
3685
3940
  ] });
3686
3941
  }
3687
3942
  function BacklinkRow({
3688
3943
  item,
3689
3944
  onOpenRecord
3690
3945
  }) {
3691
- return /* @__PURE__ */ jsx9("li", { children: /* @__PURE__ */ jsxs9(
3946
+ return /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsxs10(
3692
3947
  "button",
3693
3948
  {
3694
3949
  type: "button",
3695
3950
  className: "vos-backlink",
3696
3951
  onClick: () => onOpenRecord(item.id),
3697
3952
  children: [
3698
- /* @__PURE__ */ jsx9("span", { className: "vos-backlink-title", children: item.title }),
3699
- /* @__PURE__ */ jsxs9("span", { className: `vos-chip ${PILL_CLASS3[item.chip.tone]}`, children: [
3700
- /* @__PURE__ */ jsx9("span", { className: "vos-chip-k", children: item.chip.label }),
3953
+ /* @__PURE__ */ jsx11("span", { className: "vos-backlink-title", children: item.title }),
3954
+ /* @__PURE__ */ jsxs10("span", { className: `vos-chip ${PILL_CLASS3[item.chip.tone]}`, children: [
3955
+ /* @__PURE__ */ jsx11("span", { className: "vos-chip-k", children: item.chip.label }),
3701
3956
  item.chip.value
3702
3957
  ] })
3703
3958
  ]
@@ -3712,7 +3967,7 @@ function EvidenceTab({
3712
3967
  basePath
3713
3968
  }) {
3714
3969
  if (register === "assumptions") {
3715
- return /* @__PURE__ */ jsx9("section", { className: "vos-why-panel", children: /* @__PURE__ */ jsx9(UnderstandingPanel, { assumption: record, basePath }) });
3970
+ return /* @__PURE__ */ jsx11("section", { className: "vos-why-panel", children: /* @__PURE__ */ jsx11(UnderstandingPanel, { assumption: record, basePath }) });
3716
3971
  }
3717
3972
  const bars = resolveBarLines(
3718
3973
  record.barLines ?? [],
@@ -3720,12 +3975,12 @@ function EvidenceTab({
3720
3975
  );
3721
3976
  const mine = (related.readings ?? []).filter((r) => r.experimentId === record.id);
3722
3977
  const nested = nestReadingsByPlan(mine, [record]);
3723
- return /* @__PURE__ */ jsxs9("div", { className: "vos-record-cols", children: [
3724
- /* @__PURE__ */ jsxs9("section", { children: [
3725
- /* @__PURE__ */ jsx9("h3", { className: "vos-section-title", children: "Bar lines" }),
3726
- bars.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "vos-hint", children: "No pre-registered bars." }) : /* @__PURE__ */ jsx9("ul", { className: "vos-bars", children: bars.map((b, i) => /* @__PURE__ */ jsxs9("li", { className: "vos-bar-line", children: [
3727
- /* @__PURE__ */ jsx9("span", { className: "vos-bar-if", children: b.rightIf || "\u2014" }),
3728
- b.assumption ? /* @__PURE__ */ jsx9(
3978
+ return /* @__PURE__ */ jsxs10("div", { className: "vos-record-cols", children: [
3979
+ /* @__PURE__ */ jsxs10("section", { children: [
3980
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Bar lines" }),
3981
+ bars.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "vos-hint", children: "No pre-registered bars." }) : /* @__PURE__ */ jsx11("ul", { className: "vos-bars", children: bars.map((b, i) => /* @__PURE__ */ jsxs10("li", { className: "vos-bar-line", children: [
3982
+ /* @__PURE__ */ jsx11("span", { className: "vos-bar-if", children: b.rightIf || "\u2014" }),
3983
+ b.assumption ? /* @__PURE__ */ jsx11(
3729
3984
  "button",
3730
3985
  {
3731
3986
  type: "button",
@@ -3734,7 +3989,7 @@ function EvidenceTab({
3734
3989
  children: b.assumption.title
3735
3990
  }
3736
3991
  ) : null,
3737
- /* @__PURE__ */ jsx9(
3992
+ /* @__PURE__ */ jsx11(
3738
3993
  "span",
3739
3994
  {
3740
3995
  className: b.barVerdict ? "vos-pill vos-pill-good" : "vos-pill vos-pill-neutral",
@@ -3743,17 +3998,21 @@ function EvidenceTab({
3743
3998
  )
3744
3999
  ] }, i)) })
3745
4000
  ] }),
3746
- /* @__PURE__ */ jsxs9("section", { children: [
3747
- /* @__PURE__ */ jsx9("h3", { className: "vos-section-title", children: "Readings" }),
3748
- nested.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "vos-hint", children: "No readings logged yet." }) : /* @__PURE__ */ jsx9("ul", { className: "vos-backlinks", children: nested[0].readings.map((r) => /* @__PURE__ */ jsx9("li", { children: /* @__PURE__ */ jsxs9(
4001
+ /* @__PURE__ */ jsxs10("section", { children: [
4002
+ /* @__PURE__ */ jsx11("h3", { className: "vos-section-title", children: "Readings" }),
4003
+ nested.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "vos-hint", children: "No readings logged yet." }) : /* @__PURE__ */ jsx11("ul", { className: "vos-backlinks", children: nested[0].readings.map((r) => /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsxs10(
3749
4004
  "button",
3750
4005
  {
3751
4006
  type: "button",
3752
4007
  className: "vos-backlink",
3753
4008
  onClick: () => onOpenRecord(r.id),
3754
4009
  children: [
3755
- /* @__PURE__ */ jsx9("span", { className: "vos-backlink-title", children: formatValue(r.Title) }),
3756
- /* @__PURE__ */ jsx9("span", { className: "vos-chip vos-pill vos-pill-neutral", children: formatValue(r.Result) })
4010
+ /* @__PURE__ */ jsx11("span", { className: "vos-backlink-title", children: formatValue(r.Title) }),
4011
+ /* @__PURE__ */ jsxs10("span", { className: "vos-chip vos-pill vos-pill-neutral", children: [
4012
+ readingBeliefs(r).length,
4013
+ " belief",
4014
+ readingBeliefs(r).length === 1 ? "" : "s"
4015
+ ] })
3757
4016
  ]
3758
4017
  }
3759
4018
  ) }, r.id)) })
@@ -3765,19 +4024,20 @@ function EvidenceTab({
3765
4024
  import { useMemo as useMemo4, useState as useState10 } from "react";
3766
4025
 
3767
4026
  // src/register-table.tsx
3768
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
4027
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
3769
4028
  function RegisterTable({
3770
4029
  register,
3771
4030
  records,
3772
4031
  onRowClick,
3773
- selectedId
4032
+ selectedId,
4033
+ assumptionTitles
3774
4034
  }) {
3775
4035
  const columns = columnsFor(register);
3776
4036
  if (records.length === 0) {
3777
- return /* @__PURE__ */ jsx10("p", { className: "vos-empty", children: "No records yet." });
4037
+ return /* @__PURE__ */ jsx12("p", { className: "vos-empty", children: "No records yet." });
3778
4038
  }
3779
- return /* @__PURE__ */ jsx10("div", { className: "vos-card vos-table-scroll", children: /* @__PURE__ */ jsxs10("table", { className: "vos-table", children: [
3780
- /* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsx10("tr", { children: columns.map((c) => /* @__PURE__ */ jsx10(
4039
+ return /* @__PURE__ */ jsx12("div", { className: "vos-card vos-table-scroll", children: /* @__PURE__ */ jsxs11("table", { className: "vos-table", children: [
4040
+ /* @__PURE__ */ jsx12("thead", { children: /* @__PURE__ */ jsx12("tr", { children: columns.map((c) => /* @__PURE__ */ jsx12(
3781
4041
  "th",
3782
4042
  {
3783
4043
  scope: "col",
@@ -3786,9 +4046,9 @@ function RegisterTable({
3786
4046
  },
3787
4047
  c.key
3788
4048
  )) }) }),
3789
- /* @__PURE__ */ jsx10("tbody", { children: records.map((record) => {
4049
+ /* @__PURE__ */ jsx12("tbody", { children: records.map((record) => {
3790
4050
  const isSelected = record.id === selectedId;
3791
- return /* @__PURE__ */ jsx10(
4051
+ return /* @__PURE__ */ jsx12(
3792
4052
  "tr",
3793
4053
  {
3794
4054
  onClick: () => onRowClick?.(record.id),
@@ -3801,11 +4061,19 @@ function RegisterTable({
3801
4061
  tabIndex: onRowClick ? 0 : void 0,
3802
4062
  "aria-selected": isSelected,
3803
4063
  className: isSelected ? "is-selected" : void 0,
3804
- children: columns.map((c, i) => /* @__PURE__ */ jsx10(
4064
+ children: columns.map((c, i) => /* @__PURE__ */ jsx12(
3805
4065
  "td",
3806
4066
  {
3807
4067
  className: c.align === "right" ? "vos-r" : void 0,
3808
- children: /* @__PURE__ */ jsx10(Cell, { column: c, record, headline: i === 0 })
4068
+ children: /* @__PURE__ */ jsx12(
4069
+ Cell,
4070
+ {
4071
+ column: c,
4072
+ record,
4073
+ headline: i === 0,
4074
+ chips: i === 0 && register === "readings" ? readingAssumptionChips(record, assumptionTitles) : void 0
4075
+ }
4076
+ )
3809
4077
  },
3810
4078
  c.key
3811
4079
  ))
@@ -3818,25 +4086,32 @@ function RegisterTable({
3818
4086
  function Cell({
3819
4087
  column,
3820
4088
  record,
3821
- headline
4089
+ headline,
4090
+ chips
3822
4091
  }) {
3823
4092
  const raw = cellValue(column, record);
3824
4093
  if (column.kind === "status") {
3825
- return /* @__PURE__ */ jsx10(StatusPill, { status: raw == null ? null : String(raw) });
4094
+ return /* @__PURE__ */ jsx12(StatusPill, { status: raw == null ? null : String(raw) });
3826
4095
  }
3827
4096
  if (column.kind === "risk") {
3828
- return typeof raw === "number" ? /* @__PURE__ */ jsx10(RiskBar, { risk: raw }) : /* @__PURE__ */ jsx10("span", { className: "vos-muted", children: "\u2014" });
4097
+ return typeof raw === "number" ? /* @__PURE__ */ jsx12(RiskBar, { risk: raw }) : /* @__PURE__ */ jsx12("span", { className: "vos-muted", children: "\u2014" });
3829
4098
  }
3830
4099
  if (column.kind === "confidence") {
3831
- return typeof raw === "number" ? /* @__PURE__ */ jsx10(ConfidenceCell, { confidence: raw }) : /* @__PURE__ */ jsx10("span", { className: "vos-muted", children: "\u2014" });
4100
+ return typeof raw === "number" ? /* @__PURE__ */ jsx12(ConfidenceCell, { confidence: raw }) : /* @__PURE__ */ jsx12("span", { className: "vos-muted", children: "\u2014" });
3832
4101
  }
3833
4102
  const text = headline && (raw === null || raw === void 0 || raw === "") ? primaryLabel(record) : formatValue(raw);
3834
- return /* @__PURE__ */ jsx10("span", { className: headline ? "vos-ttl" : void 0, children: text });
4103
+ if (headline && chips && chips.length > 0) {
4104
+ return /* @__PURE__ */ jsxs11("span", { className: "vos-ttl-wrap", children: [
4105
+ /* @__PURE__ */ jsx12("span", { className: "vos-ttl", children: text }),
4106
+ /* @__PURE__ */ jsx12("span", { className: "vos-reading-chips", children: chips.map((chip, n) => /* @__PURE__ */ jsx12("span", { className: "vos-chip vos-pill vos-pill-neutral", children: chip }, n)) })
4107
+ ] });
4108
+ }
4109
+ return /* @__PURE__ */ jsx12("span", { className: headline ? "vos-ttl" : void 0, children: text });
3835
4110
  }
3836
4111
 
3837
4112
  // src/record-drawer.tsx
3838
4113
  import { useEffect as useEffect3, useState as useState6 } from "react";
3839
- import { Fragment as Fragment9, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
4114
+ import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
3840
4115
  var DERIVED_SUB = {
3841
4116
  confidence: "Signed average of concluded readings",
3842
4117
  risk: "Impact \xD7 (1 \u2212 Confidence\u207A/100)",
@@ -3909,23 +4184,23 @@ function RecordDrawer({
3909
4184
  const setField = (key, value) => setDraft((d) => ({ ...d, [key]: value }));
3910
4185
  const errors = editing ? draftErrors(register, draft) : {};
3911
4186
  const hasErrors = Object.keys(errors).length > 0;
3912
- return /* @__PURE__ */ jsxs11(
4187
+ return /* @__PURE__ */ jsxs12(
3913
4188
  DrawerShell,
3914
4189
  {
3915
4190
  open,
3916
4191
  onClose,
3917
4192
  ariaLabel: `${REGISTER_LABEL[register]} record`,
3918
4193
  children: [
3919
- /* @__PURE__ */ jsxs11("header", { className: "vos-drawer-header", children: [
3920
- /* @__PURE__ */ jsxs11("div", { style: { flex: 1, minWidth: 0 }, children: [
3921
- /* @__PURE__ */ jsx11("p", { className: "vos-drawer-eyebrow", children: REGISTER_LABEL[register] }),
3922
- /* @__PURE__ */ jsx11("h2", { className: "vos-drawer-title", children: record ? primaryLabel(record) : loading ? "Loading\u2026" : "\u2014" })
4194
+ /* @__PURE__ */ jsxs12("header", { className: "vos-drawer-header", children: [
4195
+ /* @__PURE__ */ jsxs12("div", { style: { flex: 1, minWidth: 0 }, children: [
4196
+ /* @__PURE__ */ jsx13("p", { className: "vos-drawer-eyebrow", children: REGISTER_LABEL[register] }),
4197
+ /* @__PURE__ */ jsx13("h2", { className: "vos-drawer-title", children: record ? primaryLabel(record) : loading ? "Loading\u2026" : "\u2014" })
3923
4198
  ] }),
3924
- record ? /* @__PURE__ */ jsxs11("span", { className: "vos-verbadge", children: [
4199
+ record ? /* @__PURE__ */ jsxs12("span", { className: "vos-verbadge", children: [
3925
4200
  "v",
3926
4201
  formatValue(record.version)
3927
4202
  ] }) : null,
3928
- record && !editing && onOpenFull ? /* @__PURE__ */ jsx11(
4203
+ record && !editing && onOpenFull ? /* @__PURE__ */ jsx13(
3929
4204
  "button",
3930
4205
  {
3931
4206
  type: "button",
@@ -3934,7 +4209,7 @@ function RecordDrawer({
3934
4209
  children: "Full page \u2197"
3935
4210
  }
3936
4211
  ) : null,
3937
- record && !editing ? /* @__PURE__ */ jsx11(
4212
+ record && !editing ? /* @__PURE__ */ jsx13(
3938
4213
  "button",
3939
4214
  {
3940
4215
  type: "button",
@@ -3943,7 +4218,7 @@ function RecordDrawer({
3943
4218
  children: "Edit"
3944
4219
  }
3945
4220
  ) : null,
3946
- /* @__PURE__ */ jsx11(
4221
+ /* @__PURE__ */ jsx13(
3947
4222
  "button",
3948
4223
  {
3949
4224
  type: "button",
@@ -3954,14 +4229,14 @@ function RecordDrawer({
3954
4229
  }
3955
4230
  )
3956
4231
  ] }),
3957
- /* @__PURE__ */ jsx11("div", { className: "vos-drawer-body", children: loading ? /* @__PURE__ */ jsx11("p", { className: "vos-muted", children: "Loading record\u2026" }) : error ? /* @__PURE__ */ jsx11("p", { className: "vos-error", children: error }) : !record ? /* @__PURE__ */ jsx11("p", { className: "vos-muted", children: "No record." }) : /* @__PURE__ */ jsxs11(Fragment9, { children: [
3958
- derived ? /* @__PURE__ */ jsxs11("div", { children: [
3959
- /* @__PURE__ */ jsxs11("div", { className: "vos-derived", children: [
3960
- /* @__PURE__ */ jsxs11("div", { className: "vos-derived-head", children: [
4232
+ /* @__PURE__ */ jsx13("div", { className: "vos-drawer-body", children: loading ? /* @__PURE__ */ jsx13("p", { className: "vos-muted", children: "Loading record\u2026" }) : error ? /* @__PURE__ */ jsx13("p", { className: "vos-error", children: error }) : !record ? /* @__PURE__ */ jsx13("p", { className: "vos-muted", children: "No record." }) : /* @__PURE__ */ jsxs12(Fragment9, { children: [
4233
+ derived ? /* @__PURE__ */ jsxs12("div", { children: [
4234
+ /* @__PURE__ */ jsxs12("div", { className: "vos-derived", children: [
4235
+ /* @__PURE__ */ jsxs12("div", { className: "vos-derived-head", children: [
3961
4236
  "Derived",
3962
- /* @__PURE__ */ jsx11("span", { className: "vos-lock", children: "\u{1F512} computed on write \u2014 not editable" })
4237
+ /* @__PURE__ */ jsx13("span", { className: "vos-lock", children: "\u{1F512} computed on write \u2014 not editable" })
3963
4238
  ] }),
3964
- /* @__PURE__ */ jsx11("div", { className: "vos-dgrid", children: Object.entries(derived).map(([key, value]) => /* @__PURE__ */ jsx11(
4239
+ /* @__PURE__ */ jsx13("div", { className: "vos-dgrid", children: Object.entries(derived).map(([key, value]) => /* @__PURE__ */ jsx13(
3965
4240
  DerivedCell,
3966
4241
  {
3967
4242
  field: key,
@@ -3973,11 +4248,11 @@ function RecordDrawer({
3973
4248
  key
3974
4249
  )) })
3975
4250
  ] }),
3976
- "confidence" in derived && why ? /* @__PURE__ */ jsx11("div", { className: "vos-why-panel", children: /* @__PURE__ */ jsx11(UnderstandingPanel, { assumption: record, basePath }) }) : null
4251
+ "confidence" in derived && why ? /* @__PURE__ */ jsx13("div", { className: "vos-why-panel", children: /* @__PURE__ */ jsx13(UnderstandingPanel, { assumption: record, basePath }) }) : null
3977
4252
  ] }) : null,
3978
- conflict ? /* @__PURE__ */ jsx11(ConflictBanner2, { message: conflict, onReload: reloadLatest }) : null,
3979
- saveError ? /* @__PURE__ */ jsx11("p", { role: "alert", className: "vos-banner vos-banner-crit", children: saveError }) : null,
3980
- editing ? /* @__PURE__ */ jsx11(
4253
+ conflict ? /* @__PURE__ */ jsx13(ConflictBanner2, { message: conflict, onReload: reloadLatest }) : null,
4254
+ saveError ? /* @__PURE__ */ jsx13("p", { role: "alert", className: "vos-banner vos-banner-crit", children: saveError }) : null,
4255
+ editing ? /* @__PURE__ */ jsx13(
3981
4256
  EditFields,
3982
4257
  {
3983
4258
  register,
@@ -3985,18 +4260,35 @@ function RecordDrawer({
3985
4260
  errors,
3986
4261
  onField: setField
3987
4262
  }
3988
- ) : /* @__PURE__ */ jsx11("div", { className: "vos-detail-list", children: rows.map((row) => /* @__PURE__ */ jsx11(
3989
- DetailRowView,
3990
- {
3991
- row,
3992
- onOpenRecord
3993
- },
3994
- row.key
3995
- )) })
4263
+ ) : /* @__PURE__ */ jsxs12(Fragment9, { children: [
4264
+ /* @__PURE__ */ jsx13("div", { className: "vos-detail-list", children: rows.map((row) => /* @__PURE__ */ jsx13(
4265
+ DetailRowView,
4266
+ {
4267
+ row,
4268
+ onOpenRecord
4269
+ },
4270
+ row.key
4271
+ )) }),
4272
+ typeof record.body === "string" && record.body.trim() ? /* @__PURE__ */ jsxs12("section", { className: "vos-record-prose", children: [
4273
+ /* @__PURE__ */ jsx13("div", { className: "vos-detail-k", children: register === "readings" ? "Quote" : "Narrative" }),
4274
+ /* @__PURE__ */ jsx13(Markdown, { text: record.body })
4275
+ ] }) : null,
4276
+ register === "readings" ? /* @__PURE__ */ jsxs12("section", { className: "vos-record-prose", children: [
4277
+ /* @__PURE__ */ jsx13("div", { className: "vos-detail-k", children: "Per-belief verdicts" }),
4278
+ /* @__PURE__ */ jsx13(
4279
+ BeliefVerdicts,
4280
+ {
4281
+ reading: record,
4282
+ assumptions: related?.assumptions ?? [],
4283
+ onOpenRecord
4284
+ }
4285
+ )
4286
+ ] }) : null
4287
+ ] })
3996
4288
  ] }) }),
3997
4289
  record && !loading && !error && !editing ? children : null,
3998
- record && editing ? /* @__PURE__ */ jsxs11("footer", { className: "vos-drawer-footer", children: [
3999
- /* @__PURE__ */ jsx11(
4290
+ record && editing ? /* @__PURE__ */ jsxs12("footer", { className: "vos-drawer-footer", children: [
4291
+ /* @__PURE__ */ jsx13(
4000
4292
  "button",
4001
4293
  {
4002
4294
  type: "button",
@@ -4006,7 +4298,7 @@ function RecordDrawer({
4006
4298
  children: "Cancel"
4007
4299
  }
4008
4300
  ),
4009
- /* @__PURE__ */ jsx11(
4301
+ /* @__PURE__ */ jsx13(
4010
4302
  "button",
4011
4303
  {
4012
4304
  type: "button",
@@ -4017,7 +4309,7 @@ function RecordDrawer({
4017
4309
  children: saving ? "Saving\u2026" : "Save"
4018
4310
  }
4019
4311
  )
4020
- ] }) : record ? /* @__PURE__ */ jsxs11("footer", { className: "vos-drawer-footer", children: [
4312
+ ] }) : record ? /* @__PURE__ */ jsxs12("footer", { className: "vos-drawer-footer", children: [
4021
4313
  record.id,
4022
4314
  " \xB7 updated ",
4023
4315
  formatValue(record.updatedAt)
@@ -4030,11 +4322,11 @@ function DetailRowView({
4030
4322
  row,
4031
4323
  onOpenRecord
4032
4324
  }) {
4033
- return /* @__PURE__ */ jsxs11("div", { className: "vos-detail-row", children: [
4034
- /* @__PURE__ */ jsx11("span", { className: "vos-detail-k", children: row.label }),
4035
- /* @__PURE__ */ jsx11("span", { className: "vos-detail-v", children: row.kind === "relation" ? row.items && row.items.length ? /* @__PURE__ */ jsx11(RelationLinks, { items: row.items, onOpenRecord }) : "\u2014" : row.kind === "owner" ? row.names && row.names.length ? row.names.join(", ") : "\u2014" : row.kind === "bar-lines" ? row.bars && row.bars.length ? /* @__PURE__ */ jsx11("ul", { className: "vos-bars", children: row.bars.map((b, i) => /* @__PURE__ */ jsxs11("li", { className: "vos-bar-line", children: [
4036
- /* @__PURE__ */ jsx11("span", { className: "vos-bar-if", children: b.rightIf || "\u2014" }),
4037
- b.assumption ? /* @__PURE__ */ jsx11(
4325
+ return /* @__PURE__ */ jsxs12("div", { className: "vos-detail-row", children: [
4326
+ /* @__PURE__ */ jsx13("span", { className: "vos-detail-k", children: row.label }),
4327
+ /* @__PURE__ */ jsx13("span", { className: "vos-detail-v", children: row.kind === "relation" ? row.items && row.items.length ? /* @__PURE__ */ jsx13(RelationLinks, { items: row.items, onOpenRecord }) : "\u2014" : row.kind === "owner" ? row.names && row.names.length ? row.names.join(", ") : "\u2014" : row.kind === "bar-lines" ? row.bars && row.bars.length ? /* @__PURE__ */ jsx13("ul", { className: "vos-bars", children: row.bars.map((b, i) => /* @__PURE__ */ jsxs12("li", { className: "vos-bar-line", children: [
4328
+ /* @__PURE__ */ jsx13("span", { className: "vos-bar-if", children: b.rightIf || "\u2014" }),
4329
+ b.assumption ? /* @__PURE__ */ jsx13(
4038
4330
  InlineLink,
4039
4331
  {
4040
4332
  id: b.assumption.id,
@@ -4042,7 +4334,7 @@ function DetailRowView({
4042
4334
  onOpenRecord
4043
4335
  }
4044
4336
  ) : null,
4045
- /* @__PURE__ */ jsx11(
4337
+ /* @__PURE__ */ jsx13(
4046
4338
  "span",
4047
4339
  {
4048
4340
  className: b.barVerdict ? "vos-pill vos-pill-good" : "vos-pill vos-pill-neutral",
@@ -4056,9 +4348,9 @@ function RelationLinks({
4056
4348
  items,
4057
4349
  onOpenRecord
4058
4350
  }) {
4059
- return /* @__PURE__ */ jsx11("span", { className: "vos-detail-links", children: items.map((item, i) => /* @__PURE__ */ jsxs11("span", { children: [
4351
+ return /* @__PURE__ */ jsx13("span", { className: "vos-detail-links", children: items.map((item, i) => /* @__PURE__ */ jsxs12("span", { children: [
4060
4352
  i > 0 ? ", " : null,
4061
- /* @__PURE__ */ jsx11(InlineLink, { id: item.id, title: item.title, onOpenRecord })
4353
+ /* @__PURE__ */ jsx13(InlineLink, { id: item.id, title: item.title, onOpenRecord })
4062
4354
  ] }, item.id)) });
4063
4355
  }
4064
4356
  function InlineLink({
@@ -4066,7 +4358,7 @@ function InlineLink({
4066
4358
  title,
4067
4359
  onOpenRecord
4068
4360
  }) {
4069
- return onOpenRecord ? /* @__PURE__ */ jsx11(
4361
+ return onOpenRecord ? /* @__PURE__ */ jsx13(
4070
4362
  "button",
4071
4363
  {
4072
4364
  type: "button",
@@ -4074,7 +4366,7 @@ function InlineLink({
4074
4366
  onClick: () => onOpenRecord(id),
4075
4367
  children: title
4076
4368
  }
4077
- ) : /* @__PURE__ */ jsx11("span", { children: title });
4369
+ ) : /* @__PURE__ */ jsx13("span", { children: title });
4078
4370
  }
4079
4371
  function DerivedCell({
4080
4372
  field,
@@ -4090,10 +4382,10 @@ function DerivedCell({
4090
4382
  toneClass = heroToneClass(derivedTone(field, num3));
4091
4383
  display = field === "confidence" ? formatSigned(num3) : String(Math.round(num3));
4092
4384
  }
4093
- return /* @__PURE__ */ jsxs11("div", { className: "vos-dcell", children: [
4094
- /* @__PURE__ */ jsxs11("div", { className: "vos-dcell-k", children: [
4385
+ return /* @__PURE__ */ jsxs12("div", { className: "vos-dcell", children: [
4386
+ /* @__PURE__ */ jsxs12("div", { className: "vos-dcell-k", children: [
4095
4387
  derivedLabel(field),
4096
- showWhy ? /* @__PURE__ */ jsxs11(
4388
+ showWhy ? /* @__PURE__ */ jsxs12(
4097
4389
  "button",
4098
4390
  {
4099
4391
  type: "button",
@@ -4107,17 +4399,17 @@ function DerivedCell({
4107
4399
  }
4108
4400
  ) : null
4109
4401
  ] }),
4110
- /* @__PURE__ */ jsx11("div", { className: `vos-dcell-v ${toneClass}`, children: display }),
4111
- DERIVED_SUB[field] ? /* @__PURE__ */ jsx11("div", { className: "vos-dcell-sub", children: DERIVED_SUB[field] }) : null
4402
+ /* @__PURE__ */ jsx13("div", { className: `vos-dcell-v ${toneClass}`, children: display }),
4403
+ DERIVED_SUB[field] ? /* @__PURE__ */ jsx13("div", { className: "vos-dcell-sub", children: DERIVED_SUB[field] }) : null
4112
4404
  ] });
4113
4405
  }
4114
4406
  function ConflictBanner2({
4115
4407
  message,
4116
4408
  onReload
4117
4409
  }) {
4118
- return /* @__PURE__ */ jsxs11("div", { role: "alert", className: "vos-banner vos-banner-warn", children: [
4119
- /* @__PURE__ */ jsx11("div", { className: "vos-banner-body", children: /* @__PURE__ */ jsx11("span", { children: message }) }),
4120
- /* @__PURE__ */ jsx11("button", { type: "button", onClick: onReload, children: "Review the latest" })
4410
+ return /* @__PURE__ */ jsxs12("div", { role: "alert", className: "vos-banner vos-banner-warn", children: [
4411
+ /* @__PURE__ */ jsx13("div", { className: "vos-banner-body", children: /* @__PURE__ */ jsx13("span", { children: message }) }),
4412
+ /* @__PURE__ */ jsx13("button", { type: "button", onClick: onReload, children: "Review the latest" })
4121
4413
  ] });
4122
4414
  }
4123
4415
 
@@ -4125,20 +4417,13 @@ function ConflictBanner2({
4125
4417
  import { useMemo as useMemo2, useState as useState7 } from "react";
4126
4418
 
4127
4419
  // src/form-fields.ts
4128
- import {
4129
- MARKET_RUNG_VALUES,
4130
- TESTING_RUNGS
4131
- } from "@validation-os/core";
4132
4420
  var ASSUMPTION_STATUS = ["Draft", "Live", "Invalidated"];
4133
4421
  var EXPERIMENT_STATUS = ["Draft", "Running", "Closed"];
4134
4422
  var CLOSURE_REASON = ["Completed", "Early-stop", "Kill"];
4135
4423
  var EXPERIMENT_OUTCOME = ["Achieved", "Missed", "Dropped"];
4136
4424
  var DECISION_STATUS2 = ["Active", "Provisional", "Superseded", "Reversed"];
4137
4425
  var GLOSSARY_STATUS = ["Active", "Provisional", "Superseded"];
4138
- var RESULT = ["Validated", "Invalidated", "Inconclusive"];
4139
- var MAGNITUDE = ["Low", "Typical", "High"];
4140
4426
  var FEASIBILITY = ["High", "Medium", "Low"];
4141
- var RUNGS = [...TESTING_RUNGS, ...MARKET_RUNG_VALUES];
4142
4427
  var QUALITY = ["1", "0.7", "0.5"];
4143
4428
  var FIELDS = {
4144
4429
  assumptions: [
@@ -4171,8 +4456,10 @@ var FIELDS = {
4171
4456
  readings: [
4172
4457
  { key: "Title", label: "Reading", kind: "text", required: true },
4173
4458
  { key: "Source", label: "Source", kind: "text" },
4174
- { key: "Rung", label: "Rung", kind: "select", options: RUNGS, required: true },
4175
- { key: "Result", label: "Result", kind: "select", options: RESULT, required: true },
4459
+ // Rung / Result / Magnitude band / Grading justification are PER BELIEF now
4460
+ // (OPS-1305) carried in `beliefs[]`, not on the row. They are omitted here
4461
+ // so the create form can never write a dead row-level field; grading a
4462
+ // reading's beliefs is a deferred follow-up (a `beliefs[]` editor).
4176
4463
  {
4177
4464
  key: "Representativeness",
4178
4465
  label: "Representativeness",
@@ -4187,17 +4474,7 @@ var FIELDS = {
4187
4474
  options: QUALITY,
4188
4475
  coerce: "number"
4189
4476
  },
4190
- {
4191
- key: "magnitudeBand",
4192
- label: "Magnitude band",
4193
- kind: "select",
4194
- options: MAGNITUDE
4195
- },
4196
- {
4197
- key: "Grading justification",
4198
- label: "Grading justification",
4199
- kind: "textarea"
4200
- },
4477
+ { key: "body", label: "Quote", kind: "textarea" },
4201
4478
  { key: "Date", label: "Date", kind: "text", placeholder: "YYYY-MM-DD" }
4202
4479
  ],
4203
4480
  decisions: [
@@ -4239,7 +4516,7 @@ function toCreatePayload(register, draft) {
4239
4516
  }
4240
4517
 
4241
4518
  // src/record-form.tsx
4242
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
4519
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
4243
4520
  function RecordForm({
4244
4521
  register,
4245
4522
  basePath,
@@ -4262,9 +4539,9 @@ function RecordForm({
4262
4539
  } catch {
4263
4540
  }
4264
4541
  };
4265
- return /* @__PURE__ */ jsxs12("form", { onSubmit, className: "vos-form", children: [
4266
- /* @__PURE__ */ jsxs12("div", { className: "vos-form-body", children: [
4267
- fields.map((field) => /* @__PURE__ */ jsx12(
4542
+ return /* @__PURE__ */ jsxs13("form", { onSubmit, className: "vos-form", children: [
4543
+ /* @__PURE__ */ jsxs13("div", { className: "vos-form-body", children: [
4544
+ fields.map((field) => /* @__PURE__ */ jsx14(
4268
4545
  Field,
4269
4546
  {
4270
4547
  field,
@@ -4273,11 +4550,11 @@ function RecordForm({
4273
4550
  },
4274
4551
  field.key
4275
4552
  )),
4276
- error ? /* @__PURE__ */ jsx12("p", { className: "vos-error", children: error }) : null
4553
+ error ? /* @__PURE__ */ jsx14("p", { className: "vos-error", children: error }) : null
4277
4554
  ] }),
4278
- /* @__PURE__ */ jsxs12("footer", { className: "vos-drawer-footer", children: [
4279
- /* @__PURE__ */ jsx12("button", { type: "button", onClick: onCancel, className: "vos-btn vos-btn-ghost vos-btn-sm", children: "Cancel" }),
4280
- /* @__PURE__ */ jsx12(
4555
+ /* @__PURE__ */ jsxs13("footer", { className: "vos-drawer-footer", children: [
4556
+ /* @__PURE__ */ jsx14("button", { type: "button", onClick: onCancel, className: "vos-btn vos-btn-ghost vos-btn-sm", children: "Cancel" }),
4557
+ /* @__PURE__ */ jsx14(
4281
4558
  "button",
4282
4559
  {
4283
4560
  type: "submit",
@@ -4296,12 +4573,12 @@ function Field({
4296
4573
  onChange
4297
4574
  }) {
4298
4575
  const id = `field-${field.key}`;
4299
- return /* @__PURE__ */ jsxs12("div", { className: "vos-field", children: [
4300
- /* @__PURE__ */ jsxs12("label", { htmlFor: id, className: FIELD_LABEL_CLASS, children: [
4576
+ return /* @__PURE__ */ jsxs13("div", { className: "vos-field", children: [
4577
+ /* @__PURE__ */ jsxs13("label", { htmlFor: id, className: FIELD_LABEL_CLASS, children: [
4301
4578
  field.label,
4302
- field.required ? /* @__PURE__ */ jsx12("span", { className: "vos-req", children: " *" }) : null
4579
+ field.required ? /* @__PURE__ */ jsx14("span", { className: "vos-req", children: " *" }) : null
4303
4580
  ] }),
4304
- field.kind === "textarea" ? /* @__PURE__ */ jsx12(
4581
+ field.kind === "textarea" ? /* @__PURE__ */ jsx14(
4305
4582
  "textarea",
4306
4583
  {
4307
4584
  id,
@@ -4311,7 +4588,7 @@ function Field({
4311
4588
  onChange: (e) => onChange(e.target.value),
4312
4589
  className: FIELD_CONTROL_CLASS
4313
4590
  }
4314
- ) : field.kind === "select" ? /* @__PURE__ */ jsxs12(
4591
+ ) : field.kind === "select" ? /* @__PURE__ */ jsxs13(
4315
4592
  "select",
4316
4593
  {
4317
4594
  id,
@@ -4319,11 +4596,11 @@ function Field({
4319
4596
  onChange: (e) => onChange(e.target.value),
4320
4597
  className: FIELD_CONTROL_CLASS,
4321
4598
  children: [
4322
- /* @__PURE__ */ jsx12("option", { value: "", children: "\u2014" }),
4323
- field.options?.map((opt) => /* @__PURE__ */ jsx12("option", { value: opt, children: opt }, opt))
4599
+ /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014" }),
4600
+ field.options?.map((opt) => /* @__PURE__ */ jsx14("option", { value: opt, children: opt }, opt))
4324
4601
  ]
4325
4602
  }
4326
- ) : /* @__PURE__ */ jsx12(
4603
+ ) : /* @__PURE__ */ jsx14(
4327
4604
  "input",
4328
4605
  {
4329
4606
  id,
@@ -4359,7 +4636,7 @@ function linkChoicesFrom(register) {
4359
4636
  }
4360
4637
 
4361
4638
  // src/relation-editor.tsx
4362
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
4639
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
4363
4640
  function RelationEditor({
4364
4641
  register,
4365
4642
  recordId,
@@ -4393,10 +4670,10 @@ function RelationEditor({
4393
4670
  } catch {
4394
4671
  }
4395
4672
  };
4396
- return /* @__PURE__ */ jsxs13("section", { className: "vos-relation", children: [
4397
- /* @__PURE__ */ jsx13("h3", { className: "vos-sectitle", children: "Link a record" }),
4398
- /* @__PURE__ */ jsxs13("div", { className: "vos-field-stack", children: [
4399
- /* @__PURE__ */ jsxs13(
4673
+ return /* @__PURE__ */ jsxs14("section", { className: "vos-relation", children: [
4674
+ /* @__PURE__ */ jsx15("h3", { className: "vos-sectitle", children: "Link a record" }),
4675
+ /* @__PURE__ */ jsxs14("div", { className: "vos-field-stack", children: [
4676
+ /* @__PURE__ */ jsxs14(
4400
4677
  "select",
4401
4678
  {
4402
4679
  "aria-label": "Relation",
@@ -4407,12 +4684,12 @@ function RelationEditor({
4407
4684
  },
4408
4685
  className: FIELD_CONTROL_CLASS,
4409
4686
  children: [
4410
- /* @__PURE__ */ jsx13("option", { value: "", children: "Choose a relation\u2026" }),
4411
- choices.map((c) => /* @__PURE__ */ jsx13("option", { value: c.relation, children: c.label }, c.relation))
4687
+ /* @__PURE__ */ jsx15("option", { value: "", children: "Choose a relation\u2026" }),
4688
+ choices.map((c) => /* @__PURE__ */ jsx15("option", { value: c.relation, children: c.label }, c.relation))
4412
4689
  ]
4413
4690
  }
4414
4691
  ),
4415
- active ? /* @__PURE__ */ jsxs13(
4692
+ active ? /* @__PURE__ */ jsxs14(
4416
4693
  "select",
4417
4694
  {
4418
4695
  "aria-label": "Target record",
@@ -4420,13 +4697,13 @@ function RelationEditor({
4420
4697
  onChange: (e) => setTargetId(e.target.value),
4421
4698
  className: FIELD_CONTROL_CLASS,
4422
4699
  children: [
4423
- /* @__PURE__ */ jsx13("option", { value: "", children: "Choose a record\u2026" }),
4424
- targets.map((r) => /* @__PURE__ */ jsx13("option", { value: r.id, children: primaryLabel(r) }, r.id))
4700
+ /* @__PURE__ */ jsx15("option", { value: "", children: "Choose a record\u2026" }),
4701
+ targets.map((r) => /* @__PURE__ */ jsx15("option", { value: r.id, children: primaryLabel(r) }, r.id))
4425
4702
  ]
4426
4703
  }
4427
4704
  ) : null,
4428
- error ? /* @__PURE__ */ jsx13("p", { className: "vos-error", children: error }) : null,
4429
- /* @__PURE__ */ jsx13(
4705
+ error ? /* @__PURE__ */ jsx15("p", { className: "vos-error", children: error }) : null,
4706
+ /* @__PURE__ */ jsx15(
4430
4707
  "button",
4431
4708
  {
4432
4709
  type: "button",
@@ -4493,7 +4770,7 @@ function useSavedViews(register) {
4493
4770
  }
4494
4771
 
4495
4772
  // src/register-browser.tsx
4496
- import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
4773
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
4497
4774
  function contextNeeds(register) {
4498
4775
  return {
4499
4776
  experiments: register === "assumptions" || register === "readings",
@@ -4557,6 +4834,9 @@ function RegisterBrowser({
4557
4834
  readings: ctx.readings,
4558
4835
  decisions: ctx.decisions
4559
4836
  };
4837
+ const assumptionTitles = new Map(
4838
+ (ctx.assumptions ?? []).map((a) => [a.id, primaryLabel(a)])
4839
+ );
4560
4840
  const patch = (p) => setDescriptor((d) => ({ ...d, ...p }));
4561
4841
  const saveCurrentView = () => {
4562
4842
  if (typeof window === "undefined") return;
@@ -4568,14 +4848,14 @@ function RegisterBrowser({
4568
4848
  void _name;
4569
4849
  setDescriptor(rest);
4570
4850
  };
4571
- return /* @__PURE__ */ jsxs14("div", { children: [
4572
- /* @__PURE__ */ jsxs14("div", { className: "vos-head", children: [
4573
- /* @__PURE__ */ jsxs14("div", { children: [
4574
- /* @__PURE__ */ jsx14("h1", { children: REGISTER_LABEL[register] }),
4575
- subtitle ? /* @__PURE__ */ jsx14("p", { children: subtitle }) : null
4851
+ return /* @__PURE__ */ jsxs15("div", { children: [
4852
+ /* @__PURE__ */ jsxs15("div", { className: "vos-head", children: [
4853
+ /* @__PURE__ */ jsxs15("div", { children: [
4854
+ /* @__PURE__ */ jsx16("h1", { children: REGISTER_LABEL[register] }),
4855
+ subtitle ? /* @__PURE__ */ jsx16("p", { children: subtitle }) : null
4576
4856
  ] }),
4577
- /* @__PURE__ */ jsx14("div", { className: "vos-spacer" }),
4578
- /* @__PURE__ */ jsx14(
4857
+ /* @__PURE__ */ jsx16("div", { className: "vos-spacer" }),
4858
+ /* @__PURE__ */ jsx16(
4579
4859
  "button",
4580
4860
  {
4581
4861
  type: "button",
@@ -4584,7 +4864,7 @@ function RegisterBrowser({
4584
4864
  children: "\u21BB Refresh"
4585
4865
  }
4586
4866
  ),
4587
- /* @__PURE__ */ jsxs14(
4867
+ /* @__PURE__ */ jsxs15(
4588
4868
  "button",
4589
4869
  {
4590
4870
  type: "button",
@@ -4597,10 +4877,10 @@ function RegisterBrowser({
4597
4877
  }
4598
4878
  )
4599
4879
  ] }),
4600
- /* @__PURE__ */ jsx14("div", { className: "vos-tabs", role: "tablist", "aria-label": "Views", children: shaped.tabs.map((tab) => {
4880
+ /* @__PURE__ */ jsx16("div", { className: "vos-tabs", role: "tablist", "aria-label": "Views", children: shaped.tabs.map((tab) => {
4601
4881
  const active = tab.id === shaped.activeTabId;
4602
4882
  const badge = badgeFor(tab);
4603
- return /* @__PURE__ */ jsxs14(
4883
+ return /* @__PURE__ */ jsxs15(
4604
4884
  "button",
4605
4885
  {
4606
4886
  type: "button",
@@ -4610,13 +4890,13 @@ function RegisterBrowser({
4610
4890
  onClick: () => patch({ tabId: tab.id }),
4611
4891
  children: [
4612
4892
  tab.label,
4613
- badge !== null ? /* @__PURE__ */ jsx14("span", { className: "vos-tab-badge", children: badge }) : null
4893
+ badge !== null ? /* @__PURE__ */ jsx16("span", { className: "vos-tab-badge", children: badge }) : null
4614
4894
  ]
4615
4895
  },
4616
4896
  tab.id
4617
4897
  );
4618
4898
  }) }),
4619
- /* @__PURE__ */ jsx14(
4899
+ /* @__PURE__ */ jsx16(
4620
4900
  ViewControls,
4621
4901
  {
4622
4902
  register,
@@ -4627,10 +4907,10 @@ function RegisterBrowser({
4627
4907
  onQuery: (query) => patch({ query })
4628
4908
  }
4629
4909
  ),
4630
- /* @__PURE__ */ jsxs14("div", { className: "vos-saved-views", children: [
4631
- /* @__PURE__ */ jsx14("span", { className: "vos-saved-label", children: "Saved views" }),
4632
- savedViews.views.length === 0 ? /* @__PURE__ */ jsx14("span", { className: "vos-hint", children: "none yet" }) : savedViews.views.map((v) => /* @__PURE__ */ jsxs14("span", { className: "vos-saved-view", children: [
4633
- /* @__PURE__ */ jsx14(
4910
+ /* @__PURE__ */ jsxs15("div", { className: "vos-saved-views", children: [
4911
+ /* @__PURE__ */ jsx16("span", { className: "vos-saved-label", children: "Saved views" }),
4912
+ savedViews.views.length === 0 ? /* @__PURE__ */ jsx16("span", { className: "vos-hint", children: "none yet" }) : savedViews.views.map((v) => /* @__PURE__ */ jsxs15("span", { className: "vos-saved-view", children: [
4913
+ /* @__PURE__ */ jsx16(
4634
4914
  "button",
4635
4915
  {
4636
4916
  type: "button",
@@ -4639,7 +4919,7 @@ function RegisterBrowser({
4639
4919
  children: v.name
4640
4920
  }
4641
4921
  ),
4642
- /* @__PURE__ */ jsx14(
4922
+ /* @__PURE__ */ jsx16(
4643
4923
  "button",
4644
4924
  {
4645
4925
  type: "button",
@@ -4650,7 +4930,7 @@ function RegisterBrowser({
4650
4930
  }
4651
4931
  )
4652
4932
  ] }, v.name)),
4653
- /* @__PURE__ */ jsx14(
4933
+ /* @__PURE__ */ jsx16(
4654
4934
  "button",
4655
4935
  {
4656
4936
  type: "button",
@@ -4660,20 +4940,21 @@ function RegisterBrowser({
4660
4940
  }
4661
4941
  )
4662
4942
  ] }),
4663
- loading && !records ? /* @__PURE__ */ jsxs14("p", { className: "vos-muted", children: [
4943
+ loading && !records ? /* @__PURE__ */ jsxs15("p", { className: "vos-muted", children: [
4664
4944
  "Loading ",
4665
4945
  REGISTER_LABEL[register].toLowerCase(),
4666
4946
  "\u2026"
4667
- ] }) : error ? /* @__PURE__ */ jsx14("p", { className: "vos-error", children: error }) : /* @__PURE__ */ jsx14(
4947
+ ] }) : error ? /* @__PURE__ */ jsx16("p", { className: "vos-error", children: error }) : /* @__PURE__ */ jsx16(
4668
4948
  ShapedBody,
4669
4949
  {
4670
4950
  register,
4671
4951
  shaped,
4672
4952
  onRowClick: setOpenId,
4673
- selectedId: openId
4953
+ selectedId: openId,
4954
+ assumptionTitles
4674
4955
  }
4675
4956
  ),
4676
- /* @__PURE__ */ jsx14(
4957
+ /* @__PURE__ */ jsx16(
4677
4958
  RecordDrawer,
4678
4959
  {
4679
4960
  register,
@@ -4690,7 +4971,7 @@ function RegisterBrowser({
4690
4971
  refreshRecord();
4691
4972
  refreshList();
4692
4973
  },
4693
- children: openId ? /* @__PURE__ */ jsx14(
4974
+ children: openId ? /* @__PURE__ */ jsx16(
4694
4975
  RelationEditor,
4695
4976
  {
4696
4977
  register,
@@ -4704,18 +4985,18 @@ function RegisterBrowser({
4704
4985
  ) : null
4705
4986
  }
4706
4987
  ),
4707
- /* @__PURE__ */ jsxs14(
4988
+ /* @__PURE__ */ jsxs15(
4708
4989
  DrawerShell,
4709
4990
  {
4710
4991
  open: creating,
4711
4992
  onClose: () => setCreating(false),
4712
4993
  ariaLabel: `New ${REGISTER_SINGULAR[register]} record`,
4713
4994
  children: [
4714
- /* @__PURE__ */ jsx14("header", { className: "vos-drawer-header", children: /* @__PURE__ */ jsxs14("div", { children: [
4715
- /* @__PURE__ */ jsx14("p", { className: "vos-drawer-eyebrow", children: "New" }),
4716
- /* @__PURE__ */ jsx14("h2", { className: "vos-drawer-title", children: REGISTER_SINGULAR[register] })
4995
+ /* @__PURE__ */ jsx16("header", { className: "vos-drawer-header", children: /* @__PURE__ */ jsxs15("div", { children: [
4996
+ /* @__PURE__ */ jsx16("p", { className: "vos-drawer-eyebrow", children: "New" }),
4997
+ /* @__PURE__ */ jsx16("h2", { className: "vos-drawer-title", children: REGISTER_SINGULAR[register] })
4717
4998
  ] }) }),
4718
- /* @__PURE__ */ jsx14(
4999
+ /* @__PURE__ */ jsx16(
4719
5000
  RecordForm,
4720
5001
  {
4721
5002
  register,
@@ -4743,8 +5024,8 @@ function ViewControls({
4743
5024
  }) {
4744
5025
  const sortable = columnsFor(register);
4745
5026
  const sort = descriptor.sort ?? null;
4746
- return /* @__PURE__ */ jsxs14("div", { className: "vos-view-controls", children: [
4747
- /* @__PURE__ */ jsx14(
5027
+ return /* @__PURE__ */ jsxs15("div", { className: "vos-view-controls", children: [
5028
+ /* @__PURE__ */ jsx16(
4748
5029
  "input",
4749
5030
  {
4750
5031
  type: "search",
@@ -4755,24 +5036,24 @@ function ViewControls({
4755
5036
  "aria-label": "Filter records"
4756
5037
  }
4757
5038
  ),
4758
- axes.length ? /* @__PURE__ */ jsxs14("label", { className: "vos-control", children: [
4759
- /* @__PURE__ */ jsx14("span", { children: "Group" }),
4760
- /* @__PURE__ */ jsxs14(
5039
+ axes.length ? /* @__PURE__ */ jsxs15("label", { className: "vos-control", children: [
5040
+ /* @__PURE__ */ jsx16("span", { children: "Group" }),
5041
+ /* @__PURE__ */ jsxs15(
4761
5042
  "select",
4762
5043
  {
4763
5044
  className: "vos-input",
4764
5045
  value: descriptor.groupBy ?? "",
4765
5046
  onChange: (e) => onGroupBy(e.target.value || null),
4766
5047
  children: [
4767
- /* @__PURE__ */ jsx14("option", { value: "", children: "None" }),
4768
- axes.map((axis) => /* @__PURE__ */ jsx14("option", { value: axis, children: axis }, axis))
5048
+ /* @__PURE__ */ jsx16("option", { value: "", children: "None" }),
5049
+ axes.map((axis) => /* @__PURE__ */ jsx16("option", { value: axis, children: axis }, axis))
4769
5050
  ]
4770
5051
  }
4771
5052
  )
4772
5053
  ] }) : null,
4773
- /* @__PURE__ */ jsxs14("label", { className: "vos-control", children: [
4774
- /* @__PURE__ */ jsx14("span", { children: "Sort" }),
4775
- /* @__PURE__ */ jsxs14(
5054
+ /* @__PURE__ */ jsxs15("label", { className: "vos-control", children: [
5055
+ /* @__PURE__ */ jsx16("span", { children: "Sort" }),
5056
+ /* @__PURE__ */ jsxs15(
4776
5057
  "select",
4777
5058
  {
4778
5059
  className: "vos-input",
@@ -4781,13 +5062,13 @@ function ViewControls({
4781
5062
  e.target.value ? { key: e.target.value, dir: sort?.dir ?? "desc" } : null
4782
5063
  ),
4783
5064
  children: [
4784
- /* @__PURE__ */ jsx14("option", { value: "", children: "Default" }),
4785
- sortable.map((c) => /* @__PURE__ */ jsx14("option", { value: c.key, children: c.header }, c.key))
5065
+ /* @__PURE__ */ jsx16("option", { value: "", children: "Default" }),
5066
+ sortable.map((c) => /* @__PURE__ */ jsx16("option", { value: c.key, children: c.header }, c.key))
4786
5067
  ]
4787
5068
  }
4788
5069
  )
4789
5070
  ] }),
4790
- sort ? /* @__PURE__ */ jsx14(
5071
+ sort ? /* @__PURE__ */ jsx16(
4791
5072
  "button",
4792
5073
  {
4793
5074
  type: "button",
@@ -4803,53 +5084,57 @@ function ShapedBody({
4803
5084
  register,
4804
5085
  shaped,
4805
5086
  onRowClick,
4806
- selectedId
5087
+ selectedId,
5088
+ assumptionTitles
4807
5089
  }) {
4808
5090
  if (shaped.nested) {
4809
5091
  if (shaped.nested.length === 0)
4810
- return /* @__PURE__ */ jsx14("p", { className: "vos-empty", children: "No readings in this view." });
4811
- return /* @__PURE__ */ jsx14("div", { className: "vos-groups", children: shaped.nested.map((group) => /* @__PURE__ */ jsxs14("section", { className: "vos-group", children: [
4812
- /* @__PURE__ */ jsxs14("h3", { className: "vos-group-head", children: [
5092
+ return /* @__PURE__ */ jsx16("p", { className: "vos-empty", children: "No readings in this view." });
5093
+ return /* @__PURE__ */ jsx16("div", { className: "vos-groups", children: shaped.nested.map((group) => /* @__PURE__ */ jsxs15("section", { className: "vos-group", children: [
5094
+ /* @__PURE__ */ jsxs15("h3", { className: "vos-group-head", children: [
4813
5095
  group.label,
4814
- /* @__PURE__ */ jsx14("span", { className: "vos-group-n", children: group.readings.length })
5096
+ /* @__PURE__ */ jsx16("span", { className: "vos-group-n", children: group.readings.length })
4815
5097
  ] }),
4816
- /* @__PURE__ */ jsx14(
5098
+ /* @__PURE__ */ jsx16(
4817
5099
  RegisterTable,
4818
5100
  {
4819
5101
  register,
4820
5102
  records: group.readings,
4821
5103
  onRowClick,
4822
- selectedId
5104
+ selectedId,
5105
+ assumptionTitles
4823
5106
  }
4824
5107
  )
4825
5108
  ] }, group.experimentId ?? "__none__")) });
4826
5109
  }
4827
5110
  if (shaped.groups) {
4828
5111
  if (shaped.groups.length === 0)
4829
- return /* @__PURE__ */ jsx14("p", { className: "vos-empty", children: "No records in this view." });
4830
- return /* @__PURE__ */ jsx14("div", { className: "vos-groups", children: shaped.groups.map((group) => /* @__PURE__ */ jsxs14("section", { className: "vos-group", children: [
4831
- /* @__PURE__ */ jsxs14("h3", { className: "vos-group-head", children: [
5112
+ return /* @__PURE__ */ jsx16("p", { className: "vos-empty", children: "No records in this view." });
5113
+ return /* @__PURE__ */ jsx16("div", { className: "vos-groups", children: shaped.groups.map((group) => /* @__PURE__ */ jsxs15("section", { className: "vos-group", children: [
5114
+ /* @__PURE__ */ jsxs15("h3", { className: "vos-group-head", children: [
4832
5115
  group.label,
4833
- /* @__PURE__ */ jsx14("span", { className: "vos-group-n", children: group.records.length })
5116
+ /* @__PURE__ */ jsx16("span", { className: "vos-group-n", children: group.records.length })
4834
5117
  ] }),
4835
- /* @__PURE__ */ jsx14(
5118
+ /* @__PURE__ */ jsx16(
4836
5119
  RegisterTable,
4837
5120
  {
4838
5121
  register,
4839
5122
  records: group.records,
4840
5123
  onRowClick,
4841
- selectedId
5124
+ selectedId,
5125
+ assumptionTitles
4842
5126
  }
4843
5127
  )
4844
5128
  ] }, group.key)) });
4845
5129
  }
4846
- return /* @__PURE__ */ jsx14(
5130
+ return /* @__PURE__ */ jsx16(
4847
5131
  RegisterTable,
4848
5132
  {
4849
5133
  register,
4850
5134
  records: shaped.rows,
4851
5135
  onRowClick,
4852
- selectedId
5136
+ selectedId,
5137
+ assumptionTitles
4853
5138
  }
4854
5139
  );
4855
5140
  }
@@ -4857,7 +5142,7 @@ function ShapedBody({
4857
5142
  // src/next-move-surface.tsx
4858
5143
  import { useMemo as useMemo5, useState as useState11 } from "react";
4859
5144
  import { rankNextMoves as rankNextMoves2 } from "@validation-os/core/derivation";
4860
- import { Fragment as Fragment10, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
5145
+ import { Fragment as Fragment10, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
4861
5146
  var STAGES = ["Framed", "Planned", "Tested", "Known"];
4862
5147
  var MOVE_STAGE = {
4863
5148
  "score-impact": 0,
@@ -4915,12 +5200,12 @@ function NextMoveSurface({ basePath, onNavigate }) {
4915
5200
  });
4916
5201
  };
4917
5202
  if (loading) {
4918
- return /* @__PURE__ */ jsx15(NextMoveFrame, { children: /* @__PURE__ */ jsx15("div", { className: "vos-empty", children: "Reading your beliefs\u2026" }) });
5203
+ return /* @__PURE__ */ jsx17(NextMoveFrame, { children: /* @__PURE__ */ jsx17("div", { className: "vos-empty", children: "Reading your beliefs\u2026" }) });
4919
5204
  }
4920
5205
  if (error) {
4921
- return /* @__PURE__ */ jsx15(NextMoveFrame, { children: /* @__PURE__ */ jsx15("div", { className: "vos-banner vos-banner-crit", children: /* @__PURE__ */ jsxs15("div", { className: "vos-banner-body", children: [
4922
- /* @__PURE__ */ jsx15("b", { children: "Couldn't load the workflow." }),
4923
- /* @__PURE__ */ jsx15("span", { children: error })
5206
+ return /* @__PURE__ */ jsx17(NextMoveFrame, { children: /* @__PURE__ */ jsx17("div", { className: "vos-banner vos-banner-crit", children: /* @__PURE__ */ jsxs16("div", { className: "vos-banner-body", children: [
5207
+ /* @__PURE__ */ jsx17("b", { children: "Couldn't load the workflow." }),
5208
+ /* @__PURE__ */ jsx17("span", { children: error })
4924
5209
  ] }) }) });
4925
5210
  }
4926
5211
  if (moves.length === 0) {
@@ -4932,13 +5217,13 @@ function NextMoveSurface({ basePath, onNavigate }) {
4932
5217
  };
4933
5218
  const cold = coldStartFor(records);
4934
5219
  if (cold.cold) {
4935
- return /* @__PURE__ */ jsxs15(NextMoveFrame, { children: [
4936
- /* @__PURE__ */ jsx15("div", { className: "vos-firstrun", children: FIRST_RUN_LINE }),
4937
- /* @__PURE__ */ jsxs15("div", { className: "vos-card vos-cold vos-cold-next", children: [
4938
- /* @__PURE__ */ jsx15("span", { className: "vos-cold-eyebrow", children: cold.next.eyebrow }),
4939
- /* @__PURE__ */ jsx15("h2", { className: "vos-cold-headline", children: cold.next.headline }),
4940
- /* @__PURE__ */ jsx15("p", { className: "vos-cold-body", children: cold.next.body }),
4941
- /* @__PURE__ */ jsx15(
5220
+ return /* @__PURE__ */ jsxs16(NextMoveFrame, { children: [
5221
+ /* @__PURE__ */ jsx17("div", { className: "vos-firstrun", children: FIRST_RUN_LINE }),
5222
+ /* @__PURE__ */ jsxs16("div", { className: "vos-card vos-cold vos-cold-next", children: [
5223
+ /* @__PURE__ */ jsx17("span", { className: "vos-cold-eyebrow", children: cold.next.eyebrow }),
5224
+ /* @__PURE__ */ jsx17("h2", { className: "vos-cold-headline", children: cold.next.headline }),
5225
+ /* @__PURE__ */ jsx17("p", { className: "vos-cold-body", children: cold.next.body }),
5226
+ /* @__PURE__ */ jsx17(
4942
5227
  "button",
4943
5228
  {
4944
5229
  type: "button",
@@ -4950,10 +5235,10 @@ function NextMoveSurface({ basePath, onNavigate }) {
4950
5235
  ] })
4951
5236
  ] });
4952
5237
  }
4953
- return /* @__PURE__ */ jsx15(NextMoveFrame, { children: /* @__PURE__ */ jsxs15("div", { className: "vos-empty", children: [
5238
+ return /* @__PURE__ */ jsx17(NextMoveFrame, { children: /* @__PURE__ */ jsxs16("div", { className: "vos-empty", children: [
4954
5239
  "Nothing needs your attention right now \u2014 every belief is either resting on a decision or waiting on a test. Add a new belief from",
4955
5240
  " ",
4956
- /* @__PURE__ */ jsx15(
5241
+ /* @__PURE__ */ jsx17(
4957
5242
  "button",
4958
5243
  {
4959
5244
  type: "button",
@@ -4971,11 +5256,11 @@ function NextMoveSurface({ basePath, onNavigate }) {
4971
5256
  const onDeck = rest.filter((m) => m.assumptionId !== top.assumptionId).slice(0, 3);
4972
5257
  const topPres = movePresentation(top.move);
4973
5258
  const topTone = riskLevel(top.risk);
4974
- return /* @__PURE__ */ jsxs15(NextMoveFrame, { children: [
4975
- killMoves.length > 0 && !top.killLane ? /* @__PURE__ */ jsx15(KillBanner, { count: killMoves.length, onReview: () => startStepIn(killMoves[0]) }) : null,
4976
- /* @__PURE__ */ jsxs15("div", { className: `vos-hero vos-card${top.killLane ? " vos-hero-kill" : ""}`, children: [
4977
- /* @__PURE__ */ jsx15("span", { className: "vos-hero-eyebrow", children: top.killLane ? "Kill lane \u2014 turning against you" : "Your next move" }),
4978
- /* @__PURE__ */ jsx15(
5259
+ return /* @__PURE__ */ jsxs16(NextMoveFrame, { children: [
5260
+ killMoves.length > 0 && !top.killLane ? /* @__PURE__ */ jsx17(KillBanner, { count: killMoves.length, onReview: () => startStepIn(killMoves[0]) }) : null,
5261
+ /* @__PURE__ */ jsxs16("div", { className: `vos-hero vos-card${top.killLane ? " vos-hero-kill" : ""}`, children: [
5262
+ /* @__PURE__ */ jsx17("span", { className: "vos-hero-eyebrow", children: top.killLane ? "Kill lane \u2014 turning against you" : "Your next move" }),
5263
+ /* @__PURE__ */ jsx17(
4979
5264
  "button",
4980
5265
  {
4981
5266
  type: "button",
@@ -4985,23 +5270,23 @@ function NextMoveSurface({ basePath, onNavigate }) {
4985
5270
  children: top.title
4986
5271
  }
4987
5272
  ),
4988
- /* @__PURE__ */ jsxs15("div", { className: "vos-riskchip", "aria-label": `Risk: ${RISK_PHRASE[topTone]}`, children: [
4989
- /* @__PURE__ */ jsx15("span", { className: "vos-risk-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx15(
5273
+ /* @__PURE__ */ jsxs16("div", { className: "vos-riskchip", "aria-label": `Risk: ${RISK_PHRASE[topTone]}`, children: [
5274
+ /* @__PURE__ */ jsx17("span", { className: "vos-risk-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx17(
4990
5275
  "i",
4991
5276
  {
4992
5277
  className: `vos-fill-${topTone}`,
4993
5278
  style: { width: `${riskFraction(top.risk) * 100}%` }
4994
5279
  }
4995
5280
  ) }),
4996
- /* @__PURE__ */ jsx15("span", { className: `vos-riskchip-label vos-text-${topTone}`, children: top.killLane ? "Confidence has turned negative" : RISK_PHRASE[topTone] })
5281
+ /* @__PURE__ */ jsx17("span", { className: `vos-riskchip-label vos-text-${topTone}`, children: top.killLane ? "Confidence has turned negative" : RISK_PHRASE[topTone] })
4997
5282
  ] }),
4998
- /* @__PURE__ */ jsx15(ActButton, { move: top, onStepIn: () => startStepIn(top), onReview: () => openRecord(top.assumptionId) }),
4999
- /* @__PURE__ */ jsx15("button", { type: "button", className: "vos-why", onClick: () => setWhy((w) => !w), children: why ? "Hide details" : "Why this?" })
5283
+ /* @__PURE__ */ jsx17(ActButton, { move: top, onStepIn: () => startStepIn(top), onReview: () => openRecord(top.assumptionId) }),
5284
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "vos-why", onClick: () => setWhy((w) => !w), children: why ? "Hide details" : "Why this?" })
5000
5285
  ] }),
5001
- why ? /* @__PURE__ */ jsx15(WhyPanel, { top, ranked: moves }) : null,
5002
- onDeck.length > 0 ? /* @__PURE__ */ jsxs15("section", { className: "vos-ondeck", children: [
5003
- /* @__PURE__ */ jsx15("h3", { className: "vos-sectitle", children: "On deck" }),
5004
- onDeck.map((m) => /* @__PURE__ */ jsx15(
5286
+ why ? /* @__PURE__ */ jsx17(WhyPanel, { top, ranked: moves }) : null,
5287
+ onDeck.length > 0 ? /* @__PURE__ */ jsxs16("section", { className: "vos-ondeck", children: [
5288
+ /* @__PURE__ */ jsx17("h3", { className: "vos-sectitle", children: "On deck" }),
5289
+ onDeck.map((m) => /* @__PURE__ */ jsx17(
5005
5290
  OnDeckRow,
5006
5291
  {
5007
5292
  move: m,
@@ -5011,7 +5296,7 @@ function NextMoveSurface({ basePath, onNavigate }) {
5011
5296
  m.assumptionId
5012
5297
  ))
5013
5298
  ] }) : null,
5014
- /* @__PURE__ */ jsx15(
5299
+ /* @__PURE__ */ jsx17(
5015
5300
  "button",
5016
5301
  {
5017
5302
  type: "button",
@@ -5020,7 +5305,7 @@ function NextMoveSurface({ basePath, onNavigate }) {
5020
5305
  children: "Act on a different belief \u2192"
5021
5306
  }
5022
5307
  ),
5023
- stepIn?.form === "score-impact" ? /* @__PURE__ */ jsx15(
5308
+ stepIn?.form === "score-impact" ? /* @__PURE__ */ jsx17(
5024
5309
  ScoreImpactForm,
5025
5310
  {
5026
5311
  assumption: stepIn.assumption,
@@ -5032,7 +5317,7 @@ function NextMoveSurface({ basePath, onNavigate }) {
5032
5317
  onCancel: () => setStepIn(null)
5033
5318
  }
5034
5319
  ) : null,
5035
- stepIn?.form === "write-decision" ? /* @__PURE__ */ jsx15(
5320
+ stepIn?.form === "write-decision" ? /* @__PURE__ */ jsx17(
5036
5321
  WriteDecisionForm,
5037
5322
  {
5038
5323
  assumption: stepIn.assumption,
@@ -5048,12 +5333,12 @@ function NextMoveSurface({ basePath, onNavigate }) {
5048
5333
  ] });
5049
5334
  }
5050
5335
  function NextMoveFrame({ children }) {
5051
- return /* @__PURE__ */ jsxs15("div", { children: [
5052
- /* @__PURE__ */ jsx15("div", { className: "vos-head", children: /* @__PURE__ */ jsxs15("div", { children: [
5053
- /* @__PURE__ */ jsx15("h1", { children: "Next move" }),
5054
- /* @__PURE__ */ jsx15("p", { children: "The single next move to make \u2014 and what's on deck." })
5336
+ return /* @__PURE__ */ jsxs16("div", { children: [
5337
+ /* @__PURE__ */ jsx17("div", { className: "vos-head", children: /* @__PURE__ */ jsxs16("div", { children: [
5338
+ /* @__PURE__ */ jsx17("h1", { children: "Next move" }),
5339
+ /* @__PURE__ */ jsx17("p", { children: "The single next move to make \u2014 and what's on deck." })
5055
5340
  ] }) }),
5056
- /* @__PURE__ */ jsx15("div", { className: "vos-next", children })
5341
+ /* @__PURE__ */ jsx17("div", { className: "vos-next", children })
5057
5342
  ] });
5058
5343
  }
5059
5344
  function ActButton({
@@ -5063,20 +5348,20 @@ function ActButton({
5063
5348
  }) {
5064
5349
  const pres = movePresentation(move.move);
5065
5350
  if (pres.steppable) {
5066
- return /* @__PURE__ */ jsx15("button", { type: "button", className: "vos-btn vos-hero-act", onClick: onStepIn, children: pres.cta });
5351
+ return /* @__PURE__ */ jsx17("button", { type: "button", className: "vos-btn vos-hero-act", onClick: onStepIn, children: pres.cta });
5067
5352
  }
5068
- return /* @__PURE__ */ jsxs15("div", { className: "vos-hero-agent", children: [
5069
- /* @__PURE__ */ jsx15("span", { className: "vos-agent-note", children: "\u{1F916} Claude Code runs this off the dashboard" }),
5070
- /* @__PURE__ */ jsx15("button", { type: "button", className: "vos-btn vos-btn-ghost vos-hero-act", onClick: onReview, children: "Review on the record \u2192" })
5353
+ return /* @__PURE__ */ jsxs16("div", { className: "vos-hero-agent", children: [
5354
+ /* @__PURE__ */ jsx17("span", { className: "vos-agent-note", children: "\u{1F916} Claude Code runs this off the dashboard" }),
5355
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "vos-btn vos-btn-ghost vos-hero-act", onClick: onReview, children: "Review on the record \u2192" })
5071
5356
  ] });
5072
5357
  }
5073
5358
  function KillBanner({ count, onReview }) {
5074
- return /* @__PURE__ */ jsxs15("div", { className: "vos-banner vos-banner-crit", children: [
5075
- /* @__PURE__ */ jsxs15("div", { className: "vos-banner-body", children: [
5076
- /* @__PURE__ */ jsx15("b", { children: count === 1 ? "A belief has fallen into the kill lane" : `${count} beliefs have fallen into the kill lane` }),
5077
- /* @__PURE__ */ jsx15("span", { children: "Confidence \u2264 \u221250 \u2014 the evidence is against it. Kill it or test it again." })
5359
+ return /* @__PURE__ */ jsxs16("div", { className: "vos-banner vos-banner-crit", children: [
5360
+ /* @__PURE__ */ jsxs16("div", { className: "vos-banner-body", children: [
5361
+ /* @__PURE__ */ jsx17("b", { children: count === 1 ? "A belief has fallen into the kill lane" : `${count} beliefs have fallen into the kill lane` }),
5362
+ /* @__PURE__ */ jsx17("span", { children: "Confidence \u2264 \u221250 \u2014 the evidence is against it. Kill it or test it again." })
5078
5363
  ] }),
5079
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: onReview, children: "Review" })
5364
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: onReview, children: "Review" })
5080
5365
  ] });
5081
5366
  }
5082
5367
  function OnDeckRow({
@@ -5086,47 +5371,47 @@ function OnDeckRow({
5086
5371
  }) {
5087
5372
  const pres = movePresentation(move.move);
5088
5373
  const tone = riskLevel(move.risk);
5089
- return /* @__PURE__ */ jsxs15("div", { className: "vos-ondeck-row", children: [
5090
- /* @__PURE__ */ jsx15("span", { className: "vos-risk-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx15("i", { className: `vos-fill-${tone}`, style: { width: `${riskFraction(move.risk) * 100}%` } }) }),
5091
- /* @__PURE__ */ jsx15("button", { type: "button", className: "vos-ondeck-title", onClick: onOpen, children: move.title }),
5092
- /* @__PURE__ */ jsx15("button", { type: "button", className: "vos-pill vos-pill-accent vos-ondeck-act", onClick: onAct, children: pres.pill })
5374
+ return /* @__PURE__ */ jsxs16("div", { className: "vos-ondeck-row", children: [
5375
+ /* @__PURE__ */ jsx17("span", { className: "vos-risk-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx17("i", { className: `vos-fill-${tone}`, style: { width: `${riskFraction(move.risk) * 100}%` } }) }),
5376
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "vos-ondeck-title", onClick: onOpen, children: move.title }),
5377
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "vos-pill vos-pill-accent vos-ondeck-act", onClick: onAct, children: pres.pill })
5093
5378
  ] });
5094
5379
  }
5095
5380
  function WhyPanel({ top, ranked }) {
5096
- return /* @__PURE__ */ jsxs15("div", { className: "vos-why-panel vos-next-why", children: [
5097
- /* @__PURE__ */ jsx15("p", { className: "vos-why-reason", children: top.reason }),
5098
- /* @__PURE__ */ jsxs15("div", { children: [
5099
- /* @__PURE__ */ jsx15("div", { className: "vos-why-section-title", children: "Where it sits" }),
5100
- /* @__PURE__ */ jsx15(StageStepper, { move: top.move })
5381
+ return /* @__PURE__ */ jsxs16("div", { className: "vos-why-panel vos-next-why", children: [
5382
+ /* @__PURE__ */ jsx17("p", { className: "vos-why-reason", children: top.reason }),
5383
+ /* @__PURE__ */ jsxs16("div", { children: [
5384
+ /* @__PURE__ */ jsx17("div", { className: "vos-why-section-title", children: "Where it sits" }),
5385
+ /* @__PURE__ */ jsx17(StageStepper, { move: top.move })
5101
5386
  ] }),
5102
- /* @__PURE__ */ jsxs15("div", { children: [
5103
- /* @__PURE__ */ jsx15("div", { className: "vos-why-section-title", children: "Why it's on top" }),
5104
- /* @__PURE__ */ jsxs15("p", { className: "vos-why-formula", children: [
5387
+ /* @__PURE__ */ jsxs16("div", { children: [
5388
+ /* @__PURE__ */ jsx17("div", { className: "vos-why-section-title", children: "Why it's on top" }),
5389
+ /* @__PURE__ */ jsxs16("p", { className: "vos-why-formula", children: [
5105
5390
  "Ranked by ",
5106
- /* @__PURE__ */ jsx15("b", { children: "Feasibility \xD7 Risk" }),
5391
+ /* @__PURE__ */ jsx17("b", { children: "Feasibility \xD7 Risk" }),
5107
5392
  " \u2014 Risk ",
5108
- /* @__PURE__ */ jsx15("b", { children: Math.round(top.risk) }),
5109
- top.feasibility ? /* @__PURE__ */ jsxs15(Fragment10, { children: [
5393
+ /* @__PURE__ */ jsx17("b", { children: Math.round(top.risk) }),
5394
+ top.feasibility ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
5110
5395
  " ",
5111
5396
  "\xD7 Feasibility ",
5112
- /* @__PURE__ */ jsx15("b", { children: top.feasibility })
5113
- ] }) : /* @__PURE__ */ jsx15(Fragment10, { children: " (no test planned yet \u2014 neutral feasibility)" }),
5397
+ /* @__PURE__ */ jsx17("b", { children: top.feasibility })
5398
+ ] }) : /* @__PURE__ */ jsx17(Fragment10, { children: " (no test planned yet \u2014 neutral feasibility)" }),
5114
5399
  top.killLane ? " \xB7 in the kill lane, so it jumps the queue" : null,
5115
5400
  "."
5116
5401
  ] })
5117
5402
  ] }),
5118
- /* @__PURE__ */ jsxs15("div", { children: [
5119
- /* @__PURE__ */ jsx15("div", { className: "vos-why-section-title", children: "The ranking" }),
5120
- /* @__PURE__ */ jsx15("ol", { className: "vos-why-rank", children: ranked.slice(0, 6).map((m) => /* @__PURE__ */ jsxs15("li", { className: m.assumptionId === top.assumptionId ? "vos-why-rank-top" : "", children: [
5121
- /* @__PURE__ */ jsx15("span", { className: "vos-why-rank-title", children: m.title }),
5122
- /* @__PURE__ */ jsx15("span", { className: "vos-why-rank-score", children: Math.round(m.score) })
5403
+ /* @__PURE__ */ jsxs16("div", { children: [
5404
+ /* @__PURE__ */ jsx17("div", { className: "vos-why-section-title", children: "The ranking" }),
5405
+ /* @__PURE__ */ jsx17("ol", { className: "vos-why-rank", children: ranked.slice(0, 6).map((m) => /* @__PURE__ */ jsxs16("li", { className: m.assumptionId === top.assumptionId ? "vos-why-rank-top" : "", children: [
5406
+ /* @__PURE__ */ jsx17("span", { className: "vos-why-rank-title", children: m.title }),
5407
+ /* @__PURE__ */ jsx17("span", { className: "vos-why-rank-score", children: Math.round(m.score) })
5123
5408
  ] }, m.assumptionId)) })
5124
5409
  ] })
5125
5410
  ] });
5126
5411
  }
5127
5412
  function StageStepper({ move }) {
5128
5413
  const at = MOVE_STAGE[move];
5129
- return /* @__PURE__ */ jsx15("div", { className: "vos-stepper", "aria-label": `Stage: ${STAGES[at]}`, children: STAGES.map((label, i) => /* @__PURE__ */ jsx15(
5414
+ return /* @__PURE__ */ jsx17("div", { className: "vos-stepper", "aria-label": `Stage: ${STAGES[at]}`, children: STAGES.map((label, i) => /* @__PURE__ */ jsx17(
5130
5415
  "span",
5131
5416
  {
5132
5417
  className: `vos-step${i === at ? " vos-step-at" : ""}${i < at ? " vos-step-done" : ""}`,
@@ -5136,6 +5421,290 @@ function StageStepper({ move }) {
5136
5421
  )) });
5137
5422
  }
5138
5423
 
5424
+ // src/stage-grid-surface.tsx
5425
+ import { useMemo as useMemo6, useState as useState12 } from "react";
5426
+
5427
+ // src/stage-grid-model.ts
5428
+ var STAGE_ORDER = [
5429
+ "Discovery",
5430
+ "Validation",
5431
+ "Scale",
5432
+ "Maturity"
5433
+ ];
5434
+ var STAGE_GLOSS = {
5435
+ Discovery: "Problem-solution fit \u2014 will they engage, care, disclose?",
5436
+ Validation: "Product-market fit \u2014 will they pay, sign, stay?",
5437
+ Scale: "Growth \u2014 can we acquire efficiently, does CAC<LTV hold at volume?",
5438
+ Maturity: "Defense \u2014 will incumbents respond, will regulators accept?"
5439
+ };
5440
+ var NO_LENS = "\u2014";
5441
+ var NO_STAGE = "\u2014";
5442
+ function stageOf(record) {
5443
+ const v = str(record.Stage);
5444
+ if (!v) return null;
5445
+ return STAGE_ORDER.includes(v) ? v : null;
5446
+ }
5447
+ function rankByRisk(records) {
5448
+ return [...records].map((r) => ({ r, risk: derivedNum(r, "risk") ?? 0 })).sort(
5449
+ (a, b) => a.risk !== b.risk ? b.risk - a.risk : a.r.id.localeCompare(b.r.id)
5450
+ ).map((x) => x.r);
5451
+ }
5452
+ function buildStageGrid(assumptions) {
5453
+ const lensOrder = [];
5454
+ const seenLens = /* @__PURE__ */ new Set();
5455
+ const pushLens = (lens) => {
5456
+ if (!seenLens.has(lens)) {
5457
+ seenLens.add(lens);
5458
+ lensOrder.push(lens);
5459
+ }
5460
+ };
5461
+ const buckets = /* @__PURE__ */ new Map();
5462
+ const ensureLens = (lens) => {
5463
+ let m = buckets.get(lens);
5464
+ if (!m) {
5465
+ m = /* @__PURE__ */ new Map();
5466
+ buckets.set(lens, m);
5467
+ }
5468
+ return m;
5469
+ };
5470
+ let hasNoLens = false;
5471
+ let hasNoStage = false;
5472
+ for (const a of assumptions) {
5473
+ const lens = str(a.Lens) ?? NO_LENS;
5474
+ const stage = stageOf(a) ?? NO_STAGE;
5475
+ if (lens === NO_LENS) hasNoLens = true;
5476
+ if (stage === NO_STAGE) hasNoStage = true;
5477
+ pushLens(lens);
5478
+ const byStage = ensureLens(lens);
5479
+ let list = byStage.get(stage);
5480
+ if (!list) {
5481
+ list = [];
5482
+ byStage.set(stage, list);
5483
+ }
5484
+ list.push(a);
5485
+ }
5486
+ if (hasNoLens) {
5487
+ lensOrder.splice(lensOrder.indexOf(NO_LENS), 1);
5488
+ lensOrder.push(NO_LENS);
5489
+ } else {
5490
+ const idx = lensOrder.indexOf(NO_LENS);
5491
+ if (idx >= 0) lensOrder.splice(idx, 1);
5492
+ }
5493
+ const stageOrder = [...STAGE_ORDER];
5494
+ if (hasNoStage) stageOrder.push(NO_STAGE);
5495
+ const cells = [];
5496
+ let maxCellCount = 0;
5497
+ let total = 0;
5498
+ for (const lens of lensOrder) {
5499
+ const byStage = buckets.get(lens) ?? /* @__PURE__ */ new Map();
5500
+ for (const stage of stageOrder) {
5501
+ const records = byStage.get(stage) ?? [];
5502
+ const ranked = rankByRisk(records);
5503
+ const count = ranked.length;
5504
+ maxCellCount = Math.max(maxCellCount, count);
5505
+ total += count;
5506
+ cells.push({
5507
+ lens,
5508
+ stage,
5509
+ count,
5510
+ assumptions: ranked,
5511
+ // density filled in a second pass once maxCellCount is known.
5512
+ density: 0
5513
+ });
5514
+ }
5515
+ }
5516
+ const norm2 = maxCellCount > 0 ? 1 / maxCellCount : 0;
5517
+ for (const cell of cells) {
5518
+ cell.density = cell.count * norm2;
5519
+ }
5520
+ return {
5521
+ lenses: lensOrder,
5522
+ stages: [...STAGE_ORDER],
5523
+ cells,
5524
+ maxCellCount,
5525
+ total
5526
+ };
5527
+ }
5528
+ function cellAt(view, lens, stage) {
5529
+ return view.cells.find((c) => c.lens === lens && c.stage === stage) ?? null;
5530
+ }
5531
+
5532
+ // src/stage-grid-surface.tsx
5533
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
5534
+ function StageGridSurface({ basePath, onNavigate }) {
5535
+ const assumptions = useList("assumptions", basePath);
5536
+ const loading = assumptions.loading;
5537
+ const error = assumptions.error;
5538
+ const [open, setOpen] = useState12(null);
5539
+ const view = useMemo6(
5540
+ () => buildStageGrid(assumptions.records ?? []),
5541
+ [assumptions.records]
5542
+ );
5543
+ const refresh = () => assumptions.refresh();
5544
+ const openRecord = (id) => onNavigate({ name: "record", id });
5545
+ if (loading && !assumptions.records) {
5546
+ return /* @__PURE__ */ jsx18(StageGridFrame, { children: /* @__PURE__ */ jsx18("div", { className: "vos-empty", children: "Reading where your bets cluster\u2026" }) });
5547
+ }
5548
+ if (error) {
5549
+ return /* @__PURE__ */ jsx18(StageGridFrame, { children: /* @__PURE__ */ jsx18("div", { className: "vos-banner vos-banner-crit", children: /* @__PURE__ */ jsxs17("div", { className: "vos-banner-body", children: [
5550
+ /* @__PURE__ */ jsx18("b", { children: "Couldn't load the grid." }),
5551
+ /* @__PURE__ */ jsx18("span", { children: error })
5552
+ ] }) }) });
5553
+ }
5554
+ const cold = coldStartFor({
5555
+ assumptions: assumptions.records ?? [],
5556
+ experiments: [],
5557
+ readings: [],
5558
+ decisions: []
5559
+ });
5560
+ if (cold.cold) {
5561
+ return /* @__PURE__ */ jsxs17(StageGridFrame, { children: [
5562
+ /* @__PURE__ */ jsx18("div", { className: "vos-firstrun", children: FIRST_RUN_LINE }),
5563
+ /* @__PURE__ */ jsxs17("div", { className: "vos-card vos-cold vos-cold-stage-grid", children: [
5564
+ /* @__PURE__ */ jsx18("span", { className: "vos-cold-eyebrow", children: "No bets yet" }),
5565
+ /* @__PURE__ */ jsx18("p", { className: "vos-cold-body", children: "The Lens \xD7 Stage grid reads your business state off where your bets cluster. Write your first belief and the grid fills in \u2014 the densest cell per row is where that part of the business is." }),
5566
+ /* @__PURE__ */ jsx18(
5567
+ "button",
5568
+ {
5569
+ type: "button",
5570
+ className: "vos-btn",
5571
+ onClick: () => onNavigate({ name: "records", register: "assumptions" }),
5572
+ children: "Write your first bet"
5573
+ }
5574
+ )
5575
+ ] })
5576
+ ] });
5577
+ }
5578
+ return /* @__PURE__ */ jsxs17(StageGridFrame, { total: view.total, onRefresh: refresh, children: [
5579
+ /* @__PURE__ */ jsxs17("div", { className: "vos-card vos-stage-grid-card", children: [
5580
+ /* @__PURE__ */ jsx18("div", { className: "vos-stage-grid-scroll", children: /* @__PURE__ */ jsxs17("table", { className: "vos-stage-grid", role: "grid", "aria-label": "Lens \xD7 Stage heatmap", children: [
5581
+ /* @__PURE__ */ jsx18("thead", { children: /* @__PURE__ */ jsxs17("tr", { children: [
5582
+ /* @__PURE__ */ jsx18("th", { scope: "col", className: "vos-stage-grid-corner", children: "Lens \u2193 / Stage \u2192" }),
5583
+ view.stages.map((stage) => /* @__PURE__ */ jsxs17("th", { scope: "col", className: "vos-stage-grid-col", children: [
5584
+ /* @__PURE__ */ jsx18("span", { className: "vos-stage-grid-stagename", children: stage }),
5585
+ /* @__PURE__ */ jsx18("span", { className: "vos-stage-grid-stagegloss", children: STAGE_GLOSS[stage] })
5586
+ ] }, stage))
5587
+ ] }) }),
5588
+ /* @__PURE__ */ jsx18("tbody", { children: view.lenses.map((lens) => /* @__PURE__ */ jsxs17("tr", { children: [
5589
+ /* @__PURE__ */ jsx18("th", { scope: "row", className: "vos-stage-grid-rowhead", children: lens }),
5590
+ view.stages.map((stage) => {
5591
+ const cell = cellAt(view, lens, stage);
5592
+ return /* @__PURE__ */ jsx18(
5593
+ StageCell,
5594
+ {
5595
+ cell,
5596
+ onClick: () => setOpen(cell)
5597
+ },
5598
+ stage
5599
+ );
5600
+ })
5601
+ ] }, lens)) })
5602
+ ] }) }),
5603
+ /* @__PURE__ */ jsx18("p", { className: "vos-hint vos-stage-grid-foot", children: "The densest cell per row is where that part of the business is \u2014 no flag, no declaration, the density tells you. Click a cell to drill into its assumptions, ranked by Risk. Thin/empty cells are gaps: Consumer \xD7 Maturity is honestly 0 (consumers don't drive defense bets); a thin Commercial \xD7 Scale row is under-tracking scale." })
5604
+ ] }),
5605
+ /* @__PURE__ */ jsx18(
5606
+ CellDrawer,
5607
+ {
5608
+ cell: open,
5609
+ onClose: () => setOpen(null),
5610
+ onOpenRecord: openRecord
5611
+ }
5612
+ )
5613
+ ] });
5614
+ }
5615
+ function StageGridFrame({
5616
+ total,
5617
+ onRefresh,
5618
+ children
5619
+ }) {
5620
+ return /* @__PURE__ */ jsxs17("div", { children: [
5621
+ /* @__PURE__ */ jsxs17("div", { className: "vos-head", children: [
5622
+ /* @__PURE__ */ jsxs17("div", { children: [
5623
+ /* @__PURE__ */ jsx18("h1", { children: "Lens \xD7 Stage \u2014 where your bets cluster" }),
5624
+ /* @__PURE__ */ jsx18("p", { children: "Every belief cross-tabbed by the actor it's about (Lens) and the kind of response it tests (Stage). The grid is the filter; Risk is the rank." })
5625
+ ] }),
5626
+ /* @__PURE__ */ jsx18("div", { className: "vos-spacer" }),
5627
+ total !== void 0 ? /* @__PURE__ */ jsxs17("span", { className: "vos-hint vos-stage-grid-total", children: [
5628
+ total,
5629
+ " ",
5630
+ total === 1 ? "belief" : "beliefs"
5631
+ ] }) : null,
5632
+ onRefresh ? /* @__PURE__ */ jsx18(
5633
+ "button",
5634
+ {
5635
+ type: "button",
5636
+ className: "vos-btn vos-btn-ghost",
5637
+ onClick: onRefresh,
5638
+ children: "\u21BB Refresh"
5639
+ }
5640
+ ) : null
5641
+ ] }),
5642
+ /* @__PURE__ */ jsx18("div", { className: "vos-stage-grid-host", children })
5643
+ ] });
5644
+ }
5645
+ function StageCell({
5646
+ cell,
5647
+ onClick
5648
+ }) {
5649
+ const empty = cell.count === 0;
5650
+ const style = empty ? void 0 : {
5651
+ // Heatmap fill: opacity 0.08 → 0.92 across the density range, on the
5652
+ // accent token. Keeps the grid readable in both themes.
5653
+ "--vos-cell-alpha": (0.08 + cell.density * 0.84).toFixed(3)
5654
+ };
5655
+ return /* @__PURE__ */ jsx18(
5656
+ "td",
5657
+ {
5658
+ className: `vos-stage-grid-cell${empty ? " vos-stage-grid-cell-empty" : ""}`,
5659
+ style,
5660
+ children: /* @__PURE__ */ jsx18(
5661
+ "button",
5662
+ {
5663
+ type: "button",
5664
+ className: "vos-stage-grid-btn",
5665
+ onClick,
5666
+ "aria-label": `${cell.lens} \xD7 ${cell.stage}: ${cell.count} ${cell.count === 1 ? "belief" : "beliefs"}`,
5667
+ title: empty ? "No beliefs in this cell" : `Riskiest: ${cell.assumptions[0]?.Title ?? "\u2014"}`,
5668
+ children: /* @__PURE__ */ jsx18("span", { className: "vos-stage-grid-count vos-num", children: cell.count })
5669
+ }
5670
+ )
5671
+ }
5672
+ );
5673
+ }
5674
+ function CellDrawer({
5675
+ cell,
5676
+ onClose,
5677
+ onOpenRecord
5678
+ }) {
5679
+ return /* @__PURE__ */ jsxs17(
5680
+ DrawerShell,
5681
+ {
5682
+ open: cell !== null,
5683
+ onClose,
5684
+ ariaLabel: cell ? `${cell.lens} \xD7 ${cell.stage} \u2014 ${cell.count} ${cell.count === 1 ? "belief" : "beliefs"}` : "Cell drill-through",
5685
+ children: [
5686
+ /* @__PURE__ */ jsx18("header", { className: "vos-drawer-header", children: /* @__PURE__ */ jsxs17("div", { children: [
5687
+ /* @__PURE__ */ jsx18("p", { className: "vos-drawer-eyebrow", children: "Lens \xD7 Stage" }),
5688
+ /* @__PURE__ */ jsxs17("h2", { className: "vos-drawer-title", children: [
5689
+ cell?.lens,
5690
+ " \xD7 ",
5691
+ cell?.stage
5692
+ ] }),
5693
+ /* @__PURE__ */ jsx18("p", { className: "vos-hint", children: cell && cell.count > 0 ? `${cell.count} ${cell.count === 1 ? "belief" : "beliefs"}, ranked by Risk \u2014 riskiest first.` : "No beliefs in this cell." })
5694
+ ] }) }),
5695
+ cell && cell.count > 0 ? /* @__PURE__ */ jsx18("div", { className: "vos-stage-grid-drawer-body", children: /* @__PURE__ */ jsx18(
5696
+ RegisterTable,
5697
+ {
5698
+ register: "assumptions",
5699
+ records: cell.assumptions,
5700
+ onRowClick: onOpenRecord
5701
+ }
5702
+ ) }) : cell ? /* @__PURE__ */ jsx18("p", { className: "vos-empty", style: { margin: 16 }, children: "No beliefs in this cell \u2014 a gap, not a bug." }) : null
5703
+ ]
5704
+ }
5705
+ );
5706
+ }
5707
+
5139
5708
  // src/route.ts
5140
5709
  var DEFAULT_ROUTE = { name: "next" };
5141
5710
  function parseRoute(hash, registers) {
@@ -5145,6 +5714,7 @@ function parseRoute(hash, registers) {
5145
5714
  const head = parts[0] ?? "";
5146
5715
  if (head === "next") return { name: "next" };
5147
5716
  if (head === "pipeline") return { name: "pipeline" };
5717
+ if (head === "stage-grid") return { name: "stage-grid" };
5148
5718
  if (head === "record") {
5149
5719
  const id = parts.slice(1).join("/");
5150
5720
  return id ? { name: "record", id } : DEFAULT_ROUTE;
@@ -5166,7 +5736,7 @@ function formatRoute(route) {
5166
5736
  }
5167
5737
 
5168
5738
  // src/sidebar-nav.tsx
5169
- import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
5739
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
5170
5740
  function SidebarNav({
5171
5741
  route,
5172
5742
  onNavigate,
@@ -5175,12 +5745,12 @@ function SidebarNav({
5175
5745
  registers
5176
5746
  }) {
5177
5747
  const activeRegister = route.name === "records" ? route.register : null;
5178
- return /* @__PURE__ */ jsxs16("nav", { className: "vos-nav", "aria-label": "Navigation", children: [
5179
- /* @__PURE__ */ jsxs16("div", { children: [
5180
- /* @__PURE__ */ jsx16("div", { className: "vos-nav-group", children: "Workflow" }),
5748
+ return /* @__PURE__ */ jsxs18("nav", { className: "vos-nav", "aria-label": "Navigation", children: [
5749
+ /* @__PURE__ */ jsxs18("div", { children: [
5750
+ /* @__PURE__ */ jsx19("div", { className: "vos-nav-group", children: "Workflow" }),
5181
5751
  WORKFLOW_NAV.map((item) => {
5182
5752
  const active = route.name === item.route;
5183
- return /* @__PURE__ */ jsxs16(
5753
+ return /* @__PURE__ */ jsxs18(
5184
5754
  "button",
5185
5755
  {
5186
5756
  type: "button",
@@ -5188,20 +5758,20 @@ function SidebarNav({
5188
5758
  "aria-current": active ? "page" : void 0,
5189
5759
  onClick: () => onNavigate({ name: item.route }),
5190
5760
  children: [
5191
- /* @__PURE__ */ jsx16("span", { className: "vos-nav-ic", "aria-hidden": "true", children: item.icon }),
5761
+ /* @__PURE__ */ jsx19("span", { className: "vos-nav-ic", "aria-hidden": "true", children: item.icon }),
5192
5762
  item.label,
5193
- item.isDefault ? /* @__PURE__ */ jsx16("span", { className: "vos-nav-default", children: "home" }) : null
5763
+ item.isDefault ? /* @__PURE__ */ jsx19("span", { className: "vos-nav-default", children: "home" }) : null
5194
5764
  ]
5195
5765
  },
5196
5766
  item.route
5197
5767
  );
5198
5768
  })
5199
5769
  ] }),
5200
- /* @__PURE__ */ jsxs16("div", { children: [
5201
- /* @__PURE__ */ jsx16("div", { className: "vos-nav-group", children: "Records" }),
5770
+ /* @__PURE__ */ jsxs18("div", { children: [
5771
+ /* @__PURE__ */ jsx19("div", { className: "vos-nav-group", children: "Records" }),
5202
5772
  registers.map((register) => {
5203
5773
  const active = register === activeRegister;
5204
- return /* @__PURE__ */ jsxs16(
5774
+ return /* @__PURE__ */ jsxs18(
5205
5775
  "button",
5206
5776
  {
5207
5777
  type: "button",
@@ -5209,9 +5779,9 @@ function SidebarNav({
5209
5779
  "aria-current": active ? "page" : void 0,
5210
5780
  onClick: () => onNavigate({ name: "records", register }),
5211
5781
  children: [
5212
- /* @__PURE__ */ jsx16("span", { className: "vos-nav-ic", "aria-hidden": "true", children: REGISTER_ICON[register] }),
5782
+ /* @__PURE__ */ jsx19("span", { className: "vos-nav-ic", "aria-hidden": "true", children: REGISTER_ICON[register] }),
5213
5783
  REGISTER_LABEL[register],
5214
- needsHuman?.[register] ? /* @__PURE__ */ jsx16(
5784
+ needsHuman?.[register] ? /* @__PURE__ */ jsx19(
5215
5785
  "span",
5216
5786
  {
5217
5787
  className: "vos-nav-alert",
@@ -5219,7 +5789,7 @@ function SidebarNav({
5219
5789
  children: formatCount(needsHuman[register] ?? 0)
5220
5790
  }
5221
5791
  ) : null,
5222
- /* @__PURE__ */ jsx16("span", { className: "vos-nav-count vos-num", children: counts?.[register] !== void 0 ? formatCount(counts[register] ?? 0) : "\xB7" })
5792
+ /* @__PURE__ */ jsx19("span", { className: "vos-nav-count vos-num", children: counts?.[register] !== void 0 ? formatCount(counts[register] ?? 0) : "\xB7" })
5223
5793
  ]
5224
5794
  },
5225
5795
  register
@@ -5230,12 +5800,12 @@ function SidebarNav({
5230
5800
  }
5231
5801
 
5232
5802
  // src/use-counts.ts
5233
- import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo6, useState as useState12 } from "react";
5803
+ import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo7, useState as useState13 } from "react";
5234
5804
  function useCounts(basePath = "/api") {
5235
- const [counts, setCounts] = useState12(null);
5236
- const [loading, setLoading] = useState12(true);
5237
- const [error, setError] = useState12(null);
5238
- const [tick, setTick] = useState12(0);
5805
+ const [counts, setCounts] = useState13(null);
5806
+ const [loading, setLoading] = useState13(true);
5807
+ const [error, setError] = useState13(null);
5808
+ const [tick, setTick] = useState13(0);
5239
5809
  useEffect5(() => {
5240
5810
  let live = true;
5241
5811
  setLoading(true);
@@ -5263,8 +5833,8 @@ function useNeedsHuman(basePath = "/api") {
5263
5833
  const assumptions = useList("assumptions", basePath);
5264
5834
  const experiments = useList("experiments", basePath);
5265
5835
  const decisions = useList("decisions", basePath);
5266
- const [asOf] = useState12(() => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
5267
- return useMemo6(() => {
5836
+ const [asOf] = useState13(() => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
5837
+ return useMemo7(() => {
5268
5838
  const counts = needsHumanCounts({
5269
5839
  asOf,
5270
5840
  assumptions: assumptions.records ?? [],
@@ -5280,7 +5850,7 @@ function useNeedsHuman(basePath = "/api") {
5280
5850
  }
5281
5851
 
5282
5852
  // src/dashboard-app.tsx
5283
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
5853
+ import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
5284
5854
  function initialsOf(name) {
5285
5855
  const parts = name.trim().split(/\s+/);
5286
5856
  const first = parts[0]?.[0] ?? "";
@@ -5296,7 +5866,7 @@ function ValidationOSDashboard({ config = {} }) {
5296
5866
  user,
5297
5867
  registers = REGISTER_ORDER
5298
5868
  } = config;
5299
- const [route, setRoute] = useState13(
5869
+ const [route, setRoute] = useState14(
5300
5870
  () => typeof window === "undefined" ? { name: "next" } : parseRoute(window.location.hash, registers)
5301
5871
  );
5302
5872
  const { counts } = useCounts(basePath);
@@ -5322,33 +5892,33 @@ function ValidationOSDashboard({ config = {} }) {
5322
5892
  }, []);
5323
5893
  const brandName = branding?.name ?? "Validation-OS";
5324
5894
  const brandMark = branding?.initials ?? "V";
5325
- return /* @__PURE__ */ jsxs17("div", { className: "vos-app", children: [
5326
- /* @__PURE__ */ jsxs17("div", { className: "vos-brand", children: [
5327
- /* @__PURE__ */ jsx17("span", { className: "vos-brand-dot", children: branding?.logoUrl ? /* @__PURE__ */ jsx17("img", { src: branding.logoUrl, alt: "" }) : brandMark }),
5895
+ return /* @__PURE__ */ jsxs19("div", { className: "vos-app", children: [
5896
+ /* @__PURE__ */ jsxs19("div", { className: "vos-brand", children: [
5897
+ /* @__PURE__ */ jsx20("span", { className: "vos-brand-dot", children: branding?.logoUrl ? /* @__PURE__ */ jsx20("img", { src: branding.logoUrl, alt: "" }) : brandMark }),
5328
5898
  " ",
5329
5899
  brandName
5330
5900
  ] }),
5331
- /* @__PURE__ */ jsxs17("div", { className: "vos-topbar", children: [
5332
- backendLabel ? /* @__PURE__ */ jsxs17("div", { className: "vos-backend", children: [
5333
- /* @__PURE__ */ jsx17("span", { className: "vos-live-dot" }),
5901
+ /* @__PURE__ */ jsxs19("div", { className: "vos-topbar", children: [
5902
+ backendLabel ? /* @__PURE__ */ jsxs19("div", { className: "vos-backend", children: [
5903
+ /* @__PURE__ */ jsx20("span", { className: "vos-live-dot" }),
5334
5904
  " Backend: ",
5335
- /* @__PURE__ */ jsx17("b", { children: backendLabel })
5905
+ /* @__PURE__ */ jsx20("b", { children: backendLabel })
5336
5906
  ] }) : null,
5337
- agentLabel ? /* @__PURE__ */ jsxs17("span", { className: "vos-hint", children: [
5907
+ agentLabel ? /* @__PURE__ */ jsxs19("span", { className: "vos-hint", children: [
5338
5908
  "Agent: ",
5339
- /* @__PURE__ */ jsx17("b", { style: { color: "var(--vos-text)" }, children: agentLabel })
5909
+ /* @__PURE__ */ jsx20("b", { style: { color: "var(--vos-text)" }, children: agentLabel })
5340
5910
  ] }) : null,
5341
- /* @__PURE__ */ jsx17("div", { className: "vos-spacer" }),
5342
- /* @__PURE__ */ jsx17("button", { type: "button", className: "vos-iconbtn", onClick: toggleTheme, children: "\u25D0 Theme" }),
5343
- user?.name ? /* @__PURE__ */ jsxs17("div", { className: "vos-user", children: [
5344
- /* @__PURE__ */ jsx17("span", { className: "vos-avatar", children: initialsOf(user.name) }),
5345
- /* @__PURE__ */ jsxs17("div", { children: [
5346
- /* @__PURE__ */ jsx17("span", { className: "vos-user-name", children: user.name }),
5347
- user.caption ? /* @__PURE__ */ jsx17("small", { children: user.caption }) : null
5911
+ /* @__PURE__ */ jsx20("div", { className: "vos-spacer" }),
5912
+ /* @__PURE__ */ jsx20("button", { type: "button", className: "vos-iconbtn", onClick: toggleTheme, children: "\u25D0 Theme" }),
5913
+ user?.name ? /* @__PURE__ */ jsxs19("div", { className: "vos-user", children: [
5914
+ /* @__PURE__ */ jsx20("span", { className: "vos-avatar", children: initialsOf(user.name) }),
5915
+ /* @__PURE__ */ jsxs19("div", { children: [
5916
+ /* @__PURE__ */ jsx20("span", { className: "vos-user-name", children: user.name }),
5917
+ user.caption ? /* @__PURE__ */ jsx20("small", { children: user.caption }) : null
5348
5918
  ] })
5349
5919
  ] }) : null
5350
5920
  ] }),
5351
- /* @__PURE__ */ jsx17(
5921
+ /* @__PURE__ */ jsx20(
5352
5922
  SidebarNav,
5353
5923
  {
5354
5924
  route,
@@ -5358,7 +5928,7 @@ function ValidationOSDashboard({ config = {} }) {
5358
5928
  registers
5359
5929
  }
5360
5930
  ),
5361
- /* @__PURE__ */ jsx17("main", { className: "vos-main", children: route.name === "records" ? /* @__PURE__ */ jsx17(
5931
+ /* @__PURE__ */ jsx20("main", { className: "vos-main", children: route.name === "records" ? /* @__PURE__ */ jsx20(
5362
5932
  RegisterBrowser,
5363
5933
  {
5364
5934
  register: route.register,
@@ -5367,7 +5937,7 @@ function ValidationOSDashboard({ config = {} }) {
5367
5937
  onOpenRecord: (id) => navigate({ name: "record", id })
5368
5938
  },
5369
5939
  route.register
5370
- ) : route.name === "record" ? /* @__PURE__ */ jsx17(
5940
+ ) : route.name === "record" ? /* @__PURE__ */ jsx20(
5371
5941
  RecordPage,
5372
5942
  {
5373
5943
  recordId: route.id,
@@ -5376,7 +5946,7 @@ function ValidationOSDashboard({ config = {} }) {
5376
5946
  basePath
5377
5947
  },
5378
5948
  route.id
5379
- ) : route.name === "pipeline" ? /* @__PURE__ */ jsx17(PipelineSurface, { basePath, onNavigate: navigate }, "pipeline") : /* @__PURE__ */ jsx17(NextMoveSurface, { basePath, onNavigate: navigate }, "next") })
5949
+ ) : route.name === "pipeline" ? /* @__PURE__ */ jsx20(PipelineSurface, { basePath, onNavigate: navigate }, "pipeline") : route.name === "stage-grid" ? /* @__PURE__ */ jsx20(StageGridSurface, { basePath, onNavigate: navigate }, "stage-grid") : /* @__PURE__ */ jsx20(NextMoveSurface, { basePath, onNavigate: navigate }, "next") })
5380
5950
  ] });
5381
5951
  }
5382
5952
 
@@ -5406,15 +5976,15 @@ function composeConnectCommand(input) {
5406
5976
  }
5407
5977
 
5408
5978
  // src/connect-claude-code.tsx
5409
- import { useState as useState14 } from "react";
5410
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
5979
+ import { useState as useState15 } from "react";
5980
+ import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
5411
5981
  function ConnectClaudeCode({
5412
5982
  apiBaseUrl,
5413
5983
  tokenEnv,
5414
5984
  mintToken
5415
5985
  }) {
5416
- const [state, setState] = useState14({ phase: "idle" });
5417
- const [copied, setCopied] = useState14(false);
5986
+ const [state, setState] = useState15({ phase: "idle" });
5987
+ const [copied, setCopied] = useState15(false);
5418
5988
  async function generate() {
5419
5989
  setState({ phase: "minting" });
5420
5990
  setCopied(false);
@@ -5436,21 +6006,21 @@ function ConnectClaudeCode({
5436
6006
  } catch {
5437
6007
  }
5438
6008
  }
5439
- return /* @__PURE__ */ jsxs18("div", { children: [
5440
- /* @__PURE__ */ jsx18("div", { className: "vos-head", children: /* @__PURE__ */ jsxs18("div", { children: [
5441
- /* @__PURE__ */ jsx18("h1", { children: "Connect Claude Code" }),
5442
- /* @__PURE__ */ jsx18("p", { children: "Run the validation skills against this register from your own Claude Code \u2014 no repo, no keys to hunt down." })
6009
+ return /* @__PURE__ */ jsxs20("div", { children: [
6010
+ /* @__PURE__ */ jsx21("div", { className: "vos-head", children: /* @__PURE__ */ jsxs20("div", { children: [
6011
+ /* @__PURE__ */ jsx21("h1", { children: "Connect Claude Code" }),
6012
+ /* @__PURE__ */ jsx21("p", { children: "Run the validation skills against this register from your own Claude Code \u2014 no repo, no keys to hunt down." })
5443
6013
  ] }) }),
5444
- /* @__PURE__ */ jsxs18("ol", { className: "vos-hint", style: { lineHeight: 1.8 }, children: [
5445
- /* @__PURE__ */ jsx18("li", { children: "Generate your personal connection command below." }),
5446
- /* @__PURE__ */ jsx18("li", { children: "Paste it into a terminal in the workspace you'll run the skills in." }),
5447
- /* @__PURE__ */ jsxs18("li", { children: [
6014
+ /* @__PURE__ */ jsxs20("ol", { className: "vos-hint", style: { lineHeight: 1.8 }, children: [
6015
+ /* @__PURE__ */ jsx21("li", { children: "Generate your personal connection command below." }),
6016
+ /* @__PURE__ */ jsx21("li", { children: "Paste it into a terminal in the workspace you'll run the skills in." }),
6017
+ /* @__PURE__ */ jsxs20("li", { children: [
5448
6018
  "The command carries a token tied to ",
5449
- /* @__PURE__ */ jsx18("strong", { children: "you" }),
6019
+ /* @__PURE__ */ jsx21("strong", { children: "you" }),
5450
6020
  " \u2014 anything you write lands under your name. Don't share it."
5451
6021
  ] })
5452
6022
  ] }),
5453
- state.phase !== "ready" ? /* @__PURE__ */ jsx18(
6023
+ state.phase !== "ready" ? /* @__PURE__ */ jsx21(
5454
6024
  "button",
5455
6025
  {
5456
6026
  type: "button",
@@ -5460,11 +6030,11 @@ function ConnectClaudeCode({
5460
6030
  children: state.phase === "minting" ? "Generating\u2026" : "Generate connection command"
5461
6031
  }
5462
6032
  ) : null,
5463
- state.phase === "error" ? /* @__PURE__ */ jsx18("p", { className: "vos-hint", role: "alert", children: state.message }) : null,
5464
- state.phase === "ready" ? /* @__PURE__ */ jsxs18("div", { children: [
5465
- /* @__PURE__ */ jsx18("pre", { className: "vos-code", "aria-label": "Connection command", children: state.command }),
5466
- /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: 8 }, children: [
5467
- /* @__PURE__ */ jsx18(
6033
+ state.phase === "error" ? /* @__PURE__ */ jsx21("p", { className: "vos-hint", role: "alert", children: state.message }) : null,
6034
+ state.phase === "ready" ? /* @__PURE__ */ jsxs20("div", { children: [
6035
+ /* @__PURE__ */ jsx21("pre", { className: "vos-code", "aria-label": "Connection command", children: state.command }),
6036
+ /* @__PURE__ */ jsxs20("div", { style: { display: "flex", gap: 8 }, children: [
6037
+ /* @__PURE__ */ jsx21(
5468
6038
  "button",
5469
6039
  {
5470
6040
  type: "button",
@@ -5473,31 +6043,31 @@ function ConnectClaudeCode({
5473
6043
  children: copied ? "Copied" : "Copy command"
5474
6044
  }
5475
6045
  ),
5476
- /* @__PURE__ */ jsx18("button", { type: "button", className: "vos-btn-ghost", onClick: generate, children: "Regenerate" })
6046
+ /* @__PURE__ */ jsx21("button", { type: "button", className: "vos-btn-ghost", onClick: generate, children: "Regenerate" })
5477
6047
  ] }),
5478
- /* @__PURE__ */ jsx18("p", { className: "vos-hint", style: { marginTop: 12 }, children: "Generating again revokes nothing on its own \u2014 remove old keys from your account settings when you rotate." })
6048
+ /* @__PURE__ */ jsx21("p", { className: "vos-hint", style: { marginTop: 12 }, children: "Generating again revokes nothing on its own \u2014 remove old keys from your account settings when you rotate." })
5479
6049
  ] }) : null
5480
6050
  ] });
5481
6051
  }
5482
6052
 
5483
6053
  // src/surface-placeholder.tsx
5484
- import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
6054
+ import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
5485
6055
  function SurfacePlaceholder({
5486
6056
  title,
5487
6057
  subtitle,
5488
6058
  detail
5489
6059
  }) {
5490
- return /* @__PURE__ */ jsxs19("div", { children: [
5491
- /* @__PURE__ */ jsx19("div", { className: "vos-head", children: /* @__PURE__ */ jsxs19("div", { children: [
5492
- /* @__PURE__ */ jsx19("h1", { children: title }),
5493
- /* @__PURE__ */ jsx19("p", { children: subtitle })
6060
+ return /* @__PURE__ */ jsxs21("div", { children: [
6061
+ /* @__PURE__ */ jsx22("div", { className: "vos-head", children: /* @__PURE__ */ jsxs21("div", { children: [
6062
+ /* @__PURE__ */ jsx22("h1", { children: title }),
6063
+ /* @__PURE__ */ jsx22("p", { children: subtitle })
5494
6064
  ] }) }),
5495
- /* @__PURE__ */ jsx19("div", { className: "vos-empty", children: detail })
6065
+ /* @__PURE__ */ jsx22("div", { className: "vos-empty", children: detail })
5496
6066
  ] });
5497
6067
  }
5498
6068
 
5499
6069
  // src/register-counts.tsx
5500
- import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
6070
+ import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
5501
6071
  function RegisterCounts({
5502
6072
  counts,
5503
6073
  caption,
@@ -5507,8 +6077,8 @@ function RegisterCounts({
5507
6077
  const registers = REGISTER_ORDER.filter(
5508
6078
  (r) => counts[r] !== void 0
5509
6079
  );
5510
- return /* @__PURE__ */ jsxs20("section", { "aria-label": "Register counts", children: [
5511
- /* @__PURE__ */ jsx20("div", { className: "vos-tile-grid", children: registers.map((register) => /* @__PURE__ */ jsx20(
6080
+ return /* @__PURE__ */ jsxs22("section", { "aria-label": "Register counts", children: [
6081
+ /* @__PURE__ */ jsx23("div", { className: "vos-tile-grid", children: registers.map((register) => /* @__PURE__ */ jsx23(
5512
6082
  StatTile,
5513
6083
  {
5514
6084
  label: REGISTER_LABEL[register],
@@ -5518,11 +6088,12 @@ function RegisterCounts({
5518
6088
  },
5519
6089
  register
5520
6090
  )) }),
5521
- caption ? /* @__PURE__ */ jsx20("p", { className: "vos-hint", style: { marginTop: 16 }, children: caption }) : null
6091
+ caption ? /* @__PURE__ */ jsx23("p", { className: "vos-hint", style: { marginTop: 16 }, children: caption }) : null
5522
6092
  ] });
5523
6093
  }
5524
6094
  export {
5525
6095
  BeliefJourney,
6096
+ BeliefVerdicts,
5526
6097
  CONFLICT_MESSAGE,
5527
6098
  ConfidenceCell,
5528
6099
  ConnectClaudeCode,
@@ -5533,6 +6104,9 @@ export {
5533
6104
  FIRST_RUN_LINE,
5534
6105
  FieldInput,
5535
6106
  GlossaryText,
6107
+ Markdown,
6108
+ NO_LENS,
6109
+ NO_STAGE,
5536
6110
  NextMoveSurface,
5537
6111
  PipelineSurface,
5538
6112
  REGISTER_GROUPS,
@@ -5551,9 +6125,12 @@ export {
5551
6125
  RegisterTable,
5552
6126
  RelationEditor,
5553
6127
  RiskBar,
6128
+ STAGE_GLOSS,
6129
+ STAGE_ORDER,
5554
6130
  ScoreImpactForm,
5555
6131
  SidebarNav,
5556
6132
  Sparkline,
6133
+ StageGridSurface,
5557
6134
  StatTile,
5558
6135
  StatusPill,
5559
6136
  SurfacePlaceholder,
@@ -5561,12 +6138,15 @@ export {
5561
6138
  ValidationOSDashboard,
5562
6139
  WriteDecisionForm,
5563
6140
  backlinkPanels,
6141
+ bodyPreview,
5564
6142
  buildCycles,
5565
6143
  buildJourney,
5566
6144
  buildPatch,
5567
6145
  buildPipeline,
5568
6146
  buildRecordPage,
6147
+ buildStageGrid,
5569
6148
  buildUnderstanding,
6149
+ cellAt,
5570
6150
  cellValue,
5571
6151
  coldStartFor,
5572
6152
  columnsFor,
@@ -5604,6 +6184,9 @@ export {
5604
6184
  ownerNames,
5605
6185
  parseRoute,
5606
6186
  primaryLabel,
6187
+ rankByRisk,
6188
+ readingAssumptionChips,
6189
+ readingBeliefVerdicts,
5607
6190
  resolveBarLines,
5608
6191
  riskBand,
5609
6192
  riskFraction,
@@ -5613,6 +6196,7 @@ export {
5613
6196
  sortRecords,
5614
6197
  sparklinePath,
5615
6198
  stageMeters,
6199
+ stageOf,
5616
6200
  statusTone,
5617
6201
  tabsFor,
5618
6202
  toCreatePayload,