Skip to content

Commit 013f97d

Browse files
docs(spec): record_related names its row placement inside a parent record (#20948)
Fixes #20937 Clause-②: no ## Pin measurement: the console at this repo's `.objectui-sha` places no `record_related` action on related-list rows Read at objectui `db11afd4967cd9d39381c5e21dc2deec9d706204`, the pin on `origin/main` `31c39964fc`, with `git grep` against that commit (never objectui `main`). `git grep -w record_related` answers 12 lines in 7 files. The control leg is the same command for `list_item` in `packages/app-shell/src/views/RelatedRecordActionsBridge.tsx`: 4 lines, so the read reaches the pinned tree. - **The related list's default placement never asks for `record_related`.** `RelatedRecordActionsBridge.deriveActions` (`:190`, called at `:431` and `:442`) places the child object's `list_item` actions on each row and its `list_toolbar` actions in the header. `record_related` appears nowhere in that file. - **None of the 12 hits is a related-list placement:** - Studio designer, 9 lines: i18n labels (4), the inspector's option map (1), the `record:quick_actions` page-block `location` option (`block-config.ts:536`), and `ActionPreview.tsx:832-833` (2). The preview draws `record_related` as a button in a section **header**, the toolbar reading this card replaces. - `action-bar.tsx:30` (docblock) and `useActionEngine.test.ts` (2): the generic location filter. An author who places a `record:quick_actions` / `action:bar` naming `location: 'record_related'` gets that bar where they put it. Nothing places the location by default. - `ROADMAP.md:1370`: prose. - The other spelling, `record_related_list` (`containers.tsx:525`, `RelatedList.tsx:1632` and one test), is a component type name, not this location. So the new words state the **contract** only, and they do not say the pinned console does it. The two docs rows describe where a button renders, so each says the console does not place it on those rows yet. They follow the docs corpus's own wording for this state ("declared, not yet applied" in `content/docs/ui/translations.mdx`) and carry no tracker number. ## What changed - `packages/spec/src/ui/action.zod.ts`: the `record_related` line of the `ACTION_LOCATIONS` docblock, in triage's words. It is now a per-row action on each row of a related list shown inside a parent record, in that parent's context only. Unlike `list_item` (every row wherever the object is listed), it never surfaces on the object's own list views. JSDoc only: the enum, its accept set and the `global_nav` refusal are byte-identical. - `content/docs/ui/actions.mdx` and `content/docs/protocol/objectui/actions.mdx`: the `record_related` row of each location table says the same, plus "Declared, not yet placed". - `docs/qa/platform-checklist/areas/records-forms.json`, item `records-forms.action-location-matrix`: the variant now reads "showcase_log_time on each row of the related-list section inside a record (the Tasks related list on a showcase_project record), and on no row of the showcase_task list view". **One addition beyond the claimed line:** the same item's `revision` goes 5 → 6, with a `history` entry. The checklist README's lifecycle rule for a changed item is "edit the fields, bump `revision`, append a `history` entry", because run records pin the revision they ran against. The entry also records that a run against the pinned console scores this variant as a missing placement, and that this is the correct verdict. - `.changeset/20937-record-related-row-placement.md`: `@objectstack/spec` `patch`, because `src/**/*.zod.ts` ships in the package's `files[]`. **No generated file moves.** `ActionLocationSchema` has no `.describe()`, and the docblock is not projected. `check:generated` reports "All 15 generated artifacts are up to date", including `check:docs` ("227 generated files in sync"). `content/docs/references/ui/action.mdx` lists only the allowed values for `ActionLocation`. ## Verification, at `5e744bd8bf` - `pnpm --filter @objectstack/spec build`, then `check:generated`: all 15 up to date. - `pnpm --filter @objectstack/spec run typecheck`: exit 0, including `check:scripts-typecheck` and `check:test-typecheck`. - `pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2`: 584 test files passed, 17190 tests passed, 1 todo. - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 100 commands. Each exit code was captured to a file before any pipe. `--ran` reconciled: "100 derived famil(ies) accounted for — 99 run, 1 NOT-MEASURED". - 98 exit 0. Five of those first refused with `PREREQUISITE NOT MET` (lint, formula, client-react and objectql not built). They exited 0 after `turbo run build` of those four packages. - `pnpm check:platform-checklist` exits 1 with 2 problems: `coverage.json · picklist: UNCLASSIFIED` and an ABSENT SYMBOL in `areas/identity-auth.json`. Both are **present at the base** `31c39964fc`: the validator run in a detached worktree at that commit printed the same two problems. The edited item is not among them. - NOT MEASURED: `pnpm check:dual-build-cjs-loads`. It needs every workspace package built (86 `dist/` directories absent), and this diff changes one JSDoc comment. CI's `Lint & Repo Gates` runs it. - The six roster families the derivation marks under these paths also exit 0: `check-changeset-fixed`, `check:authz-resolver`, `check:error-code-casing`, `check:filter-alias-parity`, `check:meta-url-spelling` and `check:spec-changes`. - **Lint, a declared narrowing.** ① Population, read from eslint's own config (`isPathIgnored` / `calculateConfigForFile`): of the 5 touched files, only `action.zod.ts` is linted, and the `.mdx`, `.json` and `.md` files are outside it. ② `--format json` over all 5 lists 1 file: 0 errors, 0 warnings. ③ `eslint.config.mjs` enables no type-aware linting (no `parserOptions.project` or `projectService`), so this diff cannot move any untouched file's verdict. ## The two nearby texts the dispatch asked to have measured (not changed here) - **(a) The `GLOBAL_NAV_RETIRED` refusal** (`action.zod.ts:609-622`) says "Place the action on a location a renderer serves (… `record_related` …)". At the pin this is **true only in the weak sense**. The generic `action:bar` / `record:quick_actions` filter renders a `record_related` action if an author places such a bar with that location. No surface places it by default. It becomes plainly true when the pin carries the renderer half. Changing it now would reword shipped refusal text twice, so I recommend leaving it. - **(b) The `action.locations` row in `packages/spec/liveness/action.json`** says the "VALUE SET was audited per-member", which implies every remaining member is served. For `record_related` at the pin that overstates: no default placement exists. It would take a note-only edit of that row: no status or count change, but a `patch` changeset, because `liveness` ships. Or leave it until the renderer half is at the pin. ## Acceptance notes - `skills/objectstack-ui/rules/actions.md:11` (the published skill) carries the same old wording: "Related-list section inside a record". `skills/**` is a Tier H surface and outside this card's surface. Carrier: none; it needs its own docs PR. - `packages/lint/src/validate-action-locations.ts:157`: the `action-no-placement` hint lists `record_related` among the surfaces to add, which is the same weak-sense claim as (a). - objectui's Studio `ActionPreview.tsx:832-833` (at the pin) draws `record_related` as a section-header button, the toolbar reading. It is a candidate for the renderer half's scope. That card's scope lists the host bridge, the authored channel, visibility and pins, not the Studio preview. - When the objectui pin moves past the renderer half's landing, the "Declared, not yet placed" clause comes out of both docs rows. Carrier: that pin bump. - `origin/main` advanced to `f80e2a6dad` after the branch point. It touches none of these five paths or `packages/spec`, so it was not merged in. --- _Generated by [Claude Code](https://claude.ai/code/session_018fxqvRJW12TaHC7DUQ89Y6)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5ad8488 commit 013f97d

5 files changed

Lines changed: 23 additions & 5 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
docs(spec): the `record_related` action location's docblock names its placement, each row of a related list inside a parent record, instead of "a related list section" (#20937)
6+
7+
Clause-②: no
8+
9+
Only the `record_related` line of the `ACTION_LOCATIONS` docblock in `src/ui/action.zod.ts` changes. It now states the contract a renderer implements: a per-row action on each row of a related list shown inside a parent record, in that parent's context only. Unlike `list_item`, which surfaces on every row wherever the object is listed, it never surfaces on the object's own list views. The old words, "actions on a related list section", could be read as the section's toolbar. `ACTION_LOCATIONS` and `ActionLocationSchema` are unchanged: the same six values parse, and no `.describe()` string, export or runtime behaviour moves. The console's placement of `record_related` actions on related-list rows ships separately.

‎content/docs/protocol/objectui/actions.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ The `locations` array declares where an action surfaces. The canonical enum (`AC
266266
| `list_item` | Per-row action on a list/grid row |
267267
| `record_header` | Primary actions in the record-detail title bar |
268268
| `record_more` | Overflow ("More" / ⋯) menu on a record |
269-
| `record_related` | Actions on a related-list section inside a record |
269+
| `record_related` | Per-row action on each row of a related-list section inside a parent record, in that parent's context only — unlike `list_item`, never on the object's own list views. Declared, not yet placed: the console does not render it on those rows yet |
270270
| `record_section` | Actions inside a body section/tab of a record |
271271

272272
```yaml

‎content/docs/ui/actions.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ is collected, then the body runs with those values as its `input`.
273273
| `list_item` | Per-row menu in list views |
274274
| `record_header` | Record page header |
275275
| `record_more` | Record page overflow ("…") menu |
276-
| `record_related` | Related-list sections |
276+
| `record_related` | Each row of a related list inside a parent record — there only, never on the object's own list views (unlike `list_item`). Declared, not yet placed: the console does not draw it on those rows yet |
277277
| `record_section` | Named action bars on record pages |
278278

279279
Surfaces can also reference actions **by name**:

‎docs/qa/platform-checklist/areas/records-forms.json‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@
14991499
"title": "Action buttons surface at exactly their declared locations — list toolbar, list row, record header/more/related/section — and each dispatches for real",
15001500
"since": "v15",
15011501
"status": "active",
1502-
"revision": 5,
1502+
"revision": 6,
15031503
"priority": "P1",
15041504
"surface": "browser",
15051505
"personas": [
@@ -1520,7 +1520,7 @@
15201520
"list_item — showcase_quick_view / showcase_mark_done in the row menu",
15211521
"record_header — showcase_mark_done / showcase_log_time in the detail title bar",
15221522
"record_more — showcase_open_docs / showcase_recalc_selection under the ⋯ overflow",
1523-
"record_related — showcase_log_time on the related-list section",
1523+
"record_related — showcase_log_time on each row of the related-list section inside a record (the Tasks related list on a showcase_project record), and on no row of the showcase_task list view",
15241524
"record_section — showcase_mark_done / showcase_log_time in the Task Detail quick-actions bar (record:quick_actions resolves through the location filter)",
15251525
"empty-locations semantics probe — an action with NO locations key renders on NO surface, and `locations: []` likewise (objectui#3142 collapsed the renderers onto one membership predicate, `actionRendersAt`; placement is a declaration, which is why recalc_selection has to name record_more)"
15261526
],
@@ -1616,6 +1616,12 @@
16161616
"date": "2026-08-21",
16171617
"change": "recorded on the item that its automation is pinned exclusively in the objectui repo and is therefore neither runnable nor pin-evidenced from this checkout — one of 23 items in that position, each of which every sweep had been re-deriving from scratch. The knownGap names the two honest ways to score it (hand-drive it as a manual run, or run the pin in an objectui checkout and cite the revision) and forbids the third: treating the `automated` field itself as coverage. The protocol and the exclusive-vs-mixed distinction live once in RUNNER.md; this line is the pointer (#10236 A5)",
16181618
"ref": "#10236"
1619+
},
1620+
{
1621+
"revision": 6,
1622+
"date": "2026-09-30",
1623+
"change": "re-worded the record_related variant to the location's placement as the spec's ACTION_LOCATIONS docblock now states it (#20937): a per-row action on each row of a related list inside a parent record, in that parent's context only — so showcase_log_time is expected on the rows of the Tasks related list on a showcase_project record, and on no row of the showcase_task list view. It used to read 'on the related-list section', which a runner could score against the section's toolbar. The console at this repo's objectui pin places no record_related action on related-list rows yet (its related list puts list_item actions on rows and list_toolbar actions in the header; the renderer half is objectui#11270), so a run against that pin records this variant as a missing placement — the correct verdict, not a checklist defect",
1624+
"ref": "#20937"
16191625
}
16201626
],
16211627
"enumSource": {

‎packages/spec/src/ui/action.zod.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,10 @@ const GLOBAL_NAV_RETIRED =
634634
* - `list_item` — per-row action on a list/grid row (Salesforce row-level menu).
635635
* - `record_header` — primary actions in the record-detail title bar.
636636
* - `record_more` — overflow menu under the "More" / ⋯ button on a record.
637-
* - `record_related` — actions on a related list section inside a record.
637+
* - `record_related` — per-row action on each row of a related list shown inside
638+
* a parent record, in that parent's context only. Unlike
639+
* `list_item` (every row wherever the object is listed), it
640+
* never surfaces on the object's own list views.
638641
* - `record_section` — actions surfaced inside a body section/tab of a record
639642
* (e.g. a Security tab grouping change-password, 2FA, etc.).
640643
*

0 commit comments

Comments
 (0)