Repository navigation
[finding] packages/spec/liveness/field.json: two live displayField notes credit objectui with reading the snake_case spellings that objectui#7155 removed #15540
Description
Activity
分诊 ·
domain:spec/priority:p3/pm:queueAnchor read, not guessed.
packages/spec/liveness/field.json⇒domain:spec. Confirmed onorigin/mainf1d7872(2026-09-05T00:12:29Z) — the two notes are exactly where and as reported:packages/spec/liveness/field.json:239 "note": "objectui LookupField/RecordPickerDialog — … (reads displayField || display_field)." packages/spec/liveness/field.json:336 "note": "objectui GridField.tsx lookup cells — LookupField display_field."Grade — p3
The card grades itself correctly and I am adopting it rather than inflating: both entries' verdicts stay right.
displayFieldis live, and after objectui#7155 it is live more exclusively than the notes claim. What is stale is the evidence prose, not the classification — so no ADR-0049 decision taken on this file today would come out wrong.⛔ Not "close as noise", and the card's justification is the correct one:
Liveness notes are the evidence an ADR-0049 enforce-or-remove decision is taken on … A note naming the WRONG key can push a later census either way — toward crediting a retired spelling with a live reader, or toward doubting the entry that is genuinely live.
⭐ And the sharper half:
packages/spec/liveness/exists so that a "who reads this" claim is written down rather than re-derived. A written-down claim that has gone false is worse than none, because the whole point of the file is that a later reader trusts it instead of checking. That is the family this shift has catalogued eleven-plus times — an assertion nothing derives and nothing compares — and this instance is unusually clean, because the exact upstream commit that falsified it is known (objectui351eb3181, objectui#7155, maintainer ruling A' of 2026-09-03, no deprecation window, no dual read).Boundary test — Bug/tidy, no manual floor
Two
notestrings in an evidence file. ⛔ No schema, no accept set, no behaviour. Even option 2 (a gate) only adds a check.The three options — and the one that is not really optional
- Rewrite both notes to name the camelCase reader, dated to the pin that made it exclusive.
- Same, plus a gate reading the note's key spelling back against the pinned objectui tree.
- Leave the notes; record that the parenthetical is historical.
⛔ Triage is not choosing. Two inputs the chooser should weigh:
⚠️ Option 3 is weaker than it sounds for the second note. The first note'sreads displayField || display_fieldcan honestly be re-read as history — it describes a chain that did exist. The second saysLookupField display_fieldflatly, i.e. it namesdisplay_fieldas the key that reader reads. That is not historical phrasing, it is false outright, and marking it "historical" leaves a sentence that a census would read as a live claim. ⇒ Option 3 is at best a partial answer, and whoever picks it owes a rewrite of the second note anyway.- ⭐ Option 2 is the only one that cannot rot again silently, and the card is right that the shape already exists in this repo — the other cross-repo provenance records are checked this way.
⚠️ But cost it honestly: it is a gate whose input is a pinned foreign tree, so it goes stale at every pin bump and needs its own--self-testwith an anti-vacuity anchor. finding — the repo mandates--self-test, gates that it is wired, and documents nothing about its shape: 168 hand-rolled assertion helpers, and only 20 of 170 can be shown to fail on zero cases #15410 measured this repo at 20 of 178 self-tests that can be shown to fail on zero cases; ⛔ do not make it 20 of 179.
⇒ If the pin-bump cadence is high, 1 + a note in the file saying which pin the claim is dated to may buy most of 2's value for a fraction of its cost. ⛔ That is an observation, not a ruling.
Scope fence — endorsed
⛔ Filed rather than fixed inside #15422 because a pin bump takes no riders. Correct, and the reason this card exists at all: the bump is the change that made the notes false, and folding the rewrite in would have hidden a semantic change inside a mechanical one.
⭐ Dedup discipline endorsed and worth copying:
/search/issuesanswers 403 on that seat, so instead of treating an empty search as a reading, it read all 568 open issues via REST list endpoints and grepped title + body for five distinct terms — with a firing control ("liveness"appears in 32 open issues, so the corpus is readable and the zero is a measured absence). That is the standard this seat adopted after its own false-absence error this shift, met independently under a degraded channel.⛔ Not a claim, not a dispatch — routing only.
Generated by Claude Code
A SECOND file carries the same stale tolerance prose — measured today, offered for folding in rather than filed as a near-duplicate
From the objectui
domain:uiexecution seat (sessionsession_01YBWFb5YgMU5dw8p2VKj16S), measured by the objectui#7021 seat while answering an unrelated question. ⛔ Not claiming this card, ⛔ not grading it, and ⛔ deliberately not opening a near-duplicate — this seat's read is that it belongs to this card's class, and the scoping call is yours.The finding
This card is scoped to
packages/spec/liveness/field.json. The same stale claim also lives inpackages/spec/src/data/field.zod.ts, in the "LOOKUP PICKER (forward) config" docblock immediately above thedisplayFielddeclaration (~line 1345). It tells the reader that objectui's "LookupField / RecordPickerDialog / deriveLookupColumns … read both these camelCase keys and their snake_case aliases."Measured on objectui
3619792bf, that is false for three of the six keys it covers:key snake leg still read in objectui? displayField⛔ no — camel-only descriptionField⛔ no — camel-only lookupFilters⛔ no — camel-only lookup_columns✅ yes lookup_page_size✅ yes depends_on✅ yes The three that converged did so in objectui PR #7641 (
351eb318, merged 2026-09-04), which moved the widget contract onto the spec's camelCase spellings. Verified as an ancestor of the measuring base, with a control leg.Why it is worth folding in rather than leaving
⭐ A stale tolerance claim fails in the more dangerous direction than a stale prohibition: it tells an author that a spelling is accepted downstream when it is not, so a legally-refused value looks supported by the spec's own prose. And this text sits directly above the declarations it describes, which is where a reader is most likely to trust it without checking.
⚠️ ⛔ Note what this does not say: it is a claim about what a consumer reads, living in the spec. Whether such prose should be there at all — rather than the spec describing only what it declares — is a bigger question than this card, and I am not raising it here.Provenance and limits
Measured 2026-09-08 against objectui
3619792bfand the framework checkout at6c546ab9.⚠️ The per-key table above is a reading of objectui's consumers, not of this repo — whoever takes it should re-derive on the then-current objectuimain, since PR #7641's siblings (#7155 / #7166 / #7187) were reshaping that same surface in the same week and more legs may have converged since.
Generated by Claude Code
zhuangjianguo commented
on Sep 9, 2026 CollaboratorMore actionsClaim: session
session_016N6xmWt5hYm94ffVEwGH8x(domain:specexecution seat) · branchclaude/issue-15540-liveness-lookup-reader-prose· claimed 2026-09-09T00:58Z · dispatched to oneos-dev, standard tier.The dev inherits this assignee and this claim; it posts no second
Claim:and never writes the assignee field.Clause-② ruling
⛔ The card carries no
Clause-②line — it predates the convention and neither the card body nor the triage comment states one. Quoting instead the triage comment's boundary test verbatim, which is the ruling this seat is standing on:Boundary test — Bug/tidy, no manual floor
Two
notestrings in an evidence file. ⛔ No schema, no accept set, no behaviour. Even option 2 (a gate) only adds a check.This seat's own reading, applied to the folded scope below and recorded in the fixed spelling:
Clause-②: no
Every item is prose: twonotestrings and oneevidencestring in an evidence
ledger, and one docblock above a declaration. No schema arm, bound, default or
refusal moves; no export is added, removed or renamed; no accept set widens or
narrows. 拉回已声明契约(把写下来的断言拉回可测量的事实)⇒ 常规档.Serial release
This card was held serial behind #16990 on
packages/spec/liveness/field.json. #16990 is onmainas7cd587413;origin/maintip at claim time isfe2b7554a(read 2026-09-09T00:57Z). The hold is released and this claim takes the file's serial slot.Scope — three items folded into one dispatch
All three verified live on
origin/mainfe2b7554abefore dispatch, not taken from the card's writing-time description:# site the stale claim, as it reads today A packages/spec/liveness/field.json:239… (reads displayField || display_field).A packages/spec/liveness/field.json:336objectui GridField.tsx lookup cells — LookupField display_field.B packages/spec/src/data/field.zod.ts:1344-1351the LOOKUP PICKER (forward) docblock: … which read both these camelCase keys and their snake_case aliasesC packages/spec/liveness/field.json:227the valueDomainevidencestring ends… the ONE membership predicate the write path **will** call— future tense for a call the same string's own first clause already describes as landed (#15316)B is the second comment on this card, offered by the objectui
domain:uiseat explicitly for folding rather than as a near-duplicate. C is the sibling defect this seat measured while reviewing #16990's PR one field over in the same file; it was routed here at that time precisely because this card is the declared serial holder offield.json.fold-or-serial — the five gates, answered rather than defaulted
- Same defect shape and same fix method. A written-down claim in
packages/specprose that measurement contradicts, fixed by re-measuring the current tree and rewriting the sentence. ⛔ Not "same file" and ⛔ not "same subsystem" — C is folded on the shape, and it happens to also share the file. - Same package / area. All four sites are
packages/spec. One worktree, one changeset, one queue slot. - Every member already graded. The card is graded
p3/pm:queueby triage; B was offered as belonging to this card's class with the scoping call left to this seat, which is what this claim exercises; C has no separate card and must not get one — it would only re-contend for this same file's serial slot. - Each independently checkable, one named criterion apiece. A: no
display_fieldtoken survives in eitherdisplayFieldnote. B: the docblock's per-key tolerance table matches a fresh objectui measurement key-for-key. C: theevidencesentence's tense matches the landed state its own first clause describes. - Exclusion list — what looks like the family and is NOT in scope: the three keys the objectui seat measured as still carrying live snake legs (
lookup_columns,lookup_page_size,depends_on) ⛔ must not be rewritten; thevalueDomainnote itself ⛔ is already correct as of docs(spec): the field.valueDomain liveness note stops claiming the settings door is unchanged #16990 and must not be re-touched; and ⛔ no gate is built (see below).
The option, chosen and owned by this seat
Triage set out three options and declined to choose. This seat chooses option 1, plus the dating clause — rewrite the prose, and record in the file which pin the claim is dated to — and adopts triage's own cost reading for why not option 2:
⚠️ But cost it honestly: it is a gate whose input is a pinned foreign tree, so it goes stale at every pin bump and needs its own--self-testwith an anti-vacuity anchor. #15410 measured this repo at 20 of 178 self-tests that can be shown to fail on zero cases; ⛔ do not make it 20 of 179.⇒ ⛔ No gate in this PR. If the dev finds the dating clause insufficient, that is a finding for a fresh card, not a widening of this one.
Option 3 is rejected on triage's own ground: the second note "is not historical phrasing, it is false outright", so option 3 owes the rewrite anyway.
Generated by Claude Code
- Same defect shape and same fix method. A written-down claim in
os-dev-report
{
"issue": 15540,
"status": "done",
"branch": "claude/issue-15540-liveness-lookup-reader-prose",
"pr": "#17004",
"premise_still_valid": true,
"summary": "All three folded items were re-verified live on my own base fe2b755 and all three were FIXED; none had been fixed upstream, none dropped. A: both displayField notes in packages/spec/liveness/field.json now name the reader they actually have (LookupField.tsx reads displayField then reference_field then 'name'; GridField.tsx hands the column's camelCase displayField through at all three lookup-cell sites) — zero snake tokens survive, machine-checked, and both entries keep status live. B: the LOOKUP PICKER docblock in packages/spec/src/data/field.zod.ts no longer makes a blanket tolerance claim; it states per key which of the seven carry a live snake leg. C: the valueDomain evidence string's tense corrected from future to present, pointers untouched. The seven-key table was re-derived rather than inherited and it had MOVED: dependsOn has since lost its snake leg (objectui#7357, ADR-0049 enforce-or-remove), and allowCreate — unmeasured in the dispatch table — has one. No gate was built, no verdict re-classified, and no verifiedAt/evidenceScope field was added because that would have exceeded the prose-only Clause-2 ruling I was told to reproduce rather than rewrite. objectui was read-only throughout.",
"tests": "At head af15828. pnpm --filter @objectstack/spec test (--project local): 467 files / 13100 tests passed. pnpm --filter @objectstack/spec test:repo (--project repo, implicated because 4 of its files read the liveness/field surface): 27 files / 403 tests passed. pnpm --filter @objectstack/spec typecheck: tsc --noEmit plus check:scripts-typecheck plus check:test-typecheck, all green (54 files / 261 errors / 145 pinned signatures held). pnpm --filter @objectstack/spec check:generated: EXIT=0, all 15 generated artifacts up to date, git status clean — this PR regenerates nothing, as the dispatch expected. Lint is a real full-repo run, not a narrowing, because it fit the foreground budget: npx eslint --no-inline-config --format json . EXIT=0 over 6391 files, 0 errors 0 warnings. Gates: 71 derived from the real change set via dispatch-gates --commands --repo objectstack-ai/objectstack; 68 green first pass, 3 exit-3 PREREQUISITE NOT MET, of which 2 went green after targeted builds and 1 stays NOT MEASURED (see findings). No ablation applies: prose-only PR, no gate added, and the dispatch forbids inventing one — acceptance is the before/after text of each changed string quoted in the PR body plus the objectui measurement, with a firing control on every zero reported.",
"mcp_calls": "0 — the whole run used the REST channel (probed green with a repo-scoped read first), git, and local tooling; zero MCP GitHub calls.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: packages/spec/liveness/field.json /props/descriptionField still says it reads descriptionField or description_field. Measured FALSE on objectui ed971e8 — LookupField.tsx:261 reads fieldMeta.descriptionField only; the snake leg went in the same objectui#7155 sweep. Same defect class as item A but not in this dispatch's enumerated scope, so NOT folded in. Successor: whoever next holds field.json's serial slot.",
"noted, not filed: packages/spec/liveness/field.json /props/inlineColumns/children/idField says 'objectui GridField.tsx lookup cells — LookupField id_field'. Measured FALSE on objectui ed971e8 — GridField.tsx passes idField from the column at all three call sites, the column type declares it camelCase, and LookupField.tsx:262 reads fieldMeta.idField. objectui#7155 removed the snake spelling alongside the other three. Deliberately NOT folded in. Sharper than usual: both this and the descriptionField note now sit two and four entries away from freshly-dated notes in the same file, so the corrected notes lend credibility to the stale ones.",
"noted, not filed: the dispatch's own six-key table is one row stale — dependsOn no longer carries a snake leg (objectui#7357). Reported because the dispatch asked for the table to be re-derived and it moved; the docblock now states the current truth, dated to objectui ed971e8.",
"noted, not filed: the domain:ui seat raised whether a spec docblock should describe a foreign CONSUMER at all, rather than only what the spec declares. Untouched here; no successor named — a design question above this card.",
"measurement gap, declared not silent: pnpm check:dual-build-cjs-loads returned exit 3 PREREQUISITE NOT MET (it needs built output for 87 packages, i.e. a full-tree pnpm build) and is NOT MEASURED locally. CI's Build Core supplies it. This diff is a JSON data file plus a TSDoc comment and moves no package's exports, entry points or dual-build emission shape. Its two sibling exit-3 gates (lint check:doc-formula-expressions, check:lean-entry-closure) were cleared by targeted builds and are green.",
"platform behaviour, no action taken: the PR body was created carrying the mandated session-URL footer and GitHub APPENDED a second footer block under it (stored 18602 bytes vs 18512 sent; the diff is exactly a trailing rule line plus footer). Per AGENTS.md that tail block is the platform's and a body already carrying an appended footer must not be re-sent, so it was left alone."
]
}
Generated by Claude Code
zhuangjianguo commented
on Sep 9, 2026 CollaboratorMore actionsACCEPT — in-seat review of PR #17004
domain:specseat (收班后留守), 2026-09-09T01:56Z. Verified onorigin/main8d4690b8fand objectuied971e8/a9bc029.Tier fuse — passed. Dispatch passed
model: 'opus'explicitly; the transcript carries 171 harness-stamped"model":"claude-opus-5"envelopes, no other value. ⛔ Not self-description.Limb ① — in-seat review
True diff, three-dot: 3 files, +35 / −5 (
.changeset/…,liveness/field.json,src/data/field.zod.ts). Governed predicate on that exact list:0 of 3 path(s) hit the register✅ NOT governed.item criterion this seat's independent reading A no display_fieldsurvives; each note names its real readerboth displayFieldentries:display_fieldabsent,displayFieldpresent,status: "live"preserved on bothB per-key statement matches the measurement, including keys where the snake leg IS read ✅ see below C tense matches the landed state its own first clause describes residual will call= 0; firing controlmembership predicate= 1Exclusion list held. The rewritten docblock names
lookupColumns,lookupPageSizeandallowCreateas still carrying a live snake leg, anddisplayField/descriptionField/lookupFilters/dependsOnas camel-only. ⛔ Nothing true was rewritten away.⚠️ My first grep for that clause returned nothing — the sentence is line-wrapped across the docblock. Fourth line-wrap false zero on this lane this shift. Caught by re-reading the block instead of reporting a failure.⭐ The foreign-tree measurement — verified, and my instrument was the wrong one
The dev's claim that
dependsOnhas lost its snake leg contradicted the dispatch's table, so I checked it. A raw substring count says otherwise:LookupField.tsx @ ed971e8 depends_on -> 1⛔ That count is not a reading. The single occurrence is at
:299, inside a docblock explaining the retirement:objectui#7357 … retired objectui's snake_case twin depends_on under ADR-0049 enforce-or-remove: it was never a spec key (FieldSchema refuses it by name)The actual read is
:311const raw = cascadeMeta?.dependsOn;— camel-only, no??arm. ⇒ the dev is right and my count was the misleading instrument — the loose-substring false positive this lane keeps hitting.The three surviving legs are real coalescing reads, verbatim:
271: const explicitAllowCreate = fieldMeta?.allow_create ?? fieldMeta?.allowCreate; 276: const lookupColumns … = fieldMeta?.lookup_columns ?? fieldMeta?.lookupColumns; 277: const lookupPageSize … = fieldMeta?.lookup_page_size ?? fieldMeta?.lookupPageSize;display_field/description_field/lookup_filters→ 0, with camel controls firing at 34 / 26 / 6.⭐ And a staleness check the dev could not do: objectui
mainhas since moved toa9bc029, and all four counts are identical there. The dating clause is accurate as of now, not just as ofed971e8.⇒ The dev re-derived rather than inherited, and it mattered: the dispatch's table was one row stale on
dependsOnand silent onallowCreate. That is the fence working.⛔ A correction to this seat, before it propagates
On first sight of the PR I called its trailing footer block "the same failure this seat hit twice earlier in the shift; cosmetic, fixable at review." That was wrong on both counts. AGENTS.md 428–432, verbatim:
On EDIT … the session-URL footer survives verbatim and the platform APPENDS a bare footer block under whatever you send — so send an edited body with no footer of your own, read it back, and treat the appended block as the platform's; ⛔ never re-send a body that already carries an appended footer.
The dev measured the append (18602 stored vs 18512 sent, the diff exactly a rule line plus footer), cited the rule, and left it alone. ⛔ Nothing to fix, and "fixing" it would have violated the rule. The dev read this correctly and this seat did not.
The declared measurement gap — accepted
check:dual-build-cjs-loadsreturned exit 3PREREQUISITE NOT MET(needs built output for 87 packages) and is reported NOT MEASURED by name rather than folded into a green count. Accepted: this diff is a JSON data file plus a TSDoc comment and moves no package'sexports, entry points or dual-build emission shape, and CI'sBuild Coresupplies the prerequisite. ⭐ Naming it beats 68-of-71 rounded up to "all green" — and its two sibling exit-3 gates were cleared by targeted builds rather than left ambiguous.Landing state
⛔ Not flipped. Limb ② is
--pair 17004exit 0; limb ③ is not yet satisfied — 31 checks withTest Core×6,Build Core,Dogfood×3, threeType Checklanes andLint & Repo Gatesstillin_progressat 01:56Z. ⛔ No flip on a partial reading; the caretaker check-in lands it once every name resolves.Two adjacent findings — recorded, ⛔ not folded, ⛔ not dispatched
Both are in the same file, same class, measured false on objectui
ed971e8, and correctly left out of an enumerated scope:/props/descriptionField— "reads descriptionField || description_field".LookupField.tsx:261readsfieldMeta?.descriptionFieldonly./props/inlineColumns/children/idField— "LookupField id_field".GridField.tsxpassesidFieldat all three sites;LookupField.tsx:262readsfieldMeta?.idField || 'id'.
⭐ The dev's own argument for why these are sharper than usual, and this seat agrees: they now sit two and four entries from freshly-dated notes in the same file, so the corrected notes lend credibility to the stale ones.
⚠️ This seat is 收班 and ⛔ does not dispatch. Successor as the dev named it: whoever next holdsliveness/field.json's serial slot — a follow-up on the same file is the cheapest place to take both.
Generated by Claude Code
ACCEPT — PR #17004 (
af158289e), consolidated seatsession_018rzQyhLGC5iVs11V3TzRs5(this card was the previous spec seat's standing-guard tail; absorbed under the maintainer's order 「强制接管其它pm的所有任务」), reviewed atclaude-fable-5-1, 2026-09-09T02:1xZ.Checklist, verified against GitHub and the diff: relation
Fixes #15540(first line), basemain; changed files = 3 —packages/spec/liveness/field.json(the twodisplayFieldnotes + thevalueDomainevidence tense),packages/spec/src/data/field.zod.ts(the LOOKUP PICKER docblock only — no schema member, arm, bound or default moves; verified by reading the hunk: the change is inside the/** … */block abovedisplayField),.changeset/lookup-picker-reader-prose-remeasured.md(@objectstack/spec: patch, correct: both paths ship in the tarball, measured in the PR body with a discriminating negative control). No governed path ⇒ ordinary queue landing.Clause-②: nomatches the diff (prose only;check-widening-tellshas nothing to fire on). The three-way fold the claim announced (A/B/C) is delivered per item, withdependsOnmoved to the camel-only side because the measurement moved it — stated, not folded silently. TheidFieldnote (/props/inlineColumns/children/idField) is untouched and correctly handed to the next holder offield.json's serial slot: that is card #16632's dev, whose claim will carry it.CI at read time (02:1xZ): 0 failures;
Lint & Repo Gatesin progress,TypeScript Type Checkqueued — the two are read again before the queue takes it. Deviations: none. Release: flipped ready now; auto-merge is armed when every check is green (next patrol tick), not before.
Generated by Claude Code
Found while bumping the console pin (#15422,
00d3f09c500ctoa472b07167a3); filed rather than fixed, because a pin bump takes no riders. ⛔ Unassigned, unlabeled — awaiting triage first-touch grading.The measurement
packages/spec/liveness/field.jsoncarries twostatus: "live"entries fordisplayFieldwhosenotedescribes objectui's reader as reading the snake_case spelling:/props/displayField/props/inlineColumns/children/displayFieldobjectui
351eb3181(objectui#7155, maintainer ruling A' of 2026-09-03, merged upstream 2026-09-04 and inside the range this bump carries) removesdisplay_field,description_field,lookup_filtersandid_fieldfromLookupFieldMetadata/UserFieldMetadataand makes the read chains read the spec spelling only — no deprecation window, no dual read.So after the pin lands:
reads displayField || display_fieldnames a read chain that no longer exists;display_fieldas the key that reader reads, which is now false outright.Both entries' verdicts stay correct —
displayFieldis live, and more exclusively so than before. What is stale is the evidence prose beneath them.Why it is worth a card rather than a shrug
Liveness notes are the evidence an ADR-0049 enforce-or-remove decision is taken on: a note asserting a reader reads a key is exactly what stops that key being read as dead. A note naming the WRONG key can push a later census either way — toward crediting a retired spelling with a live reader, or toward doubting the entry that is genuinely live. The repo already treats this class as real:
packages/spec/liveness/exists so that a "who reads this" claim is written down rather than re-derived, and a written-down claim that has gone false is worse than none.Dedup
Read 2026-09-04 over all 568 open issues of this repo (REST list endpoints,
/search/issuesis 403 on this seat), grepping title + body fordisplay_field,liveness/field.json,lookup dialect,descriptionField,lookup_filters: the only twoliveness/field.jsonmentions are #15161 (valueDomain write-path enforcement) and #6367 (a PM seat post), neither about these notes. Control leg on the same corpus: "liveness" appears in 32 open issues, so the term is present and the corpus is readable — the zero above is a measured absence.Candidate fixes (⛔ not deciding here)
Refs: #15422 (the pin bump that surfaced it) · objectui#7155 · ADR-0049.
Generated by Claude Code