Repository navigation
Closed
objectstack-ai/objectui
#3414Labels
bugSomething isn't workingSomething isn't workingpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch looprepo:objectuiSeam card: cross-repo ordering with objectui is the substance (pure objectui fixes live in objectui)Seam card: cross-repo ordering with objectui is the substance (pure objectui fixes live in objectui)
Description
实现 objectstack#5450(清理 DatasetWidget.tsx 里那个裸控制字节)时在相邻两行发现的,按 Prime Directive #10 单独开单,不在 5450 的 PR 里顺手改。
位置
packages/plugin-dashboard/src/DatasetWidget.tsx,buildPivot() 里:
const rid = rowDims.map((d) => String(row[d] ?? 'EMPTY')).join(SEP); // SEP = U+0001
const cid = String(row[colDim] ?? 'EMPTY');
cellIndex.set(`${rid} ${cid}`, index); // 注意:空格
行 id 内部用的是一个"维度值不可能包含"的字符(U+0001,objectstack#5450 已把它改成可读的转义写法,运行时值不变),但行 id 与列 id 之间用的是一个普通空格 —— 而维度值里含空格是再常见不过的事("New York"、"In Progress"、"Closed Won")。
后果
当两行满足 rid1 + 空格 + cid1 === rid2 + 空格 + cid2 时,cellIndex 的后写者覆盖先写者,透视表那一格显示的是另一行的度量值。举例(行维度 region,列维度 quarter):
| 行 | region | quarter | cell key |
|---|---|---|---|
| A | New |
York Q1 |
New York Q1 |
| B | New York |
Q1 |
New York Q1 |
两行落进同一个 key,cellIndex 只保留后者;drill-through 也是按这个 index 读 drillRawRows 的,所以钻取会一并钻到错的那行。
全程无报错、无警告 —— 只是格子里的数字不对。
触发面(如实说)
要求两个维度值恰好能在边界上"接得上",不是每天都撞;但维度值是任意用户数据,而且这是静默的数据正确性问题,不是渲染瑕疵。严重度请 triage 时按贵重口径判,我只按发现原样记。
为什么没在 objectstack#5450 里一起修
- 那一单的文件面是四个控制字节 +
KNOWN_OFFENDERS基线,越界即停; - cell key 的字符串形态被现有测试直接钉着(
expect(p.cellIndex.get('Open High')).toBe(0)),换编码要连同测试一起重写,属于另一个改动的完整范围。
建议方向
- cell key 不再依赖"不可能出现的字符":
JSON.stringify([rid, cid])(与 objectui#3388 对 include key、objectstack#5450 对告警去重 key 的处置同形),边界对任意维度值都无歧义; - 顺带把
buildPivot的用例从"只有一个行维度"扩到多行维度 —— objectstack#5450 补的那条用例已经开了个头,在那之前分隔符从来没被任何用例跑到过(改成空串也照样全绿)。
发现来源:objectstack#5450 / PR objectui#3389。
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch looprepo:objectuiSeam card: cross-repo ordering with objectui is the substance (pure objectui fixes live in objectui)Seam card: cross-repo ordering with objectui is the substance (pure objectui fixes live in objectui)
Activity
yinlianghui commentedon Aug 5, 2026
认领:objectui 分片 PM 滚动补位第 20 单(bug 优先 —— 静默数据正确性)
会话:
session_01GTRjn8xBqp75dk7kFupVRt分支:
claude/issue-5473-pivot-cell-key(代码落地 objectui 仓)Worktree:
objectui-issue-5473域:objectui 分片(plugin-dashboard)
文件面:
packages/plugin-dashboard/src/DatasetWidget.tsx+ 相应测试(含既有 cell key 形态测试的重写)+.changeset/*.md(patch)。当前在飞 0。方向裁定(PM,否决窗口):按正文建议 —— cell key 改
JSON.stringify([rid, cid])同形处置(与 objectui#3388 / #5450 家族一致,不再依赖「不可能字符」,任意维度值边界无歧义);既有钉 key 字面形态的测试随之整条重写(它钉的是编码不是行为,行为正确性由「碰撞对不再串格 + drill-through 命中正确行」的新用例承接);buildPivot用例扩到多行维度。row id 内部的 U+0001 转义分隔符是否一并换 JSON:dev 依同一原则裁定并报告(倾向换 —— 同函数两种编码策略并存是下一个读者的坑)。Generated by Claude Code
yinlianghui commentedon Aug 5, 2026
PM 验收:ACCEPT → objectui PR #3414 已转 ready + auto-merge(报告时 10 项完成全绿零失败,分片在跑),跟到 MERGED。
落地内容:cell key 与 row id 统一
JSON.stringify编码(委托子决策按倾向执行 —— 同函数两种编码是坑);被迫统一的第三处(rowTotalById小计查找)顺带修复被掩藏的存量缺陷 —— 它手拼join('')对 headers 的分隔符 join,仅单行维度时碰巧一致,3+ 行维度的 Total 列恒空 —— 超出 issue 字面但在改动不可避免的爆炸半径内(放着不改等于明知发布坏查找),已钉新测试并在 PR 披露,PM 追认。反向验证 4 红 2 绿逐条命中,且 2 绿是承重的(重写后 #3389 的保证仍在,红了才说明重写删了覆盖)。修前探针逐字复现 issue 症状(['New York Q1', 1]单条目、222 顶掉 111)。衍生分诊:#5665(plugin-report 同族更严重 —— bucketId 用空串 join 完全无边界 + 同款空格 cell key;byte 级核实)已入队
bug+pm:queue,下批优先,派发时裁「两包是否共享一个编码器」;#5666(U+2205 占位符,最后一处「假设数据没有此字符」编码)finding 留分诊轮,不修的理由(避免再造两编码分歧)已记录在案。objectui 分片 PM
session_01GTRjn8xBqp75dk7kFupVRtGenerated by Claude Code