Skip to content

Commit 230e494

Browse files
docs(qa): studio-authoring.picklist-bound-select, the acceptance item of objectui#10202 (#21969)
Fixes #21957 Clause-②: no ## What changes `docs/qa/platform-checklist/areas/studio-authoring.json` gains one item, `studio-authoring.picklist-bound-select`: rev 1, `since: v17.7`, P2, surface `mixed`. It is appended after `studio-authoring.doc-on-app-menu`. It is part (d) of the director ruling 6006062645 on objectui#10202 (letter A′). No other item changes, no item index moves, and no other file is touched. ## Changes from the card's draft, and why 1. **`since` is `v17.7`, not `v17.6`.** - 17.6.0 has already shipped: the `@objectstack/*@17.6.0` tags point at `617f25f8` (2026-10-02). - objectui PR 11669 merged later, on 2026-10-06, as objectui `c3623eb1`. - No 17.7 tag exists yet. Of the 315 pending changesets, 146 declare a minor bump and none a major, so the next release is 17.7. - This week's sibling item `access-security.public-form-withdrawal-layers` (PR #21964) also sets `v17.7`. - One condition: the feature ships in 17.7 only if `.objectui-sha` moves past `c3623eb1` before the 17.7 cut. See "The console pin" below. 2. **The draft's third clause is split in two.** Its `"oracle": "mixed"` is not in the gate's oracle set (`api`, `network`, `screenshot`, `dom`, `log`, `test`, `build`). The draft's words are kept in both halves: - the picker half is `dom`: picker options against `GET /meta/picklist`; - the PUT half is `api`: the captured PUT body and status. 3. **The picklist fixture line now spells the recipe**, so a runner can write it from the item's text alone: - the file to edit, `examples/app-showcase/objectstack.config.ts`, and the `defineStack` keys `picklists` and `picklistExtensions`; - `definePicklist`, exported from `@objectstack/spec`; - the extension's one value must be new: a repeated value is refused at load with `INVALID_METADATA`; - the extension may sit in the list's own package. `packages/objectql/src/engine-picklist.test.ts` pins this: its nested-plugin case merges an extension registered under the list's own package; - boot with `--compile`. Otherwise `os dev` serves an existing `dist/objectstack.json`; it warns that the artifact is stale, but it boots. The fixture stays uncommitted, and nothing is added to `examples/`. 4. **The console fixture line names the merge it must carry**: objectui PR 11669, merged as `c3623eb1`. A runner can then check whether the console under test carries it. 5. **The spec citations are now anchors the gate resolves** (README, "Write the symbol as an ANCHOR"): - `PicklistSchema`, `PicklistExtensionSchema`, `PicklistServedFieldSchema` and `definePicklist`; - `FieldSchema.picklist`; - the stack keys `picklists` and `picklistExtensions`. This file's anchor census goes from 29 to 36, and all of them resolve. The producer-obligation citation now also names objectui#10202, where comment 5925784898 lives. 6. The history entry carries `"ref": "#21957"` and lists these changes. ## The console pin On `main` (`80f9f7e6`), `.objectui-sha` is `0abd4f9f`. That pin does **not** contain `c3623eb1`, the merge of objectui PR 11669. The reading was taken in a shallow objectui checkout: - `git merge-base --is-ancestor c3623eb1 0abd4f9f` exits 1; - the control leg, `0abd4f9f~30` (`b65aa5e`) against `0abd4f9f`, exits 0; - the reverse also exits 0: `0abd4f9f` is an ancestor of `c3623eb1`, 21 commits behind it. So the console fixture line is load-bearing until the pin moves. That line asks for `pnpm objectui:refresh` from an objectui at or after the merge. ## Verification (at `eed17a88b`) `dispatch-gates.mjs --commands` derives 13 gates for this diff, and all 13 were run. Exit codes were captured before any pipe. `--ran` reconciles the list as 13 derived, 13 run, 0 NOT-MEASURED (a derived zero). | gate | exit | verdict | |---|---|---| | `pnpm check:platform-checklist` | 0 | OK: 15 areas, 275 items (271 active, 2 planned); symbol anchors 683/693 resolved (676/686 on the base) | | `node scripts/check-ci-filter-parity.mjs` | 0 | OK | | `node scripts/check-closing-keyword-parity.mjs` | 0 | OK: 3 parsers agree on all 9 keywords | | `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | 40 assertions | | `node scripts/check-comment-mask-corpus.mjs` | 0 | 8297 files, 0 disagree | | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` | 0 | clean (see below) | | `pnpm check:cross-package-test-inputs` | 0 | OK | | `pnpm check:doc-authoring` | 0 | clean | | `pnpm check:driver-memory-census` | 0 | OK | | `pnpm check:gitlink-declared` | 0 | OK | | `pnpm check:nul-bytes` | 0 | OK: no raw ASCII control bytes | | `pnpm check:refd-timer-probe` | 0 | OK | | `pnpm check:watch-hint-literal` | 0 | OK | - `check:doc-formula-expressions` first exited 3: its prerequisite was not met, because `@objectstack/formula` and `@objectstack/lint` were not built. After `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint`, it was re-run and exited 0. - `checklist-select.mjs` resolves the item as runnable under both `studio-authoring.picklist-bound-select` and `since:v17.7`. The diff is checklist JSON only and changes nothing a published package ships, so the PR takes `skip-changeset`. ## Acceptance notes - **Not run yet.** This PR writes the item; no run record exists. The first run needs a console that carries objectui PR 11669 (see "The console pin"). - **`coverage.json` is unchanged; the `picklist` kind stays waived.** - The checklist's rules do not require a mapping for a new item. - The waiver also names its own retirement edit: the promotion of the planned `records-forms.picklist-shared-across-objects`. - The waiver's premise, "No runtime reads a picklist", no longer holds. The runtime half (#19519) has landed: see objectui#10202 comment 5925784898 and `packages/objectql/src/picklist-resolution.ts`. - So the next sweep's waiver re-audit should rewrite or retire it. Carrier: none. - **The showcase has the same stale premise.** Its own coverage waivers for `picklist` and `picklistExtensions` in `examples/app-showcase/src/coverage.ts` say "declared ahead of its runtime reader". Carrier: none. - **Scope held.** The item's steps go only through the two designers objectui#10202 repaired: Setup → Metadata → Object, and the Studio data page. They never go through Studio → Access → OWD overview, a writer known to fail that is filed on the objectui side. --- _Generated by [Claude Code](https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent fb69825 commit 230e494

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

‎docs/qa/platform-checklist/areas/studio-authoring.json‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,103 @@
14511451
"history": [
14521452
{ "revision": 1, "date": "2026-09-30", "change": "new — the 清单项待写 row of docs/NORTH-STAR.md beside platform-core.docs-audience-gate and platform-core.docs-portal-render; drafted with objectui#10188 and corrected by the at-tier review of objectui PR 11258 (the UI-mirror clause scoped to entries naming an installed doc or book; no signed-out persona — /docs sits behind ProtectedRoute)", "ref": "#20939" }
14531453
]
1454+
},
1455+
{
1456+
"id": "studio-authoring.picklist-bound-select",
1457+
"title": "A picklist authored in a package is used by two objects' select fields from the designer: both forms offer its options, the bound field refuses inline options, and a GET → edit → PUT of an object with a bound field saves",
1458+
"since": "v17.7",
1459+
"status": "active",
1460+
"revision": 1,
1461+
"priority": "P2",
1462+
"surface": "mixed",
1463+
"personas": [
1464+
"seeded admin (authors the objects in Studio; the picklist is authored in a package)"
1465+
],
1466+
"fixtures": {
1467+
"app": "showcase",
1468+
"requires": [
1469+
"a package that declares a picklist and one picklistExtensions entry adding one option to it; the stock showcase declares none, and the kind is package-owned (allowRuntimeCreate false), so add both in the run's own checkout, uncommitted: inside the defineStack call of examples/app-showcase/objectstack.config.ts add `picklists: [definePicklist({ name: NAME, label: LABEL, options: [two or more { label, value }] })]` (definePicklist is exported from '@objectstack/spec') and `picklistExtensions: [{ extend: NAME, options: [{ label, value }] }]`, whose one value the list does not already carry (a repeated value is refused at load with INVALID_METADATA). The extension may sit in the same defineStack as the list; it merges the same way as one from another package. Boot with `--compile` so the artifact carries the edit (os dev otherwise serves an existing dist/objectstack.json), and revert the file after the run",
1470+
"a writable project package with two runtime objects, each with a sharingModel and one select field carrying inline options; one of them published with a field already bound (picklist: NAME, no options)",
1471+
"the console under test carries objectui#10202's build (objectui PR 11669, merged as objectui c3623eb1). While .objectui-sha predates that merge (it does at objectstack 80f9f7e6, pin 0abd4f9f), flow it back with `pnpm objectui:refresh` from a ../objectui at or after the merge, per the multi-repo rule, and name the console revision in the run record"
1472+
]
1473+
},
1474+
"steps": [
1475+
"boot the showcase isolated with the console under test; sign in as the seeded admin",
1476+
"GET /api/v1/meta/picklist and GET /api/v1/meta/picklist/NAME — the list is served with name, label, its own options and _packageId",
1477+
"GET /api/v1/meta/object/OBJ_A/layers for the object whose field is already bound — record the bound field as served (picklist + resolved options, the extension's option included)",
1478+
"metadata admin (Setup → Metadata → Object → OBJ_A): select an UNRELATED field, rename its label, let the autosave run; record the PUT body and status",
1479+
"select the bound field: record what the select-field editor shows (Options from = the picklist; the values read-only; no inline options editor)",
1480+
"open OBJ_B, select its inline select field, open 'Options from', choose the picklist; record the PUT body and status",
1481+
"Studio → the package → Data → OBJ_A: add a field and let the autosave run; record the PUT body and status",
1482+
"publish both objects; open the new-record form of each and open the bound select",
1483+
"Setup → Metadata → Picklist → NAME: record what the page shows and offers"
1484+
],
1485+
"acceptance": [
1486+
{
1487+
"clause": "the metadata-admin edit of an unrelated field saves: PUT 200, and no picklist-bound field in the body carries options; every other field (an inline select included) is sent byte-identical",
1488+
"oracle": "api",
1489+
"verify": "the captured PUT body and status",
1490+
"evidence": "the PUT body"
1491+
},
1492+
{
1493+
"clause": "the designer shows no live 'picklist and options cannot both be declared' issue on an object loaded with a served bound field",
1494+
"oracle": "dom",
1495+
"verify": "page text after load",
1496+
"evidence": "screenshot"
1497+
},
1498+
{
1499+
"clause": "the select-field editor offers the served picklists by name",
1500+
"oracle": "dom",
1501+
"verify": "picker options vs GET /meta/picklist",
1502+
"evidence": "picker screenshot"
1503+
},
1504+
{
1505+
"clause": "choosing a picklist PUTs the field with picklist and WITHOUT options (200)",
1506+
"oracle": "api",
1507+
"verify": "the captured PUT body and status",
1508+
"evidence": "the PUT body"
1509+
},
1510+
{
1511+
"clause": "a bound field refuses inline options: no inline options editor (no 'Add value'), the list's values shown read-only with the reason",
1512+
"oracle": "dom",
1513+
"verify": "the field inspector",
1514+
"evidence": "screenshot"
1515+
},
1516+
{
1517+
"clause": "the Studio data page's autosave of an object with a bound field is accepted (200), the bound field sent without options",
1518+
"oracle": "api",
1519+
"verify": "the captured PUT",
1520+
"evidence": "the PUT body"
1521+
},
1522+
{
1523+
"clause": "after publish, both objects' new-record forms offer the picklist's options, the extension's option included",
1524+
"oracle": "dom",
1525+
"verify": "open each bound select",
1526+
"evidence": "the two option lists"
1527+
},
1528+
{
1529+
"clause": "the picklist page shows label, name, owning package, each option with its label and value, and each extension under its declaring package — and offers no create, edit or delete (no New on the list; every control on the detail page disabled or read-only; no write request)",
1530+
"oracle": "dom",
1531+
"verify": "list + detail page, network log",
1532+
"evidence": "screenshots + the empty write log"
1533+
}
1534+
],
1535+
"negative": [
1536+
"any PUT of an object with a bound field answered 422 INVALID_METADATA at fields.FIELD.options — FAIL (the served-options producer obligation)",
1537+
"an inline options editor, or a free-text name box, offered on a bound field — FAIL",
1538+
"a New / Save / Delete on the picklist list or detail page — FAIL (the kind is package-owned, allowRuntimeCreate false)",
1539+
"the picklist page saying 'no package extends this picklist' when the package read failed — FAIL"
1540+
],
1541+
"traps": ["stale-console-bundle", "cache-staleness"],
1542+
"source": [
1543+
"objectui#10202 ruling 6006062645 (A′): (a) use picklist, (b) served options dropped before the PUT, (c) read-only page, (d) this item",
1544+
"objectstack#18164; producer obligation 5925784898 on objectui#10202; server pin packages/objectql/src/protocol-picklist-served-roundtrip.test.ts",
1545+
"packages/spec/src/data/picklist.zod.ts#PicklistSchema, packages/spec/src/data/picklist.zod.ts#PicklistExtensionSchema, packages/spec/src/data/picklist.zod.ts#PicklistServedFieldSchema; packages/spec/src/data/field.zod.ts#FieldSchema.picklist refinement",
1546+
"the fixture's spelling: packages/spec/src/data/picklist.zod.ts#definePicklist, the defineStack keys packages/spec/src/stack.zod.ts#picklists and packages/spec/src/stack.zod.ts#picklistExtensions; an extension in the list's own package merges (packages/objectql/src/engine-picklist.test.ts, the nested-plugin case)"
1547+
],
1548+
"history": [
1549+
{ "revision": 1, "date": "2026-10-06", "change": "new — drafted with objectui#10202 against the measured run of its PR; filed by the seat. Authored from that draft with these changes: since v17.7, because 17.6.0 shipped before objectui PR 11669 merged; the picker clause split in two, one oracle each; the picklist fixture spelled with its export, its stack keys and the reload it needs; the console fixture naming the merge it must carry; the spec citations written as anchors the gate resolves", "ref": "#21957" }
1550+
]
14541551
}
14551552
]
14561553
}

0 commit comments

Comments
 (0)