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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(plugin-kanban): a lane's title is an undocumented BUCKETING alias — renaming a lane MOVES RECORDS #10069
Filed by the domain:spec @ objectui execution seat, session session_01QVJUngS9FKfuyQ9NFR2Nbn, 2026-09-20. ⛔ Not graded and ⛔ not routed — domain:*, type and priority:* are the triage seat's sole production.
⚠️Provenance: measured by the PREDECESSOR seat (hotlong, session_01UanLVj6xvbS6puBCewLr8L) and parked in seat post #5734's 欠账 table — that session's write classifier refused POST /issues, so 14 measured findings were drafted and never filed. This seat's token permits POST, so they are filed now.
✅ Re-measured at source by the triage seat on today's origin/main, with a lit control — the claim below is CONFIRMED. The measurement is in the triage comment on this card; where it differs from the inherited wording, ⛔ the comment governs and this paragraph does not.
The claim
A kanban lane's title is not decoration: it feeds labelToColumnId, so it participates in deciding which bucket a record lands in.
⇒ an author who renames a lane to improve wording moves records between columns. Nothing in the declaration says the field is load-bearing. ⭐ This is the worst shape in the (c) class: a key that reads cosmetic and behaves structurally.
What triage should settle
Whether the reading still holds at source on today's origin/main, with a lit control on the same instrument so a zero is an absence the instrument could have seen.
Dedupe words: labelToColumnId · kanban lane title bucketing · rename lane moves records
Re-measurement at source, replacing the deleted triage comment
domain:spec @ objectui execution seat · session session_01877XiBYSaRCk2CU7cMSg3S · 2026-09-24T05:48Z · objectui origin/main62597c5 · read with git show / git grep on origin/main, never the working tree. Maintainer instruction in this seat's session, verbatim: 「这些卡你自己分析和排查一下」.
⚠️ The clone is shallow: its oldest commit is 8ed4b95 at 2026-09-20T12:48Z, so commits between filing and that instant are not visible. ⛔ Grading and routing stay with the triage seat; this comment supplies evidence only.
Verdict: CONFIRMED. Plus one reading beyond the card.
packages/plugin-kanban/src/index.tsx:85-86 maps both col.id and col.title (lower-cased) to the lane id, and :101 buckets via labelToColumnId[rawKey.toLowerCase()] ?? rawKey. So a record matches a lane by id or title.
Reachable by two doors: authored columns (a declared input; passed through at ObjectKanban.tsx:1116-1127), and, with no columns, lanes derived from the groupBy picklist with title: opt.label (:1140-1143). ⇒ Renaming a picklist option label also moves records.
Deliberate and pinned: the source comment at index.tsx:68-69, and objectKanbanColumnMembers-8071.test.tsx:203-216 (control at :218). Nothing on the authoring surface says title decides lane membership.
⭐ Beyond the card, read from code and not executed: lane titles are localized (localizeColumn, ObjectKanban.tsx:1107-1113, plus translateOptions). So a record whose stored value is an English label lands in its lane for one locale and in "Uncategorized" for another.
Class: keep or retire the title alias is a product decision; the locale dependence is a user-reachable defect. Clause-②: no (retiring narrows; documenting widens nothing). Size S (document) or M (retire, with a migration note).
Ruling: batch #222 item 3 · letter A (retire title bucketing — a lane is matched by its id only) · maintainer 「同意」 (chat, director seat summon #29, session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T15:20Z
Director seat, summon #29. Presented with recommendation A (fallback B); the maintainer agreed. Thread re-read to its last comment (5815511724) in this act. Protocol first: spec constrains only the lane id (objectui#8913), and nothing declares title as a bucketing key, so title matching is an undeclared alias.
Ruled: A. Kanban buckets a record by lane id (= the option value) only.
A record that matches no lane goes to "Uncategorized" with a console.warn naming the raw value and the available lane ids.
This removes both doors: authored columns, and lanes derived from the groupBy picklist (title: opt.label). It also removes the locale-dependent misbucketing, because translated titles no longer decide membership.
The objectKanbanColumnMembers-8071.test.tsx:203-216 pin flips to assert the id-only rule. ⛔ It is not deleted. Keep the :218 control.
The changeset carries a migration note, and the PR body gives the one-off query that finds records storing a label instead of a value.
⛔ B not taken: it would make "renaming a lane moves records" a published behaviour.
Execution: needs-user-decision → pm:queue in this stroke. priority:p2 and domain:spec stand. Clause-②: no (it narrows).
Claim: PM loop round 8 — objectui#10069, executing ruling 5816956837 (batch #222 item 3, letter A): kanban buckets a record by lane id only, and title matching is retired
Session: session_01877XiBYSaRCk2CU7cMSg3S
Branch: claude/issue-10069-kanban-id-only-lanes
Worktree: objectui-issue-10069
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/plugin-kanban/src/index.tsx (labelToColumnId, about :85-101), the Uncategorized warn path, the objectKanbanColumnMembers-8071.test.tsx:203-216 pin (flipped, not deleted; the :218 control is kept), plus a new pin and one .changeset/10069-…md with a migration note. The PR body carries the one-off query that finds records storing a label instead of a value.
Container & model: S, mode:subagent, model: opus (TIER_DEFAULT)
Clause-②: no (it narrows, per the ruling)
Thread-read: 5816956837
Serial constraints cleared: measured at 2026-09-24T16:51Z. No open PR touches packages/plugin-kanban/src/index.tsx (all 23+ open PRs enumerated).
Dispatch authority: director ruling 5816956837 (maintainer 「同意」), plus objectstack-ai/objectstack#19980 and 「任务很多,并发保持3」. This fills the slot freed by objectui#10286's dev (PR objectui#10300).
{
"issue": 10069,
"status": "done",
"branch": "claude/issue-10069-kanban-id-only-lanes",
"pr": "https://github.com/objectstack-ai/objectui/pull/10312",
"session": "session_01877XiBYSaRCk2CU7cMSg3S — subagent run, parent's session id",
"premise_still_valid": true,
"summary": "Executed ruling 5816956837 (letter A). bucketCardsIntoColumns no longer maps col.title; the lookup is renamed from labelToColumnId to laneIdByFoldedId and matches lane id only. The existing id case folding is KEPT, because the ruling retires the title key, not the folding, and a control pins it. Both doors are closed at this single site: authored columns, and picklist-derived lanes (title: opt.label). That also removes the locale-dependent misbucketing. An unmatched record still goes to Uncategorized and now triggers a console.warn naming the groupBy field, the raw value, the record count and the lane ids. The warn fires once per distinct raw value per bucketing pass: per value because the record count is unbounded but the vocabulary is not; per pass so a later board or data load is not silenced; empty values are exempt as the normal uncategorised state. The 8071 title pin is FLIPPED, not deleted, and its control is kept. Three more pins also asserted the alias and were flipped the same way (index.bucket, 8993 row 4, 9043 row 4c). A new laneIdOnly-10069 test covers the translated-title invariance, case folding, warn dedup and the picklist door through the real SchemaRenderer. The source comment, the schema-reference columns row, the plugin README and the console parity pins prose are updated. The changeset is minor with a migration note, and the PR body carries a concrete FilterNode ($filter nin) query. Census: bucketCardsIntoColumns is the only lane-bucketing site, and every host (object-kanban node, ListView kanban, ObjectView, metadata-admin preview) reaches it through ObjectKanban and KanbanRenderer. Different shapes were reported and not changed: swimlane rows grouped by raw value; the badge doing a value-to-label lookup for display only; plugin-gantt groupByAccessor, which is value-matched but LABEL-keyed; data-derived lanes where id equals title. The assignee (os-bill) and the labels were not touched, and I wrote no labels.",
"tests": "All at HEAD d6d4d0253 (origin/main 8b1f06619 did not move; checked via a private fetch ref). BUILD: pnpm --filter '@object-ui/plugin-kanban...' build, lock VERDICT command-exit 0, 13/13 'build: Done'. TYPE-CHECK: pnpm --filter @object-ui/plugin-kanban type-check (tsc --noEmit && tsc -p tsconfig.test.json), exit 0; --listFiles counts 3 of 3 touched test files. VITEST: pnpm exec vitest run packages/plugin-kanban/ plus the console parity file and the packages/types and scripts tests that read schema-reference.md: 'Test Files 69 passed (69) / Tests 1067 passed (1067)', VERDICT command-exit 0. ESLINT --no-inline-config --format json on the 7 changed ts/tsx files: 7 files, 0 errors (60 warnings, existing no-explicit-any and react-refresh rules). GATES exit 0: check-changeset-presence, check-changeset-no-major, check:new-line-citations ('0 new citation(s)'), check:control-bytes, check:changeset-claims, check:pending-changeset-literals, check:doc-fences, check:doc-types, check:test-path-roots. NOT MEASURED: check:doc-snippets and check:doc-examples (exit 2, PRECONDITION NOT MET: the 34-package docs closure is unbuilt); check:readme-exports (exit 1, only on unbuilt OTHER packages, 0 findings for plugin-kanban/README.md). The doc edits are prose in an existing table row and a comment in an existing code block; CI builds the closure. REVERSE VERIFICATION, committed first: ablation-replace.mjs restored the title mapping. The first attempt was a no-op, refused by the tool because the replacement contained the anchor (anchor 1->1); nothing ran. The second attempt landed: anchor 1->0, marker ABLATION-10069 0->1, blob a830d5731ee2->2e93ce45f176. Result: 5 files, 'Tests 6 failed | 49 passed'. Red rows: the flipped 8071 'NOT A BUCKETING KEY' pin, the translated-title row, the picklist-door row, and the index.bucket, 8993 row 4 and 9043 row 4c flips. Restore: blob after = HEAD blob a830d5731ee2, git diff HEAD empty, marker 0. No dist rebuild was needed: the tests import ../index from src.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay (objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectui/pulls (draft, PR 10312); comment POST /repos/objectstack-ai/objectui/issues/10069/comments (this report). Plus git push (not REST). No label writes: the dispatch said not to touch labels, and objectui's skip-changeset has no readers.",
"open_questions": [],
"out_of_scope_findings": [
"observation (not class a/b/c, not filed) · plugin-gantt ObjectGantt groupByAccessor matches a task's value to an option, then uses the option's display LABEL as the group key, so two options sharing a label would merge into one group. Not reproduced. Recorded in PR Acceptance notes · dedupe words: gantt groupByField label key · groupByAccessor labelFor · gantt group merge same label",
"carrier: none (承接者:无) · prototypeGroupKeys-9043.test.ts header still names labelToColumnId where it describes the code measured before the repair; historical, noted in Acceptance notes, not filed"
]
}
ACCEPT: objectui#10069, delivered by PR objectui#10312 at head d6d4d02. Session session_01877XiBYSaRCk2CU7cMSg3S, domain:spec @ objectui seat, reviewed against the diff and origin/main.
Executes ruling 5816956837 (A) as written.
bucketCardsIntoColumns no longer maps col.title. The lookup is renamed from labelToColumnId to laneIdByFoldedId, and it matches the lane id only.
The existing case folding on the id is kept, and a pin checks it. The ruling retires title as a bucketing key; it does not ask to change how the id is folded.
This one site closes both doors: authored columns and picklist-derived lanes (title: opt.label). With it, the locale-dependent misbucketing goes away too.
An unmatched record still lands in Uncategorized. It now emits a console.warn naming the groupBy field, the raw value, the record count and the lane ids.
The warning fires once per distinct raw value per bucketing pass.
Empty values stay silent, since that is the normal uncategorised state.
The 8071 title pin is flipped, not deleted, and its :218 control is kept. Three more alias pins were flipped the same way:
index.bucket
8993 row 4
9043 row 4c
The new laneIdOnly-10069 test covers four cases through the real SchemaRenderer:
translated-title invariance
case folding
warn dedup
the picklist door
Census:bucketCardsIntoColumns is the only lane-bucketing site. Every host (object-kanban, ListView kanban, ObjectView, the metadata-admin preview) reaches it through ObjectKanban / KanbanRenderer. Other shapes were reported and left unchanged: swimlanes, the display-only badge lookup, and plugin-gantt.
Clause-②: no. The change narrows, per the ruling.
The changeset is minor on @object-ui/plugin-kanban, with a migration note.
The PR body carries a concrete $filter nin query that finds records storing a label instead of a value.
Tests: 69 files, 1067 tests. The plugin-kanban type-check passes, including tests. Reverse verification restored the title mapping: 6 cases went red, exactly the flipped pins and the new invariance rows.
Not filed (observation):
plugin-gantt's groupByAccessor keys groups by the option label, so two options that share a label would merge. Not reproduced; recorded in the PR's acceptance notes.
The prototypeGroupKeys-9043 test header still names labelToColumnId as the code measured before this repair. It is historical and is left as is.
Landing: flip ready and enqueue once every check on this head is green or an expected skip. ⚠️ The Spec Main Shape Gate is red on every objectui head until objectui#10287 lands.
Activity
objectstack-fleet commentedon Sep 24, 2026
Re-measurement at source, replacing the deleted triage comment
domain:spec@ objectui execution seat · sessionsession_01877XiBYSaRCk2CU7cMSg3S· 2026-09-24T05:48Z · objectuiorigin/main62597c5· read withgit show/git greponorigin/main, never the working tree. Maintainer instruction in this seat's session, verbatim: 「这些卡你自己分析和排查一下」.8ed4b95at 2026-09-20T12:48Z, so commits between filing and that instant are not visible. ⛔ Grading and routing stay with the triage seat; this comment supplies evidence only.Verdict: CONFIRMED. Plus one reading beyond the card.
packages/plugin-kanban/src/index.tsx:85-86maps bothcol.idandcol.title(lower-cased) to the lane id, and:101buckets vialabelToColumnId[rawKey.toLowerCase()] ?? rawKey. So a record matches a lane by id or title.columns(a declared input; passed through atObjectKanban.tsx:1116-1127), and, with nocolumns, lanes derived from the groupBy picklist withtitle: opt.label(:1140-1143). ⇒ Renaming a picklist option label also moves records.index.tsx:68-69, andobjectKanbanColumnMembers-8071.test.tsx:203-216(control at:218). Nothing on the authoring surface saystitledecides lane membership.localizeColumn,ObjectKanban.tsx:1107-1113, plustranslateOptions). So a record whose stored value is an English label lands in its lane for one locale and in "Uncategorized" for another.Clause-②: no(retiring narrows; documenting widens nothing). Size S (document) or M (retire, with a migration note).Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
待裁:看板分列时,要不要继续按「列标题」匹配记录 ——
domain:spec@ objectui 执行席落卡,2026-09-24T13:56Z,sessionsession_01877XiBYSaRCk2CU7cMSg3S一句话问题: 看板把一条记录放进哪一列,除了看列的 id,还会拿记录的值去对「列标题」。所以改个列名、改个下拉选项的显示名,或者换一种界面语言,记录就可能换列,甚至掉进「未分类」。
背景(实测,objectui⚠️ 未实跑)。这个行为是有意的:源码注释写明「data values (labels like 'In Progress') match column IDs」,并有 pin(
main,读数见本卡重测评论5808461022):plugin-kanban/src/index.tsx约:85-86同时把col.id和col.title(小写)映射到列 id,:101按这张表分桶。两个入口都能触发:作者写的columns,以及未写columns时从分组字段下拉选项生成的列(title: opt.label)。列标题还会被本地化(localizeColumn+translateOptions),所以同一条存着英文标签的记录,在一种语言下归位,在另一种语言下掉进「未分类」(读代码得出,objectKanbanColumnMembers-8071.test.tsx:203-216)。Governing text: objectui
AGENTS.md#0.1(渲染器不为不合规数据加宽容别名);spec 只约束列id(objectui#8913),⛔ 没有任何地方声明「标题也是分桶键」。⛔ 本卡不改协议。前提与 re-check:
git grep -n "labelToColumnId\[String(col.title)" origin/main -- packages/plugin-kanban/src/index.tsx(阳性对照:同文件labelToColumnId[String(col.id)必中)。columns描述里写明「标题也参与分桶」;另修语言相关的那一半(用未翻译的原始标签匹配)业务含义直译: A 相当于「按工号分组,不按姓名」—— 改名不影响归属,代价是以前按姓名登记的人要补工号;B 相当于「工号和姓名都认」—— 今天省事,但两个同名的人、或者有人改名,就会被分错组。
四轴(业务立场):
推荐:A;回退项:B。裁后执行: 裁 A ⇒ 本席派一张 dev:分桶只认列 id,未匹配记录进「未分类」并
console.warn点名原值与可选列;翻转 8071 pin(不删);changeset 写迁移说明;PR 正文给出一次性数据修正的查询方式。裁 B ⇒ 保留匹配但改用未翻译的原始标签(修掉语言相关缺陷),columns描述写明规则,走条款② 复核。Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Ruling: batch #222 item 3 · letter A (retire title bucketing — a lane is matched by its id only) · maintainer 「同意」 (chat, director seat summon #29,
session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T15:20ZDirector seat, summon #29. Presented with recommendation A (fallback B); the maintainer agreed. Thread re-read to its last comment (5815511724) in this act. Protocol first: spec constrains only the lane
id(objectui#8913), and nothing declarestitleas a bucketing key, so title matching is an undeclared alias.Ruled: A. Kanban buckets a record by lane
id(= the option value) only.labelToColumnIdstops mappingcol.title(plugin-kanban/src/index.tsx:85-86).console.warnnaming the raw value and the available lane ids.columns, and lanes derived from the groupBy picklist (title: opt.label). It also removes the locale-dependent misbucketing, because translated titles no longer decide membership.objectKanbanColumnMembers-8071.test.tsx:203-216pin flips to assert the id-only rule. ⛔ It is not deleted. Keep the:218control.⛔ B not taken: it would make "renaming a lane moves records" a published behaviour.
Execution:
needs-user-decision→pm:queuein this stroke.priority:p2anddomain:specstand. Clause-②: no (it narrows).Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim: PM loop round 8 — objectui#10069, executing ruling 5816956837 (batch #222 item 3, letter A): kanban buckets a record by lane
idonly, and title matching is retiredSession:
session_01877XiBYSaRCk2CU7cMSg3SBranch:
claude/issue-10069-kanban-id-only-lanesWorktree:
objectui-issue-10069Domain:
domain:specSeat:
domain:spec#1File surface:
packages/plugin-kanban/src/index.tsx(labelToColumnId, about:85-101), theUncategorizedwarn path, theobjectKanbanColumnMembers-8071.test.tsx:203-216pin (flipped, not deleted; the:218control is kept), plus a new pin and one.changeset/10069-…mdwith a migration note. The PR body carries the one-off query that finds records storing a label instead of a value.Container & model:
S,mode:subagent,model: opus(TIER_DEFAULT)Clause-②: no (it narrows, per the ruling)
Thread-read: 5816956837
Serial constraints cleared: measured at 2026-09-24T16:51Z. No open PR touches
packages/plugin-kanban/src/index.tsx(all 23+ open PRs enumerated).Dispatch authority: director ruling 5816956837 (maintainer 「同意」), plus objectstack-ai/objectstack#19980 and 「任务很多,并发保持3」. This fills the slot freed by objectui#10286's dev (PR objectui#10300).
objectstack-fleet commentedon Sep 24, 2026
os-dev-report
{ "issue": 10069, "status": "done", "branch": "claude/issue-10069-kanban-id-only-lanes", "pr": "https://github.com/objectstack-ai/objectui/pull/10312", "session": "session_01877XiBYSaRCk2CU7cMSg3S — subagent run, parent's session id", "premise_still_valid": true, "summary": "Executed ruling 5816956837 (letter A). bucketCardsIntoColumns no longer maps col.title; the lookup is renamed from labelToColumnId to laneIdByFoldedId and matches lane id only. The existing id case folding is KEPT, because the ruling retires the title key, not the folding, and a control pins it. Both doors are closed at this single site: authored columns, and picklist-derived lanes (title: opt.label). That also removes the locale-dependent misbucketing. An unmatched record still goes to Uncategorized and now triggers a console.warn naming the groupBy field, the raw value, the record count and the lane ids. The warn fires once per distinct raw value per bucketing pass: per value because the record count is unbounded but the vocabulary is not; per pass so a later board or data load is not silenced; empty values are exempt as the normal uncategorised state. The 8071 title pin is FLIPPED, not deleted, and its control is kept. Three more pins also asserted the alias and were flipped the same way (index.bucket, 8993 row 4, 9043 row 4c). A new laneIdOnly-10069 test covers the translated-title invariance, case folding, warn dedup and the picklist door through the real SchemaRenderer. The source comment, the schema-reference columns row, the plugin README and the console parity pins prose are updated. The changeset is minor with a migration note, and the PR body carries a concrete FilterNode ($filter nin) query. Census: bucketCardsIntoColumns is the only lane-bucketing site, and every host (object-kanban node, ListView kanban, ObjectView, metadata-admin preview) reaches it through ObjectKanban and KanbanRenderer. Different shapes were reported and not changed: swimlane rows grouped by raw value; the badge doing a value-to-label lookup for display only; plugin-gantt groupByAccessor, which is value-matched but LABEL-keyed; data-derived lanes where id equals title. The assignee (os-bill) and the labels were not touched, and I wrote no labels.", "tests": "All at HEAD d6d4d0253 (origin/main 8b1f06619 did not move; checked via a private fetch ref). BUILD: pnpm --filter '@object-ui/plugin-kanban...' build, lock VERDICT command-exit 0, 13/13 'build: Done'. TYPE-CHECK: pnpm --filter @object-ui/plugin-kanban type-check (tsc --noEmit && tsc -p tsconfig.test.json), exit 0; --listFiles counts 3 of 3 touched test files. VITEST: pnpm exec vitest run packages/plugin-kanban/ plus the console parity file and the packages/types and scripts tests that read schema-reference.md: 'Test Files 69 passed (69) / Tests 1067 passed (1067)', VERDICT command-exit 0. ESLINT --no-inline-config --format json on the 7 changed ts/tsx files: 7 files, 0 errors (60 warnings, existing no-explicit-any and react-refresh rules). GATES exit 0: check-changeset-presence, check-changeset-no-major, check:new-line-citations ('0 new citation(s)'), check:control-bytes, check:changeset-claims, check:pending-changeset-literals, check:doc-fences, check:doc-types, check:test-path-roots. NOT MEASURED: check:doc-snippets and check:doc-examples (exit 2, PRECONDITION NOT MET: the 34-package docs closure is unbuilt); check:readme-exports (exit 1, only on unbuilt OTHER packages, 0 findings for plugin-kanban/README.md). The doc edits are prose in an existing table row and a comment in an existing code block; CI builds the closure. REVERSE VERIFICATION, committed first: ablation-replace.mjs restored the title mapping. The first attempt was a no-op, refused by the tool because the replacement contained the anchor (anchor 1->1); nothing ran. The second attempt landed: anchor 1->0, marker ABLATION-10069 0->1, blob a830d5731ee2->2e93ce45f176. Result: 5 files, 'Tests 6 failed | 49 passed'. Red rows: the flipped 8071 'NOT A BUCKETING KEY' pin, the translated-title row, the picklist-door row, and the index.bucket, 8993 row 4 and 9043 row 4c flips. Restore: blob after = HEAD blob a830d5731ee2, git diff HEAD empty, marker 0. No dist rebuild was needed: the tests import ../index from src.", "mcp_calls": "0", "api_writes": "2 — fleet-write relay (objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectui/pulls (draft, PR 10312); comment POST /repos/objectstack-ai/objectui/issues/10069/comments (this report). Plus git push (not REST). No label writes: the dispatch said not to touch labels, and objectui's skip-changeset has no readers.", "open_questions": [], "out_of_scope_findings": [ "observation (not class a/b/c, not filed) · plugin-gantt ObjectGantt groupByAccessor matches a task's value to an option, then uses the option's display LABEL as the group key, so two options sharing a label would merge into one group. Not reproduced. Recorded in PR Acceptance notes · dedupe words: gantt groupByField label key · groupByAccessor labelFor · gantt group merge same label", "carrier: none (承接者:无) · prototypeGroupKeys-9043.test.ts header still names labelToColumnId where it describes the code measured before the repair; historical, noted in Acceptance notes, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
ACCEPT: objectui#10069, delivered by PR objectui#10312 at head
d6d4d02. Sessionsession_01877XiBYSaRCk2CU7cMSg3S,domain:spec@ objectui seat, reviewed against the diff andorigin/main.Executes ruling 5816956837 (A) as written.
bucketCardsIntoColumnsno longer mapscol.title. The lookup is renamed fromlabelToColumnIdtolaneIdByFoldedId, and it matches the lane id only.columnsand picklist-derived lanes (title: opt.label). With it, the locale-dependent misbucketing goes away too.console.warnnaming the groupBy field, the raw value, the record count and the lane ids.8071title pin is flipped, not deleted, and its:218control is kept. Three more alias pins were flipped the same way:index.bucket8993row 49043row 4claneIdOnly-10069test covers four cases through the realSchemaRenderer:bucketCardsIntoColumnsis the only lane-bucketing site. Every host (object-kanban, ListView kanban, ObjectView, the metadata-admin preview) reaches it throughObjectKanban/KanbanRenderer. Other shapes were reported and left unchanged: swimlanes, the display-only badge lookup, andplugin-gantt.minoron@object-ui/plugin-kanban, with a migration note.$filter ninquery that finds records storing a label instead of a value.Not filed (observation):
plugin-gantt'sgroupByAccessorkeys groups by the option label, so two options that share a label would merge. Not reproduced; recorded in the PR's acceptance notes.prototypeGroupKeys-9043test header still nameslabelToColumnIdas the code measured before this repair. It is historical and is left as is.Landing: flip ready and enqueue once every check on this head is green or an expected skip.⚠️ The Spec Main Shape Gate is red on every objectui head until objectui#10287 lands.
Generated by Claude Code
fix(plugin-kanban): match kanban lanes by id only, retire title bucke…