diff --git a/.kb-doc-gate.yaml b/.kb-doc-gate.yaml index 598679fb..b0e1cee5 100644 --- a/.kb-doc-gate.yaml +++ b/.kb-doc-gate.yaml @@ -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). diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 1d2fcfd6..53347096 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -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: { diff --git a/CLAUDE.md b/CLAUDE.md index c0dfecac..daa9d0b6 100755 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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) @@ -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 @@ -35,6 +35,6 @@ Two tracks — local widget (lazy import in `src/components/dashboard/index.ts` ## Typography & Storybook -- All widget text via ``/`` 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 ``/`` 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`. diff --git a/README.md b/README.md index f55baa47..5b696924 100644 --- a/README.md +++ b/README.md @@ -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)). @@ -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 diff --git a/eslint-rules/no-typography-inline.cjs b/eslint-rules/no-typography-inline.cjs index 1368717c..f96b928b 100644 --- a/eslint-rules/no-typography-inline.cjs +++ b/eslint-rules/no-typography-inline.cjs @@ -12,7 +12,7 @@ module.exports = { type: 'problem', docs: { description: 'Disallow typographic CSS in JSX style props' }, messages: { - banned: 'Use / instead of inline `style.{{ key }}`. See https://github.com/OmniNode-ai/knowledge-base/blob/main/adrs/ADR-0039-omnidash-typography-system.md.', + banned: 'Use / instead of inline `style.{{ key }}`. See https://github.com/OmniNode-ai/knowledge_base/blob/main/adrs/ADR-0039-omnidash-typography-system.md.', }, schema: [], }, diff --git a/src/components/dashboard/contract-inspector/ContractInspector.tsx b/src/components/dashboard/contract-inspector/ContractInspector.tsx index c659a8b2..d80e6bce 100644 --- a/src/components/dashboard/contract-inspector/ContractInspector.tsx +++ b/src/components/dashboard/contract-inspector/ContractInspector.tsx @@ -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'; diff --git a/src/storybook/decorators/withDashboardContext.tsx b/src/storybook/decorators/withDashboardContext.tsx index 41894059..acbf6b8f 100644 --- a/src/storybook/decorators/withDashboardContext.tsx +++ b/src/storybook/decorators/withDashboardContext.tsx @@ -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) => {