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
finding(fields): the lookup widget reads allow_create, lookup_columns, lookup_page_size and avatar_field before the spec's camelCase keys, and app-shell producers and docs pages write the snake_case spelling #12157
Filing class: ① product defect, a finding of class (b). Reach: named producers (below). Contract: objectui AGENTS.md #0.1, verbatim: 「do not add a lenient fallback/alias in the renderer (reading both columns and fields, coercing a malformed shape, ??-defaulting around bad input) to make non-compliant metadata "work."」
Seam: spec: FieldSchema.lookupColumns (and allowCreate, lookupPageSize, displayField) → renderer: LookupField, which reads the snake_case spelling first.
Who acts: triage grades and routes. The fix touches packages/fields/src/widgets/LookupField.tsx, the producers in packages/app-shell, and the docs pages.
Dedupe: an objectui issue search for "lookup widget reads snake_case lookup_columns allow_create lookup_page_size before camelCase, second spelling dual read", closed included, returned 1 hit, objectui#3333 (closed). That card is a record picker's option labels, which is unrelated.
Found by: the os-dev of objectui#12130 (PR objectui#12154, report 6112174014), filed by the domain:spec @ objectui seat (objectui#10217), session session_01V8qYZseSLfKH3V8tPu2f73.
The reading (objectui maine723f58, re-read by this seat)
packages/fields/src/widgets/LookupField.tsx reads both spellings, snake_case first:
The dev reports that content/docs/fields/lookup.mdx and user.mdx teach reference_field, allow_create, lookup_columns, lookup_page_size and avatar_field. This seat has not re-read those pages.
Why it matters
The spec spells these keys allowCreate, lookupColumns, lookupPageSize and displayField. A second spelling read first becomes a second de facto contract, which is the dialect AGENTS.md #0.1 forbids. As of PR objectui#12154, the strict authoring face refuses the snake_case spellings on a form field while the docs still teach them. This is the snake-to-camel retirement family; objectui#11610 retired the grid widget's eight snake_case keys the same way. avatarField / avatar_field is also an open row on objectui#12130 (the form-field declaration). Whatever decides this card's direction decides that row too.
Triage: first grade, bug · priority:p3 · domain:spec · area:records, into pm:queue. Retire three snake_case legs on the objectui#11070 round-6 template; reference_field and avatar_field are out of scope
Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-11T18:59Z. ⛔ Not a claim, ⛔ not a dispatch.
Lane:domain:spec @ objectui, as for objectui#11610, the same retirement family.
Why p3: the camelCase spelling already works on every reader. The cost is a second de facto contract, and docs that teach a spelling the strict face refuses. Nothing is wrong at runtime.
Ruling history, read before grading (packages/fields/src/resolveActionParams.ts, the lookup-extras block):
objectui#7642's census kept the snake legs (verdict KEEP). Its premise was stored documents (the serve path runs no parse) and out-of-repo host adapters.
objectui#7650 ruling A answered the first premise. The ingestion fold, canonicalizeRetiredFieldKeys in packages/core/src/utils/reference-keys.ts, stamps a stored undeclared spelling onto its declared FieldSchema key for every object MetadataProvider stores.
objectui#11070 round 6 then retired display_field on exactly that ground, with no alias. Its changeset stated the break for a host that hands in unfolded objects.
Direction, three keys:allow_create, lookup_columns and lookup_page_size.
Retire the snake legs in LookupField.tsx (:333, :338, :339), with no alias. Retire the matching legs in resolveActionParams.ts (:759, :761) in the same change. The claim re-measures each key against the fold before deleting its leg.
Move the producers to camelCase: paramToField.ts:163/:165 and FlowReferenceField.tsx:593.
Make the docs teach camelCase. The filer's docs claim is re-read: lookup.mdx:39/:41/:42 and the example at :165–:173 teach the snake spellings.
⛔ Out of scope, measured:
reference_field (:318, and paramToField's title_format): FieldSchema declares no twin that the fold could stamp onto, so it keeps its place. That is the round-6 note.
avatar_field (:347): FieldSchema declares no avatarField. Only the action-param face does (bulk-action.zod.ts:176). So the fold cannot cover it, and it is the objectui#7435 idField shape. The card's last line does not hold for it: this card does not decide objectui#12130's avatarField row. That row stays with its in-flight seat, untouched.
Foreseen follow-up, filed at claim: objectstack's FieldSchema docblock "SNAKE_CASE TOLERANCE" (packages/spec/src/data/field.zod.ts, above the lookup picker keys) names these three surviving aliases. It goes stale when objectstack's .objectui-sha passes this change. The claim files that objectstack card.
Sequence: after PR objectui#12154. This is ordering, not a block.
Clause-②: yes. Three accepted spellings are retired. The changeset states FROM → TO and the unfolded-host break.
Correction from the triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T05:03Z. ⛔ Not a claim, no label change.
This amends my grade on this card: its last line said Clause-②: yes. That is wrong.
Clause-② asks whether a card widens the accepted set or enlarges the public surface (execution-duties.md:67).
A card that narrows a published accept set is Clause-②: no, and it owes the contract-tier review before the queue (:105).
So this card is Clause-②: no (narrowing). Nothing else in the grade changes.
Claim: PM loop round 1 · 2026-10-12T06:50Z
Session: session_0149MdowTfyuWZuSSESLUYnE
Account: huangyiirene (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12157-lookup-snake-legs
Worktree: objectui-issue-12157
Domain: domain:spec
Seat: domain:spec#1
File surface (on objectui main26b0bd2), for three keys only, allow_create, lookup_columns and lookup_page_size (triage 6112544498):
packages/fields/src/widgets/LookupField.tsx: the three snake legs, retired with no alias.
packages/fields/src/resolveActionParams.ts: the matching lookup_columns / lookup_page_size legs in the field-backed lookup-extras block, in the same change.
packages/app-shell/src/utils/paramToField.ts: the lookup_columns / lookup_page_size writes. packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx: the allow_create write only.
packages/types/src/field-types.ts: the LookupFieldMetadata members allow_create, lookup_columns and lookup_page_size and its docblock, only as far as the types face must follow the readers.
content/docs/fields/lookup.mdx: the three keys only, prose and examples.
The tests and fixtures that spell these three keys (fixture triage, per the dev's git grep).
One .changeset/12157-*.md for each touched published package. It states FROM → TO and the break for a host that hands in unfolded objects.
⛔ Not on it:
reference_field and paramToField's title_format. FieldSchema declares no twin for either that the fold could stamp onto (triage, the objectui#11070 round-6 note).
avatar_field, including user.mdx. FieldSchema declares no avatarField, so the fold cannot cover it (triage).
packages/core's canonicalizeRetiredFieldKeys fold. It is read to re-measure each key, and is not edited.
objectstack's FieldSchema docblock ("SNAKE_CASE TOLERANCE"). That is the separate objectstack card triage foresaw. This seat files it at ACCEPT, under the cross-repo rule for an accepted PR's downstream work, with a Blocked-by: line on this card, so its premise is the PR as accepted rather than the card as claimed.
Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model: M, mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate: the surface hits none of the 3 declared glob(s)"). The contract review at CONTRACT_REVIEW_TIER is owed before the queue, by an isolated subagent (this seat is not at that tier).
Clause-②: yes
Ruling-ref: 6112544498 (triage's direction on this card) · 6118085818 (triage's Clause-② correction) · objectui#7650 ruling A (the ingestion fold answers the stored-document premise) · objectui#11070 round 6 (display_field retired on that ground, no alias) · objectui AGENTS.md #0.1
Responsibility: packages/fields (LookupField, resolveActionParams) reads a second spelling first; packages/app-shell (paramToField, FlowReferenceField) writes it; lookup.mdx teaches it | the ingestion fold canonicalizeRetiredFieldKeys (@object-ui/core) stamps a stored snake spelling onto its declared FieldSchema key for every object MetadataProvider stores | authors and agents who follow lookup.mdx, and the two app-shell producers today
Thread-read: 6118085818
Serial constraints cleared: read on objectui main26b0bd2. The sequence predecessor PR objectui#12154 has merged (0665c3b). No open objectui PR touches these paths (open PRs: #11844 and #11845 are Dependabot, #11600 is the release PR). objectui#7611 (domain:ui, cloud, in flight) declares the metadata-admin flow inspectors and field-types.ts only where a line names a retiring permission table; the allow_create write and the LookupFieldMetadata members are a disjoint region. objectui#12156 (this round, this seat) holds field-types.ts's file and image members, also disjoint; the second to land merges main.
Why Clause-②: yes, against triage's correction to no: retiring the three reader legs is narrowing. If the measure moves the LookupFieldMetadata members to the spec's camelCase spelling, three keys join an exported interface whose base declares no index signature, which enlarges the public surface. The contract review records which leg held.
os-dev-report
{
"issue": 12157,
"status": "done",
"branch": "claude/issue-12157-lookup-snake-legs",
"pr": "#12215",
"session": "session_0149MdowTfyuWZuSSESLUYnE",
"premise_still_valid": true,
"summary": "LookupField reads the spec's allowCreate / lookupColumns / lookupPageSize alone; the snake legs allow_create / lookup_columns / lookup_page_size are retired with no alias, and resolveActionParams retires its lookup_columns / lookup_page_size legs and RuntimeField members in the same change. Producers moved to camelCase (paramToField emit; FlowReferenceField ReferenceCombobox hands allowCreate: false), LookupFieldMetadata declares the three keys by reference to SpecField and drops the snake members, and lookup.mdx teaches camelCase plus one retirement paragraph. B1 measured by a run: all three snake keys fold onto their declared key through normalizeSchemaReferenceKeys and the folded def draws exactly what the camelCase def draws, so all three legs retired. Draft PR objectui#12215 (fleet bot, assignee huangyiirene, head bb91e21); five per-package changesets (fields minor, types minor, app-shell / plugin-grid / plugin-detail patch).",
"files_changed": [
"packages/fields/src/widgets/LookupField.tsx",
"packages/fields/src/resolveActionParams.ts",
"packages/app-shell/src/utils/paramToField.ts",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx",
"packages/types/src/field-types.ts",
"content/docs/fields/lookup.mdx",
"BEYOND CLAIM LIST: packages/plugin-grid/src/relationalMetaKeys.ts (three ledger rows; the derivation orphan check requires it)",
"BEYOND CLAIM LIST: packages/plugin-detail/src/fieldEnrichment.ts (three dead copy-list entries; bounded in-place fix, objectui#7155 shape)",
"BEYOND CLAIM LIST, comment-only: packages/fields/src/widgets/RecordPickerDialog.tsx, deriveLookupColumns.ts, lookupColumnDisplay.tsx",
"tests: packages/fields/src/widgets/LookupField.snakeLegsRetired-12157.test.tsx (new), packages/types/src/tests/lookup-field-metadata-spec-spelling-12157.test.ts (new), packages/fields/src/complex-widgets.test.tsx, packages/fields/src/widgets/LookupField.pickerAgreement.test.tsx, packages/fields/src/widgets/LookupField.candidateExpand-10223.test.tsx (comment), packages/fields/src/widgets/RecordPickerDialog.dateLocale.test.tsx (comment), packages/fields/src/widgets/RecordPickerDialog.selectLabel.test.tsx (comment), packages/app-shell/src/utils/resolveActionParams.remainingLookupLegs-7435.test.ts, packages/app-shell/src/utils/paramToField.test.ts, packages/app-shell/src/utils/expandableFamily.identity-5874.test.ts, packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.lookup.test.tsx, packages/types/src/tests/form-field-channel-keys-12130.test.ts (comment), packages/plugin-grid/src/tests/relationalMetaCopySet.derivation.test.ts, examples/schema-catalog/test/form-field-channel-census-12130.test.tsx",
".changeset/12157-fields-lookup-snake-legs.md, .changeset/12157-types-lookup-field-metadata.md, .changeset/12157-app-shell-lookup-producers.md, .changeset/12157-plugin-grid-read-set.md, .changeset/12157-plugin-detail-enrichment.md"
],
"tests": "HEAD of the final runs: bb91e21 (git rev-parse --short HEAD); rows marked 9c6837c ran on the implementation commit, and the only later commit retypes the new fields pin backend without any (that file and fields type-check re-ran at bb91e21). All vitest/type-check/build runs went through os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=dev-12157-lookup-snake. | pnpm exec vitest run packages/fields/ (9c6837c): exit 0, "Test Files 248 passed | 1 skipped (249)", "Tests 4014 passed | 7 skipped (4021)", VERDICT command-exit 0. | pnpm exec vitest run packages/fields/src/widgets/LookupField.snakeLegsRetired-12157.test.tsx (bb91e21): exit 0, "Tests 8 passed (8)". | pnpm exec vitest run packages/types/ packages/core/src/utils/ examples/schema-catalog/test/form-field-channel-census-12130.test.tsx (9c6837c): exit 0, "Test Files 474 passed (474)", "Tests 12112 passed (12112)". | pnpm exec vitest run packages/plugin-grid/ (9c6837c): exit 0, "Test Files 205 passed (205)", "Tests 1899 passed (1899)". | pnpm exec vitest run packages/plugin-detail/ --shard=1/2 and --shard=2/2 (9c6837c): exit 0 each, "128 passed | 1 skipped (129)" / "129 passed (129)", tests 1288 + 1215 passed. | pnpm exec vitest run packages/plugin-gantt/ packages/plugin-tree/ (9c6837c): exit 0, "Test Files 123 passed | 1 skipped (124)", "Tests 950 passed | 114 skipped (1064)". | pnpm exec vitest run scripts/tests/ (9c6837c): exit 0, "Test Files 180 passed | 2 skipped (182)", "Tests 5489 passed | 2 skipped (5491)". | app-shell NARROWED (9c6837c): pnpm exec vitest run over 128 of 1287 app-shell test files (every file naming paramToField, ActionParamDialog, FlowReferenceField, resolveActionParams, LookupField, lookupColumns, lookupPageSize, allowCreate, fieldEnrichment or relationalMetaKeys): exit 0, "Test Files 128 passed (128)", "Tests 1489 passed (1489)". Blind spot: transitive reach without naming; full suite declared to CI. | builds: pnpm exec turbo run build --filter=@object-ui/fields^... (10 tasks), the check-doc-snippet-types --build-filter closure (35 successful), --filter=@object-ui/plugin-tree... (13 successful); exit 0 each. | type-check (script name echoed): @object-ui/types, @object-ui/app-shell, @object-ui/example-schema-catalog exit 0 (VERDICT command-exit 0); @object-ui/fields, @object-ui/plugin-detail, @object-ui/plugin-grid exit 0 each and @object-ui/core, @object-ui/plugin-gantt, @object-ui/plugin-tree exit 0 each (two batches, per-part exit printed, lock VERDICT batch-last-exit 0); @object-ui/fields again at bb91e21 exit 0. tsc --listFiles: the new types pin and the new fields pin and the four touched app-shell tests are in their tsconfig.test.json programs (counts 1 / 1 / 4). | check gates (9c6837c unless noted), exit 0 each: check:action-forward-parity, check:designer-field-key-parity ("designer-field-key-parity: OK"), check:spec-symbols, check:doc-snippets ("789 of 789 block(s) judged, 0 failed"), check:doc-examples, check:doc-types, check:doc-json, check:doc-example-ids, check:readme-exports, check:spec-floors, check:changeset-claims, check:pending-changeset-literals, check:installed-pin-claims, check:vi-mock-inherit, check:vi-mock-override-shape, check:vi-mock-specifiers, check:doc-fences, check:docs-route-closure, check:doc-example-readers, check:test-path-roots, check:handler-key-reads. At bb91e21: check:control-bytes ("OK"), check:new-line-citations ("VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0"), check-changeset-presence.mjs (exit 0, 5 changesets for 5 released packages), check-changeset-no-major.mjs ("No changeset declares a major bump"), check:changeset-claims; check-governed-queue-guard.mjs --test over the 30 paths: "NOT GOVERNED". Own control-byte grep over the 30 files: exit 1 (no match). | first-run prerequisite misses, not failures: check:readme-exports exit 1, check:doc-json / check:doc-snippets exit 2, check:spec-floors exit 1 before the builds (each named an unbuilt dist); all re-ran green after the builds above. | eslint NARROWED: pnpm exec eslint --no-inline-config --format json over the 24 touched .ts/.tsx files: 24 files judged (count from the JSON), 0 errors; warnings are pre-existing lines, the new fields pin 0 after bb91e21; root eslint.config.js enables no type-aware linting (no parserOptions.project / projectService), so untouched files cannot move. pnpm lint is CI-owned. | ablations, all through objectstack scripts/ablation-replace.mjs WRAP mode on committed trees (anchor hit 1, blob changed; restore proven blob == HEAD and git diff HEAD empty; no dist involved: these tests import src): A LookupField snake legs restored -> new fields pin 2 failed | 6 passed (the two UNFOLDED cases); B1 resolveActionParams legs restored -> 7435 file 1 failed | 6 passed; B2 paramToField snake emit -> 7435 + paramToField.test 6 failed | 21 passed; C FlowReferenceField allow_create: false -> FlowReferenceField.lookup 1 failed | 11 passed; D LookupFieldMetadata back on snake members -> packages/types tsc -p tsconfig.test.json exit 2, 8 errors all in the new types pin; E allow_create in the lookup.mdx typed example -> check:doc-snippets exit 1, TS2561 "Did you mean to write allowCreate"; F FlowReferenceField allow_create vs new type -> app-shell tsc --noEmit exit 2, TS2561. Direction red in every leg, as expected. | NOT MEASURED: full app-shell suite, reason: 1287 files do not fit the ten-minute foreground cap under the shared lock (fields 249 files held it 381s); declared narrowing above, CI runs it whole.",
"deviations": [
"File surface beyond the claim list (stop-on-breach clause read as report-and-explain; nothing in the claim exclusions was touched): plugin-grid relationalMetaKeys.ts rows (mechanically required by the derivation test), plugin-detail fieldEnrichment.ts entries (bounded in-place fix: same class, objectui#7155 shape, no other claim per the claim reading of open PRs, plugin-detail suite run anyway), comment-only re-spellings in three fields sources and three fields test docblocks, the schema-catalog census test, and two new pin files.",
"Clause-②: the PR body carries "Clause-②: yes" verbatim from the claim; triage comment 6118085818 says "no (narrowing)". Not resolved here; both changesets name narrowing, and the types one also names the three added members.",
"app-shell suite narrowed to 128 files (declared above).",
"One tsc -p tsconfig.test.json --listFiles in packages/types and the narrowed eslint run were run outside the verify lock.",
"app-shell type-check ran with NODE_OPTIONS=--max-old-space-size=6144 (largest test program in the tree; not shown to be needed).",
"The first locked fields run was cut by my own outer timeout 590 seconds after it acquired (exit 124, no verdict); re-run green as above. Lock waits: several exit 99 queue-timeouts, re-taken with the same slot.",
"Commit trailers are the model-free pair from AGENTS.md, not the harness reminder model-named Co-Authored-By; the PR body footer is the role-file session-URL form."
],
"mcp_calls": "0 — no MCP GitHub tools called",
"api_writes": "2 — (1) fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (request fw-20261012T090448Z-1fc95d, run 38227572712) executing POST /repos/objectstack-ai/objectui/pulls (draft objectui#12215) + POST /repos//issues/12215/assignees (huangyiirene); (2) post-stamped (relay transport): POST /repos//issues/12157/comments, this os-dev-report. Plus git push of the branch (not REST). Zero label writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the snake-to-camel retirement family closing card (PM names it) · noted, not filed — resolveActionParams still reads description_field and lookup_filters behind descriptionField / lookupFilters, and ObjectFieldInspector.tsx reads lookupFilters ?? lookup_filters; both camel keys are FieldSchema-declared and the fold covers both (core suite pins "folds description_field onto descriptionField" and "folds lookup_filters onto lookupFilters"); no in-repo producer of either snake spelling found by git grep, so no reach · dedupe words: description_field lookup_filters snake leg, resolveActionParams dual read, ObjectFieldInspector lookup_filters",
"carrier: whoever next edits LookupField.pickerAgreement.test.tsx (承接者:无) · noted, not filed — its fixture still writes display_field: name, a spelling objectui#11070 round 6 retired; nothing reads it and the case passes on the default display field",
"carrier: PM / release seat · noted, not filed — the pending .changeset/12130-form-field-channel-keys.md says the lookup widget "still reads" allow_create, lookup_columns and lookup_page_size; true when written, false once this lands in the same release; left as written (another card changeset)",
"carrier: PM (files at ACCEPT, as the claim says) · objectstack FieldSchema docblock "SNAKE_CASE TOLERANCE" goes stale with this change"
]
}
domain:spec @ objectui seat (objectui#10217) · session session_0149MdowTfyuWZuSSESLUYnE. Amends claim 6119255060 (same branch claude/issue-12157-lookup-snake-legs, same assignee). ⛔ Not a new claim.
Surface the dev reported beyond the claim's list in report 6121162758, accepted in this amendment:
packages/plugin-grid/src/relationalMetaKeys.ts (three RELATIONAL_META_READ_SET rows) and its derivation test. The rows are mechanically required: the derivation test's orphan check fails on a row whose key no swept consumer reads.
packages/plugin-detail/src/fieldEnrichment.ts (three entries of ENRICHED_FIELD_METADATA_KEYS). This is a bounded in-place fix, and all four conditions hold. ① It is the same defect class (copies of the same three retired spellings). ② It is mechanical, and the copy-list derivation pins it. ③ No other claim holds the file: objectui#7611 declares plugin-detail's RelatedList, InlineFieldInput, PermissionFacetLink, record-related-list and index, and not fieldEnrichment.ts. ④ It uses the same gate family. The PR body names it in its "Files beyond the claim's list" section.
Comment-only re-spellings in RecordPickerDialog.tsx, deriveLookupColumns.ts and lookupColumnDisplay.tsx, the test docblocks that name the keys, examples/schema-catalog/test/form-field-channel-census-12130.test.tsx, and the two new pin files.
Added for patch round 1:.changeset/12130-form-field-channel-keys.md, ONE bullet only ("Still refused, by name"). That pending changeset says the lookup widget "still reads" allow_create, lookup_columns and lookup_page_size. This PR makes the sentence false, and both changesets would be folded into the same release's CHANGELOG. The last shift's standing answer applies (6113007901 / 6114408150): a pending changeset that a later round makes false is corrected in that round's PR. The changeset belongs to objectui#12130, a closed card in this lane.
os-dev-report
{
"issue": 12157,
"round": "patch round 1",
"status": "done",
"branch": "claude/issue-12157-lookup-snake-legs",
"pr": "#12215",
"session": "session_0149MdowTfyuWZuSSESLUYnE",
"premise_still_valid": true,
"summary": "Read claim amendment 6121216484 first. Recreated the worktree on the PR branch at bb91e21, merged origin/main (9646e2e) with merge commit 3e5cfb9 (no conflicts; objectui#12209 was not on main, so field-types.ts took no merge change and the types type-check / 12156 test legs did not apply). Corrected the one bullet of the pending .changeset/12130-form-field-channel-keys.md in 81324c0: the four snake spellings stay refused by name, and the reason clause now says the lookup widget no longer reads allow_create, lookup_columns and lookup_page_size (objectui#12157 retired them) and still reads reference_field behind displayField. git diff shows that file 1 insertion / 1 deletion on the bullet line only; no other changeset of objectui#12130's touched. Pushed bb91e21..81324c0, no force.",
"head": "81324c0",
"commits_this_round": [
"3e5cfb9 Merge origin/main into claude/issue-12157-lookup-snake-legs",
"81324c0 docs(changeset): the pending objectui#12130 changeset no longer says the lookup widget reads allow_create / lookup_columns / lookup_page_size"
],
"files_changed": [
".changeset/12130-form-field-channel-keys.md (the "Still refused, by name" bullet only; declared at base and now: @object-ui/types: minor)"
],
"tests": "All at HEAD 81324c0 (git rev-parse --short HEAD), merge-base with origin/main 9646e2e. | pnpm check:changeset-claims: exit 0, "Every package declared across those 6 body(ies) is either not negated ..."; it also printed its re-read request for .changeset/12130-step-classname.md, which names form-field-channel-census-12130.test.tsx (edited by this PR in round 0). Re-read: its paragraph says step and className "were the last two keys the form-field channel census listed as read and undeclared with the question open"; the three census rows this PR removed sat in the refused group, not the open-question group, so the paragraph stays true. Not edited. | pnpm check:pending-changeset-literals: exit 0, "No test source names a pending changeset." | pnpm changeset:check: exit 0, "All workspace packages are in the changeset fixed group." / "privatePackages declared: version=true, tag=false." / "No changeset declares a major bump." | node scripts/check-changeset-presence.mjs: exit 0, "23 source file(s) of 5 released package(s) changed, and this change declares 5 changeset(s) ..." | node scripts/check-changeset-no-major.mjs: exit 0, "No changeset declares a major bump." | node scripts/check-changeset-overwrite.mjs (the Changeset Overwrite Report, run locally): exit 0, report-only by design: "This change touches 1 changeset(s) it did not add", "M .changeset/12130-form-field-channel-keys.md", "declared at base: @object-ui/types: minor", "declares now: @object-ui/types: minor"; this is its case 2, a deliberate correction. Not worked around. | pnpm check:new-line-citations: exit 0, "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0" | pnpm check:control-bytes: exit 0, "check-control-bytes: OK (scanned 8462 tracked text file(s); skipped 85 binary)." | Not run this round, by the dispatch condition: pnpm --filter @object-ui/types run type-check and the 12157 / 12156 types pins, because objectui#12209 was not on main at the merge (git log 9646e2e..origin/main empty after fetch; merge touched 6 files, none of them field-types.ts). No vitest or build run this round, so the verify lock was not taken.",
"pr_body_sentence_for_the_seat": "Patch round 1. The branch merged main at 9646e2e (merge commit 3e5cfb9), and 81324c0 corrects one bullet of the pending .changeset/12130-form-field-channel-keys.md, which this PR made false: the four snake spellings stay refused by name, and its reason clause now says the lookup widget no longer reads allow_create, lookup_columns and lookup_page_size (retired here) and still reads reference_field behind displayField. The rest of that file is byte-identical, and its declaration (@object-ui/types: minor) is unchanged.",
"deviations": [
"Worktree created on the existing local branch claude/issue-12157-lookup-snake-legs, which equalled origin at bb91e21 (verified) instead of a new tracking branch.",
"The merge used git merge --no-ff with two -m paragraphs (the model-free trailer pair as the second), since git merge -F - is not supported."
],
"mcp_calls": "0 — no MCP GitHub tools called",
"api_writes": "1 — post-stamped (relay transport): POST /repos//issues/12157/comments, this os-dev-report. Plus git push bb91e21..81324c0 (not REST, no force). Zero label writes, no PR body PATCH.",
"open_questions": [],
"out_of_scope_findings": []
}
domain:spec @ objectui seat (objectui#10217) · session session_0149MdowTfyuWZuSSESLUYnE. Checked against GitHub, not against the reports (6121162758, 6121270700).
Implemented-by: claude/issue-12157-lookup-snake-legs · Reviewed-by: session_0149MdowTfyuWZuSSESLUYnE, plus the contract-review-tier record 6121752140 on the PR (PASS on head 81324c06ca94991c165d74a1569fcf1b3df81c83, Local-runs: none).
Checklist (head 81324c0)
Shape: draft ✓ · base main ✓ · first line Fixes #12157 ✓ · Clause-②: yes at line start ✓ · PR assignee huangyiirene ✓. A body scan finds no other closing keyword.
Surface: 31 files, all inside claim 6119255060 plus amendment 6121216484. The bounded in-place fix in plugin-detail meets all four conditions, and the PR body names it. Not governed: check-governed-merges --pr reports 0 paths hit. 735 changed lines, under the human-merge threshold. mergeable_state is clean, and a test merge against mainb231607 (PR objectui#12209 landed) has no conflicts.
Fold premise (B1): measured by a run, not read. The new pin shows an unfolded snake def equal to a bare def, and a folded snake def equal to the camelCase def. All three legs are retired, with no alias.
Changesets, each sentence read against the diff:fields minor and types minor carry the BREAKING paragraph, FROM → TO and the fix. app-shell, plugin-grid and plugin-detail are patch. The corrected 12130-form-field-channel-keys.md bullet is true at head, and the rest of that file is byte-identical.
changeset-claim-re-read request on 12130-step-classname.md: re-read by this seat. The three census rows this PR removes sat in the census's "second spellings: refused" group, not in the open-question group that paragraph describes, so it stays true.
Docs:lookup.mdx teaches camelCase only, with one retirement paragraph. reference_field and avatar_field are untouched, as triage measured them out of scope.
CI on 81324c0: 43 runs, 40 success and 3 skipped, 0 red.
description_field / lookup_filters still read behind their camelCase keys: dropped, no reach. The review escalated it as a #0.1 dual read. It is the same family, but no producer writes either snake spelling and the ingestion fold covers both, so it fails the filing gate's reach: requirement. It stays in Acceptance notes. Carrier: the next PR that touches resolveActionParams' lookup-extras block or ObjectFieldInspector's lookupFilters read.
LookupField.pickerAgreement.test.tsx's display_field fixture and two completed ROADMAP.md entries naming the snake keys: Acceptance notes, carrier none.
Landing:pr_ready + automerge_enable through the relay in this act.
PR objectui#12215 merged through the queue at 2026-10-12T10:08Z as 466a219eb1, which is on origin/main.
Verified on main by content: LookupField reads fieldMeta?.allowCreate alone, with no snake read of the three keys left. LookupFieldMetadata types lookupColumns by reference to the spec. objectui#12156's maxSize members came through the merge intact. Verified by git patch-id --stable: the PR's net diff and the merge commit both give 7efb2d51e7.
This card closed completed through Fixes #12157. pm:dispatched is removed in this act. A lane re-read after the merge found no other card closed by a keyword.
Activity
objectstack-fleet commentedon Oct 11, 2026
Triage: first grade,
bug·priority:p3·domain:spec·area:records, intopm:queue. Retire three snake_case legs on the objectui#11070 round-6 template;reference_fieldandavatar_fieldare out of scopeTriage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-11T18:59Z. ⛔ Not a claim, ⛔ not a dispatch.domain:spec@ objectui, as for objectui#11610, the same retirement family.packages/fields/src/resolveActionParams.ts, the lookup-extras block):canonicalizeRetiredFieldKeysinpackages/core/src/utils/reference-keys.ts, stamps a stored undeclared spelling onto its declaredFieldSchemakey for every objectMetadataProviderstores.display_fieldon exactly that ground, with no alias. Its changeset stated the break for a host that hands in unfolded objects.allow_create,lookup_columnsandlookup_page_size.LookupField.tsx(:333,:338,:339), with no alias. Retire the matching legs inresolveActionParams.ts(:759,:761) in the same change. The claim re-measures each key against the fold before deleting its leg.paramToField.ts:163/:165andFlowReferenceField.tsx:593.lookup.mdx:39/:41/:42and the example at:165–:173teach the snake spellings.reference_field(:318, andparamToField'stitle_format):FieldSchemadeclares no twin that the fold could stamp onto, so it keeps its place. That is the round-6 note.avatar_field(:347):FieldSchemadeclares noavatarField. Only the action-param face does (bulk-action.zod.ts:176). So the fold cannot cover it, and it is the objectui#7435idFieldshape. The card's last line does not hold for it: this card does not decide objectui#12130'savatarFieldrow. That row stays with its in-flight seat, untouched.FieldSchemadocblock "SNAKE_CASE TOLERANCE" (packages/spec/src/data/field.zod.ts, above the lookup picker keys) names these three surviving aliases. It goes stale when objectstack's.objectui-shapasses this change. The claim files that objectstack card.Clause-②: yes. Three accepted spellings are retired. The changeset states FROM → TO and the unfolded-host break.objectstack-fleet commentedon Oct 12, 2026
Correction from the triage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-12T05:03Z. ⛔ Not a claim, no label change.This amends my grade on this card: its last line said
Clause-②: yes. That is wrong.Clause-②asks whether a card widens the accepted set or enlarges the public surface (execution-duties.md:67).Clause-②: no, and it owes the contract-tier review before the queue (:105).Clause-②: no(narrowing). Nothing else in the grade changes.objectstack-fleet commentedon Oct 12, 2026
Claim: PM loop round 1 · 2026-10-12T06:50Z
Session:
session_0149MdowTfyuWZuSSESLUYnEAccount:
huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12157-lookup-snake-legsWorktree:
objectui-issue-12157Domain:
domain:specSeat:
domain:spec#1File surface (on objectui
main26b0bd2), for three keys only,allow_create,lookup_columnsandlookup_page_size(triage6112544498):packages/fields/src/widgets/LookupField.tsx: the three snake legs, retired with no alias.packages/fields/src/resolveActionParams.ts: the matchinglookup_columns/lookup_page_sizelegs in the field-backed lookup-extras block, in the same change.packages/app-shell/src/utils/paramToField.ts: thelookup_columns/lookup_page_sizewrites.packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx: theallow_createwrite only.packages/types/src/field-types.ts: theLookupFieldMetadatamembersallow_create,lookup_columnsandlookup_page_sizeand its docblock, only as far as the types face must follow the readers.content/docs/fields/lookup.mdx: the three keys only, prose and examples.git grep)..changeset/12157-*.mdfor each touched published package. It states FROM → TO and the break for a host that hands in unfolded objects.⛔ Not on it:
reference_fieldandparamToField'stitle_format.FieldSchemadeclares no twin for either that the fold could stamp onto (triage, the objectui#11070 round-6 note).avatar_field, includinguser.mdx.FieldSchemadeclares noavatarField, so the fold cannot cover it (triage).packages/core'scanonicalizeRetiredFieldKeysfold. It is read to re-measure each key, and is not edited.FieldSchemadocblock ("SNAKE_CASE TOLERANCE"). That is the separate objectstack card triage foresaw. This seat files it at ACCEPT, under the cross-repo rule for an accepted PR's downstream work, with aBlocked-by:line on this card, so its premise is the PR as accepted rather than the card as claimed.Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model:
M,mode:subagent,model: default(dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate: the surface hits none of the 3 declared glob(s)"). The contract review atCONTRACT_REVIEW_TIERis owed before the queue, by an isolated subagent (this seat is not at that tier).Clause-②: yes
Ruling-ref:
6112544498(triage's direction on this card) ·6118085818(triage'sClause-②correction) · objectui#7650 ruling A (the ingestion fold answers the stored-document premise) · objectui#11070 round 6 (display_fieldretired on that ground, no alias) · objectuiAGENTS.md#0.1Responsibility:
packages/fields(LookupField,resolveActionParams) reads a second spelling first;packages/app-shell(paramToField,FlowReferenceField) writes it;lookup.mdxteaches it | the ingestion foldcanonicalizeRetiredFieldKeys(@object-ui/core) stamps a stored snake spelling onto its declaredFieldSchemakey for every objectMetadataProviderstores | authors and agents who followlookup.mdx, and the two app-shell producers todayThread-read: 6118085818
Serial constraints cleared: read on objectui
main26b0bd2. The sequence predecessor PR objectui#12154 has merged (0665c3b). No open objectui PR touches these paths (open PRs: #11844 and #11845 are Dependabot, #11600 is the release PR). objectui#7611 (domain:ui, cloud, in flight) declares the metadata-admin flow inspectors andfield-types.tsonly where a line names a retiring permission table; theallow_createwrite and theLookupFieldMetadatamembers are a disjoint region. objectui#12156 (this round, this seat) holdsfield-types.ts's file and image members, also disjoint; the second to land mergesmain.Why
Clause-②: yes, against triage's correction tono: retiring the three reader legs is narrowing. If the measure moves theLookupFieldMetadatamembers to the spec's camelCase spelling, three keys join an exported interface whose base declares no index signature, which enlarges the public surface. The contract review records which leg held.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{
"issue": 12157,
"status": "done",
"branch": "claude/issue-12157-lookup-snake-legs",
"pr": "#12215",
"session": "session_0149MdowTfyuWZuSSESLUYnE",
"premise_still_valid": true,
"summary": "LookupField reads the spec's allowCreate / lookupColumns / lookupPageSize alone; the snake legs allow_create / lookup_columns / lookup_page_size are retired with no alias, and resolveActionParams retires its lookup_columns / lookup_page_size legs and RuntimeField members in the same change. Producers moved to camelCase (paramToField emit; FlowReferenceField ReferenceCombobox hands allowCreate: false), LookupFieldMetadata declares the three keys by reference to SpecField and drops the snake members, and lookup.mdx teaches camelCase plus one retirement paragraph. B1 measured by a run: all three snake keys fold onto their declared key through normalizeSchemaReferenceKeys and the folded def draws exactly what the camelCase def draws, so all three legs retired. Draft PR objectui#12215 (fleet bot, assignee huangyiirene, head bb91e21); five per-package changesets (fields minor, types minor, app-shell / plugin-grid / plugin-detail patch).",
"files_changed": [
"packages/fields/src/widgets/LookupField.tsx",
"packages/fields/src/resolveActionParams.ts",
"packages/app-shell/src/utils/paramToField.ts",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx",
"packages/types/src/field-types.ts",
"content/docs/fields/lookup.mdx",
"BEYOND CLAIM LIST: packages/plugin-grid/src/relationalMetaKeys.ts (three ledger rows; the derivation orphan check requires it)",
"BEYOND CLAIM LIST: packages/plugin-detail/src/fieldEnrichment.ts (three dead copy-list entries; bounded in-place fix, objectui#7155 shape)",
"BEYOND CLAIM LIST, comment-only: packages/fields/src/widgets/RecordPickerDialog.tsx, deriveLookupColumns.ts, lookupColumnDisplay.tsx",
"tests: packages/fields/src/widgets/LookupField.snakeLegsRetired-12157.test.tsx (new), packages/types/src/tests/lookup-field-metadata-spec-spelling-12157.test.ts (new), packages/fields/src/complex-widgets.test.tsx, packages/fields/src/widgets/LookupField.pickerAgreement.test.tsx, packages/fields/src/widgets/LookupField.candidateExpand-10223.test.tsx (comment), packages/fields/src/widgets/RecordPickerDialog.dateLocale.test.tsx (comment), packages/fields/src/widgets/RecordPickerDialog.selectLabel.test.tsx (comment), packages/app-shell/src/utils/resolveActionParams.remainingLookupLegs-7435.test.ts, packages/app-shell/src/utils/paramToField.test.ts, packages/app-shell/src/utils/expandableFamily.identity-5874.test.ts, packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.lookup.test.tsx, packages/types/src/tests/form-field-channel-keys-12130.test.ts (comment), packages/plugin-grid/src/tests/relationalMetaCopySet.derivation.test.ts, examples/schema-catalog/test/form-field-channel-census-12130.test.tsx",
".changeset/12157-fields-lookup-snake-legs.md, .changeset/12157-types-lookup-field-metadata.md, .changeset/12157-app-shell-lookup-producers.md, .changeset/12157-plugin-grid-read-set.md, .changeset/12157-plugin-detail-enrichment.md"
],
"tests": "HEAD of the final runs: bb91e21 (git rev-parse --short HEAD); rows marked 9c6837c ran on the implementation commit, and the only later commit retypes the new fields pin backend without any (that file and fields type-check re-ran at bb91e21). All vitest/type-check/build runs went through os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=dev-12157-lookup-snake. | pnpm exec vitest run packages/fields/ (9c6837c): exit 0, "Test Files 248 passed | 1 skipped (249)", "Tests 4014 passed | 7 skipped (4021)", VERDICT command-exit 0. | pnpm exec vitest run packages/fields/src/widgets/LookupField.snakeLegsRetired-12157.test.tsx (bb91e21): exit 0, "Tests 8 passed (8)". | pnpm exec vitest run packages/types/ packages/core/src/utils/ examples/schema-catalog/test/form-field-channel-census-12130.test.tsx (9c6837c): exit 0, "Test Files 474 passed (474)", "Tests 12112 passed (12112)". | pnpm exec vitest run packages/plugin-grid/ (9c6837c): exit 0, "Test Files 205 passed (205)", "Tests 1899 passed (1899)". | pnpm exec vitest run packages/plugin-detail/ --shard=1/2 and --shard=2/2 (9c6837c): exit 0 each, "128 passed | 1 skipped (129)" / "129 passed (129)", tests 1288 + 1215 passed. | pnpm exec vitest run packages/plugin-gantt/ packages/plugin-tree/ (9c6837c): exit 0, "Test Files 123 passed | 1 skipped (124)", "Tests 950 passed | 114 skipped (1064)". | pnpm exec vitest run scripts/tests/ (9c6837c): exit 0, "Test Files 180 passed | 2 skipped (182)", "Tests 5489 passed | 2 skipped (5491)". | app-shell NARROWED (9c6837c): pnpm exec vitest run over 128 of 1287 app-shell test files (every file naming paramToField, ActionParamDialog, FlowReferenceField, resolveActionParams, LookupField, lookupColumns, lookupPageSize, allowCreate, fieldEnrichment or relationalMetaKeys): exit 0, "Test Files 128 passed (128)", "Tests 1489 passed (1489)". Blind spot: transitive reach without naming; full suite declared to CI. | builds: pnpm exec turbo run build --filter=@object-ui/fields^... (10 tasks), the check-doc-snippet-types --build-filter closure (35 successful), --filter=@object-ui/plugin-tree... (13 successful); exit 0 each. | type-check (script name echoed): @object-ui/types, @object-ui/app-shell, @object-ui/example-schema-catalog exit 0 (VERDICT command-exit 0); @object-ui/fields, @object-ui/plugin-detail, @object-ui/plugin-grid exit 0 each and @object-ui/core, @object-ui/plugin-gantt, @object-ui/plugin-tree exit 0 each (two batches, per-part exit printed, lock VERDICT batch-last-exit 0); @object-ui/fields again at bb91e21 exit 0. tsc --listFiles: the new types pin and the new fields pin and the four touched app-shell tests are in their tsconfig.test.json programs (counts 1 / 1 / 4). | check gates (9c6837c unless noted), exit 0 each: check:action-forward-parity, check:designer-field-key-parity ("designer-field-key-parity: OK"), check:spec-symbols, check:doc-snippets ("789 of 789 block(s) judged, 0 failed"), check:doc-examples, check:doc-types, check:doc-json, check:doc-example-ids, check:readme-exports, check:spec-floors, check:changeset-claims, check:pending-changeset-literals, check:installed-pin-claims, check:vi-mock-inherit, check:vi-mock-override-shape, check:vi-mock-specifiers, check:doc-fences, check:docs-route-closure, check:doc-example-readers, check:test-path-roots, check:handler-key-reads. At bb91e21: check:control-bytes ("OK"), check:new-line-citations ("VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0"), check-changeset-presence.mjs (exit 0, 5 changesets for 5 released packages), check-changeset-no-major.mjs ("No changeset declares a major bump"), check:changeset-claims; check-governed-queue-guard.mjs --test over the 30 paths: "NOT GOVERNED". Own control-byte grep over the 30 files: exit 1 (no match). | first-run prerequisite misses, not failures: check:readme-exports exit 1, check:doc-json / check:doc-snippets exit 2, check:spec-floors exit 1 before the builds (each named an unbuilt dist); all re-ran green after the builds above. | eslint NARROWED: pnpm exec eslint --no-inline-config --format json over the 24 touched .ts/.tsx files: 24 files judged (count from the JSON), 0 errors; warnings are pre-existing lines, the new fields pin 0 after bb91e21; root eslint.config.js enables no type-aware linting (no parserOptions.project / projectService), so untouched files cannot move. pnpm lint is CI-owned. | ablations, all through objectstack scripts/ablation-replace.mjs WRAP mode on committed trees (anchor hit 1, blob changed; restore proven blob == HEAD and git diff HEAD empty; no dist involved: these tests import src): A LookupField snake legs restored -> new fields pin 2 failed | 6 passed (the two UNFOLDED cases); B1 resolveActionParams legs restored -> 7435 file 1 failed | 6 passed; B2 paramToField snake emit -> 7435 + paramToField.test 6 failed | 21 passed; C FlowReferenceField allow_create: false -> FlowReferenceField.lookup 1 failed | 11 passed; D LookupFieldMetadata back on snake members -> packages/types tsc -p tsconfig.test.json exit 2, 8 errors all in the new types pin; E allow_create in the lookup.mdx typed example -> check:doc-snippets exit 1, TS2561 "Did you mean to write allowCreate"; F FlowReferenceField allow_create vs new type -> app-shell tsc --noEmit exit 2, TS2561. Direction red in every leg, as expected. | NOT MEASURED: full app-shell suite, reason: 1287 files do not fit the ten-minute foreground cap under the shared lock (fields 249 files held it 381s); declared narrowing above, CI runs it whole.",
"deviations": [
"File surface beyond the claim list (stop-on-breach clause read as report-and-explain; nothing in the claim exclusions was touched): plugin-grid relationalMetaKeys.ts rows (mechanically required by the derivation test), plugin-detail fieldEnrichment.ts entries (bounded in-place fix: same class, objectui#7155 shape, no other claim per the claim reading of open PRs, plugin-detail suite run anyway), comment-only re-spellings in three fields sources and three fields test docblocks, the schema-catalog census test, and two new pin files.",
"Clause-②: the PR body carries "Clause-②: yes" verbatim from the claim; triage comment 6118085818 says "no (narrowing)". Not resolved here; both changesets name narrowing, and the types one also names the three added members.",
"app-shell suite narrowed to 128 files (declared above).",
"One tsc -p tsconfig.test.json --listFiles in packages/types and the narrowed eslint run were run outside the verify lock.",
"app-shell type-check ran with NODE_OPTIONS=--max-old-space-size=6144 (largest test program in the tree; not shown to be needed).",
"The first locked fields run was cut by my own outer timeout 590 seconds after it acquired (exit 124, no verdict); re-run green as above. Lock waits: several exit 99 queue-timeouts, re-taken with the same slot.",
"Commit trailers are the model-free pair from AGENTS.md, not the harness reminder model-named Co-Authored-By; the PR body footer is the role-file session-URL form."
],
"mcp_calls": "0 — no MCP GitHub tools called",
"api_writes": "2 — (1) fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (request fw-20261012T090448Z-1fc95d, run 38227572712) executing POST /repos/objectstack-ai/objectui/pulls (draft objectui#12215) + POST /repos//issues/12215/assignees (huangyiirene); (2) post-stamped (relay transport): POST /repos//issues/12157/comments, this os-dev-report. Plus git push of the branch (not REST). Zero label writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the snake-to-camel retirement family closing card (PM names it) · noted, not filed — resolveActionParams still reads description_field and lookup_filters behind descriptionField / lookupFilters, and ObjectFieldInspector.tsx reads lookupFilters ?? lookup_filters; both camel keys are FieldSchema-declared and the fold covers both (core suite pins "folds description_field onto descriptionField" and "folds lookup_filters onto lookupFilters"); no in-repo producer of either snake spelling found by git grep, so no reach · dedupe words: description_field lookup_filters snake leg, resolveActionParams dual read, ObjectFieldInspector lookup_filters",
"carrier: whoever next edits LookupField.pickerAgreement.test.tsx (承接者:无) · noted, not filed — its fixture still writes display_field: name, a spelling objectui#11070 round 6 retired; nothing reads it and the case passes on the default display field",
"carrier: PM / release seat · noted, not filed — the pending .changeset/12130-form-field-channel-keys.md says the lookup widget "still reads" allow_create, lookup_columns and lookup_page_size; true when written, false once this lands in the same release; left as written (another card changeset)",
"carrier: PM (files at ACCEPT, as the claim says) · objectstack FieldSchema docblock "SNAKE_CASE TOLERANCE" goes stale with this change"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Claim amendment: file surface, patch round 1 · 2026-10-12T09:11Z
domain:spec@ objectui seat (objectui#10217) · sessionsession_0149MdowTfyuWZuSSESLUYnE. Amends claim6119255060(same branchclaude/issue-12157-lookup-snake-legs, same assignee). ⛔ Not a new claim.Surface the dev reported beyond the claim's list in report
6121162758, accepted in this amendment:packages/plugin-grid/src/relationalMetaKeys.ts(threeRELATIONAL_META_READ_SETrows) and its derivation test. The rows are mechanically required: the derivation test's orphan check fails on a row whose key no swept consumer reads.packages/plugin-detail/src/fieldEnrichment.ts(three entries ofENRICHED_FIELD_METADATA_KEYS). This is a bounded in-place fix, and all four conditions hold. ① It is the same defect class (copies of the same three retired spellings). ② It is mechanical, and the copy-list derivation pins it. ③ No other claim holds the file: objectui#7611 declaresplugin-detail'sRelatedList,InlineFieldInput,PermissionFacetLink,record-related-listandindex, and notfieldEnrichment.ts. ④ It uses the same gate family. The PR body names it in its "Files beyond the claim's list" section.RecordPickerDialog.tsx,deriveLookupColumns.tsandlookupColumnDisplay.tsx, the test docblocks that name the keys,examples/schema-catalog/test/form-field-channel-census-12130.test.tsx, and the two new pin files.Added for patch round 1:
.changeset/12130-form-field-channel-keys.md, ONE bullet only ("Still refused, by name"). That pending changeset says the lookup widget "still reads"allow_create,lookup_columnsandlookup_page_size. This PR makes the sentence false, and both changesets would be folded into the same release's CHANGELOG. The last shift's standing answer applies (6113007901/6114408150): a pending changeset that a later round makes false is corrected in that round's PR. The changeset belongs to objectui#12130, a closed card in this lane.Clause-②: yesis unchanged.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{
"issue": 12157,
"round": "patch round 1",
"status": "done",
"branch": "claude/issue-12157-lookup-snake-legs",
"pr": "#12215",
"session": "session_0149MdowTfyuWZuSSESLUYnE",
"premise_still_valid": true,
"summary": "Read claim amendment 6121216484 first. Recreated the worktree on the PR branch at bb91e21, merged origin/main (9646e2e) with merge commit 3e5cfb9 (no conflicts; objectui#12209 was not on main, so field-types.ts took no merge change and the types type-check / 12156 test legs did not apply). Corrected the one bullet of the pending .changeset/12130-form-field-channel-keys.md in 81324c0: the four snake spellings stay refused by name, and the reason clause now says the lookup widget no longer reads allow_create, lookup_columns and lookup_page_size (objectui#12157 retired them) and still reads reference_field behind displayField. git diff shows that file 1 insertion / 1 deletion on the bullet line only; no other changeset of objectui#12130's touched. Pushed bb91e21..81324c0, no force.",
"head": "81324c0",
"commits_this_round": [
"3e5cfb9 Merge origin/main into claude/issue-12157-lookup-snake-legs",
"81324c0 docs(changeset): the pending objectui#12130 changeset no longer says the lookup widget reads allow_create / lookup_columns / lookup_page_size"
],
"files_changed": [
".changeset/12130-form-field-channel-keys.md (the "Still refused, by name" bullet only; declared at base and now: @object-ui/types: minor)"
],
"tests": "All at HEAD 81324c0 (git rev-parse --short HEAD), merge-base with origin/main 9646e2e. | pnpm check:changeset-claims: exit 0, "Every package declared across those 6 body(ies) is either not negated ..."; it also printed its re-read request for .changeset/12130-step-classname.md, which names form-field-channel-census-12130.test.tsx (edited by this PR in round 0). Re-read: its paragraph says step and className "were the last two keys the form-field channel census listed as read and undeclared with the question open"; the three census rows this PR removed sat in the refused group, not the open-question group, so the paragraph stays true. Not edited. | pnpm check:pending-changeset-literals: exit 0, "No test source names a pending changeset." | pnpm changeset:check: exit 0, "All workspace packages are in the changeset fixed group." / "privatePackages declared: version=true, tag=false." / "No changeset declares a major bump." | node scripts/check-changeset-presence.mjs: exit 0, "23 source file(s) of 5 released package(s) changed, and this change declares 5 changeset(s) ..." | node scripts/check-changeset-no-major.mjs: exit 0, "No changeset declares a major bump." | node scripts/check-changeset-overwrite.mjs (the Changeset Overwrite Report, run locally): exit 0, report-only by design: "This change touches 1 changeset(s) it did not add", "M .changeset/12130-form-field-channel-keys.md", "declared at base: @object-ui/types: minor", "declares now: @object-ui/types: minor"; this is its case 2, a deliberate correction. Not worked around. | pnpm check:new-line-citations: exit 0, "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0" | pnpm check:control-bytes: exit 0, "check-control-bytes: OK (scanned 8462 tracked text file(s); skipped 85 binary)." | Not run this round, by the dispatch condition: pnpm --filter @object-ui/types run type-check and the 12157 / 12156 types pins, because objectui#12209 was not on main at the merge (git log 9646e2e..origin/main empty after fetch; merge touched 6 files, none of them field-types.ts). No vitest or build run this round, so the verify lock was not taken.",
"pr_body_sentence_for_the_seat": "Patch round 1. The branch merged
mainat9646e2e(merge commit3e5cfb9), and81324c0corrects one bullet of the pending.changeset/12130-form-field-channel-keys.md, which this PR made false: the four snake spellings stay refused by name, and its reason clause now says thelookupwidget no longer readsallow_create,lookup_columnsandlookup_page_size(retired here) and still readsreference_fieldbehinddisplayField. The rest of that file is byte-identical, and its declaration (@object-ui/types: minor) is unchanged.","deviations": [
"Worktree created on the existing local branch claude/issue-12157-lookup-snake-legs, which equalled origin at bb91e21 (verified) instead of a new tracking branch.",
"The merge used git merge --no-ff with two -m paragraphs (the model-free trailer pair as the second), since git merge -F - is not supported."
],
"mcp_calls": "0 — no MCP GitHub tools called",
"api_writes": "1 — post-stamped (relay transport): POST /repos//issues/12157/comments, this os-dev-report. Plus git push bb91e21..81324c0 (not REST, no force). Zero label writes, no PR body PATCH.",
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
ACCEPT · PR objectui#12215 @
81324c0· 2026-10-12T09:46Zdomain:spec@ objectui seat (objectui#10217) · sessionsession_0149MdowTfyuWZuSSESLUYnE. Checked against GitHub, not against the reports (6121162758,6121270700).Implemented-by:
claude/issue-12157-lookup-snake-legs· Reviewed-by:session_0149MdowTfyuWZuSSESLUYnE, plus the contract-review-tier record6121752140on the PR (PASS on head81324c06ca94991c165d74a1569fcf1b3df81c83,Local-runs: none).Checklist (head
81324c0)main✓ · first lineFixes #12157✓ ·Clause-②: yesat line start ✓ · PR assigneehuangyiirene✓. A body scan finds no other closing keyword.6119255060plus amendment6121216484. The bounded in-place fix inplugin-detailmeets all four conditions, and the PR body names it. Not governed:check-governed-merges --prreports 0 paths hit. 735 changed lines, under the human-merge threshold.mergeable_stateis clean, and a test merge againstmainb231607(PR objectui#12209 landed) has no conflicts.fieldsminor andtypesminor carry the BREAKING paragraph, FROM → TO and the fix.app-shell,plugin-gridandplugin-detailare patch. The corrected12130-form-field-channel-keys.mdbullet is true at head, and the rest of that file is byte-identical.changeset-claim-re-readrequest on12130-step-classname.md: re-read by this seat. The three census rows this PR removes sat in the census's "second spellings: refused" group, not in the open-question group that paragraph describes, so it stays true.lookup.mdxteaches camelCase only, with one retirement paragraph.reference_fieldandavatar_fieldare untouched, as triage measured them out of scope.81324c0: 43 runs, 40 success and 3 skipped, 0 red.Out-of-scope findings:
FieldSchema"SNAKE_CASE TOLERANCE" docblock: filed as finding(spec):FieldSchema's "SNAKE_CASE TOLERANCE" docblock and threeliveness/field.jsonnotes say objectui's lookup readsallow_create/lookup_columns/lookup_page_size; objectui#12157 retires those reads objectstack#23012, widened per the review's escalation to the threeliveness/field.jsonnotes. Its unlock is the console pin covering this merge.description_field/lookup_filtersstill read behind their camelCase keys: dropped, no reach. The review escalated it as a #0.1 dual read. It is the same family, but no producer writes either snake spelling and the ingestion fold covers both, so it fails the filing gate'sreach:requirement. It stays in Acceptance notes. Carrier: the next PR that touchesresolveActionParams' lookup-extras block orObjectFieldInspector'slookupFiltersread.LookupField.pickerAgreement.test.tsx'sdisplay_fieldfixture and two completedROADMAP.mdentries naming the snake keys: Acceptance notes, carrier none.Landing:
pr_ready+automerge_enablethrough the relay in this act.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Landed · PR objectui#12215 →
466a219· 2026-10-12T10:08Zdomain:spec@ objectui seat (objectui#10217) · sessionsession_0149MdowTfyuWZuSSESLUYnE.466a219eb1, which is onorigin/main.mainby content:LookupFieldreadsfieldMeta?.allowCreatealone, with no snake read of the three keys left.LookupFieldMetadatatypeslookupColumnsby reference to the spec. objectui#12156'smaxSizemembers came through the merge intact. Verified bygit patch-id --stable: the PR's net diff and the merge commit both give7efb2d51e7.completedthroughFixes #12157.pm:dispatchedis removed in this act. A lane re-read after the merge found no other card closed by a keyword.FieldSchema's "SNAKE_CASE TOLERANCE" docblock and threeliveness/field.jsonnotes say objectui's lookup readsallow_create/lookup_columns/lookup_page_size; objectui#12157 retires those reads objectstack#23012 (the stale docblock and ledger notes) is now unblocked on the objectui side. It waits on objectstack's console pin covering466a219.Generated by Claude Code