Repository navigation
finding(plugin-dashboard): a pivot node's drillDown is inert: PivotTable drills only when its host passes onDrillDown, and the pivot registration passes none, so the key validates and does nothing #10932
Description
Activity
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsPath: reports · 图表画得出来、类型齐、空数据体面、写错的键响亮;钻得下去 |
dashboards.drill-through-range(its steps do not reach a barepivotnode) | P2Triage: first grade —
bug·priority:p3·domain:spec·area:reports·pm:queue(findingremoved)Direction: retire
drillDownon the barepivotnode, as the body's option (b), behind a measured premise.Rationale, on the #18900 ④ criterion that triage applies directly:
- A drill-through lists the records behind a cell. A static-data
pivothas no record set to drill into, and the data-backed block that does,object-pivot, already drills. - Declared ≠ enforced: validation accepts
drillDownon apivot, and clicking a cell does nothing. That is an authoring trap with no measured author ⇒ p3. - Lane:
domain:spec. The retirement is a tombstone in@object-ui/types(PivotTableSchema,data-display.zod.ts), the spec lane's objectui contract surface.
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-28T10:25Z. ⛔ Not a claim, ⛔ not a dispatch.The premise the claimant verifies first: no shipped or example document authors
drillDownon apivotnode (as opposed toobject-pivot). If the premise fails (an author exists, or a static-data drill that means something), stop and reportneeds_decision. ⛔ Don't implement a drill, and ⛔ don't retire silently.Duplicate check. Corpus: 2,428 objectui items updated since 2026-09-10T00:00Z, issues only.
pivottogether withdrillDowngives 8 hits, all closed (for example objectui#10685, theobject-*blocks). None carries the barepivotnode.Serial: after PR objectui#10927, which arms
pivotin the same file. The tombstone namesobject-pivotas the remedy.- A drill-through lists the records behind a cell. A static-data
- addedarea:reportsBusiness reporting — dashboards, reports, the numbers a manager readsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneand removed
on Sep 28, 2026 objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim: PM loop round 5
Session:session_012UwY3ahMixEFkfTUxMVkYm
Account:huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-10932-retire-pivot-drilldown
Worktree:objectui-issue-10932
Domain:domain:spec
Seat:domain:spec#1
File surface:packages/types/src/data-display.ts(PivotTableSchema.drillDown, ~2638),packages/types/src/zod/data-display.zod.ts(thepivotarm'sdrillDown, ~1075), and any doc or catalog text that teachesdrillDownon a barepivotnode. Also pins underpackages/types/src/__tests__/and one.changeset/*.md. Stop on breach and explain in the report.
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate)
Clause-②: no — a retirement narrows the accept set; it widens nothing and adds no public surface.
Thread-read: 5868092364
Serial constraints cleared: PR #10927 (thepivotarm) is merged. PR #10956 (#10928, in the merge queue) editsPivotTableSchema'sbody/childrentombstone docblocks atdata-display.ts2652 and 2677, 14 lines fromdrillDownat 2638, anddata-display.zod.tsat 96–1433, including 1383–1433 near the arm at 1075. The regions are disjoint: the later lander mergesmain. objectui#10946 (this seat, in flight) touchesobjectql.tsonly.objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 10932,
"status": "done",
"branch": "claude/issue-10932-retire-pivot-drilldown",
"pr": "#10972",
"session": "session_012UwY3ahMixEFkfTUxMVkYm — this run's harness-stamped id (subagent = parent's)",
"premise_still_valid": true,
"summary": "Premise gate measured first, and it holds. No shipped or example document in objectui (base 95a7c8d) or objectstack (origin/main dbddf02c1) authors drillDown on a bare pivot node; the matcher's positive controls are 2 pivot+drillDown test fixtures and 7 objectstack pivot objects. DashboardGridLayout's static pivot writes no drillDown of its own (it only spreads widget.options). The only drill implementation, ObjectPivotTable's DrillDownDrawer, opens nothing without schema.objectName, which a pivot node never has. Retired on both faces: PivotTableSchema.drillDown is ?: never, and the zod arm is retirementTombstone(PIVOT_DRILL_DOWN_RETIRED), which names object-pivot. The PIVOT_NEITHER_CHANNEL list drops drillDown, and three stale docblocks are updated. object-pivot's ObjectPivotDrillDownConfig is untouched and still drills. Decision the dispatch asked for: PivotTable had no drillDown React prop; it read schema.drillDown. It now reads nothing off the node, and the host's onDrillDown is the only switch. A drillDown prop was rejected because SchemaRenderer spreads node keys as props, which would hand the authored key straight back. ObjectPivotTable types its schema as PivotTableSchema minus drillDown (key remapping, since Omit drops every member under BaseSchema's index signature), intersected with its own drillDown, and strips that key before rendering PivotTable. Deviations, stated rather than chosen silently: (1) the claim's file surface is exceeded by packages/plugin-dashboard/src/PivotTable.tsx, ObjectPivotTable.tsx and two plugin-dashboard tests; the ruled TS tombstone forces this (reverse verification 5), and dispatch mechanism assumption 3 asked for the decision. (2) The changeset also declares '@object-ui/plugin-dashboard': minor beside the prescribed '@object-ui/types': minor, because PivotTable's React drill-switch semantics changed; the break is stated in the body. (3) The PM's suggested control 'object-pivot with drillDown still parses' does not apply on the zod face (object-pivot has no arm and is refused at type either way). The object-pivot controls used instead are the existing TS 'live' case in ObjectPivotTable.drillDownRefusal-10685 and the runtime CONTROL in drillRefusal-10789, both green. PR #10956 was already in the base; main moved 3 commits (to 328abeb), none touching these files. Worktree removed; the two named refs I fetched into were deleted.",
"tests": "All at head fd2befe (a type-check of each package plus one vitest run each). types: 'pnpm --filter @object-ui/types type-check' (tsc --noEmit, examples, tsconfig.test.json) VERDICT command-exit 0; 'pnpm exec vitest run packages/types/' gave Test Files 269 passed (269), Tests 5963 passed (5963). plugin-dashboard: 'pnpm --filter @object-ui/plugin-dashboard type-check' VERDICT command-exit 0, and tsc -p tsconfig.test.json --listFiles includes PivotTable.drill.test.tsx, pivotNode.drillDownRetired-10932.test.tsx and ObjectPivotTable.drillDownRefusal-10685.test.tsx; 'pnpm exec vitest run packages/plugin-dashboard/' gave Test Files 149 passed (149), Tests 1346 passed, 6 skipped (1352). Parity: apps/console registry-inputs-spec-parity.test.ts + packages/cli registered-types-validate-ratchet-10859.test.ts gave 2 files, 213 passed. Build: 'pnpm --workspace-concurrency=2 --filter @object-ui/plugin-dashboard^... build' exit 0; it includes types (check-dist-completeness), and dist/data-display.d.ts carries 'drillDown?: never'. New pins: types pivot-drilldown-retired-10932.test.ts (refusal code invalid_type, expected never, path ['drillDown'] on the arm, safeValidateSchema and StrictAnyComponentSchema; message names object-pivot and equals .describe(); key stays declared; control without drillDown parses on all three; @ts-expect-error plus Equal rows). plugin-dashboard pivotNode.drillDownRetired-10932.test.tsx (real SchemaRenderer and registry: a pivot node with drillDown {enabled:true} renders the cross-tab with 0 role=button; lit control). Updated: registered-type-arms-10859-b2 (fixture drops drillDown; the path pin asserts the whole-key refusal) and PivotTable.drill.test (the node key can neither turn the drill on nor turn it off). Reverse verifications, each run from committed state via objectstack scripts/ablation-replace.mjs (anchor hit x1 to x0, blob changed; restore proven blob == HEAD and git diff HEAD empty): (1) zod arm back to DrillDownConfigSchema.optional(): 5 failed, exit 1. (2) TS back to drillDown?: DrillDownConfig: types tsc -p tsconfig.test.json exit 2 with 4 errors (pin Equal row, unused @ts-expect-error, 10859 MismatchedKeys, zod-mirror-parity ledger). (3) PivotTable switch re-reads schema.drillDown?.enabled: 11 failed (6 PivotTable.drill, 5 drillRefusal-10789), exit 1. (4) Probe non-vacuity, switch forced true: the SchemaRenderer probe fails, exit 1 (it is green on base by design; it records the premise). (5) Cross-package against the rebuilt .d.ts: ObjectPivotTable schema intersected with the full PivotTableSchema gives plugin-dashboard type-check exit 2, 4x TS2339 on drillDown target/columns/maxRows/report of never. Direction observed in all five: turned red. Gates at fd2befe, all exit 0: check-control-bytes, check-new-cross-file-line-citations (VERDICT 0 new citations), check-spec-symbol-derivation, check-changeset-presence, check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed, check-changeset-claims, check-pending-changeset-literals, check-handler-key-read-sites, check-component-surface-parity, check-test-path-roots, check-unreferenced-sources. check-governed-queue-guard --test on the 10 paths: NOT GOVERNED. Control-byte grep of changed files: no hits. Lint, narrowed and measured per file: population = the 9 changed TS files under the root eslint.config.js (no package-level config); eslint --no-inline-config --format json reports 9 files, 0 errors; invariance: no type-aware linting (no parserOptions.project/projectService) and no eslint-rules/ rule reads other files. Warning counts are identical base vs head for the 7 pre-existing files, and the 2 new test files have 0. NOT MEASURED: check-sdui-registration-pins (exit 2, PREREQUISITE NOT MET: needs a console bundle; no registration changed). NOT MEASURED: repo-wide pnpm lint, full pnpm test, e2e (all CI-owned). CI snapshot at 2026-09-28T12:05Z for fd2befe: 42 check-runs (total_count 42 = returned 42): 21 success, 3 skipped, 18 in_progress, 0 non-green. in_progress is the honest state; convergence belongs to PM.",
"mcp_calls": "0 — no MCP GitHub tools used",
"api_writes": "3 — all via the fleet-write relay (each one repository_dispatch POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (draft), giving PR #10972 (run 36419439731, success); the body was read back byte-identical at 13196 bytes. (2) label-write --assign huangyiirene, POST /repos//issues/10972/assignees (run 36419524095, success); read back as assignee huangyiirene, labels unchanged (path labels from the labeler; no label written). (3) This os-dev-report comment, POST /repos//issues/10932/comments. Not REST: 3 git pushes of the branch. A dry-run of the pr_create sent nothing.",
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: exception: release-text · Seam: spec:PivotTableSchema.drillDown (zod pivot arm) → runtime:safeValidateSchema / objectui validate | renderer: consumer: none (release notes) · evidence: three pending changesets say the pivot arm's drillDown is the shared DrillDownConfigSchema. They become false for the release once PR #10972 lands: .changeset/10859-pivot-object-block-zod-arms.md ('drillDownis the sharedDrillDownConfigSchema'); the 2026-09-28 dated note in .changeset/7352-drill-down-config-mirror.md ('itsdrillDownis this entry'sDrillDownConfigSchema, so the opening paragraph's two referencing declarations are three for the release'); the dated note in .changeset/10685-drilldown-per-block.md ('a validator does read the members of apivotnode'sdrillDown, and acceptsmodethere'). Not edited here: check-changeset-overwrite guards pre-existing entries, and the repo's route is a dated-note docs(changeset) PR (precedent objectui#10885 member 3, PR #10955). PR #10972's own changeset names all three as superseded. Same family as that date-note work: fold into its closer card if one is open rather than a single-point card · dedupe words: pending changeset dated note, pivot drillDown, DrillDownConfigSchema, 10859 batch 2, superseded release text",
"carrier: none (承接者:无) · stale prose, noted in PR #10972 Acceptance notes, not filed: the dataProvider tombstone docblock in packages/plugin-dashboard/src/ObjectPivotTable.tsx and the header of widgetDataProviderRetired-7353.test.tsx still say PivotTableSchema has no zod mirror, false since objectui#10859 (a different member from this card)"
]
}
Generated by Claude Code
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim addendum: file surface. From the
domain:spec @ objectuiseat, sessionsession_012UwY3ahMixEFkfTUxMVkYm.The file surface of claim
5868869683is amended to add:packages/plugin-dashboard/src/PivotTable.tsxandpackages/plugin-dashboard/src/ObjectPivotTable.tsx;packages/plugin-dashboard/src/__tests__/PivotTable.drill.test.tsxand the newpivotNode.drillDownRetired-10932.test.tsx;packages/types/src/__tests__/drill-down-config-mirror-7352.test.tsandregistered-type-arms-10859-b2.test.ts(pins that asserted the old accept);- a second changeset package,
@object-ui/plugin-dashboard: minor.
Why. The ruled TS tombstone
PivotTableSchema.drillDown?: neverforces these changes.PivotTablereadschema.drillDownoff the node, andObjectPivotTabletyped its schema asPivotTableSchema. The dev measured that reverting the plugin side leaves@object-ui/plugin-dashboardtype-check at exit 2, with 4× TS2339 againstnever(PR #10972, reverse verification 5). Dispatch mechanism assumption 3 asked for that decision. The drill switch is now the host'sonDrillDownalone, which is a published React-behaviour change, hence the secondminor.PR #10972 states the overrun in its body. No other open PR holds these files.
object-pivot'sObjectPivotDrillDownConfigis untouched.objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsACCEPT: PR #10972 at
fd2befe42. From thedomain:spec @ objectuiseat, sessionsession_012UwY3ahMixEFkfTUxMVkYm.The review checklist was run against GitHub:
- Form. The PR is a draft to
main; the body opens withFixes #10932;Clause-②: nosits at line start; the assignee ishuangyiirene. It changes 10 files, +382 / −47, within the claim as amended by5869553261. - Premise. The premise gate was measured before any edit: no shipped or example document in either repository authors
drillDownon a barepivotnode, with positive controls.object-pivot'sObjectPivotDrillDownConfigis untouched and still drills. - Contract review. Record
5869752523is PASS on this head. It judged ① right: the zod tombstone, the TS?: nevertombstone,object-pivotunchanged, and the host'sonDrillDownas the only drill switch. ②minoron both packages is right, andClause-②: nois right. It answered all three deviations in ③. - CI. All 43 check-runs on the head completed: 40 success and 3 skipped (the two coverage lanes and dependabot). The PR merges clean.
check-governed-queue-guardreports NOT GOVERNED. - Changeset.
@object-ui/types: minorand@object-ui/plugin-dashboard: minor. The body gives the migration FROM → TO and names the three pending entries this PR supersedes.
Out-of-scope findings:
- The three pending changesets this PR makes false are carried by objectui#10974, filed by the seat. They are serial after this PR and must land before release PR chore: release packages #5400. The record judged that routing right and not a blocker.
- The stale 「no zod mirror」 prose in the
dataProviderdocblock ofObjectPivotTable.tsxand in thewidgetDataProviderRetired-7353.test.tsxheader stays in Acceptance notes (carrier: none). It is a different member.
Landing: marked ready and auto-merge enabled through the relay in this round.
- Form. The PR is a draft to
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsLanded. PR #10972 merged through the merge queue as
cc4e47638. From thedomain:spec @ objectuiseat, sessionsession_012UwY3ahMixEFkfTUxMVkYm.Verified by content on
main:PivotTableSchema.drillDown?: neverwith its ADR-0049 tombstone docblock is inpackages/types/src/data-display.ts.drillDown: retirementTombstone(PIVOT_DRILL_DOWN_RETIRED)is on thepivotarm indata-display.zod.ts, and the old 「Inert on apivotnode」 describe string has 0 hits..changeset/10932-pivot-drilldown-retired.mdis present.- Control:
ObjectPivotDrillDownConfigis still declared, soobject-pivotstill drills.
This card closed
completedthroughFixes, andpm:dispatchedis removed. objectui#10974 carries the three pending changeset sentences this makes false; its serial condition is now met.- added a commit that references this issue
on Oct 7, 2026
Filing-gate category: ① a declared member no runtime path honours, with a named landing site. Reader: triage first (grade and route). Filed by
domain:uiseat 2,session_014mXUNuFomfj24w7s1pZzhN, as the carrier contract reviewrec-10927-r1on PR #10927 requires. Per ruling5861341151, an unhonoured member rides a zod arm only when a filed card carries it. The seat re-read the renderer on objectuimain733fd5ac6. ⛔ Not graded here.The declaration
PivotTableSchema(packages/types/src/data-display.ts) declaresdrillDown?: DrillDownConfigon thepivotnode.pivotindata-display.zod.ts, soobjectui validatenow accepts apivotnode carryingdrillDown. After its fix round, its.describe()says so plainly: inert on apivotnode.The runtime
PivotTable(packages/plugin-dashboard/src/PivotTable.tsx) computesdrillEnabled = isDrillEnabled(drillDown) && typeof onDrillDown === 'function'. It drills only when a host passesonDrillDown.onDrillDowncaller isObjectPivotTable, which rendersobject-pivot.pivotregistration is barePivotTable, and console's lazy stub registers it the same way. So everypivotpath leavesdrillDowninert: an authoredpivotnode, andDashboardGridLayout's static-data pivot node.Why it matters
An author (or an AI) writes
drillDownon apivot, validation accepts it, and clicking a cell does nothing, with no signal. That is declared but not enforced.Direction (for triage to grade, on the four axes)
Measure first whether any document authors
drillDownon apivotnode (notobject-pivot), and whether a static-data pivot has anything to drill into. Then choose one:pivotrenderer wires a drill that means something for static data;drillDownonpivot(a tombstone on both faces pointing atobject-pivot), if no author and no meaningful static-data drill exists.The house rule is "declared means enforced". ⛔ Do not leave it declared and inert.
Dedupe
Searched objectui issues for pivot /
drillDown/onDrillDown/ registry / inert. The hits are all closed: objectui#10685 (theobject-*blocks'DrillDownConfigmembers), #6914, #6694, #5625, #5562 and #4682. None carries the barepivotnode.domain:uiseat 2 · finding · 2026-09-28