Repository navigation
finding(plugin-dashboard,core): an authored object-metric with a structured groupBy and a rule-list filter validates, then draws an UnloweredAggregateWhereError instead of its number #11526
Description
Activity
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsTriage: first grade —
bug·priority:p2·domain:ui·area:reports·pm:queue. The authored rule list is lowered where the metric's query is builtTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-03T02:00Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2. A node the validator accepts draws an error instead of its number.
object-metricwith a rule-listfilteris live:objectstack-ai/hotcrmsrc/sales/pages/home.page.ts;- objectstack's
app-showcasemy-work.page.ts.
Adding a structured
groupByto one of those tiles turns it into this error.Routing:
packages/plugin-dashboard/src/ObjectMetricWidget.tsxbuilds the query, sodomain:ui. The spec's condition list is the bag's declared dialect, so there is no spec change.Ruling: lower at the producer, not at the adapter.
ObjectMetricWidgetlowers the authored rule list to the filter dialect before it callsobjectAggregateSpecQuery. It uses the lowering the legacy aggregate wire already applies to the same rule list (the string-groupBycontrol, which draws the number). The claim names that function. ⛔ Not a second lowering.- The adapter's
UnloweredAggregateWhereErrorstays. It is the right refusal for a caller that skipped the lowering. - ⛔ Do not narrow the bag to hide the gap.
Pins:
- structured
groupBywith a rule-listfilter, which must draw the number; - the string-
groupByand flat-filter controls.
Not blocked by objectui#11525. That decision is about the dataset-less inline
provider: 'object'widget path. This card is the authored bag node, and its dialect is declared either way.findingcomes off in this act.
Generated by Claude Code
- addedarea:reportsBusiness reporting — dashboards, reports, the numbers a manager readsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingSomething isn't workingdomain: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 seatand removed
on Oct 3, 2026 objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_01YLg8XqWGJ785fwQ5v4pH37
Account:os-elon-musk(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-11526-object-metric-rule-filter-lowering
Worktree:objectui-issue-11526
Domain:domain:ui
Seat:domain:ui#1
File surface:packages/plugin-dashboard/src/ObjectMetricWidget.tsx: the authored rule-listfilterlowered beforeobjectAggregateSpecQuery, with the lowering the legacy aggregate wire already applies;- its tests under
packages/plugin-dashboard/src/(the structured-groupBy+ rule-list pin, and the string-groupByand flat-filter controls); - only if that existing lowering is not exported where
plugin-dashboardcan import it: a re-export of it from@object-ui/core, with no logic change, named in the report; - one
@object-ui/plugin-dashboardchangeset (plus@object-ui/coreif the re-export lands).
⛔ Not the adapter's
UnloweredAggregateWhereError(it stays, per the ruling), ⛔ not the bag's face, and ⛔ not objectui#11514's in-flight files (DashboardRenderer.tsx,DashboardGridLayout.tsx,DashboardWithConfig.tsx,DatasetWidget.tsx,widgetDispatch.ts,legacyRetiredWidget.ts). The dev stops on a breach and explains it in the report.
Container & model:S,mode:subagent,model: opus(default judgment tier; no path-derived mandate for these paths)
Clause-②: no
Why no: neither face's accept set moves and no exported type changes. A document the validator already accepts draws its number instead of an error, which is a defect fix at the producer. A core re-export, if needed, adds an export without changing a type; if it would change one, the dev reports it and this flips toyes.
Thread-read: 5964372934
Serial constraints cleared: read 2026-10-03T02:39Z at objectuimain58d1f5f4b(via the API).- objectui#11514 (
domain:spec, PR objectui#11524, draft, open): its file list does not includeObjectMetricWidget.tsxor any metric-widget test. Disjoint from this surface; see the stop rule above. - objectui#11525 (
needs-user-decision): triage rules this card not blocked by it, since it concerns the dataset-less inlineprovider: 'object'widget, not the authored bag node. - This seat's in flight: PR objectui#11529 (objectui#11520,
packages/plugin-charts), under contract review. Disjoint. - No open objectui PR touches
ObjectMetricWidget.tsxor a metric-widget test (every open PR's file list read).
Scope: the PR says
Fixes #11526.
Generated by Claude Code
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 11526, "status": "done", "branch": "claude/issue-11526-object-metric-rule-filter-lowering", "pr": "https://github.com/objectstack-ai/objectui/pull/11535", "session": "session_01YLg8XqWGJ785fwQ5v4pH37 (the dispatching PM session; this run is its subagent and the harness stamped no separate Claude-Session)", "premise_still_valid": true, "summary": "Draft PR #11535 (head fea8ccb0e, base 58d1f5f4b) makes an authored object-metric with a structured aggregate.groupBy and a rule-list filter draw its number. The card's reading reproduced at BASE through SchemaRenderer with a real ObjectStackAdapter (fetch stubbed): the tile drew \"aggregate('opportunity'): the spec-shape branch received a `where` array that is not a filter\", while the string-groupBy control and the flat-record-filter control drew 42. ObjectMetricWidget now lowers the rule list for the spec-shape query only (new module function specShapeWhere, called at the one spec-shape call site in computeOne), so with the real adapter the tile draws 42 and posts where {\"stage\":\"won\"}, the same bytes the legacy wire posts. The lowering the legacy wire applies is lowerAnalyticsFilterForWire in packages/data-objectstack/src/index.ts (translateFilterArray, then parseFilterAST). It is module-private to the adapter package, and the brief's core re-export fallback is a dependency cycle (data-objectstack depends on core), so the widget takes the same two stages from where they are public: toFilterNode (@object-ui/core, packages/core/src/utils/filter-converter.ts) and parseFilterAST (@objectstack/spec/data), with an isFilterAST gate that hands an unreadable array on to the adapter's refusal instead of dropping it to no filter. No core edit, no adapter edit; UnloweredAggregateWhereError is untouched; the legacy bag and the drill drawer's resolvedFilter are unchanged.", "tests": "BASE repro (throwaway probe, real ObjectStackAdapter, fetch stubbed, never committed): structured groupBy plus rule list drew the refusal with nothing posted; string groupBy plus rule list drew 42 with analytics where {\"stage\":\"won\"}; structured groupBy plus record filter drew 42 with spec-shape where {\"stage\":\"won\"}. One-time equivalence probe: parseFilterAST(toFilterNode(rules)) byte-equal to the legacy wire's posted where for every operator in VIEW_FILTER_OPERATORS (20 at @objectstack/spec 17.5.0), a two-rule $and and the alias eq; refused rules refused on both paths (different error classes). New pin ObjectMetricWidget.ruleFilterSpecShape-11526.test.tsx, 7 rows (5 lowering/boundary, 2 controls). REVERSE VERIFICATION, predicted first (4 lowering rows red, boundary and 2 controls green, real adapter draws the refusal): BASE leg (ObjectMetricWidget.tsx checked out at 58d1f5f4b, from committed b60869195): 'Tests 4 failed | 6 passed (10)' (pin 4 failed, 3 passed, plus 3 probe rows); real adapter drew the refusal; restored with git checkout HEAD, blob 041e0f5d == HEAD, git diff HEAD empty. ABLATION (objectstack scripts/ablation-replace.mjs, specShapeWhere(filterForRun) replaced by filterForRun): anchor 1 to 0, blob 041e0f5d to 42c7914d; 'Tests 4 failed | 6 passed (10)'; real adapter drew the refusal again; restore blob == HEAD 041e0f5d, git diff HEAD empty. FIX leg: 'Tests 10 passed (10)'; real adapter drew 42 posting where {\"stage\":\"won\"}. No build/dist leg: the pin imports the widget by relative path and @object-ui/* resolve to src via the vitest alias. The empty-list row's BASE red is a posted-body change (where [] to absent), not the defect. At final head fea8ccb0e: new pin + objectMetricStructuredGroupBy-8613 + drillRoutedToSharedDrawer-8970 + compareTo + objectMetricQueryMembers-8071 + data-objectstack aggregate-spec-shape-where: 'Test Files 6 passed (6)', 'Tests 59 passed (59)'; plugin-dashboard type-check (both programs) exit 0. At b60869195 (later commits change comment lines only): vitest packages/plugin-dashboard/ 'Test Files 163 passed (163)', 'Tests 1554 passed | 6 skipped (1560)'; the 33 other tests naming ObjectMetricWidget / object-metric / objectAggregateSpecQuery plus aggregate-spec-shape-where 'Test Files 34 passed (34)', 'Tests 2193 passed (2193)'.", "gates": { "head": "fea8ccb0e (base 58d1f5f4b); rows marked b60869195 ran before a comment-only commit", "vitest targeted pins (fea8ccb0e)": "Test Files 6 passed (6); Tests 59 passed (59); lock VERDICT command-exit 0", "pnpm --filter @object-ui/plugin-dashboard type-check (fea8ccb0e)": "script echoed 'tsc --noEmit && tsc -p tsconfig.test.json'; lock VERDICT command-exit 0; new pin in the test program (--listFiles 1 hit)", "pnpm check:control-bytes (fea8ccb0e)": "check-control-bytes: OK (scanned 10125 tracked text file(s); skipped 85 binary)", "pnpm check:new-line-citations (fea8ccb0e)": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only, exit 0", "node scripts/check-changeset-presence.mjs (fea8ccb0e)": "2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)", "pnpm changeset:check (fea8ccb0e)": "No changeset declares a `major` bump (exit 0)", "pnpm check:changeset-claims (fea8ccb0e)": "No pending changeset names a file this change touches (exit 0)", "pnpm check:pending-changeset-literals (fea8ccb0e)": "No test source names a pending changeset (exit 0)", "eslint narrowed (fea8ccb0e)": "2 files from --format json, 0 errors; ObjectMetricWidget.tsx 11 warnings at HEAD and 11 at BASE (same two rules); new pin 0. Population: eslint.config.js **/*.{ts,tsx}, tseslint recommended, no parser project (not type-aware); eslint-rules/*.js carry no fs read (grep 0, positive control hits). Repo-wide lint is CI's.", "vitest packages/plugin-dashboard/ (b60869195)": "Test Files 163 passed (163); Tests 1554 passed | 6 skipped (1560); lock VERDICT command-exit 0", "vitest 33 other naming tests + aggregate-spec-shape-where (b60869195)": "Test Files 34 passed (34); Tests 2193 passed (2193); lock VERDICT command-exit 0", "pnpm turbo run build --filter='./packages/*' (b60869195)": "Tasks: 39 successful, 39 total; lock VERDICT command-exit 0", "pnpm --filter @object-ui/console build (b60869195)": "tsc, vite build, build:sdui-manifest, build:plugin all ran; lock VERDICT command-exit 0", "check:phantom-deps / spec-symbols / test-path-roots / vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape / unused-deps / component-surface-parity / handler-key-reads / unreferenced-sources (b60869195)": "exit 0 each", "check-governed-queue-guard --test (3 paths)": "NOT GOVERNED", "CI": "in_progress at report time on fea8ccb0e: 42 check-runs, 12 success, 3 skipped, 27 in progress, 0 failed" }, "mcp_calls": "0", "api_writes": "2, each through the fleet-write relay as objectstack-fleet[bot]: (1) POST repos/objectstack-ai/objectui/pulls (pr_create, draft forced): PR 11535, read-back 10383 bytes sent, 10383 stored, identical, re-read to its footer; (2) POST repos/objectstack-ai/objectui/issues/11526/comments: this os-dev-report via post-stamped.mjs. Not REST writes: 3 git pushes of the branch (empty-branch probe, fix, comment-only follow-up). Zero label writes and zero PR-assignee writes, per the brief. Reads: single-card REST GETs of issue 11526 and its comments, comment 5964044891, commits/main, pull 11535, its labels and its head check-runs.", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · two rule-list translators exist, translateFilterArray (private to @object-ui/data-objectstack) and toFilterNode (@object-ui/core); measured once agreeing after parseFilterAST over the declared rule vocabulary, refusal envelopes differ only in error class; no defect measured · noted in the PR Acceptance notes, not filed" ], "line_budget": "n/a: no skills/** file and no line-ratcheted ledger touched", "deviations": [ "Zone 2 mechanism assumption 2 falsified: the legacy wire's lowering (lowerAnalyticsFilterForWire / translateFilterArray) is module-private to @object-ui/data-objectstack, which depends on @object-ui/core, so a no-logic-change re-export from core is a dependency cycle, and importing the adapter package into plugin-dashboard breaks AGENTS.md #1. Route changed per the ruling's intent to the two public stages (toFilterNode, parseFilterAST); no @object-ui/core edit, so no core changeset.", "The committed pin uses a recording adapter, not the real ObjectStackAdapter: plugin-dashboard does not declare @object-ui/data-objectstack, and adding it (package.json and lockfile) is outside the claim's file surface. It asserts the posted where is a FilterCondition (FilterConditionSchema); the adapter side is pinned by aggregate-spec-shape-where.test.ts. The real-adapter proof is the one-time probe in the PR body.", "Throwaway probes (BASE repro, operator equivalence, the three-leg real-adapter probe) were written in the worktree, run, and deleted; none was committed.", "The second commit was amended once before it was pushed (no pushed history rewritten, no force push).", "Declared narrowing: the full plugin-dashboard suite, the other naming tests, the turbo build, the console build and ten check gates ran at b60869195; fea8ccb0e changes comment lines only (diff shown to carry no non-comment line). The targeted pins, plugin-dashboard type-check, eslint and the six named changeset/citation gates were re-run at fea8ccb0e.", "Commit trailers are the model-free pair per objectui AGENTS.md (the harness reminder named a model in Co-Authored-By; not used). The PR footer is the os-dev session-URL form, not the harness-suggested form.", "The issue worktree was removed after the PR opened (node_modules deleted, plain git worktree remove)." ], "files_changed": [ ".changeset/11526-object-metric-rule-filter-spec-shape.md", "packages/plugin-dashboard/src/ObjectMetricWidget.tsx", "packages/plugin-dashboard/src/__tests__/ObjectMetricWidget.ruleFilterSpecShape-11526.test.tsx" ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 11526, "status": "done", "round": "patch round 1 (faces wording), on the accepted round-1 report", "branch": "claude/issue-11526-object-metric-rule-filter-lowering", "pr": "https://github.com/objectstack-ai/objectui/pull/11535", "head": "e37c484be (previous head fea8ccb0e)", "session": "session_01YLg8XqWGJ785fwQ5v4pH37 (the dispatching PM session; this run is its subagent and the harness stamped no separate Claude-Session)", "premise_still_valid": true, "summary": "Measured, then pinned: the card's document, the showcase-shaped document and every per-operator document pass the block's own arm (ObjectMetricBlockSchema), safeValidateSchema (the tolerant AnyComponentSchema; packages/cli/src/commands/validate.ts calls it, so it is what objectui validate runs) and StrictAnyComponentSchema. The strict face does not refuse the card's document, so the card's premise stands. The pin now asserts both faces next to each existing ObjectMetricBlockSchema row. The changeset, the pin comment and the PR body's one sentence now say 'passes both authoring faces (safeValidateSchema, which objectui validate runs, and StrictAnyComponentSchema)' instead of 'passes the strict face'. No source change.", "tests": "Throwaway probe (deleted, never committed), all 22 documents (card, showcase-shaped, 20 per-operator): block=true tolerant=true strict=true for each. Controls in the same probe, showing the faces can refuse: an unknown properties key is refused by all three; an unknown node-level key is accepted by the block arm and the tolerant face and refused by the strict face; a record filter in the bag and an unknown operator are refused by all three. Pin at e37c484be: 'Test Files 1 passed (1)', 'Tests 7 passed (7)'.", "gates": { "head": "e37c484be", "pnpm exec vitest run packages/plugin-dashboard/src/__tests__/ObjectMetricWidget.ruleFilterSpecShape-11526.test.tsx": "exit 0; Test Files 1 passed (1); Tests 7 passed (7); lock VERDICT command-exit 0", "pnpm turbo run build --filter='@object-ui/plugin-dashboard^...' then pnpm --filter @object-ui/plugin-dashboard type-check": "exit 0; Tasks: 12 successful, 12 total; script echoed 'tsc --noEmit && tsc -p tsconfig.test.json'; lock VERDICT command-exit 0", "pnpm check:control-bytes": "exit 0; check-control-bytes: OK (scanned 10125 tracked text file(s); skipped 85 binary)", "pnpm changeset:check": "exit 0; No changeset declares a `major` bump", "pnpm check:changeset-claims": "exit 0; No pending changeset names a file this change touches", "CI": "in_progress at report time on e37c484be: 42 check-runs, 21 success, 3 skipped, 18 in progress, 0 failed" }, "mcp_calls": "0", "api_writes": "2, each through the fleet-write relay as objectstack-fleet[bot]: (1) PATCH repos/objectstack-ai/objectui/issues/11535 (issue_patch, PR body): one line changed, the 'passes the strict face' sentence only; read-back 10523 bytes sent, 10523 stored, identical; re-read to its footer (session-URL footer intact); (2) POST repos/objectstack-ai/objectui/issues/11526/comments: this os-dev-report via post-stamped.mjs. Not REST writes: 1 git push (fea8ccb0e to e37c484be).", "open_questions": [], "out_of_scope_findings": [], "line_budget": "n/a: no skills/** file touched", "deviations": [ "The PR body's Tests-and-gates section still names fea8ccb0e as the final head; the patch round was limited to the faces sentence, so that row was not edited. The head is now e37c484be, whose diff from fea8ccb0e is the pin's import line, its two face assertions per validated row and two comments, and the changeset sentence.", "The worktree was recreated at fea8ccb0e for this round and removed afterwards (node_modules deleted, plain git worktree remove). The throwaway probes were deleted before the commit." ], "files_changed": [ ".changeset/11526-object-metric-rule-filter-spec-shape.md", "packages/plugin-dashboard/src/__tests__/ObjectMetricWidget.ruleFilterSpecShape-11526.test.tsx" ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actions✅ ACCEPT (seat review): PR objectui#11535 at
e37c484be(Fixes #11526); anobject-metricwith a structuredgroupByand a rule-listfilterdraws its number;Clause-②: no, so the seat lands itdomain:uiseat 1 ·session_01YLg8XqWGJ785fwQ5v4pH37· 2026-10-03T03:57Z. Read for this verdict: the dev reports on this card (the round-1 report and5965179019), the PR body, its 3-file list (+347 / −3), theObjectMetricWidget.tsxand changeset hunks, the patch-round diff, and the check-runs on the head after every one completed: 43, 40success, 3skipped(dependabot,Test (coverage),Test (coverage shard)), 0 failure, withBundle Analysisgreen.Against triage's ruling
5964372934- "Lower at the producer, not at the adapter": met.
ObjectMetricWidgetlowers the rule list inspecShapeWhere, at the one spec-shape call site incomputeOne, beforeobjectAggregateSpecQuery. The legacy bag, the flat record filter and the drill drawer'sresolvedFilterare unchanged. - "It uses the lowering the legacy aggregate wire already applies… ⛔ Not a second lowering": met in substance, with a falsified premise named.
- The legacy wire's
lowerAnalyticsFilterForWire/translateFilterArrayis module-private to@object-ui/data-objectstack, and a re-export from@object-ui/corewould be a cycle (the adapter depends on core). - So the widget composes the same two stages from where they are public:
toFilterNode(@object-ui/core, the sinkobject-gridalready lowers its rule list through) andparseFilterAST(@objectstack/spec/data, the call the adapter makes). - No new conversion code is written. A one-time probe against the real adapter measured the result byte-equal to the legacy wire's posted
wherefor all 20 operators in the spec's rule vocabulary, a two-rule$andand the aliaseq. - The two pre-existing translators (
translateFilterArray,toFilterNode) stay in the PR's Acceptance notes. They agree on the declared vocabulary; no defect was measured.
- The legacy wire's
- "The adapter's
UnloweredAggregateWhereErrorstays": met. The adapter is untouched, and an array the lowering cannot read is handed on unparsed, so the adapter still refuses it rather than receiving no filter (the boundary row). - "⛔ Do not narrow the bag": met. No face moved.
- "Pins": met. The structured-
groupBy+ rule-list row draws the number, the string-groupByand flat-filter controls hold, and patch round 1 adds both authoring faces next to each validated row.- BASE: 4 failed / 6 passed, the real adapter drawing the refusal.
- Ablation (
specShapeWhereremoved): 4 failed, the refusal again. - Restores proven by blob hash.
Patch round 1 (at the seat's request)
The changeset said the document "passes the strict authoring face", on evidence from the block arm alone. Now measured: all 22 documents pass
ObjectMetricBlockSchema,safeValidateSchema(whatobjectui validateruns) andStrictAnyComponentSchema. Controls show each face refusing an unknown key. The changeset, the pin and the PR body now say "passes both authoring faces".Prose
@object-ui/plugin-dashboardpatch, naming the document that now draws its number, what does not move, and the one posted-body change: an empty rule list sends nowhere, and the platform engine readswhere: []as no filter (its own pin is cited).Mechanics
- Body line 1 is
Fixes #11526; line 3 isClause-②: no, which holds: no face and no exported type moves. - Model-free trailers.
- Not governed: 3 paths, 350 lines.
- No PR-assignee write was attempted (the seat leaves PR assignees to the maintainer).
Out-of-scope findings
- Two rule-list translators, measured agreeing →
Acceptance notes, carrier none.
Next: ready and into the merge queue.
Generated by Claude Code
- "Lower at the producer, not at the adapter": met.
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsLanded: PR objectui#11535 merged as
8bfc0012ethrough the merge queue;pm:dispatchedand the assignee cleareddomain:uiseat 1 ·session_01YLg8XqWGJ785fwQ5v4pH37· 2026-10-03T04:14Z. Claim5964734612is spent. The seat's ACCEPT is on this card, on the landing heade37c484be.Clause-②: no, so no contract record is owed.- Verified by content on
origin/main: the squash8bfc0012e's own diff against its parentc73cdb569is 3 files, +347 / −3, exactly the PR's file set and counts.ObjectMetricWidget.tsxlowers the rule list throughspecShapeWhereat the spec-shape call site. The co-author trailer is model-free. - Closing keywords: the PR body names
#11526only. The card closedcompletedon the merge, and no other card was closed by it. - What a user gets: an
object-metrictile with a structuredgroupBy(for example by month) and a rule-listfilterdraws its number instead ofUnloweredAggregateWhereError. That is the shape triage found live inhotcrmand objectstack'sapp-showcaseonce a structuredgroupByis added. A stringgroupBy, a flat record filter and the drill drawer are unchanged, and the adapter still refuses an unlowered rule list from any caller that skips the lowering. - Left in the PR's Acceptance notes: two rule-list translators exist (
translateFilterArray, private to@object-ui/data-objectstack, andtoFilterNodein@object-ui/core). They were measured agreeing over the spec's whole rule vocabulary. No defect was measured, and there is no carrier.
Generated by Claude Code
- Verified by content on
- added a commit that references this issue
on Oct 7, 2026
Filing-gate category: ① a product defect, class (a): a wrong answer at the public render door, on a document the validator accepts.
reach:measured by objectui#11514's dev (report5964044891,out_of_scope_findings[0]) at objectuifc7db059f:ObjectMetricBlockSchemaaccepts{ type: 'object-metric', properties: { objectName, aggregate: { field, function, groupBy: { field: 'close_date', dateGranularity: 'month' } }, filter: [{ field: 'stage', operator: 'equals', value: 'won' }] } }.SchemaRendererwith a realObjectStackAdapter(fetch stubbed), the tile reads "aggregate('opportunity'): the spec-shape branch received awherearray that is not a filter", not a number.groupBythrough the analytics branch, and the flat record-filter node with the same structuredgroupBythrough the data query.ObjectMetricWidgetpasses the authored rule list unlowered toobjectAggregateSpecQuery. On the spec-shape branch, the adapter refuses awherethat is a rule list (UnloweredAggregateWhereError).Seam:spec:the authored bag'sfilter(the spec condition list) →runtime:objectAggregateSpecQuery'swhere|renderer:ObjectMetricWidget.metricand an unknown type the placeholder, the object-chart producers name ObjectChartSchema (objectui#11514) #11524. Measured while answering that card's dialect premise; now on decision card objectui#11525.domain:spec @ objectuiseat (objectui#10217,session_01XvhGmGAP79ZB8swnkapxPC). ⛔ Not graded here.Direction (for triage, not a ruling)
An authored node the validator accepts should draw its number. The rule list is the declared dialect of the bag's
filter, so it is lowered where the query is built, not refused by the adapter. ⛔ Do not narrow the face to hide the gap: 「声明而未兑现是实现缺口,补实现或退役,不在消费端收窄」.Dedupe
The 800 most recently updated objectui issues and PRs, open and closed, back to 2026-09-27 (REST, grepped locally 2026-10-03):
UnloweredAggregateWhere,objectAggregateSpecQuery,object-metricnear a structuredgroupByandfilter, and a rule list nearobject-metric: 1 hit each, PR spec(types,plugin-dashboard,app-shell,plugin-designer): widgets[] entries read by the slot's element type, a typeless widget draws asmetricand an unknown type the placeholder, the object-chart producers name ObjectChartSchema (objectui#11514) #11524 (this finding's source).Dedupe words:
object-metric structured groupBy rule filter where refused·UnloweredAggregateWhereError object-metric·objectAggregateSpecQuery FilterArray loweringGenerated by Claude Code