@aiquants/enrichment-react 0.2.0 → 0.2.1

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/README.md CHANGED
@@ -22,7 +22,7 @@ pnpm add @aiquants/enrichment-react @aiquants/enrichment-core @aiquants/console-
22
22
  - **Rendered inside the console root.** `InfrastructureHealthMonitor`, `PipelineFlowViewer`, `PipelineRunInspector`, `QdrantStorageCard`, `SyncStatusMonitor`, `DocumentIngestConsole`, and the instant slots `RecordedInstant` and `FinishedInstant` read `@aiquants/console-ui`'s `ConsoleUiRoot` and throw outside it. The other components do not read the root and render anywhere.
23
23
  Every component that reads the root checks it before drawing anything (the root requirement below), so none of them reads the root, draws the root's label or writes in the root's zone under a root it was not written for.
24
24
  This package ships no stylesheet (the host's Tailwind build compiles its classes), and the host loads `@aiquants/console-ui/styles/console-ui.css` once, with its `cui` cascade layer ranked above the host's reset, as `@aiquants/console-ui`'s README describes under "Loading the stylesheet" (for a Tailwind v4 host, `@import` it in the CSS entry after the layer statement `@layer theme, base, components, utilities;`).
25
- Without it the root's `--cui-*` token variables are unset, a `Measured` count loses its tabular figures, `QdrantStorageCard`'s name buttons (`@aiquants/console-ui`'s `RowButton`) are drawn as the browser's plain buttons without the selected look, and the root's live region (`role="status"`) is drawn in the flow of the page instead of being visually hidden.
25
+ Without it the root's `--cui-*` token variables are unset, a `Measured` count loses its tabular figures, `QdrantStorageCard`'s name buttons (`@aiquants/console-ui`'s `RowButton`) are drawn as the browser's plain buttons without the selected look, `InfrastructureHealthMonitor`'s probe-state marks and `QdrantStorageCard`'s health badge lose their role colours (`success-fg` / `danger-fg` and their tints), and the root's live region (`role="status"`) is drawn in the flow of the page instead of being visually hidden.
26
26
  The package publishes only `dist`, and Tailwind v4's automatic source detection skips `node_modules`, so a Tailwind v4 host also adds `@source "../node_modules/@aiquants/enrichment-react/dist/**/*.js";` to its CSS entry (the path is relative to that file; inside this monorepo, point `@source` at `packages/enrichment-react/src/**/*.{ts,tsx}` instead).
27
27
  Without that line the host generates none of the components' Tailwind utilities (layout, spacing, colours, borders), so none of the colour pairs under **Colour Contrast** is drawn. A host without Tailwind is not supported.
28
28
  The root must be `locale="ja"` and `formatLocale="ja-JP"`: the package's own text is Japanese and its instants are written in `ja-JP` (`RecordedInstant`), so under any other root the root's words and digit grouping would sit inside Japanese sentences beside `ja-JP` times. Every component that reads the root throws `RangeError`, naming the root's `locale` and `formatLocale`, before drawing anything under any other root.
@@ -58,7 +58,7 @@ pnpm add @aiquants/enrichment-react @aiquants/enrichment-core @aiquants/console-
58
58
  the host resolves the zone once on the server and passes it to the root, so the server-rendered page and the hydrated one print the same string, and a host that switches the root's zone re-writes every mounted instant in the new clock.
59
59
  A timestamp is ISO 8601 with an explicit offset (`Z`, `±hh:mm` or `±hhmm`) naming an existing date and time: every text the core record schemas refuse (`z.string().datetime({ offset: true })`) throws, and so does an accepted text that names no instant the console can show (an offset beyond ±23:59, or a wall clock outside years 1–9999 in the zone). The refusal is a `ZonedTimeError` (a `RangeError` with `reason: "malformed"`).
60
60
  - **Layout.** The components use Tailwind's stock spacing, sizes, and palette, not `@aiquants/console-ui`'s tokens (its 8-px grid and 11 / 13 / 16 / 20 / 25 px type scale).
61
- Most cards are `rounded-xl border border-slate-200 border-solid bg-white p-6 shadow-sm`; `InfrastructureHealthMonitor` is `rounded-lg border border-solid bg-card p-5 shadow-sm` (the host's `card` theme colours). `PipelineFlowViewer`, `PipelineRunInspector`, and `ModelComparisonWorkbench` set type at 11 / 13 / 16 px; the other Tailwind-styled components also use 10 px, `text-xs` (12 px), and `text-sm` (14 px).
61
+ Most cards are `rounded-xl border border-slate-200 border-solid bg-white p-6 shadow-sm`; `InfrastructureHealthMonitor` is `rounded-lg border border-solid bg-card p-5 shadow-sm` (the host's `card` theme colours), and its probe-state marks alone take `@aiquants/console-ui`'s colour roles (`success-fg` on `success-tint`, `danger-fg` on `danger-tint`, see its section). `PipelineFlowViewer`, `PipelineRunInspector`, and `ModelComparisonWorkbench` set type at 11 / 13 / 16 px; the other Tailwind-styled components also use 10 px, `text-xs` (12 px), and `text-sm` (14 px).
62
62
  `DegradedSearchBanner`, `QdrantStorageCard`, and `SyncStatusMonitor` are styled inline, with no Tailwind classes. The two cards have an 8-px radius and 16-px padding, set type from 11 px up to 18 px (`QdrantStorageCard`) or 20 px (`SyncStatusMonitor`), 12 and 14 px included, and use spacings such as 2, 6, 10, and 14 px that are off the 4-px half-step grid; the banner has a 6-px radius and a padding of 12 px by 16 px, and takes its type size from the host.
63
63
  - **One card-title scale.** Every card title (`h2`) is 16 px bold (`text-base font-bold`, or `fontSize: "16px", fontWeight: 700` where the component styles inline) — the same scale `@aiquants/enrichment-react-router` and `@aiquants/governance-react` use, so sibling cards on one tab read as one heading level. `tests/HeadingOutline.spec.tsx` checks every panel's `h2`.
64
64
  - **Borders name their style.** Every Tailwind border-width utility (`border`, `border-t`, `border-2`, …) sits in the same class list as `border-solid` (or another explicit style), and every `divide-x` / `divide-y` next to `divide-solid`. A host whose base layer sets `border-style: none` on every element (for example `* { @apply border-none }`) would otherwise leave those utilities with a width and no line.
@@ -100,6 +100,11 @@ Connectivity probes for Qdrant, Neo4j, Redis, SQL Server, and the backend API. R
100
100
  Each service's version sits under one hook, `service-version-value-${service}` inside `service-version-${service}`: the version the probe read (`data-measured="true"`), set in monospace as code, or the root's unmeasured label when it read none (`version: null`, `data-measured="false"`), never `N/A`, set like the unmeasured label of every detail row and not as code. A version that is empty or only white space throws `RangeError` naming the hook.
101
101
  A host whose probe cannot read a version passes `null`: a stand-in word such as `unknown` would be drawn as a version the probe read.
102
102
  Each probe's state reads one word of the console's probe vocabulary (`service-status-${service}`): `正常接続` or `接続エラー`, the same words the overall badge composes (`全サービス正常接続` / `一部サービス接続エラー`) and `QdrantStorageCard` writes for the same probe.
103
+ Every probe-state mark — the overall badge and each probe's badge with its dot (`service-status-dot-${service}`) — is drawn in `@aiquants/console-ui`'s colour roles on the mark's own surface: `success-fg` on `success-tint` for a connected probe and `danger-fg` on `danger-tint` for a failed one, the pairs of the CUI's tinted success and danger pills (both in its `CONTRAST_PAIRS`), the roles `QdrantStorageCard`'s badge takes for the same probe.
104
+ Each probe's error text (`service-error-${service}`) is a failure mark in either state, always `danger-fg` on `danger-tint`, a connected probe's included.
105
+ Each graphic (the overall badge's icon, a badge's dot) paints `currentColor`, the mark's own text colour, and nothing in a mark pulses or fades.
106
+ The mark carries its surface, so it reads the same on the host's light or dark card (the CUI palette is light-only: its stylesheet declares `color-scheme: light` on the root). Outside those marks nothing in a service card changes with the probe's state (no element, class or attribute, its frame and fill included); the state is shown by the marks alone.
107
+ The error text is drawn only when the probe's `errorMessage` has something to read (the value slots' definition above); it breaks anywhere and is shown in full, like the endpoint. An `errorMessage` with nothing to read (empty or only white space, as an `Error` thrown with no message gives) says nothing, so the card draws no box for it and the failure reads from the probe's badge; the card does not throw on it, since a monitor that stopped on a probe's empty error would hide the failure it exists to show.
103
108
  Each probe's latency is a `Measured` count with `ms` (`health-latency-value-${service}`, `data-measured="true"`), grouped like every other duration of the console (`1,234 ms`), and must be a non-negative safe integer (otherwise `RangeError`). Measure it on a monotonic clock and round to whole ms (`Math.round(performance.now() - started)`): the wall clock (`Date.now()`) can step back during a probe, and a negative latency stops the card.
104
109
  Every detail's value sits under one hook, `health-detail-value-${service}-${key}`. A counted detail (`collectionsCount`, `nodeCount`, `totalKeys`, `endpointsCount`) given as a number is a `Measured` count with `件` and must be a non-negative safe integer (otherwise `RangeError`); any other number (a port, not grouped) and a boolean (`true` / `false` read 有効 / 無効) are figures, and a number that is not finite (`NaN`, `Infinity`) throws `RangeError` naming its hook; a string, a counted detail given as a string included, is the probe's text (all `data-measured="true"`).
105
110
  A text detail must not be empty or only white space: it throws `RangeError` naming its hook (`health-detail-value-sqlServer-fullVersion: …`), and the whole card with it, so a host passes `null` for a text it could not read, never a stand-in word (`unknown`) or an empty string, which would read as a value the probe read. A detail the probe could not read (`null`), counted or not, is the root's unmeasured label (`data-measured="false"`), so a Redis whose DBSIZE failed (`totalKeys: null`) reads as unmeasured, never `0 件`.
@@ -211,7 +216,7 @@ Every count on the card is a `Measured` count in the root's format locale (`qdra
211
216
  The point-count column is end-aligned, header included, so its tabular figures line up by place value; the other columns are start-aligned. While `overview.probe_failure` is set the totals and the collection count are unmeasured, not `0`.
212
217
  RAM and disk sit under one hook each (`qdrant-ram-usage-value`, `qdrant-disk-usage-value`), written by the package's one byte format, the same as `DocumentIngestConsole`'s file size, in a slot that never breaks between the number and its unit.
213
218
  A measured size is written in binary units (B below 1 KiB without decimals, so `512 B` and `1,023 B`, then KiB / MiB / GiB / TiB, powers of 1024), its unit chosen after rounding (1,048,575 bytes is `1.0 MiB`, never `1,024.0 KiB`), its mantissa grouped in the root's format locale in tabular figures (1,048,524 bytes is `1,023.9 KiB`; TiB has no upper bound, so 2^53 − 1 bytes is `8,192.00 TiB`) with `data-measured="true"`, and a size that is `null` or absent is the root's unmeasured label (`data-measured="false"`).
214
- `latency_ms` follows the same clock rule as `InfrastructureHealthMonitor`'s `latencyMs`: a monotonic clock, rounded to whole ms. The health badge (`qdrant-health-badge`) reads the console's probe vocabulary, `正常接続` or `接続エラー`, the words `InfrastructureHealthMonitor` writes for the same probe.
219
+ `latency_ms` follows the same clock rule as `InfrastructureHealthMonitor`'s `latencyMs`: a monotonic clock, rounded to whole ms. The health badge (`qdrant-health-badge`) reads the console's probe vocabulary, `正常接続` or `接続エラー`, in its colour roles (`success-fg` on `success-tint`, `danger-fg` on `danger-tint`): the words and the roles `InfrastructureHealthMonitor` draws for the same probe.
215
220
  In the header the badge, the latency (`qdrant-latency`) and the refresh button (`更新`, `更新中…` while refreshing) never break inside; the title group takes the width the button leaves and wraps between its items, so in a narrow card the badge and the latency move under the title whole and the button stays at the end of the first line.
216
221
  Every figure follows the console's one validity rule: `null` or absent means not measured (`ram_bytes`, `disk_bytes` and `segment_count` are typed `number | null`, like every measured count of `@aiquants/enrichment-core`), and a number — `points_count`, `vectors_count`, a named vector's `size`, `segment_count`, `ram_bytes`, `disk_bytes` or `latency_ms` — must be a non-negative safe integer: a negative, fractional or non-finite figure is a broken probe, so the card throws `RangeError` instead of writing it as a value or as unmeasured.
217
222
  The card asks `@aiquants/console-ui`'s `formatCount` to judge every figure, keeping no copy of the rule; for a figure it sums, converts or writes per row, the error names the figure in front of `formatCount`'s message (`ram_bytes: …`, `points_count of collection <name>: …`, `vectors_config.dense.size of collection <name>: …`), with that error as its `cause`, and a broken latency throws `formatCount`'s own error through `Measured`.
@@ -238,7 +243,12 @@ The package keeps no luminance computation or AA bar of its own, the colour spec
238
243
 
239
244
  - **Flow viewer:** every node's label (`flow-node-label-${key}`), phase (`flow-node-phase-${key}`), and gate line (`flow-gate-badge-${key}`) on the node's fill, unselected (`white`) and selected (`indigo-50`); the dependency edges and their arrowhead on the figure's background (`slate-500` on `rgb(248 250 252)`, 4.56:1).
240
245
  - **Run inspector:** each run row's trigger, attempt, and start time (`run-history-trigger-${id}`, `run-history-attempt-${id}`, `run-history-started-at-${id}`) on the selected row (`indigo-50`) and on an unselected row at rest (`white`) and hovered (`slate-50`).
241
- - **Status badges and counts:** the health monitor's overall badge and each `正常接続` badge (`emerald-800` on `emerald-100`), the ontology card's HITL count (`ontology-unresolved-count`, `amber-700` on its tile), and the strategy board's stage switches, open (`emerald-700` on `emerald-50`) and closed (`slate-600` on `slate-100`).
246
+ - **Status badges and counts:** the ontology card's HITL count (`ontology-unresolved-count`, `amber-700` on its tile) and the strategy board's stage switches, open (`emerald-700` on `emerald-50`) and closed (`slate-600` on `slate-100`).
247
+ - **Probe-state marks:** the health monitor's overall badge, each probe's badge, and each probe's error text (`service-error-${service}`), with every probe connected and with some probes failed (a connected one among them carrying an error text), each at rest and while re-probing, with and without the refresh button; the Qdrant card's health badge (`qdrant-health-badge`), connected and failed, at rest and while refreshing.
248
+ Each mark's texts pass `@aiquants/console-ui/testing`'s role scan `scanColourRoles` as exactly its own pair, its state's `success-fg` on `success-tint` or `danger-fg` on `danger-tint`, and the error text's `danger-fg` on `danger-tint` in either state (pairs `@aiquants/console-ui`'s `CONTRAST_PAIRS` lists, so each meets the text bar).
249
+ No class inside the mark can change what it paints (a colour, `opacity`, a filter, a blend mode, a mask, an animation or any arbitrary property such as `[color:…]`, under any variant).
250
+ On the component's elements around it there is no compositing class (`opacity`, a filter, a blend mode, a mask, an animation), no arbitrary property, and no class that paints the elements inside (a colour or compositing utility under a variant that reaches them: `*:`, `**:`, `marker:`, `selection:` or an arbitrary variant with `&` such as `[&_p]:`), which would set the mark's paint directly, whatever the order of the host's layers.
251
+ The overall badge's icon and each badge's dot paint only `currentColor`, the mark's text colour, so they meet the 3:1 bar with the text's pair.
242
252
  - **Qdrant storage card:** every text of the collections table's rows on the background it is painted on — the selected row's name button (the `fg` role on `info-tint`), domain and point count on the row's `info-tint`, the unselected rows' texts on the card's white, and each vector tag's text on its own fill. CUI token colours (`var(--cui-…)`, the `data-cui-fg` and `data-cui-surface` roles) are resolved through `@aiquants/console-ui`'s `TOKENS`, the inline hex colours as they are written.
243
253
  - **Ingest console:** the `記録なし` last-run note (`ingest-last-run-none-${id}`) and the blocked-action reason (`ingest-action-blocked-${id}`) on the row at rest and hovered (`hover:bg-slate-50/80`); the `旧版` badge (`ingest-item-superseded-${id}`, `slate-600` on its own `slate-100`, 6.90:1); the required-field marks of the URI, confidentiality, and domain fields (`ingest-required-mark-${field}`, `red-700` on the form's white card, 6.42:1).
244
254