Repository navigation
console lists: per-user list state (view tab order, filter state, sort, column widths) moves from localStorage and shared-view writes onto sys_user_preference ui.* keys; a toolbar sort or drag-reorder no longer rewrites the shared view #12418
Description
Filing gate ③, a task the maintainer dispatched in person (chat, 2026-10-15). The maintainer asked 「这是主流类似系统的做法吗?浏览器侧的个人偏好——objectui 把视图顺序和每人每视图的筛选状态存在 localStorage」; the director seat answered that mainstream systems keep per-user list preferences on the server per user and offered 「是否立一张 objectui 卡做第一层(个人偏好上服务端、排序不写共享视图)?你一个字「立」我就立,归 objectui 车道。」; the maintainer's word: 「立」. Filed by the director seat (summon #37 continuation 2, session_01LqNgdPZB2Jnr5HpGbaqLeB). ⛔ Not a claim; triage may regrade.
The problem in one sentence: a console user's list preferences live in three places — the view tab order and the Filter panel's state in the browser's localStorage (gone on another device or after a cleared cache, no admin reset), favorites / recents / palette recents on the server under sys_user_preference ui.* keys (the cloud-synced adapter), and a user's sort click or view drag written INTO the shared view metadata through client.meta.saveItem — so one user's sort changes what every user sees, and under a walled posture (group / isolated) that write is refused by the platform (ADR-0131 D12 items 7–8: tenants do not write environment metadata), so a personal preference ends in an error.
Reader who acts: the domain:ui lane, one dev round in @object-ui/app-shell (plus @object-ui/data-objectstack if the adapter needs a new slot shape).
Readings (objectui origin/main 28fb2a001; objectstack origin/main 086fa4640)
- View tab order:
packages/app-shell/src/views/ObjectView.tsx:2739-2760(handleReorderViews) writesviewOrder:<object>to localStorage first, then PATCHessortOrderonto every saved view throughdispatchViewPatches/reorderViewPatches(:1102-1118), the shared row, "so other sessions / users can pick up the order". - Sort:
:3745-3747onSortChange→persistViewPatch(viewDef.id, viewDef, { sort })(the shared view, throughupdateViewConfig→client.meta.saveItem, a PUT on/meta/view,:1168) andwriteListUrlState({ sort }). - Filter panel state:
:3752-3762onFilterChange→writeListFilterState(listFilterKey, …)(localStorage, "SESSION state only", objectui#4155's rule that the builder's group never touches the view's stored body) and the URL (objectui#11860). - Already on the server, per user:
packages/data-objectstack/src/userState.ts(createObjectStackUserStateAdapter:resourcesys_user_preference,(user_id, key, value),load()/save(), keys namespacedui.*; one shared read per load, objectui#12187, pinned byconsoleUserPreferenceBudget.test.tsx). Consumers today:ui.favorites,ui.recent,ui.flow.palette.recents(ConsoleShell.tsx:331-341). - The object: objectstack
packages/platform-objects/src/identity/sys-user-preference.object.ts("Per-user key-value preferences"), organization-owned rows, unique on(organization_id, user_id, key): a data write, not a metadata write, admitted for a tenant's own user under every posture. Environment metadata writes under a wall are refused for everyone but the platform operator (packages/metadata-core/src/meta-write-capability.ts,walledCatalogWriteVerdict). - Saved views in the console are metadata:
ObjectView.tsx:2244-2247reads them from/meta/viewvialistViews; there is no per-user or per-organization saved-view object (sys_view_definitionretired as inert, ADR-0131 §7; per-user view scope is "a parked platform-side v18 direction").
What to build (the first layer only: preferences, not personal views)
- One per-user list-state slot on the existing adapter: key
ui.list.<object>, value{ viewOrder, perView: { [viewId]: { sort, filters, columnWidths? } } }, written throughsave()and read in the same shared read as the three existing slots: the objectui#12187 budget stays ONEsys_user_preferenceread per console load (extend the pinned test; add no request). localStorage stays as the write-through cache and the no-adapter fallback (load()answering[]keeps today's localStorage path), so an adapter-less or offline host behaves as today. - A user's sort and drag-reorder stop writing the shared view:
onSortChangeandhandleReorderViewswrite the user's slot (and the URL, objectui#11860, unchanged);persistViewPatchand thesortOrderPATCHes are reached only from the view editor (Studio, or an explicit "save view" action by a metadata author), never from a toolbar click. ⛔ The view's authoredsortand the authored tab order stay the default for every user with no preference. - Filter state moves from the session-only localStorage key to the same slot, keeping objectui#4155's rule (the builder's group never touches the view's stored body) and the URL.
- Reset: the toolbar's "Clear all" (filters) and a "Reset view" entry clear the user's slot for that view; an admin deletes the row in Setup → User Preferences (already navigable).
- Under a wall: nothing new to build; the point of the move is that a tenant user's list preferences are organization rows and therefore allowed where metadata writes are refused. Measure it: a non-operator user on a
groupposture changes sort and order with no error and no change to the shared view (an adapter-level pin with the fake framework the budget test already uses, or a dogfood run). - ⛔ Not in this card: personal or shared saved views (
ViewItem.ownerwas retired in 18; that is a protocol decision card if wanted); the Studio view editor; any change topackages/spec.
Acceptance
- The objectui#12187 budget pin passes with the new slot included: still one
sys_user_preferenceread per console load, every consumer receiving its own row. - A pin that a toolbar sort or drag-reorder issues NO
/meta/viewwrite (the fake framework counts 0 PUTs) and one preferencesave(); the view editor's save still writes/meta/view. - Cross-device: the same user in a second browser (fresh localStorage) sees their order, sort and filters after
load(); another user sees the authored defaults. - The walled-posture pin of item 5.
pnpm -r typecheck, the app-shell suite and thecheck:*gates the repo's AGENTS.md lists.
Dedupe
Titles of the last 300 objectui issues (all states) grepped for preference / localStorage / viewOrder / personal / per-user / filter state / column width / sortOrder: 1 hit, objectui#12212 (closed, the bell's object label; not this). Open issue bodies mentioning sys_user_preference, viewOrder or localStorage: 0. Precedents cited, all closed: objectui#4155 (the filter panel must not persist an overlay), objectui#11860 (filters, sort and grouping in the URL), objectui#5544 and objectui#12187 (the preference read budget). The GitHub search API is not available to this session; the dedupe is the repository listing above.
Related: objectui#4155 · objectui#11860 · objectui#12187 · objectui#5544 · objectstack ADR-0131 D12 items 7–8 · objectstack walledCatalogWriteVerdict.
Activity
objectstack-fleet commentedon Oct 15, 2026
Deferred, not parked:
domain:uiseat 1 ·session_01JZnppgHRp4sREcouhkQYDB· 2026-10-15T04:40Z. ⛔ Not a claim; the card stayspm:queue, unassigned.Why it waits: this card's surface shares hot files with two in-flight claims. Same-area cards run serially, so it is next in this lane's order once both land.
6184189645) editspackages/plugin-list/src/ListView.tsx(the right toolbar cluster),packages/plugin-view/src/ViewTabBar.tsx, the grid's leading cell, and theViewTabBarcall site inObjectView.tsx. This card's sort, filter, drag-reorder and column-width paths run through the same toolbar, tab bar and grid.6184389018) editshandleRenameViewinObjectView.tsx, a few hundred lines from this card'shandleReorderViews(:2739–:2760).Known pitfalls, for whichever seat claims it:
main. Re-readhandleReorderViews,onSortChangeandonFilterChangeon the ref that carries both landings.sys_user_preferenceread per console load.consoleUserPreferenceBudget.test.tsxis the pin to extend; a fourth slot must not add a request.Restart: when objectui#12417 and objectui#12423 have both merged. The seat that claims it re-checks the in-flight list at that moment.
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1 (the deferral
6184567991is lifted: objectui#12417 and objectui#12423 have both closed)Session:
session_01JZnppgHRp4sREcouhkQYDBAccount:
sunhaolinBranch:
claude/issue-12418-per-user-list-stateWorktree:
objectui-issue-12418Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/app-shell/src/views/ObjectView.tsx(handleReorderViews, the toolbaronSortChange/onFilterChangehandlers and theviewOrder:/ list-filter reads, read onmaina2225f913at:2381,:2748,:3432,:3755),packages/app-shell/src/views/listFilterStorage.ts, the console's preference wiring (ConsoleShell.tsxand the user-state adapters provider) andconsoleUserPreferenceBudget.test.tsx,packages/data-objectstack/src/userState.tsonly if the slot needs a new shape,packages/plugin-gridorpackages/plugin-listonly where column widths are reported, the tests beside each, and one.changeset/12418-*.md(stop on breach; explain in the report)Container & model:
L,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuinames no path-derived mandate)Clause-②: yes
Responsibility: n/a — not a defect card
Thread-read: 6184567991
Serial constraints cleared: read at objectui
maina2225f913.Predecessors: objectui#12417 (
handleRenameView) and objectui#12423 (PR feat(list): Filter · Sort · Display · Search toolbar, width-fitted view tabs, one leading row cell, one-row page header #12436: the list toolbar,ViewTabBar,ObjectViewcall sites) have both landed.In flight: seat 2's objectui#12439 (
sharedUserFeeds.ts) and seat 3's objectui#12427 (UnifiedSidebar.tsx, PR feat(app-shell): the sidebar entry's ⋯ menu, one component for every entry type (part of objectui#12427) #12443) are disjoint.Fold-or-serial, answered for the shared hot files (
ListView.tsx,ObjectView.tsx): SERIAL, this card first. objectui#12440 (pm:blockedon console list page: the toolbar's settings cluster folds into one Display popover, view tabs size to their width and carry the view's type icon, the row-number cell yields to the checkbox on hover, and the page header is one row #12423, so about to unlock) edits the same two files, for a different defect: a toolbar layout slot, where this card is per-user persistence. It fails the fold gate's first test (same defect, same fix), so it runs after this card's PR lands.Why
Clause-②: yes: the route the dev picks is not known yet. A new slot shape in@object-ui/data-objectstackmay be exported, and a toolbar sort stops writing the shared view, which changes what a published package persists. When in doubt the declaration isyes. The review is this seat's own, atTIER_DEFAULT.The maintainer's word carried: 「立」 (card body, filing gate ③). The scope is "the first layer only: preferences, not personal views".
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 12418,
"status": "done",
"branch": "claude/issue-12418-per-user-list-state",
"pr": "#12471",
"session": "session_01JZnppgHRp4sREcouhkQYDB (mode:subagent, so this is the dispatching seat's session id, the same id the relay stamped)",
"premise_still_valid": true,
"summary": "Draft PR objectui#12471 (head ec82faf, 6 commits on base a2225f9). It moves each user's list state into one sys_user_preference row per object, key ui.list.OBJECT, value { viewOrder, perView: { VIEW_ID: { sort, filters, columnState } } }: the view-tab order, plus per view the sort, the Filter panel's conditions and the grid's column order and widths. A new ListPreferencesProvider in ConsoleShell holds it, with localStorage (list-state:USER:OBJECT) as the write-through cache and the no-adapter fallback. A toolbar sort (both sort sites), a column resize or drag, a Filter panel change and a Manage Views drag now write that row and never /meta/view. The view editor's save is unchanged. A3 is falsified in its simple form: the shared read is opened at boot, and the object page mounts after metadata, so a per-object key cannot join it by name. The budget is kept by a new @object-ui/data-objectstack export, createObjectStackUserPreferenceFamily, whose boot load joins the same request as a key PREFIX arm (key in [3 slot keys] OR key startswith 'ui.list.'). That is still ONE GET, pinned, with a saturation fallback for the slot keys. Item 4 also landed: 'Clear all' clears the stored filters, and a 'Reset view' button in the page header (2 new keys in all 10 i18n packs) drops the active view's entry and remounts the list on the authored defaults. Measured beyond A1: the drag door is admin-only (ViewTabBar mount has reorderable:false; only the admin-only ManageViewsDialog calls onReorder), so the reordered tabs become that admin's own order. The new cross-device pin caught a bug in this branch, now repaired: the first render ran before the bridge attached the family and seeded the list from an empty cache. The provider now waits for a signed-in user's family, bounded by 2.5 s.",
"tests": "All runs went through os-verify-lock. (1) Final-HEAD union at ec82faf: vitest run of ObjectView*, consoleUserPreferenceBudget, consoleListStateWall-12418, context/tests, data-objectstack userState*, the i18n objectView-config-keys-retired-4730 test, view-filter-fold.ratchet and writeRefusalCensus-11583 printed 'Test Files 79 passed (79) / Tests 695 passed (695)', VERDICT command-exit 0. (2) Full @object-ui/data-objectstack plus @object-ui/i18n: 1 red, the i18n namespace-count pin (+2 keys, updated with its reason), then i18n 'Test Files 83 passed (83)'. data-objectstack userState pins: 4 files, 30 tests green. (3) app-shell in segments: root + console + context + misc 204 files with 1 red, entryRegistersBuiltinDesigners-11939, a load-timing test that passed alone 1/1 and is already reported on objectui#12423's report; hooks/layout/providers/preview/utils/chrome 230 passed + 1 skipped; top-level views 100 + 103 files, where 2 source ratchets went red and were updated (filter-panel 'not amnesiac' leg, write-refusal census reorder row), re-run 62 files green; studio-design 58 of 173 green. NOT MEASURED: studio-design 115 files and views/metadata-admin 492 files, reason under gates. (4) Ablations, 7 of them, each one mutation through objectstack scripts/ablation-replace.mjs. Each anchor hit 1 time, went 1 to 0 and changed the blob, and each restore was proven by 'blob == HEAD and git diff HEAD is empty', with the tree clean after. Tests load @object-ui/* from src through the vitest alias, so there was no dist leg. A1 (the ListView sort prop writes persistViewPatch({sort}) again): 3 red, the userListState sort pin, the wall pin and the no-provider sort control. A2 (a drag also sends updateView sortOrder): 4 red, the drag pin, the wall pin, the 11583 reorder pin and the no-provider drag control. A3 (the family opens its own read): 7 red across the budget and family files. A4 (the seed ignores listPrefs.ready): 2 red. A5 (Reset view does not move the identity): 1 red. A6 (no saturation fallback): 1 red. A7 (the provider does not wait for a family to attach): 2 red. Every observed direction is turn-red, matching the prediction. (5) Cross-package types: app-shell type-check reads createObjectStackUserPreferenceFamily from the rebuilt data-objectstack .d.ts; the base declares no such symbol. That stands in for the paste-a-refused-key reverse check, which was not run separately.",
"gates": "Derived by hand from objectui package.json check:* and lint.yml / ci.yml / changeset-guard.yml / changeset-presence.yml / performance-budget.yml, since the dispatch-gates tool refuses a sister repo. Each exit code was written to a file before any pipe. At ec82faf: type-check of @object-ui/app-shell (both tsconfigs) exit 0; @object-ui/data-objectstack and @object-ui/i18n exit 0 at af031bb, neither changed since. check:control-bytes 0 ('check-control-bytes: OK (scanned 8795 tracked text file(s)')), check:new-line-citations 0 ('VERDICT new-cross-file-line-citations: 0 new citation(s)'), check:i18n-keys 0, check:i18n-drift 0, check:i18n-dead-keys 0, check:i18n-designer-parity 0, check:vi-mock-specifiers 0, check:vi-mock-inherit 0, check:vi-mock-override-shape 0, check:test-path-roots 0, check:unreferenced-sources 0, check:phantom-deps 0, check:self-import 0, check:esm-specifiers 0, check:handler-key-reads 0, check:metadata-write-doors 0, check:changeset-claims 0, check:pending-changeset-literals 0, check:unused-deps 0, check:doc-json 0, check:doc-fences 0, check-doc-links 0, and the changeset gates check-changeset-no-major / check-changeset-overwrite / check-changeset-presence / check-changeset-fixed all 0. On the console build of 831cf78: check:eager-closure 0 ('Console eager closure is 3079.3 KB gzipped ... (budget: 3119.4 KB, headroom: 40.1 KB)'; vendor-objectstack at 0.0 KB headroom, which is the installed @objectstack/* npm packages and not touched by this diff), check:eager-locale-catalogues 0, check:doc-snippets 0 ('793 of 793 block(s) judged, 0 failed'), check:doc-examples 0, check:readme-exports 0, check:docs-route-closure 0. These first ran before that build and printed PREREQUISITE NOT MET (exit 2), which is not a reading; after the scoped build they passed. They were not re-measured after the later ObjectView.tsx byte-level commits; CI's performance-budget re-measures them. ESLint on the 32 changed files: 0 errors. DECLARED NARROWING: studio-design 115/173 and views/metadata-admin 492 test files were not run locally. The shared lock was held by other agents' builds (queues of 64 to 296 s on every acquisition), and two attempts were killed by my own 590 s cap (exit 124, read as NOT MEASURED). These are declared to CI's pnpm test. PR check-runs at ec82faf: none registered yet at read time (total_count 0), so CI is in_progress / NOT MEASURED. The seat owns CI convergence.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches through scripts/pm/fleet-write/dispatch.mjs (pr_create) and scripts/pm/post-stamped.mjs (this comment), executed as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/12471/assignees (sunhaolin); POST /repos//issues/12418/comments. Plus git push of the branch (7 pushes, not REST). No label write.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: the list toolbar's density toggle and Hide Fields popover in the console are public doors, measured in consoleListStateWall-12418's CONTROL leg: under a walled fake, a density change goes to /meta/view, is answered 403 and is toasted as an error · evidence: ObjectView's relay rung onDensityChange calls persistViewPatch({ rowHeight }), and persistHiddenFields calls persistViewPatch({ hiddenFields }). Both are personal toolbar actions that still write the shared view, change it for every user, and are refused for a tenant under group/isolated posture. This is the same family as objectui#12418. The ui.list.OBJECT slot could carry both, but hiddenFields interacts with the authored columns projection (objectui#10694), so it needs a ruling and was not folded in · fold into this family's follow-up card rather than a single-point card · dedupe words: density toggle shared view, hidden fields popover persistViewPatch, toolbar writes view metadata walled, per-user display preferences",
"carrier: objectui#12440 (it edits the ViewTabBar mount next) · noted, not filed: a non-admin user has no tab-reorder door at all (the ViewTabBar mount sets reorderable:false and passes no onReorderViews; the only door is the admin-only Manage Views dialog). Now that the order is per-user, opening the door to every user is a one-prop change at that mount.",
"carrier: 承接者:无 · noted, not filed (test infrastructure, repaired in-scope because it is the pinned test this card extends): the objectui#12187 budget pin's fake framework refused an unknown filter operator only while matching rows, and an 'or' whose first arm matched every stored row never evaluated the second arm. The prefix arm went green on the unmodified pin (measured). The fake now refuses unknown operators when it reads the filter."
],
"deviations": [
"File surface beyond the claim, each named in the PR body: packages/i18n/** (2 keys x 10 packs + the namespace-count pin); docs per objectui AGENTS.md #2 (content/docs/guide/user-state-persistence.md, packages/data-objectstack/README.md); the new packages/app-shell/src/context/ListPreferencesProvider.tsx; console/tests/preferenceFramework.ts (the budget fake, extracted so the wall pin uses the same one); and 6 existing tests whose pinned behaviour this card moves (11642, 11583 x2, unboundAdapterCall, overlayPatchOnly, view-filter-fold ratchet).",
"ObjectView.tsx changes outside the A1/A2 handlers: the views-memo order read, the list seed and its readiness gate, the Reset view header button, and the header icon line. The icon line was forced: removing the views memo's try/catch let the React Compiler lint analyse ObjectViewInner for the first time, and react-hooks/static-components (error level) then refused the pre-existing icon JSX tag. It is now createElement, the ObjectDataPage convention. Warn-level compiler diagnostics in that component now appear in lint output; CI sets no --max-warnings.",
"The slot keeps columnState { order, widths } instead of the card's columnWidths: the grid reports both in one callback, and a split would leave column order writing the shared view.",
"listFilterStorage.ts is unchanged (it keeps the search term). plugin-grid and plugin-list are untouched.",
"The removed export reorderViewPatches (ObjectView.tsx) had no reader left; it was not on any package entry.",
"Local test narrowing declared (see gates).",
"The commit trailer pair is the model-free 'Claude-Session' + 'Co-authored-by: Claude', per objectui AGENTS.md; the harness reminder's model-named trailer was not used."
],
"line_budget": "n/a: no skills/** or governed ledger touched (no .claude/, AGENTS.md, docs/adr/, .github/workflows/**)",
"files_changed": [
".changeset/12418-per-user-list-state.md",
"content/docs/guide/user-state-persistence.md",
"packages/app-shell/src/console/ConsoleShell.tsx",
"packages/app-shell/src/console/tests/consoleListStateWall-12418.test.tsx",
"packages/app-shell/src/console/tests/consoleUserPreferenceBudget.test.tsx",
"packages/app-shell/src/console/tests/preferenceFramework.ts",
"packages/app-shell/src/context/ListPreferencesProvider.tsx",
"packages/app-shell/src/context/UserStateAdapters.tsx",
"packages/app-shell/src/context/tests/ListPreferencesProvider.slot-12418.test.ts",
"packages/app-shell/src/views/ObjectView.overlayPatchOnly.test.ts",
"packages/app-shell/src/views/ObjectView.toolbarWritesCompose-11642.test.tsx",
"packages/app-shell/src/views/ObjectView.tsx",
"packages/app-shell/src/views/ObjectView.unboundAdapterCall.test.ts",
"packages/app-shell/src/views/ObjectView.userListState-12418.test.tsx",
"packages/app-shell/src/views/ObjectView.viewWriteRefusal-11583.test.tsx",
"packages/app-shell/src/views/view-filter-fold.ratchet.test.ts",
"packages/app-shell/src/views/writeRefusalCensus-11583.test.ts",
"packages/data-objectstack/README.md",
"packages/data-objectstack/src/index.ts",
"packages/data-objectstack/src/userState.family-12418.test.ts",
"packages/data-objectstack/src/userState.ts",
"packages/i18n/src/tests/objectView-config-keys-retired-4730.test.ts",
"packages/i18n/src/locales/ar.ts",
"packages/i18n/src/locales/de.ts",
"packages/i18n/src/locales/en.ts",
"packages/i18n/src/locales/es.ts",
"packages/i18n/src/locales/fr.ts",
"packages/i18n/src/locales/ja.ts",
"packages/i18n/src/locales/ko.ts",
"packages/i18n/src/locales/pt.ts",
"packages/i18n/src/locales/ru.ts",
"packages/i18n/src/locales/zh.ts"
],
"cleanup": "worktree /home/user/objectui-issue-12418 removed (node_modules first, no --force, exit 0); no server or background process left by this run"
}
objectstack-fleet commentedon Oct 15, 2026
os-dev follow-up: seat review round 1 on objectui#12471
8855da7423merges objectuimaine869e41275into the branch as a merge commit, with no rebase and no force-push. The one conflict was the lucide import line inObjectView.tsx, and both sides were kept: objectui#12443'sMoreHorizontaland theSidebarItemMenuimport, plus this branch'sRotateCcw. The new head is2fcd8575af.git merge-treeagainst the newermaind25585cffbexits 0. CI has started on the head: 36 check-runs, all still queued, running or skipped.e816fd02f3and3cb0cd7763):DropdownMenuItemin the header's ⋯ menu, after the favorites entry.activeViewHasPreferenceis true, and the ⋯ trigger renders whenlistFavorite || activeViewHasPreference.console.objectView.resetView, the title isresetViewTitle, and the test id is stillobject-view-reset-view-button.2fcd8575af). The PR body still says "header button" in Clause-② item 4 and in the A5 bullet. The dev writes the body once only, so that edit is the seat's.e816fd02f3): measured that the list does emit[]: removing the last level in the Sort builder callshandleChange([]), which reachesListView'semitSortChange. TheListViewPreferencePatchdocblock now says thatsort: []is kept as "no sort", thatnullorundefinedclears the stored sort, and that Reset view is the way back. A new pin checks that a patch of{ sort: [] }storessort: [], and that this is distinct from what{ sort: null }and{ sort: undefined }store.@object-ui/app-shell(both tsconfigs),@object-ui/data-objectstackand@object-ui/i18n, ate816fd02f3. The commits after it change only tests and docs.e816fd02f3:ObjectView*(now including main'sfavoritesEntry-12427), the console preference pins,context/__tests__, data-objectstackuserState*, the i18n namespace pin and the two ratchets. That is 80 files and 699 tests.userListState-12418file passed at3cb0cd7763: 12 of 12.check:control-bytes,check:new-line-citations("0 new citation(s)"),check:i18n-keys,check:i18n-drift,check:i18n-dead-keys, the threecheck:vi-mock-*gates,check:test-path-roots,check:unreferenced-sources,check:esm-specifiers,check:handler-key-reads,check:metadata-write-doors,check:changeset-claims,check:pending-changeset-literals,check:doc-fences,check:doc-json,check-doc-links, and changesetno-major,overwriteandpresence.ablation-replace.mjs, with the restore proven against HEAD):Session:
https://claude.ai/code/session_01JZnppgHRp4sREcouhkQYDBGenerated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev follow-up: CI round on objectui#12471
6338c47e38. It is one commit on2fcd8575af, and it changes onlypackages/plugin-form/src/affordanceGrantMap-12082.test.tsx.createObjectStackUserStateAdapter > upsert. The refactor moved that upsert'sdataSource.updateanddataSource.createcalls into the sharedcreatePreferenceRowWriter > upsertinuserState.ts, which both the per-key adapter and the list-state family use. Both entries now carry the new key. Their classification (outOfFamily) and their reason are unchanged, because the reason names no handler. Nothing else in the census changed.git grepfinds no other census keyed oncreateObjectStackUserStateAdapter >or onuserState.tscall-site paths. The one other test that namesuserState.tsisone-authority-per-exported-name-6273, and it was run.affordanceGrantMap-12082andone-authority-per-exported-name-6273exit 0, 2 files and 60 tests passed.check:control-bytesandcheck:new-line-citationsboth exit 0.2fcd8575af:Test (shard 9/16)failed. Its only failure annotation is this census.Testfailed as the rollup of shard 9.Type CheckandTest (shard 3/16)succeeded, as did every other shard.Spec Main Shape Gatefailed inpackages/types/src/layout.ts(PageNodeSchema, TS2430). This PR does not touch that file.main's own scheduled runs of the gate are red atcf430cd10eand5c4deb56ab, and its last green wasa8e5b73645. So this is objectstack drift, a main-red for thedomain:devxlane, and the check is advisory on pull requests.Session:
https://claude.ai/code/session_01JZnppgHRp4sREcouhkQYDBGenerated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed ·
domain:uiseat 1 ·session_01JZnppgHRp4sREcouhkQYDB· 2026-10-15T11:58Zmaincaac3b24eeat 2026-10-15T11:45Z. It has one parent,d9d9d98684, and is an ancestor oforigin/main.mainfor all of them. The diffd9d9d98684..caac3b24eeequals the PR's own diffe869e41275..6338c47e38file by file. Twenty-three files are also blob-identical to the accepted head6338c47e38. The ten i18n packs are not blob-identical, because objectui#12461's PR feat(app-shell,i18n): the console app bar's left group is the app pill and its PREVIEW chip; an object route draws no crumb; Edit app is an icon button (objectui#12461) #12469 landed first and retiredtopbar.switchObjectfrom them. This PR's two added keys sit beside that change unchanged.Fixes #12418. The only issue closed with the merge is this card,completed.sys_user_preferencerow per object,ui.list.OBJECT, read in the console's one preference read per load. They follow the user to another browser./meta/view, so one user's click no longer changes the view for everyone, and a walled tenant is no longer refused.@object-ui/data-objectstackaddscreateObjectStackUserPreferenceFamily.6187168689, the report6190169765, and the follow-ups6190609737and6190831748;main, Reset view moved into the ⋯ menu, the empty-sort docblock);TIER_DEFAULTPASS6190683123, the ACCEPT6190697555, and the ACCEPT carried to the head6190848387;Spec Main Shape Gatebase-red note6190753666.finding,Blocked-by: #12418, now met).ObjectView.tsx/ListView.tsxnext, and starts from this merge.pm:dispatchedis removed in the same act as this note. The assignee stays, as the record of who drove it.Generated by Claude Code
feat(app-shell): a list's sort, column layout, filters and tab order …