Repository navigation
[decision] drillDown.filter and drillDown.mode have NO read site on object-metric and the shared drawer cannot give them one — is that a refusal or a gap? #9002
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 10, 2026 Triage:
domain:ui,needs-user-decision, typeTask,priority:p3.Lane — measured, because the obvious answer is wrong
drillDownlooks like a spec-contract question and is not. On objectstackorigin/main,packages/spec/src/ui/chart.test.tspins the opposite in as many words:drillDownis a REACT-TIER prop only— and
:405pins that adrillDownwritten inside the chart config is rejected, with a message naming which surface owns it. ⇒DrillDownConfigis objectui's own published prop type, not a spec contract.domain:ui, ⛔ not objectui'sdomain:specstream, ⛔ not objectstack.⭐ Why this card is right to exist, stated because the filer worried it might not be
objectui#8970's PR carries a closing keyword ⇒ #8970 leaves the open-issue sweep the moment it merges, taking an explicitly-unmade judgement with it. ⇒ Without this card the question is lost rather than deferred, and a closed card is invisible to every sweep this seat runs.
⭐ The delivering dev raised it and declined to override the closing keyword unilaterally. That is exactly right: the fix for "a closing keyword would bury an open question" is a second card, ⛔ not a weaker keyword.
Why the decision box rather than the enforce-or-remove work channel
Declared-but-unread members normally route to enforce-or-remove as work. ⛔ Not here, because both arms of that channel land on a floor:
- enforce ⇒ build read sites for
filterandmodein the shared drawer ⇒ a feature addition; - remove ⇒ delete two members from a published prop type ⇒ removing shipped surface.
⇒ Neither is triage's, and the card itself rules on nothing by design.
维护者速读
图表上有个「下钻」功能:点一个数字,弹出它背后的明细。这个功能的配置里有五个可写的选项,其中两个 ——
filter(下钻时再筛一道)和mode(用什么方式展示) —— 代码里没有任何地方读它们。写了不报错,也不生效。⚠️ 问的不是"要不要修 bug",而是:当初没实现,是想清楚了不做,还是漏了?- A —— 补上:让共享的下钻抽屉真的读这两个选项。⇒ 作者写了就生效。代价:新增功能,要设计、要测、要长期维护。
- B —— 删掉:把这两个选项从已发布的配置类型里去掉。⇒ 作者再也不会写下一个不生效的配置。
⚠️ 代价:这是已经发布出去的类型,已经这么写的用户会编译报错。 - C —— 留着并写明"暂不生效":最省,但等于承认我们发布的配置里有装饰性的键。
A / B / C?
os-decision-facets
- ① 项目长远合理性:B 让「已声明」与「已实现」重新相等 —— 这正是本仓 enforce-or-remove 纪律的全部意义。A 也让两者相等,但方向相反,且要为一个没人点名要过的能力签下长期维护。C 明确保留一处"写了不生效"的配置,而这恰恰是本仓花最多力气在消灭的那一类。
- ② 实际业务拉动:
⚠️ 没有量到任何一个想用这两个选项的人 —— 这张卡是从 finding(plugin-dashboard): theobject-metricblock hand-rolls its drill drawer, so fiveDrillDownConfigmembers the sharedDrillDownDrawerhonours are silently dropped there #8970 的重路由里掉出来的残留,不是谁提的需求。⇒ A 的拉动是推测的。B 的拉动是防止将来有人写了它然后调试半天,这个拉动是真的但也是未来的。 - ③ 防 AI 犯错:
⚠️ 这是本卡最重的一棱。一个 AI 作者读到配置类型里有filter和mode,必然会写它们 —— 类型就是它的说明书。写完不生效、不报错、不警告 ⇒ 它无从发现,只会在别处找原因。B 是唯一闭合的做法(类型拒绝 = 立刻知道)。A 也闭合。C 是最坏的:注释挡不住类型补全,而 AI 读类型多过读注释。 - ④ 创业阶段不扩散:C 零成本。B 是一次删除加一次 major/minor 说明。A 最贵:两个新读点、新测试、新文档,服务一个尚未出现的用户。
推荐:B。 三棱指向"让声明与实现相等",而 A 与 B 之间的分野是"有没有人要" —— 目前实测没有。⇒ B 更便宜、更闭合,且可逆:将来真有人要,再按 A 加回来即可;反过来先做 A,那两个读点就再也删不掉了。
本分析看不见什么:我没有量过包外有多少消费者已经在写这两个键。objectui 的这些包已发布多个版本,若已有用户在配置里写了
drillDown.filter(哪怕它不生效),B 就是一次破坏性变更,需要一个弃用期而不是直接删。⚠️ 这个读数取不到 —— 会话的仓库作用域只有 objectstack 与 objectui,看不见下游用户代码。priority:p3: nothing is broken, no user is reachable, and the cost of waiting is that two inert keys stay writable.Triage seat ·
session_017VGfRocA8VjczSe84fgjY3· R+169 · 2026-09-10T17:25Z (timestamp taken in the same tool call that posts) · comment from the triage seat
Generated by Claude Code
- enforce ⇒ build read sites for
Ruling recorded — B, as a per-block refusal:
drillDown.filteranddrillDown.modeare refused onobject-metricat the contract door; the shared type keeps them for the blocks that read them (director seat, decision batch #120 item 4, 2026-09-12)Maintainer, verbatim (live PM chat, 2026-09-12T04:2xZ), to decision batch #120 presented as
1A·2A·3D·4B·5C′: 「17508 A AI负责翻译就行。其他同意」.Derived first from the long-term axis: declared equals delivered, per block. The two members are real semantics on chart / pivot (
filter, viacomputeDrillFilter) and on the data table (mode), so they stay on the sharedDrillDownConfig; on a metric — which has no click event for anevent.*interpolation and no row to decide drill-to-record — they can never apply, and the contract says so by refusing them there, not by a doc sentence type-completion never shows. The spec recordsdrillDownas a REACT-TIER prop (chart.zod.ts:382), so the narrowing lives in@object-ui/typesunder ADR-0082's conformance ratchet.Execution
@object-ui/types: theobject-metricblock's drill-down shape excludesfilterandmode(a per-block narrowing of the published type), with a refusal naming the two keys and the blocks where they do apply.- The registration text of
object-metricstates the same in one sentence. Clause-②: no(narrowing); changeset banner says stored metric configs carrying either key are refused at the door.- objectui#8970's reroute stands; the inaccurate sentence in its body ("the drawer reads
filter") is noted here, not rewritten there.
State
needs-user-decision→pm:queue;domain:ui/priority:p3kept.
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsClaim: PM loop round 1 —
domain:uiexecution seat (serial dispatch)
Session:session_01BA3nKVUwKQJf8DBxrSVtNC
Branch:claude/issue-9002-metric-drilldown-refusal
Worktree:objectui-issue-9002
Domain:domain:ui
Seat:domain:ui#1
File surface:packages/plugin-dashboard/src/ObjectMetricWidget.tsx(thedrillDownprop type, its docblock, and the "deliberately NOT forwarded" comment), theobject-metricregistration text inpackages/plugin-dashboard/src/index.tsx,packages/types/src/data-display.tsbesideDrillDownConfig(about:2262) only, andpackages/types/src/zod/data-display.zod.tsbesideDrillDownConfigSchema(about:881) only if the measured door is the zod mirror; tests; one changeset (stop on breach; explain in the report)
Container & model:S,mode:subagent,model: opus(default judgement tier) —priority:p3: a ruled per-block narrowing of a published authoring input, whose door has to be measured first
Clause-②: no
Thread-read: 5643445104
Serial constraints cleared: open-PR file lists read 2026-09-25T15:50Z, and live claims re-read at 16:40Z. PR objectui#10643 (draft, objectui#10583) editsdata-display.tsat:702–:801anddata-display.zod.tsat:280–:346, theTableColumnregion. objectui#7759's claim names theDataTableSchema/TableColumnSchemaregions of the same two files and has no open PR (its group E landed as PR objectui#10294). Both are hunk-disjoint from theDrillDownConfigregion this card may touch. PR objectui#10635 editsplugin-dashboard/src/ObjectDataTable.tsx, which is file-disjoint. The seat runs serially by the maintainer's instruction: this is the only dev in flight.Scope
The ruling (
5643445104, director seat, maintainer 「17508 A AI负责翻译就行。其他同意」): 「B, as a per-block refusal:drillDown.filteranddrillDown.modeare refused onobject-metricat the contract door; the shared type keeps them for the blocks that read them」.- The ruling is 13 days old, so re-measure first on
origin/main.object-metricmust still read neither key. The door that sees an authoredobject-metricdrillDownhas to be found: the published TS type, a zod mirror, or theobjectui check/ validator path. - The shared
DrillDownConfig/DrillDownConfigSchemakeepsfilterandmode. ⛔ No change for chart, pivot or the data table. - ⛔ No new validator and no new runtime channel. If no existing door sees an
object-metricdrillDown, stop before editing and report the fork.
⇒
Fixes #9002.domain:uiseat #1 ·session_01BA3nKVUwKQJf8DBxrSVtNC· claim · 2026-09-25T16:37Z- The ruling is 13 days old, so re-measure first on
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsos-dev-report
{ "issue": 9002, "status": "done", "branch": "claude/issue-9002-metric-drilldown-refusal", "pr": "https://github.com/objectstack-ai/objectui/pull/10681", "session": "session_01BA3nKVUwKQJf8DBxrSVtNC (the parent's, mode:subagent)", "premise_still_valid": true, "summary": "Implements ruling B (comment 5643445104) as a per-block refusal at the TypeScript door. @object-ui/types gains ObjectMetricDrillDownConfig beside DrillDownConfig: it extends DrillDownConfig and adds filter?: never and mode?: never tombstones. These follow the repo's REFUSED BY NAME + @deprecated idiom, and their docblocks name where each key does apply (filter on object-chart / object-pivot via computeDrillFilter, mode on object-data-table). ObjectMetricWidgetProps.drillDown takes the new type, and the widget docblock and the drawer-section comment now cite the ruling. The object-metric registration's drillDown description adds one sentence. The shared DrillDownConfig and its zod mirror are unchanged, and chart, pivot and data table are untouched. The changeset declares both packages at patch.\n\nPremise re-measured on d08ab2fc8: the metric reads only enabled (isDrillEnabled), title (resolveDrillTitle), and target / columns / maxRows / report (DrillDownDrawer props). The drawer gets the metric's own resolved filter, and its inner table gets a hard-coded mode.\n\nDoors, measured in order:\n(1) The TS type: ObjectMetricWidget is exported from the package entry, and React.ComponentProps / JSX reach its props. This door sees the members and is narrowed here.\n(2) Registry inputs and manifest: drillDown is type 'object' with no 'of', so codegen emits a Record of string to unknown and validateTree checks the coarse kind only. It does not see the members.\n(3) objectui validate / check: safeValidateSchema has no object-metric arm, so a tsx probe shows every object-metric node refused at the type discriminator, with or without drillDown. The positive control on object-data-table does reach drillDown.enabled. check uses this only as a recogniser. It does not see the members.\n(4) The spec: ObjectMetricPropsSchema.drillDown is z.unknown() in @objectstack/spec 17.4.0. It sees the key but not its members.\n\nSo no runtime door was added, as dispatched. STORED JSON configs carrying either key are NOT refused: the refusal is at the type door only. The changeset banner states exactly that instead of the ruling's 'refused at the door' wording. PM to rule (open question 1).\n\nFile surface was kept. The widget imports the type from the published subpath @object-ui/types/data-display, because the root barrel list in packages/types/src/index.ts is outside the claim (open question 2).\n\nOne edit beyond code: the header of objectMetricDrillDownMembers-8071.test.tsx (in the 'tests' surface) gets an AMENDED note, because its advice against a narrower metric drill schema is now ruled for these two members. Its recorded measurements are untouched.\n\nAttribution: commit trailers are model-free (Co-Authored-By: Claude plus Claude-Session). The PR footer is the session-URL form this contract prescribes, not the harness reminder's form.", "tests": "All at HEAD fdaeab1b1 unless stated.\n\n(1) Build: pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-dashboard^...' run build under os-verify-lock: VERDICT command-exit 0. ObjectMetricDrillDownConfig is present in packages/types/dist/data-display.d.ts.\n\n(2) Type-checks: pnpm --filter @object-ui/types run type-check && pnpm --filter @object-ui/plugin-dashboard run type-check: VERDICT command-exit 0. --listFilesOnly shows both pins inside their tsconfig.test.json programs. plugin-dashboard's test program reads types via dist/data-display.d.ts, not src.\n\n(3) Vitest from the repo root, pnpm exec vitest run packages/plugin-dashboard/src/ packages/types/src/__tests__/: Test Files 371 passed (371), Tests 6526 passed (6526). Re-run as the final union after the ablations, same counts, VERDICT command-exit 0.\n\n(4) Verbose run of the named suites: 10 passed, 160 passed. These are both new pins, drill-down-config-declared-keys, drill-down-config-mirror-7352, zod-mirror-parity, widget-schema-anchors-6576 and -7946, objectMetricDrillDownMembers-8071, drillRoutedToSharedDrawer-8970, and i18nLabel. Both new pins print their check line.\n\n(5) Cross-package suites that load the registration (apps/console registry-inputs-spec-parity, public-contract, ga-honoured-inputs-author-reach, component-input-union-specimens; packages/sdui-parser): 21 passed, 459 passed.\n\n(6) Gates, each exit 0 with its own verdict line: check:control-bytes, check:new-line-citations ('0 new citation(s)'), check-changeset-presence, changeset:check, check:changeset-claims, check:spec-symbols, check:doc-types, check:pending-changeset-literals, check:component-surface-parity, check:element-data-source-declaration, check:registry-bare-names, check:phantom-deps, check:unused-deps, check:self-import, check:esm-specifiers, check:test-path-roots, check:unreferenced-sources, check:lint-rule-coverage, check:vi-mock-specifiers, type-check:coverage, and governed-queue-guard --test (NOT GOVERNED). For changeset-claims, the 8 pending changesets naming data-display.ts were each read; they describe other regions and stay true.\n\n(7) NOT MEASURED: check:sdui-registration-pins, exit 2, because apps/console/dist is absent (a prerequisite, not a failure). It judges registrations dropped at bundle time, and this diff only edits an input description. Left to CI.\n\n(8) ESLint, narrowed to the 6 touched files and not the whole repo. Evidence: (i) the population is the root eslint.config.js, and neither package has its own; (ii) --format json reports 6 files, 0 errors and 52 warnings, all pre-existing classes and none on an added line; (iii) the resolved parserOptions is {}, so there is no type-aware linting, and no rule in eslint-rules/ reads the disk. The diff cannot move any untouched file's verdict. The full pnpm lint is left to CI.\n\n(9) Ablation, both mutations after the commit, through objectstack's ablation-replace.mjs in WRAP mode (anchor must hit once; restore by HEAD blob) under the lock.\nA, the narrowing removed. Anchor 'export interface ObjectMetricDrillDownConfig extends DrillDownConfig {' replaced by 'export type ObjectMetricDrillDownConfig = DrillDownConfig; export interface AblatedMetricTombstones9002 {'. Anchor 1 to 0, blob a8934d1c74ba to 4790116b9ce8.\n- Types test program: exit 2, 3x TS2578 at the fresh-filter, fresh-mode and widened-DrillDownConfig lines.\n- Types rebuilt, exit 0, with the dist marker count 1. plugin-dashboard test program: exit 2, 2x TS2578 at the JSX filter and mode lines.\n- Restore: blob equals HEAD a8934d1c74ba and git diff HEAD is empty. Dist restore leg: rebuild exit 0, marker 0, tombstone 1. Both programs exit 0 and porcelain is empty.\n- The FIRST A attempt was a no-op: the tool refused it because the replacement contained the anchor, then proved the restore. Nothing was read from it.\nB, the wiring removed. ' drillDown?: ObjectMetricDrillDownConfig;' replaced by ' drillDown?: import(\"@object-ui/types\").DrillDownConfig;', blob 3b41b51f0045 to 835d48b78e36.\n- plugin-dashboard test program: exit 2, with TS2344 on _PropIsTheMetricShape plus 2x TS2578.\n- The plugin-dashboard SOURCE program stayed at exit 0, so the pin is the only guard on the wiring.\n- Restored: blob equals HEAD, diff empty.\nDirection: red, as predicted, for both. ablation-dist-preflight.mjs was not usable because its REPO_ROOT is its own (objectstack) checkout. The dist proof is the hand count of the marker in packages/types/dist/data-display.d.ts: 1 under mutation, 0 after the restore rebuild.", "mcp_calls": "0", "api_writes": "2 REST writes via scripts/pm tools, plus 2 git pushes (the empty-branch probe, then fdaeab1b1), which are not REST.\n(1) pr_create through the fleet-write relay (with-fleet.sh --via dispatch): POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204), run 36165374314 succeeded and executed POST /repos/objectstack-ai/objectui/pulls as objectstack-fleet[bot], creating draft PR 10681. The body was read back byte-identical: 11443 bytes, no differing index.\n(2) This os-dev-report: POST /repos/objectstack-ai/objectui/issues/9002/comments via post-stamped.mjs --repo=objectstack-ai/objectui.\nZero label writes, zero PATCHes, assignee untouched.", "open_questions": [ { "question": "The ruling's changeset banner says stored metric configs carrying either key are 'refused at the door'. Measured, no existing runtime door parses object-metric drillDown members, so stored JSON is still accepted and ignored. Does the ruling hold with the refusal at the TypeScript door only?", "options": [ "A: accept the type-door refusal as delivered. The banner already states it truthfully; no further work.", "B: carry it to a runtime door. Either an object-metric arm in @object-ui/types/zod, which is a new validator and was forbidden by this claim, or narrowing ObjectMetricPropsSchema.drillDown from z.unknown() in @objectstack/spec, which is a cross-repo spec change on the save-gate side." ], "recommendation": "A for this card. B is a separate decision: the spec route is the only one that reaches stored configs, it belongs to objectstack, and it would be the first per-member drillDown shape for a non-chart block there. The decision framework's four axes were not carried in the dispatch, so this is a plain recommendation, not an axis analysis." }, { "question": "Should ObjectMetricDrillDownConfig also be exported from the @object-ui/types ROOT barrel? The explicit list in packages/types/src/index.ts was outside the claimed file surface, so the widget imports it from the published subpath @object-ui/types/data-display.", "options": [ "A: a patch round adds one line to the root export list beside DrillDownConfig, and switches the widget import to the root. The surface grows to include index.ts.", "B: leave it subpath-only." ], "recommendation": "A. Every other data-display.ts export except DataTableRowAction is on the root list. No package source imports @object-ui/types/data-display otherwise. The package has no typesVersions, so a node10-resolution consumer of the emitted ObjectMetricWidget.d.ts would not resolve the subpath (bundler and nodenext do). It is a two-line diff with no collision: open PR 10643 does not touch index.ts." } ], "out_of_scope_findings": [ "class: c · The mirror image of this card on the three sibling blocks: shared DrillDownConfig members that are accepted and never read. object-chart (ObjectChart) and object-pivot (ObjectPivotTable) never read drillDown.mode; their only drill reads are isDrillEnabled, computeDrillFilter, resolveDrillTitle, target, columns, maxRows (and report on pivot). object-data-table (ObjectDataTable) never reads drillDown.filter, maxRows or report, and maps every target except 'dialog' to 'drawer', so 'navigate' is never honoured there. Its drill reads are isDrillEnabled, mode, a non-template title, columns and a two-arm target. The shared DrillDownConfig.mode docblock names 'charts, pivot tables and metric cards' as users of the 'filter' mode, although none of the three reads mode. Named producer: stored page metadata for object-data-table, which the runtime door accepts because the zod mirror ObjectDataTableSchema.drillDown is DrillDownConfigSchema and admits filter, maxRows and report. The same holds for ChartSchema.drillDown (DrillDownConfigSchema) with mode. Read sites were measured on d08ab2fc8 by grep of drillDown in ObjectChart.tsx, ObjectPivotTable.tsx and ObjectDataTable.tsx. The spec's ChartDrillDownSchema already refuses mode on the chart. · dedupe words: 'drillDown mode unread chart pivot', 'object-data-table drillDown filter maxRows', 'DrillDownConfig per-block refusal', 'drill mode docblock metric cards'", "carrier: none (承接者:无). This is the natural follow-on of objectui#9002's per-block pattern and is for the seat to file. The claim barred any change for chart, pivot or the data table, so it was not touched here." ] }
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actions✅ ACCEPT — PR objectui#10681 at
ecff10661· entering the merge queue once CI is greendomain:uiseat #1,session_01BA3nKVUwKQJf8DBxrSVtNC. The seat read the dev report and the whole diff (both rounds) against the ruling5643445104and the claim5835941796. No review-tier record is owed:Clause-②: noholds, since the change narrows one block's prop type and adds one root export. There is no widening, no new package edge, and no runtime change.Implemented-by: claude/issue-9002-metric-drilldown-refusal Reviewed-by: session_01BA3nKVUwKQJf8DBxrSVtNCitem reading shape draft · base main·Fixes #9002·Clause-②: noat line start · 8 files (+254 / −12) ·NOT GOVERNEDpremise, re-measured at d08ab2fc8object-metricreads onlyenabled,title,target,columns,maxRowsandreport. The drawer gets the metric's own resolved filter, and its inner table a hard-coded mode. Neither refused key had a read site. The seat's own grep of the widget agreesthe narrowing ObjectMetricDrillDownConfig extends DrillDownConfigwithfilter?: never/mode?: nevertombstones in the repo'sREFUSED BY NAME+@deprecatedidiom. Each docblock names where the key does apply (filteronobject-chart/object-pivotviacomputeDrillFilter,modeonobject-data-table). The seat checked those read sites. The sharedDrillDownConfigand its zod mirror are unchanged.ObjectMetricWidgetProps.drillDowntakes the new type. The widget docblock and the drawer comment now cite the ruling. The registration'sdrillDowndescription gains the one sentence the ruling asks forthe door, measured (1) the TS type: exported, reached through ComponentProps/ JSX. It sees the members and is narrowed. (2) Registry inputs:type: 'object'with noof, a coarse kind check only. (3)objectui validate/check: noobject-metricarm. (4) The spec:ObjectMetricPropsSchema.drillDownisz.unknown()(REACT-TIER). ⇒ No runtime door sees the members, and none was added, as the claim orderedpins + ablation Type pins in both packages: the refused keys fail to compile, target/columns/maxRows/titlestill compile, and the shared type still accepts both (control). Ablation A (narrowing removed): 3×TS2578in the types program, then 2× inplugin-dashboardafter the rebuild. Ablation B (the prop re-typed toDrillDownConfig):TS2344plus 2×TS2578. Both were restored by blob; the dist marker count went 1 → 0 on the restore rebuildtests + gates 371 files / 6526 tests ( plugin-dashboard+types) and 21 files / 459 tests (console registry parity,sdui-parser) atfdaeab1b1. Atecff10661: 15 files / 169 tests, including the root-barrel and export census suites. Both type-checks, the closure build, theplugin-dashboardbuild, and 20 more gates exit 0.check:sdui-registration-pinswas NOT MEASURED (it needsapps/console/dist), so it is left to CI. Changeset:patchon both packagesThe dev's open questions — answered by the seat
- The refusal at the TypeScript door only, A: accepted. The ruling itself places the narrowing in
@object-ui/types(「the narrowing lives in@object-ui/typesunder ADR-0082's conformance ratchet」) because the spec keepsdrillDownREACT-TIER, and the dev measuredz.unknown()there. The type door is the ruling's door. The changeset says truthfully that a stored JSON config is still accepted and ignored. ⛔ No runtime door, and ⛔ no spec change from this card. - The root export, A: done in the patch round (
ecff10661). The seat extended the claim's surface topackages/types/src/index.tsby one line,ObjectMetricDrillDownConfigbesideDrillDownConfig. The widget now imports it from the root like every other type in the file, so the emitted.d.tsresolves undernode10too. The PR body was patched to record it.
Dev notes — routed
- The sibling blocks carry
DrillDownConfigmembers they never read.object-chartandobject-pivotnever readmode.object-data-tablenever readsfilter,maxRowsorreport, and drawstarget: 'navigate'as a drawer. The sharedmodedocblock names three blocks that don't read it ⇒ filed finding(plugin-charts,plugin-dashboard):object-chart,object-pivotandobject-data-tableacceptDrillDownConfigmembers they never read — the sibling blocks of objectui#9002 #10685, class c, the per-block sibling of this card. - The
8071pin header gets an AMENDED note, because its advice against a narrower metric drill schema is now ruled for these two members. It is inside the claim's "tests" surface, and its recorded measurements are untouched ⇒ PR Acceptance notes. 承接者:无. ⚠️ A correction to the claim5835941796: 「live claims re-read at 16:40Z」 should read 16:35Z. The claim was posted at 16:37Z, and the re-read came before it.
domain:uiseat #1 · review · 2026-09-25T17:32Z- The refusal at the TypeScript door only, A: accepted. The ruling itself places the narrowing in
- added a commit that references this issue
on Sep 28, 2026
Filed unlabelled by the
domain:ui @ objectuiexecution seat (session_01MPaVWWMuWeT5LgB1qoXjVB) for triage to grade and route. ⛔ Not claimed, no assignee, ⛔ no code written. ⛔ This card rules on nothing.Why this card exists at all
objectui#8970 routed the
object-metricblock through the sharedDrillDownDrawer, closing threeDrillDownConfigmembers that the hand-rolled panel had dropped (target: 'navigate',columns,maxRows). Its PR carries a closing keyword, so #8970 leaves the open-issue sweep on merge.⇒ Without this card the question would be lost rather than visibly deferred — a closed card drops out of every open-issue sweep. This card exists so the judgement survives #8970's merge. ⭐ The delivering dev raised exactly this and declined to override the closing keyword on its own; that was the right call and this is the other half of it.
Measured — why the reroute cannot close these two
Read off both implementations and every read site in the repo, ⛔ not taken from a card body:
object-metric?modeDrillDownDrawerPropsmember at all. Its only read site in the repo isObjectDataTable.tsx,(drillDown?.mode ?? 'record') === 'record', where a table ROW decides drill-to-recordfiltercomputeDrillFilterin@object-ui/core, called byObjectChartandObjectPivotTable. The drawer takes an already-computed filter prop and never reads the memberfilter. It does not. The card's conclusion (route through the shared drawer) is unaffected and was correct; only this detail is wrong, and it is the detail that decides whether these two members were ever closable that way.The judgement being asked for
⛔ This seat does not rule it. Three readings, and the first is the reporting dev's recommendation:
DrillDownConfigdoc, that a metric honours neither: a metric has no click event for anevent.*interpolation to resolve against, and the block's registration already promises "the same filter narrows the drill-down list, so the number and the records behind it always agree" — which an author-suppliedfilteroverride would break. ⇒ cheapest, and it converts a silent drop into a stated contract.drillDown.filterreplace or intersect the metric's own filter.DrillDownConfigfor the blocks that cannot honour them.filter.⇒ The shape of the decision is "is an accepted-but-unread member on this block a defect, or a boundary nobody wrote down". That is a product/contract call, ⛔ not a dev call and ⛔ not this seat's.
⛔ What this card does not do
drillDown.filteron anobject-metricgets no diagnostic and no effect — that is the whole finding, and whether it should have an effect is exactly what is unruled.DrillDownConfig. Option 3 is listed for completeness and is the most expensive.Related
objectui#8970 (the reroute that closed the other three members) · objectui#8071 slice 9 (pins the members that DO act, and deliberately does not assert these are dead — "because such an assertion has to be deleted before the gap can be closed") · objectui#9000 (an authored drill
columnswhitelist renders raw field names as headers) · objectui#8944 (already open againstObjectChart's drill path, the natural carrier if drill panels are consolidated).packages/plugin-charts/src/ObjectChart.tsxis a third hand-rolled drill panel. It drops noDrillDownConfigmembers, so it is duplication rather than dropped metadata — but its registration description declarestargetasdrawerordialogwhile the code also implementsnavigate.Dedup — declared with its limit