@validation-os/dashboard 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +141 -7
- package/dist/index.js +370 -75
- package/dist/index.js.map +1 -1
- package/dist/styles.css +135 -0
- package/package.json +2 -2
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
|
|
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,7 +49,8 @@ var REGISTER_GROUPS = [
|
|
|
49
49
|
];
|
|
50
50
|
var WORKFLOW_NAV = [
|
|
51
51
|
{ route: "next", label: "Next move", icon: "\u25C8", isDefault: true },
|
|
52
|
-
{ route: "
|
|
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
|
|
@@ -5420,6 +5421,290 @@ function StageStepper({ move }) {
|
|
|
5420
5421
|
)) });
|
|
5421
5422
|
}
|
|
5422
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
|
+
|
|
5423
5708
|
// src/route.ts
|
|
5424
5709
|
var DEFAULT_ROUTE = { name: "next" };
|
|
5425
5710
|
function parseRoute(hash, registers) {
|
|
@@ -5429,6 +5714,7 @@ function parseRoute(hash, registers) {
|
|
|
5429
5714
|
const head = parts[0] ?? "";
|
|
5430
5715
|
if (head === "next") return { name: "next" };
|
|
5431
5716
|
if (head === "pipeline") return { name: "pipeline" };
|
|
5717
|
+
if (head === "stage-grid") return { name: "stage-grid" };
|
|
5432
5718
|
if (head === "record") {
|
|
5433
5719
|
const id = parts.slice(1).join("/");
|
|
5434
5720
|
return id ? { name: "record", id } : DEFAULT_ROUTE;
|
|
@@ -5450,7 +5736,7 @@ function formatRoute(route) {
|
|
|
5450
5736
|
}
|
|
5451
5737
|
|
|
5452
5738
|
// src/sidebar-nav.tsx
|
|
5453
|
-
import { jsx as
|
|
5739
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
5454
5740
|
function SidebarNav({
|
|
5455
5741
|
route,
|
|
5456
5742
|
onNavigate,
|
|
@@ -5459,12 +5745,12 @@ function SidebarNav({
|
|
|
5459
5745
|
registers
|
|
5460
5746
|
}) {
|
|
5461
5747
|
const activeRegister = route.name === "records" ? route.register : null;
|
|
5462
|
-
return /* @__PURE__ */
|
|
5463
|
-
/* @__PURE__ */
|
|
5464
|
-
/* @__PURE__ */
|
|
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" }),
|
|
5465
5751
|
WORKFLOW_NAV.map((item) => {
|
|
5466
5752
|
const active = route.name === item.route;
|
|
5467
|
-
return /* @__PURE__ */
|
|
5753
|
+
return /* @__PURE__ */ jsxs18(
|
|
5468
5754
|
"button",
|
|
5469
5755
|
{
|
|
5470
5756
|
type: "button",
|
|
@@ -5472,20 +5758,20 @@ function SidebarNav({
|
|
|
5472
5758
|
"aria-current": active ? "page" : void 0,
|
|
5473
5759
|
onClick: () => onNavigate({ name: item.route }),
|
|
5474
5760
|
children: [
|
|
5475
|
-
/* @__PURE__ */
|
|
5761
|
+
/* @__PURE__ */ jsx19("span", { className: "vos-nav-ic", "aria-hidden": "true", children: item.icon }),
|
|
5476
5762
|
item.label,
|
|
5477
|
-
item.isDefault ? /* @__PURE__ */
|
|
5763
|
+
item.isDefault ? /* @__PURE__ */ jsx19("span", { className: "vos-nav-default", children: "home" }) : null
|
|
5478
5764
|
]
|
|
5479
5765
|
},
|
|
5480
5766
|
item.route
|
|
5481
5767
|
);
|
|
5482
5768
|
})
|
|
5483
5769
|
] }),
|
|
5484
|
-
/* @__PURE__ */
|
|
5485
|
-
/* @__PURE__ */
|
|
5770
|
+
/* @__PURE__ */ jsxs18("div", { children: [
|
|
5771
|
+
/* @__PURE__ */ jsx19("div", { className: "vos-nav-group", children: "Records" }),
|
|
5486
5772
|
registers.map((register) => {
|
|
5487
5773
|
const active = register === activeRegister;
|
|
5488
|
-
return /* @__PURE__ */
|
|
5774
|
+
return /* @__PURE__ */ jsxs18(
|
|
5489
5775
|
"button",
|
|
5490
5776
|
{
|
|
5491
5777
|
type: "button",
|
|
@@ -5493,9 +5779,9 @@ function SidebarNav({
|
|
|
5493
5779
|
"aria-current": active ? "page" : void 0,
|
|
5494
5780
|
onClick: () => onNavigate({ name: "records", register }),
|
|
5495
5781
|
children: [
|
|
5496
|
-
/* @__PURE__ */
|
|
5782
|
+
/* @__PURE__ */ jsx19("span", { className: "vos-nav-ic", "aria-hidden": "true", children: REGISTER_ICON[register] }),
|
|
5497
5783
|
REGISTER_LABEL[register],
|
|
5498
|
-
needsHuman?.[register] ? /* @__PURE__ */
|
|
5784
|
+
needsHuman?.[register] ? /* @__PURE__ */ jsx19(
|
|
5499
5785
|
"span",
|
|
5500
5786
|
{
|
|
5501
5787
|
className: "vos-nav-alert",
|
|
@@ -5503,7 +5789,7 @@ function SidebarNav({
|
|
|
5503
5789
|
children: formatCount(needsHuman[register] ?? 0)
|
|
5504
5790
|
}
|
|
5505
5791
|
) : null,
|
|
5506
|
-
/* @__PURE__ */
|
|
5792
|
+
/* @__PURE__ */ jsx19("span", { className: "vos-nav-count vos-num", children: counts?.[register] !== void 0 ? formatCount(counts[register] ?? 0) : "\xB7" })
|
|
5507
5793
|
]
|
|
5508
5794
|
},
|
|
5509
5795
|
register
|
|
@@ -5514,12 +5800,12 @@ function SidebarNav({
|
|
|
5514
5800
|
}
|
|
5515
5801
|
|
|
5516
5802
|
// src/use-counts.ts
|
|
5517
|
-
import { useCallback as useCallback4, useEffect as useEffect5, useMemo as
|
|
5803
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo7, useState as useState13 } from "react";
|
|
5518
5804
|
function useCounts(basePath = "/api") {
|
|
5519
|
-
const [counts, setCounts] =
|
|
5520
|
-
const [loading, setLoading] =
|
|
5521
|
-
const [error, setError] =
|
|
5522
|
-
const [tick, setTick] =
|
|
5805
|
+
const [counts, setCounts] = useState13(null);
|
|
5806
|
+
const [loading, setLoading] = useState13(true);
|
|
5807
|
+
const [error, setError] = useState13(null);
|
|
5808
|
+
const [tick, setTick] = useState13(0);
|
|
5523
5809
|
useEffect5(() => {
|
|
5524
5810
|
let live = true;
|
|
5525
5811
|
setLoading(true);
|
|
@@ -5547,8 +5833,8 @@ function useNeedsHuman(basePath = "/api") {
|
|
|
5547
5833
|
const assumptions = useList("assumptions", basePath);
|
|
5548
5834
|
const experiments = useList("experiments", basePath);
|
|
5549
5835
|
const decisions = useList("decisions", basePath);
|
|
5550
|
-
const [asOf] =
|
|
5551
|
-
return
|
|
5836
|
+
const [asOf] = useState13(() => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
|
|
5837
|
+
return useMemo7(() => {
|
|
5552
5838
|
const counts = needsHumanCounts({
|
|
5553
5839
|
asOf,
|
|
5554
5840
|
assumptions: assumptions.records ?? [],
|
|
@@ -5564,7 +5850,7 @@ function useNeedsHuman(basePath = "/api") {
|
|
|
5564
5850
|
}
|
|
5565
5851
|
|
|
5566
5852
|
// src/dashboard-app.tsx
|
|
5567
|
-
import { jsx as
|
|
5853
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
5568
5854
|
function initialsOf(name) {
|
|
5569
5855
|
const parts = name.trim().split(/\s+/);
|
|
5570
5856
|
const first = parts[0]?.[0] ?? "";
|
|
@@ -5580,7 +5866,7 @@ function ValidationOSDashboard({ config = {} }) {
|
|
|
5580
5866
|
user,
|
|
5581
5867
|
registers = REGISTER_ORDER
|
|
5582
5868
|
} = config;
|
|
5583
|
-
const [route, setRoute] =
|
|
5869
|
+
const [route, setRoute] = useState14(
|
|
5584
5870
|
() => typeof window === "undefined" ? { name: "next" } : parseRoute(window.location.hash, registers)
|
|
5585
5871
|
);
|
|
5586
5872
|
const { counts } = useCounts(basePath);
|
|
@@ -5606,33 +5892,33 @@ function ValidationOSDashboard({ config = {} }) {
|
|
|
5606
5892
|
}, []);
|
|
5607
5893
|
const brandName = branding?.name ?? "Validation-OS";
|
|
5608
5894
|
const brandMark = branding?.initials ?? "V";
|
|
5609
|
-
return /* @__PURE__ */
|
|
5610
|
-
/* @__PURE__ */
|
|
5611
|
-
/* @__PURE__ */
|
|
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 }),
|
|
5612
5898
|
" ",
|
|
5613
5899
|
brandName
|
|
5614
5900
|
] }),
|
|
5615
|
-
/* @__PURE__ */
|
|
5616
|
-
backendLabel ? /* @__PURE__ */
|
|
5617
|
-
/* @__PURE__ */
|
|
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" }),
|
|
5618
5904
|
" Backend: ",
|
|
5619
|
-
/* @__PURE__ */
|
|
5905
|
+
/* @__PURE__ */ jsx20("b", { children: backendLabel })
|
|
5620
5906
|
] }) : null,
|
|
5621
|
-
agentLabel ? /* @__PURE__ */
|
|
5907
|
+
agentLabel ? /* @__PURE__ */ jsxs19("span", { className: "vos-hint", children: [
|
|
5622
5908
|
"Agent: ",
|
|
5623
|
-
/* @__PURE__ */
|
|
5909
|
+
/* @__PURE__ */ jsx20("b", { style: { color: "var(--vos-text)" }, children: agentLabel })
|
|
5624
5910
|
] }) : null,
|
|
5625
|
-
/* @__PURE__ */
|
|
5626
|
-
/* @__PURE__ */
|
|
5627
|
-
user?.name ? /* @__PURE__ */
|
|
5628
|
-
/* @__PURE__ */
|
|
5629
|
-
/* @__PURE__ */
|
|
5630
|
-
/* @__PURE__ */
|
|
5631
|
-
user.caption ? /* @__PURE__ */
|
|
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
|
|
5632
5918
|
] })
|
|
5633
5919
|
] }) : null
|
|
5634
5920
|
] }),
|
|
5635
|
-
/* @__PURE__ */
|
|
5921
|
+
/* @__PURE__ */ jsx20(
|
|
5636
5922
|
SidebarNav,
|
|
5637
5923
|
{
|
|
5638
5924
|
route,
|
|
@@ -5642,7 +5928,7 @@ function ValidationOSDashboard({ config = {} }) {
|
|
|
5642
5928
|
registers
|
|
5643
5929
|
}
|
|
5644
5930
|
),
|
|
5645
|
-
/* @__PURE__ */
|
|
5931
|
+
/* @__PURE__ */ jsx20("main", { className: "vos-main", children: route.name === "records" ? /* @__PURE__ */ jsx20(
|
|
5646
5932
|
RegisterBrowser,
|
|
5647
5933
|
{
|
|
5648
5934
|
register: route.register,
|
|
@@ -5651,7 +5937,7 @@ function ValidationOSDashboard({ config = {} }) {
|
|
|
5651
5937
|
onOpenRecord: (id) => navigate({ name: "record", id })
|
|
5652
5938
|
},
|
|
5653
5939
|
route.register
|
|
5654
|
-
) : route.name === "record" ? /* @__PURE__ */
|
|
5940
|
+
) : route.name === "record" ? /* @__PURE__ */ jsx20(
|
|
5655
5941
|
RecordPage,
|
|
5656
5942
|
{
|
|
5657
5943
|
recordId: route.id,
|
|
@@ -5660,7 +5946,7 @@ function ValidationOSDashboard({ config = {} }) {
|
|
|
5660
5946
|
basePath
|
|
5661
5947
|
},
|
|
5662
5948
|
route.id
|
|
5663
|
-
) : route.name === "pipeline" ? /* @__PURE__ */
|
|
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") })
|
|
5664
5950
|
] });
|
|
5665
5951
|
}
|
|
5666
5952
|
|
|
@@ -5690,15 +5976,15 @@ function composeConnectCommand(input) {
|
|
|
5690
5976
|
}
|
|
5691
5977
|
|
|
5692
5978
|
// src/connect-claude-code.tsx
|
|
5693
|
-
import { useState as
|
|
5694
|
-
import { jsx as
|
|
5979
|
+
import { useState as useState15 } from "react";
|
|
5980
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
5695
5981
|
function ConnectClaudeCode({
|
|
5696
5982
|
apiBaseUrl,
|
|
5697
5983
|
tokenEnv,
|
|
5698
5984
|
mintToken
|
|
5699
5985
|
}) {
|
|
5700
|
-
const [state, setState] =
|
|
5701
|
-
const [copied, setCopied] =
|
|
5986
|
+
const [state, setState] = useState15({ phase: "idle" });
|
|
5987
|
+
const [copied, setCopied] = useState15(false);
|
|
5702
5988
|
async function generate() {
|
|
5703
5989
|
setState({ phase: "minting" });
|
|
5704
5990
|
setCopied(false);
|
|
@@ -5720,21 +6006,21 @@ function ConnectClaudeCode({
|
|
|
5720
6006
|
} catch {
|
|
5721
6007
|
}
|
|
5722
6008
|
}
|
|
5723
|
-
return /* @__PURE__ */
|
|
5724
|
-
/* @__PURE__ */
|
|
5725
|
-
/* @__PURE__ */
|
|
5726
|
-
/* @__PURE__ */
|
|
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." })
|
|
5727
6013
|
] }) }),
|
|
5728
|
-
/* @__PURE__ */
|
|
5729
|
-
/* @__PURE__ */
|
|
5730
|
-
/* @__PURE__ */
|
|
5731
|
-
/* @__PURE__ */
|
|
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: [
|
|
5732
6018
|
"The command carries a token tied to ",
|
|
5733
|
-
/* @__PURE__ */
|
|
6019
|
+
/* @__PURE__ */ jsx21("strong", { children: "you" }),
|
|
5734
6020
|
" \u2014 anything you write lands under your name. Don't share it."
|
|
5735
6021
|
] })
|
|
5736
6022
|
] }),
|
|
5737
|
-
state.phase !== "ready" ? /* @__PURE__ */
|
|
6023
|
+
state.phase !== "ready" ? /* @__PURE__ */ jsx21(
|
|
5738
6024
|
"button",
|
|
5739
6025
|
{
|
|
5740
6026
|
type: "button",
|
|
@@ -5744,11 +6030,11 @@ function ConnectClaudeCode({
|
|
|
5744
6030
|
children: state.phase === "minting" ? "Generating\u2026" : "Generate connection command"
|
|
5745
6031
|
}
|
|
5746
6032
|
) : null,
|
|
5747
|
-
state.phase === "error" ? /* @__PURE__ */
|
|
5748
|
-
state.phase === "ready" ? /* @__PURE__ */
|
|
5749
|
-
/* @__PURE__ */
|
|
5750
|
-
/* @__PURE__ */
|
|
5751
|
-
/* @__PURE__ */
|
|
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(
|
|
5752
6038
|
"button",
|
|
5753
6039
|
{
|
|
5754
6040
|
type: "button",
|
|
@@ -5757,31 +6043,31 @@ function ConnectClaudeCode({
|
|
|
5757
6043
|
children: copied ? "Copied" : "Copy command"
|
|
5758
6044
|
}
|
|
5759
6045
|
),
|
|
5760
|
-
/* @__PURE__ */
|
|
6046
|
+
/* @__PURE__ */ jsx21("button", { type: "button", className: "vos-btn-ghost", onClick: generate, children: "Regenerate" })
|
|
5761
6047
|
] }),
|
|
5762
|
-
/* @__PURE__ */
|
|
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." })
|
|
5763
6049
|
] }) : null
|
|
5764
6050
|
] });
|
|
5765
6051
|
}
|
|
5766
6052
|
|
|
5767
6053
|
// src/surface-placeholder.tsx
|
|
5768
|
-
import { jsx as
|
|
6054
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
5769
6055
|
function SurfacePlaceholder({
|
|
5770
6056
|
title,
|
|
5771
6057
|
subtitle,
|
|
5772
6058
|
detail
|
|
5773
6059
|
}) {
|
|
5774
|
-
return /* @__PURE__ */
|
|
5775
|
-
/* @__PURE__ */
|
|
5776
|
-
/* @__PURE__ */
|
|
5777
|
-
/* @__PURE__ */
|
|
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 })
|
|
5778
6064
|
] }) }),
|
|
5779
|
-
/* @__PURE__ */
|
|
6065
|
+
/* @__PURE__ */ jsx22("div", { className: "vos-empty", children: detail })
|
|
5780
6066
|
] });
|
|
5781
6067
|
}
|
|
5782
6068
|
|
|
5783
6069
|
// src/register-counts.tsx
|
|
5784
|
-
import { jsx as
|
|
6070
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
5785
6071
|
function RegisterCounts({
|
|
5786
6072
|
counts,
|
|
5787
6073
|
caption,
|
|
@@ -5791,8 +6077,8 @@ function RegisterCounts({
|
|
|
5791
6077
|
const registers = REGISTER_ORDER.filter(
|
|
5792
6078
|
(r) => counts[r] !== void 0
|
|
5793
6079
|
);
|
|
5794
|
-
return /* @__PURE__ */
|
|
5795
|
-
/* @__PURE__ */
|
|
6080
|
+
return /* @__PURE__ */ jsxs22("section", { "aria-label": "Register counts", children: [
|
|
6081
|
+
/* @__PURE__ */ jsx23("div", { className: "vos-tile-grid", children: registers.map((register) => /* @__PURE__ */ jsx23(
|
|
5796
6082
|
StatTile,
|
|
5797
6083
|
{
|
|
5798
6084
|
label: REGISTER_LABEL[register],
|
|
@@ -5802,7 +6088,7 @@ function RegisterCounts({
|
|
|
5802
6088
|
},
|
|
5803
6089
|
register
|
|
5804
6090
|
)) }),
|
|
5805
|
-
caption ? /* @__PURE__ */
|
|
6091
|
+
caption ? /* @__PURE__ */ jsx23("p", { className: "vos-hint", style: { marginTop: 16 }, children: caption }) : null
|
|
5806
6092
|
] });
|
|
5807
6093
|
}
|
|
5808
6094
|
export {
|
|
@@ -5819,6 +6105,8 @@ export {
|
|
|
5819
6105
|
FieldInput,
|
|
5820
6106
|
GlossaryText,
|
|
5821
6107
|
Markdown,
|
|
6108
|
+
NO_LENS,
|
|
6109
|
+
NO_STAGE,
|
|
5822
6110
|
NextMoveSurface,
|
|
5823
6111
|
PipelineSurface,
|
|
5824
6112
|
REGISTER_GROUPS,
|
|
@@ -5837,9 +6125,12 @@ export {
|
|
|
5837
6125
|
RegisterTable,
|
|
5838
6126
|
RelationEditor,
|
|
5839
6127
|
RiskBar,
|
|
6128
|
+
STAGE_GLOSS,
|
|
6129
|
+
STAGE_ORDER,
|
|
5840
6130
|
ScoreImpactForm,
|
|
5841
6131
|
SidebarNav,
|
|
5842
6132
|
Sparkline,
|
|
6133
|
+
StageGridSurface,
|
|
5843
6134
|
StatTile,
|
|
5844
6135
|
StatusPill,
|
|
5845
6136
|
SurfacePlaceholder,
|
|
@@ -5853,7 +6144,9 @@ export {
|
|
|
5853
6144
|
buildPatch,
|
|
5854
6145
|
buildPipeline,
|
|
5855
6146
|
buildRecordPage,
|
|
6147
|
+
buildStageGrid,
|
|
5856
6148
|
buildUnderstanding,
|
|
6149
|
+
cellAt,
|
|
5857
6150
|
cellValue,
|
|
5858
6151
|
coldStartFor,
|
|
5859
6152
|
columnsFor,
|
|
@@ -5891,6 +6184,7 @@ export {
|
|
|
5891
6184
|
ownerNames,
|
|
5892
6185
|
parseRoute,
|
|
5893
6186
|
primaryLabel,
|
|
6187
|
+
rankByRisk,
|
|
5894
6188
|
readingAssumptionChips,
|
|
5895
6189
|
readingBeliefVerdicts,
|
|
5896
6190
|
resolveBarLines,
|
|
@@ -5902,6 +6196,7 @@ export {
|
|
|
5902
6196
|
sortRecords,
|
|
5903
6197
|
sparklinePath,
|
|
5904
6198
|
stageMeters,
|
|
6199
|
+
stageOf,
|
|
5905
6200
|
statusTone,
|
|
5906
6201
|
tabsFor,
|
|
5907
6202
|
toCreatePayload,
|