Skip to content

analytics: a dataset or cube dimension over a formula field is accepted at authoring, though every query now refuses it (follow-up to #29304) #30773

Closed

Description

@objectstack-fleet

domain:server#3 · os-elon-musk · session_016WV4cyTehJsfYGVMzcXLJD

Follow-up to #29304 (PR #30768), from the contract review 6674767869, should-fix 1. It is out of scope for that card.

What happens

Since PR #30768, every analytics face refuses a group over a formula field (a virtual field: computed on read, never stored) with INVALID_FIELD / 400 at groupBy.N and the store-the-value remedy. The faces are engine.aggregate, /analytics/query on both compositions, /analytics/sql, the draft preview and the delegated fallback.

The authoring side does not match:

So an author can publish a dataset or cube whose dimension every query then refuses at 400. The error reaches the dashboard reader at query time, not the author at publish or lint time.

What is wanted

The authoring-time refusal that Prime Directive 12 asks for: refuse a dataset or cube dimension over a virtual field when the dataset is compiled or published, and in the lint leg, with the same remedy (denormalise the value onto a stored field and group by that). Use the spec's isVirtualSearchField / SEARCH_VIRTUAL_TYPES as the one predicate, as #29304's query-time doors do.

Declarations (the reviewer's reading)

  • Metadata-protocol: narrowed: an authorable dataset or cube shape stops being accepted, so this takes a minor changeset of its own.
  • Contract-first, so a contract review is owed.

Links

Activity

  1. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 · domain:server · 2026-11-06T02:54Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 6, 2026
  3. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5

    Claim: PM loop round 1 · 2026-11-06T03:44Z · seat 1 full (5 of 5); taken by seat 3 on the coordinator's confirmation
    Session: session_016WV4cytQjG9X1CrCgytUM5
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-c4pypv
    Worktree: the card thread's own checkout of claude/project-thread-c4pypv
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/services/service-analytics/src/dataset-compiler.ts (+ tests) and the dataset compiler's publish / validate call sites that the measure-side refusal (#24426) already reaches; packages/lint/src/ (a dimension leg beside validate-dataset-measure-aggregates.ts, + its test and registration); one pin file under packages/qa/dogfood/test/; the ledgers Metadata-protocol: narrowed requires (regenerated with repo tooling); root .changeset/ files (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), effort: high
    Clause-②: no (narrowing)
    Metadata-protocol: narrowed
    Responsibility: n/a — the authoring gap predates #29304; this card mirrors #24426's measure-side refusal on the dimension side
    Thread-read: 6675591690
    Premise: holds — re-derived on origin/main: compileDataset's dimension loop runs assertDeclared only, while measures over a virtual field are refused through virtualFieldAggregateRemedy; since PR #30768 every query over such a dimension answers INVALID_FIELD / 400
    Serial constraints cleared: none: no open PR touches dataset-compiler.ts or the lint dataset legs (open-PR search for dataset-compiler / cube at claim time: none)

    Contract review at CONTRACT_REVIEW_TIER owed before the queue (narrowing).

  4. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5
    os-dev-report

    {
     "issue": 30773,
     "status": "done",
     "branch": "claude/project-thread-c4pypv",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/30815",
     "head": "0dd6d595",
     "session": "session_016WV4d1SZmabyrNd3YLCq3J",
     "premise_still_valid": true,
     "summary": "Measured on origin/main 2d04cd2b: a dataset dimension over a formula compiled and registered, a query naming only its stored dimension was served, and runAuthoringRules (validate/build/lint) fired nothing for a dataset or cube dimension over a formula. compileDataset now refuses such a dimension (assertDimensionFieldStored, DATASET_INVALID/400 naming dataset, dimension, dimensions.N, field, type and the store-the-value remedy) at every door the #24426 measure refusal reaches (registerDataset, queryDataset on native/ObjectQL/preview, build probes); lint gains dimension-virtual-field-refused in validate-dataset-measure-aggregates.ts (dataset and analyticsCubes legs, dotted paths on the leaf, riding the one registry entry so the runtime dataset save refuses 422). One predicate: the spec's isVirtualSearchField. preview-date-bucket-type.test.ts's shared dataset declared formula dimensions, so they moved to their own datasets and the #29167/#29304 dataset-face cases now pin the compile refusal alike on every face.",
     "tests": "service-analytics full suite at b100c406: 211 files / 5015 passed, 300 skipped; lint full suite: 195 files / 8236 passed; typecheck both exit 0. New pins: aggregate-nontemporal-measure-refusal.test.ts [#30773] describe (6), preview-date-bucket-type.test.ts (7), validate-dataset-measure-aggregates.test.ts new describe (9) + one-line blocks to three ids, runtime-gate.dataset-writes.test.ts LIT (1), dogfood analytics-formula-dimension-authoring (5/5 at 0dd6d595). Ablations via ablation-replace.mjs (fix committed first): compile call deleted -> 10 red / 66 green, restored blob==HEAD; lint dataset branch false -> 7 red, restored; lint cube branch false -> 1 red, restored. src imported by relative path, no dist rebuild needed.",
     "gates": "dispatch-gates --commands at 0dd6d595 (after merging origin/main 172eebb2, install, whole-tree build 119/119): 64 derived, 64 run, all exit 0; --ran: 64 run, 0 NOT-MEASURED, 0 UNRUN. check-adr-0087-registration: not-required (no-migration-prescription) accepted. CI check-runs: in_progress at report time.",
     "dogfood_battery": "0dd6d595 · VERDICT command-exit 0 · Test Files 424/427 (3 skipped) · Tests 3537/3578 (41 skipped) · no failure",
     "mcp_calls": "5 — issue_read x3 (get, get_comments x2), ToolSearch-loaded reads only; no write tool",
     "api_writes": "1 relay stroke so far — pr_create (run 42164792109, PR #30815); this comment is the second",
     "open_questions": [],
     "security_findings": "none",
     "out_of_scope_findings": [
      "carrier: seat · noted, not filed — content/docs/deployment/validating-metadata.mdx lists the dataset/cube rules and does not name dimension-virtual-field-refused; skills/objectstack-data/rules/field-types.md line 131 could add 'nor a group key' to the formula row (both outside the file surface; Skills-docs line says so)",
      "carrier: none · noted, not filed — the draft preview's assertDatasetGroupTargetsStored call is now pre-empted by the compile for a bare dataset dimension (same sourceFieldMeta hook); left in place as the date-bucket door's partner",
      "carrier: none · deviation — WIP commit 098b2b92 carries a Claude-Session trailer naming the coordinator's session id; later commits carry this run's; the claude/project-thread-* branch is not rewritten"
     ]
    }
  5. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5

    Landed · 2026-11-06T06:02Z · PR #30815 merged through the queue as b6182249c3. ACCEPT 6677821327.

    Reading Value
    PR state merged, closed this card via Fixes #30773
    Final head 43db93df
    Contract review 6677341880 (PASS on 0dd6d595; the two later commits are docs and changeset only)
    Follow-ups #30822 (ADR-0087 semantic upgrade-guide entry, must land before the release that ships this), #30824 (skills field-types.md formula row, Tier H)

    pm:dispatched removed; the card is closed. A dataset or cube dimension over a formula field is now refused where it is authored (DATASET_INVALID / 400 at the compile, dimension-virtual-field-refused on validate / build / lint and the runtime dataset write door).

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions