You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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 runtime layer — metadata loading and the engine, domain:engine: packages/metadata*, packages/objectql, packages/platform-objects)
Load*.picklist.ts before objects; register the kind in the metadata registry; picklistExtensions from any package merge additively into the named picklist (duplicate value = refused loudly, ⛔ not last-wins).
Resolve at serve time: a select field with picklist: name is served with the resolved options (merged base + extensions, translated per the request locale through the translation face the spec sub-issue declares); an unknown picklist name is a loud load-time error naming the field and the package, ⛔ never an empty option list.
Write validation uses the resolved set at the write door (the same door that validates inline options today); the refusal names the picklist.
hotcrm acceptance: the reference app migrates its shared lists (src/objects/_picklists.ts, 17 consumers across three packages) — filed as a hotcrm card by the epic PM when this lands; ⛔ not in this PR.
Phase 2 (⛔ not here): per-organization overlay in sys_metadata with allowOrgOverride: true and an overlay schema that accepts new values only; Studio surfaces (the objectui sub-issue).
Acceptance
One dogfood case (ADR-0136 D2.4): one picklist, two objects, a package extension adds a value, object A writes it, a value outside the set is refused on object B, a locale switch relabels. Engine tests pin: load order, merge, unknown-name refusal, write refusal, served shape. check:engine-* families green.
Pointer from the #19518 spec layer (PR #20823): runtime enumerations and gaps that this card inherits · 2026-09-30T13:53Z
domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1). ⛔ Not a claim; no state change here. These come from the #19518 dev reports 5908082075 / 5912287363 and the at-tier review record 5912646092 on PR #20823. When PR #20823 lands, these are what resolving field.picklist at runtime still owes:
Kind enumerations that do not list picklist yet.objectqlengine.tsMETADATA_ARRAY_KEYS; metadataplugin.tsARTIFACT_FIELD_TO_TYPE; runtimeapp-plugin.tsAPP_CATEGORY_KEYS / SECURITY_FIELDS; metadata-protocol reference sites (field.picklist is a new cross-kind reference); metadata-coretypes.ts's lockstep enum; and, found by the review, packages/metadata/src/serializers/typescript-serializer.tsANNOTATION_BY_METADATA_TYPE. scripts/check-stack-collection-maps.mjs carries PENDING waiver rows for the ones it knows, and they fail stale when this card lands.
The served-shape round trip. A served picklist-bound field carries both picklist and the resolved options (PicklistServedFieldSchema). A client that PUTs the served object back is refused at the field door, loudly and with a prescription. The write path either strips resolved options for a resolvable picklist or keeps refusing.
resolveObjectFieldLabels. The field-labels endpoint returns field-level option labels only, so picklist-inherited labels are missing there. The server-side translateObject does carry them.
Pointer: when this card resolves picklists at runtime, the #18386 import template must see the same options the engine sees · 2026-09-30T17:09Z
domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1). ⛔ Not a claim; no state change. This comes from the #18386 fix PR #20904's report.
The link: the import template now stars a required column only when the engine fills no insert-time default, and a picklist option marked default: true counts as such a default. On main nothing resolves a picklist reference into options, so the template's object read and the engine's registry schema both see none, and they agree.
The obligation when this card lands: the resolved options have to reach BOTH sides. If only the object read carries them, a picklist option marked default: true would unstar a column that the engine still refuses when it is left blank.
Where to pin it: add a picklist shape to the parity test in packages/rest/src/import-template-route.test.ts. It checks, for each shape, that the template stars a column exactly when the real import door refuses a blank in it.
Claim: PM loop round 1
Session: session_01Ujdtvqs7ree7WyQmEDwEnG (dispatching seat; the dev runs as a cloud session named in the dispatch record)
Account: os-litant (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-19519-picklist-runtime
Worktree: objectstack-issue-19519 (in the cloud session's own container)
Domain: domain:engine
Seat: domain:engine#2 (seat post #20966; runs the lane queue by the maintainer's order recorded on #6367)
File surface (the body's scope items 1 to 3 and its Acceptance, with the two pointers 5912707861 and 5916040159):
Load and register the picklist kind: packages/metadata (the loader, plugin.tsARTIFACT_FIELD_TO_TYPE, serializers/typescript-serializer.tsANNOTATION_BY_METADATA_TYPE), packages/metadata-core (types.ts's lockstep enum), packages/objectql/src/engine.tsMETADATA_ARRAY_KEYS (near :2889). picklistExtensions merge additively; a duplicate value is refused loudly.
Resolve at serve time: a select field with picklist: name is served with resolved options, translated per locale (PicklistServedFieldSchema). An unknown name is a loud load-time error naming the field and the package. This covers the field-labels path (resolveObjectFieldLabels) and the served-shape round trip (a PUT of the served object).
Write validation against the resolved set, at the door that validates inline options today. The refusal names the picklist.
Declared cross-lane touches (domain:cli): packages/runtimeapp-plugin.tsAPP_CATEGORY_KEYS / SECURITY_FIELDS, and the import-template parity pin in packages/rest/src/import-template-route.test.ts (pointer 5916040159).
scripts/check-stack-collection-maps.mjs PENDING waiver rows retire as their maps gain picklist (gate wiring: declared cross-lane, domain:spec). The liveness ledger row field.picklist flips from planned to live.
One dogfood case (ADR-0136 D2.4), and engine pins for load order, merge, unknown-name refusal, write refusal and served shape. .changeset/19519-*.md.
Stop on breach and explain in the report.
⛔ Not phase 2 (the sys_metadata per-organization overlay, Studio surfaces), and ⛔ not the hotcrm migration (scope item 4: a hotcrm card filed by the epic PM on landing).
Dispatch record for claim 5923202473 (domain:engine#2 · session_01Ujdtvqs7ree7WyQmEDwEnG · 2026-10-01T02:00Z): the dev runs as cloud session session_01MZu5JqVPacMktogpMxq9Xu ("⚡ engine #19519 picklist runtime"), with outcome branch claude/issue-19519-picklist-runtime and model claude-opus-5-5. Its report arrives on this card as an os-dev-report comment. ⛔ Not a second claim.
os-dev-report
{
"issue": 19519,
"status": "done",
"branch": "claude/issue-19519-picklist-runtime",
"pr": "#21047",
"session": "session_01MZu5JqVPacMktogpMxq9Xu",
"premise_still_valid": true,
"summary": "The runtime layer of the picklist kind is implemented in objectql, with the artifact door, the TS-serializer annotation, the message catalog and the ledgers following it. (1) Load: picklists / picklistExtensions join METADATA_ARRAY_KEYS and register through the shared registerMetadataCollections seam; ARTIFACT_FIELD_TO_TYPE maps picklists: picklist. (2) Merge: extensions append additively; a repeated value is refused 422 INVALID_METADATA naming both declarations, in either registration order, never last-wins. (3) Serve: the registry's object fold writes the resolved options onto every picklist-bound field and keeps picklist, so every /meta read, sys_metadata bodies and the write door share one set; resolution is idempotent and drops stale options when the list is gone. (4) Unknown name: the boot fails at kernel:ready naming each field (and each orphan extension) and its package; after the seal, a late artifact is checked before anything registers. (5) Write door: judged against the resolved set, the refusal names the picklist, and an unresolved field accepts nothing. Measured H1-H5. H1 holds: both enumerations lacked picklist. H2 is partly falsified: only METADATA_ARRAY_KEYS and ARTIFACT_FIELD_TO_TYPE carried PENDING rows; APP_CATEGORY_KEYS and SECURITY_FIELDS carry DELIBERATE rows and stay unchanged; metadata-core's enum is not lockstep (it already lacks seed) and has no picklist reader, so it is left alone. H3 has two live readings (open_questions). H4 is pinned. H5 needs no new code: INVALID_METADATA is already in objectql's ADR-0112 ledger, so Clause-② stays no. Merged origin/main twice (clean; the second merge at 4bb0dad). The card assignee was already os-litant and was not written; the PR assignee was set to match.",
"tests": "Final head 4bb0dad. Measurements were taken at a1e3908 / 881c31f. The two later commits are test-double fixes plus a main merge that only touched test-typecheck ledgers; the gates and typechecks they affect were re-run green after them. objectql pnpm test (before the second merge): Test Files 351 passed, Tests 6851 passed. objectql pnpm typecheck green on the final merged tree, and so are metadata and rest typecheck. metadata pnpm test: 836 passed. New and changed pins: engine-picklist.test.ts 25/25; plugin-picklist-boot-audit.test.ts 6/6 (real ObjectKernel); protocol-picklist-served-roundtrip.test.ts 2/2; rest import-template-route.test.ts 31/31 (new parity row picklist_option_default, which passes only if the engine read the resolved default); dogfood picklist-shared-across-objects 5/5, plus multi-package-artifact, 14/14 re-run post-merge after rebuilding the dogfood closure; metadata typescript-serializer-annotation green inside the metadata suite; spec validation-message.test.ts green; lint lint-liveness-properties.test.ts green; metadata-protocol code-only-types / reference-sites derivation / meta-types-degenerate green. Ablation (one-time, not kept): scripts/ablation-replace.mjs replaced return this.resolvePicklistFields(merged); with return merged; in registry.ts (anchor 1 to 0, blob 24f69343 to 253ad400). engine-picklist.test.ts went 8 failed / 16 passed of 24. Restored: blob == HEAD 24f6934320bf and git diff HEAD is empty. The direction observed was red, as expected. Gates: dispatch-gates --commands derived 114 families; all were run. --ran reconciliation with exit codes: 113 run, 1 NOT-MEASURED. check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET: no dist for 8 packages outside this diff. Non-zero, kept: check-empty-changeset exit 1, the deliberate correction of the pending 19518 changeset (open_questions); check:platform-checklist exit 1, reproduced identically on origin/main 2f2fa11, not this PR's. Fixed and re-run green: check:objectql-double-limit and check:slot-lookup (both were my new test doubles). Shallow-clone refusals that passed after the prescribed deepening: check-engine-split-ratio, check-plugin-teardown-shape --self-test. Extra: check:liveness, check:stack-collection-maps (+ --self-test), check:startup-registry-verdict, check:durability-log-level, check:doc-authoring, check:nul-bytes, check:engine-double-contract all exit 0. eslint narrowed to the 16 touched TS/MJS files: 0 errors / 0 warnings. The repo-wide pnpm lint and the full check farm are CI's (not run). Driver conformance ledger: not run (no driver or fake-engine file in the diff).",
"mcp_calls": "3 — mcp__github__issue_read (get, get_comments x2); all reads, no MCP write tool",
"api_writes": "3 — all via the scripts/pm fleet-write relay (repository_dispatch, landing as objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectstack/pulls (#21047, draft); label-write assign POST /repos//issues/21047/assignees (os-litant); os-dev-report POST /repos//issues/19519/comments. git push is not counted.",
"open_questions": [
{
"question": "H3: writing back the served object. GET /meta/object/NAME serves picklist + resolved options; a PUT of that body is refused 422 INVALID_METADATA by FieldSchema with its prescription (measured, pinned in protocol-picklist-served-roundtrip.test.ts). Keep refusing, or strip resolved options at the write door?",
"options": [
"A — keep refusing (this PR). Business: the real writer of a served body is the Studio object designer (the GET, edit, PUT round trip registry.ts records at #8027). Under A it is refused on any object with a picklist-bound field until Studio drops options when picklist is set — a producer-side change for the phase-2 objectui sub-issue, and before hotcrm's 17 consumers migrate. Long-term: one strict authoring shape; it matches PicklistServedFieldSchema's declared contract. AI-safety: an author or AI that writes both keys is refused loudly. Startup scope: costs nothing now.",
"B — strip options at the metadata write door when picklist resolves and the options equal the resolved list (declared and tested, e.g. as an ADR-0087 conversion entry). Business: Studio keeps working without a change. Long-term: a second accepted shape at an authoring door, which is consumer-side tolerance, and the stored row may disagree with the served one. AI-safety: worse, because a stale or equal copy is silently absorbed. Startup scope: a new conversion surface with no external user named."
],
"recommendation": "A, on all four axes: the spec already declares the refusal (spec over implementation), it is contract-first, and it makes the wrong shape loud. The cost lands on Studio, which must fix the producer before picklist-bound objects become common. That is a dependency for the phase-2 objectui card and the hotcrm migration card, to be named when the epic PM files them."
},
{
"question": "Confirm the correction of a pending release note. .changeset/19518-picklist-kind.md (unreleased) said the release does not resolve the reference and the field is served without options. With this PR in the same release that is false, so this PR replaced that sentence with one pointing at the runtime entry. check-empty-changeset stays red until someone confirms (its documented deliberate-correction path).",
"options": [
"A — confirm the correction (keep the PR's edit)",
"B — restore the original sentence and let the release author reconcile the two notes at release time"
],
"recommendation": "A: restoring republishes a sentence this PR makes false. The edit is one sentence, named in the PR body."
},
{
"question": "resolveObjectFieldLabels (GET /api/v1/i18n/labels/OBJECT/LOCALE) reads only the bundle and has no field-to-picklist binding, so picklist-inherited option labels are absent there while /meta carries them. The fix needs service-i18n and the runtime i18n dispatcher, both outside this claim. Separate card?",
"options": [
"A — a follow-up card on service-i18n plus the runtime dispatcher, passing the object's field-to-picklist binding",
"B — leave it: clients read translated options from /meta/object"
],
"recommendation": "A only if a consumer of the labels endpoint is named; otherwise B under startup focus. NOT MEASURED which clients read option labels from that endpoint."
}
],
"out_of_scope_findings": [
"class: a · reach: public gate — node scripts/check-platform-checklist.mjs exits 1 on origin/main 2f2fa11 (ABSENT SYMBOL packages/plugins/plugin-auth/src/auth-plugin.ts#twoFactor in docs/qa/platform-checklist/areas/identity-auth.json), so every PR's pnpm check:platform-checklist is red · evidence: the identical failure on a clean origin/main worktree, measured in this run · dedupe words: platform-checklist, identity-auth, twoFactor, ABSENT SYMBOL",
"carrier: 承接者:无 · noted, not filed — examples/app-showcase/src/coverage.ts still waives picklistExtensions (and KIND_COVERAGE.picklist) as 'ahead of the runtime merge'; demonstrating it is example-app work outside this claim",
"carrier: checklist seat (checklist-test) · noted, not filed — docs/qa/platform-checklist records-forms.picklist-shared-across-objects / picklist-org-append and coverage.json still read 'no runtime behaviour to drive yet'; they can be re-run against this PR's runtime",
"carrier: 承接者:无 · noted, not filed — under os dev HMR, metadata:reloaded re-ingests objects but not picklists or picklistExtensions, so an edited list reaches the registry only on a full manifest re-registration (not measured)",
"carrier: 承接者:无 · noted, not filed — metadata-core MetadataTypeSchema calls itself lockstep with the spec kernel enum but lacks seed and picklist; no reader of picklist through it was found, so not widened here"
]
}
Seat answer — #19519's three open questions (report 5924129203): Q1 A, Q2 A (through the contract review), Q3 B; in-seat, open to veto
domain:engine#2 (seat post #20966) · session_01Ujdtvqs7ree7WyQmEDwEnG · 2026-10-01T03:43Z. Open to the maintainer's veto; a veto lands before the PR is queued.
Q1 — a PUT of the served object (picklist + resolved options): A, keep refusing
That round trip is refused on an object with a picklist-bound field until Studio drops options whenever picklist is set.
That is producer-side work for the Studio half, objectui#10202 (pm:blocked, phase 2). The seat carries the pointer there at landing.
Today no shipped object binds a picklist; hotcrm's 17 use sites are not migrated yet.
Q2 — the correction of the pending .changeset/19518-picklist-kind.md: A, confirmed through the contract review record
The landing rule for a DELIBERATE CORRECTION applies: check-empty-changeset stays red by design on this head. The at-tier review record confirms it by naming the corrected note and judging the rewritten sentence; no maintainer wait is needed.
The PR then rides that one red into the queue only when all three hold:
the gate is red by design;
it does not run on merge_group;
a PR comment records it.
Restoring the old sentence (B) would publish a sentence this PR makes false.
Q3 — picklist option labels absent from GET /api/v1/i18n/labels/:object/:locale: B for now
No consumer of that endpoint's option labels is named, and none was measured. /meta/object carries the translated options, and that is the read this card serves.
os-dev-report
{
"issue": 19519,
"status": "done",
"branch": "claude/issue-19519-picklist-runtime",
"pr": "#21047",
"session": "session_01MZu5JqVPacMktogpMxq9Xu",
"premise_still_valid": true,
"summary": "Patch round 1, on the seat's FAIL record (head 4bb0dad). (1) BLOCKING fixed. The dogfood file cited ADR-0136 D2.4, an ADR that does not exist: docs/adr has 0135 and 0137 and no 0136, measured. It now cites ADR-0054, which requires a runtime proof of a live authorable property and is the decision this dogfood case pins. check:adr-anchors exit 0; no allowlist row was added. The PR body still reads 'ADR-0136 D2.4' once, in the dogfood bullet under '## Tests'. The body was written once at pr_create and I do not PATCH it. Suggested seat edit: replace 'the ADR-0136 D2.4 case' with 'the ADR-0054 runtime proof'. (2) Escalated question, measured. metadata-protocol's derived index REFERENCE_SITES.byTarget.get('picklist') yields [{fromType: field, property: picklist}, {fromType: object, property: picklist}, {fromType: translation, property: picklists}]. It is derived by the naming rule in reference-sites.ts (rule 1, 'its name spells T'; deriveReferenceSites, line 445), so there is no row to add. Pinned: reference-sites.derivation.test.ts now asserts object.fields.picklist is a site of target picklist. (3) Q1 A / Q2 A / Q3 B noted from seat answer 5924290772; no action. Merged origin/main again (8f78495, clean; it auto-merged import-template-route.test.ts, and the parity row survives). Head 42d750f.",
"tests": "Head 42d750f. Rebuilt the rest closure after the merge. rest import-template-route.test.ts 37/37 (main added cases; picklist_option_default kept). objectql engine-picklist + plugin-picklist-boot-audit + protocol-picklist-served-roundtrip 33/33. objectql and rest typecheck green. metadata-protocol reference-sites.derivation.test.ts 22/22 (new pin included); metadata-protocol typecheck green. The new pin was not ablated. Lint family (CI skipped steps 11-192 on the old head): check:adr-anchors 0, check:error-code-casing 0, check:error-code-provenance (spec) 0, check:stack-collection-maps 0; eslint --no-inline-config on the 17 touched TS/MJS files: 0 errors, 0 warnings (the repo-wide pnpm lint is CI's). dispatch-gates --commands (no paths) derived 114 families on 42d750f (the same list as before); all run. --ran with exit codes: 112 run, 2 NOT-MEASURED, both PREREQUISITE NOT MET exit 3 on this fresh worktree: check:dual-build-cjs-loads (dist of 8 packages outside the diff) and check:type-check-debt (it needs every package's dist; lint.yml builds the closure first). Non-zero, kept: check-empty-changeset exit 1, the confirmed deliberate correction (seat Q2 A). check:platform-checklist exit 1, the twoFactor ABSENT SYMBOL in areas/identity-auth.json, which reproduces on a clean origin/main 8f78495 worktree (exit 1), so it is base-side. All other 110 exit 0.",
"mcp_calls": "0 this round (3 reads in round 0, all issue_read; no MCP write tool ever)",
"api_writes": "1 this round — the os-dev-report comment, via scripts/pm/post-stamped.mjs and the fleet-write relay: POST /repos//issues/19519/comments. git push is not counted. Round 0's 3 writes are reported in comment 5924129203.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public gate — pnpm check:platform-checklist exits 1 on origin/main 8f78495 (and 2f2fa11), ABSENT SYMBOL packages/plugins/plugin-auth/src/auth-plugin.ts#twoFactor in docs/qa/platform-checklist/areas/identity-auth.json; it reds Lint for every PR · evidence: the clean-main worktree run in both rounds · dedupe words: platform-checklist, identity-auth, twoFactor, ABSENT SYMBOL (same finding as round 0, still live)"
]
}
ACCEPT — PR #21047 @ 42d750f1 (picklist runtime: served options, additive extensions, write validation; phase 1 of #18164)
domain:engine#2 (seat post #20966) · session_01Ujdtvqs7ree7WyQmEDwEnG · 2026-10-01T05:24Z. Judged against GitHub, not the reports (5924129203, 5924919167).
Form: draft PR on main. The body opens Fixes #19519 / Clause-②: no, its only closing keyword. The seat replaced the body's one stale ADR-0136 D2.4 mention with ADR-0054 runtime proof before this record, because the squash message is the body.
Scope: 26 files, inside claim 5923202473 and the dispatch's declared cross-lane touches:
objectql: picklist-resolution.ts (new), the registry fold, plugin.ts's boot audit, record-validator.ts, and engine.tsMETADATA_ARRAY_KEYS;
metadata: the artifact door and the TS serializer annotation;
spec: the message text and the liveness ledger regrade;
check-stack-collection-maps.mjs rows retired;
tests in objectql, metadata-protocol, rest (the import-template parity row), lint and dogfood;
two changesets: its own, and the deliberate correction of .changeset/19518-picklist-kind.md.
Not governed. +1579 / −78.
Contract reviews:
FAIL 5924563914 @ 4bb0dadc, on one ground: a bare ADR-0136 citation turned check:adr-anchors red. The number came from this seat's dispatch order.
Delta PASS 5925299679 @ this head. The fix cites ADR-0054 (it exists, Accepted); the reference-sites pin was added. 24 of 26 net hunks are byte-identical to the reviewed head, and the merge of main is clean. Clause-②: no, with objectql minor, spec patch and metadata patch, holds.
CI on 42d750f1: 42 check-runs: 35 success, 5 skipped on the roster (check-expected-skips --pr 21047: OK, exit 0), and 2 × Check Changeset red by design. The PR merges cleanly onto main (git merge-tree). All seven required contexts are green, including Lint & Repo Gates, which on this head ran the 183 families that were skipped on the prior head.
The by-design red rides into the queue, all three conditions recorded in 5925299679:
The gate's annotation names the DELIBERATE CORRECTION class. The corrected note's hunk is byte-identical to the one confirmed earlier, and the sentence is re-read true on this head.
pr-automation.yml triggers on pull_request only, with no merge_group leg.
That record is the PR comment that states it.
Open questions (seat answer 5924290772): Q1 A, a PUT of the served object stays refused. The named cost, Studio's object-designer round trip, belongs to objectui#10202 (phase 2), and the seat carries a pointer there at landing. Q2 A, confirmed through the reviews. Q3 B.
The four noted items are Acceptance notes with their carriers: the showcase coverage.ts waiver, the checklist items, HMR not re-ingesting picklists (not measured), and metadata-core's non-lockstep enum.
Landing: this seat readies and arms the PR through the queue.
domain:engine#2 (seat post #20966) · session_01Ujdtvqs7ree7WyQmEDwEnG · 2026-10-01T06:09Z.
Merged through the merge queue at 2026-10-01T06:08Z as squash 88b484e00 on main. The PR object and origin/main's log agree. The squash carries the PR's 26 files (1579 insertions, 78 deletions).
Records it landed on:
seat answer 5924290772;
review FAIL 5924563914, then delta PASS 5925299679 @ 42d750f1;
ACCEPT on this card.
The Check Changeset red rode in by design, under the three conditions that record states.
A select field that names picklist: 'NAME' is served with the resolved options (base plus package extensions, translated).
Writes are validated against that set, and the refusal names the picklist.
An unknown picklist name fails the boot, naming the field and the package.
A duplicate extension value is refused, ⛔ not last-wins.
A PUT of the served object (picklist + options) stays refused, per ruling 5904864936.
The card closes completed by the PR's Fixes #19519. pm:dispatched is removed in the same act as this record. The cloud session session_01MZu5JqVPacMktogpMxq9Xu is archived after this record.
Downstream, other lanes (their unlock scans act; this seat changes no state there):
Activity
objectstack-fleet commentedon Sep 30, 2026
Pointer from the #19518 spec layer (PR #20823): runtime enumerations and gaps that this card inherits · 2026-09-30T13:53Z
domain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1). ⛔ Not a claim; no state change here. These come from the #19518 dev reports5908082075/5912287363and the at-tier review record5912646092on PR #20823. When PR #20823 lands, these are what resolvingfield.picklistat runtime still owes:picklistyet.objectqlengine.tsMETADATA_ARRAY_KEYS;metadataplugin.tsARTIFACT_FIELD_TO_TYPE;runtimeapp-plugin.tsAPP_CATEGORY_KEYS/SECURITY_FIELDS;metadata-protocolreference sites (field.picklistis a new cross-kind reference);metadata-coretypes.ts's lockstep enum; and, found by the review,packages/metadata/src/serializers/typescript-serializer.tsANNOTATION_BY_METADATA_TYPE.scripts/check-stack-collection-maps.mjscarries PENDING waiver rows for the ones it knows, and they fail stale when this card lands.picklistand the resolvedoptions(PicklistServedFieldSchema). A client that PUTs the served object back is refused at the field door, loudly and with a prescription. The write path either strips resolved options for a resolvable picklist or keeps refusing.resolveObjectFieldLabels. The field-labels endpoint returns field-level option labels only, so picklist-inherited labels are missing there. The server-sidetranslateObjectdoes carry them.picklistmetadata kind — a shared option list select fields reference by name (#19518) #20823 cuts the present-tense "the server resolves the reference" wording until then. The ledger rowfield.picklistisplanned+authorWarn, and it flipslivewith this card's reader.Generated by Claude Code
objectstack-fleet commentedon Sep 30, 2026
Pointer: when this card resolves picklists at runtime, the #18386 import template must see the same options the engine sees · 2026-09-30T17:09Z
domain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1). ⛔ Not a claim; no state change. This comes from the #18386 fix PR #20904's report.default: truecounts as such a default. Onmainnothing resolves apicklistreference intooptions, so the template's object read and the engine's registry schema both see none, and they agree.default: truewould unstar a column that the engine still refuses when it is left blank.packages/rest/src/import-template-route.test.ts. It checks, for each shape, that the template stars a column exactly when the real import door refuses a blank in it.Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Triage: unlocked. #19518 landed, so
pm:blocked→pm:queueTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-01T00:02Z. ⛔ Not a claim, ⛔ not a dispatch.Measured: #19518 is closed
completed. The spec layer, PR #20823, is onmain.The next claim reads, in order:
picklistcollection,Field.select({ picklist }), server-resolved options, translation face (phase 1 of objectstack#18164) #19518's runtime enumerations and gaps (5912707861), and the import-template parity obligation (5916040159);Unchanged:
priority:p2·domain:engine·area:records.Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Claim: PM loop round 1
Session:
session_01Ujdtvqs7ree7WyQmEDwEnG(dispatching seat; the dev runs as a cloud session named in the dispatch record)Account:
os-litant(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-19519-picklist-runtimeWorktree:
objectstack-issue-19519(in the cloud session's own container)Domain:
domain:engineSeat:
domain:engine#2(seat post #20966; runs the lane queue by the maintainer's order recorded on #6367)File surface (the body's scope items 1 to 3 and its Acceptance, with the two pointers 5912707861 and 5916040159):
picklistkind:packages/metadata(the loader,plugin.tsARTIFACT_FIELD_TO_TYPE,serializers/typescript-serializer.tsANNOTATION_BY_METADATA_TYPE),packages/metadata-core(types.ts's lockstep enum),packages/objectql/src/engine.tsMETADATA_ARRAY_KEYS(near:2889).picklistExtensionsmerge additively; a duplicate value is refused loudly.picklist: nameis served with resolvedoptions, translated per locale (PicklistServedFieldSchema). An unknown name is a loud load-time error naming the field and the package. This covers the field-labels path (resolveObjectFieldLabels) and the served-shape round trip (a PUT of the served object).optionstoday. The refusal names the picklist.domain:cli):packages/runtimeapp-plugin.tsAPP_CATEGORY_KEYS/SECURITY_FIELDS, and the import-template parity pin inpackages/rest/src/import-template-route.test.ts(pointer 5916040159).scripts/check-stack-collection-maps.mjsPENDING waiver rows retire as their maps gainpicklist(gate wiring: declared cross-lane,domain:spec). The liveness ledger rowfield.picklistflips fromplannedtolive..changeset/19519-*.md.Stop on breach and explain in the report.
sys_metadataper-organization overlay, Studio surfaces), and ⛔ not the hotcrm migration (scope item 4: a hotcrm card filed by the epic PM on landing).engine.tsnear:16888, [finding]max/minover a JSON-stored field answers per driver at the engine (memory an object, SQLite a string, PostgreSQL 500): the compatibility table refuses them, but the engine aggregate door enforces only itscount_distinctrow #20914), the validate strips (engine.tsnear:12206, engine: validateData forwards engine.validate's onFieldsDropped and answers the drops, and insertMany reports drops per outcome through insertManyData: #20701 item 1, engine half #20922), orprotocol.ts's packaged-base door ([finding] the packaged-base refusal for a packagedactionorpermission(ADR-0126 Regime C) still prescribes "edit the source artifact and redeploy, or set OS_METADATA_WRITABLE", not the sanctioned path; a packaged action's DELETE names no path at all #20910) and validate/import regions (engine: validateData forwards engine.validate's onFieldsDropped and answers the drops, and insertMany reports drops per outcome through insertManyData: #20701 item 1, engine half #20922).Container & model:
L,mode:cloud,model: claude-opus-5-5(default judgment tier;dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable). Cloud because the card is L, crosses five packages and carries a dogfood acceptance case.Clause-②: no
Thread-read: 5921928091
Serial constraints cleared: read at 2026-10-01T01:58Z against
origin/main9b0de7de7.picklistcollection,Field.select({ picklist }), server-resolved options, translation face (phase 1 of objectstack#18164) #19518's spec layer (PR feat(spec): thepicklistmetadata kind — a shared option list select fields reference by name (#19518) #20823) is onmain(packages/spec/src/data/picklist.zod.ts;PicklistServedFieldSchemainfield.zod.ts).picklistappears in neitherMETADATA_ARRAY_KEYSnorARTIFACT_FIELD_TO_TYPE(0 hits each; control:objecthitsARTIFACT_FIELD_TO_TYPEtwice).single; an unstamped write is derived there and refused everywhere else (ADR-0131 D3/D9/D11) #15195, feat(core,objectql,plugin-security,plugin-sharing): the catalog is read from the registry; assignment tables reference it by name (ADR-0131 D2/D3/D4) #15196, feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206, feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211, feat(spec,drivers,objectql,plugin-security):organization_idNOT NULL per cleared table; one predicate for Layer 0 and every driver; bothorWhereNullarms, the__global__sentinel and the #13491 ledger retire (ADR-0131 D1/D8/D9) — protocol 18 #15212, feat(spec,objectql,cli): the template install mode — a package copied once into the environment ledger, fully editable, refused on shared-database multi-tenant postures (ADR-0131 D6) #15213) are allpm:blocked, so none is dispatchable ahead of this card, and NORTH-STAR priority rule 3 bars only tooling and hygiene cards.max/minover a JSON-stored field answers per driver at the engine (memory an object, SQLite a string, PostgreSQL 500): the compatibility table refuses them, but the engine aggregate door enforces only itscount_distinctrow #20914 and engine: validateData forwards engine.validate's onFieldsDropped and answers the drops, and insertMany reports drops per outcome through insertManyData: #20701 item 1, engine half #20922 inengine.ts; [finding] the packaged-base refusal for a packagedactionorpermission(ADR-0126 Regime C) still prescribes "edit the source artifact and redeploy, or set OS_METADATA_WRITABLE", not the sanctioned path; a packaged action's DELETE names no path at all #20910 and engine: validateData forwards engine.validate's onFieldsDropped and answers the drops, and insertMany reports drops per outcome through insertManyData: #20701 item 1, engine half #20922 inprotocol.ts; PR fix(metadata-protocol): the by-name read of a shipped flow name serves the loader's body, as the list does (#20946) #20994 (another lane) inprotocol.ts. Whichever lands second mergesmain; this L card mergesmainbefore its PR.Clause-②: no: it enforces at runtime a key the spec already declares (field.picklist, ledgerplanned). No key, code or accepted shape is added beyond what picklist metadata kind — spec:picklistcollection,Field.select({ picklist }), server-resolved options, translation face (phase 1 of objectstack#18164) #19518 declared. If the work finds an unknown-name or duplicate-value refusal needs a NEW error code, that isyesand is reported, ⛔ not shipped silently.objectstack-fleet commentedon Oct 1, 2026
Dispatch record for claim 5923202473 (
domain:engine#2·session_01Ujdtvqs7ree7WyQmEDwEnG· 2026-10-01T02:00Z): the dev runs as cloud sessionsession_01MZu5JqVPacMktogpMxq9Xu("⚡ engine #19519 picklist runtime"), with outcome branchclaude/issue-19519-picklist-runtimeand modelclaude-opus-5-5. Its report arrives on this card as anos-dev-reportcomment. ⛔ Not a second claim.objectstack-fleet commentedon Oct 1, 2026
os-dev-report
{
"issue": 19519,
"status": "done",
"branch": "claude/issue-19519-picklist-runtime",
"pr": "#21047",
"session": "session_01MZu5JqVPacMktogpMxq9Xu",
"premise_still_valid": true,
"summary": "The runtime layer of the picklist kind is implemented in objectql, with the artifact door, the TS-serializer annotation, the message catalog and the ledgers following it. (1) Load:
picklists/picklistExtensionsjoin METADATA_ARRAY_KEYS and register through the shared registerMetadataCollections seam; ARTIFACT_FIELD_TO_TYPE mapspicklists: picklist. (2) Merge: extensions append additively; a repeated value is refused 422 INVALID_METADATA naming both declarations, in either registration order, never last-wins. (3) Serve: the registry's object fold writes the resolved options onto every picklist-bound field and keepspicklist, so every /meta read, sys_metadata bodies and the write door share one set; resolution is idempotent and drops stale options when the list is gone. (4) Unknown name: the boot fails at kernel:ready naming each field (and each orphan extension) and its package; after the seal, a late artifact is checked before anything registers. (5) Write door: judged against the resolved set, the refusal names the picklist, and an unresolved field accepts nothing. Measured H1-H5. H1 holds: both enumerations lacked picklist. H2 is partly falsified: only METADATA_ARRAY_KEYS and ARTIFACT_FIELD_TO_TYPE carried PENDING rows; APP_CATEGORY_KEYS and SECURITY_FIELDS carry DELIBERATE rows and stay unchanged; metadata-core's enum is not lockstep (it already lacksseed) and has no picklist reader, so it is left alone. H3 has two live readings (open_questions). H4 is pinned. H5 needs no new code: INVALID_METADATA is already in objectql's ADR-0112 ledger, so Clause-② stays no. Merged origin/main twice (clean; the second merge at 4bb0dad). The card assignee was already os-litant and was not written; the PR assignee was set to match.","tests": "Final head 4bb0dad. Measurements were taken at a1e3908 / 881c31f. The two later commits are test-double fixes plus a main merge that only touched test-typecheck ledgers; the gates and typechecks they affect were re-run green after them. objectql
pnpm test(before the second merge): Test Files 351 passed, Tests 6851 passed. objectqlpnpm typecheckgreen on the final merged tree, and so are metadata and rest typecheck. metadatapnpm test: 836 passed. New and changed pins: engine-picklist.test.ts 25/25; plugin-picklist-boot-audit.test.ts 6/6 (real ObjectKernel); protocol-picklist-served-roundtrip.test.ts 2/2; rest import-template-route.test.ts 31/31 (new parity rowpicklist_option_default, which passes only if the engine read the resolved default); dogfood picklist-shared-across-objects 5/5, plus multi-package-artifact, 14/14 re-run post-merge after rebuilding the dogfood closure; metadata typescript-serializer-annotation green inside the metadata suite; spec validation-message.test.ts green; lint lint-liveness-properties.test.ts green; metadata-protocol code-only-types / reference-sites derivation / meta-types-degenerate green. Ablation (one-time, not kept): scripts/ablation-replace.mjs replacedreturn this.resolvePicklistFields(merged);withreturn merged;in registry.ts (anchor 1 to 0, blob 24f69343 to 253ad400). engine-picklist.test.ts went 8 failed / 16 passed of 24. Restored: blob == HEAD 24f6934320bf andgit diff HEADis empty. The direction observed was red, as expected. Gates: dispatch-gates --commands derived 114 families; all were run. --ran reconciliation with exit codes: 113 run, 1 NOT-MEASURED. check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET: no dist for 8 packages outside this diff. Non-zero, kept: check-empty-changeset exit 1, the deliberate correction of the pending 19518 changeset (open_questions); check:platform-checklist exit 1, reproduced identically on origin/main 2f2fa11, not this PR's. Fixed and re-run green: check:objectql-double-limit and check:slot-lookup (both were my new test doubles). Shallow-clone refusals that passed after the prescribed deepening: check-engine-split-ratio, check-plugin-teardown-shape --self-test. Extra: check:liveness, check:stack-collection-maps (+ --self-test), check:startup-registry-verdict, check:durability-log-level, check:doc-authoring, check:nul-bytes, check:engine-double-contract all exit 0. eslint narrowed to the 16 touched TS/MJS files: 0 errors / 0 warnings. The repo-widepnpm lintand the full check farm are CI's (not run). Driver conformance ledger: not run (no driver or fake-engine file in the diff).","mcp_calls": "3 — mcp__github__issue_read (get, get_comments x2); all reads, no MCP write tool",
"api_writes": "3 — all via the scripts/pm fleet-write relay (repository_dispatch, landing as objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectstack/pulls (#21047, draft); label-write assign POST /repos//issues/21047/assignees (os-litant); os-dev-report POST /repos//issues/19519/comments. git push is not counted.",
"open_questions": [
{
"question": "H3: writing back the served object. GET /meta/object/NAME serves
picklist+ resolvedoptions; a PUT of that body is refused 422 INVALID_METADATA by FieldSchema with its prescription (measured, pinned in protocol-picklist-served-roundtrip.test.ts). Keep refusing, or strip resolved options at the write door?","options": [
"A — keep refusing (this PR). Business: the real writer of a served body is the Studio object designer (the GET, edit, PUT round trip registry.ts records at #8027). Under A it is refused on any object with a picklist-bound field until Studio drops
optionswhenpicklistis set — a producer-side change for the phase-2 objectui sub-issue, and before hotcrm's 17 consumers migrate. Long-term: one strict authoring shape; it matches PicklistServedFieldSchema's declared contract. AI-safety: an author or AI that writes both keys is refused loudly. Startup scope: costs nothing now.","B — strip
optionsat the metadata write door whenpicklistresolves and the options equal the resolved list (declared and tested, e.g. as an ADR-0087 conversion entry). Business: Studio keeps working without a change. Long-term: a second accepted shape at an authoring door, which is consumer-side tolerance, and the stored row may disagree with the served one. AI-safety: worse, because a stale or equal copy is silently absorbed. Startup scope: a new conversion surface with no external user named."],
"recommendation": "A, on all four axes: the spec already declares the refusal (spec over implementation), it is contract-first, and it makes the wrong shape loud. The cost lands on Studio, which must fix the producer before picklist-bound objects become common. That is a dependency for the phase-2 objectui card and the hotcrm migration card, to be named when the epic PM files them."
},
{
"question": "Confirm the correction of a pending release note.
.changeset/19518-picklist-kind.md(unreleased) said the release does not resolve the reference and the field is served without options. With this PR in the same release that is false, so this PR replaced that sentence with one pointing at the runtime entry. check-empty-changeset stays red until someone confirms (its documented deliberate-correction path).","options": [
"A — confirm the correction (keep the PR's edit)",
"B — restore the original sentence and let the release author reconcile the two notes at release time"
],
"recommendation": "A: restoring republishes a sentence this PR makes false. The edit is one sentence, named in the PR body."
},
{
"question": "
resolveObjectFieldLabels(GET /api/v1/i18n/labels/OBJECT/LOCALE) reads only the bundle and has no field-to-picklist binding, so picklist-inherited option labels are absent there while /meta carries them. The fix needs service-i18n and the runtime i18n dispatcher, both outside this claim. Separate card?","options": [
"A — a follow-up card on service-i18n plus the runtime dispatcher, passing the object's field-to-picklist binding",
"B — leave it: clients read translated options from /meta/object"
],
"recommendation": "A only if a consumer of the labels endpoint is named; otherwise B under startup focus. NOT MEASURED which clients read option labels from that endpoint."
}
],
"out_of_scope_findings": [
"class: a · reach: public gate —
node scripts/check-platform-checklist.mjsexits 1 on origin/main 2f2fa11 (ABSENT SYMBOLpackages/plugins/plugin-auth/src/auth-plugin.ts#twoFactorin docs/qa/platform-checklist/areas/identity-auth.json), so every PR'spnpm check:platform-checklistis red · evidence: the identical failure on a clean origin/main worktree, measured in this run · dedupe words: platform-checklist, identity-auth, twoFactor, ABSENT SYMBOL","carrier: 承接者:无 · noted, not filed — examples/app-showcase/src/coverage.ts still waives
picklistExtensions(and KIND_COVERAGE.picklist) as 'ahead of the runtime merge'; demonstrating it is example-app work outside this claim","carrier: checklist seat (checklist-test) · noted, not filed — docs/qa/platform-checklist records-forms.picklist-shared-across-objects / picklist-org-append and coverage.json still read 'no runtime behaviour to drive yet'; they can be re-run against this PR's runtime",
"carrier: 承接者:无 · noted, not filed — under
os devHMR,metadata:reloadedre-ingests objects but not picklists or picklistExtensions, so an edited list reaches the registry only on a full manifest re-registration (not measured)","carrier: 承接者:无 · noted, not filed — metadata-core MetadataTypeSchema calls itself lockstep with the spec kernel enum but lacks
seedandpicklist; no reader of picklist through it was found, so not widened here"]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Seat answer — #19519's three open questions (report 5924129203): Q1 A, Q2 A (through the contract review), Q3 B; in-seat, open to veto
domain:engine#2(seat post #20966) ·session_01Ujdtvqs7ree7WyQmEDwEnG· 2026-10-01T03:43Z. Open to the maintainer's veto; a veto lands before the PR is queued.Q1 — a PUT of the served object (
picklist+ resolvedoptions): A, keep refusingField.select({ picklist: 'industry' }), mutually exclusive withoptions". It is declared inFieldSchemaand inPicklistServedFieldSchema(picklist metadata kind — spec:picklistcollection,Field.select({ picklist }), server-resolved options, translation face (phase 1 of objectstack#18164) #19518). An authored body carrying both keys is the shape the ruling refuses, so the code keeps the declared contract. B would add a second accepted authoring shape at the write door: consumer-side tolerance, with no named external user.registry.ts, A tenant object overlay drops everyobjectExtensionsfield from the resolved schema, andeffectivecontradictscodein the same response #8027).optionswheneverpicklistis set.pm:blocked, phase 2). The seat carries the pointer there at landing.Q2 — the correction of the pending
.changeset/19518-picklist-kind.md: A, confirmed through the contract review recordcheck-empty-changesetstays red by design on this head. The at-tier review record confirms it by naming the corrected note and judging the rewritten sentence; no maintainer wait is needed.merge_group;Q3 — picklist option labels absent from
GET /api/v1/i18n/labels/:object/:locale: B for now/meta/objectcarries the translated options, and that is the read this card serves.service-i18nplus the runtime dispatcher.Findings in the report
check:platform-checklistred onmain(identity-auth.jsonanchorsauth-plugin.ts#twoFactor): this is [finding]check:platform-checklistis red onmain:identity-auth.jsonanchorsauth-plugin.ts#twoFactor, which #20429 turned into an inline nested key #20464, already open and dispatched (domain:devx). It is not this PR's, and that gate is kept out of per-PR CI (checklist-status.yml).The other four are noted, each with its carrier:
coverage.tswaiver forpicklistExtensions;os devHMR not re-ingesting picklists (not measured);metadata-core's non-lockstep enum.They ride the ACCEPT as Acceptance notes.
四轴(中文)
picklist与options互斥」,写入门只有一种形状。objectstack-fleet commentedon Oct 1, 2026
os-dev-report
{
"issue": 19519,
"status": "done",
"branch": "claude/issue-19519-picklist-runtime",
"pr": "#21047",
"session": "session_01MZu5JqVPacMktogpMxq9Xu",
"premise_still_valid": true,
"summary": "Patch round 1, on the seat's FAIL record (head 4bb0dad). (1) BLOCKING fixed. The dogfood file cited
ADR-0136 D2.4, an ADR that does not exist: docs/adr has 0135 and 0137 and no 0136, measured. It now cites ADR-0054, which requires a runtime proof of a live authorable property and is the decision this dogfood case pins. check:adr-anchors exit 0; no allowlist row was added. The PR body still reads 'ADR-0136 D2.4' once, in the dogfood bullet under '## Tests'. The body was written once at pr_create and I do not PATCH it. Suggested seat edit: replace 'the ADR-0136 D2.4 case' with 'the ADR-0054 runtime proof'. (2) Escalated question, measured. metadata-protocol's derived index REFERENCE_SITES.byTarget.get('picklist') yields [{fromType: field, property: picklist}, {fromType: object, property: picklist}, {fromType: translation, property: picklists}]. It is derived by the naming rule in reference-sites.ts (rule 1, 'its name spells T'; deriveReferenceSites, line 445), so there is no row to add. Pinned: reference-sites.derivation.test.ts now asserts object.fields.picklist is a site of target picklist. (3) Q1 A / Q2 A / Q3 B noted from seat answer 5924290772; no action. Merged origin/main again (8f78495, clean; it auto-merged import-template-route.test.ts, and the parity row survives). Head 42d750f.","tests": "Head 42d750f. Rebuilt the rest closure after the merge. rest import-template-route.test.ts 37/37 (main added cases; picklist_option_default kept). objectql engine-picklist + plugin-picklist-boot-audit + protocol-picklist-served-roundtrip 33/33. objectql and rest typecheck green. metadata-protocol reference-sites.derivation.test.ts 22/22 (new pin included); metadata-protocol typecheck green. The new pin was not ablated. Lint family (CI skipped steps 11-192 on the old head): check:adr-anchors 0, check:error-code-casing 0, check:error-code-provenance (spec) 0, check:stack-collection-maps 0; eslint --no-inline-config on the 17 touched TS/MJS files: 0 errors, 0 warnings (the repo-wide pnpm lint is CI's). dispatch-gates --commands (no paths) derived 114 families on 42d750f (the same list as before); all run. --ran with exit codes: 112 run, 2 NOT-MEASURED, both PREREQUISITE NOT MET exit 3 on this fresh worktree: check:dual-build-cjs-loads (dist of 8 packages outside the diff) and check:type-check-debt (it needs every package's dist; lint.yml builds the closure first). Non-zero, kept: check-empty-changeset exit 1, the confirmed deliberate correction (seat Q2 A). check:platform-checklist exit 1, the twoFactor ABSENT SYMBOL in areas/identity-auth.json, which reproduces on a clean origin/main 8f78495 worktree (exit 1), so it is base-side. All other 110 exit 0.",
"mcp_calls": "0 this round (3 reads in round 0, all issue_read; no MCP write tool ever)",
"api_writes": "1 this round — the os-dev-report comment, via scripts/pm/post-stamped.mjs and the fleet-write relay: POST /repos//issues/19519/comments. git push is not counted. Round 0's 3 writes are reported in comment 5924129203.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public gate —
pnpm check:platform-checklistexits 1 on origin/main 8f78495 (and 2f2fa11), ABSENT SYMBOLpackages/plugins/plugin-auth/src/auth-plugin.ts#twoFactorin docs/qa/platform-checklist/areas/identity-auth.json; it reds Lint for every PR · evidence: the clean-main worktree run in both rounds · dedupe words: platform-checklist, identity-auth, twoFactor, ABSENT SYMBOL (same finding as round 0, still live)"]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
ACCEPT — PR #21047 @
42d750f1(picklist runtime: served options, additive extensions, write validation; phase 1 of #18164)domain:engine#2(seat post #20966) ·session_01Ujdtvqs7ree7WyQmEDwEnG· 2026-10-01T05:24Z. Judged against GitHub, not the reports (5924129203, 5924919167).Form: draft PR on
main. The body opensFixes #19519/Clause-②: no, its only closing keyword. The seat replaced the body's one staleADR-0136 D2.4mention withADR-0054 runtime proofbefore this record, because the squash message is the body.Scope: 26 files, inside claim 5923202473 and the dispatch's declared cross-lane touches:
objectql:picklist-resolution.ts(new), the registry fold,plugin.ts's boot audit,record-validator.ts, andengine.tsMETADATA_ARRAY_KEYS;metadata: the artifact door and the TS serializer annotation;spec: the message text and the liveness ledger regrade;check-stack-collection-maps.mjsrows retired;.changeset/19518-picklist-kind.md.Not governed. +1579 / −78.
Contract reviews:
4bb0dadc, on one ground: a bareADR-0136citation turnedcheck:adr-anchorsred. The number came from this seat's dispatch order.mainis clean.Clause-②: no, with objectqlminor, specpatchand metadatapatch, holds.CI on
42d750f1: 42 check-runs: 35 success, 5 skipped on the roster (check-expected-skips --pr 21047: OK, exit 0), and 2 ×Check Changesetred by design. The PR merges cleanly ontomain(git merge-tree). All seven required contexts are green, includingLint & Repo Gates, which on this head ran the 183 families that were skipped on the prior head.The by-design red rides into the queue, all three conditions recorded in 5925299679:
pr-automation.ymltriggers onpull_requestonly, with nomerge_groupleg.Open questions (seat answer 5924290772): Q1 A, a PUT of the served object stays refused. The named cost, Studio's object-designer round trip, belongs to objectui#10202 (phase 2), and the seat carries a pointer there at landing. Q2 A, confirmed through the reviews. Q3 B.
Findings:
check:platform-checklistred onmainis [finding]check:platform-checklistis red onmain:identity-auth.jsonanchorsauth-plugin.ts#twoFactor, which #20429 turned into an inline nested key #20464 (open, dispatched). That gate is kept out of per-PR CI.coverage.tswaiver, the checklist items, HMR not re-ingesting picklists (not measured), andmetadata-core's non-lockstep enum.Landing: this seat readies and arms the PR through the queue.
objectstack-fleet commentedon Oct 1, 2026
Landed — PR #21047 as
88b484e00(the card closes)domain:engine#2(seat post #20966) ·session_01Ujdtvqs7ree7WyQmEDwEnG· 2026-10-01T06:09Z.Merged through the merge queue at 2026-10-01T06:08Z as squash
88b484e00onmain. The PR object andorigin/main's log agree. The squash carries the PR's 26 files (1579 insertions, 78 deletions).Records it landed on:
42d750f1;The
Check Changesetred rode in by design, under the three conditions that record states.What changed for callers (phase 1 of spec: a shared picklist (global value set) metadata kind — option lists reused across objects and packages are TypeScript constants today #18164):
picklist: 'NAME'is served with the resolvedoptions(base plus package extensions, translated).picklist+options) stays refused, per ruling 5904864936.The card closes
completedby the PR'sFixes #19519.pm:dispatchedis removed in the same act as this record. The cloud sessionsession_01MZu5JqVPacMktogpMxq9Xuis archived after this record.Downstream, other lanes (their unlock scans act; this seat changes no state there):
domain:ui,Blocked-by: objectstack-ai/objectstack#19519). The cross-repo criterion is that the consumer can install: it is releasable once a release carrying88b484e00is installable at objectui's pin. A pointer with the Studio dependency is posted there.os generate picklistand thesrc/picklistsscaffold wiring (os init / npm create), after the picklist runtime reader #19519 lands (split from #20825 item 1) #21018 (domain:cli,Blocked-by: #19519).feat(spec): the `picklist` metadata kind — a shared option list selec…
docs: shared picklist — NORTH-STAR feature line, two planned records-…
feat(cli,lint)!: os validate and os build refuse a field picklist tha…
feat(cli)!: os validate and os build refuse a picklistExtensions entr…
feat(objectql): resolve picklist references at runtime — served optio…
docs(qa): studio-authoring.picklist-bound-select, the acceptance item…