@validation-os/dashboard 0.7.1 → 0.8.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 +315 -108
- package/dist/index.js +699 -130
- package/dist/index.js.map +1 -1
- package/dist/styles.css +117 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { Collection, AnyRecord, Relation } from '@validation-os/core';
|
|
3
|
+
import { Collection, AnyRecord, Result, Relation, BarLine } from '@validation-os/core';
|
|
4
4
|
import { PortfolioProgress, StageExperimentInput, MoveKind, NextMoveInput, BeliefStage, JourneyEvent, NextMove, JourneyEventKind, ConfSign, StageKey, Progress, MoverKind, TrajectoryPoint } from '@validation-os/core/derivation';
|
|
5
5
|
export { StageKey } from '@validation-os/core/derivation';
|
|
6
6
|
|
|
@@ -384,6 +384,60 @@ interface SidebarNavProps {
|
|
|
384
384
|
*/
|
|
385
385
|
declare function SidebarNav({ route, onNavigate, counts, needsHuman, registers, }: SidebarNavProps): react.JSX.Element;
|
|
386
386
|
|
|
387
|
+
/**
|
|
388
|
+
* The "Connect Claude Code" command composer (OPS-1349). A person signed into
|
|
389
|
+
* the dashboard mints a personal token and gets back ONE ready-to-paste command
|
|
390
|
+
* that points their own Claude Code at this hosted register through the
|
|
391
|
+
* `remote-api` connector. Everything environmental — the API URL, the env-var
|
|
392
|
+
* name — is baked in here; the person supplies only their minted token.
|
|
393
|
+
*
|
|
394
|
+
* Pure and deterministic so it can be unit-tested exactly (prior art:
|
|
395
|
+
* `route.ts`). The config keys it writes (`api_base_url`, `token_env`) are the
|
|
396
|
+
* `remote-api` connector's contract, fixed by the spec — so this does not
|
|
397
|
+
* depend on the connector doc or the setup wizard shipping first.
|
|
398
|
+
*/
|
|
399
|
+
/** The env var the `remote-api` connector reads the bearer token from. */
|
|
400
|
+
declare const DEFAULT_TOKEN_ENV = "VALIDATION_OS_TOKEN";
|
|
401
|
+
interface ConnectCommandInput {
|
|
402
|
+
/** The personal bearer token the deployment minted for the signed-in user. */
|
|
403
|
+
token: string;
|
|
404
|
+
/** The hosted API root, baked in by the deployment. */
|
|
405
|
+
apiBaseUrl: string;
|
|
406
|
+
/** Override the token env-var name; defaults to {@link DEFAULT_TOKEN_ENV}. */
|
|
407
|
+
tokenEnv?: string;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Build the paste command: export the token into its env var, then write a
|
|
411
|
+
* `remote-api` `validation-os.config.yaml` at the workspace root. Running it
|
|
412
|
+
* leaves the workspace ready for `/setup-validation-os` to confirm, or for the
|
|
413
|
+
* skills to use directly.
|
|
414
|
+
*/
|
|
415
|
+
declare function composeConnectCommand(input: ConnectCommandInput): string;
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* The "Connect Claude Code" page (OPS-1349). A person already signed into the
|
|
419
|
+
* dashboard mints a personal token and gets one ready-to-paste command that
|
|
420
|
+
* points their own Claude Code at this hosted register.
|
|
421
|
+
*
|
|
422
|
+
* Auth-vendor-free by construction: token minting is INJECTED (`mintToken`), so
|
|
423
|
+
* this package never imports Clerk — the deployment wires a mint function that
|
|
424
|
+
* creates the signed-in user's personal API key and hands back the token
|
|
425
|
+
* (mirrors how the API's `authenticate` is injected). The command itself is the
|
|
426
|
+
* pure `composeConnectCommand`; this component is only the chrome around it.
|
|
427
|
+
*/
|
|
428
|
+
interface ConnectClaudeCodeProps {
|
|
429
|
+
/** The hosted API root, baked into the emitted command. */
|
|
430
|
+
apiBaseUrl: string;
|
|
431
|
+
/** Override the token env-var name written into the config. */
|
|
432
|
+
tokenEnv?: string;
|
|
433
|
+
/**
|
|
434
|
+
* Mint a personal bearer token for the signed-in user. Injected by the
|
|
435
|
+
* deployment (e.g. create a Clerk API key whose subject is the user's ID).
|
|
436
|
+
*/
|
|
437
|
+
mintToken: () => Promise<string>;
|
|
438
|
+
}
|
|
439
|
+
declare function ConnectClaudeCode({ apiBaseUrl, tokenEnv, mintToken, }: ConnectClaudeCodeProps): react.JSX.Element;
|
|
440
|
+
|
|
387
441
|
interface RecordPageProps {
|
|
388
442
|
/** The record being drilled into (`#record/<id>`). */
|
|
389
443
|
recordId: string;
|
|
@@ -574,6 +628,75 @@ interface MovePresentation {
|
|
|
574
628
|
/** The front-door copy + step-in modality for one act. */
|
|
575
629
|
declare function movePresentation(kind: MoveKind): MovePresentation;
|
|
576
630
|
|
|
631
|
+
/**
|
|
632
|
+
* The per-belief cycles view-model (OPS-1347) — the validation loop's rounds,
|
|
633
|
+
* not just the belief's flat dated event log (`journey.ts`) or the
|
|
634
|
+
* strongest-push-first attribution list (`understanding.ts`). Grounded
|
|
635
|
+
* directly in the registry model (`registry-schema.md`):
|
|
636
|
+
*
|
|
637
|
+
* - a **cycle** is one round of the loop — an Experiment designed against
|
|
638
|
+
* this belief, the (dated) Readings it produced, and the per-belief
|
|
639
|
+
* bar-line verdict it settles at closure. That is literally
|
|
640
|
+
* "experiment → readings → re-score", the round the operator asked to
|
|
641
|
+
* see, and it is the only unit the data model pre-registers as a trial:
|
|
642
|
+
* the bar line's `We're right if` / `We're wrong if` are written *before*
|
|
643
|
+
* any Reading exists, so its verdict is a real round boundary, not one we
|
|
644
|
+
* invent;
|
|
645
|
+
* - readings with **no** Experiment (bare/found — a Market-rung commitment
|
|
646
|
+
* or desk research dropped in directly) carry no pre-registered bar, so
|
|
647
|
+
* they are not a "round" in that strict sense. They still move the
|
|
648
|
+
* number, so they collect into one closing, kind-`"direct"` entry rather
|
|
649
|
+
* than disappearing from the picture.
|
|
650
|
+
*
|
|
651
|
+
* Ordered chronologically (oldest first) — the point of this view is watching
|
|
652
|
+
* the belief move round by round, which `understanding.ts`'s magnitude-first
|
|
653
|
+
* ranking deliberately does not show.
|
|
654
|
+
*
|
|
655
|
+
* No new maths: each round's push on Confidence is read off
|
|
656
|
+
* `confidenceAttribution`'s per-experiment mover — the same decomposition
|
|
657
|
+
* `understanding.ts` shows, just regrouped by time instead of by size, so a
|
|
658
|
+
* cycle's push and the drawer's push always agree. Computed fresh on read,
|
|
659
|
+
* out of the OPS-1251 on-write recompute.
|
|
660
|
+
*/
|
|
661
|
+
|
|
662
|
+
/** The round's key: the experiment id, or `"direct"` for the bare-reading bucket. */
|
|
663
|
+
declare const DIRECT_CYCLE_KEY = "direct";
|
|
664
|
+
/** One reading's place inside a round, reduced to what the timeline draws. */
|
|
665
|
+
interface CycleReadingView {
|
|
666
|
+
id: string;
|
|
667
|
+
date: string | null;
|
|
668
|
+
result: Result | null;
|
|
669
|
+
}
|
|
670
|
+
/** One round of the loop. */
|
|
671
|
+
interface CycleView {
|
|
672
|
+
key: string;
|
|
673
|
+
kind: "experiment" | "direct";
|
|
674
|
+
/** The experiment's title; null for the direct bucket. */
|
|
675
|
+
title: string | null;
|
|
676
|
+
/** The experiment's lifecycle status; null for the direct bucket. */
|
|
677
|
+
status: string | null;
|
|
678
|
+
/** The round's anchor date: the experiment's own `Date`, or (falling back)
|
|
679
|
+
* its earliest reading's date. Null only when neither is known. */
|
|
680
|
+
date: string | null;
|
|
681
|
+
/** This belief's bar-line verdict, once judged; null pre-closure and always
|
|
682
|
+
* null for the direct bucket (it carries no bar line). */
|
|
683
|
+
barVerdict: Result | null;
|
|
684
|
+
/** The round's readings, oldest first. */
|
|
685
|
+
readings: CycleReadingView[];
|
|
686
|
+
/** Signed push on Confidence this round contributed (sums, across every
|
|
687
|
+
* round, to the belief's Confidence). */
|
|
688
|
+
contribution: number;
|
|
689
|
+
/** |contribution| — how hard this round moved the number. */
|
|
690
|
+
magnitude: number;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Build one belief's cycles from its readings and the Experiments register.
|
|
694
|
+
* Both arrays are the raw records (Title-cased fields) — the same shape
|
|
695
|
+
* `understanding.ts`/`journey.ts` take — so a caller loading the registers
|
|
696
|
+
* once can hand them straight through.
|
|
697
|
+
*/
|
|
698
|
+
declare function buildCycles(assumptionId: string, readings: AnyRecord[], experiments: AnyRecord[]): CycleView[];
|
|
699
|
+
|
|
577
700
|
/** A journey event with its front-door copy attached. */
|
|
578
701
|
interface JourneyEventView extends JourneyEvent {
|
|
579
702
|
/** Plain-language label the story renders. */
|
|
@@ -587,6 +710,9 @@ interface JourneyView {
|
|
|
587
710
|
stage: BeliefStage;
|
|
588
711
|
/** The story: the belief's life, oldest first, `now` last. */
|
|
589
712
|
events: JourneyEventView[];
|
|
713
|
+
/** The loop's rounds, oldest first (OPS-1347) — the same history the story
|
|
714
|
+
* tells, regrouped by Experiment run instead of by dated event. */
|
|
715
|
+
cycles: CycleView[];
|
|
590
716
|
/** The ranked next move for this belief; null once it is resolved. */
|
|
591
717
|
nextMove: NextMove | null;
|
|
592
718
|
/** Killed (Invalidated) / moot / null — the drill-in's terminal state. */
|
|
@@ -626,7 +752,9 @@ declare function buildJourney(assumptionId: string, records: NextMoveRecords, no
|
|
|
626
752
|
* rail is pure status: nothing to act on there;
|
|
627
753
|
* - it **expands into the chronological story** through the record page's
|
|
628
754
|
* existing "Why?" reveal idiom — the dated event log (bet → score →
|
|
629
|
-
* experiment → readings → confidence-cross → now),
|
|
755
|
+
* experiment → readings → confidence-cross → now), the same history
|
|
756
|
+
* regrouped into **rounds** (OPS-1347 — one card per Experiment run, plus
|
|
757
|
+
* any bare/direct evidence, oldest first), and ending in the ranked
|
|
630
758
|
* next-move card (OPS-1292).
|
|
631
759
|
*
|
|
632
760
|
* **Step-in is story-only** (OPS-1297): the next-move card and the per-event
|
|
@@ -839,6 +967,10 @@ interface FieldEditor {
|
|
|
839
967
|
options?: readonly string[];
|
|
840
968
|
/** An empty input clears the field to `null` rather than "". */
|
|
841
969
|
nullable?: boolean;
|
|
970
|
+
/** For `number`: the inclusive range a hand-scored value must sit in
|
|
971
|
+
* (e.g. Impact 0–100, `registry-schema.md`). Omitted = unbounded. */
|
|
972
|
+
min?: number;
|
|
973
|
+
max?: number;
|
|
842
974
|
}
|
|
843
975
|
/** The fields a register lets you edit, in render order. */
|
|
844
976
|
declare function editableFields(register: Collection): FieldEditor[];
|
|
@@ -865,15 +997,21 @@ declare function hasEdits(register: Collection, original: AnyRecord, draft: Draf
|
|
|
865
997
|
* surfaces editing one register should never drift into two different forms.
|
|
866
998
|
* Derived numbers are never here — they are computed on write (OPS-1251).
|
|
867
999
|
*/
|
|
868
|
-
declare function EditFields({ register, draft, onField, }: {
|
|
1000
|
+
declare function EditFields({ register, draft, errors, onField, }: {
|
|
869
1001
|
register: Collection;
|
|
870
1002
|
draft: Draft;
|
|
1003
|
+
/** Per-field validation messages (keyed by field), e.g. Impact out of
|
|
1004
|
+
* 0–100 — `edit.ts`'s `draftErrors`. Absent/empty = every field is valid. */
|
|
1005
|
+
errors?: Record<string, string>;
|
|
871
1006
|
onField: (key: string, value: string) => void;
|
|
872
1007
|
}): react.JSX.Element;
|
|
873
1008
|
/** One editable field, as the control its `kind` calls for. */
|
|
874
|
-
declare function FieldInput({ field, value, onChange, }: {
|
|
1009
|
+
declare function FieldInput({ field, value, error, onChange, }: {
|
|
875
1010
|
field: FieldEditor;
|
|
876
1011
|
value: string | undefined;
|
|
1012
|
+
/** A validation message shown under the control, e.g. "Impact must be at
|
|
1013
|
+
* most 100." — never blocks typing, only the Save the caller gates on it. */
|
|
1014
|
+
error?: string;
|
|
877
1015
|
onChange: (value: string) => void;
|
|
878
1016
|
}): react.JSX.Element;
|
|
879
1017
|
|
|
@@ -913,6 +1051,117 @@ interface RegisterTableProps {
|
|
|
913
1051
|
*/
|
|
914
1052
|
declare function RegisterTable({ register, records, onRowClick, selectedId, }: RegisterTableProps): react.JSX.Element;
|
|
915
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* The record-page view-model (OPS-1286) — the pure join behind the canonical
|
|
1056
|
+
* full record page. Given a record and the related registers, it computes the
|
|
1057
|
+
* header lane/queue pills (all derived), the leading-score meters per register,
|
|
1058
|
+
* the genuine human-input free-text remainder, and the backlink panels grouped
|
|
1059
|
+
* by relation (each row carrying a glance-readable score chip, an empty relation
|
|
1060
|
+
* kept as a "none yet" panel rather than dropped). DOM-free and unit-tested at
|
|
1061
|
+
* this seam; `RecordPage` renders what it returns and the understanding layer
|
|
1062
|
+
* supplies the "Why?" attribution unchanged.
|
|
1063
|
+
*/
|
|
1064
|
+
|
|
1065
|
+
/** The registers a record page reads to resolve its relations. All optional —
|
|
1066
|
+
* a panel whose register is absent simply resolves to "none yet". */
|
|
1067
|
+
interface RelatedSet {
|
|
1068
|
+
assumptions?: AnyRecord[];
|
|
1069
|
+
experiments?: AnyRecord[];
|
|
1070
|
+
readings?: AnyRecord[];
|
|
1071
|
+
decisions?: AnyRecord[];
|
|
1072
|
+
glossary?: AnyRecord[];
|
|
1073
|
+
}
|
|
1074
|
+
interface RecordPageOptions {
|
|
1075
|
+
/** ISO date "now" for the Overdue pill; omitted → nothing reads overdue. */
|
|
1076
|
+
asOf?: string;
|
|
1077
|
+
}
|
|
1078
|
+
/** A header pill: a short derived label toned by meaning. */
|
|
1079
|
+
interface Pill {
|
|
1080
|
+
label: string;
|
|
1081
|
+
tone: Tone;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* The derived lane/queue pills for a record header (story 2). Every register
|
|
1085
|
+
* leads with its Status pill; assumptions add Moot / Kill lane / Testing,
|
|
1086
|
+
* experiments add Concluded / Overdue, decisions mark Standing. All derived —
|
|
1087
|
+
* none is a stored field.
|
|
1088
|
+
*/
|
|
1089
|
+
declare function headerPills(register: Collection, record: AnyRecord, related?: RelatedSet, options?: RecordPageOptions): Pill[];
|
|
1090
|
+
/** A leading-score meter. `bar`/`signed` carry a number in a min…max domain;
|
|
1091
|
+
* `pill` carries a categorical value shown as a toned pill. */
|
|
1092
|
+
interface Meter {
|
|
1093
|
+
key: string;
|
|
1094
|
+
label: string;
|
|
1095
|
+
kind: "bar" | "signed" | "pill";
|
|
1096
|
+
/** Number (bar/signed) or category (pill); null when the record has no value. */
|
|
1097
|
+
value: number | string | null;
|
|
1098
|
+
tone: Tone;
|
|
1099
|
+
/** For bar/signed: the domain the fill maps onto. */
|
|
1100
|
+
min?: number;
|
|
1101
|
+
max?: number;
|
|
1102
|
+
/** True when a "Why?" attribution is available (Confidence only). */
|
|
1103
|
+
hasWhy?: boolean;
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* The register's leading scores as meters (story 4). Reads only what the
|
|
1107
|
+
* migrated schema actually stores — a derived number becomes a bar/signed meter,
|
|
1108
|
+
* a categorical leading field becomes a pill; nothing is invented where the
|
|
1109
|
+
* schema carries no number. Confidence is flagged `hasWhy` — the understanding
|
|
1110
|
+
* layer decomposes it.
|
|
1111
|
+
*/
|
|
1112
|
+
declare function leadingMeters(register: Collection, record: AnyRecord): Meter[];
|
|
1113
|
+
/** The genuine human-input free-text remainder — clearly separated from what
|
|
1114
|
+
* the system computed. Auto-linked against the glossary at render time. */
|
|
1115
|
+
interface HumanText {
|
|
1116
|
+
key: string;
|
|
1117
|
+
label: string;
|
|
1118
|
+
text: string;
|
|
1119
|
+
}
|
|
1120
|
+
/** The human-input fields a register carries text for (empty ones dropped). */
|
|
1121
|
+
declare function humanInputFields(register: Collection, record: AnyRecord): HumanText[];
|
|
1122
|
+
/** A glance-readable score chip for a linked record (story 9). */
|
|
1123
|
+
interface ScoreChip {
|
|
1124
|
+
label: string;
|
|
1125
|
+
value: string;
|
|
1126
|
+
tone: Tone;
|
|
1127
|
+
}
|
|
1128
|
+
interface BacklinkItem {
|
|
1129
|
+
id: string;
|
|
1130
|
+
register: Collection;
|
|
1131
|
+
title: string;
|
|
1132
|
+
chip: ScoreChip;
|
|
1133
|
+
}
|
|
1134
|
+
/** A relation panel — the inbound/outbound edges of one relation, grouped and
|
|
1135
|
+
* labelled. Kept even when empty (story 10). */
|
|
1136
|
+
interface RelationPanel {
|
|
1137
|
+
id: string;
|
|
1138
|
+
label: string;
|
|
1139
|
+
register: Collection;
|
|
1140
|
+
items: BacklinkItem[];
|
|
1141
|
+
}
|
|
1142
|
+
/** The linked record's headline score, glance-readable (story 9). */
|
|
1143
|
+
declare function scoreChip(register: Collection, record: AnyRecord): ScoreChip;
|
|
1144
|
+
/** The backlink panels for a record, grouped by relation, each row carrying a
|
|
1145
|
+
* score chip. Empty relations are kept (items: []) so a missing connection reads
|
|
1146
|
+
* as "none yet", not an absent section (story 8/10). */
|
|
1147
|
+
declare function backlinkPanels(register: Collection, record: AnyRecord, related?: RelatedSet): RelationPanel[];
|
|
1148
|
+
type RecordTabId = "overview" | "evidence" | "connections" | "history";
|
|
1149
|
+
interface RecordPageModel {
|
|
1150
|
+
register: Collection;
|
|
1151
|
+
title: string;
|
|
1152
|
+
pills: Pill[];
|
|
1153
|
+
meters: Meter[];
|
|
1154
|
+
humanText: HumanText[];
|
|
1155
|
+
panels: RelationPanel[];
|
|
1156
|
+
/** The tabs this record shows, in order (story 3 + 11). */
|
|
1157
|
+
tabs: RecordTabId[];
|
|
1158
|
+
/** True when the belief journey drill-in can mount here (story 13). */
|
|
1159
|
+
hasJourney: boolean;
|
|
1160
|
+
}
|
|
1161
|
+
/** Assemble the whole record-page model. Pure: same record + related always
|
|
1162
|
+
* gives the same page. */
|
|
1163
|
+
declare function buildRecordPage(register: Collection, record: AnyRecord, related?: RelatedSet, options?: RecordPageOptions): RecordPageModel;
|
|
1164
|
+
|
|
916
1165
|
interface RecordDrawerProps {
|
|
917
1166
|
register: Collection;
|
|
918
1167
|
/** The open record, or null while loading / when nothing is selected. */
|
|
@@ -931,6 +1180,17 @@ interface RecordDrawerProps {
|
|
|
931
1180
|
/** Open this record's canonical full page (story 12). When set, the header
|
|
932
1181
|
* shows a "Full page" link; the drawer stays the quick read/edit peek. */
|
|
933
1182
|
onOpenFull?: () => void;
|
|
1183
|
+
/**
|
|
1184
|
+
* Open *any* linked record's full page (OPS-1345) — the same navigation the
|
|
1185
|
+
* canonical record page's Connections tab uses, reused here so a relation
|
|
1186
|
+
* field or a bar line's assumption is a click, not inert text. Falls back
|
|
1187
|
+
* to plain (unclickable) titles when omitted.
|
|
1188
|
+
*/
|
|
1189
|
+
onOpenRecord?: (id: string) => void;
|
|
1190
|
+
/** The other registers' rows, loaded so a relation field / bar line can
|
|
1191
|
+
* resolve to a title instead of a raw id (OPS-1345). Omitted relations
|
|
1192
|
+
* simply fall back to showing the id. */
|
|
1193
|
+
related?: RelatedSet;
|
|
934
1194
|
/** Extra content below the fields in read mode — e.g. the relation editor. */
|
|
935
1195
|
children?: ReactNode;
|
|
936
1196
|
}
|
|
@@ -945,7 +1205,7 @@ interface RecordDrawerProps {
|
|
|
945
1205
|
* the relation editor (`children`). Chrome is shared via `DrawerShell`; styled
|
|
946
1206
|
* with the package's own token sheet, no host Tailwind.
|
|
947
1207
|
*/
|
|
948
|
-
declare function RecordDrawer({ register, record, loading, error, open, onClose, basePath, onChanged, onOpenFull, children, }: RecordDrawerProps): react.JSX.Element;
|
|
1208
|
+
declare function RecordDrawer({ register, record, loading, error, open, onClose, basePath, onChanged, onOpenFull, onOpenRecord, related, children, }: RecordDrawerProps): react.JSX.Element;
|
|
949
1209
|
|
|
950
1210
|
interface RecordFormProps {
|
|
951
1211
|
register: Collection;
|
|
@@ -1418,115 +1678,62 @@ interface GlossaryTextProps {
|
|
|
1418
1678
|
declare function GlossaryText({ text, terms, selfId, onOpenTerm, }: GlossaryTextProps): react.JSX.Element;
|
|
1419
1679
|
|
|
1420
1680
|
/**
|
|
1421
|
-
* The record
|
|
1422
|
-
*
|
|
1423
|
-
*
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1426
|
-
*
|
|
1427
|
-
*
|
|
1428
|
-
*
|
|
1681
|
+
* The record drawer's generic field list (OPS-1345) — the pure view-model
|
|
1682
|
+
* behind the "everything else" rows a record carries beyond its meters/
|
|
1683
|
+
* human-text/panels. `RecordDrawer` iterates a record's own keys (skipping
|
|
1684
|
+
* provenance/meta), and this module decides how each one reads: a relation
|
|
1685
|
+
* id/id-list (`Depends on`, `Readings`, `Assumption`…) resolves to the linked
|
|
1686
|
+
* record's title, `Owner`/`Agreed by` (stored as dashboard-user objects,
|
|
1687
|
+
* `{id, name}` — `connectors/nosql-schema.md`) reads as name(s) only, and
|
|
1688
|
+
* `barLines` (the embedded per-belief pre-registration on an experiment)
|
|
1689
|
+
* reads as structured rows with a linked assumption title — never the raw
|
|
1690
|
+
* stored JSON or an internal id, per this project's "explain visually, hide
|
|
1691
|
+
* complexity" bias. Everything else still formats through `columns.ts`.
|
|
1692
|
+
* DOM-free and unit-tested at this seam; `record-drawer.tsx` renders what it
|
|
1693
|
+
* returns.
|
|
1429
1694
|
*/
|
|
1430
1695
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
interface
|
|
1434
|
-
assumptions?: AnyRecord[];
|
|
1435
|
-
experiments?: AnyRecord[];
|
|
1436
|
-
readings?: AnyRecord[];
|
|
1437
|
-
decisions?: AnyRecord[];
|
|
1438
|
-
glossary?: AnyRecord[];
|
|
1439
|
-
}
|
|
1440
|
-
interface RecordPageOptions {
|
|
1441
|
-
/** ISO date "now" for the Overdue pill; omitted → nothing reads overdue. */
|
|
1442
|
-
asOf?: string;
|
|
1443
|
-
}
|
|
1444
|
-
/** A header pill: a short derived label toned by meaning. */
|
|
1445
|
-
interface Pill {
|
|
1446
|
-
label: string;
|
|
1447
|
-
tone: Tone;
|
|
1448
|
-
}
|
|
1449
|
-
/**
|
|
1450
|
-
* The derived lane/queue pills for a record header (story 2). Every register
|
|
1451
|
-
* leads with its Status pill; assumptions add Moot / Kill lane / Testing,
|
|
1452
|
-
* experiments add Concluded / Overdue, decisions mark Standing. All derived —
|
|
1453
|
-
* none is a stored field.
|
|
1454
|
-
*/
|
|
1455
|
-
declare function headerPills(register: Collection, record: AnyRecord, related?: RelatedSet, options?: RecordPageOptions): Pill[];
|
|
1456
|
-
/** A leading-score meter. `bar`/`signed` carry a number in a min…max domain;
|
|
1457
|
-
* `pill` carries a categorical value shown as a toned pill. */
|
|
1458
|
-
interface Meter {
|
|
1459
|
-
key: string;
|
|
1460
|
-
label: string;
|
|
1461
|
-
kind: "bar" | "signed" | "pill";
|
|
1462
|
-
/** Number (bar/signed) or category (pill); null when the record has no value. */
|
|
1463
|
-
value: number | string | null;
|
|
1464
|
-
tone: Tone;
|
|
1465
|
-
/** For bar/signed: the domain the fill maps onto. */
|
|
1466
|
-
min?: number;
|
|
1467
|
-
max?: number;
|
|
1468
|
-
/** True when a "Why?" attribution is available (Confidence only). */
|
|
1469
|
-
hasWhy?: boolean;
|
|
1470
|
-
}
|
|
1471
|
-
/**
|
|
1472
|
-
* The register's leading scores as meters (story 4). Reads only what the
|
|
1473
|
-
* migrated schema actually stores — a derived number becomes a bar/signed meter,
|
|
1474
|
-
* a categorical leading field becomes a pill; nothing is invented where the
|
|
1475
|
-
* schema carries no number. Confidence is flagged `hasWhy` — the understanding
|
|
1476
|
-
* layer decomposes it.
|
|
1477
|
-
*/
|
|
1478
|
-
declare function leadingMeters(register: Collection, record: AnyRecord): Meter[];
|
|
1479
|
-
/** The genuine human-input free-text remainder — clearly separated from what
|
|
1480
|
-
* the system computed. Auto-linked against the glossary at render time. */
|
|
1481
|
-
interface HumanText {
|
|
1482
|
-
key: string;
|
|
1483
|
-
label: string;
|
|
1484
|
-
text: string;
|
|
1485
|
-
}
|
|
1486
|
-
/** The human-input fields a register carries text for (empty ones dropped). */
|
|
1487
|
-
declare function humanInputFields(register: Collection, record: AnyRecord): HumanText[];
|
|
1488
|
-
/** A glance-readable score chip for a linked record (story 9). */
|
|
1489
|
-
interface ScoreChip {
|
|
1490
|
-
label: string;
|
|
1491
|
-
value: string;
|
|
1492
|
-
tone: Tone;
|
|
1493
|
-
}
|
|
1494
|
-
interface BacklinkItem {
|
|
1696
|
+
type DetailRowKind = "text" | "relation" | "owner" | "bar-lines";
|
|
1697
|
+
/** One resolved relation target — a title to show, an id to navigate to. */
|
|
1698
|
+
interface DetailRelationItem {
|
|
1495
1699
|
id: string;
|
|
1496
1700
|
register: Collection;
|
|
1497
1701
|
title: string;
|
|
1498
|
-
chip: ScoreChip;
|
|
1499
1702
|
}
|
|
1500
|
-
/**
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
}
|
|
1508
|
-
/** The linked record's headline score, glance-readable (story 9). */
|
|
1509
|
-
declare function scoreChip(register: Collection, record: AnyRecord): ScoreChip;
|
|
1510
|
-
/** The backlink panels for a record, grouped by relation, each row carrying a
|
|
1511
|
-
* score chip. Empty relations are kept (items: []) so a missing connection reads
|
|
1512
|
-
* as "none yet", not an absent section (story 8/10). */
|
|
1513
|
-
declare function backlinkPanels(register: Collection, record: AnyRecord, related?: RelatedSet): RelationPanel[];
|
|
1514
|
-
type RecordTabId = "overview" | "evidence" | "connections" | "history";
|
|
1515
|
-
interface RecordPageModel {
|
|
1516
|
-
register: Collection;
|
|
1517
|
-
title: string;
|
|
1518
|
-
pills: Pill[];
|
|
1519
|
-
meters: Meter[];
|
|
1520
|
-
humanText: HumanText[];
|
|
1521
|
-
panels: RelationPanel[];
|
|
1522
|
-
/** The tabs this record shows, in order (story 3 + 11). */
|
|
1523
|
-
tabs: RecordTabId[];
|
|
1524
|
-
/** True when the belief journey drill-in can mount here (story 13). */
|
|
1525
|
-
hasJourney: boolean;
|
|
1703
|
+
/** One bar line, human-readable: the belief it tests resolved to a title. */
|
|
1704
|
+
interface ResolvedBarLine {
|
|
1705
|
+
rightIf: string;
|
|
1706
|
+
wrongIf: string | null;
|
|
1707
|
+
plannedRung: string;
|
|
1708
|
+
barVerdict: string | null;
|
|
1709
|
+
assumption: DetailRelationItem | null;
|
|
1526
1710
|
}
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1711
|
+
interface DetailRow {
|
|
1712
|
+
key: string;
|
|
1713
|
+
label: string;
|
|
1714
|
+
kind: DetailRowKind;
|
|
1715
|
+
/** `kind: "text"` — the formatted display string. */
|
|
1716
|
+
text?: string;
|
|
1717
|
+
/** `kind: "relation"` — the resolved link targets, in stored order. */
|
|
1718
|
+
items?: DetailRelationItem[];
|
|
1719
|
+
/** `kind: "owner"` — the dashboard-user name(s), never the id/object. */
|
|
1720
|
+
names?: string[];
|
|
1721
|
+
/** `kind: "bar-lines"` — the embedded pre-registration, resolved. */
|
|
1722
|
+
bars?: ResolvedBarLine[];
|
|
1723
|
+
}
|
|
1724
|
+
/** The dashboard-user name(s) off an `Owner`/`Agreed by` value — the stored
|
|
1725
|
+
* shape is `{id, name}[]`; a bare string is tolerated as a fallback. */
|
|
1726
|
+
declare function ownerNames(value: unknown): string[];
|
|
1727
|
+
/** Bar lines resolved against the loaded assumptions — shared by the drawer's
|
|
1728
|
+
* generic list and the record page's Evidence tab so the two never drift. */
|
|
1729
|
+
declare function resolveBarLines(bars: BarLine[], related: RelatedSet): ResolvedBarLine[];
|
|
1730
|
+
/**
|
|
1731
|
+
* The record's own fields, beyond its meta/derived tuple, as rows a drawer
|
|
1732
|
+
* can render directly — relation fields resolved to a title + navigate
|
|
1733
|
+
* target, `Owner`/`Agreed by` to plain names, `barLines` to structured rows.
|
|
1734
|
+
* Everything else still formats through `formatValue` (spec stories 1–3).
|
|
1735
|
+
*/
|
|
1736
|
+
declare function detailRows(register: Collection, record: AnyRecord, related?: RelatedSet): DetailRow[];
|
|
1530
1737
|
|
|
1531
1738
|
/** Plain-language labels — the register is a surface a non-technical
|
|
1532
1739
|
* teammate meets, so no jargon and no code-y plurals. */
|
|
@@ -1548,4 +1755,4 @@ declare const REGISTER_GROUPS: {
|
|
|
1548
1755
|
registers: Collection[];
|
|
1549
1756
|
}[];
|
|
1550
1757
|
|
|
1551
|
-
export { type BacklinkItem, BeliefJourney, type BeliefJourneyProps, CONFLICT_MESSAGE, type CellKind, type ColdStart, type ColumnDef, ConfidenceCell, type Counts, type DashboardConfig, type Draft, EditBeliefForm, type EditBeliefFormProps, EditFields, type ExperimentView, FIRST_RUN_LINE, type FieldEditor, FieldInput, type FieldKind, type FormField, type GlossaryTerm, GlossaryText, type GlossaryTextProps, type GroupBucket, type GroupByAxis, type HumanText, type JourneyColdState, type JourneyEventView, type JourneyView, type LinkArgs, type LinkChoice, type LinkifyNode, type LinkifyOptions, type Meter, type MeterKind, type MovePresentation, type NeedsHumanByRegister, type NeedsHumanCounts, type NeighbourChip, type NestedGroup, type NextColdStart, type NextMoveRecords, NextMoveSurface, type NextMoveSurfaceProps, type OtherMover, type Pill, type PipelineColdStart, type PipelineRow, PipelineSurface, type PipelineView, REGISTER_GROUPS, REGISTER_ICON, REGISTER_LABEL, REGISTER_ORDER, REGISTER_SINGULAR, REGISTER_SUBTITLE, RISK_CRIT, RISK_WARN, RecordDrawer, type RecordDrawerProps, RecordForm, type RecordFormProps, RecordPage, type RecordPageModel, type RecordPageProps, type RecordTabId, RegisterBrowser, type RegisterBrowserProps, type RegisterContext, RegisterCounts, type RegisterCountsProps, RegisterTable, type RegisterTableProps, type RelatedSet, RelationEditor, type RelationEditorProps, type RelationPanel, type ResolvedRow, type RiskBand, RiskBar, type Route, type SaveResult, type SavedView, type ScoreChip, ScoreImpactForm, type ScoreImpactFormProps, type ShapedRegister, SidebarNav, type SidebarNavProps, type SortSpec, Sparkline, type StageMeterInput, type StageMeterView, StatTile, StatusPill, type StepInForm, type StoryStepIn, SurfacePlaceholder, type SurfacePlaceholderProps, type TabDef, type TermPreview, type Tone, type Understanding, UnderstandingPanel, type UseCountsResult, type UseCreateResult, type UseLinkResult, type UseListResult, type UseNeedsHumanResult, type UseRecordResult, type UseSavedViewsResult, type UseUpdateResult, ValidationOSDashboard, type ValidationOSDashboardProps, type ViewDescriptor, WriteDecisionForm, type WriteDecisionFormProps, backlinkPanels, buildJourney, buildPatch, buildPipeline, buildRecordPage, buildUnderstanding, cellValue, coldStartFor, columnsFor, confidenceTone, configureRiskBands, defaultTabId, dontConfuseWith, draftFrom, editableFields, emptyDraft, eventStepIn, eventTone, filterRecords, formFieldsFor, formatCount, formatRoute, formatSigned, formatValue, groupByAxesFor, groupRecords, hasEdits, headerPills, humanInputFields, interpretSave, journeyColdState, leadingMeters, linkChoicesFrom, linkify, missingRequired, movePresentation, needsHumanCounts, nestReadingsByPlan, parseRoute, primaryLabel, riskBand, riskFraction, riskLevel, scoreChip, shapeRegister, sortRecords, sparklinePath, stageMeters, statusTone, tabsFor, toCreatePayload, toGlossaryTerms, toNextMoveInput, toStageExperimentInput, useCounts, useCreate, useLink, useList, useNeedsHuman, useRecord, useSavedViews, useUpdate, weekOverWeekDelta };
|
|
1758
|
+
export { type BacklinkItem, BeliefJourney, type BeliefJourneyProps, CONFLICT_MESSAGE, type CellKind, type ColdStart, type ColumnDef, ConfidenceCell, ConnectClaudeCode, type ConnectClaudeCodeProps, type ConnectCommandInput, type Counts, type CycleReadingView, type CycleView, DEFAULT_TOKEN_ENV, DIRECT_CYCLE_KEY, type DashboardConfig, type DetailRelationItem, type DetailRow, type DetailRowKind, type Draft, EditBeliefForm, type EditBeliefFormProps, EditFields, type ExperimentView, FIRST_RUN_LINE, type FieldEditor, FieldInput, type FieldKind, type FormField, type GlossaryTerm, GlossaryText, type GlossaryTextProps, type GroupBucket, type GroupByAxis, type HumanText, type JourneyColdState, type JourneyEventView, type JourneyView, type LinkArgs, type LinkChoice, type LinkifyNode, type LinkifyOptions, type Meter, type MeterKind, type MovePresentation, type NeedsHumanByRegister, type NeedsHumanCounts, type NeighbourChip, type NestedGroup, type NextColdStart, type NextMoveRecords, NextMoveSurface, type NextMoveSurfaceProps, type OtherMover, type Pill, type PipelineColdStart, type PipelineRow, PipelineSurface, type PipelineView, REGISTER_GROUPS, REGISTER_ICON, REGISTER_LABEL, REGISTER_ORDER, REGISTER_SINGULAR, REGISTER_SUBTITLE, RISK_CRIT, RISK_WARN, RecordDrawer, type RecordDrawerProps, RecordForm, type RecordFormProps, RecordPage, type RecordPageModel, type RecordPageProps, type RecordTabId, RegisterBrowser, type RegisterBrowserProps, type RegisterContext, RegisterCounts, type RegisterCountsProps, RegisterTable, type RegisterTableProps, type RelatedSet, RelationEditor, type RelationEditorProps, type RelationPanel, type ResolvedBarLine, type ResolvedRow, type RiskBand, RiskBar, type Route, type SaveResult, type SavedView, type ScoreChip, ScoreImpactForm, type ScoreImpactFormProps, type ShapedRegister, SidebarNav, type SidebarNavProps, type SortSpec, Sparkline, type StageMeterInput, type StageMeterView, StatTile, StatusPill, type StepInForm, type StoryStepIn, SurfacePlaceholder, type SurfacePlaceholderProps, type TabDef, type TermPreview, type Tone, type Understanding, UnderstandingPanel, type UseCountsResult, type UseCreateResult, type UseLinkResult, type UseListResult, type UseNeedsHumanResult, type UseRecordResult, type UseSavedViewsResult, type UseUpdateResult, ValidationOSDashboard, type ValidationOSDashboardProps, type ViewDescriptor, WriteDecisionForm, type WriteDecisionFormProps, backlinkPanels, buildCycles, buildJourney, buildPatch, buildPipeline, buildRecordPage, buildUnderstanding, cellValue, coldStartFor, columnsFor, composeConnectCommand, confidenceTone, configureRiskBands, defaultTabId, detailRows, dontConfuseWith, draftFrom, editableFields, emptyDraft, eventStepIn, eventTone, filterRecords, formFieldsFor, formatCount, formatRoute, formatSigned, formatValue, groupByAxesFor, groupRecords, hasEdits, headerPills, humanInputFields, interpretSave, journeyColdState, leadingMeters, linkChoicesFrom, linkify, missingRequired, movePresentation, needsHumanCounts, nestReadingsByPlan, ownerNames, parseRoute, primaryLabel, resolveBarLines, riskBand, riskFraction, riskLevel, scoreChip, shapeRegister, sortRecords, sparklinePath, stageMeters, statusTone, tabsFor, toCreatePayload, toGlossaryTerms, toNextMoveInput, toStageExperimentInput, useCounts, useCreate, useLink, useList, useNeedsHuman, useRecord, useSavedViews, useUpdate, weekOverWeekDelta };
|