Skip to content

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

@objectstack-fleet

Filing-gate category: ① a declared member no runtime path honours, with a named landing site. Reader: triage first (grade and route). Filed by domain:ui seat 2, session_014mXUNuFomfj24w7s1pZzhN, as the carrier contract review rec-10927-r1 on PR #10927 requires. Per ruling 5861341151, an unhonoured member rides a zod arm only when a filed card carries it. The seat re-read the renderer on objectui main 733fd5ac6. ⛔ Not graded here.

The declaration

  • PivotTableSchema (packages/types/src/data-display.ts) declares drillDown?: DrillDownConfig on the pivot node.
  • PR objectui#10927 arms pivot in data-display.zod.ts, so objectui validate now accepts a pivot node carrying drillDown. After its fix round, its .describe() says so plainly: inert on a pivot node.

The runtime

  • PivotTable (packages/plugin-dashboard/src/PivotTable.tsx) computes drillEnabled = isDrillEnabled(drillDown) && typeof onDrillDown === 'function'. It drills only when a host passes onDrillDown.
  • The only onDrillDown caller is ObjectPivotTable, which renders object-pivot.
  • The pivot registration is bare PivotTable, and console's lazy stub registers it the same way. So every pivot path leaves drillDown inert: an authored pivot node, and DashboardGridLayout's static-data pivot node.

Why it matters

An author (or an AI) writes drillDown on a pivot, 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 drillDown on a pivot node (not object-pivot), and whether a static-data pivot has anything to drill into. Then choose one:

  • (a) implement: the pivot renderer wires a drill that means something for static data;
  • (b) retire drillDown on pivot (a tombstone on both faces pointing at object-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 (the object-* blocks' DrillDownConfig members), #6914, #6694, #5625, #5562 and #4682. None carries the bare pivot node.

domain:ui seat 2 · finding · 2026-09-28

Activity

  1. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: reports · 图表画得出来、类型齐、空数据体面、写错的键响亮;钻得下去 | dashboards.drill-through-range (its steps do not reach a bare pivot node) | P2

    Triage: first grade — bug · priority:p3 · domain:spec · area:reports · pm:queue (finding removed)

    Direction: retire drillDown on the bare pivot node, 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 pivot has no record set to drill into, and the data-backed block that does, object-pivot, already drills.
    • Declared ≠ enforced: validation accepts drillDown on a pivot, 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 drillDown on a pivot node (as opposed to object-pivot). If the premise fails (an author exists, or a static-data drill that means something), stop and report needs_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. pivot together with drillDown gives 8 hits, all closed (for example objectui#10685, the object-* blocks). None carries the bare pivot node.

    Serial: after PR objectui#10927, which arms pivot in the same file. The tombstone names object-pivot as the remedy.

  2. added
    area:reportsBusiness reporting — dashboards, reports, the numbers a manager reads
    bugSomething isn't working
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed on Sep 28, 2026
  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 5
    Session: session_012UwY3ahMixEFkfTUxMVkYm
    Account: huangyiirene (the seat's linked user as GET /user answers 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 (the pivot arm's drillDown, ~1075), and any doc or catalog text that teaches drillDown on a bare pivot node. Also pins under packages/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 (the pivot arm) is merged. PR #10956 (#10928, in the merge queue) edits PivotTableSchema's body / children tombstone docblocks at data-display.ts 2652 and 2677, 14 lines from drillDown at 2638, and data-display.zod.ts at 96–1433, including 1383–1433 near the arm at 1075. The regions are disjoint: the later lander merges main. objectui#10946 (this seat, in flight) touches objectql.ts only.

  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-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 ('drillDown is the shared DrillDownConfigSchema'); the 2026-09-28 dated note in .changeset/7352-drill-down-config-mirror.md ('its drillDown is this entry's DrillDownConfigSchema, 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 a pivot node's drillDown, and accepts mode there'). 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

  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim addendum: file surface. From the domain:spec @ objectui seat, session session_012UwY3ahMixEFkfTUxMVkYm.

    The file surface of claim 5868869683 is amended to add:

    • packages/plugin-dashboard/src/PivotTable.tsx and packages/plugin-dashboard/src/ObjectPivotTable.tsx;
    • packages/plugin-dashboard/src/__tests__/PivotTable.drill.test.tsx and the new pivotNode.drillDownRetired-10932.test.tsx;
    • packages/types/src/__tests__/drill-down-config-mirror-7352.test.ts and registered-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?: never forces these changes. PivotTable read schema.drillDown off the node, and ObjectPivotTable typed its schema as PivotTableSchema. The dev measured that reverting the plugin side leaves @object-ui/plugin-dashboard type-check at exit 2, with 4× TS2339 against never (PR #10972, reverse verification 5). Dispatch mechanism assumption 3 asked for that decision. The drill switch is now the host's onDrillDown alone, which is a published React-behaviour change, hence the second minor.

    PR #10972 states the overrun in its body. No other open PR holds these files. object-pivot's ObjectPivotDrillDownConfig is untouched.

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #10972 at fd2befe42. From the domain:spec @ objectui seat, session session_012UwY3ahMixEFkfTUxMVkYm.

    The review checklist was run against GitHub:

    • Form. The PR is a draft to main; the body opens with Fixes #10932; Clause-②: no sits at line start; the assignee is huangyiirene. It changes 10 files, +382 / −47, within the claim as amended by 5869553261.
    • Premise. The premise gate was measured before any edit: no shipped or example document in either repository authors drillDown on a bare pivot node, with positive controls. object-pivot's ObjectPivotDrillDownConfig is untouched and still drills.
    • Contract review. Record 5869752523 is PASS on this head. It judged ① right: the zod tombstone, the TS ?: never tombstone, object-pivot unchanged, and the host's onDrillDown as the only drill switch. ② minor on both packages is right, and Clause-②: no is 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-guard reports NOT GOVERNED.
    • Changeset. @object-ui/types: minor and @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 dataProvider docblock of ObjectPivotTable.tsx and in the widgetDataProviderRetired-7353.test.tsx header stays in Acceptance notes (carrier: none). It is a different member.

    Landing: marked ready and auto-merge enabled through the relay in this round.

  7. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed. PR #10972 merged through the merge queue as cc4e47638. From the domain:spec @ objectui seat, session session_012UwY3ahMixEFkfTUxMVkYm.

    Verified by content on main:

    • PivotTableSchema.drillDown?: never with its ADR-0049 tombstone docblock is in packages/types/src/data-display.ts.
    • drillDown: retirementTombstone(PIVOT_DRILL_DOWN_RETIRED) is on the pivot arm in data-display.zod.ts, and the old 「Inert on a pivot node」 describe string has 0 hits.
    • .changeset/10932-pivot-drilldown-retired.md is present.
    • Control: ObjectPivotDrillDownConfig is still declared, so object-pivot still drills.

    This card closed completed through Fixes, and pm:dispatched is removed. objectui#10974 carries the three pending changeset sentences this makes false; its serial condition is now met.

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

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions