You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(plugin-list): a chart list view bound to a semantic dataset gets a node with no filter, so neither the authored view filter nor the toolbar Filter reaches its query #10327
Ruled: 5825582592 · letter A (refuse view filter on dataset chart; withhold toolbar Filter) · 2026-09-25T02:18Z
Filing-gate category: ① a product defect with a named site and a reproduction. Reader: triage first (route and grade), then the domain:ui execution seat that claims it. The site: the chart branch of packages/plugin-list/src/ListView.tsx for the dataset binding shape (resolveListChartBinding shape 'dataset', ADR-0021), and ObjectChart's queryDataset call in packages/plugin-charts.
Filed by the domain:ui#4 execution seat (session_01BP8CMtACxTdLjqR6rhd33C) from the os-dev-report of objectui#10250 (PR objectui#10323). The dev measured it; ⛔ it is filed bare, not graded here.
The defect
A chart list view bound to a semantic dataset gets an object-chart node carrying no filter at all. Two filters are lost:
the view's own authored filter, which the list view declares and an author expects to scope the chart;
the toolbar Filter and chips.
ObjectChart calls queryDataset with only the dimensions and measures. objectui#10250 (PR objectui#10323) forwards the effective filter to the OBJECT-bound chart only. This shape was left out on purpose, because it is not a one-line forwarding. queryDataset's runtimeFilter is the spec's FilterCondition, and a dataset's field namespace need not be the list object's. Mapping list-object fields onto dataset dimensions is a real design step.
Reproduction (the dev's real-renderer probe, on main8b1f06619 and on PR head 3bd041e6a, not committed)
The view has authored filter [[name,!=,zzz]] and toolbar status = open is active. queryDataset is called as ["task_ds", { "dimensions": ["status"], "measures": ["total_estimate"] }], with no runtimeFilter.
⚠️ These readings are the dev's, relayed by the seat, ⛔ not re-run by the seat.
Grading notes (for triage, not a grade)
The authored-filter half is the more serious one. An author's declared scope is silently dropped on this binding shape, so the chart shows unfiltered totals.
Fix direction is open: translate the list filter into the dataset's runtimeFilter (needs a field-namespace mapping), or refuse a list-view filter on a dataset-bound chart at authoring time. That may be a decision.
Dedupe
REST page walk over the 1000 most recently updated objectui items, pattern queryDataset … (runtimeFilter|filter) / dataset … chart … filter … (drop|lost|never|ignor|not) / runtimeFilter … ListView ⇒ 0 hits. Control pattern toolbar Filter never reaches ⇒ objectui#10250, the must-hit control, which did hit. ⇒ No duplicate.
Triage: lands in @object-ui/plugin-list / plugin-charts ⇒ domain:ui, bug, priority:p2, needs-user-decision (finding removed — graded); rationale: a dataset-bound chart list view gets an object-chart node with NO filter, so both the view's AUTHORED filter and the toolbar Filter are silently dropped and the chart shows unfiltered totals (the dev measured queryDataset called without runtimeFilter); the repair forks — translate the list-object filter into the dataset's runtimeFilter (a field-namespace mapping, since a dataset's fields need not be the list object's) or refuse a view filter on a dataset-bound chart at authoring time and withhold the toolbar Filter there — which is a product/contract choice.
Ruling: batch #224 item 2 · letter A (refuse a view filter on a dataset-bound chart at authoring; withhold the toolbar Filter there) · maintainer 「批 #224 同意」 (chat, director seat summon #29, session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-25T02:16Z
Director seat, summon #29. Presented with recommendation A (fallback B); the maintainer agreed. Thread re-read to its last comment (5820798059) in this act.
Ruled: A. A dataset-bound chart list view takes its scope from the dataset.
At authoring: a view filter on such a view is refused loudly, with the remedy "a dataset chart's scope is written in the dataset". The dev locates the refusal at the surface that owns it (the objectui validate face, or the spec door if the key is spec-owned) and states which in the PR.
At runtime: the toolbar Filter is not offered on such a view.
⛔ No list-object → dataset field mapping (B).
Pins: the authoring refusal, and the toolbar Filter being absent on a dataset chart while present on an object-bound chart (control).
The stored rows are not censused. If the dev finds existing dataset-chart views carrying a filter, the changeset names them with the fix.
Execution: needs-user-decision → pm:queue in this stroke. Serial after objectui#10250 / PR #10323 (ListView.tsx chart branch), in the same lane as objectui#10326. priority:p2, bug and domain:ui stand.
Claim: PM loop round 4 — domain:ui execution seat 2
Session: session_014mXUNuFomfj24w7s1pZzhN
Branch: claude/issue-10327-dataset-chart-view-filter
Worktree: objectui-issue-10327
Domain: domain:ui
Seat: domain:ui#2
File surface: packages/plugin-list/src/ListView.tsx (the toolbar Filter is withheld on a dataset-bound chart view: the toolbar flags and the chart branch's 'dataset' shape only); the authoring refusal at the surface that owns it, per ruling 5825582592: on objectui's validate face that is packages/types/src/zod/objectql.zod.ts (the ListViewSchema region only). If the refusal belongs at the spec door, the dev stops and reports: that is cross-repo, outside this claim. Also tests beside them and one .changeset/10327-…md (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus — dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes ruling 5825582592 (letter A)
Clause-②: yes
Thread-read: 5825582592
Serial constraints cleared: the ruled predecessor, objectui#10250's PR objectui#10323, merged 2026-09-24T19:22Z. The latest ListView.tsx holder, PR objectui#10454 (objectui#10370), merged 974760a. Open-PR file lists read 2026-09-25T02:57Z: no open PR edits ListView.tsx or objectql.zod.ts. Seat 1's objectui#9559 holds complex.zod.ts, not this file. Live pm:dispatched claims name neither file. Fold-or-serial with objectui#10326 (same ListView.tsx toolbar flags): serial. Five-gate gate ① fails: this card carries an authoring-refusal half, a different fix from #10326's withhold-only change. Ruling 5825585515 also orders #10326 after this card. objectui#5157 (ObjectMapConfigSchema.strict(), same objectql.zod.ts) is serial behind this claim.
Clause-②: yes — a view filter on a dataset-bound chart view goes from accepted-and-silently-dropped to refused at authoring. A published validate face's accept set moves.
{
"issue": 10327,
"status": "done",
"branch": "claude/issue-10327-dataset-chart-view-filter",
"pr": "https://github.com/objectstack-ai/objectui/pull/10477",
"session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, the parent PM seat's id (commit trailer Claude-Session line)",
"premise_still_valid": true,
"summary": "Ruling 5825582592 letter A is implemented in two halves. Runtime (plugin-list ListView.tsx): a new primitive, datasetChartOnScreen, is true when currentView is chart and resolveListChartBinding(schema).shape is dataset. While it is true, the Filter builder (toolbarFlags.showFilters) and the UserFilters chips (new toolbarFlags.showUserFilters) are not rendered. The object-bound chart keeps both controls. currentView state moved above toolbarFlags so the flags can read it. Authoring (types objectql.zod.ts, ListViewSchema region): a module-private checkListViewDatasetChartFilter is attached as a second superRefine. It adds one custom issue at filter and/or the legacy filters when viewType is chart, the effective block (chart, else options.chart) names a dataset, and the filter is a non-empty array. The message ends with the ruling's remedy. H1 confirmed: the chips feed the same effective filter, whose only reader on this view is ListView's own fetch and record-count bar, never the chart, so both controls are withheld. H2 partly falsified: filter and chart are spec-owned by reference, but objectui's face is not only a mirror. The view kind is objectui's viewType, and two spellings objectui owns (filters, options.chart) reach the same branch. So the refusal is located on objectui's validate face, as the PR states. H3: the console metadata-admin validates views against the spec's ViewSchema (clientValidation.ts dynamic-imports @objectstack/spec/ui), so this refusal surfaces via safeValidateSchema (CLI validate/check), not via Studio. The spec door is open question 1. H4: 0 dataset-bound chart views in examples/apps/content (0 with a filter); the control viewType kanban/grid/calendar gave 1 file; 0 list-view JSON/YAML documents anywhere. objectstack showcase has 2 dataset chart views, neither with a filter. So the changeset names no stored view. One write deviation: the PR assignee write was refused by the classifier and needs the seat (see deviations).",
"tests": "At head 45597bacf. types suite, pnpm exec vitest run --maxWorkers=2 packages/types/: 'Test Files 231 passed (231)', 'Tests 5142 passed (5142)'. plugin-list suite: 'Test Files 91 passed (91)', 'Tests 1077 passed (1077)'. pnpm --filter @object-ui/types --filter @object-ui/plugin-list run type-check: both 'type-check: Done' (tsc --noEmit plus tsconfig.test.json); with --listFiles each new test file appears once in its test program. The dependency closure pnpm --filter '@object-ui/plugin-list^...' run build was built first (13 projects, exit 0). RED ON BASE ab50ccc, GREEN ON HEAD: ListView.datasetChartToolbarFilter-10327.test.tsx gives base 'Tests 3 failed | 2 passed (5)' (the 3 dataset cases fail on 'found button ... Filter'; the 2 controls pass) and head 'Tests 5 passed (5)'. list-view-dataset-chart-filter-refusal-10327.test.ts gives base 'Tests 4 failed | 5 passed (9)' (the 4 refused cases fail with 'expected true to be false'; the 5 controls pass) and head 'Tests 9 passed (9)'. Each red leg used git checkout ab50ccc on the one file (marker grep -c = 0), then git checkout HEAD, and was proven by restored blob == HEAD blob (860eeb7 and 87a3fef) and an empty git diff HEAD. ABLATION of the chips gate: node objectstack scripts/ablation-replace.mjs changed anchor '{filterElements && toolbarFlags.showUserFilters && (' (x1 to x0) to '{filterElements && (' (x0 to x1), blob 860eeb7 to 943ab9b. Result: 'Tests 3 failed | 2 passed (5)', each failure found data-testid=user-filters. Restored with blob == HEAD and an empty git diff HEAD. There is no dist step: both tests import their subject from source (../ListView and ../zod/index.zod).",
"gates": [
"node scripts/check-changeset-presence.mjs exit 0: '4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'",
"pnpm changeset:check exit 0: 'No changeset declares a major bump.'",
"pnpm check:new-line-citations exit 0: 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0'",
"pnpm check:control-bytes exit 0: 'check-control-bytes: OK'",
"pnpm check:spec-symbols exit 0: '0 untriaged collisions in 0 packages'",
"pnpm check:test-path-roots exit 0: OK",
"pnpm check:pending-changeset-literals exit 0: 'No test source names a pending changeset.'",
"pnpm check:handler-key-reads exit 0: OK",
"pnpm check:unreferenced-sources exit 0: OK",
"pnpm check:vi-mock-specifiers exit 0: OK",
"pnpm check:changeset-claims exit 0, report-only: 26 pending changesets name a touched file; re-read for the chart toolbar; 10250-self-querying-views-toolbar-state.md still true",
"eslint --no-inline-config on the 4 touched source files: 0 errors; 0 messages on lines this diff adds (-f json against git diff -U0 ab50ccc HEAD)",
"doc/readme gates: none reached (no docs, README or content file touched)",
"NOT MEASURED locally, left to CI: repo-wide pnpm lint, pnpm test shards, e2e, pnpm check (its list-view population in this repo is 0 JSON/YAML documents, so recognition cannot move)"
],
"files_changed": [
"packages/plugin-list/src/ListView.tsx",
"packages/plugin-list/src/__tests__/ListView.datasetChartToolbarFilter-10327.test.tsx",
"packages/types/src/zod/objectql.zod.ts",
"packages/types/src/__tests__/list-view-dataset-chart-filter-refusal-10327.test.ts",
".changeset/10327-dataset-chart-view-filter.md"
],
"deviations": [
"PR assignee NOT written. The command node scripts/pm/label-write.mjs --repo objectstack-ai/objectui --issue 10477 --assign os-elon-musk was refused by the Claude Code auto-mode classifier (reason: External System Writes) before any request was sent. Per the role file there was no retry and no other route. The seat needs to write it: PR 10477 assignee os-elon-musk.",
"The render-site gate on the chips (the UserFilters mount in the toolbar JSX) is outside the literal 'toolbar flags and dataset chart branch' surface. It is the one consumer of the new showUserFilters flag, in the same file.",
"A third commit (changeset plus typing the pin without any) was added beyond the suggested two-commit route."
],
"mcp_calls": "0",
"api_writes": "2 — (1) fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches carrying pr_create, which executed POST /repos/objectstack-ai/objectui/pulls (draft), run 36094033651 success, PR 10477 created with body read back byte-identical; (2) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/10327/comments via post-stamped.mjs. The label-write attempt was refused by the classifier before sending (0 requests). git push is not counted.",
"open_questions": [
{
"question": "Spec door. Should objectstack also refuse the same shape at its three list-view doors? The shape is type chart, a chart block (dataset is required there) and a non-empty filter. The doors are packages/spec/src/ui/view.zod.ts, ListViewShapeSchema's terminals and the overlay arm, where checkListViewCalendarVisualization attaches. Stored view rows authored through Studio or MCP only meet that door: the console's clientValidation validates views against the spec's ViewSchema, so this PR's refusal does not reach that path.",
"options": [
"A: file an objectstack card (seat files it, back-link to objectui#10327). The spec exports checkListViewDatasetChartFilter, attached at the three doors. objectui keeps its own check, because it reads viewType, filters and options.chart, which the spec check cannot. objectui may later read the spec's message.",
"B: leave the spec door as it is; only objectui's validate face refuses."
],
"recommendation": "A. Business need (measured): list views are authored as stored view rows through the spec door, and objectstack's showcase already authors two dataset chart views there, while objectui's own tree has zero list-view JSON documents. So without A the refusal misses the population that exists. Long-term: one ruling enforced at the contract, with objectui's face as the adapter for its own spellings, which is the objectui#7715 pattern. AI-error prevention: a loud refusal at publish, where MCP and AI authors write, not a silently dropped key. Startup focus: no new gate and no new capability, just one check on an existing door. This PR's use of Fixes is unaffected, because A is a separate card in another repository."
},
{
"question": "userFilters (and filterableFields, which feeds only the Filter builder's field list) authored on a dataset-bound chart view. The runtime now withholds both controls there, so the authored block renders nothing, where before the chips rendered and changed nothing drawn. Should it be refused at authoring like filter? The ruling names only a view filter.",
"options": [
"A: extend the same refusal to userFilters and filterableFields on a dataset-bound chart (objectui face now, spec door with open question 1)",
"B: leave them accepted and inert on such a view"
],
"recommendation": "A. It is the same defect class, a list-object filter surface with no door into the dataset query. An accepted key that the runtime does not honour is exactly the AI-authoring trap the ruling removes for filter. The change is small and in the same superRefine. It needs a ruling extension because it moves the accept set beyond the ruling's text, so it was not implemented here."
}
],
"out_of_scope_findings": [
"none filed. Noted in the PR's Acceptance notes, not class a/b/c: (1) zod 4 skips object-level refinements when a field already failed, so a filter written as objectui runtime FilterNode tuples meets the spec field's invalid_type before this refusal; the calendar neighbour behaves the same (pre-existing, documented in normalize-list-view); (2) the record-count bar on any chart view reports ListView's own fetch of list-object rows, which is pre-existing and not changed; (3) README and content/docs do not document the dataset-bound chart list view, which is outside the file surface. carrier: none (承接者:无)."
]
}
✅ ACCEPT: objectui#10477 at 45597ba; ready + auto-merge in this act
domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. It executes ruling 5825582592 (letter A: a dataset-bound chart list view takes its scope from the dataset).
ListViewSchema gains a second superRefine (checkListViewDatasetChartFilter). It adds one custom issue at the written key when all three hold: viewType: 'chart', the effective chart block (chart, else options.chart) names a dataset, and filter / legacy filters is non-empty. The message ends with the ruling's remedy, verbatim. The reviewer ran 23 of their own probes through ListViewSchema and safeValidateSchema, and the two doors agreed on every one. Eight controls parse, including an object-bound chart with a filter, an empty filter, and a grid that only offers a chart switch
location
the ruling left it to the dev: "the objectui validate face, or the spec door". viewType, filters and options.chart are objectui's own spellings, so this node's refusal is objectui's. The PR says so. The spec door is a separate, cross-repo question (open question 1 below)
runtime
datasetChartOnScreen withholds the Filter builder and the UserFilters chips only while a dataset-bound chart is on screen. The chips feed only ListView's own fetch, never the dataset node, so withholding them is inside "the toolbar Filter is not offered". The object-bound chart keeps both controls (control pin). No stale-flag path was found
stored rows
0 dataset-bound chart views in objectui's examples / apps / content (control: 1 hit). The objectstack showcase has 2, neither with a filter. The changeset names none, as the ruling asks
Clause-②: yes
published @object-ui/types@17.6.0 accepts all three refused shapes, and the head refuses them
contract review
PASS at CONTRACT_REVIEW_TIER on this head, record 5826843556 (the seat read the reviewer transcript: every turn at tier)
semver
@object-ui/types: minor, @object-ui/plugin-list: minor. A new refusal on a published validate face is a narrowing, and objectui states breaking meaning under minor (AGENTS.md §9)
governed
NOT GOVERNED (5 paths)
CI
43 check-runs on 45597ba: 40 success, 3 skipped by design, 0 red. A merge-tree dry run against main shows no conflict
closing keywords
the body's only closing reference is Fixes #10327
Findings, each with its disposition
Open question 1 (spec door): Studio- and MCP-authored view rows only meet @objectstack/spec's door, which this PR does not reach. The dev recommends an objectstack card that attaches the same check at the spec's three list-view doors. The coverage gap is real and disclosed, but it does not stop this PR ⇒ put to the maintainer; no card is filed until they answer.
Open question 2 (userFilters / filterableFields on a dataset-bound chart): these are accepted and now not offered at runtime. Refusing them would move the accept set beyond the ruling's text ⇒ put to the maintainer.
Pre-existing, disclosed: zod 4 skips object-level refinements when a field already failed, so a filter written as runtime FilterNode tuples meets invalid_type first. The calendar neighbour behaves the same (the reviewer measured it) ⇒ Acceptance notes.
The PR assignee is not set: the dev's label-write was refused by its classifier, which is a seat matter and not a landing condition ⇒ reported to the maintainer.
State
ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable in this act. needs:contract-review is not hung, because a same-head PASS is on file.
Activity
objectstack-fleet commentedon Sep 24, 2026
分诊首次定级:
priority:p2·bug·domain:ui·needs-user-decision—— 绑定到语义数据集(dataset)的图表列表视图,作者声明的视图筛选和工具栏筛选都到不了查询,图表显示的是未筛选的总数;修法有两条方向相反的路,需要维护者定Path:
packages/plugin-list/src/ListView.tsx(chart分支,resolveListChartBinding的'dataset'形状,ADR-0021)→packages/plugin-chartsObjectChart的queryDataset调用(只带dimensions/measures)Triage: lands in
@object-ui/plugin-list/plugin-charts⇒domain:ui,bug,priority:p2,needs-user-decision(findingremoved — graded); rationale: a dataset-boundchartlist view gets anobject-chartnode with NOfilter, so both the view's AUTHORED filter and the toolbar Filter are silently dropped and the chart shows unfiltered totals (the dev measuredqueryDatasetcalled withoutruntimeFilter); the repair forks — translate the list-object filter into the dataset'sruntimeFilter(a field-namespace mapping, since a dataset's fields need not be the list object's) or refuse a view filter on a dataset-bound chart at authoring time and withhold the toolbar Filter there — which is a product/contract choice.分诊席 #6015,2026-09-24T19:29Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论)。卡面的探针(
queryDataset被调用为["task_ds", { "dimensions": ["status"], "measures": ["total_estimate"] }],没有runtimeFilter)是 #10250 的开发在 main 和 PR #10323 的 head 上测的,本席没有重跑。为什么进决策箱
runtimeFilter。 用户体验最好,但要设计一套字段命名空间映射(列表对象字段 → 数据集维度),映射不上的字段还得有拒绝路径,工作量和风险都大得多。⇒ 两条路都消除今天的「静默丢掉作者的范围」。区别在于:是告诉作者「这里不支持」,还是做成「支持」。
定级说明
p2:作者声明的范围被静默丢掉,图表显示的是全量总数,读起来却像是筛选后的结果。这是卡面指出的更严重的一半。
裁决后的执行要点
ListView.tsx的图表分支正被 finding(plugin-list): on tree and chart views the toolbar Filter never reaches the view's own query, and on gantt the toolbar Search does not — same shape as objectui#10037, three more sites #10250 的 PR fix(plugin-list,plugin-gantt,types): toolbar Filter and chips reach the tree and chart queries; toolbar Search reaches the gantt query (objectui#10250) #10323 修改(它把有效筛选转给对象绑定的图表)。⛔ 排在它后面。Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
Ruling: batch #224 item 2 · letter A (refuse a view filter on a dataset-bound chart at authoring; withhold the toolbar Filter there) · maintainer 「批 #224 同意」 (chat, director seat summon #29,
session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-25T02:16ZDirector seat, summon #29. Presented with recommendation A (fallback B); the maintainer agreed. Thread re-read to its last comment (5820798059) in this act.
Ruled: A. A dataset-bound
chartlist view takes its scope from the dataset.Execution:
needs-user-decision→pm:queuein this stroke. Serial after objectui#10250 / PR #10323 (ListView.tsxchart branch), in the same lane as objectui#10326.priority:p2,buganddomain:uistand.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
Claim: PM loop round 4 —
domain:uiexecution seat 2Session:
session_014mXUNuFomfj24w7s1pZzhNBranch:
claude/issue-10327-dataset-chart-view-filterWorktree:
objectui-issue-10327Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/plugin-list/src/ListView.tsx(the toolbar Filter is withheld on a dataset-boundchartview: the toolbar flags and thechartbranch's'dataset'shape only); the authoring refusal at the surface that owns it, per ruling5825582592: on objectui's validate face that ispackages/types/src/zod/objectql.zod.ts(theListViewSchemaregion only). If the refusal belongs at the spec door, the dev stops and reports: that is cross-repo, outside this claim. Also tests beside them and one.changeset/10327-…md(stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus—dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes ruling5825582592(letter A)Clause-②: yes
Thread-read: 5825582592
Serial constraints cleared: the ruled predecessor, objectui#10250's PR objectui#10323, merged 2026-09-24T19:22Z. The latest
ListView.tsxholder, PR objectui#10454 (objectui#10370), merged974760a. Open-PR file lists read 2026-09-25T02:57Z: no open PR editsListView.tsxorobjectql.zod.ts. Seat 1's objectui#9559 holdscomplex.zod.ts, not this file. Livepm:dispatchedclaims name neither file. Fold-or-serial with objectui#10326 (sameListView.tsxtoolbar flags): serial. Five-gate gate ① fails: this card carries an authoring-refusal half, a different fix from #10326's withhold-only change. Ruling5825585515also orders #10326 after this card. objectui#5157 (ObjectMapConfigSchema.strict(), sameobjectql.zod.ts) is serial behind this claim.Clause-②: yes— a view filter on a dataset-bound chart view goes from accepted-and-silently-dropped to refused at authoring. A published validate face's accept set moves.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
os-dev-report
{ "issue": 10327, "status": "done", "branch": "claude/issue-10327-dataset-chart-view-filter", "pr": "https://github.com/objectstack-ai/objectui/pull/10477", "session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, the parent PM seat's id (commit trailer Claude-Session line)", "premise_still_valid": true, "summary": "Ruling 5825582592 letter A is implemented in two halves. Runtime (plugin-list ListView.tsx): a new primitive, datasetChartOnScreen, is true when currentView is chart and resolveListChartBinding(schema).shape is dataset. While it is true, the Filter builder (toolbarFlags.showFilters) and the UserFilters chips (new toolbarFlags.showUserFilters) are not rendered. The object-bound chart keeps both controls. currentView state moved above toolbarFlags so the flags can read it. Authoring (types objectql.zod.ts, ListViewSchema region): a module-private checkListViewDatasetChartFilter is attached as a second superRefine. It adds one custom issue at filter and/or the legacy filters when viewType is chart, the effective block (chart, else options.chart) names a dataset, and the filter is a non-empty array. The message ends with the ruling's remedy. H1 confirmed: the chips feed the same effective filter, whose only reader on this view is ListView's own fetch and record-count bar, never the chart, so both controls are withheld. H2 partly falsified: filter and chart are spec-owned by reference, but objectui's face is not only a mirror. The view kind is objectui's viewType, and two spellings objectui owns (filters, options.chart) reach the same branch. So the refusal is located on objectui's validate face, as the PR states. H3: the console metadata-admin validates views against the spec's ViewSchema (clientValidation.ts dynamic-imports @objectstack/spec/ui), so this refusal surfaces via safeValidateSchema (CLI validate/check), not via Studio. The spec door is open question 1. H4: 0 dataset-bound chart views in examples/apps/content (0 with a filter); the control viewType kanban/grid/calendar gave 1 file; 0 list-view JSON/YAML documents anywhere. objectstack showcase has 2 dataset chart views, neither with a filter. So the changeset names no stored view. One write deviation: the PR assignee write was refused by the classifier and needs the seat (see deviations).", "tests": "At head 45597bacf. types suite, pnpm exec vitest run --maxWorkers=2 packages/types/: 'Test Files 231 passed (231)', 'Tests 5142 passed (5142)'. plugin-list suite: 'Test Files 91 passed (91)', 'Tests 1077 passed (1077)'. pnpm --filter @object-ui/types --filter @object-ui/plugin-list run type-check: both 'type-check: Done' (tsc --noEmit plus tsconfig.test.json); with --listFiles each new test file appears once in its test program. The dependency closure pnpm --filter '@object-ui/plugin-list^...' run build was built first (13 projects, exit 0). RED ON BASE ab50ccc, GREEN ON HEAD: ListView.datasetChartToolbarFilter-10327.test.tsx gives base 'Tests 3 failed | 2 passed (5)' (the 3 dataset cases fail on 'found button ... Filter'; the 2 controls pass) and head 'Tests 5 passed (5)'. list-view-dataset-chart-filter-refusal-10327.test.ts gives base 'Tests 4 failed | 5 passed (9)' (the 4 refused cases fail with 'expected true to be false'; the 5 controls pass) and head 'Tests 9 passed (9)'. Each red leg used git checkout ab50ccc on the one file (marker grep -c = 0), then git checkout HEAD, and was proven by restored blob == HEAD blob (860eeb7 and 87a3fef) and an empty git diff HEAD. ABLATION of the chips gate: node objectstack scripts/ablation-replace.mjs changed anchor '{filterElements && toolbarFlags.showUserFilters && (' (x1 to x0) to '{filterElements && (' (x0 to x1), blob 860eeb7 to 943ab9b. Result: 'Tests 3 failed | 2 passed (5)', each failure found data-testid=user-filters. Restored with blob == HEAD and an empty git diff HEAD. There is no dist step: both tests import their subject from source (../ListView and ../zod/index.zod).", "gates": [ "node scripts/check-changeset-presence.mjs exit 0: '4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'", "pnpm changeset:check exit 0: 'No changeset declares a major bump.'", "pnpm check:new-line-citations exit 0: 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0'", "pnpm check:control-bytes exit 0: 'check-control-bytes: OK'", "pnpm check:spec-symbols exit 0: '0 untriaged collisions in 0 packages'", "pnpm check:test-path-roots exit 0: OK", "pnpm check:pending-changeset-literals exit 0: 'No test source names a pending changeset.'", "pnpm check:handler-key-reads exit 0: OK", "pnpm check:unreferenced-sources exit 0: OK", "pnpm check:vi-mock-specifiers exit 0: OK", "pnpm check:changeset-claims exit 0, report-only: 26 pending changesets name a touched file; re-read for the chart toolbar; 10250-self-querying-views-toolbar-state.md still true", "eslint --no-inline-config on the 4 touched source files: 0 errors; 0 messages on lines this diff adds (-f json against git diff -U0 ab50ccc HEAD)", "doc/readme gates: none reached (no docs, README or content file touched)", "NOT MEASURED locally, left to CI: repo-wide pnpm lint, pnpm test shards, e2e, pnpm check (its list-view population in this repo is 0 JSON/YAML documents, so recognition cannot move)" ], "files_changed": [ "packages/plugin-list/src/ListView.tsx", "packages/plugin-list/src/__tests__/ListView.datasetChartToolbarFilter-10327.test.tsx", "packages/types/src/zod/objectql.zod.ts", "packages/types/src/__tests__/list-view-dataset-chart-filter-refusal-10327.test.ts", ".changeset/10327-dataset-chart-view-filter.md" ], "deviations": [ "PR assignee NOT written. The command node scripts/pm/label-write.mjs --repo objectstack-ai/objectui --issue 10477 --assign os-elon-musk was refused by the Claude Code auto-mode classifier (reason: External System Writes) before any request was sent. Per the role file there was no retry and no other route. The seat needs to write it: PR 10477 assignee os-elon-musk.", "The render-site gate on the chips (the UserFilters mount in the toolbar JSX) is outside the literal 'toolbar flags and dataset chart branch' surface. It is the one consumer of the new showUserFilters flag, in the same file.", "A third commit (changeset plus typing the pin without any) was added beyond the suggested two-commit route." ], "mcp_calls": "0", "api_writes": "2 — (1) fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches carrying pr_create, which executed POST /repos/objectstack-ai/objectui/pulls (draft), run 36094033651 success, PR 10477 created with body read back byte-identical; (2) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/10327/comments via post-stamped.mjs. The label-write attempt was refused by the classifier before sending (0 requests). git push is not counted.", "open_questions": [ { "question": "Spec door. Should objectstack also refuse the same shape at its three list-view doors? The shape is type chart, a chart block (dataset is required there) and a non-empty filter. The doors are packages/spec/src/ui/view.zod.ts, ListViewShapeSchema's terminals and the overlay arm, where checkListViewCalendarVisualization attaches. Stored view rows authored through Studio or MCP only meet that door: the console's clientValidation validates views against the spec's ViewSchema, so this PR's refusal does not reach that path.", "options": [ "A: file an objectstack card (seat files it, back-link to objectui#10327). The spec exports checkListViewDatasetChartFilter, attached at the three doors. objectui keeps its own check, because it reads viewType, filters and options.chart, which the spec check cannot. objectui may later read the spec's message.", "B: leave the spec door as it is; only objectui's validate face refuses." ], "recommendation": "A. Business need (measured): list views are authored as stored view rows through the spec door, and objectstack's showcase already authors two dataset chart views there, while objectui's own tree has zero list-view JSON documents. So without A the refusal misses the population that exists. Long-term: one ruling enforced at the contract, with objectui's face as the adapter for its own spellings, which is the objectui#7715 pattern. AI-error prevention: a loud refusal at publish, where MCP and AI authors write, not a silently dropped key. Startup focus: no new gate and no new capability, just one check on an existing door. This PR's use of Fixes is unaffected, because A is a separate card in another repository." }, { "question": "userFilters (and filterableFields, which feeds only the Filter builder's field list) authored on a dataset-bound chart view. The runtime now withholds both controls there, so the authored block renders nothing, where before the chips rendered and changed nothing drawn. Should it be refused at authoring like filter? The ruling names only a view filter.", "options": [ "A: extend the same refusal to userFilters and filterableFields on a dataset-bound chart (objectui face now, spec door with open question 1)", "B: leave them accepted and inert on such a view" ], "recommendation": "A. It is the same defect class, a list-object filter surface with no door into the dataset query. An accepted key that the runtime does not honour is exactly the AI-authoring trap the ruling removes for filter. The change is small and in the same superRefine. It needs a ruling extension because it moves the accept set beyond the ruling's text, so it was not implemented here." } ], "out_of_scope_findings": [ "none filed. Noted in the PR's Acceptance notes, not class a/b/c: (1) zod 4 skips object-level refinements when a field already failed, so a filter written as objectui runtime FilterNode tuples meets the spec field's invalid_type before this refusal; the calendar neighbour behaves the same (pre-existing, documented in normalize-list-view); (2) the record-count bar on any chart view reports ListView's own fetch of list-object rows, which is pre-existing and not changed; (3) README and content/docs do not document the dataset-bound chart list view, which is outside the file surface. carrier: none (承接者:无)." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
✅ ACCEPT: objectui#10477 at
45597ba; ready + auto-merge in this actdomain:uiseat #2,session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. It executes ruling5825582592(letter A: a dataset-boundchartlist view takes its scope from the dataset).ListViewSchemagains a secondsuperRefine(checkListViewDatasetChartFilter). It adds onecustomissue at the written key when all three hold:viewType: 'chart', the effective chart block (chart, elseoptions.chart) names adataset, andfilter/ legacyfiltersis non-empty. The message ends with the ruling's remedy, verbatim. The reviewer ran 23 of their own probes throughListViewSchemaandsafeValidateSchema, and the two doors agreed on every one. Eight controls parse, including an object-bound chart with a filter, an empty filter, and a grid that only offers a chart switchviewType,filtersandoptions.chartare objectui's own spellings, so this node's refusal is objectui's. The PR says so. The spec door is a separate, cross-repo question (open question 1 below)datasetChartOnScreenwithholds the Filter builder and theUserFilterschips only while a dataset-bound chart is on screen. The chips feed only ListView's own fetch, never the dataset node, so withholding them is inside "the toolbar Filter is not offered". The object-bound chart keeps both controls (control pin). No stale-flag path was foundexamples/apps/content(control: 1 hit). The objectstack showcase has 2, neither with a filter. The changeset names none, as the ruling asksClause-②: yes@object-ui/types@17.6.0accepts all three refused shapes, and the head refuses themCONTRACT_REVIEW_TIERon this head, record5826843556(the seat read the reviewer transcript: every turn at tier)@object-ui/types: minor,@object-ui/plugin-list: minor. A new refusal on a published validate face is a narrowing, and objectui states breaking meaning underminor(AGENTS.md §9)45597ba: 40 success, 3 skipped by design, 0 red. A merge-tree dry run against main shows no conflictFixes #10327Findings, each with its disposition
viewrows only meet@objectstack/spec's door, which this PR does not reach. The dev recommends an objectstack card that attaches the same check at the spec's three list-view doors. The coverage gap is real and disclosed, but it does not stop this PR ⇒ put to the maintainer; no card is filed until they answer.userFilters/filterableFieldson a dataset-bound chart): these are accepted and now not offered at runtime. Refusing them would move the accept set beyond the ruling's text ⇒ put to the maintainer.filterwritten as runtime FilterNode tuples meetsinvalid_typefirst. The calendar neighbour behaves the same (the reviewer measured it) ⇒ Acceptance notes.label-writewas refused by its classifier, which is a seat matter and not a landing condition ⇒ reported to the maintainer.State
readyand auto-merge (squash) go through the relay opspr_ready+automerge_enablein this act.needs:contract-reviewis not hung, because a same-head PASS is on file.Generated by Claude Code
fix(plugin-list,types): a dataset-bound chart list view takes its sco…