Repository navigation
feat(spec)!: addRecord says what renders — enabled required, position top, mode/formView retired - #24970
Conversation
… top, mode/formView retired (WIP) Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…drecord-retire-mode-formview
📓 Docs Drift CheckThis PR changes 3 package(s): 1 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 — 144 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 1fe2d6a94e12ed4f6b9c54c1de3080cfa8983af1 && git checkout 1fe2d6a94e12ed4f6b9c54c1de3080cfa8983af1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6440cf16334e1c8106dfdb31d87b6ca728d176c2 fc643e459f6327a3840106256a3eb3a6f575a800 && git checkout -B drift-repro 6440cf16334e1c8106dfdb31d87b6ca728d176c2 && git merge --no-ff fc643e459f6327a3840106256a3eb3a6f575a800
node scripts/docs-audit/affected-docs.mjs --json 6440cf16334e1c8106dfdb31d87b6ca728d176c2
|
…drecord-retire-mode-formview
…cord composite's four new rows Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Read against: card #24692 (body; ruling 6281834942 letter B′ items 1–6; seat-2 hold 6282077441; the 甲 note 6292027850; dispatch 6296388083; dev reports 6299365608 and 6303362402), the standing ruling #6015 comment 6292005854 (「甲」), the PR body, its 37-file list and the three-dot diff ① Derived judgmentsEvery accept-set and public-surface change, named against the ruling:
The
Also read, nothing wrong found: the ② Semver level
③ Boundary flagsGate verdicts on this head (the check-runs ARE the verdicts). 42 check-runs on Dev flag 1 — Dev flag 2 / the landing hazard — objectui
Out-of-scope / remaining items from the dev report, each answered or escalated:
Implemented-by: VERDICT: PASS |
Closes #24692
Clause-②: yes (narrowing:
mode/formViewretire through ADR-0087 drop conversions;enabledbecomes required)A list's
addRecordblock now says what the renderer draws.enabledis required with no default,positiondefaults totop, andmode/formVieware retired through thespec-property-retirementkit. It ships in 18.x under the standing ruling for breaking narrowings after GA (#6015, comment 6292005854, 「甲」), because ADR-0087 conversions cover every body that parsed under 18.0.The ruling this implements (comment 6281834942, letter B′, items 1–5 verbatim)
What changed
Schema (
packages/spec/src/ui/view.zod.ts,AddRecordConfigSchema). One def serves every door:ListViewSchema,ObjectListViewSchema(an object's or a container'slistViews),InterfacePageConfigSchema(a list page'sinterfaceConfig) and the pagelist-viewnode's props row.enabledisz.boolean()with no default. If the key is omitted, the parse refuses with a prescription that names the key and says how to fix it.positiondefaults totop. The valuestop/bottom/bothare unchanged. I checked the renderer at objectui origin/main and at the pinned sha616df6598b:ListView.tsx#resolveAddRecordPlacementmaps an absent position to top, andshowAddRecordneedsenabled === true.modeandformViewareretiredKey()tombstones. Authoring either key is atscerror and also a parse error that carries the prescription.ADR-0087. There are two D2 conversions, both retired from the load path with
retiredAfter: '18.0.0'.stack.views[]in all three persisted spellings,objects[].listViews.*,pages[].interfaceConfigand every pagelist-viewnode.add-record-mode-form-view-removedstrips both keys and emits one notice per key.add-record-enabled-defaultedwritesenabled: trueonto a block that omitsenabled. An explicit value is never touched.RETIRED_KEYS_BY_MAJOR[18]gainsui/AddRecordConfig:modeandui/AddRecordConfig:formView.add-record-mode-form-view-retiredandadd-record-enabled-required. Each has its own step-18 rationale fragment.DEFAULT_CHANGES_BY_MAJOR[18].Ruling item 3 under 「甲」: the
enabledhalf ships with a conversion, not as a warning. I measured whether any producer writesaddRecordwithoutenabled:71696121a6: the showcase's two blocks and the lint fixture all writeenabled: true;addRecord: { enabled: true };The measured population is zero, so the conversion is sound. It is lossless against the contract, because it writes the value the 18.0 parse already produced. It is not lossless in pixels, and the changeset says so: a stored block that omitted
enableddrew no button, and once converted it draws the one it declared. No 19.0 refusal card is needed.Forms. In
view.form.tsandpage.form.ts, theaddRecordcomposites now listenabledandpositionexplicitly. The new nested labels are translated in the three locales.Liveness ledger. The
liveness/view.jsonaddRecordrow records the removal. The sub-keys are one drill level below a recorded undrilled container, so no row is added or removed. The README residue line is updated.Producers and docs.
contact.view.tsandactive-projects.page.ts, and the lint fixtureshowcase-shape.fixtures.ts, dropmode/formView.content/docs/ui/create-vs-edit-form.mdxstates the convention (formViews.createwhen declared, elseform/formViews.default) and names no binding.content/docs/ui/views.mdxdropsaddRecord.formViewfrom where a named form is served and states thecreateconvention.@objectstack/lint:os explain list-view-field-unknownand one docblock no longer nameaddRecord.formView.lintViewRefsnever read it.content/docs/references/are regenerated.Tests.
packages/spec/src/ui/add-record-config-retirement.test.ts, in the repo project. It covers every door, the prescriptions, thetscchannel, the conversions over stored view, page and object rows, idempotence, load-path retirement, the ledger rows, the forms, and a tree-scoped absence pin over the five declared roots.retired-key-removal-version.pin.test.tsjoins both new conversions.view.test.ts/page.test.tspins onmodeand thebottomdefault are rewritten.Not in this PR
p1-spec-alignment.test.ts:189parity row (modedefaultinline) will go red when objectui's pin takes this spec release, and ruling item 4 says that row changes then. No objectui source writesmodeorformViewat the pin (git grepat616df6598b).content/docs/releases/is untouched.Acceptance notes
active-projects.page.tssetsuserActions.addRecordForm: falsenext toaddRecord: { enabled: true }. objectui'sListViewwithholds the Add button onaddRecordForm === false, so that page probably shows no Add button, even though its comment says it shows one. I only read this from the code and did not reproduce it in a browser, so it is not filed. Carrier: none.position: 'bottom'into built artifacts that carried anaddRecordblock. Those artifacts keepbottomexplicitly, so nothing moves on screen for them.Verification (final head
a05f141642, after merging origin/main)pnpm --filter @objectstack/spec buildandcheck:generated:✓ All 14 generated artifacts are up to date.pnpm --filter @objectstack/spec test:Test Files 703 passed (703),Tests 21369 passed | 1 todo.pnpm --filter @objectstack/spec test:repo:72 passed (72),1236 passed.pnpm --filter @objectstack/spec typecheck: exit 0.pnpm --filter @objectstack/lint typecheck: exit 0.pnpm --filter @objectstack/lint test:151 passed (151),7013 passed.&&chain under the verify lock, which reportedVERDICT command-exit 0.objectstack validateprinted✓ Validation passed, andtsc --noEmitexited 0.check-adr-0087-registration: registered, 4 ids new here.check:i18n: in sync.check:i18n-coverage: none new.check:cross-package-test-inputs,check:nul-bytesandcheck:doc-authoring: green.dispatch-gatesderives were run on the final heada05f141642, and every one exited 0.--ranreconciles:120 run, 0 NOT-MEASURED.formView: 'create'back intocontact.view.ts(ablation-replace: mutation landed, blob changed) turned the pin red,1 failed | 34 passed, namingexamples/app-showcase/src/ui/views/contact.view.ts. The restore was verified: the blob equals HEAD andgit diff HEADis empty.pnpm lint(repo-wide eslint) is NOT MEASURED locally and left to CI.Generated by Claude Code