Filed unassigned and unlabelled by the objectui domain:ui dev seat implementing objectui#6614 (PM session 8ca04858-ea8e-5b85-9182-de59aa49e00c). Grading and routing are triage's. ⛔ This is the record of a missing carrier, not a request to land the port blind — read the ordering analysis before scheduling it.
What is missing
#12719 established the invariant both copies of the parser owe each other:
Invariant: both copies byte-agree on the accepted grammar and on diagnostic codes.
It carried two obligations, and deliberately landed only one:
| half | state |
|---|
the inert-expressiondiagnostic port | ✅ landed — PR #12811, card closed 2026-08-27 |
| the grammar widening, if objectui#6614 ruled to widen | ⛔ withheld, in the card's own words: "porting a grammar change before that card is ruled would be premature" |
objectui#6614 has since been ruled — maintainer, 2026-08-28, Q1-A adopted whole. The grammar widening is now decided, and the card that was holding its port is closed. So the obligation is live and its carrier is not.
Measured, with a positive control: a search_issues over this repo for the port's own vocabulary returns zero open cards; the same query shape without the is:open filter returns exactly #12719 and #12814, both closed. The zero is real, not a mis-aimed probe.
What the port is
objectui landed the objectui side today (objectui PR for objectui#6614, branch claude/issue-6614-brace-literal-subset). interpretBrace there now materialises the JS literal subset — exactly two widenings over JSON:
- single-quoted strings, in value position and in key position;
- unquoted identifier object keys.
Everything else JSON refuses is still refused and still becomes { $expr }: trailing commas, comments, array holes, spreads, undefined / NaN / Infinity, +1 / .5 / 1. / 0x1f, template literals, and every genuine expression. JSON.parse still runs first and untouched, so strict-JSON behaviour is invariant by construction.
⚠️ One detail the port must not drop: an authored __proto__ key is written as an own data property (what JSON.parse gives), never through the prototype setter. A plain obj[key] = value in the unquoted-key path would hand untrusted page source a prototype-pollution lever the strict-JSON path never had.
The objectui side also reworded the inert-expression message, because the old text advised "write it as JSON (double-quoted strings and keys)" and named a now-legal spelling as the wrong one. Diagnostic codes are unchanged; the message string is not byte-equal any more, which is itself part of what #12719's invariant covers.
⚠️ Ordering — this is NOT urgent, and the reason matters
The window opened by objectui landing first is benign, and it is benign in a way that reverses if this repo goes first:
⇒ objectui-first (what happened): a page saves exactly as it does today and now renders correctly. Nothing that saves today stops saving.
⇒ objectstack-first would have been the dangerous order: the save gate materialises while the renderer still defers, so a page saves clean and renders inert — precisely the "saves clean, renders inert" failure #12719 names, and precisely today's objectui#6598 production defect.
This is also the direction #12814 took: objectui#3832 ruled and landed on the objectui copy, and this repo ported after (PR #12857).
So the cost of the gap is drift, not breakage — but drift with nothing watching it: there is no mechanical parity gate in either repo (33 check-* scripts in objectui, none comparing the copies), so the invariant is documentary only. That is the argument for a card rather than for haste.
Refs: #12719 (the invariant and the withheld half) · #12814 and PR #12857 (the lockstep-port pattern, same direction) · #12811 (the diagnostic half) · objectui#6614 (the ruling) · objectui#6598 (the production defect) · ADR-0078 · ADR-0080.
Filed unassigned and unlabelled by the objectui
domain:uidev seat implementing objectui#6614 (PM session8ca04858-ea8e-5b85-9182-de59aa49e00c). Grading and routing are triage's. ⛔ This is the record of a missing carrier, not a request to land the port blind — read the ordering analysis before scheduling it.What is missing
#12719 established the invariant both copies of the parser owe each other:
It carried two obligations, and deliberately landed only one:
inert-expressiondiagnostic portobjectui#6614 has since been ruled — maintainer, 2026-08-28, Q1-A adopted whole. The grammar widening is now decided, and the card that was holding its port is closed. So the obligation is live and its carrier is not.
Measured, with a positive control: a
search_issuesover this repo for the port's own vocabulary returns zero open cards; the same query shape without theis:openfilter returns exactly #12719 and #12814, both closed. The zero is real, not a mis-aimed probe.What the port is
objectui landed the objectui side today (objectui PR for objectui#6614, branch
claude/issue-6614-brace-literal-subset).interpretBracethere now materialises the JS literal subset — exactly two widenings over JSON:Everything else JSON refuses is still refused and still becomes
{ $expr }: trailing commas, comments, array holes, spreads,undefined/NaN/Infinity,+1/.5/1./0x1f, template literals, and every genuine expression.JSON.parsestill runs first and untouched, so strict-JSON behaviour is invariant by construction.__proto__key is written as an own data property (whatJSON.parsegives), never through the prototype setter. A plainobj[key] = valuein the unquoted-key path would hand untrusted page source a prototype-pollution lever the strict-JSON path never had.The objectui side also reworded the
inert-expressionmessage, because the old text advised "write it as JSON (double-quoted strings and keys)" and named a now-legal spelling as the wrong one. Diagnostic codes are unchanged; the message string is not byte-equal any more, which is itself part of what #12719's invariant covers.The window opened by objectui landing first is benign, and it is benign in a way that reverses if this repo goes first:
interpretBraceemits no diagnostic in either dialect — it silently materialises or silently defers. The save gate can only observe the difference throughvalidateTree'sinert-expression.validate-jsx-pagesruns parse-only today (resolveSduiManifest()returns undefined; nosdui.manifest.jsonis tracked here — 0 hits against 80 forpackage.jsonas the control), sovalidateTreeis not reached from the production gate at all. Measured on The twosdui-parsercopies still disagree on diagnostic codes after theinert-expressionport —dashboard-widget-optionsand the union-armtype-mismatchhave never been ported #12810 / Port the union-armtype-mismatchcheck into the hoistedsdui-parser— the half of the lockstep debt that CHANGES what this copy accepts and rejects #12814, re-confirmed here.inert-expressionat warning. The worst case is stale advice, never a rejection.⇒ objectui-first (what happened): a page saves exactly as it does today and now renders correctly. Nothing that saves today stops saving.
⇒ objectstack-first would have been the dangerous order: the save gate materialises while the renderer still defers, so a page saves clean and renders inert — precisely the "saves clean, renders inert" failure #12719 names, and precisely today's objectui#6598 production defect.
This is also the direction #12814 took: objectui#3832 ruled and landed on the objectui copy, and this repo ported after (PR #12857).
So the cost of the gap is drift, not breakage — but drift with nothing watching it: there is no mechanical parity gate in either repo (33
check-*scripts in objectui, none comparing the copies), so the invariant is documentary only. That is the argument for a card rather than for haste.Refs: #12719 (the invariant and the withheld half) · #12814 and PR #12857 (the lockstep-port pattern, same direction) · #12811 (the diagnostic half) · objectui#6614 (the ruling) · objectui#6598 (the production defect) · ADR-0078 · ADR-0080.