Repository navigation
feat(spec)!: retire the page kind jsx — refused naming html, its D2 conversion leaves the load path (F5-jsx of #23543) - #23638
Conversation
…onversion leaves the load path (WIP) Claude-Session: https://claude.ai/code/session_01DdfPiKZUYAduc1ERcEvDso Co-authored-by: Claude <noreply@anthropic.com>
…t for the jsx retirement Claude-Session: https://claude.ai/code/session_01DdfPiKZUYAduc1ERcEvDso Co-authored-by: Claude <noreply@anthropic.com>
…piled kind Claude-Session: https://claude.ai/code/session_01DdfPiKZUYAduc1ERcEvDso Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DdfPiKZUYAduc1ERcEvDso Co-authored-by: Claude <noreply@anthropic.com>
…tire-jsx-page-kind
📓 Docs Drift CheckThis PR changes 5 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 149 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 19a19bd1898e24742059dea73e169fa3fabb9cf0 && git checkout 19a19bd1898e24742059dea73e169fa3fabb9cf0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 23e689dc7d1de961a168997685295ddf009d5c2c 2e1b65d066242d602f855ba62d5e4f247a09871b && git checkout -B drift-repro 23e689dc7d1de961a168997685295ddf009d5c2c && git merge --no-ff 2e1b65d066242d602f855ba62d5e4f247a09871b
node scripts/docs-audit/affected-docs.mjs --json 23e689dc7d1de961a168997685295ddf009d5c2c
|
席位核对 — ACCEPT ·
|
Contract reviewServed-tier: Family F5-jsx of ruling 6182001882 (items 5 and 7) on card #23543, PR #23638, read at 2026-10-15T08:32Z. Inputs: the card body and its thirteen comments, the PR body and its 43-file list, the net diff against Gate verdicts on this head (second reading): 44 check-runs, 33 Governance: none of the 43 paths is a governed surface ( ① Derived judgmentsAccept-set changes (each narrows what an author may write):
Public-surface changes: no new export ( ② Semver level
③ Boundary flagsDev
Dev
Dev
Residual text (not in the report), to ride the FAIL remedy push:
Report corrections, not flags: the dev report says 44 files; the PR has 43 (its own enumeration lists 43). The report read 24 check-runs with 22 in progress; at this record's second reading there are 44, with 3 in progress, named above. Premise re-read on the head: no Remedy for the FAIL (one push; the record is re-rendered on the new head): add Implemented-by: VERDICT: FAIL |
…the jsx-retirement prose names the doors that parse a page Claude-Session: https://claude.ai/code/session_01DdfPiKZUYAduc1ERcEvDso Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Family F5-jsx of ruling 6182001882 (items 5 and 7) on card #23543, PR #23638, second record, read at 2026-10-15T08:50Z. Inputs: the card body and its fourteen comments (the ruling, the F5-jsx claim 6185261661, both dev reports 6187521557 and 6188089228), the PR body and its 43-file list, the PR's three comments (the drift check, the seat review 6187645640 and the earlier record 6187937404 on Gate verdicts on this head (fourth reading): 39 check-runs, 27 Governance: none of the 43 paths is a governed surface ( ① Derived judgmentsAccept-set changes, each a narrowing of what an author may write:
Public-surface changes: no new export ( ② Semver level
③ Boundary flagsDev
Dev
Dev
Residual text from the earlier record (items 8, 9 and 10): all three answered on this head by ① judgment 10 (b), (c) and (d); nothing further is owed. No new residue was found on the head beyond the objectui-dependent note in item 5. Report corrections, not flags: the first dev report says 44 files; the PR has 43. The patch-round report's gate readings are the dev's own and are not inputs here; the check-runs above are. Premise re-read on the head: no Landing terms are the seat's (6187645640 item 8): this record, then every check green — the seven Implemented-by: VERDICT: PASS |
… and move the console sample to html (objectui#12464) @objectstack/spec 18 refuses the page kind jsx (objectstack-ai/objectstack#23638). PageNodeSchema.kind drops 'jsx'; the console's sdui-jsx-preview sample authors kind 'html'. The page renderer keeps its 'jsx' arm for stored rows until the resolved spec carries the retirement; it reads kind as a widened wire value so that arm still compiles against the narrowed type. Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB Co-authored-by: Claude <noreply@anthropic.com>
Part of #23543
Clause-②: yes (narrowing)
This PR lands family F5-jsx of ruling
6182001882(item 5) only. F3, F2, F4 and F5-http stay on #23543, one PR each, in the ruled order. #23543 remains open.What
Ruling F5-jsx A:
'jsx'retires fromPageSchema.kindthroughenumWithRetiredValuesnaminghtml, together with theCOMPILED_PAGE_KINDSbranch; the entry retires.PageSchema.kindis nowenumWithRetiredValues(['full', 'slotted', 'html', 'react'], PAGE_KIND_RETIRED_GUIDANCE)(packages/spec/src/ui/page.zod.ts). An authoredkind: 'jsx'failstsc(it leftz.input) and, at parse, gets the prescription in place of zod's anonymous enum error: "Pagekind: 'jsx'was removed in @objectstack/spec 18 (ADR-0087 D2) … Usekind: 'html'." AtdefineStackthat isSTACK_SCHEMA_INVALID/ 422 with one issue atpages.0.kind. The guidance carries noos migrate metasentence on purpose: the rename belongs to protocol 11, belowMIGRATION_SUPPORT_FLOOR, so the tool lists no edit for it (theflow-node-crud-filter-aliasprecedent).COMPILED_PAGE_KINDSis['html'].checkPageSourceCompleteness's source kinds arehtml/react. ThecheckPageRequiresKindrefusal no longer namesjsx.page-kind-jsx-to-htmlgetsretiredFromLoadPath: trueandretiredAfter: '17.7.0'(the stamp PR feat(spec)!: retire seven overdue ADR-0087 D2 conversions from the load path at 18; record why eight stay #23523 and PR feat(spec)!: retire the datasource driver spelling mongo — refused naming mongodb, its D2 conversion leaves the load path (F1 of #23543) #23600 used). Its docblock's "stays on the load path — a recorded verdict" paragraph is rewritten as the retirement record.18.page-kind-jsx-retired(semantic, step 18) states the hand edit. It carries noconversionIds: no migration step replays a protocol-11 conversion, andmigrations.test.tsrefuses an id no step replays.conversions.test.tsmoves the entry to the retired list. A newdescribe('page-kind-jsx-to-html')pins three claims: a storedjsxrow still converges tohtmland the converted row parses; the authoring funnel no longer rewrites an authoredjsx; anddefineStackrefuses it withSTACK_SCHEMA_INVALID/ 422 atpages.0.kind, message first sentence asserted, withhtmland a typo (htm) as controls. The removal-version pin'sJOINgains the row.Mechanism assumptions, measured
applyConversionsToStoredItem('page', …)runs withincludeRetired: true. The stored-row readers aremetadata-protocolconvertStoredItemDetailed(protocol.ts) andmetadatadatabase-loader.ts, so asys_metadatapage row written asjsxreachesPageSchemaashtml. This is pinned inconversions.test.ts. The metadata save door does not replay page conversions (itsapplyConversionsToFlowfallback is for flows only), so a page saved withkind: 'jsx'is refused 422. The D3 entry and the changeset both say so. No credential-redactor-style reader judges a raw page body by kind, so F1's "keep it on a contract face" situation does not arise here.'jsx'readers. Re-taken on this tree withgit grep(non-testpackages/*/src). Each branch is now unreachable because the parse refuses the kind, so each is deleted; none keeps consumer-side tolerance:metadata-protocol/src/runtime-authoring-gate.ts: the localCOMPILED_PAGE_KINDSis['html'];cli/src/utils/sdui-manifest.ts:checkedPageKeysreadshtmlonly;cli/src/utils/i18n-extract.ts: comments only;lint/src/page-walk.ts:SOURCE_AUTHORED_KINDSishtml/react;lint/src/validate-jsx-pages.ts: readshtmlonly;lint/src/validate-page-source-styling.ts: readshtml/react;lint/src/authoring-rules.ts,rule-explanations.ts,validate-translation-references.ts: comment and explanation text;spec/src/ui/page.form.ts: thesourcefield'svisibleWhenand help text. The generateden.metadata-forms.generated.tswas regenerated withnode scripts/check-i18n-bundles.mjs --write, and the three translated help-text values were edited by hand to drop the alias.registry.ts's docblock is rewritten as the retirement record (as above).content/docs/references/ui/page.mdx(check:generated --fix) anden.metadata-forms.generated.ts.check:generatedreported no change toapi-surface/,export-origins/,authorable-surface/or the strictness ledger: an enum-value narrowing is byte-invisible to them.jsxwas the "live conversion" subject of several suites (assumption 5's question). Each now drivesflow-node-http-callout-rename, the live entry that retires last in the ruled order:lint-conversion-notices.e2e,build-json-failure-conversions.e2eandvalidate-json-failure-conversions.e2e;stack-conversions-record.test.ts(the "two conversions" case) andconversions.test.ts(copy-on-write,normalizeStackInput);artifact-forward-conversion.test.tsFIRING CONTROL 1, which drivespage-component-visibility-to-visibleWhen.Fixture triage (pin sweep, whole repo:
kind: 'jsx'and the conversion id)html(they used the alias): lintvalidate-jsx-pages.test.ts,page-walk-conversion-parity.test.tsandvalidate-action-name-refs.test.ts; clisdui-manifest.test.ts(two fixtures).object-refinement-check-exports.test.ts(twojsxrows) andpage-print.test.ts(one row);page-requires-compiled-kinds.test.ts, whose vocabulary pin now reads four kinds and one compiled kind;page-walk.test.ts,validate-page-source-styling.test.tsandvalidate-jsx-pages.test.ts, where thejsxrows now assert the rule does not read the retired kind.protocol.batch-verb-driver-text.test.tsseeds storedjsxrows. That is still a non-canonical stored row that the stored pass rewrites, so only its comment changed.format.conversion-notice.test.tsformats a synthetic notice.content/docs/ui/pages.mdxandreact-pages.mdx;liveness/page.json(therequiresrow's evidence);18.page-requires-non-compiled-kind-refusedand18.ui-html-page-div-refused, and the step-18 rationale paragraph forpage-requires-non-compiled-kind-refused(registry.ts.template).Changeset
.changeset/23543-f5-jsx-retire-page-kind-jsx.md:@objectstack/specminor;metadata-protocol,cliandlintpatch.Clause-②: yes (narrowing). It names the refused spelling, the prescription (html), and how stored rows keep loading.registered page-kind-jsx-retired.Verification
Head before the
mainmerge:5bf25840. Mergedorigin/mainf7cd580bthroughscripts/pm/os-regen-merge.sh(no conflicts;check:generatedthen read "All 14 generated artifacts are up to date").831a9fa8: spec (src/conversions,src/migrations,src/ui,src/shared,stack-conversions-record) 195 files / 6977 passed; metadata-core 18 / 719 passed; metadata-protocol 236 files / 20550 passed, 19 skipped (closure rebuilt first). The readings below were taken on5bf25840, before the merge;main's incoming commits touched none of this diff's files.@objectstack/spec: full suite 740 files, 21785 passed (the one failing file,page-requires-compiled-kinds.test.ts, was then fixed and re-run green with the conversion, pin and migration suites: 8 files / 567 passed);typecheckexit 0;check:generatedall 14 up to date.@objectstack/lint: 139 files / 6771 passed; typecheck exit 0.@objectstack/metadata-protocol: 237 files / 28429 passed, 19 skipped; typecheck exit 0.@objectstack/metadata-core: 18 files / 701 passed; typecheck exit 0.@objectstack/cli: unit tier 290 files / 4323 passed; typecheck exit 0. The three edited nightly-tier e2e suites (OS_TEST_TIERS=nightly): 3 files / 35 passed.pnpm check:i18n: OK, all bundles in sync.dispatch-gates.mjs --commandsderived 118 commands. Each was run one by one, with its exit code captured before any pipe.--ran(with exit codes): "118 derived famil(ies) accounted for — 116 run, 2 NOT-MEASURED".check-plugin-teardown-shape --self-test(shallow clone) andcheck:dual-build-cjs-loads(full build absent).check:platform-checklistexits 1 on symbol anchors inmetadata-protocol/src/protocol.tsandservice-storage(countable,canEdit,anonymousFormIntake*,envWideRawViewRows). This diff touches neither file; it is the samemain-tree red F1's report recorded.check-adr-0087-registration,check:spec-changes,check:upgrade-guide,check:docs,check:liveness,check:doc-authoring,check:nul-bytes,check:i18n-stale-fill.scripts/ablation-replace.mjs). The kind enum was spelled back as a barez.enum([...four kinds]), which keeps the narrowing and drops the prescription.4ceaa5dffafc→35fbaad1835c.defineStackrefusal case inconversions.test.tsand thepage-kind-jsx-to-htmlrow ofretired-key-removal-version.pin.test.ts(direction: red).git diff HEADempty. Spec tests resolvesrc, so no dist leg applies.Acceptance notes
major, Changesets pre mode onnext, and the two gate edits (the maintainer's ruling on #12030), after #12030 lands objectui#12334). The ruling sized objectui's half as "one line" (the console sampleapps/console/src/sdui-jsx-preview.tsx:87). At the pinned.objectui-shab9814b334there are three more readers:packages/types/src/layout.ts:1795declaresPageNodeSchema.kind?: 'full' | 'slotted' | 'html' | 'jsx' | 'react'on an interface that extends the spec'sPagewith some keys omitted, withkindnot inPAGE_SPEC_EXCLUDED. Once objectui builds against this spec, that override no longer narrows the spec'skind(an "incorrectly extends" error, by reading; not compiled here).packages/components/src/renderers/layout/page.tsx:611keeps akind === 'jsx'branch.typeszod mirror (SpecPageFieldsfromSpecPageSchema.shape) will refusejsxat runtime.scripts/build-console.shinjects this tree's spec only at the vite bundle step, and objectui's owntscresolves the spec from objectui's lockfile.skills/objectstack-ui/rules/pages.md:138still says "The legacy valuekind:'jsx'is a deprecated alias forkind:'html'." That file is a governed (Tier H) surface, so it is left for a separate skills-only PR rather than making this one Tier H.flow-node-http-callout-rename, F4's two visibility entries, F3's two lifts andretry-policy-converged. The suites re-pointed here rideflow-node-http-callout-rename, which retires last (F5-http). That PR inherits the "no live conversion left" question F1's report recorded.Generated by Claude Code