Repository navigation
refactor(views): remove the inert list.tabs[] block from every view file - #1316
Merged
Merged
Conversation
The object-view switcher builds its tab strip from view descriptors --
one tab per listViews entry plus the primary list, which it moves to the
front and marks default. Re-measured on @objectstack/console 17.1.0:
Dm({ definedViews: U.listViews, primary: U.list, primaryId,
savedViews, viewOverrides, fallbackTab })
tabs appears nowhere in that path. A tab's text is the view's own label
and its icon is viewTypeIcons[view.type], from a map the console
hardcodes over eight view types. #1304 removed the entries' label; this
removes the rest of the entry -- 60 entries, 48 icon: keys, 12 files.
Corrects the beliefs that rested on the old model: view-references
asserted that a listViews entry left out of tabs was unreachable (it was
not -- it now guards navigation entries naming an undefined view, which
nothing checked), crm.app.ts pointed authors at list.tabs as the string
to edit, and four suites read list.tabs for a property that comes from
listViews. view-tab-label-inert is re-aimed from "carries no label" to
"tabs is absent", with an anti-vacuity half pinning that the walk really
reached the twelve list blocks.
userFilters.tabs[] (ADR-0047) is untouched: a different key on page
lists, where label is live and translated.
The card's headline reads '36 of 48'. Re-measured on this tree it is 33 of 48 that name an icon their target view cannot render, and 15 that coincide -- 8 exactly (calendar, map) and 7 by prefix (gallery-thumbnails on a gallery view, gantt-chart on a gantt one). Under the stricter reading (the authored string is literally one of the eight viewTypeIcons keys) it is 39 and 9. Neither reproduces 36, so both the changeset and the pin now carry the measurement and the rule it was taken under. The premise is unaffected: all 48 are inert either way.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
This was referenced Aug 26, 2026
hotlong
marked this pull request as ready for review
August 26, 2026 06:09
This was referenced Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
list.tabs[]is inert in its entirety. PR #1304 removed the entries'label; this removes the rest of the entry — 60 entries, 48icon:keys, 12 files — and corrects the five places in this repo that wrote the falsified model down.The card's premise was re-measured before any edit, as its acceptance criteria demand, and it reproduced. Read directly out of
node_modules/@objectstack/console@17.1.0in this worktree (the lockfile pin has not moved):dist/assets/src-*.js:_m={grid:$e,kanban:yt,calendar:ur,gallery:Ve,timeline:En,gantt:We,map:Yn,chart:qe}, passed to the switcher asviewTypeIcons:_m. Exactly the eight view types the card names.tabs— its strip comes fromDm({ definedViews: U.listViews || U.list_views || {}, primary: U.list, primaryId, savedViews, viewOverrides, fallbackTab }), andDm's body builds descriptors fromdefinedViews,primaryandsavedViewsonly. The primary isunshifted to the front and force-markedisDefault: true. Each tab's text isb(object, view.name, view.label)— the view's own label, i18n-resolved.listViewsmatches 8 bundles,viewTypeIcons2 — so the search reached the code. The singlelist.tabshit in the wholedistis an i18n string key,"list.tabs": "Tabs", not a read.userFiltersblock is ignored because "the view switcher owns the tab bar here" (ADR-0047 "views" mode). That is the same fact from the other side, and it is whyViewTabSchema.labelis untouched here.Type of Change
Related Issues
Closes #1307
Refs #1283 (ruled
removeoverenforce; not re-litigated here) · PR #1304 · #760Changes Made
1. The block itself — 12 files, 91 lines.
tabsis.optional()onListViewSchema, so removal is schema-legal and changes no behaviour.src/views/{account,campaign,case,contact,contract,event,forecast,knowledge_article,opportunity,product,quote,task}.view.ts.2. Five false-belief sites corrected — three named on the card, two found by the dispatching seat:
test/view-references.test.tstabsarray, only the listed views render", naming seven queues as "defined, tested, unreachable"src/apps/crm.app.tsheaderlist.tabsinsrc/views/*.view.ts"labelsrc/apps/crm.app.tsSales grouppipelinetab (OpportunityViews.list.tabs)"pipeline_kanbaninlistViews, on the strip under its own label Sales Pipelinetest/case-assignment.test.tstabs[]entry forunassigned_triageand assertedtab.pinned === truelistViewsentry, so it is on the strip by existing.pinnedwas inerttest/docs-search-navigation-views.test.tslist.tabs[].labelinto the expected label set, and readisDefaultoff a tab entryt.labelpermanentlyundefined, discarded byfilter(Boolean)) and could add nothing — a tab only ever pointed atlistor alistViewsentry, whose labels are already in the set. Removed. "Opens on Open Deals" is now asserted as what it is: a property of being the primary listTwo further sites in the same file, not on the card, which my own deletion would otherwise have left dangling: the "All Tasks" comment cited
isDefault+pinnedoff the tab entry, and the Activity group citedEventViews.list.tabs. Both re-authored the same way. One more insrc/views/account.view.ts: theuserFiltersblock justified its placement with "the default view'stabsact as the view switcher" — false, and the measured constraint is aboutelement, not placement, so the comment now states that instead.3. The #1304 pin re-aimed, not withdrawn —
test/view-tab-label-inert.test.ts. It said so itself: "if a refactor empties everytabs[]array, the assertion passes vacuously". This is that refactor. Upgraded from "list.tabs[]carries nolabel" to "list.tabs[]is absent", and the anti-vacuity face moved with it — from "there are still tabs to inspect" to "the walk really reached the twelvelistblocks it claims to have cleared", pinned by name rather than by count so a bundle dropping out ofsrc/views/index.tscannot silently shrink the surface.4.
account-renewal-model/decorative-field-sweep— both asserted a removed view's absence fromlistViewsand fromtabsas two distinct broken states. There is only one place a view can be reachable from, so each now asserts over the whole strip (list+listViews) — which is also stricter: reintroducing the view as the primary list would now fail too.5. Changeset:
.changeset/a-tab-is-a-view.md(hotcrm: patch).Testing
pnpm test: 140 files, 2969 passed, 1 skipped (the skip is a pre-existingit.skipIfinscript-main-guard.test.ts, untouched here)pnpm lintexit 0;pnpm lint:i18n-gateprints✓ i18n lint gate: 0 i18n/missing-* issuespnpm buildexit 0,✓ Build complete,14 Viewspnpm validateexit 0 ·pnpm hygiene→✓ source hygiene clean·pnpm hygiene:tokens→✓ source token ratchet cleanThe whole union above was re-run after the final commit, on
803742a9, with a clean tree.Reverse verification — three legs, each with the mutation confirmed on disk by blob hash before the reading was taken, and each restored via
git checkout HEAD -- <abs path>withgit diff HEADproven empty afterwards. Predicted direction was RED for all three, and all three were RED:tabsblock oncrm_product(blob707f529a→e830dfff) → the pin fails withcrm_product.list.tabs is authored (2 entries). The anti-vacuity half stayed green, so the two halves are independent.ProductViewsfromsrc/views/index.ts(blobee83fd09→52621a34) → the anti-vacuity half fails withthese `list` blocks were never inspected, namingcrm_product. The absence rule stayed green — which is exactly the vacuous pass it exists to catch.viewNametomy_open_taskz(blobf7bda5fc→de8327ab) → the new guard fails withnav_my_tasks: "crm_task" defines no view "my_open_taskz" — the entry opens on nothing, listing what the object does ship.Additional Notes
One figure in the card does not reproduce, and it is in the title. The card says "36 of the 48 authored icons name something that can never render there". Measured on this tree, resolving every tab's
viewto its target view'stypethrough the built artifact (all 48 targets resolved, none guessed):crown,inbox,git-commit-horizontal,user,columns-3, …)calendar,map) and 7 by prefix (gallery-thumbnailson agalleryview,gantt-charton aganttone, which is the card's own example of a coincidence)Under the stricter reading — the authored string is literally one of the eight
viewTypeIconskeys — it is 39 and 9. Neither reading gives 36. The changeset and the pin carry the measured numbers together with the rule they were taken under, rather than the card's. The premise is unaffected either way: all 48 are inert, because the authored string is never looked up at all; the icon is chosen by the view'stype.The token ratchet now prints a new advisory (status 0, not a failure): removing 91 lines drops the interaction layer by ~1,027 tokens, taking its headroom to 4,576 and past the "over twice the 5% buffer" line, so the gate asks for the ceiling to be re-anchored to ~40,000.
scripts/check-source-token-ratchet.mjsis outside this PR's file fence, so it is left for the maintainer rather than edited here.Not touched, deliberately:
ViewTabSchema.labeland the schema field —userFilters.tabs[](ADR-0047) is a different key on page lists wherelabelis live and translated.src/views/lead.view.tsandsrc/views/event_attendee.view.tscarry notabs. Theunassigned_triageview'sfilteris #1145's subject and is untouched here.content/docs/**is outside the fence; theTabcolumns some pages publish are reported separately to the dispatching seat.Generated by Claude Code