Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
236 commits
Select commit Hold shift + click to select a range
221bbaa
feat(fixtures): Python fixture generator [OMN-30] (#1)
clone45 Apr 19, 2026
df92afa
feat(types): generate TS types from Part 1 Pydantic models [OMN-24] (#2)
clone45 Apr 19, 2026
7380043
feat(data-source): ProtocolSnapshotSource interface [OMN-25] (#4)
clone45 Apr 19, 2026
4ceeb75
feat(data-source): FileSnapshotSource (middleware in Task 4b) [OMN-26…
clone45 Apr 19, 2026
249e185
feat(data-source): HttpSnapshotSource [OMN-28] (#6)
clone45 Apr 19, 2026
b36eeaf
feat(vite): fixturesMiddleware with testable handler + 5 contract tes…
clone45 Apr 19, 2026
17558a7
refactor(hooks): useProjectionQuery consumes ProtocolSnapshotSource […
clone45 Apr 19, 2026
4bb87b8
feat(hint): starter widget_type -> category preference heuristic [OMN…
clone45 Apr 19, 2026
b5ba39a
feat(registry): scan node_modules/@omninode/* for dashboardComponents…
clone45 Apr 19, 2026
3c92a01
feat(layout): file-based layout persistence [OMN-32] (#11)
clone45 Apr 19, 2026
aeb7915
feat(config): per-component config panel via @rjsf [OMN-33] (#12)
clone45 Apr 19, 2026
43888b8
test(proof-of-life): scripted end-to-end verification + pipeline sani…
clone45 Apr 19, 2026
99e1fb1
feat(header): New dashboard button with inline create form [OMN-38] (…
clone45 Apr 19, 2026
56f1788
fix(registry): call resolveImplementations() eagerly so built-ins sho…
clone45 Apr 19, 2026
2b3ce44
feat(fixtures): emit summary DTOs matching widget contracts; split sh…
clone45 Apr 20, 2026
ecd0957
fix(dashboard): Save button now persists layout via layoutPersistence…
clone45 Apr 20, 2026
721354f
feat(ui): install Tailwind + shadcn utilities + IBM Plex, port OKLCH …
clone45 Apr 20, 2026
66b51f8
feat(ui): rebuild Frame, Header, Sidebar, DashboardView (Phase 2) [OM…
clone45 Apr 20, 2026
ce1d16c
fix(ci): drop unused waitFor import in Sidebar.test.tsx [OMN-43] (#20)
clone45 Apr 20, 2026
0b5329e
feat(ui): verbatim CSS port of prototype; rewrite TSX to use semantic…
clone45 Apr 21, 2026
5ef4672
chore(audit): scaffold chunked UI fidelity audit folders + README + e…
clone45 Apr 21, 2026
bc9d4a2
chore(audit): generate remaining 38 chunk files across 6 components […
clone45 Apr 21, 2026
ba591ca
audit: claim widget-library-06 [OMN-48]
clone45 Apr 21, 2026
c624714
audit: complete widget-library-06 [OMN-48]
clone45 Apr 21, 2026
55faaa4
audit: complete widget-library-01 [OMN-48]
clone45 Apr 21, 2026
6af0bec
audit: complete widget-library-02 [OMN-48]
clone45 Apr 21, 2026
c118800
audit: complete widget-library-03 [OMN-48]
clone45 Apr 21, 2026
015b475
audit: complete widget-library-04 [OMN-48]
clone45 Apr 21, 2026
f2eed6a
audit: complete widget-library-05 [OMN-48]
clone45 Apr 21, 2026
befd649
audit: complete empty-state-01 [OMN-48]
clone45 Apr 21, 2026
4fd80b1
audit: complete empty-state-02 [OMN-48]
clone45 Apr 21, 2026
ae140ee
audit: complete empty-state-03 [OMN-48]
clone45 Apr 21, 2026
ba89289
audit: complete empty-state-04 [OMN-48]
clone45 Apr 21, 2026
acf9700
audit: complete empty-state-05 [OMN-48]
clone45 Apr 21, 2026
acfb923
audit: complete widget-card-01 [OMN-48]
clone45 Apr 21, 2026
c218787
audit: complete widget-card-02 [OMN-48]
clone45 Apr 21, 2026
c060bf8
audit: complete widget-card-03 [OMN-48]
clone45 Apr 21, 2026
7ac8786
audit: complete widget-card-04 [OMN-48]
clone45 Apr 21, 2026
5d118ba
audit: complete topbar-01 [OMN-48]
clone45 Apr 21, 2026
0c09c2b
audit: complete topbar-02 [OMN-48]
clone45 Apr 21, 2026
09b8478
audit: complete topbar-03 [OMN-48]
clone45 Apr 21, 2026
3846019
audit: complete sidebar-01 [OMN-48]
clone45 Apr 21, 2026
c89aa0b
audit: complete sidebar-02 [OMN-48]
clone45 Apr 21, 2026
834b5fe
audit: complete sidebar-03 [OMN-48]
clone45 Apr 21, 2026
0053f12
audit: complete sidebar-04 [OMN-48]
clone45 Apr 21, 2026
895b35c
audit: complete sidebar-05 [OMN-48]
clone45 Apr 21, 2026
a167aea
audit: complete sidebar-06 [OMN-48]
clone45 Apr 21, 2026
4352180
audit: complete sidebar-07 [OMN-48]
clone45 Apr 21, 2026
ab93bfb
audit: complete sidebar-08 [OMN-48]
clone45 Apr 21, 2026
510e452
audit: complete sidebar-09 [OMN-48]
clone45 Apr 21, 2026
66cb7b4
audit: complete sidebar-10 [OMN-48]
clone45 Apr 21, 2026
4207e0c
audit: complete dashboard-01 [OMN-48]
clone45 Apr 21, 2026
41ec74a
audit: complete dashboard-02 [OMN-48]
clone45 Apr 21, 2026
5a62720
audit: complete dashboard-03 [OMN-48]
clone45 Apr 21, 2026
40f5ae0
audit: complete dashboard-04 [OMN-48]
clone45 Apr 21, 2026
25a288a
audit: complete dashboard-05 [OMN-48]
clone45 Apr 21, 2026
8f2bbf7
audit: complete dashboard-06 [OMN-48]
clone45 Apr 21, 2026
99faf6d
audit: complete dashboard-07 [OMN-48]
clone45 Apr 21, 2026
c4c3e4f
audit: complete dashboard-08 [OMN-48]
clone45 Apr 21, 2026
719d411
audit: complete dashboard-09 [OMN-48]
clone45 Apr 21, 2026
047dbb1
audit: complete dashboard-10 [OMN-48]
clone45 Apr 21, 2026
3977af3
audit: complete dashboard-11 [OMN-48]
clone45 Apr 21, 2026
4145b96
feat(ui): port EmptyState + WidgetLibrary missing structure [OMN-48]
clone45 Apr 21, 2026
2902d69
audit: mark EmptyState + WidgetLibrary chunks done [OMN-48]
clone45 Apr 21, 2026
a3668f3
feat(ui): port dashboard header + meta row per prototype [OMN-48]
clone45 Apr 21, 2026
d408089
audit: mark dashboard header + meta chunks done [OMN-48]
clone45 Apr 21, 2026
31d988e
fix(ui): gate widget Live badge on isLive prop [OMN-48]
clone45 Apr 21, 2026
dc583ed
audit: close drag-scope chunks (blocked on OMN-44) + live badge fix d…
clone45 Apr 21, 2026
d15bc4c
fix(ui): sidebar + topbar polish per audit [OMN-48]
clone45 Apr 21, 2026
0320a0c
audit: close remaining 17 chunks — 4 fixed, 13 accepted deviations [O…
clone45 Apr 21, 2026
326d6f3
fix(ui): widgets added via palette now persist + no longer hidden beh…
clone45 Apr 21, 2026
84cfbe4
docs: add OMN-22 UX polish plan (10 tickets OMN-49..OMN-58) [OMN-22]
clone45 Apr 21, 2026
c64ba6c
fix(ui): rename inputs are now readable and auto-select text [OMN-22]
clone45 Apr 21, 2026
d07defa
fix(ui): sidebar rename flow + remove workspace chip [OMN-22]
clone45 Apr 21, 2026
89d5d53
refactor(ui): remove widget count from dash-meta row [OMN-22]
clone45 Apr 21, 2026
e5fb461
refactor(ui): remove sidebar-foot status + version strings [OMN-22]
clone45 Apr 21, 2026
e32827c
refactor(ui): remove Header chrome without backing systems [OMN-22]
clone45 Apr 21, 2026
73a34f9
docs(checklist): mark tasks 20, 23, 24, 26, 27, 28 done [OMN-22]
clone45 Apr 21, 2026
7aafb68
feat(ui): library rail smooth transition + close on switch + Escape […
clone45 Apr 22, 2026
50e2758
fix(ui): explicit fixed height on CostTrend + QualityScore charts [OM…
clone45 Apr 22, 2026
f611868
fix(theme): expose mutedForeground; widgets no longer render text in …
clone45 Apr 22, 2026
270f17d
fix(layout): .main constrained to 100vh so content below fold is scro…
clone45 Apr 22, 2026
967cca1
fix(ui): DropdownMenuItem hover now visible; cursor shows pointer [OM…
clone45 Apr 22, 2026
534073c
fix(theme): ThemeProvider now drives both data-theme + .theme-* class…
clone45 Apr 22, 2026
c8991d1
refactor(ui): grid now uses CSS columns for masonry-style flow [OMN-22]
clone45 Apr 22, 2026
a03861d
feat(ui): widget kebab menu + flatten sub-card chrome + rename grid c…
clone45 Apr 22, 2026
ddfe74c
feat(ui): port prototype menu + modal patterns; drop shadcn dropdown/…
clone45 Apr 22, 2026
a96b589
fix(widgets): promote primary data labels to --ink + bump tiny label …
clone45 Apr 23, 2026
8835565
feat(theme): add --chart-* tokens + --status-* aliases on :root [OMN-22]
clone45 Apr 23, 2026
6ab4095
refactor(readiness): convert ReadinessGate from cards to table layout…
clone45 Apr 23, 2026
40e3b72
feat(grid): drag-and-drop reorder + palette-to-grid insert [OMN-22]
clone45 Apr 23, 2026
03b0fa8
docs(claude): rewrite widget-add recipe to match actual two-track mec…
clone45 Apr 23, 2026
7e8ed05
feat(cost-trend-3d): experimental Tron-style 3D cost visualization wi…
clone45 Apr 23, 2026
10f3c56
docs(checklist): mark polish items done [OMN-22]
clone45 Apr 23, 2026
4d197f3
feat(filters): global time range selector + stacked-area Cost Trend […
clone45 Apr 23, 2026
d91b1ef
fix(cost-trend): legend below chart + drop emphasis.focus to fix hove…
clone45 Apr 23, 2026
43a6f8f
feat(filters): custom start/end date range picker [OMN-22]
clone45 Apr 23, 2026
d5fd990
fix(range-picker): theming cascade + sensible default times [OMN-22]
clone45 Apr 23, 2026
e8eaafc
feat(cost-trend): replace ECharts with three.js 2D stacked-area chart…
clone45 Apr 23, 2026
3dce6c3
feat(cost-trend): chartType config — stacked area or stacked bar [OMN…
clone45 Apr 23, 2026
2bf96e0
fix(cost-trend): bar-mode cell-center x-mapping + suppress zero y-lab…
clone45 Apr 23, 2026
be8cabf
fix(routing-table): tighten narrow columns + shorter timestamp [OMN-22]
clone45 Apr 23, 2026
69560d5
feat(event-stream): search, sticky header, paused indicator, source p…
clone45 Apr 23, 2026
5ede9cc
feat(quality): three.js rewrite — pass-rate headline + tier-coloured …
clone45 Apr 23, 2026
fef849e
fix(quality): Tron-style bars + clearer mean marker [OMN-22]
clone45 Apr 23, 2026
14a89c6
fix(quality): theme-aware contrast for light mode [OMN-22]
clone45 Apr 23, 2026
38a970d
fix(quality): light-mode floor was black — explicit hex + new cssVarT…
clone45 Apr 23, 2026
5f9b20a
feat(cost-by-model): three.js pie widget — cost share per model [OMN-22]
clone45 Apr 24, 2026
329dd56
refactor(styles): unify font-family tokens — single source in :root […
clone45 Apr 24, 2026
b8e1b81
feat(dashboard): UX polish batch — solo, hover tint, header regroup, …
clone45 Apr 24, 2026
10e74ea
docs(plans): add typography system refactor plan [OMN-22]
clone45 Apr 24, 2026
7f18861
docs(plans): typography plan — add Known Types Inventory + R1-R10 rev…
clone45 Apr 24, 2026
300a2f2
docs(plans): restructure typography plan to ## Task N: format for pla…
clone45 Apr 24, 2026
e4c6a04
docs(plans): link typography plan to OMN-59 epic [OMN-59]
clone45 Apr 24, 2026
8e6c482
docs(plans): add epic_id frontmatter + per-task dependencies [OMN-59]
clone45 Apr 24, 2026
2ec8e30
test(typography): compliance scorecard baseline [OMN-60]
clone45 Apr 24, 2026
7d3d8df
docs(adr): establish typography system direction [OMN-61]
clone45 Apr 24, 2026
54645fd
docs(claude): add Typography conventions section [OMN-95]
clone45 Apr 24, 2026
06c33b4
docs(ux-polish): mark typography refactor in progress [OMN-97]
clone45 Apr 24, 2026
4f2128f
feat(styles): add typography type-scale + weight + leading + text-col…
clone45 Apr 24, 2026
1e5d002
fix(typography): clean tsc errors in compliance test file [OMN-60]
clone45 Apr 24, 2026
227538c
feat(typography): add token type definitions and CSS var maps [OMN-63]
clone45 Apr 24, 2026
423a7af
test(typography): add Text component tests (pre-implementation) [OMN-64]
clone45 Apr 24, 2026
a0e21c0
test(typography): add Heading component tests (pre-implementation) [O…
clone45 Apr 24, 2026
8edffef
feat(typography): implement Heading component [OMN-67]
clone45 Apr 24, 2026
c473354
feat(typography): implement Text component [OMN-65]
clone45 Apr 24, 2026
8888f94
feat(typography): add barrel export [OMN-68]
clone45 Apr 24, 2026
8d13d3d
refactor(typography): migrate CostTrendPanel to <Text> [OMN-77]
clone45 Apr 24, 2026
7950aa2
refactor(typography): migrate CostByModelPie to <Text> [OMN-79]
clone45 Apr 24, 2026
9ec2555
refactor(typography): migrate DelegationMetrics to <Text> [OMN-81]
clone45 Apr 24, 2026
322f9e9
refactor(typography): migrate QualityScorePanel to <Text>/<Heading> […
clone45 Apr 24, 2026
1bda6ab
refactor(typography): migrate CostTrend3D HTML overlays to <Text> [OM…
clone45 Apr 24, 2026
f2681d8
feat(styles): add .text-tracked + .text-input-* utility classes [OMN-59]
clone45 Apr 24, 2026
4f79ba8
docs(typography): README with usage examples [OMN-96]
clone45 Apr 24, 2026
2789029
refactor(typography): migrate TimezoneSelector to <Text> [OMN-86]
clone45 Apr 24, 2026
6033f9f
refactor(typography): migrate AutoRefreshSelector to <Text> [OMN-87]
clone45 Apr 24, 2026
c3da136
refactor(typography): migrate ReadinessGate to <Text> [OMN-83]
clone45 Apr 24, 2026
e3faa0c
refactor(typography): migrate BaselinesRoiCard to <Text> [OMN-82]
clone45 Apr 24, 2026
09fdaab
refactor(typography): DateRangeSelector already clean [OMN-85]
clone45 Apr 24, 2026
d57715e
refactor(typography): migrate ComponentWrapper to <Text>/<Heading> [O…
clone45 Apr 24, 2026
4c81870
refactor(typography): migrate ComponentPalette to <Text> [OMN-90]
clone45 Apr 24, 2026
680962b
refactor(typography): migrate RoutingDecisionTable to <Text> [OMN-75]
clone45 Apr 24, 2026
205a890
refactor(typography): migrate EventStream to <Text> [OMN-76]
clone45 Apr 24, 2026
7f5f531
refactor(typography): migrate CustomRangePicker to <Text> [OMN-84]
clone45 Apr 24, 2026
aa1f69b
refactor(typography): migrate DashboardView header to <Text> [OMN-88]
clone45 Apr 24, 2026
c5b2290
refactor(typography): catch-all dashboard migration [OMN-91]
clone45 Apr 24, 2026
e7a1de2
feat(eslint): no-typography-inline custom rule [OMN-92]
clone45 Apr 24, 2026
51e7d6e
feat(eslint): wire no-typography-inline rule + lint script [OMN-93]
clone45 Apr 24, 2026
42c3370
ci(eslint): add lint job [OMN-94]
clone45 Apr 24, 2026
ce7c1c7
feat(typography): extend enforcement to chrome/agent/pages [OMN-99]
clone45 Apr 24, 2026
38587c4
chore(storybook): scaffold Storybook + theme/a11y addons [OMN-69]
clone45 Apr 24, 2026
cc0bf62
chore(storybook): configure main.ts for typography story path [OMN-70]
clone45 Apr 24, 2026
0c4a5fb
chore(storybook): configure preview with theme decorator [OMN-71]
clone45 Apr 24, 2026
527ff8a
docs(storybook): Heading levels story [OMN-73]
clone45 Apr 24, 2026
3f53959
docs(storybook): Typography showcase (10 stories) [OMN-72]
clone45 Apr 24, 2026
c391dda
ci(storybook): add Storybook build job [OMN-74]
clone45 Apr 24, 2026
7788a86
chore(typography): refactor complete — compliance is now a permanent …
clone45 Apr 24, 2026
9a29b43
docs(plans): add storybook widget coverage plan [OMN-100]
clone45 Apr 24, 2026
5b54fc9
docs(adr): storybook widget coverage decisions [OMN-102]
clone45 Apr 24, 2026
ca71fde
test(storybook): coverage scorecard baseline [OMN-101]
clone45 Apr 24, 2026
dd0a234
feat(storybook): foundation — decorator + fixtures + interface export…
clone45 Apr 24, 2026
b5a31d8
docs(storybook): CostTrendPanel stories [OMN-106]
clone45 Apr 24, 2026
1b11244
docs(storybook): CostByModelPie stories [OMN-108]
clone45 Apr 24, 2026
8b7f7af
docs(storybook): CostTrend3D stories [OMN-107]
clone45 Apr 24, 2026
6106d0e
docs(storybook): QualityScorePanel stories [OMN-109]
clone45 Apr 24, 2026
5115557
docs(storybook): DelegationMetrics stories [OMN-110]
clone45 Apr 24, 2026
ada62ff
docs(storybook): EventStream stories [OMN-105]
clone45 Apr 24, 2026
f689c7f
docs(storybook): RoutingDecisionTable stories [OMN-104]
clone45 Apr 24, 2026
d73898b
docs(storybook): BaselinesROICard stories [OMN-111]
clone45 Apr 24, 2026
f5e4828
docs(storybook): ReadinessGate stories [OMN-112]
clone45 Apr 24, 2026
9d10a9b
docs(storybook): ComponentWrapper stories [OMN-116]
clone45 Apr 24, 2026
7abe03d
docs(storybook): Selectors (TimezoneSelector + AutoRefreshSelector) s…
clone45 Apr 24, 2026
8de7370
docs(storybook): ComponentPalette stories [OMN-117]
clone45 Apr 24, 2026
be9d6fd
docs(storybook): DateRangeSelector stories [OMN-114]
clone45 Apr 24, 2026
7a39390
docs(storybook): CustomRangePicker stories [OMN-113]
clone45 Apr 24, 2026
ab51c90
chore(storybook): widget coverage complete — compliance is now a perm…
clone45 Apr 24, 2026
5654a3e
fix(storybook): dedupe react + trim addons + fix docgen scope [OMN-100]
clone45 Apr 24, 2026
911c0ee
fix(storybook): stop dark flash + cache-clobber in widget decorator […
clone45 Apr 24, 2026
0e7668c
chore(sidebar): remove non-functional Share link from dashboard kebab…
clone45 Apr 25, 2026
8e2505d
docs(storybook): app shell stories — Header / Sidebar / FrameLayout […
clone45 Apr 25, 2026
df5b11e
docs(storybook): ComponentConfigPanel stories [OMN-122]
clone45 Apr 25, 2026
1483f1c
merge: combine OMN-124 + OMN-120 + OMN-122 onto integration branch fo…
clone45 Apr 25, 2026
5b8aaae
docs(storybook): rename interaction story for Sidebar [OMN-121]
clone45 Apr 25, 2026
7340816
feat(sidebar): confirm dashboard delete in a dialog [OMN-127]
clone45 Apr 25, 2026
79dfe37
docs(storybook): AgentChat + AgentLauncher stories [OMN-119]
clone45 Apr 25, 2026
8e41aca
feat(refresh): wire dashboard-level auto-refresh interval [OMN-126]
clone45 Apr 25, 2026
129be42
feat(timezone): wire dashboard-level timezone selector [OMN-125]
clone45 Apr 25, 2026
8e7b5ff
feat(delegation): rebuild chart in three.js — tilted doughnut, 3D lea…
clone45 Apr 25, 2026
1c2f321
fix(delegation): spin doughnut flat around its own axis + vertical-sk…
clone45 Apr 25, 2026
b7241d0
merge: OMN-121
clone45 Apr 25, 2026
d3e66ed
merge: OMN-127
clone45 Apr 25, 2026
9ce531d
merge: OMN-119
clone45 Apr 25, 2026
068d793
merge: OMN-126
clone45 Apr 25, 2026
9b00d65
merge: OMN-125 (resolve conflicts in filters store + compliance test)
clone45 Apr 25, 2026
82f300a
merge: OMN-129
clone45 Apr 25, 2026
44185c9
style(delegation): darker labels in light mode + smaller font [OMN-129]
clone45 Apr 25, 2026
f8a69d0
merge: OMN-129 label tweaks (darker light-mode labels + smaller font)
clone45 Apr 25, 2026
a4b2089
feat(header): wire topbar Refresh button to invalidate queries [OMN-131]
clone45 Apr 25, 2026
03e13d0
merge: OMN-131 (Refresh button wired)
clone45 Apr 25, 2026
d980047
style(delegation): shrink 3D label font ~1/3 [OMN-129]
clone45 Apr 25, 2026
bcc0bdc
merge: OMN-129 label font shrink
clone45 Apr 25, 2026
1a3b23d
fix(delegation): label size constant on rotation [OMN-129]
clone45 Apr 25, 2026
675ae62
merge: OMN-129 constant-size labels
clone45 Apr 25, 2026
7d3aedf
style(delegation): halve label screen size [OMN-129]
clone45 Apr 25, 2026
92caaa4
merge: OMN-129 halve label size
clone45 Apr 25, 2026
0542e69
feat(refresh): live countdown on auto-refresh selector [OMN-126]
clone45 Apr 25, 2026
69d3bd0
merge: OMN-126 countdown
clone45 Apr 25, 2026
d197144
fix(delegation): swap canvas-texture sprites for CSS2DRenderer DOM la…
clone45 Apr 25, 2026
cee4c88
merge: OMN-129 CSS2DRenderer DOM labels
clone45 Apr 25, 2026
caf9648
refactor(palette): regroup widgets by domain instead of chart shape
clone45 Apr 25, 2026
ef72b04
fix(storybook): cost-trend-panel mock should be 'cost', not 'quality'
clone45 Apr 25, 2026
05cdc99
fix(widget): pin LIVE indicator next to the kebab on the right
clone45 Apr 25, 2026
12fce68
fix(theme): dark scrollbars + native UI via color-scheme
clone45 Apr 25, 2026
b911b6d
fix(registry): move component-registry.json out of public/ to silence…
clone45 Apr 25, 2026
fd92b78
docs: widget configuration audit — schema vs. wiring vs. recommendations
clone45 Apr 25, 2026
2f1edcc
fix(config): apply widget-config audit — bug fixes + hide empty modals
clone45 Apr 25, 2026
af55e15
fix(routing): coerce config.pageSize to number — RJSF select returns …
clone45 Apr 25, 2026
c80506c
feat(dashboard): single-column layout below 720px viewport width
clone45 Apr 25, 2026
ca7c3fe
fix(dashboard): account for 240px sidebar in single-column breakpoint
clone45 Apr 25, 2026
7bc32d0
feat(sidebar): collapsible left rail with click-to-switch in compact …
clone45 Apr 25, 2026
ab812e5
docs: requirements compliance audit against 04-17 spec + engagement r…
clone45 Apr 25, 2026
2dada15
fix(tests): four regressions surfaced by client review pass
clone45 Apr 25, 2026
859e47a
chore(brand): OmniDash title + favicon using the brand-mark SVG
clone45 Apr 25, 2026
9a14197
fix(env): stop bleeding env-specific literals into the source tree [O…
clone45 Apr 25, 2026
f3e85a0
fix(quality): capability/test honesty pass [OMN-148..154]
clone45 Apr 25, 2026
18a7651
refactor(arch): truth-ownership pass — service-led writes, source via…
clone45 Apr 25, 2026
7a0beb3
feat(widgets): 2D companions + threshold config + cleanup bundle [OMN…
clone45 Apr 25, 2026
6c2a9c6
fix: bundle 1 — small mechanical leftovers (M4, M16, LOW.6, LOW.8)
clone45 Apr 26, 2026
f0260ab
test+fix: bundle 2 — test discipline pass (M8, M9, M14, M1)
clone45 Apr 26, 2026
e0cb96f
fix(ux): bundle 3 — UI/UX polish (H5, H16, LOW.1, LOW.7)
clone45 Apr 26, 2026
3a4136f
build(lint): bundle 4 — ESLint 9 + flat config + cluster-B rule (M12,…
clone45 Apr 26, 2026
10b699a
test+lint: bundle 5 — final pass (M17, LOW.4, §8.B)
clone45 Apr 26, 2026
37a0345
fix(ci): pin @eslint/js to 9.x — npm ci was rejecting the 10.x peer m…
clone45 Apr 26, 2026
14fc659
docs(review): refresh response doc to reflect bundles 1-5
clone45 Apr 26, 2026
23514c7
ci(OMN-9845): adapt golden-chain-coverage for v2 layout
jonahgabriel Apr 26, 2026
cfe69f0
ci(OMN-9845): align node-version to 20.x matching ci.yml
jonahgabriel Apr 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 55 additions & 10 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,58 @@
# Part 4: AI Assistant Configuration
# omnidash-v2 environment configuration template.
# Copy to `.env` and fill in values for your environment.
# Do NOT commit `.env` — it is ignored by .gitignore.

# LLM backend host only — no /v1 suffix (the client appends /v1 itself)
# Change to http://192.168.86.201:8001 to use DeepSeek-R1-14B fallback
VITE_LLM_BASE_URL=http://192.168.86.201:8000
VITE_LLM_MODEL=qwen3-coder-30b-awq
VITE_LLM_API_KEY=not-needed
# ---------------------------------------------------------------------------
# Frontend (Vite — VITE_* vars are exposed to the browser)
# ---------------------------------------------------------------------------

# Set to "false" to disable the AI assistant entirely (hides the button + panel)
VITE_AGENT_ENABLED=true
# Data source mode. `file` reads from ./fixtures/ (default in dev, zero infra).
# `http` reads via the Express bridge declared by VITE_HTTP_DATA_SOURCE_URL.
# VITE_DATA_SOURCE=file

# Part 1: API backend (omnidash v1 server)
VITE_API_BASE=http://localhost:3000
# HTTP data-source URL. Required when VITE_DATA_SOURCE=http.
# VITE_HTTP_DATA_SOURCE_URL=http://localhost:3002

# WebSocket invalidation channel. Required when running with the Express bridge.
# Mirrors VITE_HTTP_DATA_SOURCE_URL but with the ws:// or wss:// scheme.
# VITE_WS_URL=ws://localhost:3002/ws

# Optional override for the Vite dev server port (default 3001).
# VITE_DEV_PORT=3001

# ---------------------------------------------------------------------------
# Frontend — AI Assistant
# ---------------------------------------------------------------------------

# Master toggle. Set to "false" to hide the assistant button + panel entirely.
# VITE_AGENT_ENABLED=true

# LLM backend host (no /v1 suffix; the client appends it).
# Required for production builds; in dev the Vite proxy stands in for it
# only if this is set. Leave unset to disable the proxy in dev.
# VITE_LLM_BASE_URL=http://your-llm-host:8000
# VITE_LLM_MODEL=qwen3-coder-30b-awq
# VITE_LLM_API_KEY=not-needed

# Optional fallback LLM (only consulted when callers pass useFallback=true).
# VITE_LLM_FALLBACK_URL=http://your-llm-fallback-host:8001
# VITE_LLM_FALLBACK_MODEL=deepseek-r1-14b-awq
# VITE_LLM_FALLBACK_API_KEY=not-needed

# ---------------------------------------------------------------------------
# Server (Express bridge — server/index.ts)
# ---------------------------------------------------------------------------

# Postgres connection string for the analytics DB. REQUIRED — server fails
# fast at startup if this is unset.
# OMNIDASH_ANALYTICS_DB_URL=postgresql://user:password@host:5432/omnidash_analytics

# ---------------------------------------------------------------------------
# Build-time scripts
# ---------------------------------------------------------------------------

# Path to a checkout of omnibase_core. REQUIRED for `npm run types:generate`.
# OMNIBASE_CORE_PATH=/path/to/omnibase_core

# Path to a checkout of omnibase_infra. REQUIRED for `npm run generate:fixtures`.
# OMNIBASE_INFRA_PATH=/path/to/omnibase_infra
27 changes: 24 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,31 @@ jobs:
- name: Install dependencies
run: npm ci

- name: TypeScript typecheck
- name: Env-contamination gate
run: bash scripts/check-no-env-contamination.sh

- name: TypeScript typecheck (frontend)
run: npx tsc --noEmit

- name: Run tests
run: npx vitest run
- name: TypeScript typecheck (server / vite config)
run: npm run build:server

- name: Lint
run: npm run lint

- name: Run tests with coverage
run: npm run test:coverage
env:
CI: true

- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
if-no-files-found: ignore
retention-days: 14

- name: Build Storybook
run: npx storybook build -o storybook-static
66 changes: 66 additions & 0 deletions .github/workflows/golden-chain-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# .github/workflows/golden-chain-coverage.yml
# Golden Chain Coverage Gate (OMN-9845)
#
# Adapted from omnidash v1 (OMN-7495).
# v2 path changes:
# - v1 watched: server/consumers/read-model/** (Kafka read-model consumer dir)
# - v2 watches: src/data-source/** (snapshot projection sources) + shared/types/topics.ts
#
# Always produces a `golden-chain` check status (required by branch protection).
# Skips the heavy test run when no projection-related files changed.
name: Golden Chain Coverage Gate

on:
pull_request:
merge_group:
push:
branches: [main]

jobs:
golden-chain:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Check for projection-related changes
id: changes
run: |
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "merge_group" ]; then
echo "run_tests=true" >> "$GITHUB_OUTPUT"
exit 0
fi
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
CHANGED=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- \
'src/data-source/**' \
'shared/types/topics.ts' \
'server/__tests__/golden-chain/**' \
)
if [ -n "$CHANGED" ]; then
echo "run_tests=true" >> "$GITHUB_OUTPUT"
echo "Projection files changed — running golden chain tests"
else
echo "run_tests=false" >> "$GITHUB_OUTPUT"
echo "No projection files changed — skipping tests"
fi

- uses: actions/setup-node@v4
if: steps.changes.outputs.run_tests == 'true'
with:
node-version: '20.x'
cache: 'npm'

- run: npm ci
if: steps.changes.outputs.run_tests == 'true'

- name: Run golden projection tests (unit mode)
if: steps.changes.outputs.run_tests == 'true'
run: npx vitest run server/__tests__/golden-chain/ --reporter=verbose
env:
GOLDEN_MODE: unit

- name: Verify projection coverage gate
if: steps.changes.outputs.run_tests == 'true'
run: npx vitest run server/__tests__/golden-chain/coverage-gate.test.ts --reporter=verbose
28 changes: 28 additions & 0 deletions .gitignore
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,31 @@ node_modules/
dist/
.vite/
*.local
fixtures/
# Storybook fixture builders are part of the source tree (OMN-103).
!src/storybook/fixtures/
!src/storybook/fixtures/**
build/
dashboard-layouts/

# Skill-result artifacts (local runs; not for repo)
.onex_state/

# Stray compiled JS from .ts sources (pre-existing, should not be in repo)
src/**/*.js
src/**/*.test.js
shared/**/*.js
shared/**/*.test.js

# Prototype design files — captured locally, large, not committed.
# reference/README.md is tracked as a breadcrumb to where the files came from.
reference/claude-design/

*storybook.log
storybook-static

# tsc --build / project references — intermediate cache files
*.tsbuildinfo

# vitest coverage output — generated by `npm run test:coverage`
coverage/
54 changes: 54 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(ts|tsx|mdx)'],
addons: [
// Trimmed addon list for cold-start performance. Re-add anything
// below when actually used.
// '@chromatic-com/storybook' — visual regression service. Not used.
// '@storybook/addon-vitest' — Storybook test runner integration. We
// use vitest directly; the addon's
// manager-side UniversalStore bootstrap
// throws on every Storybook boot
// without a "leader" test runner.
// '@storybook/addon-onboarding' — welcome tour for new Storybook users.
// '@storybook/addon-docs' — MDX docs framework. We use plain TSX
// stories; not authoring MDX.
'@storybook/addon-a11y',
'@storybook/addon-themes',
],
framework: { name: '@storybook/react-vite', options: {} },
// Switched from `react-docgen-typescript` (uses full TS program — accurate
// but very slow on cold start, the single biggest contributor to startup
// time when stories include heavy widgets like CostTrend3D / CostByModelPie)
// to `react-docgen` (regex/AST-based, ~10× faster). Prop tables in the
// Controls panel will be slightly less detailed but still functional.
// To regain the richer prop typing later, reverse this flag.
typescript: { reactDocgen: 'react-docgen' },
// Dedupe react / react-dom so libraries that bring their own peer-dep
// resolution (echarts-for-react, @tanstack/react-query, three drei, etc.)
// share the host iframe's React instance. Without this, hook calls inside
// those libraries hit "resolveDispatcher() is null / cannot read property
// useMemo" because Vite's dependency optimizer materialized two React
// copies. Also pre-bundle the chart libraries + react-query explicitly so
// Vite resolves their React references against the deduped copy at
// optimize time, which dramatically improves cold-load performance.
viteFinal: async (config) => {
config.resolve = config.resolve ?? {};
config.resolve.dedupe = Array.from(
new Set([...(config.resolve.dedupe ?? []), 'react', 'react-dom']),
);
config.optimizeDeps = config.optimizeDeps ?? {};
config.optimizeDeps.include = Array.from(
new Set([
...(config.optimizeDeps.include ?? []),
'echarts-for-react',
'echarts',
'@tanstack/react-query',
'three',
]),
);
return config;
},
};
export default config;
35 changes: 35 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Preview } from '@storybook/react-vite';
import { withThemeByDataAttribute } from '@storybook/addon-themes';
import '../src/styles/globals.css';

// Per OMN-103 (plan amendment to OMN-100 Task 3): the dashboard
// decorator `makeDashboardDecorator` from
// `src/storybook/decorators/withDashboardContext.tsx` is applied
// **explicitly per-story** rather than wired here in the global
// `decorators` array. Storybook composes (does not replace) decorator
// stacks, so a global default would double the QueryClient + ThemeProvider
// context for every widget story that supplies its own. See ADR
// `docs/adr/002-storybook-widget-coverage.md` for context.

const preview: Preview = {
parameters: {
backgrounds: { disable: true },
controls: { matchers: { color: /(background|color)$/i } },
a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: 'todo',
},
},
decorators: [
withThemeByDataAttribute({
themes: { Light: 'light', Dark: 'dark' },
defaultTheme: 'Light',
attributeName: 'data-theme',
parentSelector: 'html',
}),
],
};

export default preview;
93 changes: 93 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
## Local dev mode (no infra)

This repo runs in two modes:
- `VITE_DATA_SOURCE=file` (default in dev) — reads snapshots from `./fixtures/`, persists layouts to `./dashboard-layouts/`. Zero infra required.
- `VITE_DATA_SOURCE=http` — reads via `http://localhost:3002` Express bridge. Used only when we have a running Express server.

### Hard rules

1. **Do NOT hardcode** `localhost:3002` anywhere. All data access goes through `src/data-source/` — either `FileSnapshotSource` or `HttpSnapshotSource`, selected by `VITE_DATA_SOURCE`.
2. **Do NOT hand-edit** `src/registry/component-registry.json`. Run `npm run generate:registry`.
3. **Do NOT hand-edit** anything under `src/shared/types/generated/`. Run `npm run types:generate`.
4. **Do NOT edit** any file under `node_modules/`. Components discovered there are read-only.
5. **Fixtures and layouts are not committed.** They live under `./fixtures/` and `./dashboard-layouts/`, both gitignored.

### Common tasks

**Regenerate everything from scratch:**
```bash
npm run types:generate
npm run generate:fixtures
npm run generate:projection-registry
npm run generate:registry
npm run dev
```

**Add a new widget (two tracks — pick one):**

_Track A — local MVP widget (the seven current widgets use this path):_
1. Create `src/components/dashboard/<name>/<Name>.tsx`. Default-export a React component that accepts a `config` prop shaped per its manifest.
2. Register the lazy import in `src/components/dashboard/index.ts` under its `implementationKey` (e.g. `'<name>/<Name>': lazy(() => import('./<name>/<Name>'))`).
3. Add the manifest entry to the `MVP_COMPONENTS` object in `scripts/generate-registry.ts`. This is the canonical MVP manifest location — there is no per-widget `manifest.ts` file for local widgets.
4. Run `npm run generate:registry` to rewrite `src/registry/component-registry.json`.
5. Restart dev server.

_Track B — external package widget (plugin extension path):_
1. Publish an `@omninode/*` npm package containing your widget component plus a JSON manifest file listing one or more `ComponentManifest` entries.
2. Reference the manifest path in the package's `package.json` via `"dashboardComponents": "./path/to/manifests.json"`.
3. `npm install` the package into omnidash-v2.
4. Run `npm run generate:registry` — the script auto-scans `node_modules/@omninode/*` and merges discovered manifests into the registry.
5. Dynamic code loading for external packages is a future phase; for now they surface in the palette with `status: 'not_implemented'` unless their `implementationKey` also appears in the local `componentImports` map.

**Add a new data source adapter:**
1. Create `src/data-source/<name>-snapshot-source.ts` implementing `ProtocolSnapshotSource`.
2. Register it in `src/data-source/index.ts` under its `VITE_DATA_SOURCE` key.
3. Add a test in `src/data-source/<name>-snapshot-source.test.ts`.

### Gotchas

- Edit mode toggle is in the Zustand `editModeSlice`. Drag and resize are ONLY enabled when edit mode is active.
- When you move a widget on the canvas, save the layout explicitly (`Save` button) — it does NOT auto-persist per drag.
- If the palette is empty, your `src/registry/component-registry.json` is likely out of date. Run `npm run generate:registry`.
- If widgets render but show "no data", check `./fixtures/<topic>/` has JSON files and `./fixtures/registry.json` lists the topic.

### Where to look

- Data fetching: `src/data-source/`
- Grid behavior: `src/components/dashboard/DashboardGrid.tsx`
- Palette: `src/components/dashboard/ComponentPalette.tsx`
- Edit/view toggle: `src/store/editModeSlice.ts`, `src/pages/DashboardBuilder.tsx`
- Layout persistence: `src/layout/layout-persistence.ts`
- Widget lazy-import map: `src/components/dashboard/index.ts`
- Widget MVP manifests: `scripts/generate-registry.ts` (`MVP_COMPONENTS`)
- External package manifest discovery: `scripts/generate-registry.ts` → `scanInstalledPackages()`

## Typography

- All text in widgets must be rendered via `<Text>` or `<Heading>` from
`@/components/ui/typography`. Do not set `fontSize`, `fontFamily`,
`fontWeight`, text `color`, `textTransform`, or `letterSpacing` in
inline `style` props — enforced by the local ESLint rule
`local/no-typography-inline`.
- Tokens live in `src/styles/globals.css :root`. See
`docs/adr/001-typography-system.md` for rationale.
- Showcase: `npm run storybook` → Typography pages.

## Storybook conventions

- New stories live alongside their component as `<Name>.stories.tsx`
(e.g. `src/components/dashboard/quality/QualityScorePanel.stories.tsx`).
- Any widget that calls `useProjectionQuery` must wrap its stories with
`makeDashboardDecorator(...)` from
`@/storybook/decorators/withDashboardContext` so the projection client
is seeded with deterministic fixture data.
- Fixtures live under `src/storybook/fixtures/` and are exported via
`src/storybook/fixtures/index.ts`. Extend existing fixtures rather
than duplicating — every story should compose from the shared barrel.
- Each widget must expose at minimum `Empty` and `Populated` story
exports. State-specific variants (`Loading`, `Error`,
`HighDisagreement`, `BalancedSplit`, etc.) are encouraged where
meaningful. The compliance scorecard
`src/storybook-coverage-compliance.test.ts` enforces this contract on
every `npm test`. See `docs/adr/002-storybook-widget-coverage.md` for
rationale.
Loading
Loading