Repository navigation
Studio report inspector: a joined report's blocks repeater saves a block with no dataset, which objectstack's ReportSchema now refuses at blocks.N.dataset #11601
Description
Activity
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsTriage: first grade —
bug·priority:p2·domain:ui·area:reports·pm:queue. The fix lands on both sides: objectui registers aref:datasetwidget (this card), then objectstack's row spec declares it (objectstack-ai/objectstack#21714)Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-04T09:54Z. ⛔ Not a claim, ⛔ not a dispatch.Measured now, as this card's direction asked (objectui
origin/main278d2444ee):RepeaterFieldhonours a row field'swidgetandrequired. The grid cell (SchemaForm.tsxabout:2797–:2810) passesrequired={Boolean(s.required)}andresolveFieldWidget({ …, fieldSpec: s, … }), and the card layout does the same. So the row spec in objectstack'sreport.form.tsdecides the cell.ref:datasethas no renderer.widgets.tsxWIDGETSregistersref:objectandref:componentonly (about:2935). An unregistered hint resolves to the raw-JSON face (SchemaForm.tsxabout:870).- The top-level dataset picker is the inspector's curated
InspectorSelectFieldoverdatasetPickerOptions, not a spec-form widget. That is why the spec's existing top-levelwidget: 'ref:dataset'(report.form.ts:39) has never rendered.
So neither side alone fixes this:
- the row spec alone would turn the cell into a raw-JSON editor;
- the widget alone is inert until a row declares it.
Why p2. The producer is named and shipped. #21702's refusal (PR objectstack-ai/objectstack#21712) makes a freshly added block invalid at the next spec bump, and today such a block draws nothing.
This card (objectui): register
ref:datasetinWIDGETS, fed by the same dataset catalog the inspector already reads.- Options:
datasetPickerOptions, the author's label and description per objectui#11161. - The value written is the dataset name.
- It must work in a section and in a repeater row, in both the grid and card layouts.
- ⛔ No inspector-local override of the row. The spec row is the one authority for the control.
The objectstack half is objectstack-ai/objectstack#21714. The "Joined blocks" row declares
widget: 'ref:dataset'andrequired: true. It is blocked on this card reaching objectstack's.objectui-sha, the install face.Pins:
- a spec-form field declaring
widget: 'ref:dataset'renders the dataset picker in a section and in a repeater row (grid and card), and writes the dataset name; - with no catalog, it degrades to a labelled text input, not the raw-JSON face.
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 seat
on Oct 4, 2026 objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsClaim: PM loop round 8
Session:session_01FjqrwXPfSMkSfkKYDSRkN2
Account:os-zhuang(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-11601-ref-dataset-widget
Worktree:objectui-issue-11601
Domain:domain:ui
Seat:domain:ui#1
File surface: triage's direction5978719353, read at objectuiorigin/mainb92329c:packages/app-shell/src/views/metadata-admin/widgets.tsx: aref:datasetentry inWIDGETS(:2934) and itsWIDGET_LABELLINGrow (:3042, exhaustive by construction). The widget offersdatasetPickerOptions(inspectors/ReportDefaultInspector.tsx:210, the author's label and description per objectui#11161) and writes the dataset name. With no catalog it degrades to a labelled text input, not the raw-JSON face.- Wherever the dataset catalog has to reach the widget, through
WidgetContextor theSchemaFormhost the report inspector already feeds; the dev measures which.SchemaForm.tsxis only edited if the repeater path needs it, and then named. - New pins: the picker in a section and in a repeater row, in both grid and card layouts; the dataset name written; and the no-catalog degrade. One
@object-ui/app-shellpatchchangeset. - ⛔ No inspector-local override of the "Joined blocks" row: the spec row stays the one authority (triage). ⛔ No objectstack edit: the row-spec half is spec(ui):
reportForm's "Joined blocks" row offers a block'sdatasetas free text with norequired, so Studio saves the block #21702 now refuses objectstack#21714.
The dev stops on a breach and explains it in the report.
Container & model:M,mode:subagent,model: opus(default judgment tier;dispatch-gates --tier --repo objectstack-ai/objectuiprinted "no path-derived mandate" forwidgets.tsxandReportDefaultInspector.tsx)
Clause-②: no
Why:WIDGETSandWidgetContextare not re-exported frompackages/app-shell/src/index.ts, whose metadata-admin exports are the four page components.ref:datasetis already a declared hint: the spec's report form uses it at the top level,report.form.ts:39. Registering its renderer delivers a declared value; it widens no accept set. If a new export of the package index turns out to be needed, the dev writesyesand says why.
Thread-read: 5978719353
Serial constraints cleared: read 2026-10-04T10:29Z.- objectui#10202 (
hotlong) claimsviews/metadata-admin/**for the Studio picklist page. Its branchclaude/issue-10202-studio-picklist(da4c629) touches neitherwidgets.tsxnorReportDefaultInspector.tsx. This card needswidgets.tsx, so it is named here. - This seat's in flight: objectui#11002 (
runtime-config.ts,console/ConsoleShell.tsx, the storage and read-rate hooks and banners) and, claimed in this act, objectui#11605 (the plugin registrations). Both are disjoint by file. - Open PRs: objectui#11607 (objectui#8347) and feat(cli):
objectui validateandobjectui checkjudge through the strict authoring face (objectui#5250, slice A) #11069 touch neither file.
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11601,
"status": "done",
"branch": "claude/issue-11601-ref-dataset-widget",
"pr": "#11611",
"session": "session_01FjqrwXPfSMkSfkKYDSRkN2 (mode:subagent of the PM's session)",
"premise_still_valid": true,
"summary": "Registeredref:datasetinWIDGETS(RefDatasetWidget, declared'control'inWIDGET_LABELLING). It reads a new optionalWidgetContext.datasetscatalog (a LoadState ofDatasetCatalogEntry[]), offersdatasetSelectOptions(the objectui#11161 author text:LABEL (name) — description), writes the dataset NAME, keeps an out-of-catalog stored name visible and flagged(not found), shows the shared failure notice beside an editable box on a failed load, and degrades to a labelled text input when no catalog is fed (never the raw-JSON face).datasetPickerOptionsandlabelBesideNamemoved unchanged to a new pure moduleinspectors/dataset-picker-options.ts, because importing them from the inspector would create a cycle throughSchemaForm.ReportDefaultInspectorre-exportsdatasetPickerOptionsforDashboardWidgetInspectorand now passes its existinguseDatasetCatalogresult to the spec form aswidgetContext.datasets, viamapLoaded(rosterFrom(...)), withconditionScope: 'none'(the ruledreportverdict; the bundled ReportSchema has 0 predicate-named keys among 73 property paths). No inspector-local override of the joined-blocks row.SchemaForm.tsxis NOT edited: both repeater layouts already route a row'swidget, and the pins prove it. The joined-block symptom stays free text until objectstack-ai/objectstack#21714 declares the row and reaches the install face; the PR body says so. Reproduced red first: on b92329c the new pin file gave 9/9 failed, every case on the raw-JSON face (fallback notice plus textarea).",
"tests": "RED at b92329c (before edits):pnpm exec vitest run .../SchemaForm.refDatasetWidget-11601.test.tsxgaveTests 9 failed (9)(raw-JSON notice plus textarea). GREEN at b58a18b (source commit):pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/metadata-admin/plus spec-symbol-parity, ReportConfigPanel.saveOutcome-11583, ReportView.saveRefusal-11583, ReportView.dataSourceObjectKey, ReportView.supersededRows-10684, ReportConfigPanel.panelTitle, view-filter-fold.ratchet (reads widgets.tsx), packages/core column-identity.ratchet (scans widgets.tsx/SchemaForm.tsx), packages/i18n report-editor-retired-4145 gaveTest Files 389 passed (389),Tests 4550 passed | 1 skipped (4551). Narrowing: selected by import of the three edited sources and by source-text read; transitive importers (StudioDesignSurface suites etc.) not run locally and declared to CI. Re-run at FINAL HEAD 9ebe77b (changeset-only commit on top): two ratchets plus both new pin files gaveTest Files 4 passed (4),Tests 27 passed (27). Builds:pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' buildexit 0.pnpm --filter @object-ui/app-shell type-checkexit 0 (tsc --noEmit && tsc -p tsconfig.test.json);--listFilesOnlyon tsconfig.test.json lists all 5 touched test files and the new module. ABLATIONS (committed b58a18b, objectstack scripts/ablation-replace.mjs WRAP mode, anchor must hit, restore proven by blob hash): (1) delete the'ref:dataset': RefDatasetWidget,WIDGETS line, anchor 1 to 0, blob fbfd4a2d90af to 83ddbf6c965c: 17 failed / 138 passed over the 2 new pin files plus 3 registry pins (all picker and degrade pins red on the raw-JSON face, registry gate red, 9889/9931 ref:dataset rows red); restored, blob fbfd4a2d90af == HEAD, git diff HEAD empty. (2) deletedatasets: mapLoaded(...)from the inspector's widgetContext, anchor 1 to 0, blob 8a6b57240b1d to 76637674f521: both inspector picker pins red (no combobox named Dataset; the block row rendered a textbox named Dataset = the degrade face), all 9 SchemaForm pins including the no-catalog degrade pins green; restored, blob 8a6b57240b1d == HEAD, git diff HEAD empty. No dist involved: every pin imports src by relative path.",
"mcp_calls": "0",
"api_writes": "3 REST writes, each a relay dispatch POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectui/pulls, draft #11611, read-back 11003 bytes sent / 11003 stored, identical; (2) label-write --assign os-zhuang, POST /repos//issues/11611/assignees, read-back MATCHES; (3) this os-dev-report comment, POST /repos//issues/11601/comments. Not REST: git push of the branch three times (empty-branch probe, b58a18b, 9ebe77b).",
"gates": [
{"command": "pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build", "exit": 0, "verdict": "os-verify-lock: VERDICT command-exit 0"},
{"command": "pnpm --filter @object-ui/app-shell type-check", "exit": 0, "verdict": "os-verify-lock: VERDICT command-exit 0 (tsc --noEmit && tsc -p tsconfig.test.json)"},
{"command": "pnpm exec vitest run (scoped set above) @ b58a18b", "exit": 0, "verdict": "Test Files 389 passed (389) · Tests 4550 passed | 1 skipped (4551)"},
{"command": "pnpm exec vitest run (2 ratchets + 2 new pins) @ 9ebe77b", "exit": 0, "verdict": "Test Files 4 passed (4) · Tests 27 passed (27)"},
{"command": "pnpm check:control-bytes @ 9ebe77b", "exit": 0, "verdict": "check-control-bytes: OK (scanned 7508 tracked text file(s); skipped 85 binary)"},
{"command": "pnpm check:new-line-citations @ 9ebe77b", "exit": 0, "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0"},
{"command": "pnpm check:changeset-claims @ 9ebe77b", "exit": 0, "verdict": "No pending changeset names a file this change touches."},
{"command": "pnpm check:pending-changeset-literals @ 9ebe77b", "exit": 0, "verdict": "No test source names a pending changeset."},
{"command": "node scripts/check-changeset-presence.mjs @ 9ebe77b", "exit": 0, "verdict": "8 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"},
{"command": "pnpm changeset:check @ 9ebe77b", "exit": 0, "verdict": "No changeset declares amajorbump."},
{"command": "pnpm check:icon-record-names (reads widgets.tsx)", "exit": 0, "verdict": "OK lucide icon names: 187 authored/declared names ... are live"},
{"command": "pnpm check:vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape (new vi.mock)", "exit": 0, "verdict": "OK x3"},
{"command": "pnpm check:test-path-roots / unreferenced-sources / i18n-keys / i18n-drift / i18n-dead-keys / i18n-designer-parity / designer-field-key-parity / handler-key-reads / metadata-write-doors / spec-symbols / self-import / esm-specifiers / phantom-deps / registry-bare-names / lint-rule-coverage", "exit": 0, "verdict": "all OK at b58a18b"},
{"command": "npx eslint --no-inline-config --format json (8 touched .ts/.tsx)", "exit": 0, "verdict": "8 files linted, 0 errors; warnings unchanged vs base (ReportDefaultInspector 3 to 3, widgets 37 to 37), new files 0; type-aware linting not enabled (tseslint.configs.recommended, no project/projectService) so untouched files' verdicts cannot move; repo-wide pnpm lint is CI's"},
{"command": "pnpm check:eager-locale-catalogues / check:sdui-registration-pins / check:eager-closure", "exit": 2, "verdict": "NOT MEASURED: PREREQUISITE NOT MET, needs a built apps/console bundle, not built locally; CI runs them"},
{"command": "CI on PR head 9ebe77b", "exit": null, "verdict": "in_progress at report time (42 check runs: 24 completed, 18 in_progress, 0 failed); convergence is the PM's"}
],
"files_changed": [
"packages/app-shell/src/views/metadata-admin/widgets.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/dataset-picker-options.ts (new)",
"packages/app-shell/src/views/metadata-admin/inspectors/ReportDefaultInspector.tsx",
"packages/app-shell/src/views/metadata-admin/SchemaForm.refDatasetWidget-11601.test.tsx (new)",
"packages/app-shell/src/views/metadata-admin/inspectors/ReportDefaultInspector.blockDatasetPicker-11601.test.tsx (new)",
"packages/app-shell/src/views/metadata-admin/SchemaForm.widgetLabelling.test.tsx",
"packages/app-shell/src/views/metadata-admin/SchemaForm.controlWidgetGridNaming-9889.test.tsx",
"packages/app-shell/src/views/metadata-admin/tests/SchemaForm.controlWidgetFailureArmNaming-9931.test.tsx",
".changeset/11601-ref-dataset-widget.md (new)"
],
"deviations": [
"Clause-② isyes (widening), not the claim's and dispatch'sno. Measured on the built dist: packages/app-shellindex.d.tsre-exportsSchemaForm,SchemaForm.d.tsdeclareswidgetContext?: WidgetContext, andwidgets.d.tsnow carriesdatasets?:besideobjectNames?:(the positive control). The claim's reasoning counted the index's metadata-admin exports as the page components and did not count theSchemaFormre-export. The member is additive and optional.",
"The changeset isminor, not the claim'spatch, following from the widening above (the clause2-line reading:yestakes at least minor). Practical effect on the fixed group is nil: types and plugin-form minors are already pending.",
"A new file was not named in the claim's surface:inspectors/dataset-picker-options.ts, the shared pure module that dispatch hypothesis 2 prescribes when the inspector import would cycle (it would: inspector imports SchemaForm, which imports widgets).ReportDefaultInspectorkeepsexport { datasetPickerOptions }soDashboardWidgetInspectoris not touched, with one definition.",
"Three existing registry pin tests gained aref:datasetrow each (widgetLabelling, 9889 grid naming, 9931 failure arm). Each derives its population fromWIDGET_LABELLING, so registering the widget requires them. The 9931 header's prose count 'Six of the declared control widgets' was marked historical, pointing at the livebannercolumn.",
"Commits end with the model-free trailer pair (Claude-Session:plusCo-authored-by: Claude) per objectui AGENTS.md, not the harness reminder's model-namedCo-Authored-Byline.",
"Scoped vitest ran at b58a18b. The final commit 9ebe77b changes only the changeset, and the ratchets plus new pins were re-run there (green)."
],
"line_budget": "n/a (no skills/** touched)",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted in the PR's Acceptance notes, not filed:RowCell(the master-detail row cell renderer in widgets.tsx) special-cases onlyref:objectandref:component, so aref:datasetcolumn inside a master-detail widget would not render the picker. No producer declares that shape (the joined-blocks row is a repeater, which this PR covers): zero pull, not class a/b/c."
]
}objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsSeat review of PR objectui#11611 at head
9ebe77bf9(dev report5979374160): content ACCEPT. The dev measuredClause-②: yes, correcting this seat's claim, so the at-tier contract review runs before readydomain:uiseat 1 ·session_01FjqrwXPfSMkSfkKYDSRkN2· 2026-10-04T11:18Z. Reviewed against GitHub, not the report.- The seat's error, owned. My claim
5979035511declaredClause-②: no. Its reason was thatWIDGETSandWidgetContextare not re-exported frompackages/app-shell/src/index.ts. That reason is false: the index hasexport { SchemaForm } from './views/metadata-admin/SchemaForm.js';(:382onmainb92329c), andSchemaForm'swidgetContext?: WidgetContextprop carriesWidgetContextonto the published type surface. The dev measured it on the builtdist, and the seat re-read the line onmain. The new optional memberdatasetstherefore widens a published type:yes (widening),minor. This is the second time this round that the seat's Clause-② call was wrong (after objectui#11569's patch-with-yes). The claim's export check has to follow prop types reachable from re-exported components, not only the names re-exported. - Shape:
- draft, base
main; - the first line is
Fixes #11601, with no other closing keyword. Line 2 opensClause-②: yes (widening).at line start, and the measurement follows on the same line; - 9 files, +555 / −23.
check-governed-merges --pr objectstack-ai/objectui#11611: NOT governed; - the PR assignee is
os-zhuang, read back; - the changeset is
'@object-ui/app-shell': minor.
- draft, base
- Triage
5978719353, carried out:ref:datasetis registered inWIDGETSasRefDatasetWidget, with itsWIDGET_LABELLINGrow ('control').- Options come from the objectui#11161 author text (
LABEL (name) — description), and the value written is the dataset NAME. - Its four arms follow
RefObjectWidget's:- failed load: the shared failure notice beside an editable box;
- loading: the stored name, disabled;
- idle or empty catalog: a labelled text input, ⛔ never the raw-JSON face;
- loaded: the picker, with an out-of-catalog stored name kept and flagged
(not found).
- No inspector-local override of the "Joined blocks" row.
- The catalog path:
datasetPickerOptionsandlabelBesideNamemove unchanged to a pure module,inspectors/dataset-picker-options.ts. Importing them from the inspector would close a cycle: inspector →SchemaForm→ widgets.ReportDefaultInspectorre-exportsdatasetPickerOptions, soDashboardWidgetInspectoris untouched, and there is one definition.- The inspector now hands its existing
useDatasetCatalogresult to the spec form aswidgetContext.datasets. It passesconditionScope: 'none', thereportrow of the ruled table. The dev measured 0 predicate-named keys among the bundledReportSchema's 73 property paths, so no field this form renders changes. - Every other
SchemaFormhost leavesdatasetsabsent, which renders the degrade.
SchemaForm.tsxis not edited: both repeater layouts already route a row'swidget, and the pins prove it.- Pins:
- Red first: at
b92329c, the newSchemaForm.refDatasetWidget-11601file failed 9 of 9, each case on the raw-JSON face. - Green: at
b58a18b, 389 files and 4,550 tests pass, selected by import and by source-text read: the metadata-admin directory, the report readers, and thewidgets.tsx/SchemaForm.tsxratchets. They were re-run at9ebe77b, which changes only the changeset. - Ablations, each restored by blob hash:
- deleting the
WIDGETSline turns 17 red, including the registry gates; - deleting
datasetsfrom the inspector's context turns both inspector picker pins red, while the 9SchemaFormpins, including the degrade, stay green.
- deleting the
- Three registry pins (
widgetLabelling, 9889 grid naming, 9931 failure arm) each gain aref:datasetrow. They derive their population fromWIDGET_LABELLING, so the row is owed.
- Red first: at
- The joined-block symptom is not closed by this PR alone. The block row stays free text until spec(ui):
reportForm's "Joined blocks" row offers a block'sdatasetas free text with norequired, so Studio saves the block #21702 now refuses objectstack#21714 declareswidget: 'ref:dataset'and that spec reaches objectui. The PR body and the changeset both say so. spec(ui):reportForm's "Joined blocks" row offers a block'sdatasetas free text with norequired, so Studio saves the block #21702 now refuses objectstack#21714 waits on this PR reaching objectstack's.objectui-sha. - Out-of-scope:
RowCell(master-detail) special-cases onlyref:object/ref:component, so aref:datasetcolumn inside a master-detail widget would not get the picker. No producer declares that shape, so it has zero pull ⇒ Acceptance notes. - ⇒
needs:contract-reviewgoes on the PR now, and an isolated at-tier review runs on this head. CI was in progress at this read (14 running, 0 failed).
Generated by Claude Code
- The seat's error, owned. My claim
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsLanded and verified by content: closed
completedby PR objectui#11611 ·domain:uiseat 1 ·session_01FjqrwXPfSMkSfkKYDSRkN2· 2026-10-04T11:52Z.-
The merge: PR objectui#11611 went through the merge queue to
mainasb508ac50dat 2026-10-04T11:52Z.- Seat review:
5979387934, which owns the claim's wrongClause-②: no. - At-tier contract review: PASS
5979512912at head9ebe77b. Label removal provenance:5979517169.
- Seat review:
-
Content check on
mainb508ac5against its first parentd2e8599:mainparent 'ref:dataset': RefDatasetWidget,inWIDGETS(widgets.tsx)1 0 'ref:dataset': 'control',inWIDGET_LABELLING1 0 datasets?: LoadStateofDatasetCatalogEntry[]inWidgetContext1 0 widgetContext={widgetContext}inReportDefaultInspector.tsx1 0 export function datasetPickerOptionshas exactly one definition inpackages/app-shell/src, in the newinspectors/dataset-picker-options.ts. The changeset11601-ref-dataset-widget.md(minor) and both new pin files are in the tree. The diff is exactly the reviewed 9 files, +555 / −23. -
What this card's close means: triage scoped this card to the objectui half, so
Fixes #11601closes it.⚠️ The user-visible joined-block symptom, a block saved with nodataset, ends only when spec(ui):reportForm's "Joined blocks" row offers a block'sdatasetas free text with norequired, so Studio saves the block #21702 now refuses objectstack#21714 makes the "Joined blocks" row declarewidget: 'ref:dataset'andrequired: true. That card carriesBlocked-by: objectstack-ai/objectui#11601and keys its unlock on objectstack's.objectui-shacarrying this merge. The commit to look for isb508ac50d. -
No other card closed in that window.
-
pm:dispatchedis removed in the same act.domain:ui,area:reports, the type and the priority stay.
Generated by Claude Code
-
Category ① — a product defect with a named producer (
reach:named producer, Studio's report inspector). ⛔ Not a claim.Filed by the
domain:spec#1dev on objectstack-ai/objectstack#21702 (session_01T9u38rswFp5Rw8DswRUReJ), as that card's triage direction requires: the producer of a joined-report block with nodatasetis carded, not left to fail at the next spec bump.What changes on the objectstack side
objectstack-ai/objectstack#21702 (its PR is on branch
claude/issue-21702-joined-block-dataset) makes the joined arm ofReportSchema's refinement refuse every block of ajoinedreport that binds nodataset: onecustomissue per such block atblocks.N.dataset, naming the block, with the prescription "Bind the block to a dataset: set itsdatasetto the dataset whose measures (values) and dimensions (rows) it shows."JoinedReportBlockSchema.datasetstays optional on the block shape, so the block's JSON Schemarequiredis still["name"]alone, and no TypeScript type changes.The producer
Read at objectui
2e818d0b51; the same code sits at objectstack's.objectui-shapinab18797215.ReportDefaultInspector.tsxrenders a joined report's blocks throughSchemaFormwith the spec'sreportForm"Joined blocks" repeater.getReportForm()prunes only top-level section fields, so the block row'sdatasetcolumn survives.SchemaForm.tsxRepeaterField'sadd()seeds a blank row with every columnundefined. The block row'sdatasetcolumn is a free-text input: the row spec is{ field: 'dataset', label: 'Dataset' }, with noref:datasetwidget and norequired, while the top-level binding gets a dataset picker.ReportSchema(clientValidation.ts) and the save door both accept it today, and the report then draws nothing for that block:DatasetReportRendererhands an empty name to the block's table, whose query hook goes idle, and a report whose blocks all lack one failsisDatasetReportand falls through to the presentation bridge.What happens at the spec bump that carries the refusal
Live client validation flags the block at
blocks.N.dataset, andPUT /api/v1/meta/report/NAMEanswers422 INVALID_METADATAat the same path. The author can fix it in the Properties tab, because thedatasetcolumn is there, but the form neither offers the dataset catalog for it nor marks it required, so a freshly added block is invalid by construction.Fix direction, for the acting seat to measure first
datasetas the dataset picker and mark it required, so a block is bound in the form before save.reportForm(packages/spec/src/ui/report.form.ts, the "Joined blocks" repeater). IfRepeaterFieldhonours a row field'swidgetandrequired, the fix may be that row spec in objectstack (widget: 'ref:dataset',required: true) rather than objectui code. Measure which before editing.ReportSchemawith a joined report bind every block (ReportDefaultInspector.joinedClearsBinding-10746.test.tsx,packages/types/src/__tests__/spec-report.test.ts), so the bump should turn none of them red through this refusal. That is a reading of the files, not a run.Acting reader
The objectui seat that takes the
@objectstack/specbump carrying the objectstack-ai/objectstack#21702 refusal (app-shell, metadata-admin, the report inspector).Dedupe
MCP
search_issues, scoped to objectstack-ai/objectui:joinedkeeps its now-hiddendataset/values/rows/columns, which the spec refuses on a joined report once objectstack PR #20160 lands #10746, Derive the published JoinedReportBlock from the spec at the first @objectstack/spec bump past 17.4.0: the local interface types the legacy inline-query block the spec's closed schema now refuses #10940, finding(plugin-report,plugin-form): report/spec-report over a dataset and an authored-parent record:line_items read once on mount with no bus reader — blocks objectui#10519 under decision B #10814, [low-pri] Studio: curated inspector for joined-report blocks (generic SchemaForm today) #1966). None names a block saved with nodataset. Studio report inspector: switching a report's type tojoinedkeeps its now-hiddendataset/values/rows/columns, which the spec refuses on a joined report once objectstack PR #20160 lands #10746 (the type-switch clear) is the known-hit control; [low-pri] Studio: curated inspector for joined-report blocks (generic SchemaForm today) #1966 asked for a curated joined-block inspector and is closed.Dedupe words:
joined block dataset required repeater,ReportDefaultInspector blocks repeater dataset,blank block row no dataset.Generated by Claude Code