Skip to content

picklist metadata kind — spec: picklist collection, Field.select({ picklist }), server-resolved options, translation face (phase 1 of objectstack#18164) #19518

Closed

Description

@os-project-manager

Path: 本地跑起来、看到 — records-forms.picklist-shared-across-objects, records-forms.picklist-org-append | P2

Sub-issue of objectstack#18164 (shared picklist / global value set), filed by the director seat, summon #25 (session_012GcsUbuqFGBibkEDMRC1eE) under ruling batch #209 item 1 · letter A · maintainer 「18164 同意」 (2026-09-21, chat). ⛔ Not a claim. Position in the road: step ②「本地跑起来、看到」, records/studio; it is taken after the open product P0/P1 checklist items by the road order — ⛔ not dispatched before them. The design of record is the batch #147 item 2 ruling on the parent (comment 5715762696), reproduced here only where this layer needs it.

Scope (the spec layer — packages/spec, the domain:spec seat)

  1. New metadata kind picklist (name ruled picklist on the parent, ruling 5904864936, batch 🔗 Broken links detected in documentation #251 item 3 · Q2 A): { name, label, description?, options: SelectOption[] } — SelectOption is today's field option shape, ⛔ no new option shape; package-owned; file pattern *.picklist.ts; registered before object in load order; a stack collection like any other metadata (registry row, JSON schema, manifest listing, allowRuntimeCreate per the ADR-0088 rules for authored kinds).
  2. Field reference Field.select({ picklist: 'industry' }), mutually exclusive with options: both on a select type is refused at the schema door with a prescription. (Neither: 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 for the maintainer, seat ruling on this card, because refusing it narrows stored data.)
  3. Server-resolved contract: the field metadata served to clients carries the resolved options (so objectui's renderers, validation and filters are unchanged in phase 1); the spec declares that shape — the resolution itself is the runtime sub-issue.
  4. Translation face: TranslationData.picklists.<name>.{ label?, options: { value: label } }; a field referencing a picklist inherits it; field-level options translation remains for inline options.
  5. Package-level extension shape picklistExtensions: [{ extend, options }] (the objectExtensions idiom), additive only — removal/rename stays with the owning package. The per-organization overlay (ADR-0005, allowOrgOverride) is phase 2 and ⛔ not declared here.
  6. The os CLI compile / validate path accepts the new kind and refuses the two-or-neither case (CLI is domain:cli; if the change lands in packages/cli it is a sibling PR by that seat, filed from this card). Filed as 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; the os i18n extract walk rides PR feat(spec): the picklist metadata kind — a shared option list select fields reference by name (#19518) #20823.

Also with this card (Tier H, its own small docs PR, the maintainer merges)

The feature-map line in docs/NORTH-STAR.md 「路上的功能点」 step ② records group — records · 共享选项集:多个对象复用同一份选项,客户按组织追加值而不改应用源码 · records-forms · <the two new item ids> — and the two records-forms checklist items (one picklist, two objects; org A adds a value, A writes it, B is refused; locale switch relabels) authored under docs/qa/platform-checklist/areas/records-forms.json (ADR-0136 D2.4). Until that PR lands the line reads 清单项待写.

Acceptance

Schema tests: the kind parses; picklist + options together refused (neither: #20827); the served field shape carries resolved options; translation keys resolve; check:spec-* families green; changeset minor (new published kind). Not in v1: cascading picklists (per-option visibleWhen / dependsOn exist), unrestricted mode, per-record-type value restriction.

Dedupe words: picklist, global value set, valueSet, shared select options, _picklists.ts, picklistExtensions.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Ruling on the round-2 report 5912287363 · 2026-09-30T13:31Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409. PR #20823 at 388dcceb29; the seat read CI there as green.

    Accepted as delivered:

    • Gate 1: check:skill-top-level-keys is green. SKILL.md lists picklists and picklistExtensions, and the cost is covered by two cuts in the same file. One removes "below", which was false: Part 3 moved out in 595621d35c. The other removes the redundant "High-level". The file is 7 bytes and 2 tokens smaller, and its line count is unchanged.
    • Gate 2: check:i18n-walk-parity is green. The walk covers picklists.NAME.{label, options.VALUE} and extensions, with a six-test pin, and an ablation turns the gate red.
    • The six census pins round 1 missed: driver-sql's column-collision classification, the CLI schema gate, the metadata-protocol bootstrap set, the platform-objects echo counts, and the runtime census cells. Each one enumerates registered kinds or FieldSchema keys, so each falls under the claim's clause for pins that enumerate. The changeset now names @objectstack/cli and @objectstack/driver-sql.

    This PR is Tier H: skills/** accounts for one path. The seat rewrote the PR body with the 维护者速读 section, built from the dev's draft. It stays Part of #19518: the Tier H docs PR (the NORTH-STAR line and the two records-forms items) is still owed and will carry the coverage.json classification that check:platform-checklist asks for.

    Next: needs:contract-review goes on the PR and this card, and the at-tier review runs. After a PASS the seat does NOT make the PR ready, queue it or arm auto-merge. That waits for an authorized approval.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
     "issue": 19518,
     "status": "blocked",
     "branch": "claude/issue-19518-picklist-kind",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/20823",
     "session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
     "premise_still_valid": true,
     "head": "remote 388dcceb29 (unchanged); local f072bf2215, not pushed",
     "blocked_on": "PR #20823 is in the merge queue (ref gh-readonly-queue/main/pr-20823-6c96b37be8, queue sha addbbf02ab; PR open, not draft, head 388dcceb29). The append-only push of the round-3 commits was refused: `git push origin claude/issue-19518-picklist-kind` returned remote GH006 'A pull request for this branch has been added to a merge queue. Branches that are queued for merging cannot be updated. To modify this branch, dequeue the associated pull request.' This run did not enqueue the PR, and it does not dequeue it: that is another actor's state. The push was not retried and not re-routed to another branch.",
     "summary": "Round 3 is done locally and only publishing is blocked. The worktree was rebuilt from remote 388dcceb29. origin/main was 8 commits ahead, so it was merged via os-regen-merge.sh at 74cb5c1a7c; `check:generated --fix` afterwards reported all 15 artifacts current, so no regeneration commit was needed. The four present-tense sentences were deleted or restated in 830102dc7e (packages/spec/src/data/field.zod.ts +3/-7, picklist.zod.ts +1/-4; no behavior or assertion change). Their generated copies were regenerated with the repo's own `check:generated --fix` (gen:docs) in f072bf2215: content/docs/references/data/field.mdx, data/object.mdx, system/migration.mdx. Nothing else was touched. Patch-ids (git patch-id --stable): 830102dc7e = cb436dd6aafc31b19b01e4b2dfc7cc754d1cded3, f072bf2215 = 4bde9dacada4c96ee523a2662230df94f4d59386. The two commits are saved as format-patch files in the shared scratchpad, issue-19518/round3/0001-*.patch and 0002-*.patch. The worktree /home/user/objectstack-issue-19518 is kept (with node_modules) because its local branch holds the unpushed commits.",
     "text_changes": [
      {
       "where": "FieldSchema.picklist .describe() (field.zod.ts, around line 1363)",
       "before": "Name of a shared `picklist` whose options this field offers — instead of `options`, never with it. Option types only (select, radio, multiselect, checkboxes, tags). The server resolves the reference: the field clients read carries the resolved `options`.",
       "after": "Name of a shared `picklist` whose options this field offers — instead of `options`, never with it. Option types only (select, radio, multiselect, checkboxes, tags).",
       "how": "sentence deleted (the preferred form); no tracker number added"
      },
      {
       "where": "FieldSchema.picklist docblock (field.zod.ts, around line 1354)",
       "before": "The reference is resolved on the SERVER: the field a client reads from the object read exits carries the resolved `options` next to this key (`PicklistServedFieldSchema`), so renderers, the record validator and filter pickers read `options` exactly as they do for an inline list.",
       "after": "`PicklistServedFieldSchema` declares the served form.",
       "how": "restated as what holds now: the schema declares the served shape. The following sentence on translation keys is unchanged."
      },
      {
       "where": "PicklistServedFieldSchema docblock (picklist.zod.ts, around line 147)",
       "before": "Every consumer that reads `field.options` today (renderers, the record validator, filter pickers, import coercion) therefore reads the key it always has, and nothing a client does changes for a picklist-bound field.",
       "after": "(deleted)",
       "how": "sentence deleted; the paragraph now ends at 'still naming the list they came from.'"
      },
      {
       "where": "picklist + options refusal message (field.zod.ts, around line 2150)",
       "before": "Keep `picklist: 'NAME'` and delete `options`: the shared list supplies them (to offer a new value, ...",
       "after": "Keep `picklist: 'NAME'` and delete `options`: the picklist holds them (to offer a new value, ...",
       "how": "'supplies them' (resolution) became 'holds them' (the picklist item declares the options, which is true now). No test asserts the old literal: picklist.test.ts asserts only toContain('`picklist`') on this message, so no assertion text changed."
      }
     ],
     "prose_net": "source hunks: 846 bytes removed, 282 added, net -564. Lines: field.zod.ts +3/-7, picklist.zod.ts +1/-4. The generated mdx rows only shrink (5 table rows).",
     "generated_artifacts": "Tracked, regenerated by `pnpm --filter @objectstack/spec check:generated --fix` (which ran gen:docs as the only stale artifact of 15): content/docs/references/data/field.mdx (1 row), content/docs/references/data/object.mdx (2 rows), content/docs/references/system/migration.mdx (2 rows). Built and gitignored, regenerated by the spec build that --fix forces: packages/spec/json-schema (Field.json and every schema that embeds FieldSchema). No copy exists in the platform-objects metadata-forms bundles, because `picklist` is on the metadata-form omit row, and `git grep` of the describe text finds no other tracked file. The api-surface, declaration-map, export-origins and authorable-surface artifacts were current before and after.",
     "tests": "At local head f072bf2215, all runs used os-verify-lock (VERDICT command-exit 0), and exit codes were captured before any pipe. `check:generated` exit 0, 'All 15 generated artifacts are up to date' (measured against the dist built by the preceding --fix run over the same source). spec `typecheck` exit 0 (test-typecheck: 52 files / 137 pinned signatures held). spec `vitest run --project local` exit 0: 580 files, 17134 passed, 1 todo. `dispatch-gates --commands` at f072bf2215 derives 149 families, the identical set to round 2 at 388dcceb29. NOT MEASURED: `dispatch-gates --ran` at f072bf2215 (reason: the head cannot reach the PR while it is queued, and the full 149-family pass holds the shared lock for about 42 minutes, so it is deferred to the dequeue decision; round 2's --ran at 388dcceb29 accounted for all 149, 148 run and 1 NOT-MEASURED). CI: the round-3 head has no CI, since it is not pushed. CI on the PR head 388dcceb29, deduplicated by name keeping the newest started_at: 54 runs, 35 names, 31 success, 4 skipped (Auto Label, Check PR Size, Console Pin Gate, Packed-tarball smoke (opt-in)), 0 failed, 0 running.",
     "mcp_calls": "0",
     "api_writes": "1 relay write through scripts/pm/fleet-write/dispatch.mjs (transport dispatch): comment POST /repos/objectstack-ai/objectstack/issues/19518/comments (this os-dev-report). The git push of f072bf2215 was refused by the remote (GH006, merge queue). It is not a REST write, and it was not retried.",
     "open_questions": [
      {
       "question": "PR #20823 is queued at 388dcceb29 and the round-3 wording commits cannot be appended. Which way?",
       "options": [
        "A: dequeue #20823 (maintainer or seat). Then push f072bf2215 as a fast-forward: the local branch is 388dcceb29 + merge 74cb5c1a7c + the two commits. CI reruns and the delta is checked by the patch-ids above; then re-enqueue. Cost: the queue slot, a full CI round, and a fresh maintainer approval if branch protection dismisses stale reviews on push (Tier H, skills/**).",
        "B: let #20823 land at 388dcceb29, and carry the two commits as a docs-only follow-up PR from a fresh branch off the new main (cherry-pick 830102dc7e and f072bf2215, or apply the saved patches, then re-run gen:docs if main moved the pages). It touches packages/spec/src/data and content/docs/references only, neither of which is on the governed register, so it needs no maintainer merge; it takes a patch changeset or skip-changeset per the published-surface rule (the describe ships in dist and the JSON schema)."
       ],
       "recommendation": "B, because the contract review 5912646092 rated the wording 'not blocking' and allowed 'a docs touch now'. The follow-up needs no second maintainer approval of the skills/** hunk, and the commits are already built and verified."
      }
     ],
     "out_of_scope_findings": []
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Ruling on the round-3 report 5913048688: B · 2026-09-30T14:14Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409.

    • What happened: os-zhuang APPROVED PR feat(spec): the picklist metadata kind — a shared option list select fields reference by name (#19518) #20823 at the reviewed head 388dcceb29 at 2026-09-30T13:57Z, and queued it at 2026-09-30T13:59Z. The round-3 push was then refused (GH006), because a queued branch cannot be updated.
    • B: feat(spec): the picklist metadata kind — a shared option list select fields reference by name (#19518) #20823 lands at 388dcceb29, which is the head the PASS 5912646092 and the approval both name. The four text cuts ride a follow-up PR from a fresh branch off the new main, carrying the dev's two commits (830102dc7e, f072bf2215, saved as patches). The ruled cut stays exactly as it is.
      • That PR touches packages/spec/src/data/** and content/docs/references/** only. Neither is governed, so it lands through the queue after its own at-tier review.
      • It is Part of #19518 and carries a patch changeset.
    • Not dequeued: the queue state is the approver's act, and the review rated the wording non-blocking.
    • The approval hand-off is complete: the needs-user-decision label and the outstanding review request came off after the approval.

    Generated by Claude Code

  4. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Landed: PR #20823 → addbbf02ab (the spec layer); the card stays open for two follow-ups · 2026-09-30T14:32Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409.


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
     "issue": 19518,
     "status": "done",
     "branch": "claude/issue-19518-picklist-wording",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/20878",
     "session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
     "premise_still_valid": true,
     "head": "3ccc350fab",
     "summary": "Follow-up per ruling 5913074894 (B), after #20823 landed as addbbf02ab. Branch claude/issue-19518-picklist-wording was cut from origin/main 07356a6ab0 (it contains addbbf02ab), and the empty branch was pushed first as the write probe. 830102dc7e and f072bf2215 were cherry-picked as 107b5e0518 and c9eca3df29, with identical patch-ids (cb436dd6... and 4bde9dac...). `check:generated --fix` then left the tree unchanged, so main had not moved the pages and nothing was regenerated by hand. Added `.changeset/19518-picklist-wording.md` ('@objectstack/spec': patch, `Clause-②: no`) as 3ccc350fab. Its one sentence holds for all four edits: the describe, two doc comments and the refusal no longer say that the reference is resolved and its options served. Opened draft PR #20878: body line 1 `Part of #19518`, paragraph 2 `Clause-②: no`, then two sentences and the session footer; relay read-back identical. Assignee os-justin was set via label-write.mjs and read back matching; it was not refused. No labels were written: none were named, and a changeset exists. check-governed-merges --branch HEAD: NOT governed, 0 of 6 paths, +16/-16. The old worktree /home/user/objectstack-issue-19518 was removed (node_modules first, no --force) after the content was confirmed on the new branch. This worktree is removed after this report.",
     "file_patch_ids": {
      "_method": "git diff 07356a6ab0 3ccc350fab -- FILE | git patch-id --stable. The five non-changeset files equal the round-3 per-file ids (git diff 74cb5c1a7c f072bf2215 -- FILE).",
      ".changeset/19518-picklist-wording.md": "59a7d3b4ba1fc4098672f24709f4e753305d9b5d (+7/-0)",
      "content/docs/references/data/field.mdx": "d4fc68fda9f4bab040f69f0469513ad89ee550fc (+1/-1)",
      "content/docs/references/data/object.mdx": "813c88a231d4caa0ed5f9311dc7ffae9847f63eb (+2/-2)",
      "content/docs/references/system/migration.mdx": "f6a4ac0cd2db431db7cd6e50dd5eaad2d070df9e (+2/-2)",
      "packages/spec/src/data/field.zod.ts": "a5786a127a1188c2637ff62425456858e29630f8 (+3/-7)",
      "packages/spec/src/data/picklist.zod.ts": "26cb02c430eba9ee3782ed8dba82641d6b85addb (+1/-4)"
     },
     "commit_patch_ids": "107b5e0518 cb436dd6aafc31b19b01e4b2dfc7cc754d1cded3 (= 830102dc7e); c9eca3df29 4bde9dacada4c96ee523a2662230df94f4d59386 (= f072bf2215); 3ccc350fab changeset only.",
     "tests": "At head 3ccc350fab, every run used os-verify-lock, and exit codes were captured before any pipe. One lock hold (VERDICT command-exit 0) ran four steps. `check:generated --fix` exit 0 ('All 15 generated artifacts are up to date', dist built by that run) left `git status` empty. `check:generated` exit 0 ('All 15 ... up to date'). spec `typecheck` exit 0 (test-typecheck: 52 files / 137 pinned signatures held). spec `vitest run --project local` exit 0: 580 files, 17136 passed, 1 todo. `dispatch-gates --commands` derives 102 families, and all 102 were run under the lock: 96 exit 0 and 6 exit 3 (PREREQUISITE NOT MET, because the fresh worktree has no built dist). The six are check:doc-formula-expressions and check:doc-security-posture (lint and formula dist), check:skill-examples (client-react dist), check:docs-transcript-drift (lint dist), check:lean-entry-closure (objectql dist) and check:dual-build-cjs-loads (a full `pnpm build`). A prerequisite build plus rerun of five of them was queued twice and got exit 99 both times, never acquired: 540s each, behind another agent's issue-20234 verify.sh (held 866s+) and then a full `pnpm build` from /home/user/objectstack-verify-18386. So this narrowing is declared: the six stay NOT MEASURED locally, and CI covers them (Lint & Repo Gates and all Type Check lanes are green below). `dispatch-gates --ran` (third lock attempt, VERDICT command-exit 0): '102 derived famil(ies) accounted for — 96 run, 6 NOT-MEASURED (6 DERIVED from a recorded exit 3)', exit 0. CI on 3ccc350fab, deduplicated by name keeping the newest started_at: 35 names, 33 success, 2 skipped (Console Pin Gate, Packed-tarball smoke (opt-in)), 0 failed, 0 running. Success: Auto Label, Build Core, Build Docs, Check Changeset, Check Documentation Links, Check PR Size, Dogfood Regression Gate (1/3, 2/3, 3/3, roster), Dogfood Verify CLI, Flag docs affected by code changes, Governed Surface Queue Guard, Lint & Repo Gates, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, Spec property liveness, Temporal Conformance (live PG + MySQL), Test Core (1/6 to 6/6, roster), The card this PR closes must claim this branch, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, TypeScript Type Check, filter. ci-failure.mjs --pr 20878: 'VERDICT: GREEN — all 35 check-run(s) completed, none failed', exit 0.",
     "mcp_calls": "0",
     "api_writes": "3 relay writes through scripts/pm (transport dispatch, as objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectstack/pulls (draft #20878; body read back identical); assign POST /repos/objectstack-ai/objectstack/issues/20878/assignees (os-justin, via label-write.mjs; read-back matches); comment POST /repos/objectstack-ai/objectstack/issues/19518/comments (this os-dev-report). Plus 2 git pushes of the new branch (the empty probe, then 07356a6ab0..3ccc350fab), which are not REST writes.",
     "open_questions": [],
     "out_of_scope_findings": []
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Landed: PR #20878 → 93d4e0ee6e, the wording follow-up · 2026-09-30T16:32Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409.

    • Landed: PR docs(spec): say only what holds before the picklist reference is resolved (#19518) #20878 merged through the merge queue at 2026-09-30T16:30Z as 93d4e0ee6e, with one parent, b1aab1e309.
    • Content check: each of the 6 files has the same git patch-id --stable as the reviewed head 3ccc350fab. The at-tier PASS is 5914782694.
    • Delivered: the four present-tense sentences about resolving the picklist reference are cut or restated in the describe, two docblocks and the pair-refusal message. The five generated doc rows are regenerated.
    • A fifth "supplies them" at field.zod.ts 2649-2650 was found by the review. It rides the next PR that edits field.zod.ts. fields: number rendering honours the authored useGrouping (1 key) #20313, now held by another seat, gets a pointer.
    • Still owed here: the Tier H docs PR, which covers the NORTH-STAR feature-map line, the two records-forms checklist items and the coverage.json picklist classification.

    Generated by Claude Code

  7. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Dispatched: the Tier H docs PR, the last follow-up on this card · 2026-09-30T20:13Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409.


    Generated by Claude Code

  8. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 19518,
      "status": "done",
      "branch": "claude/issue-19518-picklist-docs",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20938",
      "session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
      "premise_still_valid": true,
      "head": "8e7420019e",
      "summary": "Draft PR #20938 (Part of #19518, Tier H, assigned os-justin, labels documentation, size/m and skip-changeset) delivers the four files of dispatch 5918866874 on base aaad682dbc. Each seat fact was re-measured there. NORTH-STAR had no 共享选项集 (grep exit 1); line 13 defines the row format and line 24 uses 清单项待写. records-forms.json had 40 items, all active. coverage.json has keys $comment and metadataKinds and no picklist entry, while packages/spec/liveness/picklist.json exists. examples-upgrade.md line 11 is the 16-era fieldMappings source; the 'connector sync run' sentence is at line 67, under the line-61 heading. evals line 26 is as described. (1) NORTH-STAR: the card's line verbatim, ids picklist-shared-across-objects and picklist-org-append. It is placed after the last records row (search), so it ranks below every existing records capability; the PR body flags placement as the maintainer's priority call. (2) records-forms.json: two items, both status planned, since null, P2, mixed, with no steps, per README 'Implementation status'. No code outside packages/spec reads a picklist (liveness grades every key planned; check-stack-collection-maps holds picklists and picklistExtensions as PENDING rows for #19519), so neither item has anything to drive. picklist-shared-across-objects is phase 1: two objects served the same resolved options, a package extension value, the write door refusing an out-of-set value, and the locale relabel. It has three drafted acceptance clauses from the design of record and #19519's acceptance sentence, plus four negatives. picklist-org-append is phase 2: org A appends, A writes, B is refused. It has no acceptance clauses, because the overlay is undesigned. A knownGaps entry states it is not declared: the picklist registry row has allowOrgOverride false, and ruling 5904864936 defers the overlay to its own sub-issue. (3) coverage.json: picklist is a waiver, not items. The gate's own rule settles this: a kind whose only items are planned is UNMAPPED, the remedy is 'add an item that RUNS, or waive the kind with a reason', and an entry cannot hold both. The waiver gives the measured reason, names both planned ids, and states what retires it. Side effect: checklist-select capability:picklist matches nothing until the waiver flips to items. (4) examples-upgrade.md: #20903 retired connector.syncConfig and connector.fieldMappings whole. The D2 conversion connector-sync-keys-removed (toMajor 18) is inside the default `os migrate meta --from 16` terminus, and the fieldMappings tombstone points at a target-side mapping with connectorSource and a job. So three statements were false and now say what is true: the transform tombstone as the prescription, the connector 'landing raw values', and the report template's 'connector sync run against staging'. The file drops from 1197 to 1188 tokens at the same 119 lines. evals/protocol-major-upgrade.json eval 3 was read and is not false (it claims no sync run), so it is unchanged, per the four-file scope. Two standard-text points: the newest Claim (5905425409) names branch claude/issue-19518-picklist-kind while this branch is picklist-docs, which the parent's instruction and dispatch 5918866874 cover, so no claim was posted. That claim's `Clause-②: yes` belongs to the spec layer, and this PR releases nothing, so the line was not copied into the body and skip-changeset was applied (pr-automation route 2 names skills/ and docs/). Worktree node_modules and the worktree are removed after this report.",
      "tests": "All at head 8e7420019e unless stated; exit codes captured before any pipe. dispatch-gates --commands --repo objectstack-ai/objectstack (stderr: tree of objectstack-ai/objectstack at 8e7420019e; 4 paths vs merge base aaad682db; +111/-9) derives 25 families. All 25 ran: 24 exit 0, and check:platform-checklist exits 1 (below). pnpm --filter @objectstack/lint run check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET: no formula/lint dist). It exits 0 after `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2` under os-verify-lock (VERDICT command-exit 0, held 95s, waited 0s), with '22 record-scoped formula example(s) across 458 files / 1382 TS blocks judged clean'. dispatch-gates --ran: '25 derived famil(ies) accounted for — 25 run, 0 NOT-MEASURED (a DERIVED zero — all 25 recorded an exit code and none of them is 3)', exit 0. check:platform-checklist exits 1 on both trees. On aaad682dbc it reported 2 problems: 'coverage.json · picklist: UNCLASSIFIED' and 'areas/identity-auth.json: ABSENT SYMBOL … auth-plugin.ts#twoFactor'. At 8e7420019e it reports 1 problem, the same twoFactor anchor, which is pre-existing and untouched; self-test 221 assertions pass, and the 5 anchors added (PicklistServedFieldSchema, PicklistSchema, PicklistExtensionSchema, translateObject, DEFAULT_METADATA_TYPE_REGISTRY) resolve. gen:checklist-status: self-test 28 pass; records-forms 40 active / 2 planned; 264 active · 2 planned overall. checklist-select on the new id: 0 runnable, 1 PLANNED. check-skills-token-ratchet: 'examples-upgrade.md is 1188 tokens (ceiling 1197; headroom 9)', authored total 143461 to 143452, exit 0. check:skill-identifier-liveness OK (457 citations over 53 files). check:doc-authoring '53 published skill files clean'. check:nul-bytes OK, plus a manual control-byte scan of the 4 files (grep exit 1, none). check-governed-merges --branch HEAD: exit 3, GOVERNED, tier H, 2 of 4 paths (skills/** and docs/NORTH-STAR.md), 120 changed lines. Skill readings: examples-upgrade.md 119 to 119 lines, 4788 to 4751 bytes; package (all 10 SKILL.md) 4394 to 4394 lines. No ablation: docs-only, with no gate or test added. CI on 8e7420019e at 2026-09-30T20:38Z (one read, no polling): 33 check-runs, 10 success, 11 skipped, 12 in_progress, 0 failed.",
      "mcp_calls": "0",
      "api_writes": "4 REST writes in 3 relay dispatches through scripts/pm (transport dispatch, as objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectstack/pulls (draft #20938; 9303 bytes sent and stored, identical, re-read by REST and byte-equal); labels_add POST /repos/objectstack-ai/objectstack/issues/20938/labels (skip-changeset) plus assign POST /repos/objectstack-ai/objectstack/issues/20938/assignees (os-justin), via label-write.mjs, read back matching; comment POST /repos/objectstack-ai/objectstack/issues/19518/comments (this os-dev-report, via post-stamped.mjs). Plus 3 git pushes of the branch (the empty probe, then 2c41e486c8 and 8e7420019e), which are not REST writes.",
      "open_questions": [
        {
          "question": "The card's NORTH-STAR text includes 客户按组织追加值 and its second item names org append, but ruling 5904864936 defers the per-organization overlay to its own sub-issue on a measured customer requirement. As authored, the overlay is on the road and on the checklist as a planned requirement. Keep it?",
          "options": [
            "A: keep as authored. The line is verbatim, and records-forms.picklist-org-append is planned with a knownGaps entry naming the deferral. A planned item never runs and is never coverage, so nothing is claimed, but the overlay becomes a road item eligible for P2 under NORTH-STAR 优先级 rule 2 before a customer requirement is measured.",
            "B: trim the line to its phase-1 half and drop records-forms.picklist-org-append before this lands (an id that never landed is not a retired one). The overlay's line and item arrive with its sub-issue. The road then carries only ruled, scheduled work, at the cost of editing the card's dictated text."
          ],
          "recommendation": "A. The maintainer named per-organization extension as the motivating need on #18164 (the park's Restart-when). The design of record's verification sentence names it. The planned status is the ledger's honest form for a required-but-unbuilt capability. The maintainer merges this PR and can take B by deleting two strings."
        },
        {
          "question": "The card groups 'locale switch relabels' with the org item. It was authored on the phase-1 item (picklist-shared-across-objects) instead. Accept?",
          "options": [
            "A: as authored. Phase-1 behaviour (the translation face landed in #19518; resolution arrives with #19519) sits on the item #19519 can promote. Promotion is per item and needs a passing run, and #19519's acceptance sentence groups the relabel with phase 1.",
            "B: follow the card's grouping. The relabel then stays unverifiable until phase 2 lands, although it ships in phase 1."
          ],
          "recommendation": "A: B would leave a phase-1 capability with no runnable item."
        },
        {
          "question": "Where in step ② should the new line sit? It is after the last records row (search), so it ranks below every existing records capability.",
          "options": [
            "A: keep it last among the records rows. It is new, P2 and unbuilt, and the card says it is taken after the open product P0/P1.",
            "B: move it beside the forms row (表单能用 … 级联选项), grouping it with option behaviour and raising its rank."
          ],
          "recommendation": "A: 改它即改优先级, and the lowest-disruption placement is the one that raises nothing."
        }
      ],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · scripts/check-platform-checklist.mjs: the --self-test success line ('driven on fixtures rather than on a ledger that carries none of it') and two comments (BATTERY_PLANNED_STATUS roster note; selfTestPlannedStatus docblock) state the live ledger carries zero planned items. This PR makes that prose stale (2 planned); assertions are unaffected, 221 pass · noted, not filed (drift, not one of the three classes). Named in the PR's Acceptance notes.",
        "carrier: the daily platform-checklist-watchdog workflow (files or refreshes one issue while the gate is red) · check:platform-checklist is red on origin/main aaad682dbc for areas/identity-auth.json ABSENT SYMBOL packages/plugins/plugin-auth/src/auth-plugin.ts#twoFactor, identically before and after this diff · noted, not filed.",
        "carrier: the seat · the Path: lines on #19518 and #19519 still read 清单项待写. Once #20938 lands they can name records-forms.picklist-shared-across-objects and records-forms.picklist-org-append · noted, not filed.",
        "carrier: 承接者:无 · the #19518 card body cites 'ADR-0136 D2.4', but this repo's ADR registry has no 0136 (git grep ADR-0136 and 0136- give 0 hits in docs/adr). If it is a cloud ADR, AGENTS.md #13 spells it 'cloud ADR-0136'. Neither new item cites it · noted, not filed."
      ]
    }

    Generated by Claude Code

  9. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Ruling on report 5919353754 (the Tier H docs PR) · 2026-09-30T20:42Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409.


    Generated by Claude Code

  10. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 19518,
      "status": "done",
      "branch": "claude/issue-19518-picklist-docs",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20938",
      "session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
      "premise_still_valid": true,
      "head": "cab0e1b557",
      "summary": "Cut round per coordinator message and review 5919896214 (PASS at 8e7420019e). The worktree was recreated at 8e7420019e and the route checked (transport dispatch). The coordinator asked for the smaller true edit of two; the four review cuts follow, one append-only commit cab0e1b557, with no main merge (main moved, but none of the five paths) and no rebase. (i) examples-upgrade.md: the smaller true edit was the template's chain line, '**Chain:** 16 → 17' to '16 → 18' (the chain the default `os migrate meta --from 16` replays: terminus max(17, MIGRATION_MAJORS) = 18). The walkthrough now matches sentence 1. The heading 'Protocol 16 → 17 upgrade' and 'replay-from-17 applies 0' stay true under SKILL.md's own box: `--to` defaults one past the installed major, and replay-from-17 applies nothing once the 18-step edits are ported. It is a same-length edit: 4751 bytes, 1188 tokens, 119 lines. (ii) 'nothing outside packages/spec reads a picklist' became 'no runtime reads a picklist' in the records-forms history (≈:4234) and the coverage waiver (≈:229). Measured at 8e7420019e: objectql, metadata, metadata-core, metadata-protocol, runtime and rest src (non-test) carry the word 3 times, all in comments. The CLI's walkPicklists (i18n-extract.ts) reads picklists only to emit translation keys. (iv) scripts/check-platform-checklist.mjs: FOUR sentences, not three, said the live ledger has zero planned items: the :1059 roster comment, the :2280 docblock, the :2541 self-test success string and the :2622 comment ('planned count is the 0 this gate prints'). Each now states the true condition, that no coverage.json entry maps a planned item, which is why the fixtures are still the only witness. The :2541 string lost 'rather than on a ledger that carries none of it'. No test pins that text: git grep outside the file gives 0 hits, and no *.test.* names the script. Not changed: the same success line's 'the N live items are judged exactly as before' now counts the 2 planned items among N; the non-planned items are judged as before. (iii) The PR body was NOT edited. os-dev.md says a dev writes the body once, at pr_create, never PATCHes it, and names the edits for the seat to write. The seat's own adoption in 5919896214 says it writes the final 速读 at ACCEPT. This conflicts with the coordinator's instruction to edit the body; the standard wins, and the exact edits are in open_questions[0] for the seat. The PR is now 5 files, +119/-17, still Tier H (2 of 5 paths). The worktree is removed after this report.",
      "tests": "At head cab0e1b557; exit codes captured before any pipe. dispatch-gates --commands --repo objectstack-ai/objectstack derives 43 families (5 paths vs merge base aaad682db; +119/-17). All 43 ran. 42 exit 0, and check:platform-checklist exits 1 on the pre-existing twoFactor anchor: '1 problem(s)', only 'areas/identity-auth.json: ABSENT SYMBOL … auth-plugin.ts#twoFactor'; self-test 221 assertions pass, and its success line now reads 'the `planned` status is driven on fixtures — the accept set widened…'. check:doc-formula-expressions first exited 3 (no dist in the fresh worktree). It exits 0 after a locked build of formula and lint (os-verify-lock VERDICT command-exit 0, waited 155s, held 2s, 4/4 cached). check:pm-dispatch-gates exits 0: 'dispatch-gates self-test: 1976 cases pass', 1058.6s, run in the background and awaited in the foreground on its recorded PID. The script's own suite (rule ⑤) is its --self-test, which ran inside check:platform-checklist; no *.test.* names the script, and the derived self-test families (check-self-test-wired, check-self-test-workflow-commands, check-comment-mask-corpus, check-scripts-symbol-anchors, check-declaration-mirrors) all exit 0. dispatch-gates --ran: '43 derived famil(ies) accounted for — 43 run, 0 NOT-MEASURED (a DERIVED zero — all 43 recorded an exit code and none of them is 3)', exit 0. check-skills-token-ratchet exits 0: 'examples-upgrade.md is 1188 tokens (ceiling 1197; headroom 9)'. Skill readings: examples-upgrade.md 119 lines / 4751 bytes (unchanged by this round); all 10 SKILL.md 4394 lines. check-governed-merges --branch HEAD: exit 3, tier H, 2 of 5 paths, 136 changed lines. Control-byte scan of the 4 edited files: grep exit 1 (none). CI on cab0e1b557 at 2026-09-30T21:40Z, one read: 31 check-runs, 22 success, 8 skipped, 1 in_progress, 0 failed.",
      "mcp_calls": "0",
      "api_writes": "1 REST write in 1 relay dispatch: comment POST /repos/objectstack-ai/objectstack/issues/19518/comments (this os-dev-report, via post-stamped.mjs). Plus 1 git push (8e7420019e..cab0e1b557), which is not a REST write. No PR body edit, and no label or assignee write.",
      "open_questions": [
        {
          "question": "The PR body edits this round owes, for the seat to write (the dev does not PATCH a PR body). Apply them at ACCEPT together with the final 速读?",
          "options": [
            "A: the seat applies E1 to E8 verbatim. E1, first paragraph: 'Four files' becomes 'Five files'. E2, What changes: add item 5 '`scripts/check-platform-checklist.mjs`: four sentences said the live ledger carries zero planned items; they now say no coverage.json entry maps a planned item', and append to item 4 'The report template's chain line now reads 16 → 18, the chain the default run replays.' E3, the How section: 'no code outside `packages/spec` reads a picklist yet' becomes 'no runtime reads a picklist yet'. E4, Local verification: head cab0e1b557, 43 families, 43 run, 0 NOT-MEASURED; check:pm-dispatch-gates exit 0; governed 2 of 5 paths, +119 / -17. E5, Acceptance notes bullet 1 becomes '`scripts/check-platform-checklist.mjs` said in four places that the live ledger carries zero planned items; this PR corrects them (cab0e1b557). Carrier: this PR.' E6, 速读 改了什么 third bullet becomes 'upgrade 技能示例改正三处:第一句把处方指向一个已不存在的 `transform` 墓碑;第二、三句说连接器同步跑过、落过数据,实际从未有引擎跑过。报告模板的链改为 16 → 18。' E7, 速读 你要做的 becomes one action: '合并本 PR(Tier H:需您亲手合并,或给出授权的 APPROVED 后由席位落地)。' E8, 速读 风险与代价: '回滚是 revert 两个提交' becomes '回滚是 revert 三个提交'.",
            "B: the coordinator re-authorizes a dev PATCH of the body under os-dev.md's rule, and a later round applies A."
          ],
          "recommendation": "A: os-dev.md reserves body writes after pr_create to the seat, and the seat's adoption in 5919896214 already plans to write the final 速读 at ACCEPT."
        }
      ],
      "out_of_scope_findings": [
        "carrier: this PR · the stale 'zero planned items' prose that last round's report gave as carrier none is now corrected here, in four places, not three · closed in cab0e1b557."
      ]
    }

    Generated by Claude Code

  11. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Landed: PR #20938 → c1602ba429 (the Tier H docs follow-up); the card closes · 2026-09-30T23:26Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5905425409.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions