Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/listview-map-liveness-live.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
---
"@objectstack/spec": patch
---

**Liveness-ledger verdict:** `view.list.map` (`ListViewSchema`'s view-level `map` block) moves `planned` → `live` (#11442).

objectui#5908 landed the missing half of the forward: `packages/plugin-list/src/ListView.tsx`'s `resolveListMapConfig` now merges the view-level `map` block over the legacy `options.map` bag before `case 'map'` builds the `object-map` schema, and the same merged config also feeds the visualization-switcher's capability gate — so a view that binds its coordinates only in the spec's `map` block both renders on the map surface and is no longer filtered out of `allowedVisualizations`. Nothing about the schema shape or the authoring-time validation changed; only the runtime consequence of authoring the key does.

Pinned by objectui `packages/plugin-list/src/__tests__/ListView.mapViewLevelConfig.test.tsx` (the forward, against a spy) and `packages/plugin-map/src/ObjectMap.listViewMapConfigReach.test.tsx` (the end-to-end read through a real `ObjectMap` — markers, titles, camera). Re-measured against objectui `origin/main@08ca73f8` (squash commit `e2e8e68` for #5908 confirmed an ancestor).
2 changes: 1 addition & 1 deletion packages/spec/liveness/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -798,7 +798,7 @@ marker where the Notes cell goes, never a guess at what belongs there.
| skill | `permissions` REMOVED 2026-07 (#3704); `triggerPhrases` REMOVED 2026-07-30 (#3896 close-out sweep — phrases were never matched; activation is `triggerConditions` + the agent's `skills[]` + /skill-name pinning) |
| dataset | `measures.certified` (declared-but-unenforced governance flag) REMOVED in 16.0 (#2377) |
| page | fully live + one planned |
| view | list/form drilled via `children` (#2998 Track B); list.{responsive,performance} + form.{defaultSort,aria} REMOVED 2026-07-30 (#3896 close-out sweep — list aria/data stay live); **form.data was that sweep's one CORRECTION** — the removal attempt broke the build (`defineForm` writes `data.provider='schema'` onto every metadata form, `metadata-protocol` serves it), so it stands `live` with re-verified evidence; form.{buttons,defaults} live (framework#1894 / #2998); audit-era DEAD lines superseded by re-verification. **The dead set is six, not the four removals above**: #4534 (the last #4001 batch, batch 6e) declared three CONTAINER-level keys this row had never classified — `name` and `label`, both `dead`, and `object`, `live`. All three are properties of the `views: [...]` *container*, not of a view: `name` is dead as a BODY key because the live one is the `sys_metadata` row column the door supplies, and `label` is container display metadata with no reader. Neither is `authorWarn`'d and both are deliberately KEPT — the platform's own writers send `name` (artifact-shipped containers, the metadata-validation sweep), so tombstoning it would reject shapes we write ourselves. `object` is the container's object binding, and it was *stripped on every parse* until #4534 declared it. Separately, the level-2 dead residue (userActions.buttons, addRecord.mode/formView, tabs[].order) is noted on parents and is **not** in the counts — one drill level only **#9340**: `list.map` declared — the eighth visualization block (`ListMapConfigSchema`), keys mirroring objectui plugin-map's documented read set. `planned`, deliberately not `live`: the component-level reader exists (ObjectMap.tsx getMapConfig reads `schema.map`) but objectui ListView.tsx `case 'map'` still forwards only `options.map`, never the view-level block; flips live when the pre-registered objectui consumer card (Blocked-by #9340) lands the forwarding |
| view | list/form drilled via `children` (#2998 Track B); list.{responsive,performance} + form.{defaultSort,aria} REMOVED 2026-07-30 (#3896 close-out sweep — list aria/data stay live); **form.data was that sweep's one CORRECTION** — the removal attempt broke the build (`defineForm` writes `data.provider='schema'` onto every metadata form, `metadata-protocol` serves it), so it stands `live` with re-verified evidence; form.{buttons,defaults} live (framework#1894 / #2998); audit-era DEAD lines superseded by re-verification. **The dead set is six, not the four removals above**: #4534 (the last #4001 batch, batch 6e) declared three CONTAINER-level keys this row had never classified — `name` and `label`, both `dead`, and `object`, `live`. All three are properties of the `views: [...]` *container*, not of a view: `name` is dead as a BODY key because the live one is the `sys_metadata` row column the door supplies, and `label` is container display metadata with no reader. Neither is `authorWarn`'d and both are deliberately KEPT — the platform's own writers send `name` (artifact-shipped containers, the metadata-validation sweep), so tombstoning it would reject shapes we write ourselves. `object` is the container's object binding, and it was *stripped on every parse* until #4534 declared it. Separately, the level-2 dead residue (userActions.buttons, addRecord.mode/formView, tabs[].order) is noted on parents and is **not** in the counts — one drill level only **#9340**: `list.map` declared — the eighth visualization block (`ListMapConfigSchema`), keys mirroring objectui plugin-map's documented read set. FLIPPED `planned` → `live` 2026-08-24 (#11442): objectui#5908 landed `resolveListMapConfig`, which merges the view-level `map` block over the legacy `options.map` bag before `ListView.tsx`'s `case 'map'` forwards it into `ObjectMap`, with the same merged config also feeding the visualization-switcher's capability gate so a view binding coordinates only in the spec block is no longer filtered out of `allowedVisualizations` either (objectui#5042) |
| report | dataset-bound (ADR-0021); the aria/performance LEDGER entries were stale — the keys left the schema in the report-liveness close-out; deleted 2026-07-30 as hygiene. Audit-era `chart` DEAD superseded (framework#1890 / #3441) |
| dashboard | ADR-0021 dataset widgets (#3251; DashboardWidgetSchema `.strict()`); `aria`/`performance` (and widget `performance` + PerformanceConfigSchema) REMOVED 2026-07-30 (#3896 close-out sweep — no renderer applied any of them); audit-era `globalFilters`/`dateRange` DEAD superseded (framework#2501) **#4956**: `widgets` DRILLED — the row jumps 20 → 41 classified because all 22 widget-level keys enter the count at once. They had never been classified at all: the entry carried one blanket `live` plus a `note` asserting they were classified "in the DashboardWidgetSchema subtree", and no such subtree existed in any of the 28 ledger files. That gap, not any evidence, is what carried `widgets[].responsive` through the #3896 sweep that removed both its sibling `widgets[].performance` and its literal namesake `view.responsive` — `view` is drilled, so `list.responsive` got asked and went out. New dead 6 = `responsive` (retired #4876/#4995, tombstone keeps the row) + `colorVariant` + `actionUrl`/`actionType`/`actionIcon` + `aria`. The action trio is the sharpest: no renderer draws a per-widget action button at all (every `actionUrl` read in DashboardRenderer is scoped to `header.actions[]`), yet `validate-dashboard-action-refs.ts` enforces reference integrity on it and its docblock calls it "the per-widget button" — a lint guarding an affordance that does not exist. `requiresService` is the counter-example worth remembering: dead by every objectui measurement, and LIVE server-side (`filterDashboardForUser`, ADR-0057 D10) — judging a widget key from the renderer repo alone would have retired an enforced gate. `compareTo` is `live` on ONE path only (inline object-provider charts); on the ADR-0021 dataset path the string arms are dropped and `{ offset }` throws in the executor. **#6774** moves the row 33/8 → 34/7: `colorVariant` CORRECTED dead → live 2026-08-09, the enforce leg of #5010 ruling B landing from the renderer side (objectui#3359 / PR objectui#3799, absorbed by pin `09987b68`). Worth reading beside `requiresService` above, because it is the same lesson from the other end — that row warns against judging a widget key from the renderer repo alone, and this one is a `dead` verdict that was correct in this repo AND correct in the renderer repo on the day it was measured, and stopped being either when a cross-repo decision was implemented. A ledger row is a claim with a timestamp; `verifiedAt` is what makes the claim re-askable. It also empties the dashboard warn set, so the author-side lint now says nothing about any widget key — `dashboard` stays in the lint's TYPE_COLLECTIONS all the same (the `webhook`/`email_template` resolved state) |
| query | **not a metadata type** — the REQUEST surface (`QuerySchema`: client SDK QueryBuilder output; the `POST /data/:object/query` body), governed via `SPEC_ONLY_SCHEMAS` (#4286). The gate's one-level walk resolves 1 experimental; the 7 marker-experimental search affordances sit one level deeper, below the walk — resolved from `[EXPERIMENTAL — not enforced]` describe markers, not ledger entries (search `fuzzy`/`operator`/`boost`/`minScore`/`language`/`highlight` + `aggregations[].filter` — declared engine affordances no executor receives). The #4286 sweep closed out same-release: `having` ENFORCED 2026-07-31 (engine-side post-aggregation filter, both paths; was finding 1); dead 4 = the tombstoned removals `joins`/`windowFunctions`/`cursor`/`distinct` — REMOVED 2026-07-31 (retiredKey keeps each in the walked shape so the rows stay; protocol-17 semantic migrations; the JoinNode + WindowFunctionNode clusters and the `QueryBuilder.cursor()`/`.distinct()` producers deleted with their keys; `distinct`'s mis-wired REST count suppression deleted too — finding 2). **#6815** adds the 5th dead: `aggregations[].distinct` REMOVED 2026-08-09 (live → dead, `-1` live). It is the one member of this ledger the #4286 sweep could not have caught with the question it asked — that sweep looked for keys NO executor reads, and this one had a reader: the objectql in-memory fallback deduplicated before applying the function while all five other faces (driver-sql, driver-turso, driver-mongodb, driver-memory, service-analytics' `AGGREGATE_SQL`) ignored it, so one query answered two plausible NUMBERS depending on which backend served it. The lesson for the next audit is the question, not the key: a per-key `live` verdict is only as good as the count of faces it was measured across, and this row's 2026-07-31 evidence (`in-memory-aggregation.ts:167,204-206`) was TRUE and still the wrong verdict. `count_distinct` is the surviving spelling (enforce leg, #6409) |
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/liveness/state-counts.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,7 +39,7 @@ for both corollaries.
| `skill` | 16 | 0 | 1 | 0 | 17 |
| `dataset` | 27 | 0 | 0 | 0 | 27 |
| `page` | 23 | 0 | 0 | 1 | 24 |
| `view` | 77 | 0 | 9 | 1 | 87 |
| `view` | 78 | 0 | 9 | 0 | 87 |
| `report` | 21 | 0 | 0 | 0 | 21 |
| `dashboard` | 34 | 0 | 7 | 0 | 41 |
| `webhook` | 19 | 0 | 0 | 0 | 19 |
Expand All@@ -58,4 +58,4 @@ for both corollaries.
| `capability` | 12 | 0 | 0 | 0 | 12 |
| `qa` | 4 | 0 | 5 | 0 | 9 |
| `manifest` | 22 | 0 | 21 | 0 | 43 |
| **total** | **821** | **5** | **76** | **11** | **913** |
| **total** | **822** | **5** | **76** | **10** | **913** |
7 changes: 4 additions & 3 deletions packages/spec/liveness/view.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -118,10 +118,11 @@
"note": "objectui: @object-ui/plugin-tree ObjectTree.tsx (spec CHANGELOG: 'Renderer ships in objectui @object-ui/plugin-tree')."
},
"map": {
"status": "planned",
"verifiedAt": "2026-08-17",
"status": "live",
"verifiedAt": "2026-08-24",
"evidenceScope": "cross-repo",
"note": "PLANNED, deliberately not `live`, and the gap is one spread. Declared spec-first by the #9340 cross-repo ruling (transfer of objectui#5001). The renderer's read of this exact key set exists today — objectui plugin-map ObjectMap.tsx getMapConfig validates `schema.map` against a local zod schema with the same seven keys (latitudeField/longitudeField/locationField/titleField/descriptionField/zoom/center) — but objectui ListView.tsx `case 'map'` forwards only `schema.options?.map` and never the view-level `map` block, so authoring this key changes nothing at runtime until the pre-registered objectui consumer card (Blocked-by #9340) lands the view→renderer forwarding. Flip to `live` citing that ListView.tsx read when it lands — measured objectui at the checkout current on 2026-08-17."
"evidence": "objectui: packages/plugin-list/src/ListView.tsx:113 resolveListMapConfig merges the view-level `map` block over the legacy `options.map` bag (view-level wins); :1849-1858 the visualization-switcher capability gate asks the SAME merged config, not `options.map` alone, before offering 'map' in allowedVisualizations; :2181-2205 `case 'map'` forwards the merged config into the object-map schema. objectui: packages/plugin-list/src/__tests__/ListView.mapViewLevelConfig.test.tsx pins the forward against a spy; objectui: packages/plugin-map/src/ObjectMap.listViewMapConfigReach.test.tsx pins the end-to-end read through a real ObjectMap (markers/titles/camera) — measured objectui @08ca73f8",
"note": "FLIPPED planned → live 2026-08-24: objectui#5908 (merged 2026-08-23T19:52:08Z; squash commit `e2e8e68` on objectui main, confirmed an ancestor of the objectui @08ca73f8 checkout this row cites) landed the view→renderer forwarding the prior PLANNED note's flip condition named. `resolveListMapConfig` now merges the view-level `map` block this key declares over the legacy `options.map` bag, `case 'map'` forwards the merge into `ObjectMap`, and the same merged config also feeds the visualization-switcher's capability gate — closing a second hole the prior note didn't need to describe (a view binding coordinates only in the spec `map` block no longer gets silently filtered out of `allowedVisualizations`, objectui#5042). The ADR-0047 `InterfaceListPage` path (packages/app-shell/src/views/InterfaceListPage.tsx:406-409) forwards the authored `map` block verbatim onto the schema it hands to `ListView`, so it reaches the same resolver rather than dead-ending. Pins: `ListView.mapViewLevelConfig.test.tsx` (the forward, against a spy) and `ObjectMap.listViewMapConfigReach.test.tsx` (the end-to-end read). Prior PLANNED note (verifiedAt 2026-08-17, #9340) is superseded; its flip instruction is discharged."
},
"description": {
"status": "live",
Expand Down
Loading