feat(react-inspector): schema annotation tooltips, container labels, and lineage#688
Conversation
Replaces the previous native `title=` attribute with a proper hover/focus tooltip that surfaces every useful Effect Schema annotation at once: - description, documentation - examples (formatted via `pretty` when present) - default - constraints derived from `JSONSchemaAnnotationId` set by refinements (`nonEmptyString`, `int`, `between`, `pattern`, `format`, …) - possible values for `Literal`, `Enums`, `Union`-of-literal, and `TemplateLiteral` ASTs (capped at 12 with `… +N more`) Tooltips attach to field names, root labels, and struct type badges. Triggers are keyboard-focusable and wire `aria-describedby` to the tooltip for screen-reader users. Bug fix: `getFieldSchema` no longer eagerly unwraps refinement / transformation wrappers, so user-supplied annotations on a `.pipe(...).annotations(...)` chain reach the tooltip. Downstream traversal still works because each lookup re-applies `unwrapAstForDisplay` at its entry point. Effect's built-in primitive descriptions like "a string" / "a number" are filtered out of `hasContent`, so primitive fields without user annotations do not get a tooltip affordance. New exports: `SchemaTooltip`, `SchemaInfo`, `SchemaConstraint`, `getSchemaInfo`, `getConstraintsFromJSONSchema`, `getPossibleValuesFromAST`. Storybook: new `SchemaTooltipFull` (exercises every annotation kind), `SchemaTooltipKeyboardA11y`, `SchemaTooltipTruncatedPossibleValues`, `SchemaTooltipMixedAnnotated` stories. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 511ae87b7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…N Schema collection Two review fixes: - `SchemaTooltip`: close on scroll and resize (capture-phase scroll listener so nested scrollable containers also trigger). Coords were captured once at open time and would otherwise drift away from the trigger element as the page scrolled. - `getConstraintsFromJSONSchema`: guard against self-referential Suspend chains with a WeakSet. The try/catch around `ast.f()` does not catch identity-cycle recursion (it would StackOverflow without throwing). Also: fix stale doc comment in `SchemaTooltip` that referenced a "transform-anchored wrapper" that doesn't exist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- `getConstraintsFromJSONSchema`: recurse before writing JSON Schema fragments so that outer refinements win on duplicate keys. Previous recurse-after-write order let inner refinements clobber tighter outer bounds (e.g. `between(0, 100).pipe(between(10, 50))` reported `0..100` instead of `10..50`). - `SchemaAwareObjectPreview`: keep the "Object " badge as a tooltip trigger when a plain-object root has tooltip content but no `title`/`identifier`. Otherwise the description was unreachable at depth 0 because the field-name trigger doesn't exist for root nodes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trivial formatting nit — oxfmt prefers a leading `;` on the standalone `<SchemaTooltip>` JSX example to make ASI-safe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…cords, tuples (#686) Surface the schema's element/value/positional types in the type-badge slot instead of falling back to the runtime constructor name: - `Schema.Array(Item)` → `Array<Item>(N)` (was `Array(N)`) - `Schema.Array(Item).annotations({ identifier: 'Pinned' })` → `Pinned(N)` - `Schema.Record({ key: String, value: Money })` → `Record<string, Money>` (was `Object`) - `Schema.Tuple(String, Number, Boolean)` → `[string, number, boolean](N)` Element labels follow the same precedence as everywhere else: `title` ?? `identifier` ?? type-kind. Anonymous structs/unions return `undefined` and the renderer falls through to the previous behavior. `getFieldSchema` now falls back to the first `indexSignature.type` when no `propertySignature` matches, so per-field schema resolution works inside records (tooltips, pretty formatting, nested navigation). `SchemaInfo` gains an optional `containerLabel: string` field. New `ContainerLabels` storybook story exercises all four cases. Out of scope here (tracked separately under #686): `Map`/`Set` containers, runtime tagged-union narrowing to a specific variant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ations (#686, #687) Wraps up the remaining work on issue #686 and adds the full lineage annotation namespace from issue #687. ## #686 leftovers - **Map/Set container labels**: `Schema.Map({key, value})` renders as `Map<K, V>(N)`, `Schema.Set(T)` as `Set<T>(N)`, plus the `Readonly*` variants. Detected via the `effect/annotation/TypeConstructor` annotation on `Declaration` ASTs (a stable internal Effect signal). - **Runtime tagged-union narrowing**: when a field's declared schema is `Schema.Union(A, B, C)` of `_tag`-discriminated variants and the runtime value carries a matching `_tag`, the inspector narrows the display (name, tooltip, container label, nested-field resolution) to the matched variant. Narrowing happens on every path segment, not just the leaf, so deeply nested fields under a tagged union resolve through the matched variant. `SchemaProvider` gains an optional `rootData` prop; context exposes new `getContextForPathWithValue(path, value)`. `withSchemaSupport` / `withSchemaContext` forward `data` as `rootData` automatically, so HOC consumers get narrowing for free. ## #687 lineage annotations New module `src/schema/lineage.ts` defining a hybrid namespace: - **Fat tagged union** `Lineage`: `SourceOfTruth | Derived | Projection | Cache | Mirror | External | Computed` — answers the *epistemic* question "where does this field's value come from". - **Companion annotations** (composable, orthogonal): `Authority` (writers/readers), `Freshness` (capturedAt + maxAgeMs), `ForeignKey` (target schema + field). - All shapes are themselves Effect Schemas (self-describing per #687 acceptance criteria), enabling decode-and-validate at the consumer. - Ergonomic pipe-style constructors: `Schema.X.pipe( Lineage.derivedFrom(['a', 'b'], 'Pure', { pure: true }))`, `Lineage.cache('rate', { ttlMs: 60_000 })`, `Lineage.authority(...)`, etc. Bare-string `from` refs are coerced to `Field` shape. - Extractors (`Lineage.getLineage(schema)` etc.) are fail-soft — corrupt annotation values return `undefined` rather than crashing the renderer. - Round-trip tested in `src/schema/lineage.test.ts` (9 tests). ### Renderer wiring - `SchemaInfo.lineage?: LineageBundle` bundles the lineage display + companion annotations. - `SchemaTooltip` gains a `LINEAGE` section (kind badge + summary + optional details) plus `AUTHORITY` / `FRESHNESS` / `REF` rows. - A small superscript glyph (`ƒ`, `≈`, `☷`, `↻`, `↗`, `⊙`) sits next to annotated field names. `SourceOfTruth` is the implicit default and intentionally has no badge to avoid clutter. - `Derived.from` field paths in the tooltip carry `data-lineage-target="$.path"` for future jump-to-source wiring. ## Stories - `MapAndSetContainerLabels` — `Schema.MapFromSelf`, `Schema.SetFromSelf`, `Schema.ReadonlyMapFromSelf` with real `Map`/`Set` values. - `RuntimeTaggedUnionNarrowing` — `Schema.Union(EventCreated, EventUpdated, EventDeleted)` with two sample audit entries. - `LineageAnnotations` — `OrderTotals` exercising every Lineage tag plus a companion-only example. ## Lints / CI Fixed two pre-existing `no-shadow` warnings in `@overeng/notion-md` (`opts` in `workspace.ts:visit`, `pageId` in `sync.e2e.test.ts: readSyncStateFile`). CI runs `oxlint --deny-warnings`, so those were blocking the lint job for any branch — unrelated to react-inspector but needed for green CI on this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI runs oxlint through the @overeng/oxc-config JS plugin wrapper, which adds the `overeng/explicit-boolean-compare` rule (requires `=== true`, `=== false`, `!== null` instead of implicit boolean coercion). The base `oxlint` binary on $PATH doesn't load the plugin, so these only surface in CI. Affected: SchemaContext.tsx, SchemaTooltip.tsx, SchemaAwareObjectPreview.tsx, SchemaAwareNodeRenderer.tsx, effectSchema.tsx, lineage.ts. Pure mechanical change — no behavior diffs. Verified locally with the built oxlint-with-plugins wrapper: 0 warnings, 0 errors across packages/ scripts/ context/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI Measurementspartial - advisory gate - readiness
nix / closures / packages
Unchanged / 0-impact measurements (17)These rows had compatible baseline data, but their semantic impact rounded to 0.00x because the movement was below the configured budget, below the noise floor, or inside the robust noise band. devenv / devenv cli
devenv / devenv shell
devenv / genie
devenv / quality gates
devenv / workspace setup
nix / closures / packages
Diagnostic / ungated measurements (7)source / effect-utils
devenv / devenv shell
All measurements
Previous runs
Source-of-truth JSON{
"schemaVersion": 1,
"title": "CI Measurements",
"status": "partial",
"gate": "advisory",
"readiness": "partial (17/26 enabled observations gateable)",
"commit": {
"shortSha": "8203d0c",
"sha": "8203d0cc06f450862c06644854def221dcbc2c80"
},
"run": {
"id": "26422219238",
"attempt": "1",
"url": "https://github.com/overengineeringstudio/effect-utils/actions/runs/26422219238"
},
"baseline": null,
"protocol": "devenv-perf-warm-median-v2",
"chart": {
"meaning": "semantic-impact",
"zeroImpactMeaning": "no actionable PR impact after budgets, noise floor, and robust evidence checks",
"svg": "https://raw.githubusercontent.com/overengineeringstudio/effect-utils/ci-measurement-assets/ci-measurements/pr-688/8203d0cc06f450862c06644854def221dcbc2c80/run-26422219238-attempt-1/ci-measurements.svg",
"lightPng": "https://raw.githubusercontent.com/overengineeringstudio/effect-utils/ci-measurement-assets/ci-measurements/pr-688/8203d0cc06f450862c06644854def221dcbc2c80/run-26422219238-attempt-1/ci-measurements.png",
"darkPng": "https://raw.githubusercontent.com/overengineeringstudio/effect-utils/ci-measurement-assets/ci-measurements/pr-688/8203d0cc06f450862c06644854def221dcbc2c80/run-26422219238-attempt-1/ci-measurements-dark.png"
},
"measurements": [
{
"id": "source.lines",
"label": "Genie runtime lines",
"group": "source / effect-utils",
"path": [
"source",
"effect-utils",
"packages",
"genie",
"source / genie"
],
"groupPath": [
"source",
"effect-utils"
],
"status": "pass",
"direction": "regressed",
"gateable": false,
"gateReason": "disabled",
"confidence": "diagnostic",
"comparisonMode": "budget",
"unit": "lines",
"baseline": 18806,
"current": 18874,
"delta": 68,
"ratio": 1.003615867276401,
"semanticImpactScore": null,
"semanticImpactKind": "diagnostic",
"baselineSources": 8,
"currentSamples": 62,
"pairedSamples": 0,
"evidenceDeltaLower": -1812.6000000000001,
"evidenceDeltaUpper": 1948.6000000000001,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"scope": "genie_runtime"
}
},
{
"id": "source.lines",
"label": "Genie CI workflow helpers lines",
"group": "source / effect-utils",
"path": [
"source",
"effect-utils",
"genie",
"ci-workflow",
"source / ci"
],
"groupPath": [
"source",
"effect-utils"
],
"status": "pass",
"direction": "regressed",
"gateable": false,
"gateReason": "disabled",
"confidence": "diagnostic",
"comparisonMode": "budget",
"unit": "lines",
"baseline": 6759.5,
"current": 6765,
"delta": 5.5,
"ratio": 1.000813669650122,
"semanticImpactScore": null,
"semanticImpactKind": "diagnostic",
"baselineSources": 8,
"currentSamples": 7,
"pairedSamples": 0,
"evidenceDeltaLower": -670.45,
"evidenceDeltaUpper": 681.45,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"scope": "genie_ci_workflow"
}
},
{
"id": "source.files",
"label": "Genie runtime files",
"group": "source / effect-utils",
"path": [
"source",
"effect-utils",
"packages",
"genie",
"source / genie"
],
"groupPath": [
"source",
"effect-utils"
],
"status": "pass",
"direction": "regressed",
"gateable": false,
"gateReason": "disabled",
"confidence": "diagnostic",
"comparisonMode": "budget",
"unit": "count",
"baseline": 61.5,
"current": 62,
"delta": 0.5,
"ratio": 1.008130081300813,
"semanticImpactScore": null,
"semanticImpactKind": "diagnostic",
"baselineSources": 8,
"currentSamples": 62,
"pairedSamples": 0,
"evidenceDeltaLower": -5.65,
"evidenceDeltaUpper": 6.65,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"scope": "genie_runtime"
}
},
{
"id": "task_check_quick_forced",
"label": "Forced check:quick",
"group": "devenv / quality gates",
"path": [
"devenv",
"quality gates",
"check:quick"
],
"groupPath": [
"devenv",
"quality gates"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 9.185,
"current": 9.567,
"delta": 0.3819999999999997,
"ratio": 1.0415895481763744,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 3,
"currentSamples": 3,
"pairedSamples": 3,
"evidenceDeltaLower": -0.206,
"evidenceDeltaUpper": 0.382,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"workload": "forced-task-cache",
"taskCacheMode": "refresh",
"probe": "task_check_quick_forced",
"probeLabel": "Forced check:quick",
"status": 0,
"sampleCount": 6,
"warmupCount": 0,
"measuredSampleCount": 3,
"pairedSampleCount": 3,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "shell_eval_warm",
"label": "Warm shell eval",
"group": "devenv / devenv shell",
"path": [
"devenv",
"devenv shell"
],
"groupPath": [
"devenv",
"devenv shell"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 6.19,
"current": 6.133,
"delta": -0.057000000000000384,
"ratio": 0.9907915993537963,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 5,
"currentSamples": 5,
"pairedSamples": 5,
"evidenceDeltaLower": -0.086,
"evidenceDeltaUpper": 0.026,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"probe": "shell_eval_warm",
"probeLabel": "Warm shell eval",
"status": 0,
"sampleCount": 11,
"warmupCount": 1,
"measuredSampleCount": 5,
"pairedSampleCount": 5,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "task_check_quick_warm",
"label": "Warm cached check:quick",
"group": "devenv / quality gates",
"path": [
"devenv",
"quality gates",
"check:quick"
],
"groupPath": [
"devenv",
"quality gates"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 3.427,
"current": 3.459,
"delta": 0.03200000000000003,
"ratio": 1.0093376130726583,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 5,
"currentSamples": 5,
"pairedSamples": 5,
"evidenceDeltaLower": -0.241,
"evidenceDeltaUpper": 0.126,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"workload": "cached-no-op",
"taskCacheMode": "warm",
"probe": "task_check_quick_warm",
"probeLabel": "Warm cached check:quick",
"status": 0,
"sampleCount": 11,
"warmupCount": 1,
"measuredSampleCount": 5,
"pairedSampleCount": 5,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "genie_check_direct",
"label": "Genie check direct",
"group": "devenv / genie",
"path": [
"devenv",
"genie"
],
"groupPath": [
"devenv",
"genie"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 9,
"current": 9.026,
"delta": 0.0259999999999998,
"ratio": 1.002888888888889,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 5,
"currentSamples": 5,
"pairedSamples": 5,
"evidenceDeltaLower": 0.008,
"evidenceDeltaUpper": 0.033,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"probe": "genie_check_direct",
"probeLabel": "Genie check direct",
"status": 0,
"sampleCount": 11,
"warmupCount": 1,
"measuredSampleCount": 5,
"pairedSampleCount": 5,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "task_genie_run",
"label": "Genie run task",
"group": "devenv / genie",
"path": [
"devenv",
"genie"
],
"groupPath": [
"devenv",
"genie"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 1.449,
"current": 1.427,
"delta": -0.02200000000000002,
"ratio": 0.9848171152518979,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 5,
"currentSamples": 5,
"pairedSamples": 5,
"evidenceDeltaLower": -0.024,
"evidenceDeltaUpper": 0.02,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"probe": "task_genie_run",
"probeLabel": "Genie run task",
"status": 0,
"sampleCount": 11,
"warmupCount": 1,
"measuredSampleCount": 5,
"pairedSampleCount": 5,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "task_pnpm_install",
"label": "pnpm install task",
"group": "devenv / workspace setup",
"path": [
"devenv",
"workspace setup"
],
"groupPath": [
"devenv",
"workspace setup"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 0.716,
"current": 0.707,
"delta": -0.009000000000000008,
"ratio": 0.9874301675977654,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 5,
"currentSamples": 5,
"pairedSamples": 5,
"evidenceDeltaLower": -0.015,
"evidenceDeltaUpper": -0.007,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"probe": "task_pnpm_install",
"probeLabel": "pnpm install task",
"status": 0,
"sampleCount": 11,
"warmupCount": 1,
"measuredSampleCount": 5,
"pairedSampleCount": 5,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "processes_help",
"label": "devenv processes --help",
"group": "devenv / devenv cli",
"path": [
"devenv",
"devenv cli"
],
"groupPath": [
"devenv",
"devenv cli"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 0.023,
"current": 0.022,
"delta": -0.0010000000000000009,
"ratio": 0.9565217391304347,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 9,
"currentSamples": 9,
"pairedSamples": 9,
"evidenceDeltaLower": -0.001,
"evidenceDeltaUpper": 0.001,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"probe": "processes_help",
"probeLabel": "devenv processes --help",
"status": 0,
"sampleCount": 19,
"warmupCount": 1,
"measuredSampleCount": 9,
"pairedSampleCount": 9,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "tasks_list",
"label": "devenv tasks list",
"group": "devenv / devenv cli",
"path": [
"devenv",
"devenv cli"
],
"groupPath": [
"devenv",
"devenv cli"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "paired",
"unit": "seconds",
"baseline": 0.053,
"current": 0.054,
"delta": 0.0010000000000000009,
"ratio": 1.0188679245283019,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 9,
"currentSamples": 9,
"pairedSamples": 9,
"evidenceDeltaLower": -0.001,
"evidenceDeltaUpper": 0.001,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"probe": "tasks_list",
"probeLabel": "devenv tasks list",
"status": 0,
"sampleCount": 19,
"warmupCount": 1,
"measuredSampleCount": 9,
"pairedSampleCount": 9,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
},
{
"id": "source.files",
"label": "Genie CI workflow helpers files",
"group": "source / effect-utils",
"path": [
"source",
"effect-utils",
"genie",
"ci-workflow",
"source / ci"
],
"groupPath": [
"source",
"effect-utils"
],
"status": "pass",
"direction": "unchanged",
"gateable": false,
"gateReason": "disabled",
"confidence": "diagnostic",
"comparisonMode": "budget",
"unit": "count",
"baseline": 7,
"current": 7,
"delta": 0,
"ratio": 1,
"semanticImpactScore": null,
"semanticImpactKind": "diagnostic",
"baselineSources": 8,
"currentSamples": 7,
"pairedSamples": 0,
"evidenceDeltaLower": -1,
"evidenceDeltaUpper": 1,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"scope": "genie_ci_workflow"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Nix sources closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"genie",
"buckets",
"nix-sources",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "nix-sources"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Nix sources closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"megarepo",
"buckets",
"nix-sources",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "nix-sources"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Nix sources closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"oxlint-npm",
"buckets",
"nix-sources",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "nix-sources"
}
},
{
"id": "source.files",
"label": "Nix workspace tools files",
"group": "source / effect-utils",
"path": [
"source",
"effect-utils",
"nix",
"workspace-tools",
"source / nix"
],
"groupPath": [
"source",
"effect-utils"
],
"status": "pass",
"direction": "unchanged",
"gateable": false,
"gateReason": "disabled",
"confidence": "diagnostic",
"comparisonMode": "budget",
"unit": "count",
"baseline": 13,
"current": 13,
"delta": 0,
"ratio": 1,
"semanticImpactScore": null,
"semanticImpactKind": "diagnostic",
"baselineSources": 8,
"currentSamples": 13,
"pairedSamples": 0,
"evidenceDeltaLower": -1.3,
"evidenceDeltaUpper": 1.3,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"scope": "nix_workspace_tools"
}
},
{
"id": "source.lines",
"label": "Nix workspace tools lines",
"group": "source / effect-utils",
"path": [
"source",
"effect-utils",
"nix",
"workspace-tools",
"source / nix"
],
"groupPath": [
"source",
"effect-utils"
],
"status": "pass",
"direction": "unchanged",
"gateable": false,
"gateReason": "disabled",
"confidence": "diagnostic",
"comparisonMode": "budget",
"unit": "lines",
"baseline": 3237,
"current": 3237,
"delta": 0,
"ratio": 1,
"semanticImpactScore": null,
"semanticImpactKind": "diagnostic",
"baselineSources": 8,
"currentSamples": 13,
"pairedSamples": 0,
"evidenceDeltaLower": -323.70000000000005,
"evidenceDeltaUpper": 323.70000000000005,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"scope": "nix_workspace_tools"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Node / pnpm closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"genie",
"buckets",
"node",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "node"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Node / pnpm closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"megarepo",
"buckets",
"node",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "node"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Node / pnpm closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"oxlint-npm",
"buckets",
"node",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "node"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Rust closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"genie",
"buckets",
"rust",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "rust"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Rust closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"megarepo",
"buckets",
"rust",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "rust"
}
},
{
"id": "nix.closure.bucket.nar_size",
"label": "Rust closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"oxlint-npm",
"buckets",
"rust",
"nix closure buckets"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "unknown",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "unknown",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 0,
"current": 0,
"delta": 0,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": "unknown",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "rust"
}
},
{
"id": "nix.closure.path_count",
"label": "Total closure path count",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"genie",
"total",
"path-count",
"nix closure"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "budget",
"unit": "count",
"baseline": 80,
"current": 80,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10,
"evidenceDeltaUpper": 10,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total"
}
},
{
"id": "nix.closure.path_count",
"label": "Total closure path count",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"megarepo",
"total",
"path-count",
"nix closure"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "budget",
"unit": "count",
"baseline": 5,
"current": 5,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10,
"evidenceDeltaUpper": 10,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total"
}
},
{
"id": "nix.closure.path_count",
"label": "Total closure path count",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"oxlint-npm",
"total",
"path-count",
"nix closure"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "budget",
"unit": "count",
"baseline": 8,
"current": 8,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10,
"evidenceDeltaUpper": 10,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total"
}
},
{
"id": "nix.closure.nar_size",
"label": "Total closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"genie",
"total",
"closure-size",
"nix closure"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 533018624,
"current": 533018624,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10660372.48,
"evidenceDeltaUpper": 10660372.48,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total"
}
},
{
"id": "nix.closure.nar_size",
"label": "Total closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"megarepo",
"total",
"closure-size",
"nix closure"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 148820792,
"current": 148820792,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total"
}
},
{
"id": "nix.closure.nar_size",
"label": "Total closure size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"oxlint-npm",
"total",
"closure-size",
"nix closure"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "budget",
"unit": "bytes",
"baseline": 161363816,
"current": 161363816,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 7,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -10485760,
"evidenceDeltaUpper": 10485760,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total"
}
},
{
"id": "nix.closure.serialized_nar_size",
"label": "Total serialized NAR size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"genie",
"total",
"serialized-nar-size",
"nix closure diagnostics"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "diagnostic",
"unit": "bytes",
"baseline": 533018624,
"current": 533018624,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 6,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -53301862.400000006,
"evidenceDeltaUpper": 53301862.400000006,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total",
"sizeKind": "nar"
}
},
{
"id": "nix.closure.serialized_nar_size",
"label": "Total serialized NAR size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"megarepo",
"total",
"serialized-nar-size",
"nix closure diagnostics"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "diagnostic",
"unit": "bytes",
"baseline": 148820792,
"current": 148820792,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 6,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -14882079.200000001,
"evidenceDeltaUpper": 14882079.200000001,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total",
"sizeKind": "nar"
}
},
{
"id": "nix.closure.serialized_nar_size",
"label": "Total serialized NAR size",
"group": "nix / closures / packages",
"path": [
"nix",
"closures",
"packages",
"oxlint-npm",
"total",
"serialized-nar-size",
"nix closure diagnostics"
],
"groupPath": [
"nix",
"closures",
"packages"
],
"status": "pass",
"direction": "unchanged",
"gateable": true,
"gateReason": "eligible",
"confidence": "noise_floor",
"comparisonMode": "diagnostic",
"unit": "bytes",
"baseline": 161363816,
"current": 161363816,
"delta": 0,
"ratio": 1,
"semanticImpactScore": 0,
"semanticImpactKind": "neutral",
"baselineSources": 6,
"currentSamples": 1,
"pairedSamples": 0,
"evidenceDeltaLower": -16136381.600000001,
"evidenceDeltaUpper": 16136381.600000001,
"pairedEvidenceQuantile": 0.25,
"dimensions": {
"bucket": "total",
"sizeKind": "nar"
}
},
{
"id": "shell_eval_traced",
"label": "Shell eval with OTEL trace",
"group": "devenv / devenv shell",
"path": [
"devenv",
"devenv shell"
],
"groupPath": [
"devenv",
"devenv shell"
],
"status": "missing_baseline",
"direction": "unknown",
"gateable": false,
"gateReason": "missing_baseline",
"confidence": "missing_baseline",
"comparisonMode": "historical",
"unit": "seconds",
"baseline": null,
"current": 77.815,
"delta": null,
"ratio": null,
"semanticImpactScore": null,
"semanticImpactKind": null,
"baselineSources": 0,
"currentSamples": 1,
"pairedSamples": null,
"evidenceDeltaLower": null,
"evidenceDeltaUpper": null,
"pairedEvidenceQuantile": null,
"dimensions": {
"probe": "shell_eval_traced",
"probeLabel": "Shell eval with OTEL trace",
"status": 0,
"sampleCount": 2,
"warmupCount": 0,
"measuredSampleCount": 1,
"pairedSampleCount": 1,
"pairedOrderProtocol": "balanced-seeded-alternating-v1",
"pairedOrderSeed": "26422219238-1-80e9a6fe1a84c338f6ac49ca3617743a6db8997d",
"measurementProtocol": "devenv-perf-warm-median-v2",
"aggregation": "median",
"phase": "warm",
"devenvRev": "2cf62a010000b70f15c78a72761fad7c9e6fb47a",
"otelServiceName": "devenv-perf-ci"
}
}
]
} |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0da4fb36c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…trigger Codex P1 review on PR #688: `pointer-events: none` made the tooltip unhoverable — combined with `onMouseLeave` close, long content was unreadable, especially for magnification users. The earlier `pointer-events: none` was over-correction for an adjacent- row-blocking issue from the previous review round. Better fix: position the tooltip to the right of the trigger (not below), so it lives outside the tree's left column entirely. Sibling row triggers below the active row are no longer covered, which lets the tooltip stay pointer- interactive without blocking neighbor hover. Placement: right-of-trigger → left-of-trigger (if right overflows) → below-trigger clamped to viewport (last resort). Tooltip body now has `pointer-events: auto`, `onMouseEnter` cancels the close timer, and `onMouseLeave` re-arms it — standard hover-bridge behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ackage The `Lineage` annotation namespace was added to `@overeng/react-inspector` in #688, but its definitions only depend on `effect` — the inspector merely reads the annotations to render badges/tooltips. Pull the vocabulary into a new `@overeng/schema-lineage` package so non-React consumers can annotate schemas with epistemic lineage and share a single source of truth for the schema, symbols, helpers, and display formatting. - New package `@overeng/schema-lineage` exposes the Lineage namespace (`Lineage`, `LineageRef`, `DerivationKind`, `Authority`, `Freshness`, `Reference`, annotation symbols, `get*` readers, `getLineageDisplay`, and the `sourceOfTruth` / `derivedFrom` / `projection` / `cache` / `mirror` / `external` / `computed` / `authority` / `freshness` / `foreignKey` constructors). - `react-inspector` adds `@overeng/schema-lineage` as a workspace dep and re-exports it as `Lineage` from `./schema/mod.tsx` and `./index.tsx`, preserving the public API surface from #688. - Tightened `getLineageDisplay` to satisfy `exactOptionalPropertyTypes` in the new package's stricter tsconfig (no behavior change). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Move the `Lineage` annotation namespace (added in #688) out of `@overeng/react-inspector` and into `@overeng/utils`, exposed through the package's existing main isomorphic entry. Non-React consumers can now annotate schemas with epistemic lineage without pulling in the inspector, while sharing a single source of truth for the schema, symbols, helpers, and display formatting. Exposed via the existing `.` export (same pattern as `InMemoryBacking`) rather than a separate `./lineage` subpath, since every other isomorphic module already lives on the main entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the `Lineage` annotation namespace (added in #688) out of `@overeng/react-inspector` and into `@overeng/utils`, exposed through the package's existing main isomorphic entry. Non-React consumers can now annotate schemas with epistemic lineage without pulling in the inspector, while sharing a single source of truth for the schema, symbols, helpers, and display formatting. Exposed via the existing `.` export (same pattern as `InMemoryBacking`) rather than a separate `./lineage` subpath, since every other isomorphic module already lives on the main entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the `Lineage` annotation namespace (added in #688) out of `@overeng/react-inspector` and into `@overeng/utils`, exposed through the package's existing main isomorphic entry. Non-React consumers can now annotate schemas with epistemic lineage without pulling in the inspector, while sharing a single source of truth for the schema, symbols, helpers, and display formatting. Exposed via the existing `.` export (same pattern as `InMemoryBacking`) rather than a separate `./lineage` subpath, since every other isomorphic module already lives on the main entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the `Lineage` annotation namespace (added in #688) out of `@overeng/react-inspector` and into `@overeng/utils`, exposed through the package's existing main isomorphic entry. Non-React consumers can now annotate schemas with epistemic lineage without pulling in the inspector, while sharing a single source of truth for the schema, symbols, helpers, and display formatting. Exposed via the existing `.` export (same pattern as `InMemoryBacking`) rather than a separate `./lineage` subpath, since every other isomorphic module already lives on the main entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ry (#695) Move the `Lineage` annotation namespace (added in #688) out of `@overeng/react-inspector` and into `@overeng/utils`, exposed through the package's existing main isomorphic entry. Non-React consumers can now annotate schemas with epistemic lineage without pulling in the inspector, while sharing a single source of truth for the schema, symbols, helpers, and display formatting. Exposed via the existing `.` export (same pattern as `InMemoryBacking`) rather than a separate `./lineage` subpath, since every other isomorphic module already lives on the main entry. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes #686. Closes #687.
Summary
Three related improvements to
@overeng/react-inspector:1. Rich schema annotation tooltips
Replaces the previous native
title=attribute on schema-annotated tree nodes with a proper hover/focus tooltip that surfaces every useful Effect Schema annotation at once —description,examples,default, refinement-derived constraints (min/max/length/pattern/format/...), and possible values forLiteral/Enums/Union-of-literal /TemplateLiteralASTs.Tooltip attaches to field names, root labels, and struct type badges in collapsed previews. Triggers are keyboard-focusable and wire
aria-describedbyto the tooltip for screen readers.Example: hovering
ageonSchema.Number.pipe(Schema.int(), Schema.between(0, 150)).annotations({ identifier: 'Age', title: 'Age', description: 'Age in whole years', examples: [18, 42, 80], default: 0 })shows:2. Schema-derived container labels (closes #686)
Arrays, records, tuples, Maps, Sets, and tagged unions now surface their schema-derived type instead of the runtime constructor name:
Schema.Array(Item)→Array<Item>(N)(wasArray(N))Schema.Array(Item).annotations({ identifier: 'Pinned' })→Pinned(N)Schema.Record({ key: String, value: Money })→Record<string, Money>(wasObject)Schema.Tuple(String, Number, Boolean)→[string, number, boolean]Schema.Map({ key, value })→Map<K, V>(N)(+ReadonlyMap,Set,ReadonlySet)Schema.Union(EventA, EventB, EventC)with_tagdiscriminator + matching runtime_tag→ narrows display to the matched variant (display name, tooltip, container label, nested-field resolution)SchemaInfogains optionalcontainerLabel: string.getFieldSchemafalls back toindexSignature.typefor records.SchemaProvidergains an optionalrootDataprop; context exposes newgetContextForPathWithValue(path, value)for the union-narrowing path.withSchemaSupportforwardsdataasrootDataautomatically.3. Lineage annotations (closes #687)
New
Lineagenamespace describing the epistemic status of a field — where the value comes from, who owns it, how fresh it is, what it references.Design: hybrid of the issue's options (A) + (B) — one fat tagged union for the core kinds, plus small composable companion annotations.
The schema-aware renderer surfaces:
ƒderived,≈projection,☷cache,↻mirror,↗external,⊙computed).SourceOfTruthis the implicit default — no glyph.LINEAGE/AUTHORITY/FRESHNESS/REFblock in the schema tooltip.data-lineage-targetattributes onDerived.fromfield paths, ready for a future jump-to-source UI.All annotation shapes are themselves Effect Schemas (self-describing per #687 acceptance). Extractors fail-soft via
Schema.decodeUnknownOption. 9 round-trip vitest tests.Bug fixes bundled in
getFieldSchemano longer eagerly unwraps refinement / transformation wrappers — user-supplieddescription/examples/defaulton.pipe(int(), between(...)).annotations(...)chains now reach the tooltip.getConstraintsFromJSONSchemarecurses before writing fragments so outer refinements win on duplicate keys (between(0, 100).pipe(between(10, 50))now correctly reports10..50, not0..100).getConstraintsFromJSONSchemaagainst self-referentialSuspend.SchemaTooltipcloses on scroll/resize andEscapeper WCAG.no-shadowwarnings in@overeng/notion-md(blocking--deny-warningsCI for any branch).New exports
SchemaTooltip,SchemaTooltipPropsSchemaInfo,SchemaConstraint,LineageBundlegetSchemaInfo(schema),getConstraintsFromJSONSchema(ast),getPossibleValuesFromAST(ast)Lineagenamespace (annotation symbols, schemas, extractors, pipe constructors,getLineageDisplay)Storybook
SchemaTooltipFull/SchemaTooltipKeyboardA11y/SchemaTooltipTruncatedPossibleValues/SchemaTooltipMixedAnnotatedContainerLabels— arrays, named arrays, records, tuplesMapAndSetContainerLabelsRuntimeTaggedUnionNarrowingLineageAnnotations— every lineage tag + companion-only exampleFiltering
Effect's built-in primitive descriptions (
"a string","a number", etc.) are filtered out ofhasContent, so primitive fields without user annotations do not get a tooltip affordance.Implementation notes
aria-describedby+ Escape-to-close) is small enough that the dep isn't worth it, and RAC'sTooltipTriggerrequires its child to consumeFocusableContextwith an interactive ARIA role — which a tree-item field-name span isn't.position: fixed+pointer-events: noneso it can't sit on top of adjacent tree-row triggers and block hover. Important for dense (~14px) tree rows.Test plan
tsc --noEmitcleanoxlint --import-plugin --deny-warnings(viaoxlint-with-pluginsNix wrapper) — 0 warnings, 0 errors acrosspackages/ scripts/ context/oxfmt --checkcleanvitest run— 39 tests passingplaywright-cliagainst each new story (screenshots intmp/schema-tooltip-screenshots/)ComplexOrderExamplenow showsArray<Order Item>(2),ApiResponseWithDescriptions,ExpandedVsCollapsedPreview, etc.)🤖 Generated with Claude Code
Posted on behalf of @schickling
agent_nameagent_session_idagent_toolagent_tool_versionagent_runtimeagent_modelworktreemachinetooling_profile