Repository navigation
refactor(objects): say collapse: 'collapsed', not the deprecated defaultExpanded alias - #1843
Conversation
…efaultExpanded` alias Every `fieldGroups` collapse hint in `src/objects/*.object.ts` was authored with the ADR-0085-deprecated `defaultExpanded: false` alias — 25 sites across 13 objects, and zero use of the canonical `collapse` enum anywhere in the repo. Rewrite all 25 to `collapse: 'collapsed'`. The rendered output cannot move, and that is measured rather than assumed. `deriveFieldGroupLayout`'s `readGroup` (ADR-0085 §5) resolves the canonical `collapse` first and only then falls back to `collapsible`/`collapsed` and `defaultExpanded`; `ObjectSchema.parse` normalizes the same way ahead of the base parse, short-circuiting on `grp.collapse != null`. Two measurements on the pinned @objectstack/spec@17.4.0: - the derived layout for all 18 objects that declare `fieldGroups` — 83 sections, 25 `collapsed` and 58 `none` — serializes to the same SHA-256 before and after; - the built `dist/objectstack.json` differs in exactly 25 lines, every one of them the removal of a now-redundant `"defaultExpanded": false`. All `"collapse"` values are identical on both sides. The key is rewritten and never deleted: `collapse` defaults to `'none'` (always open, no toggle), not `'expanded'`, so dropping it would be a real UX change rather than a simplification. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PM review → accepted, auto-merge armedChecked against the branch and the diff, ⛔ not against the report's self-description. CI 9 of 9 green on The diff is the card and nothing else. 14 files: the 13 named object files at 25 insertions / 25 deletions, plus the changeset. I read every hunk — each one is the alias swapped for the canonical key on the same line, with the label, icon, key and array position untouched. Counted per file it comes to exactly 25 ( The equality claim is proved at three independent layers, and the middle one is the reason I believe the other two.
Coverage was widened beyond the dispatch, correctly. I asked for the The trap was respected. 25 rewrites, 0 deletions. The PR body states the reason in the right form ( The two "nothing to do here" calls are both right, and both are stated with their evidence rather than as assertions: no comment taught the retired spelling ( Auto-merge armed (squash). #1835 closes on merge; nothing further needed from you. Generated by Claude Code |
Description
Every
fieldGroupscollapse hint insrc/objects/*.object.tswas authored with theADR-0085-deprecated
defaultExpanded: falsealias — 25 sites across 13 objects, andzero use of the canonical
collapseenum anywhere in the repo. All 25 now writecollapse: 'collapsed'.This is a spelling change on the authoring surface. No group was added, removed,
reordered or re-labelled, and no group changed whether it starts open or closed.
Type of Change
Related Issues
Fixes #1835
Changes Made
defaultExpanded: falsetocollapse: 'collapsed'in the 13src/objects/*.object.tsfiles that carried the alias:accountcampaigncasecontactcontracteventforecastknowledge_articleleadopportunityproductquotetask.git diff --statagainst the base is 13 object files at 25 insertions /25 deletions, plus the changeset.
No code comment needed updating: no comment anywhere in the repo taught the retired
spelling (
grep -rniE 'expand|collaps'oversrc/objects/*.object.tsreturns onlywhitespace-collapsing prose, unrelated to this key).
The equality proof
The card's claim is equality, so equality is what is measured — green CI would not
have shown it.
1. The mechanism, read off the installed dist
In the pinned
@objectstack/spec@17.4.0,deriveFieldGroupLayout(ADR-0085 §5) is thesingle place a group's collapse behaviour is resolved for the form and
synthesized-detail renderers. Its
readGroupreads the canonical key first:ObjectSchema.parse/safeParsenormalize the same way ahead of the base parse, vianormalizeSemanticRoleAliases, which short-circuits onif (grp.collapse != null) return g;.So an authored
collapse: 'collapsed'lands on exactly the valuedefaultExpanded: falsewas being folded into — it does not merely produce an equivalent, it takes the same branch's
output.
2. The derived layout is byte-identical
Every object was parsed through the pinned
ObjectSchema(each file already callsObjectSchema.create, which parses) and run throughderiveFieldGroupLayout, on bothrevisions. Coverage is all 18 objects that declare
fieldGroups, not just the exemplar:83 derived sections — 81 declared groups plus the two synthesized ungrouped sections on
crm_caseandcrm_task— of which 25 arecollapsedand 58none.The
crm_contact.mailing_addressexemplar the finding used in the browser derives{ key: 'mailing_address', label: 'Mailing Address', icon: 'map-pin', collapse: 'collapsed', fields: [mailing_street, mailing_city, mailing_state, mailing_postal_code, mailing_country] }on both sides, identically.
3. The probe is load-bearing — negative control
A probe that reported equality because it never read the value would be worthless, so it
was proved able to fail. One site was mutated to
collapse: 'expanded'after theimplementation was committed, the mutation was verified on disk by content (not by the
editor's exit code, which is 0 on zero matches), and the probe was re-run:
The restore leg is
git checkout HEAD -- path(never the bare form, which would take themutation back out of the index) and is proved by the blob hash matching HEAD and by
git diff HEADbeing empty — not by a clean-up step's exit code.4. The built artifact — the strongest reading
pnpm buildwas run on both revisions and the twodist/objectstack.jsonartifacts(2.0 MB each) were compared key-sorted. The entire difference is 25 lines:
Every
"collapse"value is present and identical on both sides — 25collapsed,56
none, 0expanded. So the shipped metadata does change in one respect and only one:the now-redundant deprecated alias key is no longer emitted. Nothing a renderer reads
moved.
That is also why the changeset frontmatter is empty rather than a
patch: nothing newreaches a user.
Why the key is rewritten and never deleted
collapsedefaults to'none'— always open, no toggle — not to'expanded'. Agroup that declares no collapse key is therefore not the same as
defaultExpanded: false,and "tidying" the key away would have been a real UX change disguised as a simplification.
Every site is rewritten; none is dropped.
Testing
pnpm verifyis green end to end onf36ce0d, and each stage was additionally run on itsown so the exit codes are separable rather than hidden behind the chain's
&&:pnpm validatepnpm typecheckpnpm lintpnpm lint:i18n-gatepnpm hygienepnpm hygiene:tokenspnpm buildpnpm testpnpm verify(whole chain)Test counts are unchanged, measured by running the suite on the base commit
62e23f5andon
f36ce0d:No test was added. Nothing in this diff is a behaviour to pin: the canonical spelling is
already enforced by the platform's own schema, and a repo-local guard forbidding an alias
the platform still accepts would be exactly the gate farm AGENTS.md Scope rule 3 rules out.
The 8 author-time build warnings are unchanged from the base and none of them concerns
field groups.
Not browser-verified. The finding's open question was whether the pinned console honours
collapseon the synthesized detail path as well as the alias; that is answered above atthe layer which decides it — both spellings resolve through the same
readGroupbranchinto the same derived value, and the built artifact confirms no renderer input changed.
Checklist
declaration documented in
.github/workflows/changeset-check.yml:33, precedent test(i18n): point the #802 term guard's pack rule at the real zh-CN tree #1778Additional Notes
Out of scope and deliberately untouched:
FormSectionSchema's owncollapsible/collapsedkeys on form view sections insrc/views/*.view.ts(a different schema,not aliases of anything), and
defaultExpandedDepth(a different key, on a treecomponent). Zero occurrences of
defaultExpandedremain anywhere in the repo outsidenode_modules.🤖 Generated with Claude Code
https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
Generated by Claude Code