Skip to content

Commit 15b586d

Browse files
fix(spec): grade connector.actions.description/outputSchema and app.areas.description live at the objectui pin (#20814)
Closes #20287 Part of #20299 Clause-②: no Three liveness rows go `dead` → `live`. Each cites its objectui reader and producer, read at the `.objectui-sha` pin `db11afd4967`: - `connector.actions.description`: the flow designer's Action picker (`FlowReferenceField.tsx#connectorActionsToOptions`), from objectui#11028. - `connector.actions.outputSchema`: the flow designer's downstream references (`flow-scope.ts#nodeOutputRefs`), from objectui#11028. - `app.areas.description`: the Studio app preview's Areas list (`AppPreview.tsx#readAreas`), from objectui#11027. #20299 stays open. Three of its rows are unchanged, because no reader at the pin reaches them: - `permission.rowLevelSecurity.label` and `.description`: `PermissionPreview` renders both, but no Studio route mounts it for `permission`. `MetadataResourceEditPage` hands a permission item to the registered custom `PermissionMatrixEditPage`. That page renders no preview, and it reads no policy label or description. - The `view` container `label`: `ViewPreview` draws the draft's `label`, but the draft is always a ViewItem. Both the metadata list and the Studio list drop the aggregated container. Expansion takes each ViewItem's `label` from its list or form entry, not from the container. Also in the diff: the regenerated `state-counts/app.md` and `state-counts/connector.md`. Four hand-written sentences that these flips made false are also corrected: the `app` and `connector` README Notes cells, the `connector.actions.inputSchema` note, and the `app.areas` container note. ## Acceptance notes - `check:liveness` passes at `41b5470514`: `connector` is 31 live, 1 planned, 23 dead, and `app` is 50 live, 8 dead, 1 planned. The shard sum is 960 live and 122 dead. - The pin verdicts come from a static call-graph closure at `db11afd4967`. No Studio was booted. --- _Generated by [Claude Code](https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4b45afa commit 15b586d

8 files changed

Lines changed: 40 additions & 18 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
Liveness ledger: `connector.actions.description`, `connector.actions.outputSchema` and `app.areas.description` are now `live`, not `dead`. Studio reads each of them at the `.objectui-sha` pin, and each row cites that reader and its producer. Ledger data, two README Notes cells and the regenerated count shards only. ⛔ No schema, parse, `.describe()` or accept-set change.
6+
7+
The ledgers ship inside this package (`files[]` includes `liveness`), and `@objectstack/lint` reads them to decide which authored keys draw an advisory warning. None of the three rows sets `authorWarn`, so the set of warnings does not change.
8+
9+
- `connector.actions.description`: the flow designer's Action picker on a `connector_action` node shows each action's description beside its label.
10+
- `connector.actions.outputSchema`: the flow designer offers a `connector_action` node's downstream references from the top-level `properties` of its action's `outputSchema`.
11+
- `app.areas.description`: the Studio app preview lists each area, with its description beneath it when one is authored.
12+
- Both connector rows are fed from the plugin and provider door, as their sibling `actions.*` rows are: the `actions` an author writes on a metadata connector entry never reach the registry the designer reads.
13+
- The regenerated count shards: `connector` has 31 live and 23 dead (was 29 and 25), and `app` has 50 live and 8 dead (was 49 and 9).

‎packages/spec/liveness/README.md‎

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

‎packages/spec/liveness/app.json‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,12 @@
220220
"note": "2026-09-27 (#20146): REPOINTED off objectui's `AppSidebar.tsx` — deprecated, never mounted (the console renders `UnifiedSidebar`), and removed from objectui main by objectui PR #10617 — to the mounted reader(s) above, each re-read at the `.objectui-sha` pin f8a9d0fb and unchanged at objectui main fb91ac9b0."
221221
},
222222
"description": {
223-
"status": "dead",
224-
"verifiedAt": "2026-08-01",
225-
"note": "display annotation no surface renders. Benign — docs-shaped, kept, not warned (hook.label precedent). VERDICT RE-TESTED AND UPHELD 2026-08-10 (#7427) under the previews ruling (#7131; README, 'Designer previews count as consumers'): 'no surface renders' is exactly the claim that ruling put back on the table for display keys, so it was measured instead of trusted. At objectui @e9ab52f9 AppPreview IS registered (previews/index.ts:40) and reachable (ResourceEditPage.tsx:949), and it contains ZERO occurrences of `areas` — it reads the app label at AppPreview.tsx:193 and walks `navigation` items, never the area collection. The area-level description reaches no human there."
223+
"status": "live",
224+
"verifiedAt": "2026-09-30",
225+
"evidenceScope": "cross-repo",
226+
"evidence": "objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/previews/AppPreview.tsx#readAreas (resolves each area's `description` through `resolveI18nLabel` in the designer locale; unauthored stays undefined and draws nothing); objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/previews/AppPreview.tsx#AppPreview (draws it under the area's label in the preview's Areas list, in read and design mode)",
227+
"producer": "objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/previews/index.ts#registerBuiltinPreviews (registers AppPreview for `app`); objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx#MetadataResourceEditPageImpl (`app` registers no custom EditPage, so the generic edit route resolves `getMetadataPreview('app')` and hands it the draft); framework: packages/rest/src/meta-item-read-gate.ts#filterAppForUserWithReason (the served app keeps every key of each area it serves)",
228+
"note": "RE-GRADED dead → live 2026-09-30 (#20299) under the #7131 previews ruling (README, 'Designer previews count as consumers'): for a display key, being shown to a human is the whole claimed effect. objectui#11027, read at the `.objectui-sha` pin db11afd4967, added the Areas list; the superseded note measured AppPreview at @e9ab52f9 with zero `areas` reads. UNCHANGED: still docs-shaped, deliberately KEPT (ADR-0033) and not authorWarn'd."
226229
},
227230
"navigation": {
228231
"status": "live",
@@ -232,7 +235,7 @@
232235
"note": "the active area's tree replaces the top-level navigation. Since #4722 area trees ARE server-side gated: filterAppForUser (packages/rest/src/rest-server.ts:1870) runs the SAME filterNav over every `areas[].navigation`, so an item's `requiredPermissions` / `requiresService` is enforced identically in both trees and a gated entry (with its objectName/pageName/componentRef target) never reaches the browser. An area emptied BY the gate is dropped, mirroring the top-level group collapse; an area authored empty is passed through. Still client-only at both levels: `visible` (CEL — needs a bound user context the read layer lacks) and `requiresObject`. The area-LEVEL keys stay retired (#4651) — this enforces the items inside, not a revived area gate. 2026-09-27 (#20146): REPOINTED off objectui's `AppSidebar.tsx` — deprecated, never mounted (the console renders `UnifiedSidebar`), and removed from objectui main by objectui PR #10617 — to the mounted reader(s) above, each re-read at the `.objectui-sha` pin f8a9d0fb and unchanged at objectui main fb91ac9b0. The `AppSchemaRenderer` leg is unchanged by this re-point."
233236
}
234237
},
235-
"note": "Drilled because the gating keys diverged sharply from the live identity/tree keys — and they are gone: `visible` and `requiredPermissions` were RETIRED in 17.0.0 (#4651), rows DELETED because NavigationAreaSchema is strict, so the keys left the walked shape and retained rows would report ORPHAN. Keep drilling: `description` is the surviving benign dead key, and the drill is what would catch a new gate being added here."
238+
"note": "Drilled because the gating keys diverged sharply from the live identity/tree keys — and they are gone: `visible` and `requiredPermissions` were RETIRED in 17.0.0 (#4651), rows DELETED because NavigationAreaSchema is strict, so the keys left the walked shape and retained rows would report ORPHAN. Keep drilling: the drill is what would catch a new gate being added here."
236239
},
237240
"contextSelectors": {
238241
"children": {

‎packages/spec/liveness/connector.json‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,28 @@
8585
"note": "Display-shaped and settled by the #7131 split — the designer's action picker IS the claimed effect. REQUIRED, so there is no empty state."
8686
},
8787
"description": {
88-
"status": "dead",
89-
"verifiedAt": "2026-09-17",
90-
"note": "Projected onto the wire and read by nobody. `engine.ts#getConnectorDescriptors` copies `description: a.description` into the `GET /api/v1/automation/connectors` payload, and no consumer in either repo reads it back: objectui's three connector-descriptor consumers take `name`/`label`/`origin` (`connectorsToOptions`), `key`/`label` (`connectorActionsToOptions`) and `key`/`inputSchema` (`connectorActionInputSchema`), and nothing in this repo reads a projected action's description. The lit control for that scan is `inputSchema` in the same projection, which IS read (see that row). Being on a machine-readable surface is not a consumer — the `view.label` precedent."
88+
"status": "live",
89+
"verifiedAt": "2026-09-30",
90+
"evidenceScope": "cross-repo",
91+
"evidence": "packages/services/service-automation/src/engine.ts#getConnectorDescriptors — `description: a.description` on each projected action, the `GET /api/v1/automation/connectors` payload; objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx#connectorActionsToOptions (a non-blank string `description` becomes the action option's `hint`, fed by `useConnectorActionOptions` off that payload); objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx#ReferenceCombobox (draws each option as `label — hint` in the `connector_action` node's Action picker)",
92+
"producer": "packages/connectors/connector-slack/src/slack-connector.ts#createSlackConnector — a `description` on each of its three actions; packages/connectors/connector-openapi/src/openapi-connector.ts#createOpenApiConnector — `description: op.description`; packages/connectors/connector-mcp/src/mcp-connector.ts#createMcpConnector — the server's tool description verbatim; objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts#FLOW_NODE_CONFIG (the `connector_action` node's `actionId` field is a `connector-action` reference, which is what mounts that picker). Same two-door caveat as `actions.key`.",
93+
"note": "RE-GRADED dead → live 2026-09-30 (#20287): objectui#11028, read at the `.objectui-sha` pin db11afd4967, shows it beside the action's label in the flow designer's Action picker. Display-shaped, so the picker IS the claimed effect (the #7131 split), as for `actions.label`. The superseded note — no consumer in either repo reads it back — was true until objectui#11028."
9194
},
9295
"inputSchema": {
9396
"status": "live",
9497
"verifiedAt": "2026-09-17",
9598
"evidenceScope": "cross-repo",
9699
"evidence": "packages/services/service-automation/src/engine.ts#getConnectorDescriptors — `inputSchema: a.inputSchema` on the projected action; objectui @dda8f3815 packages/app-shell/src/views/metadata-admin/inspectors/connector-input-fields.ts#connectorActionInputSchema finds the committed action in that payload and returns its `inputSchema`, and `FlowNodeInspector.tsx` types the connector node's whole Input section from it (`connectorInputFields(connectorActionInputSchema(...))`, objectui #4305) — an action that declares none falls back to the generic key/value repeater, which is the observable difference.",
97100
"producer": "packages/connectors/connector-mcp/src/mcp-connector.ts — the MCP tool's own JSON Schema is passed straight through ('The MCP inputSchema is already JSON Schema'); packages/connectors/connector-openapi/src/openapi-connector.ts derives it from the operation's parameters. Same two-door caveat as `actions.key`.",
98-
"note": "The one action key with a structural (not display) consumer, and it is cross-repo: the designer builds a typed form from it. Declared `z.record(z.string(), z.unknown())` — JSON Schema by convention, unvalidated here — so it has no child shape and nothing rides on a blanket verdict."
101+
"note": "A structural (not display) consumer, cross-repo like `outputSchema`'s: the designer builds a typed form from it. Declared `z.record(z.string(), z.unknown())` — JSON Schema by convention, unvalidated here — so it has no child shape and nothing rides on a blanket verdict."
99102
},
100103
"outputSchema": {
101-
"status": "dead",
102-
"verifiedAt": "2026-09-17",
103-
"note": "The twin of `inputSchema`, projected the same way and consumed by nothing — which is exactly what makes this row falsifiable rather than a guess. `engine.ts#getConnectorDescriptors` publishes `outputSchema: a.outputSchema`; the census over both repos finds no reader, while the identically-projected `inputSchema` one line above returns objectui's `connectorActionInputSchema` in the same scan. A flow node's downstream references are typed from the RUN's actual output (`nodeOutputRefs`), not from this declaration. ⛔ Not an ADR-0049 sweep candidate on this reading: the honest repair is to type the node's output refs from it, which is a feature decision, not a deletion."
104+
"status": "live",
105+
"verifiedAt": "2026-09-30",
106+
"evidenceScope": "cross-repo",
107+
"evidence": "packages/services/service-automation/src/engine.ts#getConnectorDescriptors — `outputSchema: a.outputSchema` on each projected action, the `GET /api/v1/automation/connectors` payload; objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts#nodeOutputRefs (a committed `connector_action` node offers one `nodeId.key` reference per top-level `properties` key of its action's `outputSchema`, through `connectorActionOutputSchema` and `connectorActionOutputKeys`; no schema, no references); objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts#resolveFlowScope (hands those references to every downstream node's and edge's data picker)",
108+
"producer": "objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/connector-input-fields.ts#useConnectorRegistry (reads that payload); objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.tsx#FlowNodeInspector and objectui @db11afd4967: packages/app-shell/src/views/metadata-admin/inspectors/FlowEdgeInspector.tsx#FlowEdgeInspector (each reads the registry when the flow holds a committed connector action and passes it to `useFlowScope` — the input the read depends on); framework: packages/connectors/connector-slack/src/slack-connector.ts#createSlackConnector — `outputSchema: slackOutputSchema()` on every action; packages/connectors/connector-openapi/src/openapi-connector.ts#buildOutputSchema; packages/connectors/connector-mcp/src/mcp-connector.ts#createMcpConnector — the tool's `outputSchema` when the server declares one. Same two-door caveat as `actions.key`.",
109+
"note": "RE-GRADED dead → live 2026-09-30 (#20287): objectui#11028, read at the `.objectui-sha` pin db11afd4967, types a connector node's downstream references from it — the repair the superseded note named. The engine stores each top-level key of a node's `output` as `nodeId.key`, so the offered references are the ones a run writes. The designer offers them and stops flagging them as out of scope; nothing validates a reference against the schema."
104110
},
105111
"effect": {
106112
"status": "live",

‎packages/spec/liveness/permission.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,13 @@
170170
"status": "dead",
171171
"evidenceScope": "cross-repo",
172172
"verifiedAt": "2026-08-10",
173-
"note": "CORRECTED 2026-07-30 (was live with no evidence): no consumer in either repo. VERDICT RE-TESTED AND UPHELD 2026-08-10 (#7427) against the maintainer ruling that a designer preview rendering a key to a human is a runtime consumer (2026-08-10, #7131; README, 'Designer previews count as consumers'). This row is the closest structural twin of the four rows that ruling re-graded — a display `label` marked dead — so it was measured rather than assumed, and it comes out the other way. THE MEASUREMENT, at objectui @e9ab52f9: PermissionPreview IS registered for `permission` (previews/index.ts:71) and IS reachable (ResourceEditPage.tsx:949), so the preview lookup runs; but PermissionPreview.tsx:111 reads `rowLevelSecurity` only as an ARRAY and PermissionPreview.tsx:164 renders `${rls.length} RLS rules` — a COUNT. It never indexes a policy, never reads `.label`, and no policy field reaches a human through it. The 2026-07-30 wording 'PermissionPreview counts them' was exact, and counting is not rendering: the ruling turns on the VALUE being shown to a person, which is precisely what a length does not do. The other measured surface is PermissionAdvancedFacets.tsx:192-193 (reads `draft.rowLevelSecurity`, strips retired keys) and :264 (writes it back) — an authoring FORM, the 'authoring surface echoing input' the 2026-07 correction rejected, and the new ruling names previews, not edit forms. So both halves of the original closure survive it. Benign display metadata — deliberately NOT authorWarn'd. To re-open this row, the thing to look for is a preview that renders the policy's label text, not another surface that counts policies."
173+
"note": "No reader reaches it, measured at objectui @db11afd4967. PermissionPreview.tsx#readPolicies reads each policy's `label`, and `PermissionPreview` draws it in its Row-Level Security list, but no route mounts that preview for `permission`. ResourceEditPage.tsx#MetadataResourceEditPage hands every non-create `permission` item to the custom EditPage that services/builtinComponents.tsx registers, `PermissionMatrixEditPage`. That page renders no preview, and its RLS form `PermissionAdvancedFacets` reads no policy label. Create mode previews only object, report and dataset. The other `getMetadataPreview` callers (`EmbeddedItemEditor`, `StudioDesignSurface`, the dev-only preview gallery) never open a `permission`. A preview no route mounts is a read point that never runs (README, 'Designer previews count as consumers'). Benign display metadata, deliberately NOT authorWarn'd. To re-open: a mounted surface that draws the policy's label."
174174
},
175175
"description": {
176176
"status": "dead",
177177
"evidenceScope": "cross-repo",
178178
"verifiedAt": "2026-08-10",
179-
"note": "CORRECTED 2026-07-30 (was live with no evidence): same closure as label. RE-TESTED AND UPHELD 2026-08-10 (#7427) with `label`, same measurement at objectui @e9ab52f9 — the permission preview counts RLS policies (PermissionPreview.tsx:164) and renders no field of any individual policy. Benign — not authorWarn'd."
179+
"note": "Same closure as `label`, at objectui @db11afd4967: `PermissionPreview` draws each policy's `description` beneath its row, but no route mounts it for `permission`. `PermissionMatrixEditPage` takes the item, and its RLS form reads no description. Benign, not authorWarn'd."
180180
},
181181
"object": {
182182
"status": "live",

‎packages/spec/liveness/state-counts/app.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ committed anywhere: `check:liveness` sums the shards when it reads them.
1212

1313
| Type | live | exp | elsewhere | dead | planned | classified |
1414
|---|---|---|---|---|---|---|
15-
| `app` | 49 | 0 | 0 | 9 | 1 | 59 |
15+
| `app` | 50 | 0 | 0 | 8 | 1 | 59 |

‎packages/spec/liveness/state-counts/connector.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ committed anywhere: `check:liveness` sums the shards when it reads them.
1212

1313
| Type | live | exp | elsewhere | dead | planned | classified |
1414
|---|---|---|---|---|---|---|
15-
| `connector` | 29 | 0 | 0 | 25 | 1 | 55 |
15+
| `connector` | 31 | 0 | 0 | 23 | 1 | 55 |

0 commit comments

Comments
 (0)