Repository navigation
ListViewSchema.fieldOrder has a complete reader and no producer anywhere — is it meant to be authorable at all, given columns already carries order? #7516
Description
Ruled: 5809517921 · letter ratified 5635656263 (add the per-view fieldOrder relay rung) · 2026-09-24T07:12Z
(Blocked-by line removed 2026-09-11 — objectstack#15184 ruled B; see the director seat ruling in the comments.)
Split out of #7218 by the triage seat (R+122). #7218 filed fieldOrder and rowColor together and said "it may differ per key. I measured the delivery gap, not the intent." Measured this round: it does differ, and the two halves need different answers, so they are now two cards.
⇒ #7218 keeps rowColor (a delivery-path inconsistency, mechanical). This card is fieldOrder (an intent question with no mechanical answer available).
os-decision-facets
Measured — tree origin/main 0e3b3be, read 2026-09-03T16:05:21Z
The reader is real and complete. packages/plugin-list/src/ListView.tsx:
:2241—// Apply hiddenFields and fieldOrder to produce effective fields:2265—if (schema.fieldOrder && schema.fieldOrder.length > 0) {:2266— builds anorderMapfrom the array and sorts the column set by it:2275—schema.fieldOrderis in the memo's dependency list
:2078-2088); located by content instead. ⛔ Not a defect in that card — the file has grown.
No producer, anywhere. Across packages/** and apps/**, every other fieldOrder occurrence belongs to a different, unrelated feature — the metadata-admin form-ordering prop (metadata-admin/SchemaForm.tsx:684/:704/:756, ResourceEditPage.tsx:545/:2674/:2698, registry.ts:131, default-schemas.ts:339). ⛔ None of those is ListViewSchema.fieldOrder, and none reaches ListView.
⇒ The key is declared (it arrives from the @objectstack/spec base), fully implemented behind the declaration, and written by nothing. Reachable today only if a caller puts it on the schema by hand.
⭐ Why this is a decision and not a delivery bug
ListViewSchema already carries columns, which is an ordered array — so column order is already expressible by an author, through a key every host does relay. That makes fieldOrder a second way to say the same thing, and the question is not "which host forgot to relay it" but "should it exist".
⇒ ⛔ Do not fix this by adding fieldOrder to the host relays. That would ship a second ordering mechanism whose interaction with columns order is undefined — and ListView.tsx:2241 shows it composes with hiddenFields too, so the interaction surface is three keys, not two.
四棱
① 长期正确性(主导) —— 一个槽位两种表达是 dialect 而非设计,而这里更糟:columns 的顺序已经是权威顺序,fieldOrder 再给一份,两者冲突时谁赢没有任何地方定义过(实现里 fieldOrder 排在 columns 之后作用,所以事实上它赢,但那是实现顺序不是契约)。⇒ 本轴要求先回答「要不要第二种表达」,⛔ 不允许先接线后定义。
② 真实业务拉力 —— 可测的零:没有任何 host、任何 fixture、任何 app 写过它。⛔ 我没测仓外(见置信缺口)。
③ 防 AI 编码错误 —— AI 作者从 spec 看到 fieldOrder 被声明、从文档看不到它不可达,于是会写它;写了之后静默无效,没有任何门禁会红。这是最坏形态。columns 是否同时被写,而两者的优先级没有定义。
④ 创业期不扩张 —— 退役让面变小;接线是新增一条与既有 columns 重叠的作者面,零实测拉力下扩张。
建议(一句):按 ADR-0049 enforce-or-remove 退役 —— 删掉 ListView 里的 fieldOrder 读取路径(:2241-:2275),让 columns 的顺序成为唯一顺序表达;若 fieldOrder 来自 @objectstack/spec 基座,则在 objectstack 侧立卡走该仓的退役流程,⛔ 不在 objectui 侧偷偷 strip。
回退:若维护者认为「隐藏字段后仍要独立控制剩余列顺序」是真实需求(fieldOrder 与 hiddenFields 同批读取,暗示它本来就是为这个场景设计的),则保留并接线,但同一 PR 必须定义 columns 顺序与 fieldOrder 冲突时的优先级,并把它 pin 住。⛔ 不接受「接线了但优先级留给实现顺序」。
置信缺口(必填):我只测了 packages/** 与 apps/**,没有测 examples/、objectstack 侧的 *.view.ts 语料,也没测用户代码。若 spec 语料里已经有 fieldOrder 的真实作者用法,② 的零就不成立,而且退役会破坏现存文档 —— 这一条足以把建议从「退役」翻成「保留并接线」。⇒ 取用前请先量这个分布。
Related
#7218 (this card's other half — rowColor, which does have a delivery path) · #7199 (description, same defect class, being fixed) · #5435 (rowColor from the normalize/view-save angle — relevant to #7218, ⛔ not to this card).
Generated by Claude Code
Activity
os-warren commentedon Sep 4, 2026
Maintainer ruling recorded — A: retire
fieldOrderat the spec; this card carries the objectui reader removal and is blocked on the spec card.needs-user-decision→pm:blockedin the same stroke.Director seat, summon 14 (
session_01LsEjuNMPitCHwEfYftZ1um, GitHubos-warren). Provenance: maintainer, live PM chat, 2026-09-04, decision batch #28, verbatim 「同意」 on the presented recommendation (A; fallback B — keep and definecolumns×fieldOrder×hiddenFieldsprecedence with pins). Premises re-verified at 05:03Z: objectuiorigin/main4bb5e10— reader atpackages/plugin-list/src/ListView.tsx:2265-2275, zero authoredfieldOrderinpackages/**/apps/**/examples/**; objectstackorigin/maine293038— the key is the spec's (packages/spec/src/ui/view.zod.ts:1794), authored only byview.test.ts, validated bypackages/lint/src/validate-list-view-field-refs.ts, and the liveness ledger's "live" verdict (liveness/view.json:164) citesobjectui: packages/react/src/spec-bridge/bridges/list-view.ts:124, a path that does not exist on objectuimaintoday (control: thebridges/directory itself is absent).The ruling
ListView.fieldOrderis retired in the spec — filed as objectstack#15184 (domain:spec,pm:queue, Clause-② yes,spec-property-retirementroute, consumer census with a positive control as its stop condition, liveness row re-measured).ListView.tsx:2241-2275, thefieldOrderdependency in the memo, and the mention inListView.columnIdentity.test.tsx's header;columnsorder becomes the only order expression — lands after the spec retirement is consumable here (the spec pin that carries it), so this card isBlocked-by: objectstack-ai/objectstack#15184(body line added).columnsandhiddenFieldsis the shape ADR-0049 removes.Execution constraints, for the
domain:uiseat (after unlock)Ruling authority: maintainer 2026-09-04 (batch #28). Related: objectstack#15184 · #7218 (
rowColor, unaffected) · #7199 · ADR-0049.Generated by Claude Code
os-tesla commentedon Sep 11, 2026
Ruling — class-one self-adjudication (director seat, summon #22,
session_01QsCVSivtpwT6ZXs5Rtvqxe(GitHubos-tesla)), 2026-09-11T14:08Z: the upstream ruling flipped to B, so this card's work is the missing relay rung, not the reader removalChannel: 一类自裁 (three-criterion gate). Recorded in the summon #22 ledger on objectstack#12708 for the maintainer's 追认.
What changed upstream. objectstack#15184 — this card's
Blocked-by:— was ruled B by the maintainer today (batch #115, 「同意」):fieldOrderis kept and thecolumns × hiddenFields × fieldOrdercomposition is written into the contract. The 2026-09-04 ruling A (retire at the spec; this card carries the objectui reader removal) rested on a premise measured false (the key is live end to end; see objectstack#15184 comment 5625933602). ⇒ the reader removal this card was blocked for is void.Ruling. What remains on this card is the gap its own body measured and objectui's ABSENCES ledger records as
known-gap(ObjectView.relayRungCensus-7559.test.ts:480): the per-view spellingui/ObjectListView:fieldOrderis declared, accepted, lint-validated and then silently dropped —renderListView's relay (ObjectView.tsx, the...listSchemaspread and thehiddenFieldsrung at ~:2426) has nofieldOrderrung. Add the rung, so an authored per-viewfieldOrderreachesListViewand composes exactly as the list-node spelling does; flip the census ledger entry fromknown-gapto the rung's evidence.ListView.tsxalready runs.fieldOrderstarts ordering its columns — the declared behaviour; one revert.Execution (⚠️ If
domain:uiseat,Clause-②: yes— the relay begins accepting a declared spelling it drops today, the same reading #7435's slices used): the rung, a pin at the relay, the ledger entry, apatchchangeset.ListView's composition and #15184's describe text disagree when you read them, stop and report — that is a spec question, ⛔ not a rider.Blocked-by:line removed from the body (the upstream card is no longer a prerequisite for a rung that needs no spec change).State:
pm:blocked→pm:queue.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Ratified: summon #22 class-1 ruling 5635656263 (add the per-view
fieldOrderrelay rung) · UI closure batch 3 item 2 · maintainer 「同意」 (chat, director seat summon #29,session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T07:10ZThe class-1 self-adjudication recorded on 2026-09-11 was listed for the maintainer's 追认 on objectstack#12708, and it is now ratified as written. Upstream objectstack#15184 kept
fieldOrder(ruling B), so this card's work is the missing rung inrenderListView's relay: an authored per-viewfieldOrderreachesListViewand composes withcolumnsandhiddenFieldsas the contract states. Read on objectuiorigin/main62597c5: the rung is still absent, andObjectView.relayRungCensus-7559.test.ts:480carriesfieldOrderas aknown-gapwhose reason still says the card is open withneeds-user-decision. That text is stale. The PR adding the rung removes theknown-gaprow in the same change, as the census requires.pm:queue·priority:p3·domain:uistand.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
Claim: PM loop round 5 —⚠️ stop and report if
domain:uiexecution seat 2Session:
session_014mXUNuFomfj24w7s1pZzhNBranch:
claude/issue-7516-fieldorder-relay-rungWorktree:
objectui-issue-7516Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/views/ObjectView.tsx(therenderListViewrelay only: the per-viewfieldOrderrung beside thehiddenFieldsrung),packages/app-shell/src/views/ObjectView.relayRungCensus-7559.test.ts(thefieldOrderknown-gaprow removed and replaced by the rung's evidence, plus its now-stale header sentences), a pin at the relay, and one.changeset/7516-…md('@object-ui/app-shell': patch, per the ruling). Stop on breach and explain it in the reportContainer & model:
S,mode:subagent,model: opus—dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes ruling5635656263, ratified5809517921(add the per-viewfieldOrderrelay rung;ListView's composition and objectstack#15184's describe text disagree)Clause-②: yes
Thread-read: 5809517921
Serial constraints cleared: open-PR file lists read 2026-09-25T10:58Z. No open PR touches
packages/app-shell/src/views/ObjectView.tsxor the census test. The one live claim naming that file is this seat's own objectui#7483 (parked atneeds_decision, awaiting the maintainer, with no branch work), whose surface is the props declaration, not the relay. This seat's PR objectui#10577 (objectui#10506) editsplugin-view'sObjectView.tsx, a different file.Clause-②: yes— the relay begins accepting a declared spelling it drops today (the ruling's own reading).Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
os-dev-report
{
"issue": 7516,
"status": "done",
"branch": "claude/issue-7516-fieldorder-relay-rung",
"pr": "#10622",
"session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, the dispatching seat id",
"premise_still_valid": true,
"summary": "Added the per-view fieldOrder rung to renderListView's relay in packages/app-shell/src/views/ObjectView.tsx:
fieldOrder: viewDef.fieldOrder ?? listSchema.fieldOrder, beside the hiddenFields rung and with its precedence (view over list node; a view that authors none keeps the list node's). H1 held (red on base, below); H2 found no disagreement: spec origin/main (objectstack a08e059) describes columns projects, hiddenFields subtracts, fieldOrder sorts the survivors with unlisted survivors last in columns order, and ListView's effectiveFields memo runs exactly that (plus the FLS drop the spec docblock itself names). H3: the census known-gap row is removed, a named check 'objectui#7516 — the per-view fieldOrder rung is present' records the rung as #7199/#7218 are recorded, the two stale header sentences are rewritten, and the census CONTROL case that used fieldOrder as its declared-absence example now uses operations. H5: the relay header comment did not literally call #7516 open; it now says all three instances carry their rung. The card assignee (os-elon-musk) was already set; not written.","tests": "HEAD 09d4968. RED ON BASE (new pin, base relay): 'Tests 3 failed | 2 passed (5)' — 'AssertionError: expected undefined to deeply equal [ 'stage', 'name' ]' (per-view case) and 'expected [ 'owner', 'stage', 'name' ] to deeply equal [ 'stage', 'name' ]' (both override cases); both CONTROLs green. GREEN ON HEAD: pin + census 'Test Files 2 passed (2) · Tests 30 passed (30)'. ABLATION (objectstack scripts/ablation-replace.mjs, WRAP mode, --delete of anchor 'fieldOrder: viewDef.fieldOrder ?? listSchema.fieldOrder,'): 'anchor x1 → x0', 'blob 51a823a8ab22 → d16c4a7d6716', in-run grep -c = 0; predicted before the run 5 failed / 25 passed; measured 'Tests 5 failed | 25 passed (30)': census 'leaves NO member both unrelayed and undeclared' (received [ "fieldOrder" ]) + 'objectui#7516 — the per-view fieldOrder rung is present', pin the three FIX cases; restore 'blob after restore == blob at HEAD (51a823a8ab22)', 'git diff HEAD empty'. No build in the ablation path: both files read ./ObjectView from source. BUILD closure: turbo run build --filter='@object-ui/app-shell^...' --concurrency=2 'Tasks: 28 successful, 28 total'. TYPE-CHECK @object-ui/app-shell ('tsc --noEmit && tsc -p tsconfig.test.json' echoed): 'VERDICT command-exit 0'; tsc -p tsconfig.test.json --listFiles lists ObjectView.fieldOrderRelay-7516.test.tsx and ObjectView.relayRungCensus-7559.test.ts. TESTS whole @object-ui/app-shell package (799 files) from repo root in 11 chunks under the verify lock, every chunk 'VERDICT command-exit 0': 845 files incl. 46 out-of-package tests that read app-shell sources, 9569 passed, 0 failed, 9 skipped (pre-existing env-conditional: describe.runIf(DRIVEN) in auditHistoryDisplay.dateOnlyZone-10183, skipIf in flow-node-config.spec-reconciliation). LINT narrowed, three proofs: ESLint isPathIgnored false for the 3 changed ts/tsx files; eslint --format json: 3 files, 0 errors (ObjectView.tsx warnings 171 head = 171 base; pin 6 no-explicit-any warnings; census 0); calculateConfigForFile shows no parserOptions.project/projectService and no eslint-rules/ rule reads the filesystem, so untouched files' verdicts cannot move; repo-wide pnpm lint left to CI.",
"gates": [
"check-changeset-presence EXIT 0: '3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/7516-fieldorder-relay-rung.md.'",
"check:new-line-citations EXIT 0: 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only'",
"check:control-bytes EXIT 0: 'check-control-bytes: OK (scanned 8692 tracked text file(s); skipped 85 binary).'",
"check-changeset-no-major EXIT 0 · check-changeset-overwrite EXIT 0 ('No pre-existing changeset was modified or deleted.') · check-changeset-fixed EXIT 0 · check-pending-changeset-literals EXIT 0",
"check-changeset-claims EXIT 0 (report-only): names .changeset/7070-no-invented-gantt-date-fields.md for ObjectView.tsx; its paragraph is about the gantt branch, untouched here; re-read, still true",
"check-vi-mock-specifiers / check-vi-mock-inherit / check-vi-mock-override-shape EXIT 0 OK · check-test-path-roots EXIT 0 OK",
"check-shell-escape-residue EXIT 0 · check-action-ref-convention EXIT 0 · check-type-check-coverage EXIT 0 · check-lint-coverage EXIT 0",
"check:unreferenced-sources / handler-key-reads / metadata-write-doors / doc-example-readers / self-import / phantom-deps EXIT 0 OK",
"check:comment-mask-corpus EXIT 0: 1 disagreeing file apps/console/src/pages/DocsIndex.tsx, within the residue objectui#7882 holds; untouched here",
"check-governed-queue-guard --test (4 paths): 'NOT GOVERNED'",
"NOT MEASURED locally, CI's: performance-budget (full console build), readme-exports / spec-range-floors / published-dist (not reached: no manifest, export or docs change), E2E, repo-wide pnpm lint"
],
"files_changed": [
"packages/app-shell/src/views/ObjectView.tsx (the fieldOrder rung beside hiddenFields + the relay header comment)",
"packages/app-shell/src/views/ObjectView.relayRungCensus-7559.test.ts (known-gap row removed, named rung check added, two header sentences, CONTROL example swapped to operations)",
"packages/app-shell/src/views/ObjectView.fieldOrderRelay-7516.test.tsx (new relay pin: 3 FIX + 2 CONTROL)",
".changeset/7516-fieldorder-relay-rung.md ('@object-ui/app-shell': patch)"
],
"deviations": [
"PR assignee NOT set: 'node /home/user/objectstack/scripts/pm/label-write.mjs --repo objectstack-ai/objectui --issue 10622 --assign os-elon-musk' was refused by the Claude Code auto mode classifier before running — 'Permission for this action was denied by the Claude Code auto mode classifier. Reason: [External System Writes]'. Not retried, not rerouted; the seat sets the PR 10622 assignee to os-elon-musk.",
"Role-file increment vs order: the order places os-dev-report on the card; delivered there through post-stamped.mjs (this comment).",
"Worktree /home/user/objectui-issue-7516 did not exist at dispatch; created by this run from /home/user/objectui at origin/main a7df45f (git worktree add --no-track), fetched inside the worktree only."
],
"pr_body_replacement": null,
"mcp_calls": "0 — none",
"api_writes": "2 — (1) pr_create via the fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204, run 36134419419 success) executing POST /repos/objectstack-ai/objectui/pulls (draft) → PR 10622; (2) this os-dev-report comment, POST /repos//issues/7516/comments via post-stamped.mjs. label-write --assign: refused by the classifier before any request, zero writes. git push (not REST): 2 pushes to claude/issue-7516-fieldorder-relay-rung (empty-branch probe, then 09d4968).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: objectui#10577 (this seat's PR editing packages/plugin-view/src/ObjectView.tsx) · plugin-view's renderListView composition reads fieldOrder from currentNamedViewConfig only while it reads hiddenFields from activeView; no reachable door drops a per-view fieldOrder after this PR (the only in-tree renderListView hosts are app-shell ObjectView, now rung-covered, and the Studio design surface, which has no saved views) · noted in PR Acceptance notes, not filed"
]
}
Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
✅ ACCEPT: objectui#10622 at
09d4968; ready and auto-merge follow this ACCEPTdomain:uiseat #2,session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. Claim5831273279. It executes ruling5635656263, ratified5809517921.packages/app-shell/src/views/ObjectView.tsx:fieldOrder: viewDef.fieldOrder ?? listSchema.fieldOrder, besidehiddenFieldsand with its operator and precedence.viewDefis the resolved active view on every path (named entry, default, runtime switch, open draft), the same value thehiddenFieldsrung readsview.zod.ts, objectstackorigin/main) againstListView'seffectiveFieldsstep by step, including the FLS drop, an unlisted survivor sorting last incolumnsorder, an emptyfieldOrderand an emptycolumns: they agree. Duplicates are unspecified on the spec side, so they are not a disagreementknown-gaprow is removed in the same change (the ratification's condition), and the rung is recorded the way #7199 / #7218 are. Members are still re-derived from the zod mirror. TheoperationsCONTROL is a real declared absence with a readerexpected undefined to deeply equal [ 'stage', 'name' ]), green on head. The reviewer re-ran the ablation (delete the rung) in a scratch worktree:5 failed | 25 passed (30), exactly the dev's figureClause-②: yes/ semver'@object-ui/app-shell': patch, both named by the ruling. The changeset and the PR body are true sentence by sentence (reviewer)CONTRACT_REVIEW_TIERon this head, record5832533618. The seat read the transcript: every turn ran at tiergit merge-treeagainst mainb1030c71a: clean. Neighbour commits (#10577 plugin-viewObjectView.tsx, #10597ListView.tsx) touch none offieldOrder,hiddenFieldsoreffectiveFields09d4968: 40 success, 3 skipped by design, 0 redFixes #7516onlyFindings, each with its disposition
packages/spec/liveness/view.json(/props/list/children/fieldOrder, itsnote) says the app-shell relay "still recordsfieldOrderas a declared absence (objectui#7516) in its relay-rung census". That is false once this lands ⇒ owed as a card on objectstack for a re-cite; the seat files it in its next filing round.packages/app-shell/src/views/InterfaceListPage.tsxresolveslistViews[cfg.sourceView]and hand-projects keys, carrying NEITHERhiddenFieldsNORfieldOrder(0 mentions in the file). It is an interface-page door, a different class from this relay ⇒ owed as a card after a dedupe walk, in the next filing round.renderListViewcomposition readshiddenFieldsfromactiveViewandfieldOrderfromcurrentNamedViewConfig. No in-tree host reaches the difference: app-shell handsviews, notlistViews, and Studio hands neither. It stays latent for an out-of-tree host ⇒ Acceptance notes, not filed.Deviations recorded
label-write --assignwas refused by the permission classifier ([External System Writes]). The seat does not re-issue a refused write; it is surfaced to the maintainer.State
In one stroke:
readyand auto-merge (squash), through the relay opspr_ready+automerge_enable. The PR body is the dev's, unchanged.Generated by Claude Code
fix(app-shell): relay a list view's own fieldOrder to ListView (objec…