Uh oh!
There was an error while loading. Please reload this page.
fix(sdui-parser): braced non-JSON values draw an inert-expression warning instead of vanishing silently - #6613
Merged
Conversation
…ning instead of vanishing silently
A braced attribute value that fails JSON materialization compiles to the
parser's deferred { $expr } marker, and nothing downstream evaluates that
marker — the html tier parses, never executes (ADR-0080), and no renderer
consumes $expr. The value reached the renderer as an opaque object, defensive
non-array reads degraded it to 'not declared', and the author's binding
vanished with zero diagnostics anywhere (ADR-0078's prohibited
parsed-but-silently-inert state). validateTree now names it at compile time,
warning severity, with the fix in the message.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Aug 27, 2026
os-sales
marked this pull request as ready for review
August 27, 2026 14:07
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #6598
What the card asked, and what measurement answered
The card's mechanism claim was "
columnsnever reaches the renderer because the registration's declared inputs omit it", with a directive to confirm on the live registration and to report the fork if it is declared. Measured onorigin/main(base 574c33f):list-view, notobject-table. The original report (objectstack-ai/objectstack issue 12649, which this card was moved from) nameslist-viewliterally.object-tablehas no live registration anywhere in this repo — it exists only in sdui-parser test fixtures and one plugin-dashboard test. Theobject-tablespelling entered at triage; the tier.test.ts fixture the card anchored on is synthetic.list-viewregistration declarescolumns({ name: 'columns', type: 'array' }inpackages/plugin-list/src/index.tsx), plusobjectName(required),viewType,filter,sort,options. It declaredcolumnsat the reporter's 17.1.0 too (verified at release commit 620f618). The registration is not systematically short.parse.tskeeps every attribute, andvalidateTreeonly emits warning-severityunknown-propfor undeclared ones. Compile never strips a prop, declared or not.The real mechanism — the fork the card authorised
interpretBracematerializes strict-JSON braced values only. Anything else — the single-quoted array every JSX author writes (columns={['name','amount']}), unquoted object keys (columns={[{field:"name"}]}), any JS expression — compiles to the deferred{ $expr }marker, and nothing downstream evaluates that marker: this tier parses, never executes (ADR-0080), and a repo-wide grep finds zero$exprconsumers outside sdui-parser. The marker reaches the renderer as an opaque object; ListView's defensive non-array read degrades it to "no declared columns"; rows still fetch viaobjectName. Result: row count + toolbar + index column, zero data columns, zero diagnostics anywhere — ADR-0078's prohibited parsed-but-silently-inert state, and exactly the production symptom.Live-path reproduction (compile against the registry-built manifest exactly as
page.tsxbuilds it, rendered through SchemaRenderer with the real plugin-list registration, a stubobject-gridrecording the handoff):columns={["name","amount"]}(strict JSON): zero diagnostics, grid receives['name','amount']— the pipeline is lossless for JSON spellings on main and at 17.2.0 (ca58e45).columns={['name','amount']}(single quotes): zero diagnostics, tree carries{ $expr: "['name','amount']" }, grid receivescolumns: [], rows still fetched — the silent vanish.columns='["name","amount"]'(JSON-string form): warning-severity type-mismatch at compile,[]at the grid — silent at runtime.aggregate(the maintainer's follow-up): kept in the tree, drawsunknown-prop(warning) at compile, read by no renderer — its loud half already exists; nothing to declare (the grid vocabulary isaggregations).kind:'react'folds real evaluated JS props into the schema node (react-page.tsx scope wrappers), so the same spelling works there — which is why the reporter saw the tier split.Version archaeology: at 17.1.0 (620f618) the registry path had the pre-#3144 defect (no data-source adapter reached a bare-registered
list-viewat all), so the production environment was running a later console bundle; from 17.2.0 through main the JSON spellings work and the non-JSON spellings vanish silently. The$exprhole exists at every version measured.The fix (deliberately the loud half only)
validateTreenow emits a warning-severityinert-expressiondiagnostic when a declared input's value is the$exprmarker, message carrying the fix (write the value as JSON, double-quoted strings and keys). Warning, not error, per the objectui#5709 posture for inert authored keys: pages keep compiling and rendering exactly as before — the silence is what changed. Pinned bypackages/sdui-parser/src/__tests__/inert-expression-6598.test.ts, including "strict-JSON spellings stay diagnostic-free".Reverse verification: with
validate.tsreverted to base (fix committed first, revert via git checkout from base, restore via git checkout from HEAD,git diff HEADempty after), the three inert-expression pins go red (3 failed, 2 passed) and return green on the restored tree (5 passed).Deliberately NOT decided here — maintainer contract decisions
Each of these changes what the html tier accepts, so none is taken unilaterally; they are escalated in the dev report on the issue:
inert-expressionto error severity (would flip compile accept/reject for pages carrying inert expressions today).$expronstyle(BASE_PROPS) is equally inert and currently skipped before the input lookup.sdui-parserwhose save gate runs parse-only (no manifest wired), so this diagnostic reaches it only when that repo syncs its copy and wires the manifest; grammar decisions must move both copies in lockstep or save-vs-render dialects split.Out of scope, untouched: issue 6458 remains open (the four-key adjudication on ObjectGrid authored-column reads —
format/options/appearance/essentialnot touched; the new columnReadBoundary guard from PR 6587 is unaffected: no plugin-grid file changed). Issues 5905 and 6150 remain open; the manifest-wiring gap above is 5905-adjacent context, not addressed here.Gates (all at HEAD f62a923, after the final commit)
pnpm exec vitest run packages/sdui-parser/— 10 files, 82 passed (includes the 5 new pins).pnpm --filter @object-ui/sdui-parser run type-check— clean;tsc -p tsconfig.test.json --listFilesconfirms the new test file is in the checked closure (1 hit).pnpm --filter @object-ui/sdui-parser run lint— 0 errors, 7 pre-existing warnings all in untouched files (render.test.tsx, verify.ts); the changed files lint 0/0. Narrowing note: repo lint isturbo run lint(per-package eslint units); the changed package's whole unit ran; the diff touches no other package's files.node scripts/check-control-bytes.mjs— OK (5463 files)..changeset/6598-inert-expression-warning.md(@object-ui/sdui-parser: minor; no major, per repo version policy).Generated by Claude Code
Generated by Claude Code
Generated by Claude Code