Skip to content

feat(spec): the picklist metadata kind — a shared option list select fields reference by name (#19518) - #20823

Merged
os-zhuang merged 24 commits into
mainfrom
claude/issue-19518-picklist-kind
Sep 30, 2026
Merged

os-zhuang merged 24 commits into
mainfrom
claude/issue-19518-picklist-kind

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Part of #19518

Clause-②: yes

The spec layer of the shared picklist:

  • the picklist kind: registered, loads before object, package-owned;
  • Field.select({ picklist }), refused when options is also declared;
  • the served shape PicklistServedFieldSchema;
  • picklistExtensions;
  • the picklists.NAME translation face and its resolvers.

Two gates this PR must keep green are also carried here:

  • the published platform skill lists the two new top-level keys (check:skill-top-level-keys);
  • os i18n extract walks picklists.NAME.{label, options.VALUE} (check:i18n-walk-parity).

Every pin that enumerates registered kinds or FieldSchema keys moves with the kind. That includes driver-sql's column-collision classification.

Resolving the reference at runtime is #19519. Until then the liveness ledger grades the new keys planned. Refusing a select / radio with neither options nor picklist is #20827 (ruled A, after this PR). The CLI compile / validate path is #20825. #19518 stays open for its Tier H docs PR: the NORTH-STAR line and the two records-forms checklist items.

维护者速读

改了什么: skills/objectstack-platform/SKILL.md 的顶层键清单加上 picklists、picklistExtensions 两个键(第 43 行起)。同一文件 CLI 小节的一句指路文字(第 453 行附近)删掉两处:

  • 已失真的「below」:Part 3 已由 595621d35c 拆到 references/operations.md,不在本页下方;
  • 与 cheat sheet 重复的「High-level」。

读数: 整文件 489 行不变;token 5829 → 5827,上限 5833;技能包总行数 4396 不变。check-governed-merges:75 个路径中 1 个命中登记(skills/**),所以是 Tier H;共 1564 行改动,低于 5000。

为什么改: 本 PR 给 stack 新增了这两个顶层键。必需门禁 check:skill-top-level-keys 要求技能页的清单与 schema 一致;页面上没列的键,AI 作者就不会写。

风险与回滚: 只改文字,链接目标不变,作者需要的内容一处没删。回滚办法是 revert 4049ae31ba,但若不同时去掉这两个 stack 键,该门禁会重新变红。

席位意见: 建议批准。复核 PASS 后,席位在本 PR 上贴出记录。

你要做的: 看 SKILL.md 的两处改动,然后给出授权的 APPROVED 审阅,由席位落地;也可以亲手合并。

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1

…map, strictness counts

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
…etadata-protocol

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
…d llms.txt inventory

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
…te, quick-reference counts

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
…anslation bundles

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/cli, @objectstack/driver-sql, @objectstack/platform-objects, @objectstack/spec, touching 43 documentable anchor(s). ⚠️ 22 changed file(s) yielded no anchor (packages/spec/api-surface-signatures.json, packages/spec/api-surface/data.json, packages/spec/api-surface/root.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

16 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 05a7547c9f40e0dfab89a34f5e5b60f818af70d2.

⛔ 4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 22 changed file(s) yielded no anchor (packages/spec/api-surface-signatures.json, packages/spec/api-surface/data.json, packages/spec/api-surface/root.json, …) — pages documenting those are invisible to this run
  • 4 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 05a7547c9f40e0dfab89a34f5e5b60f818af70d2 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 9275a54138667b9a6d539209b8b99008ab32b6d3 — the merge of head 388dcceb29f580b984200eceadfce9c723c33678 into base 05a7547c9f40e0dfab89a34f5e5b60f818af70d2, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 9275a54138667b9a6d539209b8b99008ab32b6d3 && git checkout 9275a54138667b9a6d539209b8b99008ab32b6d3
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 05a7547c9f40e0dfab89a34f5e5b60f818af70d2 388dcceb29f580b984200eceadfce9c723c33678 && git checkout -B drift-repro 05a7547c9f40e0dfab89a34f5e5b60f818af70d2 && git merge --no-ff 388dcceb29f580b984200eceadfce9c723c33678

node scripts/docs-audit/affected-docs.mjs --json 05a7547c9f40e0dfab89a34f5e5b60f818af70d2

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 05a7547c9f40e0dfab89a34f5e5b60f818af70d2 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

…ions among the top-level stack keys

The CLI cheat-sheet lead no longer says Part 3 sits below: the split moved it
to references/operations.md, so the sentence points there by name. The cut pays
for the two keys under the token ceiling.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
…vel-1 heading

A level-1 opener is demoted when the reference page renders, and the
file-description corpus pins how many descriptions need that. The page's
frontmatter description is unchanged.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
The merge driver kept one side of content/docs/references/api/protocol.mdx;
regenerated from the merged schemas it carries both main's `computed`
drop reason and this branch's `picklists` translation group.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 388dcceb29f580b984200eceadfce9c723c33678
Local-runs: none

Reviewed read-only: card #19518 (body and all eight comments), the parent's design of record 5715762696 and rulings 5755653853 / 5904864936, the split cards #20825 and #20827 (ruling 5910124148), PR #20823's body and 75-file list, the net diff from merge-base 820d3f4f8e to the head (+1432 / -132), and the head's check-runs. Scope tested is #19518 Scope 1-5 as amended by the seat: the "neither" refusal is #20827 and is not expected here.

① Derived judgments

Accept-set and public-surface changes, each judged:

  1. New kind picklist — MetadataTypeSchema member, DEFAULT_METADATA_TYPE_REGISTRY row (loadOrder 8, below object at 10 and field at 20; allowRuntimeCreate: false, allowOrgOverride: false, supportsOverlay: false; filePatterns **/*.picklist.ts|yml|json; domain: 'data'), BUILTIN_METADATA_TYPE_SCHEMAS binding, PLURAL_TO_SINGULAR and the regenerated meta-url map, check-liveness GOVERNED. Right. Matches Scope 1 and the capability precedent for a package-owned kind (ADR-0088 clause 2 is met by the file loader, which is registry-derived). Two consequences that are live on main the day this lands: GET /meta/picklist and /meta/picklists list (empty until picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519 registers items) instead of refusing an unknown type, and PUT /meta/picklist/NAME is refused 403 not_creatable on every kernel because the derived CODE_ONLY_TYPES set now holds picklist (both pinned in metadata-protocol). The registry comment claiming that refusal is true at land time.
  2. PicklistSchema { name, label, description?, options } — strictObject, SnakeCaseIdentifierSchema for name (the mapping precedent), ADR-0010 envelope spread, aliases values|choices|items to options and title|displayName to label, definePicklist on the root barrel. Right. options.min(1) is one step past the ruled shape (SelectOption[]) and is correct: an empty shared list is the ADR-0078 dead choice at list level, and the message says so. SelectOptionSchema is reused verbatim — no second option shape, as ruled.
  3. PicklistExtensionSchema { extend, options min 1 }, strictObject, guidance on remove and label as wrong-layer pointers, aliases picklist|target|name|extends to extend; stack collections picklists and picklistExtensions, both concat on compose. Right — additive only per design item 4; no key can remove or rename, and the guidance says where such a change belongs.
  4. FieldSchema.picklist (SnakeCaseIdentifierSchema, optional) with a superRefine that refuses it on a non-option type at path picklist and refuses picklist + options at path options with the prescription; the old picklist to options alias removed; valueSet|globalValueSet|optionSet now alias to picklist. Right. Pure widening: before this PR every picklist key on a field was an unknown-key refusal, so nothing accepted on main is refused now. The option-type set in the message (select, radio, multiselect, checkboxes, tags) equals SINGLE_OPTION_TYPES plus MULTI_OPTION_TYPES. "Neither" is deliberately not refused (seat ruling; A select / radio field with neither options nor picklist: refuse it at the FieldSchema door (an accept-set narrowing), or keep it at the ADR-0078 completeness gate? (split from #19518) #20827, ruled A after this PR).
  5. Field.select overloads — the new selectFromPicklist form returns { type: 'select', picklist, ...config } with no options; a call handed both keeps both and reaches the door refusal (pinned). Right. One unstated widening rides with it: the inline form's parameter type moved from SelectOption[] | string[] to an array of SelectOption or string, so a mixed array now type-checks (the runtime already mapped elements one by one; the graduation of field.test.ts's two TS2322 debt entries is the measurement). Public type surface, not mentioned in the changeset, and Field carries no hash in api-surface-signatures.json so no baseline moved. Right in substance (the type now matches the runtime); minor covers it.
  6. PicklistServedFieldSchema — looseObject { picklist, options min 1 }, the Scope 3 shape. Right, and the strictness ledger row classifies it as a served passthrough by design. It is a declared contract with no producer on main at land time (see item 7 and the text judgments below).
  7. checkFieldCompleteness counts a picklist string as the field's option source; the fix names both keys. Right after picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519 lands; an interim at land time that the record must name. On main today nothing resolves the reference, so a { type: 'select', picklist: 'x' } field now parses, passes the ADR-0078 completeness gate (which used to be an error for a select with nothing to choose), and is served with no options and no server-side value check — the exact case the rule names. The compensating control is real: field.picklist is ledgered planned with authorWarn and an authorHint that says keep inline options on fields that must work today, and the lintLivenessProperties authoring rule is advisory, commands: ALL (os validate, os build, os lint), severity warning, never fatal. Studio cannot author the key (the metadata-form reconciliation omits it). This is the ruled spec-first sequencing (5755653853, 5904864936) and the seat accepted it in 5908214854; judged right as the interim, with the moment named.
  8. Translation face — picklists.NAME.{ label?, options } on TranslationDataSchema, PlatformTranslationDataSchema and TranslationItemSchema (strict entry, aliases, picklist to picklists alias on all three doors), the ten-to-eleven group prose updated in six places, translatePicklist registered so TRANSLATABLE_METADATA_TYPES gains picklist, and translateObject letting a picklist-bound field inherit picklists.NAME.options.VALUE with a field-level entry winning. Right. The "field-level wins" precedence is one step past Scope 4's wording ("field-level remains for inline options") and is within the design: the more specific entry wins, and the seat accepted it by name. Note the extractor never scaffolds a field-level option key for a picklist-bound field (pinned), while the resolver honours a hand-written one — consistent, not a gap.
  9. os i18n extract walk (walkPicklists) — picklists.NAME.label via pushEntry, picklists.NAME.options.VALUE with the check-i18n-bundles merge mode never updates an EXISTING field description, so editing one leaves the en bundle silently stale (and the gate green) #8543 derived rule, an extension's options keyed under the list it extends, new picklist coverage source so os lint reports i18n/missing-picklist (lint.ts forms the id from the source), fixture member parity_tier, six-test pin. Right; the walk skips an option whose value is not a string, and SelectOptionSchema.value is a string, so nothing is lost.
  10. driver-sql FIELD_KEY_STORAGE_CLASS.picklist: 'presentation'. Right — the option code lives in the select's own column; the reference is metadata.
  11. Census — every enumerating pin moved (type-schema closure 25/26 to 26/27, create-seeds KNOWN_UNSEEDED, form-reconciliation omit row, lint authorWarnedProperties('field'), metadata-protocol CODE_ONLY_TYPES with a probe and the field property count 74 to 75, recovery-doors bootstrap set, platform-objects 27 to 28 types / 10 to 11 bare / 16 to 18 leaves / 657 to 658, runtime parity cells, CLI GATED_AT, showcase KIND_COVERAGE and STACK_COLLECTION_COVERAGE waived to picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519, check-stack-collection-maps waiver rows written as PENDING rows that fail stale when picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519 lands, liveness README 40 to 41 governed types plus shards, strictness ledger 158 to 161 sites, llms.txt, doc counts 27 to 28 / 29 to 30 / 1521 to 1524, generated baselines). Right; the green check-runs on the head are the proof for every pinned one. Two unpinned enumerations of registered kinds did not move: packages/metadata/src/serializers/typescript-serializer.ts ANNOTATION_BY_METADATA_TYPE (named in neither report; no picklist item can reach it before picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519 registers one) and packages/metadata-core/src/types.ts MetadataTypeSchema (named by the dev; its "lockstep" comment was already false in both directions before this PR, no pin). Both belong to the runtime layer; see ③.

Author-shown and AI-facing text, each sentence tested against the tree:

  • FieldSchema.picklist describe (copied by generation into field.mdx, object.mdx, migration.mdx and the JSON schema): "The server resolves the reference: the field clients read carries the resolved options." Over-broad at land time. On main when this PR lands nothing resolves the reference and a picklist-bound field is served without options — the changeset says exactly that one sentence later, and field.json's authorHint says it to the author at lint time. True only after picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519 lands. The same present tense sits in the picklist docblock in field.zod.ts, in the PicklistServedFieldSchema docblock ("Every consumer that reads field.options today … nothing a client does changes"), and in the pair-refusal message ("the shared list supplies them"). picklist.mdx's own prose is conditional ("once the reference is resolved") and is fine. Not blocking: the ledger planned + authorWarn row is this repo's declared-ahead mechanism (the useGrouping precedent), the changeset states the gap, and the showcase waiver states it. Flagged in ③ for a wording touch.
  • Registry comment: 403 not_creatable with the prescription read from filePatterns[0], and loadOrder: 8 before object — true at land time (the code-only door is pinned; the order is a registry fact, and the loader that honours it for picklist items is picklist metadata kind — runtime: resolve picklist → options when serving field metadata, validate writes against the resolved set, apply package-level extensions (phase 1 of objectstack#18164) #19519).
  • field.zod.ts comment and the picklist.test.ts pin that "neither on a select/radio is the completeness gate's error, not a parse refusal" — true now; ruling 5910124148 (A) moves that refusal to the door after this PR lands, at which point this comment and pin move with it. Stated so the next author does not read it as permanent.
  • PICKLIST_HISTORY ("Until this shape was closed these would have been dropped silently …") — a counterfactual, phrased as one; the kind was born closed. Acceptable.
  • .changeset/19518-picklist-kind.md — every bullet holds: the kind and its registry facts, the reference and its two refusals, the completeness predicate, the served shape with the explicit "This release does not resolve the reference", additive extensions, the translation face with field-level precedence, the Studio type label in four bundles, the extraction walk and i18n/missing-picklist, the SQL classification. The one sentence that is true only after another PR is the picklist describe quoted above, and the changeset's next sentence names that moment itself.
  • PR body, including 维护者速读 — every reading verified on the tree: SKILL.md 489 lines before and after; bytes 23313 to 23306; tokens (ceil bytes/4) 5829 to 5827 against the 5833 ceiling in check-skills-token-ratchet.mjs; skills package SKILL.md lines 4396 unchanged; 1 of 75 paths governed (skills/objectstack-platform/SKILL.md, Tier H); 1564 changed lines; the hunks at lines 43-45 and 453; 4049ae31ba touches only that file (+5/-5); 595621d35c is the split that moved Part 3 to references/operations.md. "Every pin that enumerates registered kinds or FieldSchema keys moves with the kind" is true of pins; the two unpinned enumerations are named in ③. "Part of picklist metadata kind — spec: picklist collection, Field.select({ picklist }), server-resolved options, translation face (phase 1 of objectstack#18164) #19518", A select / radio field with neither options nor picklist: refuse it at the FieldSchema door (an accept-set narrowing), or keep it at the ADR-0078 completeness gate? (split from #19518) #20827 ruled A after this PR, picklist kind: the os CLI compile / validate / lint path accepts *.picklist.ts, picklists and picklistExtensions, and os validate refuses a picklist that names no picklist (Scope 6 of #19518) #20825 for the CLI path — all match the rulings.
  • skills/objectstack-platform/SKILL.md hunk, read as text an AI author acts on. The addition lists picklists and picklistExtensions after objectExtensions among the defineStack() top-level keys — required by check:skill-top-level-keys, and true: both keys parse. An author who writes them today gets a stack that loads and a field-level advisory warning telling them the reference is not resolved yet; the skill page itself carries no such note, and the ledger is the mechanism that does. Cut 1 ("covered in Part 3 — Operations below" to "in Part 3 — Operations"): the stated reason holds — on the base tree the only Part 3 text below line 452 is the moved-verbatim pointer at line 479; the content is in references/operations.md since 595621d35c; the link target is unchanged, so an author following it lands where they did before. Cut 2 ("High-level cheat sheet" to "Cheat sheet"): redundant, as stated; the block's content is untouched. Nothing an author needs left the page.

② Semver level

  • @objectstack/spec: minor — matches the diff. New published kind, new FieldSchema key, two new stack collections, a new translation group on three doors, new exports (PicklistSchema, PicklistExtensionSchema, PicklistServedFieldSchema, definePicklist, the Picklist* types, translatePicklist, PicklistLike) all recorded in the api-surface, export-origins and declaration-map baselines. Widening only; nothing an author could write on main is refused now (the alias removal changes a refusal's suggestion, not the accept set).
  • Clause-②: yes on the claim and the PR body; yes (widening) on the changeset, which is where AGENTS.md says the arm is read. Consistent with a new kind and a new Field.select reference; yes takes at least minor, satisfied. Correct.
  • @objectstack/cli: patch — acceptable. The walk is the parity obligation of spec's new group; os i18n extract gains no command, flag or option. A stricter reading would call the new rule id i18n/missing-picklist new functionality and say minor; either level leaves the release the same, since spec's minor lifts the workspace. Not a blocker.
  • @objectstack/platform-objects: patch (four bundle entries) — correct. @objectstack/driver-sql: patch (one classification row) — correct.
  • No changeset owed for @objectstack/lint, @objectstack/metadata-protocol, @objectstack/runtime (test-only changes) or examples/app-showcase (private).

③ Boundary flags

Dev report 1 (5908082075), open_questions, each answered by the seat's ruling 5908214854 and verified on the head:

  1. "Neither refused" — split to A select / radio field with neither options nor picklist: refuse it at the FieldSchema door (an accept-set narrowing), or keep it at the ADR-0078 completeness gate? (split from #19518) #20827; maintainer ruled A (5910124148), sequenced after this PR with a census and the Studio create-field order first. Not delivered here, by ruling. Answered.
  2. check:skill-top-level-keys — A; delivered at 4049ae31ba, the PR is Tier H. Answered.
  3. check:i18n-walk-parity — A; delivered at c9fe5047d4, gate green on the head. Answered.
  4. Closes vs Part of — A; the body reads Part of #19518, the Part-of PR must not also close its card check is green. Answered.

Dev report 1, out_of_scope_findings (flags): lint R8 select-missing-options not counting picklist — routed to #20825, whose body carries it as point 3. Answered. Runtime enumerations (METADATA_ARRAY_KEYS, ARTIFACT_FIELD_TO_TYPE, APP_CATEGORY_KEYS/SECURITY_FIELDS, reference-sites, the metadata-core enum) — routed to #19519 and waived as PENDING rows that fail stale when it lands. Answered. Served-shape round trip (a client that PUTs a served field back is refused at the door) and resolveObjectFieldLabels not seeing inherited labels — routed to #19519 / objectui#10202, "noted, not filed". Answered by routing; whether those notes reached #19519's thread is outside this record's inputs — escalated to the seat: make sure #19519's body or thread carries them before it is dispatched. check:platform-checklist coverage.json picklist UNCLASSIFIED (manual cadence, docs/qa off-limits to this card) plus the pre-existing identity-auth twoFactor anchor — carried by the seat's Tier H docs PR. Answered.

Dev report 1 deviation: the schema-door "neither" refusal implemented, measured (4 spec fixtures, 9 metadata-protocol tests red) and withdrawn — the right call; the measurement is what #20827's ruling now sequences on. Answered.

Dev report 2 (5912287363): open_questions empty. out_of_scope_findings: the same check:platform-checklist reading — answered as above; the owed PR-body update — done, the body at this head carries 维护者速读, the governed-merges line and the round-2 surfaces. NOT MEASURED locally: check:pm-dispatch-gates (timeout; reads scripts/pm tooling this PR does not touch) — the head's check-runs cover the derived families, no flag.

Reviewer's own flags:

Check-runs on 388dcceb29f580b984200eceadfce9c723c33678, read last, deduplicated by name keeping the newest started_at: 46 runs, 35 names — 31 success, 4 skipped (Auto Label, Check PR Size, Console Pin Gate, Packed-tarball smoke (opt-in)), 0 failed, 0 still running. Every name is complete; nothing is in progress. Governed Surface Queue Guard, Check Changeset, Spec property liveness, all Type Check jobs, Test Core 1-6 and the three claim guards are green.

Implemented-by: claude/issue-19518-picklist-kind
Reviewed-by: session_01Sfe5YjBLwB9J3y8fvm2xq1

VERDICT: PASS

Adopted and posted by domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1) · 2026-09-30T13:49Z · rendered by the seat's at-tier review subagent on this head. The seat read its served tier family from the subagent transcript before posting.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读 · 2026-09-30T13:51Z

domain:spec seat 5(session_01Sfe5YjBLwB9J3y8fvm2xq1)。这是终稿,由本席对照 diff 写成。本 PR 受管的部分只有一个文件:skills/objectstack-platform/SKILL.md。审核记录是达档复核 PASS 5912646092。

改了什么

  • 本 PR 新增共享选项集 picklist 这一元数据类型。技能文档的顶层键清单(第 43 行起)因此加上 picklists、picklistExtensions 两个键。
  • 同一文件 CLI 小节的一句指路文字(第 453 行附近)删了两个词:已失真的「below」(Part 3 已由 595621d35c 拆到 references/operations.md)和与 cheat sheet 重复的「High-level」。
  • 读数:文件 489 行不变;token 从 5829 降到 5827,上限 5833;技能包总行数 4396 不变。

为什么改
必需门禁 check:skill-top-level-keys 要求技能页的清单与 schema 一致。页面上没列的键,AI 作者就不会写。

风险与代价(含回滚)

席位意见
建议批准。技能文档的两处删减,理由都已在仓库里核实;新增的两个键是门禁要求的最小改动。

你要做的
在本 PR 上给一个 APPROVED 审阅,由你或授权账户 os-zhuang / hotlong 之一给出。现在批或删文字那一轮之后批都可以,批准不会因后续推送失效。之后本席核对删改,转 ready 并入合并队列。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 30, 2026 13:57
@os-zhuang
os-zhuang enabled auto-merge September 30, 2026 13:58
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 30, 2026
@os-justin
os-justin removed the request for review from hotlong September 30, 2026 14:14
Merged via the queue into main with commit addbbf0 Sep 30, 2026
58 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-19518-picklist-kind branch September 30, 2026 14:31
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…lved (objectstack-ai#19518) (objectstack-ai#20878)

Part of objectstack-ai#19518

Clause-②: no

Follow-up to objectstack-ai#20823. The server does not resolve a `picklist` reference
yet, so four sentences that said it does are deleted or restated: the
`FieldSchema.picklist` describe, its doc comment, the
`PicklistServedFieldSchema` doc comment, and the refusal of `picklist`
with `options`. The reference pages that copy the describe are
regenerated with `check:generated --fix`. There is no behavior or
assertion change.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants