…not STRIPS
The `record:details` block said the spec's section object "STRIPS" the extras
`RecordDetailsRenderer` also honours (`title`, `showBorder`, `hideEmpty`) on
parse. Measured on the installed `@objectstack/spec` 17.2.0,
`RecordDetailsProps.safeParse` on a section carrying any of the three returns
`success: false` with `unrecognized_keys` naming the key, against a control
(`columns: 2`) that parses and whose value survives. A stripped key is dropped
in silence and the page still renders; a refused key fails the parse.
The same probe falsifies the neighbouring `record:highlights` claim that the
spec "strips the unknown key on parse without error" for a top-level
`readonly`: `RecordHighlightsProps.safeParse({ fields: [...], readonly: true })`
is refused with `unrecognized_keys: ['readonly']`, against a control
(`layout: 'vertical'`) that parses and survives. Same class, same file, one
sweep — corrected here too.
Comment-only. Every changed line is a `//` line; no declaration, type,
renderer, input or decision moved. The four-party divergence about `hideEmpty`
stays where it is routed (objectui#7129). Context: objectui#7127.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wwHa4aaFybxXrfmfHioDM
Fixes#7127
Comment-only. Every changed line in
packages/plugin-detail/src/index.tsxis a//line — mechanically checked:git diff -U0produces 40 changed lines and 0 that do not match^[+-] //. No declaration, type, renderer, input or decision moved.1. Re-measured at the version installed now — not quoted from the card
@objectstack/spec17.2.0 (root andpackages/plugin-detail/node_modulesboth resolve to 17.2.0; declared range^17.1.0). Probe run from the worktree againstdist/ui/index.mjs:RecordDetailsProps.safeParse({ sections: [{ label, fields, title: 'T' }] })unrecognized_keys: ['title']at pathsections.0showBorder: trueunrecognized_keys: ['showBorder']hideEmpty: trueunrecognized_keys: ['hideEmpty']columns: 2data.sections[0].columns === 2{ label, fields }sectionfieldssurvivesVerbatim refusal message (it recounts the very history the card points at):
So the comment's mechanism was wrong in the direction that matters: a stripped key is dropped in silence and the page still renders; a refused key fails the parse and the document does not validate. The decision the block records — do not publish
title/showBorder/hideEmptyas authorable inputs — is unchanged and is now carried by the stronger reason.2. The self-contradiction: CONFIRMED, with one correction to the card
Confirmed. Both sentences live in the same contiguous
//block on therecord:detailsregistration, six lines apart:layout)Corrected. The card also says the block "even records why the behaviour changed — Until #4001 batch A an undeclared prop was dropped in silence…". That sentence is not in
index.tsx: it is the spec's own refusal message, quoted above, and it is echoed in the sibling test files' header comments (recordDetailsInputs.spec-parity.test.ts:257,recordHighlightsInputs.spec-parity.test.ts:80). Control for that zero:grep -i silenceonindex.tsxdoes hit — lines 74, 209, 265 — just not that sentence.Git-history provenance for "STRIPS is pre-#4001 wording" is NOT MEASURED: this checkout is shallow (
git rev-parse --is-shallow-repository= true; deepened to 525 commits andindex.tsxstill shows only 3 touching commits), sogit log -Scollapses every one of the three phrases onto the graft-boundary commit. The pre-#4001 reading rests on the spec's own message ("the props schema stripped it"), not on history here.3. The sweep — what else in the block asserts spec parse behaviour
All other parse claims in this file were probed at 17.2.0. Three are true and untouched:
layoutis a tombstone the spec "rejects on parse"{ layout: 'auto' }invalid_type, "removed in @objectstack/spec 17.0.0 (#6946, ADR-0087 D2)" — claim truehideFieldsisz.array(z.string()), rejects{name}entries{ hideFields: [{ name: 'phone' }] }['phone']parses — claim trueinlineEdit/showHeaderplain booleans,1/'true'/nullrejected by valueinvalid_type; controlfalseparses — claim trueOne is the same defect, and is fixed here too — the neighbouring
record:highlightsregistration comment (line 562) said the spec "strips the unknown key on parse without error" for a top-levelreadonly:RecordHighlightsProps.safeParse({ fields: ['phone'], readonly: true })unrecognized_keys: ['readonly']{ fields: ['phone'], layout: 'vertical' }layoutsurvivesSame class (a comment certifying spec parse behaviour the spec no longer has), same file, same measurement, and the card's dispatch asked for the sweep to fix same-class staleness and say which was fixed and which was left. Its decision —
readonlyis documented inside thefieldsdescription, never declared as a top-level input — is unchanged.Left alone deliberately: every declaration. The four-party divergence about
hideEmpty(spec refuses /@object-ui/typesviews.ts:230declares / the zod mirror omits /RecordDetailsRendererhonours) is a maintainer decision routed on #7129 and is not resolved here.4. Does any test pin the old wording? No — measured
No test reads
packages/plugin-detail/src/index.tsxas text. The onlyreadFileSync(join(SRC_DIR, …))inplugin-detail's tests targetsrenderers/record-details.tsx. Controls for those zeros: 7 test files in that directory do side-effect-import'../index'(so the edited module is loaded and executed by the green run below), and 204 test files repo-wide usereadFileSync.5. Gates — all run at the final commit
783f04300pnpm exec vitest runon the twoplugin-detailspec-parity files +apps/console/src/__tests__/registry-inputs-spec-parity.test.tsTest Files 3 passed (3)/Tests 131 passed (131); lockVERDICT command-exit 0pnpm exec eslint packages/plugin-detail/src/index.tsx✖ 31 problems (0 errors, 31 warnings)— all 31 pre-existing, on lines 148-243, none touched herenode scripts/check-changeset-presence.mjs(staged first)✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s) … Every one of them has an EMPTY frontmatter — declared as releasing nothing, which is the explicit exemption and a complete answer to this gate.node scripts/check-changeset-no-major.mjs✅ No changeset declares a 'major' bump.node scripts/check-control-bytes.mjs✅ check-control-bytes: OK (scanned 5908 tracked text file(s); skipped 85 binary).Declared narrowing —
pnpm --filter @object-ui/plugin-detail run type-checkis NOT MEASURED, not green. It exits 2 with 21 diagnostics that are allTS2307 Cannot find module '@object-ui/components' / '@object-ui/core' / …plus the implicit-anycascade behind them — an unbuilt dependency closure in a fresh worktree, present before this change and unrelated to it. Rather than spend a shared-box closure build on a diff that changes zero non-comment lines, it is declared unrun: the file is proven to still parse and register by the vitest run above, which imports it.The changeset is empty-frontmatter — this releases nothing.
Generated by Claude Code