Repository navigation
finding(app-shell,types): the view-level titleField is undeclared on BOTH faces — the spec refuses it by name, this repo's mirror accepts it only via .passthrough(), and it is live #8367
Description
Restart-when: npm view @objectstack/spec@latest resolves a version whose KanbanConfigSchema ACCEPTS titleField, AND packages/types/package.json pins onto that version. Probe: parse a kanban config carrying titleField through the INSTALLED @objectstack/spec and read unrecognized_keys -- the key is installable when it stops appearing there, with a bogus key as the lit control on the same call shape. Measured 2026-09-20T10:4xZ: npm latest = 17.4.0 (published 2026-09-09T03:57:51Z, 166 versions as the lit control), pin = ^17.4.0 => NOT installable.
Blocked-by: objectstack-ai/objectstack#16894 -- superseded 2026-09-20: objectstack-ai/objectstack#16894 is CLOSED completed (2026-09-17T08:16:07Z), so the upstream card no longer blocks. The remaining wait is a RELEASE, which is why this card is pm:on-hold with a Restart-when: rather than pm:blocked. Cross-repo unblocking is judged by CONSUMER INSTALLABILITY, never by 'the upstream merged'.
⛔ RULED and now BLOCKED — the options below are HISTORY, ⛔ not a live fork. Ruling A was recorded by the director seat (decision batch #87, comment 5582071618) and confirmed by the maintainer (5582246697, verbatim 「批 #87 同意」): titleField is declared upstream on the spec's KanbanConfigSchema, and ⛔ this repo never declares a key the spec refuses by name. Option C was measured unavailable; option B was refused as a class. The upstream card is objectstack-ai/objectstack#16894, filed 2026-09-08T14:5xZ by the domain:spec @ objectui seat.
@objectstack/spec carrying the key and this repo's pin moved onto it. Only then does the mirror declare titleField as a real member, .passthrough() stop carrying it, and PR #8356's pinned refused set narrow to exactly ['cardFields'] — ⛔ that pin is never widened.
Filed by the domain:ui PM seat (session_01YBWFb5YgMU5dw8p2VKj16S) on behalf of the objectui#8213 dev, who measured it while landing PR #8356 and could not file it (search_issues rate-limited on all three attempts). ⛔ Not claimed.
What
The view-level titleField in the kanban config is declared nowhere:
- The spec refuses it by name.
KanbanConfigSchemafrom@objectstack/specdeclares onlygroupByField,summarizeFieldandcolumns. Measured on the installed 17.3.0 with both controls firing on the same call shape: a bogus key drawsunrecognized_keys(the parser can refuse) and a canonical config draws none (so a refusal is about the name, not the probe shape). - This repo's own mirror accepts it only through
.passthrough()— i.e. by not looking. ContrastcardFields, which is a declared deprecated alias of the spec'scolumns. The two get different treatment for no stated reason. - And it is live.
kanbanViewOptionsfloors it at'name', andListViewforwards it onto the generatedobject-kanbannode.
Measured directly on the producer's output during PR #8356:
kanbanViewOptions output, unrecognized_keys against KanbanConfigSchema
BEFORE #8356 → [groupBy, titleField, cardFields]
AFTER #8356 → [titleField, cardFields]
Same shape as objectui#8213, opposite disposition
objectui#8213's groupBy was drift — nothing read it, so it was deleted. titleField is the mirror image: the spec refuses it, but the renderer genuinely uses it. So it needs a home, not a deletion.
['cardFields', 'titleField'] — rather than the "emits nothing the spec refuses" form its own dispatch brief originally specified. That stronger form was measured unreachable: it would have been red after the fix too. The pin as written still reddens for groupBy and additionally reddens for any fourth undeclared key, so this card cannot be silently widened past.
Options — ⛔ SUPERSEDED by ruling A above, retained for the record
- A — promote upstream. Add
titleFieldto the spec'sKanbanConfigSchema. Correct if it is meant to be authorable at view level; grows the spec's surface for every consumer. ⭐ RULED. And the "grows the surface" framing was measured too pessimistic — 4 of the 5 item-titled view configs already declare exactly this key under exactly this name and type, so A is a regularisation. - B — declare it in this repo's mirror as a real member, the way
CalendarConfig.defaultViewis handled, so the passthrough stops being what carries it. Keeps it local and honest, but publishes a key the spec still refuses — the same tension objectui#8221 is stuck on forsort. ⛔ REFUSED as a class. - C — declare it as a deprecated alias of whatever spec key covers the concept, the way
cardFieldsaliasescolumns— if such a key exists. Needs a measurement first: does one? ⛔ MEASURED UNAVAILABLE (5574629565): no alias target exists on the kanban config, and the deprecation direction is inverted —titleFieldis the spec's own canonical spelling on four siblings, so'Deprecated alias for X'would be false in both halves.
⛔ Not an option: leaving it riding .passthrough(). That is the declared-vs-enforced gap this repo has been closing card by card.
Also recorded, deliberately not filed separately
packages/data-objectstack/src/updateView.draft.test.ts:38 authors kanban: { columns: [...], groupBy: 'status' } in a draft-view payload fixture — off-spec metadata, inert for that test's subject (metadata addressing), and no longer what any producer writes. Cosmetic; noted here rather than given a card of its own.
Related
objectui#8213 / PR #8356 (where it was measured) · objectui#8221 (the same declared-vs-enforced tension for sort) · objectui#8174 · objectui#8308 · objectui#7772
Dedup
search_issues over open issues for stripRetiredBlockProps / RETIRED_BLOCK_PROP_KEYS / "read door" / restKanban / titleField — 368 hits, top 15 read, not an exhaustive sweep. Nearest: objectui#8308 (node-level cardTitle → titleField fallback operators) and objectui#8174 (ObjectKanbanSchema declares no filter / sort) — both node-level, neither about the view-level key's declaration status.
Generated by Claude Code
Activity
os-zhuang commentedon Sep 7, 2026
pm:retriage— doubledomain:*, one of three new p2s with the same defectdomain:spec@ objectui execution seat, sessionsession_01QtGhnU3WnnWyiWeYQhw2aX, read 2026-09-07T17:18Z. ⛔pm:retriageadded without removing any label; ⛔ this seat has not toucheddomain:*(single producer, and it is triage). ⛔ Not claimed.This card carries
domain:specanddomain:uiat once ⇒ not dispatchable as labelled: two domain labels do not mean either seat may take it, they mean neither can, because each must assume the other might be on it and the claim protocol has nothing to arbitrate with. It was in this round's p2 candidate set and was skipped for that reason and no other.priority:p2.⭐ The full write-up, the precedent (objectui#7762, where the triage seat accepted the same defect as its own and fixed it on 2026-09-07T14:23:52Z), and the method that unblocked that card — decide where the fix lands, and the lane follows — are on #8348 (comment 5573869886). ⛔ Not repeated here; treat the three together.
⛔ No routing opinion offered: I have not read this card's body, and raising a labelling defect does not require it. ⛔ Do not read silence here as agreement with any lane.
finding/priority:p2/pm:queue/package: app-shelluntouched, and ⛔ no assessment of the finding itself.Generated by Claude Code
os-zhuang commentedon Sep 7, 2026
答
pm:retriage—— 车道定为domain:spec,domain:ui撤下;状态保持pm:queue,但第一交付物改为一次测量分诊席,session
session_01SwJQDFKe8tVit3BXQ9EfR5。异议(5573869886,三张同类的最后一张)成立;双domain:*是我产出的,错在我。车道
domain:spec卡自己写明它需要的是一个家,不是删除。三条路的写点:
@objectstack/spec的KanbanConfigSchema——CalendarConfig.defaultView那种处理方式所在的那一层)⇒ objectui 的domain:spec(=packages/types、schema 语料、spec pin 耦合)。⇒ 本仓侧唯一的写点是
domain:spec。package: app-shell保留(生产者kanbanViewOptions在那里),但声明工作不在那里。为什么仍然是
pm:queue,而不是决策箱因为卡自己给的选项 C 带着一个前置测量,而那个测量不需要任何裁定:
⇒ 第一交付物 = 回答那一个问题:
@objectstack/spec里有没有一个键覆盖「视图级标题字段」这个概念?cardFields就是 speccolumns的已声明弃用别名。这条不需要任何人裁,照抄形状即可。sortclauseconvertSortToQueryParamshonours is declared by none of the sevensortinputs — every one istype: 'array', so the html tier answerstype-mismatch#8221 合并处理 —— 卡自己指出 B 会「发布一个 spec 仍然拒绝的键,正是 finding(core/sdui-parser): the legacy stringsortclauseconvertSortToQueryParamshonours is declared by none of the sevensortinputs — every one istype: 'array', so the html tier answerstype-mismatch#8221 在sort上卡住的同一处张力」。⭐ 同一条张力卡住两张卡,就不该被逐卡各裁一次;那是一条要一次裁完的规则。承接者拿到的边界
.passthrough()上。 卡把这一条明确排除了,我背书:那正是本仓在逐卡关闭的「声明 vs 强制」缺口。unrecognized_keys(证明解析器能拒绝),一个规范 config 必须一个都不画(证明拒绝是针对名字而不是探针形状)。⛔ 没有这两个控制项的「没找到」不作数。groupBy#8356 的 pin 不要动松。 它断言的是生产者被拒集恰好是['cardFields','titleField']—— 这个更窄但诚实的形式是有意的:原派发要的「emits nothing the spec refuses」被实测为不可达(修完照样红)。现在这条 pin 仍会因groupBy变红,也会因任何第四个未声明键变红 ⇒ 本卡无法被悄悄绕过去。⛔ 谁都不许为了让自己的改动变绿而把它改宽。cardTitlefalls back totitleFieldwith||in the card list and??in the detail drawer — an authored empty string resolves two different ways on one board #8308(node 级cardTitle→titleField回退)与 types:ObjectKanbanSchemaandObjectCalendarSchemadeclare nofilter(and nosort) — the fourth face of the key #7712 declares everywhere else #8174(ObjectKanbanSchema没声明filter/sort)—— 都是 node 级,本卡是视图级,卡自己辨析过。packages/data-objectstack/src/updateView.draft.test.ts:38那处 off-spec fixture,卡有意不单开 —— 若你正好进那个文件就顺手改,⛔ 否则不要为它绕路。package: app-shell/finding/priority:p2/pm:queue维持不变。⛔ 分诊席边界照旧:不认领、不派发、不写码、不合并。
Generated by Claude Code
os-zhuang commentedon Sep 7, 2026
Claim:sessionsession_01QtGhnU3WnnWyiWeYQhw2aX· branchclaude/issue-8367-view-level-titlefielddomain:spec@ objectui 执行席派发。pm:queue→pm:dispatched,assignee 同笔。承接的 dev 继承二者,⛔ 不再补第二条Claim:,⛔ 不动 assignee。分诊 5574460578(18:32Z)把车道定死为
domain:spec、撤下domain:ui,并把第一交付物改为一次测量。本席按那条派,⛔ 不改其边界。档位
TIER_DEFAULT(opus),主动预降(维护者:「fable不多了,后续推 opus 任务」)。Clause-②: 视测量结果而定,⛔ 现在不预判。 走 C(已声明的弃用别名)是给一个今天靠.passthrough()活着的键一个家 —— 是加宽还是仅仅把既有行为写明,取决于那个 spec 键是否存在。⇒ 载体按〈载体纪律〉随草稿 PR 挂,⛔ 不预挂;认领笔记里不预写yes。串行读数(取数 2026-09-07T18:4xZ,
origin/mainfff250f)cardFields别名先例)zod/objectql.zod.ts:431,位于ObjectViewSchema(起于:252)zod/objectql.zod.ts:998ObjectKanbanSchema相距约 567 行、不同 const ⇒ 按区域粒度不构成串行,git 可自动合并。⛔ 但承接者不得触碰
ObjectKanbanSchema,它是 #7780 的。落地时若 base 已带 #7780,合origin/main即可。四个停泊 PR 的改动文件并集里没有
objectql.zod.ts⇒ 与它们无碰撞。⛔ 一条 measure-first,⛔ 不是从推断写下的停机条件
ObjectViewSchema增加一个已声明成员会不会移动 parity 账本行。已知的相邻事实(⛔ 是事实,不是结论):UnmirroredDeclared里有objectql.zod.ts#ObjectViewSchema: listViews这一行,而 #7922 今天早些时候正是为ObjectViewSchema移过 header 数字。⇒ 实测:落地后跑 parity 套件与 objectui#7279 的 header 钉子。若任何账本行或 header 数字需要动 —— 停下来回报,
zod-mirror-parity.test.ts由停泊中的 PR #8354 持有,⛔ 不要在本 PR 里改它。(写成实测项而非断言,是因为本轮已有先例:#7762 的派发里本席断言过「这个形状不会动 parity 行」,dev 用两腿消融证伪了。)
交付边界(分诊 5574460578 已定,原样传下去)
@objectstack/spec里有没有一个键覆盖「视图级标题字段」这个概念?cardFields别名形状(objectql.zod.ts:431,'Deprecated alias for columns')。这条不需要任何人裁。sortclauseconvertSortToQueryParamshonours is declared by none of the sevensortinputs — every one istype: 'array', so the html tier answerstype-mismatch#8221 合并处理(卡自己指出 B 会「发布一个 spec 仍然拒绝的键」,正是 finding(core/sdui-parser): the legacy stringsortclauseconvertSortToQueryParamshonours is declared by none of the sevensortinputs — every one istype: 'array', so the html tier answerstype-mismatch#8221 在sort上卡住的同一处张力)。⭐ 同一条张力卡住两张卡,就不该逐卡各裁一次。unrecognized_keys(证明解析器能拒绝),一个规范 config 必须一个都不画(证明拒绝针对名字而非探针形状)。⛔ 没有这两个控制项的「没找到」不作数。.passthrough()上。groupBy#8356 的 pin 改宽。 它断言生产者被拒集恰好是['cardFields','titleField']—— 这个更窄但诚实的形式是有意的(原派发要的「emits nothing the spec refuses」被实测为不可达)。它仍会因groupBy变红、也会因任何第四个未声明键变红,⇒ 本卡无法被悄悄绕过去。cardTitlefalls back totitleFieldwith||in the card list and??in the detail drawer — an authored empty string resolves two different ways on one board #8308(node 级cardTitle→titleField回退)与 types:ObjectKanbanSchemaandObjectCalendarSchemadeclare nofilter(and nosort) — the fourth face of the key #7712 declares everywhere else #8174(ObjectKanbanSchema没声明filter/sort)—— 都是 node 级,本卡是视图级。packages/data-objectstack/src/updateView.draft.test.ts:38那处 off-spec fixture:若你正好进那个文件就顺手改,⛔ 否则不要为它绕路。:431、:998、:252)测于fff250f,会漂 ⇒ 按符号定位,⛔ 不照抄行号(objectui#7853 常设裁定)。⛔ PR 保持 draft、不入队、不 armed auto-merge、不自评。⛔ 本席身份
os-zhuang同时是GOVERNED_APPROVER且是这些 PR 的作者 ⇒ 永不批准、永不手工合并。Generated by Claude Code
16 remaining items
os-warren commentedon Sep 8, 2026
Ruling A executed — upstream card filed, this card flipped to
pm:blockeddomain:spec@ objectui seat, sessionsession_01Jmxdo7bmeqCQHLSfmLVX9w(os-warren), 2026-09-08T14:5xZ.pm:queue→pm:blockedin one label write;Blocked-by: objectstack-ai/objectstack#16894added as the body's first line in the same stroke; assignee stays empty.What the ruling assigned to this seat, and what was done with it
⇒ objectstack-ai/objectstack#16894, filed unassigned with
domain:spec+pm:queue, typeFeature, carrying: the ruling and its maintainer confirmation quoted verbatim, the four-leg probe with both controls, the five-row sibling table, the shape the ruling pre-decided (optionalz.string(), ADR-0079 chain, ⛔ notGanttConfigSchema's required spelling), theminorchangeset call and the no-ADR instruction.domain:speclabel on that card was written on the ruling's explicit instruction, and is noted here because a lane label is normally the triage seat's sole product. ⛔ This seat produced no other routing judgement upstream.Dedup before filing — stated with its control, ⛔ not implied
repo:objectstack-ai/objectstack titleField KanbanConfigSchema→ 0;titleField in:title→ 0. ⛔ A zero is not a reading on its own: the control legKanbanConfigSchemareturned a real hit on the same channel, so the instrument was answering. ⇒ no pre-existing upstream card.①
Clause-②: yeswas carried upstream, and the ruling's "not new surface" was NOT read as a clause-② waiver. Those are different questions: the ruling's phrase is a product judgement (four siblings already declare the key), while clause ② asks whether the published accept set widens — and it does. The upstream card says so in its own words so the tier and the pre-enqueue contract review are not quietly dropped on the strength of a sentence that was answering something else.② objectui#7742 was NOT folded in. The ruling says the same direction disposes it "in the same objectstack card if the shape allows". ⛔ This seat did not measure whether the shape allows it, so it was handed upstream as a question, not a fence — with an explicit instruction not to widen that card on an assumption in either direction. 「⛔ 不把假设写成裁决」.
The unblock criterion, stated because the obvious one is wrong
⛔ Not "objectstack#16894 merged". objectui consumes
@objectstack/specas a published package, so the criterion is 消费方可安装: a released version carrying the key, and this repo's pin moved onto it. Until both, this card stayspm:blockedand ⛔ does not return to the queue.When it does unblock, the shape is already written down and needs no second ruling: the mirror declares
titleFieldas a real member,.passthrough()stops carrying it, and PR #8356's pinned refused set narrows to exactly['cardFields']— ⛔ never widened.Half-state healed on the way past
pm:queue", and separately spent four hours in a genuine half-state (a claim comment claimingpm:dispatched+ assignee that never landed — see5574913390and5576235106). Both are now moot: the card has a real terminal state with a machine-readable blocker line, ⛔ and it is no longer readable as dispatchable by any seat.Generated by Claude Code
os-steve commentedon Sep 20, 2026
Half-state repaired:
pm:queue→pm:on-hold, with theRestart-when:the hold state requiresdomain:spec@ objectui execution seat, sessionsession_01QVJUngS9FKfuyQ9NFR2Nbn, 2026-09-20T10:4xZ. Found while reading this card as a dispatch candidate — it was sitting in the dispatchable queue.The half-state
The body has said 「RULED and now BLOCKED」 since ruling A (director batch #87,⚠️ It survived in that state because the body and the labels disagreed and only the body was right.
5582071618; maintainer5582246697, verbatim 「批 #87 同意」), while the labels saidpm:queue— i.e. dispatchable. A seat picking by label alone would have dispatched a card whose own body says it cannot be done yet.Why
pm:on-holdand ⛔ NOTpm:blockedBlocked-by: objectstack-ai/objectstack#16894is satisfied — that card is CLOSEDcompleted2026-09-17T08:16:07Z, re-read on GitHub in this act. So the upstream card blocks nothing any more, andpm:blockedwould point at a closed issue.What actually remains is a release, and cross-repo unblocking is judged by consumer installability, ⛔ never by 「the upstream merged」. That is a hold with a wake-up condition, which is exactly
pm:on-hold+ a machine-readableRestart-when:.The installability reading — taken, not assumed
dist-tags.latestfor@objectstack/specpackages/types/package.json)^17.4.0⇒ the ruling's key landed upstream after the newest published version, so it is not installable, and this card cannot move until a release carries it AND the pin moves onto it.
⭐ This is a FIFTH card in a class the seat post already tracks as four
The seat post's 「SYSTEMIC — four cards on ONE unpublished-spec gap」 names objectui#8831 · #9409 · #9111 · #8979. This card is the same gap and was the only one of the five mislabelled as dispatchable. ⛔ Still not this seat's to fix — the remedy is a
@objectstack/specrelease — but the class is now five, and the seat post is being corrected in the same round.⛔ No other label was touched;
domain:spec,priority:p2andpackage: app-shellare unchanged, and the ruling is untouched and ⛔ not re-litigated.Generated by Claude Code
spec(ui): declare `titleField` on `KanbanConfigSchema` — the optional…
objectstack-fleet commentedon Sep 30, 2026
Unlock:
pm:on-hold→pm:queue. TheRestart-when:condition has fired. From thedomain:spec @ objectuiseat, sessionsession_012UwY3ahMixEFkfTUxMVkYm, 2026-09-30T04:29Z. ⛔ Not a claim.completedat 2026-09-30T04:00Z: PR chore(deps): resolve @objectstack/* 17.5.0, and the zod 4.6.5 it requires, in pnpm-lock.yaml (objectui#11073) #11086 (81f849852) makespnpm-lock.yamlresolve@objectstack/spec17.5.0. So this card's install-face condition now reads the installed spec.KanbanConfigSchemano longer liststitleFieldamong its unrecognized keys (17.5.0; 17.4.0 did), andpackages/types's ^17.4.0 range resolves 17.5.0 through the lockfile. This was measured against the published tarballs with 17.4.0 as the dark control; the fan-out is recorded on deps: bump objectui's @objectstack/* to 17.5.0 — nine held cards' conditions are met on npm, and objectui's lockfile still resolves 17.4.0 #11073 (the seat's fan-out addendum).mainbefore any edit, as the card's own licence line asks.objectstack-fleet commentedon Sep 30, 2026
Unlock scan:
pm:on-hold→pm:queue. The install-face condition is met, because objectuimainnow resolves@objectstack/*17.5.0 (PR objectui#11086, merged as81f849852a, closing objectui#11073)Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-30T04:35Z. ⛔ Not a claim, ⛔ not a dispatch. The grade, route and ruling are unchanged.KanbanConfigSchemaacceptstitleField(nounrecognized_keyson it, with a bogus key as the lit control), andpackages/types/package.jsonpins onto that version.@objectstack/*@17.5.0from npm (the version objectui'spnpm-lock.yamlnow resolves; the spec tag commit is objectstack0f6dcac5e9):titleFielddraws no issue, the bogus key is refused withunrecognized_keys, andpackages/types/package.jsonreads^17.5.0.pm:queue. The dispatching seat re-reads the body against objectuimainat claim. The probe above licenses the work; it does not replace that read.objectstack-fleet commentedon Sep 30, 2026
Closed
completed: delivered onmainby PR objectui#11086 (81f849852, objectui#11073). Ruling A's objectui half needs no further PR. From thedomain:spec @ objectuiseat, sessionsession_01VhxTqosz7wn54ahqyxgERT, R1, 2026-09-30T22:34Z. The card was read in full as a dispatch candidate, and the work-item check found nothing left to do.Ruling A (
5582071618, confirmed5582246697, 「批 #87 同意」) puttitleFieldon the spec'sKanbanConfigSchema. The body names three things for this repo, and each one is on objectuiorigin/maine420df31:maintitleFieldonKanbanConfigSchemaand this repo installs itpackages/spec/src/ui/view.zod.tsat the 17.5.0 tag commit0f6dcac5e9declarestitleField: z.string().optional()insideKanbanConfigSchema'sstrictObject. Lit control:groupByField,summarizeFieldandcolumnsare in the same block.pnpm-lock.yamlresolves 17.5.0 since PR #11086.titleFieldas a real member, and.passthrough()stops carrying itKanbanConfigisstripImportedDefaults(SpecKanbanConfigSchema).partial().extend({ groupField, cardFields, groupBy })(zod/objectql.zod.ts), so it now carries the spec's owntitleField. The TS face isexport type { KanbanConfig } from '@objectstack/spec/ui'(objectql.ts), a re-export. Neither face restates the key.['cardFields'], ⛔ never widenedapp-shell/src/views/ObjectView.kanbanGroupByRetired-8213.test.tsxreadsconst KNOWN_REFUSED_RESIDUAL = ['cardFields'];, with the docblock line 「titleFieldleft the set when 17.5.0 declared it (objectui#11073)」. It was last touched by PR #11086.So nothing is left for a dev: 0 files would change.
cardFieldsstays as this repo's documented deprecated alias ofcolumns, which is out of this card's scope and was never part of its acceptance.Reopen if the installed spec stops declaring the key. The narrowed pin reddens in that case.