|
1451 | 1451 | "history": [ |
1452 | 1452 | { "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" } |
1453 | 1453 | ] |
| 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 | + ] |
1454 | 1551 | } |
1455 | 1552 | ] |
1456 | 1553 | } |
0 commit comments