# Equilibrium Review (`equilibrium-01`) - SignalOS page block

> Full-page equilibrium definition review block. Displays AI-generated equilibrium definitions with metrics, weights, thresholds, and batch review tracking.

- **Version:** 0.5.0
- **Kind:** block (group: semantics-details) · **Category:** pages
- **Install:** `npx shadcn@latest add @signalos/equilibrium-01`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/badge, @signalos/input, @signalos/label, @signalos/select, @signalos/checkbox, @signalos/tooltip, @signalos/textarea, @signalos/split-panel, @signalos/command, @signalos/popover, @signalos/progress, @signalos/page-header, @signalos/dialog
- **npm dependencies:** lucide-react@^0.462.0
- **Files installed:** `src/components/blocks/equilibrium-01/Equilibrium.tsx`, `src/components/blocks/equilibrium-01/components/EquilibriumAddDialog.tsx`, `src/components/blocks/equilibrium-01/Equilibrium.types.ts`, `src/components/blocks/equilibrium-01/MetricInfoButton.tsx`, `src/components/blocks/equilibrium-01/components/EquilibriumDetail.tsx`, `src/components/blocks/equilibrium-01/components/EquilibriumReadView.tsx`, `src/components/blocks/equilibrium-01/components/EquilibriumEditView.tsx`, `src/components/blocks/equilibrium-01/components/EquilibriumQueue.tsx`, `src/components/blocks/equilibrium-01/components/AddDialogFormFields.tsx`, `src/components/blocks/equilibrium-01/components/MetricsWeightsSection.tsx`, `src/components/blocks/equilibrium-01/components/StateThresholdsSection.tsx`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
// after: npx shadcn@latest add @signalos/equilibrium-01
// mount the pulled page in a route, e.g. src/app/semantics-details/page.tsx
import Equilibrium from "@/components/blocks/equilibrium-01/Equilibrium"

export default function Page() {
  return <Equilibrium />
}
```

## Props

### `EquilibriumScoringMethod`

```ts
export type EquilibriumScoringMethod = "weighted_average" | "geometric_mean"
```

### `EquilibriumStateThresholds`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `STABLE` | `number` | yes | - |  |
| `DRIFTING` | `number` | yes | - |  |
| `INTERVENTION` | `number` | yes | - |  |
| `CRITICAL` | `number` | yes | - |  |

### `EquilibriumDefinition`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `equilibrium_id` | `string` | yes | - |  |
| `name` | `string` | yes | - |  |
| `description` | `string` | yes | - |  |
| `domain` | `string` | yes | - |  |
| `scoring_method` | `EquilibriumScoringMethod` | yes | - |  |
| `decay_rate` | `number` | yes | - |  |
| `healthy_range` | `[number, number]` | yes | - |  |
| `metrics` | `string[]` | yes | - |  |
| `weights` | `Record<string, number>` | yes | - |  |
| `confidence` | `number` | yes | - |  |
| `state_thresholds` | `EquilibriumStateThresholds` | yes | - |  |
| `review_origin` | `string \| null \| undefined` | no | - |  |

### `MetricDirection`

```ts
export type MetricDirection = "up_is_good" | "down_is_good" | "neutral"
```

### `MetricCatalogEntry`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `display_name` | `string \| null \| undefined` | no | - |  |
| `description` | `string \| null \| undefined` | no | - |  |
| `direction` | `MetricDirection \| null \| undefined` | no | - |  |
| `unit` | `string \| null \| undefined` | no | - |  |
| `connector_id` | `string \| null \| undefined` | no | - |  |
| `source_cluster` | `string \| null \| undefined` | no | - |  |
| `is_cross_source` | `boolean \| null \| undefined` | no | - |  |
| `source_entities` | `string[] \| null \| undefined` | no | - |  |
| `sql_logic` | `string \| null \| undefined` | no | - |  |

### `MetricCatalog`

```ts
export type MetricCatalog = Record<string, MetricCatalogEntry>
```

### `EquilibriaArtifact`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `definitions` | `EquilibriumDefinition[]` | yes | - |  |

### `EquilibriumReviewItem`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `index` | `number` | yes | - |  |
| `status` | `"accepted" \| "flagged" \| "deleted"` | yes | - |  |
| `feedback` | `string` | yes | - |  |
| `edits` | `Partial<Pick<EquilibriumDefinition, "name" \| "domain" \| "scoring_method" \| "decay_rate" \| "description" \| "healthy_range" \| "state_thresholds" \| "metrics" \| "weights" \| "confidence">>` | yes | - |  |
| `connector_id` | `string \| undefined` | no | - |  |
| `item_id` | `string \| undefined` | no | - |  |

### `SubmitEquilibriaReviewPayload`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `"confirm" \| "retry"` | yes | - |  |
| `items` | `EquilibriumReviewItem[] \| undefined` | no | - |  |

### `EquilibriumItemEdits`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `equilibrium_id` | `string \| undefined` | no | - |  |
| `name` | `string` | yes | - |  |
| `description` | `string` | yes | - |  |
| `domain` | `string` | yes | - |  |
| `scoring_method` | `EquilibriumScoringMethod` | yes | - |  |
| `decay_rate` | `number` | yes | - |  |
| `healthy_range` | `[number, number]` | yes | - |  |
| `state_thresholds` | `EquilibriumStateThresholds` | yes | - |  |
| `confidence` | `number` | yes | - |  |
| `metrics` | `string[]` | yes | - |  |
| `weights` | `Record<string, number>` | yes | - |  |

### `AddEquilibriumPayload`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `"add_item" \| "improve_new_item"` | yes | - |  |
| `feedback` | `string \| undefined` | no | - |  |
| `item_edits` | `EquilibriumItemEdits` | yes | - |  |
| `connector_id` | `string \| undefined` | no | - |  |

### `AddEquilibriumResponse`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `status` | `string \| undefined` | no | - |  |
| `item` | `EquilibriumDefinition \| undefined` | no | - |  |
| `soft_warning` | `string \| undefined` | no | - |  |

## Changelog

## 0.5.0

- Extract `AddDialogFormFields` into its own component file; split `StateThresholdsSection` and `MetricsWeightsSection` into dedicated subcomponents.
- Decompose `EquilibriumAddDialog`, `EquilibriumEditView`, `EquilibriumReadView`, `EquilibriumQueue`, and `EquilibriumDetail` into the `components/` folder.

## 0.4.10

- Replace raw scale token classes with semantic tokens (text-text-error, bg-bg-success, border-border-warning, etc.) to respect client theme overrides.

## 0.4.9

- Fix cross-item imports to use canonical @/components paths; add missing signalos.category to manifests.

## 0.4.8

- `Equilibrium`: remove `isSubmitting` prop and `metricPickerOpen`/`onMetricPickerChange` props (metric picker open state is now internal to `EquilibriumDetail`).
- `Equilibrium`: add `onAddFormValidationFail` callback prop; thread through to `EquilibriumAddDialog`.
- `Equilibrium`: move confirmed banner outside `PageHeader`, update border token to `border-border-success` and remove `CheckCircle2` icon.
- `Equilibrium`: rename confirm button `data-testid` from `equilibrium-confirm-button` to `equilibrium-submit-button`.
- `Equilibrium`: update header description copy.
- `EquilibriumAddDialog`: replace `FormDialog`+`TextField` with raw `Dialog`/`DialogContent`/`DialogHeader`/`DialogTitle`/`DialogDescription`/`DialogFooter` and `Label`+`Input`; add `onValidationFail` prop.
- `EquilibriumAddDialog`: move `MetricCatalogEntry` import from `metrics-01` to local `Equilibrium.types.ts`.
- `Equilibrium.types.ts`: define `MetricCatalog` and `MetricCatalogEntry` locally; remove import from `metrics-01`.
- Remove `@signalos/form-dialog` and `@signalos/text-field` from `registryDependencies`; add `@signalos/label`.

## 0.4.7

- Replace raw Dialog/DialogFooter with FormDialog in EquilibriumAddDialog; custom footer carries error banner + cancel/create buttons.
- Replace Label + Input with TextField for Name, Domain, Decay Rate, and Healthy Range fields; Description textarea keeps inline label + aria-invalid.
- Fix raw color tokens: text-destructive → text-text-error, bg-destructive/10 → bg-bg-error, border-destructive/30 → border-border-error throughout.
- Swap @signalos/dialog + @signalos/label → @signalos/form-dialog + @signalos/text-field; @signalos/input kept for compact inline weight/threshold rows.

## 0.4.5

- Fix removed statics buttons

## 0.4.4

- Fix file casing: rename Metrics.types.ts to match PascalCase import paths.

## 0.4.3

- Lift EquilibriumAddDialog form state (form, errors, metricPickerOpen) to props. Parent now owns all add-dialog state via addForm, addFormErrors, addMetricPickerOpen, onAddFormChange, onAddMetricPickerOpenChange.


## 0.3.1

- Replace desktop `lg:grid-cols-12` layout with `SplitPanel` widget for the queue/detail split.
- Mobile tab-switcher layout unchanged; `SplitPanel` is shown only on `lg:` and above.
- Add `@signalos/split-panel` to `registryDependencies`.

## 0.2.0

Initial release.
