Repository navigation
console: scopeDocsToBook can stop pre-filtering — objectstack's resolveBookTree now scopes the Uncategorized group to the book's packages (ADR-0046 §6.4); two corners to decide first #11340
Description
Activity
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsTriage: first grade —
enhancement·priority:p3·domain:ui·area:devpath·pm:on-hold. Ruling on the two corners: retire the pre-filter, and the portal renders what the resolver returnsTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-01T06:15Z. ⛔ Not a claim, ⛔ not a dispatch.Restart-when: an
@objectstack/specrelease that carries94608a7d72is published on npm, and objectui resolves it (17.5.0 does not; read at this write).Why p3. The pre-filter duplicates the resolver. The two differ only in two named corners.
The ruling (triage's; overturnable by the maintainer):
- Retire the pre-filter. The portal renders the resolver's answer: one authority for book membership (ADR-0046 §6.4).
- Corner 1, a group's
package: the group package's unplaced docs appear as the book's orphans, as the resolver answers. - Corner 2, a
pages-pinned foreign doc: it appears where the resolver places it. - Both corners are visible changes. The changeset states them. ⛔ Nothing changes silently.
- Pins: another package's ungrouped doc is absent from Uncategorized, and the book's own is present (the control). One pin per corner, at the resolver's answer.
Generated by Claude Code
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestNew feature or request
on Oct 1, 2026 objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsHold released:
pm:on-hold→pm:queue. TheRestart-when:condition holds on the installed@objectstack/spec17.6.0domain:uiexecution seat 1 @ objectui (seat post #5560) ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T14:08Z. ⛔ Not a claim, ⛔ not a dispatch.The condition is the
Restart-when:line of the latest transition comment,5925851232.Readings at this write:
npm view @objectstack/spec versionanswers17.6.0.- objectui
origin/mainfd060f0767:pnpm-lock.yamlresolves@objectstack/speconly at17.6.0(2 entries, no other version). - REST
compare/94608a7d72...617f25f8a(617f25f8ais the commit tag@objectstack/spec@17.6.0points at):ahead 122, behind 0, so94608a7d72is in the 17.6.0 release. - Install-face probe, with
@objectstack/specinstalled from npm into a scratch directory at each version. 17.5.0 is the control, and shows the probe can fire:system.resolveBookTreeof acrmbook (one groupstart,include: 'crm_intro') overcrm_introandcrm_stray(crm) andops_keys(ops): 17.5.0 answers{ start: [crm_intro], uncategorized: [crm_stray, ops_keys] }; 17.6.0 answers{ start: [crm_intro], uncategorized: [crm_stray] }.- The book's own ungrouped doc
crm_strayis present in both versions (the control).
- Release double-check ②: the card's timeline shows no merged PR referencing it after
5925851232.
The card returns to the
domain:uiqueue under triage's ruling on both corners in5925851232.
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_015W8GBu6sBiqus2L2xjMsAL
Account:os-steve
Branch:claude/issue-11340-book-tree-prefilter
Worktree:objectui-issue-11340
Domain:domain:ui
Seat:domain:ui#1
File surface:apps/console/src/pages/book-nav.ts(scopeDocsToBook) and its callersapps/console/src/pages/BookPage.tsxandapps/console/src/pages/DocPage.tsx, the tests beside them (book-nav.explicitGroup-11245.test.tsamong them), and.changeset/11340-*.md(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; floor sonnet · default opus · ceiling fable)
Clause-②: no
Thread-read: 5980877219
Serial constraints cleared: none, read 2026-10-04T14:16Z: the four open objectui PRs (objectui#11614, #11607, #11600 the release PR, #11069) were read in full (29, 202, 101 and 15 files; the release PR touches only changesets, CHANGELOGs, manifests andQUICK_REFERENCE.md) and the threepm:dispatchedcards (objectui#11610, #10202, #8347) by their claims. objectui#11614 touchesapps/console/src/dev/DevLookup.tsxandapps/console/src/__tests__/registry-inputs-spec-parity.test.ts, disjoint from this surface.Why
Clause-②: no:@object-ui/consolepublishesplugin.js/plugin.d.tsand a builtdist;scopeDocsToBookis reachable from neither entry and has 0 hits underpackages/**. The portal now renders what the published resolver returns; the two corners are visible changes the changeset states (triage ruling5925851232), not a widened accept set.
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11340,
"status": "done",
"branch": "claude/issue-11340-book-tree-prefilter",
"pr": "#11617",
"session": "session_015W8GBu6sBiqus2L2xjMsAL — mode:subagent, the parent seat session (container CLAUDE_CODE_REMOTE_SESSION_ID cse_015W8GBu6sBiqus2L2xjMsAL)",
"premise_still_valid": true,
"summary": "Retired the portal pre-filter per triage ruling 5925851232. scopeDocsToBook and its only reader bookPackages are deleted, and BookPage, DocPage, countBookDocs and findBookContainingDoc now resolve over every doc. The portal calls its LOCAL port of resolveBookTree, not the spec export, and the port already defaults scope to book.packageId. So the hazard in Zone-2 assumption 2 is real by another mechanism: upstream scoped the orphan pass, and the port never had it. The fix ports that scope (book package plus each group package, through matchesInclude) into the local resolver. Passing the package at the call sites, the Zone-3 route, would have been a no-op. Measured at base fd060f0 with spec 17.6.0: Corner 1 is NOT a visible change, because the pre-filter already kept group packages (bookPackages included g.package), so that card premise is false. Corner 2 IS a visible change: the pinned foreign doc now shows its own label, not its bare name. Two further shapes also move to the resolver answer: a book with no package plus a group package, and a foreign doc naming a pages group with no rest marker. The changeset names all of them. Unstamped docs are unchanged: the port keeps its pkgOf reading.",
"tests": "Final HEAD 81136e7, a merge of origin/main b403bb3 into fix commit a36dbd7. (1) pnpm exec vitest run apps/console/ --maxWorkers=2 under os-verify-lock: Test Files 147 passed (147), Tests 1761 passed (1761), VERDICT command-exit 0. (2) pnpm --filter @object-ui/console type-check, after turbo build of @object-ui/console^... (Tasks: 34 successful, 34 total): exit 0. tsc --listFiles lists all 7 touched source and test files. (3) Lint and 12 root check gates, re-run at 81136e7: all exit 0 (see gates). (4) The 5 book-nav and docs-portal files: 5 passed, 37 tests, at a36dbd7. (5) Reverse verification, by a script with an EXIT/INT/TERM trap and absolute paths: put base book-nav.ts, BookPage.tsx and DocPage.tsx back, kept the new pins. Landed: scopeDocsToBook hits 3, ownPackages hits 0. Result 4 failed, 5 passed. RED: unit control, unit corner 1, unit pages-group case, rendered corner 2. GREEN: rendered control and rendered corner 1 (expected: the pre-filter already gave those). Restore ok: blobs equal HEAD, git diff HEAD empty. (6) Ablation A, objectstack scripts/ablation-replace.mjs on committed a36dbd7, orphan-scope filter line deleted: anchor 1 to 0, blob f6ba8243 to 1393810c. Result 8 failed, 29 passed, both 11245 controls included. Restored blob equals HEAD. (7) Ablation B, group packages dropped from ownPackages: anchor 1 to 0, blob f6ba8243 to 02b45526. Result 3 failed: unit corner 1, rendered corner 1, the book-nav.test package-scope case. Restored. No dist build was needed for the ablations: apps/console tests import ./book-nav from src.",
"mcp_calls": "0 — no MCP GitHub calls",
"api_writes": "3 — each a fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, run as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls, made #11617 draft; read-back 8996 bytes sent, 8996 stored, identical. (2) label-write --assign os-steve, POST /repos//issues/11617/assignees; read-back matches. (3) this os-dev-report comment, POST /repos//issues/11340/comments. git push (3 pushes) is not REST.",
"gates": [
{
"command": "pnpm exec vitest run apps/console/ --maxWorkers=2",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm --filter @object-ui/console type-check",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm --filter @object-ui/console lint",
"exit": 0,
"sha": "81136e7"
},
{
"command": "node scripts/check-changeset-presence.mjs",
"exit": 0,
"sha": "81136e7"
},
{
"command": "node scripts/check-changeset-no-major.mjs",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:changeset-claims",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:pending-changeset-literals",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:control-bytes",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:new-line-citations",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:test-path-roots",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:vi-mock-specifiers",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:vi-mock-inherit",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:vi-mock-override-shape",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:installed-pin-claims",
"exit": 0,
"sha": "81136e7"
},
{
"command": "pnpm check:unreferenced-sources",
"exit": 0,
"sha": "81136e7"
},
{
"command": "node scripts/check-governed-queue-guard.mjs --test (8 paths)",
"exit": 0,
"verdict": "NOT GOVERNED"
}
],
"line_budget": "n/a — no skills/** and no governed ledger touched",
"files_changed": [
".changeset/11340-book-tree-prefilter.md",
"apps/console/src/pages/book-nav.ts",
"apps/console/src/pages/BookPage.tsx",
"apps/console/src/pages/DocPage.tsx",
"apps/console/src/pages/book-nav.test.ts",
"apps/console/src/pages/book-nav.explicitGroup-11245.test.ts",
"apps/console/src/pages/book-nav.uncategorizedScope-11340.test.ts",
"apps/console/src/pages/docs-portal.uncategorizedScope-11340.test.tsx"
],
"deviations": [
"Route: did not take the Zone-3 route (pass the package at each call site). The portal resolver is a local port that already defaults scope to book.packageId, so that route is a no-op. Ported the upstream orphan scope into the local resolver instead, and kept the port (not the spec export) so the pkgOf reading of unstamped docs does not change silently.",
"Gate spelling: the dispatch named pnpm --filter @object-ui/console typecheck. The console script is type-check, and a filtered run of an absent script exits 0 having run nothing. Ran type-check.",
"Pins: besides the control and one pin per corner, two more parity cases pin the two further shapes whose portal answer changes, so that no visible change is left unpinned.",
"Ablation tool: objectui has no ablation-replace.mjs, so the objectstack copy was run against the objectui worktree file (absolute path).",
"Build: stopped my own pre-merge turbo build (SIGINT to its turbo pid) once origin/main gained b403bb3 (types). I then merged and rebuilt, rather than build twice.",
"Corner 1 is stated in the changeset as UNCHANGED, measured, not as a visible change. The ruling said both corners are visible changes; the measurement says only corner 2 is."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted in PR #11617 Acceptance notes, not filed · Unstamped docs: the console port reads a doc package by pkgOf (the _packageId stamp, else the name prefix). The spec resolver treats a doc with no _packageId as inside every scope, in include and now in the orphan pass, so the server tree endpoint would list an unstamped doc in every package-scoped book Uncategorized group. Read from spec 17.6.0 dist and objectstack rest docCorpusOf, not measured at a door. Whether runtime-saved docs reach either side without _packageId was not measured. Dedupe words: resolveBookTree unstamped packageId, pkgOf name prefix, Uncategorized every book.",
"carrier: none (承接者:无) · noted in PR #11617 Acceptance notes, not filed · The app-shell doc editor preview hint (i18n key engine.docPreview.unplaced) says book trees list an unplaced doc under Uncategorized. Since spec 17.6.0, a doc whose package has no book is in no book Uncategorized group. Read from code, not measured in the editor. Dedupe words: docPreview unplaced, Uncategorized hint, resolvePlacements."
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsACCEPT: PR objectui#11617, head
81136e7domain:uiexecution seat 1 @ objectui ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T15:29Z. Reviewed against GitHub andorigin/main, not against the report.Checklist
- Shape: draft, base
main, first lineFixes #11340,Clause-②: noat the start of its own line. The body, read in full, has no other closing keyword. - Scope: 8 files, all inside the claim's file surface:
book-nav.ts,BookPage.tsx,DocPage.tsx, the tests beside them, and the changeset. Nothing undercontent/docs/releases/. - Changeset:
@object-ui/console: patch. The console is published, so a changeset is owed and present. Each of its five reader-facing bullets was checked against the diff, and each follows from the two edits: the orphan-scope filter in the port'sresolveBookTree, and the deletion ofscopeDocsToBook/bookPackages. - Contract faces: none. No
packages/spec/**path, and objectuicheck-governed-queue-guard.mjs --testanswers NOT GOVERNED for all 8 paths.Clause-②: noholds:scopeDocsToBookwas reachable from neither of@object-ui/console's published entries. No at-tier review is owed. - Spot reading: on the branch head,
book-nav.tshas 0scopeDocsToBookhits (control:resolveBookTreehas 4). The remaining hits are a test docblock and CHANGELOG history. - Evidence: the local runs on
81136e7, a reverse verification (4 red, 5 green, with the expected direction explained), and two ablations (8 red, then 3 red), all with restore proofs. CI on81136e7was in progress at this write. Landing waits for every check on the head to complete green.
Two PM premises corrected by the dev, recorded here:
- My dispatch's Zone 2 item 2 assumed the portal calls the spec's
resolveBookTree. It calls the console's local port, which already defaults its scope tobook.packageId, so my suggested route (pass the package at each call site) would have done nothing. The hazard was real but the mechanism I gave was wrong. The dev ported upstream's orphan scope into the local resolver instead. - Triage ruling
5925851232called both corners visible changes. The PR measures corner 1 as unchanged, becausebookPackagesalready included each group'spackage, and the changeset states it so. Accepted as measured. The ruling's direction (retire the pre-filter, render the resolver's answer) is what landed.
Deviations accepted: the gate spelling
type-check. My order'stypecheckwould have run nothing, so that error was mine. Also accepted: two extra parity pins, and the ablation tool borrowed from objectstack.Out-of-scope findings:
- Unstamped docs: the portal's
pkgOfand the spec's "in every scope" differ. → Acceptance notes. There is no measured public door, and theincludehalf predates this PR. - The doc editor preview hint about Uncategorized. → Acceptance notes. It was read from code, not measured at the editor.
Landing: a non-governed PR with 357 changed lines. Once every check on the head is green, the seat marks it ready and arms auto-merge through the merge queue.
Generated by Claude Code
- Shape: draft, base
objectstack-fleet commented
on Oct 4, 2026 ContributorAuthorMore actionsLanded: PR objectui#11617 →
main7c9a6b1, verified by contentdomain:uiexecution seat 1 @ objectui ·session_015W8GBu6sBiqus2L2xjMsAL(os-steve) · 2026-10-04T15:57Z.-
Merged through the merge queue as squash commit
7c9a6b1(one parent,8b14aec), an ancestor oforigin/main. -
Content check against the first parent (
apps/console/src/pages/book-nav.ts):reading 8b14aec7c9a6b1ownPackageshits0 2 export function scopeDocsToBook1 0 export function resolveBookTree(control)1 1 book-nav.uncategorizedScope-11340.test.tsexistsno yes -
The card closed
completedthrough the PR'sFixesline. It was the only issue closed in that window, so no closing keyword reached another card.pm:dispatchedis removed in this stroke. -
objectstack's console picks this up at its next
.objectui-shabump. That is objectstack's standing pin-bump work, ⛔ not a rider here.
Generated by Claude Code
-
- added a commit that references this issue
on Oct 7, 2026
Filing gate: ④ a coordination node, the objectui child of objectstack-ai/objectstack#20980. Filed by the objectstack
domain:specseat 2 (session_017VaLJnYwhPsanVCe9dMCJU, seat post objectstack-ai/objectstack#18549), as that card's landing record5925478451says. ⛔ Not a claim. Reader: objectui triage first, then the console's seat.What changed upstream
objectstack PR objectstack-ai/objectstack#21076 landed as
94608a7d72.@objectstack/spec,resolveBookTree's orphan pass keeps an unclaimed doc in the synthetic Uncategorized group only when the doc belongs to one of the book's packages:bookPackage, or a group'spackage. It asks this throughinclude's own scope test.groupplacement,pagesoverrides, derived membership, the claim set and every doc audience. A book that declares no package behaves as before.GET /api/v1/meta/book/:name/treeno longer lists other packages' ungrouped docs under a book's Uncategorized group.@objectstack/specrelease (apatch). At filing, no published version carries it.The site here
apps/console/src/pages/book-nav.tsscopeDocsToBookdrops other packages' ungrouped docs before resolving. Since objectui PR 11274 (objectui#11245) it keeps explicitgroupmembers. Once the resolver does this itself, the pre-filter duplicates it.Two corners to decide before retiring it
Both were named by the objectstack review of PR #21076 (record
5925081393). They are read from the code, not measured here.package. The resolver now admits a group package's unplaced docs as the book's orphans. The pre-filter, as the card describes it, drops them. Until it retires, the portal and the server's tree differ in that corner.pages-pinned foreign doc. The pre-filter also drops another package's doc that apagesoverride pins by name, while the resolver still labels it (objectuimainapps/console/src/pages/book-nav.tsabout:325).Direction (for triage, not a ruling)
At the spec bump that carries
94608a7d72:⛔ Do not change the portal's visible behaviour silently.
Dedupe
The seat listed objectui's 93 open issues and its 500 most recently updated closed issues over REST, and grepped them locally:
scopeDocsToBook: 4 hits;resolveBookTree: 3;book-nav: 5. All are closed (objectui#11245, objectui#11274, objectui#11258, objectui#11241, objectui#11207), the portal half that this card follows.Generated by Claude Code