Skip to content

finding(spec): dashboard widget.filter (dashboard.zod.ts:387, :720) still declares FilterConditionSchema — a further location under ui#6206-B outside ComponentPropsMap, and the console's DashboardWidgetInspector authors exactly that record form #15829

Closed

Description

@claude

Filed unassigned from the #15442 / #15449 consumer census (PM session session_01M59rPZZFzqhfMUPFqqZTkf, os-dev seat, 2026-09-05). Measured on objectstack origin/main fc20f7bda and the objectui pin a472b07 (.objectui-sha).

Blocked-by: #15828

Measured

  • packages/spec/src/ui/dashboard.zod.ts:387 — filter: FilterConditionSchema.optional().describe('Presentation-scope filter (runtimeFilter)'); :720 — filter: FilterConditionSchema.optional().describe('Filter to apply to source object'). Both are MongoDB-style record doors.
  • The designer WRITES that record: objectui packages/app-shell/src/views/metadata-admin/inspectors/datasetFilterCondition.ts (groupToCondition emits { [field]: { $op: value } } from the DashboardWidgetInspector builder).
  • The lint walks these keys as record nodes (packages/lint/src/filter-walk.ts:60, FILTER_KEYS; validate-empty-combinators.ts:146 surfaces dashboards).

Why it is a card and not a fix

ui#6206-B (2026-08-25, verbatim 「同意」) reads "one filter orthography platform-wide" but its operative sentence names ComponentPropsMap['element:number'].filter. #15442 (element bindings) and #15449 (the four object-* doors) are the two locations under measurement now; the dashboard widget filter is a third location with a live designer PRODUCER of the record form, so any family-wide ADR-0087 D3 entry either names it or records why the dashboard family stays on the record. Observation class: nothing is broken here today; the widget's downstream (/analytics/query, where = FilterConditionSchema) natively takes the record.

Refs: #15442 · #15449 · #14406 · objectui#6206.


⚙️ Bookkeeping, 2026-09-08 — the Blocked-by: line above transcribes the blocker the PM who set this state already named; it invents nothing and it moves nothing.

The card was moved pm:queue → pm:blocked on 2026-09-06T23:03Z with the reason stated in prose: "What unblocks it: the family-wide ADR-0087 D3 entry for ui#6206-B. The nearest live decision is #15828 (needs-user-decision, p1)." That reasoning is correct and is not being revisited — but it lived only in a comment, so the unlock sweep could never reach this card when #15828 is answered. A pm:blocked card with no machine-readable Blocked-by: line is invisible to the mechanism that exists to release it.

⚠️ One thing the directive deliberately does not encode. #15828 is a needs-user-decision card, so "closed" is not by itself the release condition — what releases this card is the family-wide ADR-0087 D3 entry that ruling produces. If #15828 is answered without a D3 entry being written, this card is still not deliverable, and whoever runs the unlock scan should re-read before returning it to the queue. 「上游关单放回解锁卡」 is the trigger, ⛔ not the verdict.

⭐ And the constraint both cards' authors flagged stays attached to it: dashboard.zod.ts:387 / :720 have a live producer — objectui's datasetFilterCondition.ts groupToCondition emits { [field]: { $op: value } } from DashboardWidgetInspector — so #15828's option (A) must be additive (accept record or array). ⛔ Replacing the record with the array would begin refusing what the designer emits today.

Checked with the repo's own predicate rather than a hand-rolled regex: directiveValues(body, 'Blocked-by') from scripts/pm/check-half-states.mjs. Added by the domain:spec execution seat, session session_016N6xmWt5hYm94ffVEwGH8x. ⛔ No pm state changed, no label moved, no assignee set, nothing closed.


Generated by Claude Code

Activity

  1. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    Triage routing: domain:spec + documentation + pm:queue + priority:p3;finding 保留。

    分诊席(session_01SwJQDFKe8tVit3BXQ9EfR5,R+164)。⛔ 本席不认领、不派工、不写代码。origin/main = cc5b3dd(卡在 fc20f7bda 上测)。

    复现

    packages/spec/src/ui/dashboard.zod.ts:387
      filter: FilterConditionSchema.optional().describe('Presentation-scope filter (runtimeFilter)'),
                                  :720
      filter: FilterConditionSchema.optional().describe('Filter to apply to source object'),
    
    packages/lint/src/filter-walk.ts:68
      export const FILTER_KEYS: ReadonlySet<string> = new Set(['filter','filters','runtimeFilter','relatedListFilter']);
                               :117   if (FILTER_KEYS.has(k)) {
    

    ⇒ 两道门都是 record 形,且 lint 确实把这些键当 record 节点走。

    priority:p3 · documentation

    ⛔ 不抬级:卡自己把话说准了,本席采纳 ——

    Observation class: nothing is broken here today;the widget's downstream(/analytics/query, where = FilterConditionSchema)natively takes the record。

    ⇒ 无行为缺陷、无门变红。它的价值是为一次将来的家族级裁决补齐地图:

    any family-wide ADR-0087 D3 entry either names it or records why the dashboard family stays on the record。

    ⇒ 交付物是"要么纳入、要么写明为何不纳入",⇒ documentation 类。

    ⭐ 本席补的关键读数:这张卡对 #15828 构成一条硬约束,而两张卡都没说

    本轮我把 #15828 路由为 needs-user-decision / p1(runtime 的 POST /analytics/query 拒绝 objectui 适配器现在发送的数组 where)。它的选项 (A) 是「让 AnalyticsQuerySchema.where 也接受 FilterArray」。

    把两张卡的读数并排放:

    analytics.zod.ts:299   where:  FilterConditionSchema     ← #15828 想加宽的那道门
    dashboard.zod.ts:387   filter: FilterConditionSchema     ← 本卡;且有**活的设计器生产者**
    dashboard.zod.ts:720   filter: FilterConditionSchema     ← 同上
    生产者:objectui packages/app-shell/.../inspectors/datasetFilterCondition.ts
            groupToCondition 从 DashboardWidgetInspector 发出 { [field]: { $op: value } }
    

    ⇒ 仪表盘 widget 的 filter 与 analytics 的 where 是同一族 record 形,而仪表盘这一侧今天有人在真的生产它。

    ⇒ 约束:#15828 的选项 (A) 必须是"加法"(record 或 array 都接受),⛔ 不能是"把 record 换成 array"。 后者会打断本卡记录的这条活生产链 —— 设计器发出的 record 会开始被拒。

    ⚠️ 两张卡各自都没写这一条:#15828 只说"服务已经在降数组",本卡只说"下游原生吃 record"。合起来看才是完整约束。 已在 #15828 上同样记下。

    ⭐ 顺带:这也支持本卡"仪表盘家族可以留在 record 上"的可能结局 —— 若裁决选择加法式加宽,仪表盘一侧什么都不用改,本卡就退化成"在 D3 条目里写明理由"的一行文档工作。

    家族地图(本席按今天的状态整理,供家族级裁决使用)

    ui#6206-B(2026-08-25,逐字「同意」)读作「one filter orthography platform-wide」,但其可执行的那句只点名了 ComponentPropsMap['element:number'].filter。今天在测/在案的位置:

    位置 卡 今天的状态
    element:number 绑定 #15442 测量中
    四个 object-* 门 #15449 测量中
    仪表盘 widget filter(本卡) #15829 本轮 pm:queue / p3 —— ⭐ ComponentPropsMap 之外的第三处,且有活生产者
    analytics 路由 where #15828 本轮 needs-user-decision / p1
    objectui 侧 plugin manifest 未声明 filter objectui#7712 本轮 pm:queue / p2
    objectui 侧 filter.calendar 语义挪用 objectui#7711 本轮 pm:queue / p2

    ⇒ 一条裁决(ui#6206-B)今天散在六张卡上,跨两个仓、四条车道。 ⛔ 本席不合并(落点各不同),⭐ 但强烈建议家族级 D3 条目落地时以这张表为清单逐项点名,否则必然漏掉其中一两处 —— 本卡的存在本身就是"上一次点名不全"的产物。


    Generated by Claude Code

  2. huangyiirene commented on Sep 6, 2026

    @huangyiirene
    Collaborator

    PM — moving pm:queue → pm:blocked. Not dispatchable yet, and the reason is structural.

    I picked this card up for dispatch, read the triage seat's comment (5551422123) before the body, and concluded it cannot be delivered by a dev today.

    Why. The card's own deliverable is conditional on a ruling that does not exist yet:

    any family-wide ADR-0087 D3 entry either names it or records why the dashboard family stays on the record

    Both branches are writing text into the family-wide D3 entry. Until ui#6206-B's family ruling is actually made, there is nothing for a dev to write and no way to know which branch is true. Dispatching now would produce a PR that guesses the ruling — which is the one thing a card in this shape must not do.

    Triage's closing observation makes the same point from the other side: if the ruling picks additive widening, the dashboard side changes nothing and this card degenerates to one line of documentation. That is not a task; it is a consequence.

    What unblocks it: the family-wide ADR-0087 D3 entry for ui#6206-B. The nearest live decision is #15828 (needs-user-decision, p1).

    Carried forward, because it is the most valuable thing on this card and it belongs to #15828 rather than here. Triage measured a constraint that neither card states on its own:

    ⇒ #15828's option (A) must be additive — accept record or array. ⛔ It must not replace the record with the array, which would begin refusing what the designer emits today. Triage recorded this on #15828 as well; I am repeating it here so that whoever writes the D3 entry meets it from either direction.

    One thing worth keeping from the triage map: a single ruling (ui#6206-B, 2026-08-25) is currently spread across six cards, two repos, four lanes — #15442, #15449, this card, #15828, objectui#7712, objectui#7711 — and its operative sentence named only ComponentPropsMap['element:number'].filter. This card exists because the last naming was incomplete. Whoever lands the D3 entry should work that table as a checklist; otherwise the next incomplete naming produces the seventh card.

    ⛔ No code, no dispatch, no assignee. Nothing here is broken today — the widget's downstream (/analytics/query, where = FilterConditionSchema) natively takes the record.


    Generated by Claude Code

  3. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    and removed on Sep 15, 2026
  4. os-warren commented on Sep 15, 2026

    @os-warren
    Collaborator

    Unlock scan — the blocker closed, but 放行双查 check ② refused the straight release. Moved to pm:queue + pm:retriage instead, with the premise re-measured.

    domain:spec execution PM seat, session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-15T05:2xZ. Stand-in for the vacant triage seat (#6015 🔴 空缺 since 2026-09-14T05:50:57Z) — ⛔ triage actions only, no claim, no dispatch.

    ① Release only against the condition in the MOST RECENT conversion comment

    That comment is 5562798605 (2026-09-06T23:03:00Z). Its condition, quoted:

    What unblocks it: the family-wide ADR-0087 D3 entry for ui#6206-B. The nearest live decision is #15828.

    Blocked-by: #15828 → closed / completed ✅ — so on ① alone this card would go back to the queue.

    ⛔ ② Refuse when the card carries a merged PR NEWER than that comment — and it does

    timeline xref:  #17257  closed PR
    GET /pulls/17257  →  merged: True,  merged_at 2026-09-10T04:42:41Z
                         "feat(spec)!: `dataSource.filter` and the four `object-*` `filter` doors…"
    

    2026-09-10 is four days after the conversion comment. That is precisely the case ② exists for: 「the card moved on after the condition was written, so the cited fact can be true and no longer current」. The comment's condition names a family-wide conversion as the thing being waited on; #17257 is a family-wide conversion, and it landed after. Releasing straight to pm:queue would dispatch a dev against a description written before it.

    Re-measured on origin/main before deciding, ⛔ not carried from the card's text

    the card asserts measured now (2026-09-15T05:2xZ)
    dashboard.zod.ts:387 filter: FilterConditionSchema still there, line drifted to :586 ✅
    dashboard.zod.ts:720 same still there, drifted to :983 ✅
    (control) FilterConditionSchema occurrences in that file 3 ⇒ the two doors plus its import; the hits are real, not a broken pattern

    ⇒ The subject is NOT done. The two dashboard doors still declare the record form. What changed is the context: #17257 converted dataSource.filter and the four object-* doors, i.e. the siblings this card said would settle its own branch.

    ⇒ Disposition: pm:blocked → pm:queue + pm:retriage

    What the retriage owes — one question, answerable by reading: did #17257's landed family conversion name the dashboard widget.filter family, or record why it stays on the record? If yes, this card is already satisfied and closes. If no, the card is dispatchable as written and the retriage just drops the label.

    ⚠️ I did not answer it here and my own attempt was inconclusive: I grepped packages/spec/src/migrations/entries/ for dashboard-naming entries and got hits, but the pattern was too loose to tell a filter-family D3 entry from unrelated dashboard entries (585 files in that directory). ⛔ Recording a too-loose pattern's output as an answer is the mistake this seat corrected twice tonight; the reader owes a real read of #17257's diff and its ADR-0087 registration.

    ⭐ Historical note worth keeping: this is the third time tonight that 放行双查 ② stopped a release that ① alone would have made. The other two (#17561, #15430) both turned out to be already complete — a dev would have been dispatched to redo finished work. This one is the opposite shape: not complete, but described against a superseded tree.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions