Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .kb-doc-gate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ mode: strict
# out of the repo root by OMN-16602
#
# Deliberately absent: any `docs/**` escape hatch. Platform documentation for
# this repo lives in OmniNode-ai/knowledge-base (public) and
# this repo lives in OmniNode-ai/knowledge_base (public) and
# OmniNode-ai/knowledge-base-internal (operational runbooks).
2 changes: 1 addition & 1 deletion .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import '../src/styles/globals.css';
// `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
// https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md for context.
// https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md for context.

const preview: Preview = {
parameters: {
Expand Down
12 changes: 6 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
> Shared standards: `~/.claude/CLAUDE.md`. Worktrees, PR/CI gates, merge policy, repo registry: `omni_home/CLAUDE.md`. This file is omnidash-specific. Full dev guide (setup, commands, widget tracks, Storybook, key source locations): [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge-base/blob/main/guides/omnidash-development.md).
> Shared standards: `~/.claude/CLAUDE.md`. Worktrees, PR/CI gates, merge policy, repo registry: `omni_home/CLAUDE.md`. This file is omnidash-specific. Full dev guide (setup, commands, widget tracks, Storybook, key source locations): [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge_base/blob/main/guides/omnidash-development.md).

## What this is

Composable widget dashboard — Vite + React, services-led. Components render authoritative data; they never create it ([doctrine](https://github.com/OmniNode-ai/omni_home/blob/main/docs/standards/OMNINODE_DETERMINISTIC_TRUTH_DOCTRINE.md)). Component-local truth contract: [Dashboard Component Truth Boundary](https://github.com/OmniNode-ai/knowledge-base/blob/main/architecture/omnidash-component-truth-boundary.md).
Composable widget dashboard — Vite + React, services-led. Components render authoritative data; they never create it ([doctrine](https://github.com/OmniNode-ai/omni_home/blob/main/docs/standards/OMNINODE_DETERMINISTIC_TRUTH_DOCTRINE.md)). Component-local truth contract: [Dashboard Component Truth Boundary](https://github.com/OmniNode-ai/knowledge_base/blob/main/architecture/omnidash-component-truth-boundary.md).

## Deployed instance is NOT this app (forensic readback 2026-07-02 — re-verify before deploy work)

Expand All @@ -19,13 +19,13 @@ The base contract deliberately carries NO backend URL — unconfigured `http` mo
1. Never hardcode a backend URL/port. All data access goes through `src/data-source/` (`FileSnapshotSource`/`HttpSnapshotSource`, selected by `resolveEffectiveDataSource()`).
2. Never read `VITE_DATA_SOURCE` directly in components — always `resolveEffectiveDataSource()` from `src/data-source/data-source-override.ts`, the single runtime-override seam (written by the `DataSourceControl` chrome).
3. `/api/` path literals belong only in `src/services/` or `src/data-source/`. NOTE: source comments cite a `local/no-api-literal` ESLint rule — no such rule exists at HEAD (checked 2026-07-26); the seam is convention. The live local rule set is in `eslint.config.js`.
4. Components must not own truth: no backend/event-bus clients, no reducers, no inferred authoritative state. Contract: [Dashboard Component Truth Boundary](https://github.com/OmniNode-ai/knowledge-base/blob/main/architecture/omnidash-component-truth-boundary.md).
4. Components must not own truth: no backend/event-bus clients, no reducers, no inferred authoritative state. Contract: [Dashboard Component Truth Boundary](https://github.com/OmniNode-ai/knowledge_base/blob/main/architecture/omnidash-component-truth-boundary.md).
5. Never hand-edit generated artifacts: `src/registry/component-registry.json` (`npm run generate:registry`) and `src/shared/types/generated/` (`npm run types:generate`).
6. `./fixtures/` IS committed (`.gitignore` carve-out `!fixtures/**`); `./dashboard-layouts/` is not.

## Widgets

Two tracks — local widget (lazy import in `src/components/dashboard/index.ts` + manifest entry in `MVP_COMPONENTS` in `scripts/generate-registry.ts`; there are no per-widget manifest files) or external `@omninode/*` package (`"dashboardComponents"` key in its package.json, auto-scanned by `generate:registry`; palette-visible but `not_implemented` until its `implementationKey` is also in the local `componentImports` map). Steps: [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge-base/blob/main/guides/omnidash-development.md) §Adding a New Widget. New data-source adapters implement `ProtocolSnapshotSource` and register in `src/data-source/index.ts`.
Two tracks — local widget (lazy import in `src/components/dashboard/index.ts` + manifest entry in `MVP_COMPONENTS` in `scripts/generate-registry.ts`; there are no per-widget manifest files) or external `@omninode/*` package (`"dashboardComponents"` key in its package.json, auto-scanned by `generate:registry`; palette-visible but `not_implemented` until its `implementationKey` is also in the local `componentImports` map). Steps: [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge_base/blob/main/guides/omnidash-development.md) §Adding a New Widget. New data-source adapters implement `ProtocolSnapshotSource` and register in `src/data-source/index.ts`.

## Gotchas

Expand All @@ -35,6 +35,6 @@ Two tracks — local widget (lazy import in `src/components/dashboard/index.ts`

## Typography & Storybook

- All widget text via `<Text>`/`<Heading>` from `@/components/ui/typography`; no inline font/color/weight styles — enforced by `local/no-typography-inline` (rationale: [ADR-0039 — Dashboard Typography System](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0039-omnidash-typography-system.md); tokens: `src/styles/globals.css`).
- Every widget ships `Empty` + `Populated` stories alongside the component; widgets calling `useProjectionQuery` wrap stories in `makeDashboardDecorator(...)` from `@/storybook/decorators/withDashboardContext`. Enforced by `src/storybook-coverage-compliance.test.ts` on every `npm test` (rationale: [ADR-0040](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md)).
- All widget text via `<Text>`/`<Heading>` from `@/components/ui/typography`; no inline font/color/weight styles — enforced by `local/no-typography-inline` (rationale: [ADR-0039 — Dashboard Typography System](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0039-omnidash-typography-system.md); tokens: `src/styles/globals.css`).
- Every widget ships `Empty` + `Populated` stories alongside the component; widgets calling `useProjectionQuery` wrap stories in `makeDashboardDecorator(...)` from `@/storybook/decorators/withDashboardContext`. Enforced by `src/storybook-coverage-compliance.test.ts` on every `npm test` (rationale: [ADR-0040](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md)).
- Live updates are HTTP polling only — no WebSocket; raw WebSocket construction is blocked by `local/no-projection-websocket`.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,29 @@ OmniDash follows the [OmniNode deterministic truth doctrine](https://github.com/

| Knowledge base | Scope |
|---|---|
| **https://github.com/OmniNode-ai/knowledge-base** | Public — architecture, decision records, guides, schema references |
| **https://github.com/OmniNode-ai/knowledge_base** | Public — architecture, decision records, guides, schema references |

### Architecture and reference (public knowledge base)

| Topic | Canonical page |
|---|---|
| Architecture | [OmniDash Composable Frame Architecture](https://github.com/OmniNode-ai/knowledge-base/blob/main/architecture/omnidash-composable-frame.md) — the three-layer frame (frame / component registry / widgets) |
| Component truth boundary | [Dashboard Component Truth Boundary](https://github.com/OmniNode-ai/knowledge-base/blob/main/architecture/omnidash-component-truth-boundary.md) — read before adding or modifying a widget |
| Development guide | [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge-base/blob/main/guides/omnidash-development.md) — commands, data-source modes, registry generation, Storybook, widget directory layout |
| DashboardDefinition schema | [DashboardDefinition Schema](https://github.com/OmniNode-ai/knowledge-base/blob/main/reference/omnidash-dashboard-definition.md) |
| ComponentManifest schema | [ComponentManifest Schema](https://github.com/OmniNode-ai/knowledge-base/blob/main/reference/omnidash-component-manifest.md) |
| Typography primitives | [Typography Primitives — Text and Heading](https://github.com/OmniNode-ai/knowledge-base/blob/main/reference/omnidash-typography-primitives.md) |
| Implementation status | [OmniDash Implementation Status](https://github.com/OmniNode-ai/knowledge-base/blob/main/reference/omnidash-implementation-status.md) — Parts 1–4 breakdown |
| Architecture | [OmniDash Composable Frame Architecture](https://github.com/OmniNode-ai/knowledge_base/blob/main/architecture/omnidash-composable-frame.md) — the three-layer frame (frame / component registry / widgets) |
| Component truth boundary | [Dashboard Component Truth Boundary](https://github.com/OmniNode-ai/knowledge_base/blob/main/architecture/omnidash-component-truth-boundary.md) — read before adding or modifying a widget |
| Development guide | [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge_base/blob/main/guides/omnidash-development.md) — commands, data-source modes, registry generation, Storybook, widget directory layout |
| DashboardDefinition schema | [DashboardDefinition Schema](https://github.com/OmniNode-ai/knowledge_base/blob/main/reference/omnidash-dashboard-definition.md) |
| ComponentManifest schema | [ComponentManifest Schema](https://github.com/OmniNode-ai/knowledge_base/blob/main/reference/omnidash-component-manifest.md) |
| Typography primitives | [Typography Primitives — Text and Heading](https://github.com/OmniNode-ai/knowledge_base/blob/main/reference/omnidash-typography-primitives.md) |
| Implementation status | [OmniDash Implementation Status](https://github.com/OmniNode-ai/knowledge_base/blob/main/reference/omnidash-implementation-status.md) — Parts 1–4 breakdown |

### Decision records (public knowledge base)

| Decision | Canonical page |
|---|---|
| Dashboard typography system | [ADR-0039](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0039-omnidash-typography-system.md) |
| Storybook coverage for every dashboard widget | [ADR-0040](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md) |
| BaselinesROICard stays bespoke | [ADR-0041](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0041-omnidash-baselines-roi-card-stays-bespoke.md) |
| Cross-renderer typed empty-state gate | [ADR-0042](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0042-omnidash-cross-renderer-typed-empty-state-gate.md) |
| Stock @rjsf for Pydantic-generated JSON schema | [ADR-0043](https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0043-omnidash-rjsf-discriminated-union-handling.md) |
| Dashboard typography system | [ADR-0039](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0039-omnidash-typography-system.md) |
| Storybook coverage for every dashboard widget | [ADR-0040](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md) |
| BaselinesROICard stays bespoke | [ADR-0041](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0041-omnidash-baselines-roi-card-stays-bespoke.md) |
| Cross-renderer typed empty-state gate | [ADR-0042](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0042-omnidash-cross-renderer-typed-empty-state-gate.md) |
| Stock @rjsf for Pydantic-generated JSON schema | [ADR-0043](https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0043-omnidash-rjsf-discriminated-union-handling.md) |

Markdown that stays in this repo is limited to the GitHub-surface and agent-configuration set — this `README.md`, `CLAUDE.md`, `.claude/`, `CHANGELOG.md`, `SECURITY.md`, `LICENSE`, and `.github/` — enforced on every PR by the `kb-doc-gate` check in `strict` mode (see [`.kb-doc-gate.yaml`](.kb-doc-gate.yaml)).

Expand Down Expand Up @@ -106,7 +106,7 @@ VITE_DATA_SOURCE=file npm run dev
| `npm run types:generate` | Regenerate types under `src/shared/types/generated/` |
| `npm run storybook` | Storybook on port 6006 |

Adding a widget, the data-source modes, and the registry-generation workflow are covered in the [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge-base/blob/main/guides/omnidash-development.md).
Adding a widget, the data-source modes, and the registry-generation workflow are covered in the [OmniDash Development Guide](https://github.com/OmniNode-ai/knowledge_base/blob/main/guides/omnidash-development.md).

## Key Source Locations

Expand Down
2 changes: 1 addition & 1 deletion eslint-rules/no-typography-inline.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {
type: 'problem',
docs: { description: 'Disallow typographic CSS in JSX style props' },
messages: {
banned: 'Use <Text>/<Heading> instead of inline `style.{{ key }}`. See https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0039-omnidash-typography-system.md.',
banned: 'Use <Text>/<Heading> instead of inline `style.{{ key }}`. See https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0039-omnidash-typography-system.md.',
},
schema: [],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// branch. @rjsf 6.x reads discriminator.propertyName and uses const-matching
// to select the active branch without a custom widget.
//
// Findings documented in: https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0043-omnidash-rjsf-discriminated-union-handling.md
// Findings documented in: https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0043-omnidash-rjsf-discriminated-union-handling.md

import { useState, useCallback, type ChangeEvent } from 'react';
import Form, { type IChangeEvent } from '@rjsf/core';
Expand Down
2 changes: 1 addition & 1 deletion src/storybook/decorators/withDashboardContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface DashboardContextOptions {
* composes (does not replace) — wiring a default decorator globally
* would double the QueryClient + ThemeProvider context for every
* widget story that supplies its own. See ADR
* https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md for context.
* https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0040-omnidash-storybook-widget-coverage.md for context.
*/
export function makeDashboardDecorator(opts: DashboardContextOptions = {}): Decorator {
return (Story, context) => {
Expand Down
Loading