Repository navigation
Commit 305e7fc
docs(platform-objects): name the slotted page that declares the org record tab strip (#17750)
Part of #16270
- **Clause-②: no** — this PR puts no new key on any published payload.
## The card's premise is false, and that is the deliverable
The card asked for a measurement first: three documents assert that the
organization record page opens on a **Members** tab with Invitations and
Teams beside it, while `packages/platform-objects/src/identity/`
declares no `Field.relatedList` prominence key. It framed a two-way
disjunction — reading 1, the metadata is short three `relatedList:
'primary'` declarations; reading 2, the three documents are stale — and
the triage admitted the card on the grounds that **both branches are
defects**.
**Neither branch holds.** The tab strip is declared metadata. It is
simply not declared by the key the measurement looked for, and not in
the directory it looked in.
`packages/platform-objects/src/pages/sys-organization.page.ts` exports
`SysOrganizationDetailPage`: a `type: 'record'`, `kind: 'slotted'`,
`isDefault: true` page for `sys_organization` whose `slots.tabs`
override carries exactly three `record:related_list` tabs — **Members,
Invitations, Teams, in that order**.
`packages/plugins/plugin-auth/src/auth-plugin.ts` hands it to the
runtime as `pages: [SysOrganizationDetailPage, SysUserDetailPage]`, and
its own comment there already said so: *"sys_organization gets a Members
/ Invitations / Teams tab strip"* — a fourth document making the claim,
and the only one that named the mechanism.
The renderer half, read from objectui at the sha this repo pins
(`.objectui-sha` = `53ded82bf7`):
- `packages/plugin-detail/src/synth/buildDefaultPageSchema.ts` — when
the assigned page supplies a `tabs` slot, the synthesizer pushes that
authored node and **never calls `buildDefaultTabs`**. The authored strip
replaces the synthesized one outright, so Members is at index 0.
- The same file's `buildDefaultTabs` always seeds `items[0]` with
**Details**. So even under reading 1 — three `relatedList: 'primary'`
declarations added — tab 0 would have been *Details*, never *Members*.
Reading 1 could not have produced the documented surface.
- `packages/app-shell/src/utils/deriveRelatedLists.ts` sets `isPrimary`
from `fieldDef.relatedList === 'primary'`, exactly as the card quoted.
That key is a different mechanism, and while the `tabs` slot is present
it would not move this page at all.
`sys-organization.page.ts` was already in the tree at `77781151d`, the
commit the card measured against (verified through the contents API at
that ref: HTTP 200, 4606 bytes). The zero was real; the inference from
it was not.
## What this PR changes — prose only
No metadata. No behaviour. The three documents that assert the tab order
now name the page that declares it, so the next reader does not repeat
the measurement:
| file | change |
|---|---|
| `packages/platform-objects/src/identity/sys-member.object.ts` | the
`invite_user` mirror's rationale gains a note naming
`../pages/sys-organization.page.ts` as the declaring page, and stating
that `relatedList` is a different mechanism absent from this directory |
| `packages/platform-objects/src/identity/invite-entry-toolbar.test.ts`
| the file header — the stated premise of the whole pin — gains the same
pointer |
| `docs/qa/platform-checklist/areas/identity-auth.json` |
`identity-auth.org-membership-team-management` gains one `source` entry,
plus the `revision` 2 to 3 and `history` bump its ledger requires |
**What a grader will now do differently** (the checklist is what QA
grades, so this is stated plainly): nothing about the grade changes. The
item's `steps`, `acceptance` clauses, their oracles and `verify` text,
and the `negative` list are byte-unchanged — the same screenshot, the
same three tabs, the same FAIL condition for the Organization nav
landing on the raw list. What is added is a `source` entry, which is a
pointer a grader reads to locate the surface, and it tells them one new
thing: if the page renders **Details plus a stacked `Related` tab**
instead of the three, that means `SysOrganizationDetailPage` failed to
load — it does not mean the clause was wrong. That reading was not
available before, and it is the reading this card was filed for lack of.
## Verification
| check | result |
|---|---|
| `pnpm lint` (repo-wide, `eslint . --no-inline-config`) | exit 0, 2m05s
— full run, no narrowing claimed |
| `pnpm --filter @objectstack/platform-objects test` | exit 0 — 39
files, 561 tests passed |
| `pnpm --filter @objectstack/platform-objects typecheck` | exit 0 |
| `pnpm --filter "@objectstack/platform-objects..." build` | exit 0
(dependency closure) |
| `pnpm check:platform-checklist` | `OK — 15 areas, 264 items; symbol
anchors: 633/633 resolved` |
| `pnpm check:nul-bytes` · `check:doc-authoring` ·
`check:page-declaration-shape` · `check:published-files` ·
`check:test-source-alias` · `check:cross-package-test-inputs` ·
`check:type-check-coverage` · `check:comment-mask-adoption` ·
`check:comment-mask-corpus` · `check:keyed-text-bounds` ·
`check:closing-keyword-parity` | each exit 0 |
| `check-empty-changeset` · `check-changeset-no-major` ·
`check-adr-0087-registration`, each `--base origin/main` | each exit 0 |
| `check-partof-closing-keyword` with this body and this branch's commit
list | exit 0 |
Every exit code above was captured before any pipe (`cmd > file 2>&1;
EXIT=$?`), and the two lock-held runs are quoted from the wrapper's own
`VERDICT command-exit` line.
**Ablation — the checklist gate's new anchor really is checked.** With
the new `source` entry's symbol renamed on disk to
`SysOrganizationDetailPageXX` (injected text present 1, original present
0, both counted with `grep -oF`), `check-platform-checklist` went to
exit 1 with `ABSENT SYMBOL ... is not in
packages/platform-objects/src/pages/sys-organization.page.ts outside its
comments`. Restored from a pristine copy and proved byte-identical by
`git hash-object` (`168dca14` before and after). The green above is
therefore a reading, not a gate that judged nothing.
**Why a changeset and not the publishes-nothing exemption.**
`@objectstack/platform-objects` ships `files: ["dist", ...]`, and its
`src` comments reach `dist`: after the build, the new comment text
appears **4** times under `packages/platform-objects/dist`, with an
exported symbol (`SysMember`, 16 occurrences) as the positive control
and the edited test file's header absent at **0**. Published bytes move,
so a `patch` changeset is owed —
`.changeset/16270-org-record-tab-strip-provenance.md`, in the tree's
issue-scoped spelling.
**Declared narrowing.** `scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 62 runnable commands for this change
set; the table above is a subset chosen by what this diff can move, and
the rest is CI's farm. The derivation also warned that this branch's
base is 3 commits behind `origin/main` and that one file it derives from
(`scripts/check-regen-pending.mjs`) changed across that range;
re-deriving after `git fetch origin main` produced a byte-identical
command list.
## Why `Part of` and not a closing keyword
This PR carries the measurement and repairs the discoverability gap, but
it does not discharge the card.
`docs/adr/0133-org-management-open-basics.md`, under *"What this record
does not decide"*, now states something false — that the tab claim is
*"declared by none of its metadata"* and that the ordering is *"either
an emergent property of the renderer or a claim that has gone stale"*.
`docs/adr/**` is a governed surface, outside this dispatch's declared
file face, and its correction is the maintainer's call. Recorded as a
finding in the round report rather than ridden in here.
## 验收备注
- **objectui is read-only and was read, not assumed.** All renderer
readings are from the sha this repo pins (`53ded82bf7`), taken with `git
show 53ded82bf7:path` in the sibling checkout. That checkout's own HEAD
is `3fbdd4a2d` on an unrelated branch; nothing there was edited.
- **A second, genuinely different surface exists and is easy to confuse
with this one.** objectui's console carries a hand-written organization
management area at `/organizations/:slug`
(`packages/app-shell/src/console/organizations/manage/OrganizationLayout.tsx`),
whose tabs are **Members / Invitations / Settings** with an index
redirect to `members`. It is reached from a "Manage" button on the
organizations list, not from Setup's `nav_organization`, and it has no
Teams tab. Noted so the next reader does not measure that surface and
grade this one. Not filed: no defect, just a collision of names.
- **The checklist item has never been run.**
`docs/qa/platform-checklist/runs/` contains only `README.md`, so
`identity-auth.org-membership-team-management` has no run record and its
tab assertion had never been executed against a live console. Noted, not
filed.
- **The running-app measurement the triage asked for was not
performed.** It is no longer decisive — the static evidence now names
the declaring page, the registration site and the renderer branch that
honours it — but it remains the only way to observe the rendered strip.
Stated here rather than implied.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent aaacf1d commit 305e7fc
4 files changed
Lines changed: 73 additions & 2 deletions
File tree
- .changeset
- docs/qa/platform-checklist/areas
- packages/platform-objects/src/identity
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
747 | 747 | | |
748 | 748 | | |
749 | 749 | | |
750 | | - | |
| 750 | + | |
751 | 751 | | |
752 | 752 | | |
753 | 753 | | |
| |||
822 | 822 | | |
823 | 823 | | |
824 | 824 | | |
| 825 | + | |
825 | 826 | | |
826 | 827 | | |
827 | 828 | | |
| |||
831 | 832 | | |
832 | 833 | | |
833 | 834 | | |
834 | | - | |
| 835 | + | |
| 836 | + | |
835 | 837 | | |
836 | 838 | | |
837 | 839 | | |
| |||
Lines changed: 12 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
10 | 22 | | |
11 | 23 | | |
12 | 24 | | |
| |||
Lines changed: 12 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
51 | 63 | | |
52 | 64 | | |
53 | 65 | | |
| |||
0 commit comments