Repository navigation
fix(console): the docs portal renders the book resolver's answer; the Uncategorized pre-filter is retired (objectui#11340) - #11617
Merged
objectstack-fleet[bot] merged 2 commits intoOct 4, 2026
Conversation
… Uncategorized pre-filter is retired The console's port of `resolveBookTree` now scopes its synthetic Uncategorized group to the book's own packages (the book's, and each group's `package`), asked through `include`'s own scope test, as the framework's resolver does since objectstack#20980. `scopeDocsToBook` and `bookPackages` are deleted; `BookPage`, `DocPage`, `countBookDocs` and `findBookContainingDoc` resolve over every doc they read. Pins: the control pair, corner 1 (a group's `package`), corner 2 (a `pages`-pinned doc of another package), and the two further shapes whose portal answer moves to the resolver's, each checked against the spec's `resolveBookTree`; and the rendered sidebar through the real route table. Claude-Session: https://claude.ai/code/session_015W8GBu6sBiqus2L2xjMsAL Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015W8GBu6sBiqus2L2xjMsAL Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Oct 4, 2026
objectstack-fleet
Bot
deleted the
claude/issue-11340-book-tree-prefilter
branch
October 4, 2026 15:56
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.
Fixes #11340
Clause-②: no
What changed
The portal now renders the book resolver's answer, with no pre-filter in front of it. This follows the triage ruling in comment
5925851232: one authority for book membership (ADR-0046 §6.4).resolveBookTree(apps/console/src/pages/book-nav.ts) now scopes its synthetic Uncategorized group to the book's own packages. Those are the book's (bookPackage, elsebook.packageId) and each group'spackage, asked throughinclude's own scope test. The framework's resolver does the same since [finding] GET /meta/book/:name/tree puts every package's ungrouped docs in the book's synthetic Uncategorized group — resolveBookTree's orphan catch-all ignores bookPackage, against ADR-0046 §6.4 and the portal's per-package answer objectstack#20980 (@objectstack/spec17.6.0).scopeDocsToBookis deleted, and so is its helperbookPackages, which nothing else read.BookPage,DocPage,countBookDocsandfindBookContainingDocnow resolve over every doc they read.No export, prop, type member or i18n key of any
@object-ui/*package is added or removed.Landing site, and why the route differs from the suggested one
The landing site is the expected one:
book-nav.ts,BookPage.tsx,DocPage.tsxand the tests beside them.Mechanism assumption 2 is half true. The portal does call its resolver with two arguments. But that resolver is the console's local port: the
book-nav.tsheader calls it "a faithful local port of the framework'sresolveBookTree". It is not the spec's export. The port already defaults its scope tobook.packageId, so passing the book's package at each call site, the suggested route, changes nothing.The hazard is real, by another mechanism. Upstream's fix never reached the port, so the port's orphan pass was unscoped. Deleting the pre-filter alone widens Uncategorized to every package's docs (column (b) below). The fix ports upstream's orphan scope into the local resolver, then deletes the pre-filter.
Why port it rather than call the spec's export. The port and the spec read a doc's package differently.
pkgOf: the_packageIdstamp, else the prefix of the doc's name.The port also marks the synthetic group (
synthetic), whichcountBookDocsandfindBookContainingDocread. Calling the spec's export would also change what unstamped docs do ininclude, a visible change the ruling does not cover. Ported withpkgOf, an unstamped doc behaves as it did under the pre-filter.Measured: before and after
Probe at base
fd060f0767, with the installed@objectstack/spec17.6.0. Every doc carries apackageId, except in the last row. The columns:resolveBookTree, with the book's package as its third argument.startincludescrm_intro; docscrm_intro,crm_stray(crm),ops_keys(ops)crm_straycrm_stray,ops_keyscrm_strayextwithpackage: b; unplacedb_note(b) andc_note(c)b_noteb_note,c_noteb_notepagesarecrm_intro,ops_keys;ops_keysis labelled Keysops_keys, no labelops_keyslabelled Keys;ops_otherin Uncategorizedops_keyslabelled Keysall(include: '*') andext(package: b)all:b_1all:a_1,b_1all:a_1,b_1groupnames apagesgroup that has no...ops_unstampedbeside a crm bookbookPackagesincluded each group'spackage.Tests
book-nav.uncategorizedScope-11340.test.ts(new). The control pair, Corner 1, Corner 2, a package-less book, and the two further shapes. Every case also asserts that the portal's full tree equals the spec'sresolveBookTreeover the same docs, scoped by the book's package. That covers every group, Uncategorized included.docs-portal.uncategorizedScope-11340.test.tsx(new). The rendered sidebar, through the real route table (DocsLayout, DocPage, BookSidebar). It pins the control pair, Corner 1, and Corner 2, whose link is named by the doc's own label.book-nav.explicitGroup-11245.test.ts, re-judged.portalTreeis nowresolveBookTree(b, all). Everything it pins about explicitgroupplacement stands. Its controls are now held by the resolver's own orphan scope: ablation A below turns them red.book-nav.test.ts, re-judged. Its package-scope case pinned the old unscoped orphan:b_xsat in the Uncategorized group of a book that draws from packageaalone. It now pins the resolver's answer, which has no Uncategorized group. The "drops nothing" case is renamed to say it concerns a book that declares no package.Runs on the merge commit
81136e7(origin/mainb403bb36fmerged in):a36dbd7, before the merge, and again inside the full console run below.pnpm exec vitest run apps/console/(the root spelling): 147 test files passed, 1761 tests passed, exit 0.pnpm --filter @object-ui/console type-checkafter a turbo build of@object-ui/console^...: exit 0. The build was 34 of 34 tasks.--listFilesshows all seven touched files in the run.pnpm --filter @object-ui/console lint: exit 0, 0 errors. The warnings inDocPage.tsxare on lines this PR does not touch.Reverse verification. The base implementation of
book-nav.ts,BookPage.tsxandDocPage.tsxwas put back fromfd060f0767, with the new pins kept. Result: 4 failed, 5 passed.pages-group case, and the rendered Corner 2, whose link was namedops_keysrather than Keys.git diff HEADis empty.Ablations on the committed fix
a36dbd7, through objectstack'sscripts/ablation-replace.mjs. In each, the anchor went from 1 hit to 0, the blob changed, the file was restored to equal HEAD, andgit diff HEADwas empty.pages-group case, both 11245 controls, the 11245 group-packagecase, and thebook-nav.test.tspackage-scope case.book-nav.test.tspackage-scope case.Gates, run locally, each exit 0:
node scripts/check-changeset-presence.mjsandnode scripts/check-changeset-no-major.mjs;pnpm check:changeset-claimsandpnpm check:pending-changeset-literals;pnpm check:control-bytesandpnpm check:new-line-citations;pnpm check:test-path-roots,pnpm check:vi-mock-specifiers,pnpm check:vi-mock-inheritandpnpm check:vi-mock-override-shape;pnpm check:installed-pin-claimsandpnpm check:unreferenced-sources.node scripts/check-governed-queue-guard.mjs --testanswers NOT GOVERNED for all eight paths. CI runs the full farm.Acceptance notes
pkgOf, which falls back to the name's prefix. The spec treats a doc with no_packageIdas inside every scope, inincludeand now in the orphan pass. Theincludehalf of that divergence predates this PR. This PR keeps the portal's reading for orphans, so nothing changes for unstamped docs. Whether runtime-saved docs reach the portal without_packageIdwas not measured here.packages/app-shellsays "Not in any book section yet — book trees list it under Uncategorized." Since spec 17.6.0, a doc whose package has no book is in no book's Uncategorized group. This is read from the code and was not measured at the editor.pnpm --filter @object-ui/console typecheck. The console's script istype-check, and a filtered run that matches no script exits 0. This PR rantype-check.Generated by Claude Code