You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
data page: the generated filter bar includes single-value relation fields (lookup / master_detail / user) through LookupValuePicker, so Organization → Members → View all can filter by user (ruling F1 on objectstack#24815) #13310
Filing gate ③: a task the maintainer set. This carries out ruling F1 on objectstack-ai/objectstack#24815: the maintainer's 「F1」 in the triage seat's chat, on the seat's re-boxed decision 6310115089. Filed by objectstack triage (session_01AavokzJ5DndAwitDXvKy4U). ⛔ Not a claim.
Reader (who acts): the objectui domain:ui seat, in one PR on the renderer of ObjectDataPage's generated filter bar.
Why
The gap: an admin on an organization's detail page opens Members → View all and can filter only by role, not by user.
Why the old ruling (E′) could not fix it: "View all" opens no declared list view (objectui#12741 deliberately anchors none), so a sys_member list-view filter would never be reached. The dev measured this (objectstack report 6309736149).
The shape (F1)
ObjectDataPage's auto-generated filter bar also offers single-value relation fields (lookup / master_detail / user).
It uses the list view's existing LookupValuePicker: search by name, scoped by the caller's permissions.
So Organization → Members → View all → User filter → typing a name gives one row for a member and zero rows for a non-member.
Not in scope:
free-text search over the page (ADR-0061 Tier 2 stays deferred);
no objectstack metadata PR (the ruling voids E′'s "metadata only here" clause);
multi-value relations.
Done when
The PR carries a browser measurement: a member gives 1 row, a non-member gives 0 rows, on an organization's Members "View all" page.
Pins: a relation field appears in the generated bar and filters by id, the picker honours the caller's read scope, and a non-relation page is unchanged.
The objectstack console pin bump follows objectui's own landing flow.
Claim: PM loop round 22 (priority:p2)
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-13310-data-page-relation-filters
Worktree: objectui-issue-13310
Domain: domain:ui
Seat: domain:ui#2
File surface:
packages/app-shell/src/views/ObjectDataPage.tsx (the auto-derived user-filter bar: USER_FILTER_TYPES and how a field becomes a filter);
the user-filter renderer that already hosts LookupValuePicker (packages/plugin-list/src/UserFilters.tsx) only where the generated bar needs it to accept a relation field;
packages/app-shell/src/views/userFilterUrlState.ts only if the uf_* URL persistence must carry a relation id;
tests beside them;
one .changeset/13310-data-page-relation-filters.md (patch for each touched package).
⛔ No objectstack metadata PR; no free-text page search (ADR-0061 Tier 2); no multi-value relations; LookupValuePicker itself is reused, not forked. Stop on breach; explain in the report.
Container & model: S, mode:subagent, model: opus (default tier; no path-derived mandate)
Clause-②: no (internal generated filter bar; no exported contract moves)
Responsibility: n/a — not a defect card (an enhancement the maintainer ruled, F1 on objectstack-ai/objectstack#24815)
Thread-read: none
Serial constraints cleared:
No open objectui PR touches ObjectDataPage.tsx, UserFilters.tsx or userFilterUrlState.ts (read at 09:25Z). Siblings objectui#13309 and objectui#13308 (same round) touch test files in other packages.
Claimed at: 2026-10-21T09:28Z
{
"issue": 13310,
"status": "done",
"branch": "claude/issue-13310-data-page-relation-filters",
"pr": "https://github.com/objectstack-ai/objectui/pull/13313",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "ObjectDataPage's generated filter bar now also offers single-value lookup / master_detail / user fields through one exported helper, deriveDataPageUserFilterFields: picklists first in declaration order (the old set and order, unchanged), then single-value relations in declaration order, under the unchanged MAX_USER_FILTERS cap of 4; hidden, unreadable and multiple:true fields are never offered. UserFilters, LookupValuePicker and userFilterUrlState were already able to render, filter (field in [id]) and persist (uf_FIELD) a relation chip, so none of them changed. Ruling 2: sys_member has 3 candidate fields, so the cap did not cost the User filter; relations-after-picklists is the order that is pinned. Pin (b): the field is offered (as LookupValuePicker already does) and an unreadable related object lists no options. The browser measurement is in the PR body: Members View All, User = Dev Admin (member) gives 1 record, User = Ada Auditor (removed from the org) gives 0, and reload keeps uf_user_id.",
"tests": "HEAD 76f01dd1a2. Under os-verify-lock: turbo build of the @object-ui/app-shell^... closure (28/28 ok), then `pnpm --filter @object-ui/app-shell type-check` (tsc --noEmit plus tsconfig.test.json, whose listFiles include the new test) exit 0, then `pnpm exec vitest run --maxWorkers=1` over the new ObjectDataPage.relationUserFilters-13310.test.tsx plus the 5 other ObjectDataPage.* files and userFilterUrlState.listState-11860: 7 files, 85 tests passed, VERDICT command-exit 0. The full packages/app-shell/ directory is declared to CI. Ablation via objectstack scripts/ablation-replace.mjs (anchor hit 1 to 0, blob d8f37661c3fe to 95dd516c3430), USER_FILTER_RELATION_TYPES emptied: 6 failed / 3 passed. Red: both (a), (b), (d), (e), relation order. Green: (c) control, picklists-keep-slots, no-fields. Predicted direction was (a), (e) and order red, (c) green. Observed (b) and (d) red too, because both assert the single-value relation chips are present. No dist hop: the test imports ./ObjectDataPage from source. Restore: blob after restore d8f37661c3fe == HEAD blob, git diff HEAD empty. Gates on 76f01dd1a2, all exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, check-hand-rolled-comment-mask.mjs, check-changeset-fixed.mjs, check-changeset-presence.mjs. eslint --no-inline-config on the 2 changed source files: exit 0, 0 errors, 14 warnings, equal to the origin/main copy (14). Narrowing evidence: config block **/*.{ts,tsx}; file count 2 from --format json; no type-aware linting in the config. Repo-wide pnpm lint is CI's. Control-byte self-scan of the 3 files: 0 hits. Browser: objectstack origin/main 28c9a2cb66 app-showcase --fresh on a private port, plus this branch's console vite, Playwright Chromium; 1 record / 0 records / reload holds; screenshots were local and are deleted.",
"mcp_calls": "0",
"api_writes": "2 relay REST writes: POST /repos/objectstack-ai/objectstack/dispatches carrying pr_create (draft, assignees baozhoutao; read-back 6990/6990 bytes identical), and POST /repos/objectstack-ai/objectstack/dispatches carrying this os-dev-report comment on objectui#13310. Not REST: 3 git pushes of the branch. Zero label writes, because objectui labels are path-derived and the dispatch named none.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed: docs/adr/0055-parameterized-bare-data-surface.md point 4 still says the bar derives from enum-ish fields; an ADR is a dated record and is outside the claimed file surface",
"carrier: none · noted, not filed: on the measured page the URL drill chip reads Organization = org_mvhxp7nxzorku6gl (raw id, not the org name), and sys_member's Title column shows the raw user id, which the sys_member source documents as the formula's known limit; polish, no class"
],
"deviations": "Ablation prediction did not name (b) and (d) going red; the observed direction is what is reported. The objectstack measurement tree is a separate detached worktree (objectstack-ui13310-measure) and is removed after the run.",
"files_changed": [
"packages/app-shell/src/views/ObjectDataPage.tsx",
"packages/app-shell/src/views/ObjectDataPage.relationUserFilters-13310.test.tsx",
".changeset/13310-data-page-relation-filters.md"
],
"gates": "all listed gates exit 0 on 76f01dd1a2; check:spec-floors not run (not in the dispatch list); CI: in_progress, not awaited"
}
Clause-②: no. The generated bar of one console page; deriveDataPageUserFilterFields is exported @internal for its test only, and no package contract moves. No contract review is owed, and the seat read the report and the diff.
Seat review: ObjectDataPage's auto-derived filter bar now goes through one helper, deriveDataPageUserFilterFields. Picklist-like fields come first, in declaration order: the old set and order, unchanged. Single-value lookup / master_detail / user fields follow, in declaration order, under the unchanged MAX_USER_FILTERS cap of 4. Hidden fields, unreadable fields and multiple: true relations are never offered. UserFilters, LookupValuePicker and userFilterUrlState already render, filter (field in [id]) and persist (uf_<field>) a relation chip, so none of them changed. No objectstack metadata changes.
Ruling 2: sys_member has 3 candidate fields, so the cap does not cost the User filter. Relations after picklists is the pinned order: an object whose picklists already fill the cap keeps exactly its old bar.
Pins: (a) a lookup and a user field appear and filter by id; (b) the field is offered, as LookupValuePicker already does, and an unreadable related object lists no options; (c) CONTROL: a picklist-only object gets the same bar; (d) a multi-value relation is not offered; (e) the filter round-trips through uf_* on reload; plus the relation order. Ablation (relation types emptied): (a), (b), (d), (e) and the order went red, with (c), picklists-keep-slots and no-fields green. (b) and (d) also go red because both assert the single-value chip is present. The restore was proven by blob.
Browser measurement (ruling F1's Done-when), in the PR body: objectstack main28c9a2cb66app-showcase plus this branch's console, in Chromium. Organization → Members → View all: User = a member gives 1 record; User = a user removed from the org gives 0; reload keeps uf_user_id.
Changeset: @object-ui/app-shellpatch.
CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
Path fork: no governed path. Seat landing.
Findings: Acceptance notes, not filed. ADR-0055 point 4 still says the bar derives from enum-ish fields; an ADR is a dated record. On the measured page the drill chip and sys_member's Title show raw ids, which the sys_member source documents as a known limit.
Next: ready + auto-merge; landing is verified by content on main.
Verified by content: each of the 3 files the PR changes has the same blob at 78bd6d732b as at the accepted head 76f01dd1a2. The merge message carries no model identifier.
Landed (ruling F1 on sys_member list view: a User filter (the searchable user picker), so an organization's members can be found by name from the Members tab's View all objectstack#24815):ObjectDataPage's auto-derived filter bar offers single-value lookup / master_detail / user fields after the picklists, under the unchanged cap of 4, through the existing LookupValuePicker; a selection filters by the related id and persists as uf_<field>. Multi-value relations, hidden and unreadable fields are not offered; picklist-only objects keep their bar. Measured in a browser: Organization → Members → View all, User = a member gives 1 record, a removed user gives 0, and reload keeps the filter.
Next: the objectstack console pin bump follows objectui's own landing flow.
Activity
objectstack-fleet commentedon Oct 21, 2026
Claim: PM loop round 22 (
priority:p2)Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-13310-data-page-relation-filtersWorktree:
objectui-issue-13310Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/views/ObjectDataPage.tsx(the auto-derived user-filter bar:USER_FILTER_TYPESand how a field becomes a filter);LookupValuePicker(packages/plugin-list/src/UserFilters.tsx) only where the generated bar needs it to accept a relation field;packages/app-shell/src/views/userFilterUrlState.tsonly if theuf_*URL persistence must carry a relation id;.changeset/13310-data-page-relation-filters.md(patch for each touched package).⛔ No objectstack metadata PR; no free-text page search (ADR-0061 Tier 2); no multi-value relations;
LookupValuePickeritself is reused, not forked. Stop on breach; explain in the report.Container & model:
S,mode:subagent,model: opus(default tier; no path-derived mandate)Clause-②: no (internal generated filter bar; no exported contract moves)
Responsibility: n/a — not a defect card (an enhancement the maintainer ruled, F1 on objectstack-ai/objectstack#24815)
Thread-read: none
Serial constraints cleared:
ObjectDataPage.tsx,UserFilters.tsxoruserFilterUrlState.ts(read at 09:25Z). Siblings objectui#13309 and objectui#13308 (same round) touch test files in other packages.Claimed at: 2026-10-21T09:28Z
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
os-dev-report
{ "issue": 13310, "status": "done", "branch": "claude/issue-13310-data-page-relation-filters", "pr": "https://github.com/objectstack-ai/objectui/pull/13313", "session": "session_01XVp19E1MYUTFM3dnkwz8gB", "premise_still_valid": true, "summary": "ObjectDataPage's generated filter bar now also offers single-value lookup / master_detail / user fields through one exported helper, deriveDataPageUserFilterFields: picklists first in declaration order (the old set and order, unchanged), then single-value relations in declaration order, under the unchanged MAX_USER_FILTERS cap of 4; hidden, unreadable and multiple:true fields are never offered. UserFilters, LookupValuePicker and userFilterUrlState were already able to render, filter (field in [id]) and persist (uf_FIELD) a relation chip, so none of them changed. Ruling 2: sys_member has 3 candidate fields, so the cap did not cost the User filter; relations-after-picklists is the order that is pinned. Pin (b): the field is offered (as LookupValuePicker already does) and an unreadable related object lists no options. The browser measurement is in the PR body: Members View All, User = Dev Admin (member) gives 1 record, User = Ada Auditor (removed from the org) gives 0, and reload keeps uf_user_id.", "tests": "HEAD 76f01dd1a2. Under os-verify-lock: turbo build of the @object-ui/app-shell^... closure (28/28 ok), then `pnpm --filter @object-ui/app-shell type-check` (tsc --noEmit plus tsconfig.test.json, whose listFiles include the new test) exit 0, then `pnpm exec vitest run --maxWorkers=1` over the new ObjectDataPage.relationUserFilters-13310.test.tsx plus the 5 other ObjectDataPage.* files and userFilterUrlState.listState-11860: 7 files, 85 tests passed, VERDICT command-exit 0. The full packages/app-shell/ directory is declared to CI. Ablation via objectstack scripts/ablation-replace.mjs (anchor hit 1 to 0, blob d8f37661c3fe to 95dd516c3430), USER_FILTER_RELATION_TYPES emptied: 6 failed / 3 passed. Red: both (a), (b), (d), (e), relation order. Green: (c) control, picklists-keep-slots, no-fields. Predicted direction was (a), (e) and order red, (c) green. Observed (b) and (d) red too, because both assert the single-value relation chips are present. No dist hop: the test imports ./ObjectDataPage from source. Restore: blob after restore d8f37661c3fe == HEAD blob, git diff HEAD empty. Gates on 76f01dd1a2, all exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, check-hand-rolled-comment-mask.mjs, check-changeset-fixed.mjs, check-changeset-presence.mjs. eslint --no-inline-config on the 2 changed source files: exit 0, 0 errors, 14 warnings, equal to the origin/main copy (14). Narrowing evidence: config block **/*.{ts,tsx}; file count 2 from --format json; no type-aware linting in the config. Repo-wide pnpm lint is CI's. Control-byte self-scan of the 3 files: 0 hits. Browser: objectstack origin/main 28c9a2cb66 app-showcase --fresh on a private port, plus this branch's console vite, Playwright Chromium; 1 record / 0 records / reload holds; screenshots were local and are deleted.", "mcp_calls": "0", "api_writes": "2 relay REST writes: POST /repos/objectstack-ai/objectstack/dispatches carrying pr_create (draft, assignees baozhoutao; read-back 6990/6990 bytes identical), and POST /repos/objectstack-ai/objectstack/dispatches carrying this os-dev-report comment on objectui#13310. Not REST: 3 git pushes of the branch. Zero label writes, because objectui labels are path-derived and the dispatch named none.", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed: docs/adr/0055-parameterized-bare-data-surface.md point 4 still says the bar derives from enum-ish fields; an ADR is a dated record and is outside the claimed file surface", "carrier: none · noted, not filed: on the measured page the URL drill chip reads Organization = org_mvhxp7nxzorku6gl (raw id, not the org name), and sys_member's Title column shows the raw user id, which the sys_member source documents as the formula's known limit; polish, no class" ], "deviations": "Ablation prediction did not name (b) and (d) going red; the observed direction is what is reported. The objectstack measurement tree is a separate detached worktree (objectstack-ui13310-measure) and is removed after the run.", "files_changed": [ "packages/app-shell/src/views/ObjectDataPage.tsx", "packages/app-shell/src/views/ObjectDataPage.relationUserFilters-13310.test.tsx", ".changeset/13310-data-page-relation-filters.md" ], "gates": "all listed gates exit 0 on 76f01dd1a2; check:spec-floors not run (not in the dispatch list); CI: in_progress, not awaited" }Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
ACCEPT — PR #13313 @
76f01dd1a23fe7669ef4e7c064e3770fa7d2f5b5·domain:uiseat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)deriveDataPageUserFilterFieldsis exported@internalfor its test only, and no package contract moves. No contract review is owed, and the seat read the report and the diff.ObjectDataPage's auto-derived filter bar now goes through one helper,deriveDataPageUserFilterFields. Picklist-like fields come first, in declaration order: the old set and order, unchanged. Single-valuelookup/master_detail/userfields follow, in declaration order, under the unchangedMAX_USER_FILTERScap of 4. Hidden fields, unreadable fields andmultiple: truerelations are never offered.UserFilters,LookupValuePickeranduserFilterUrlStatealready render, filter (field in [id]) and persist (uf_<field>) a relation chip, so none of them changed. No objectstack metadata changes.sys_memberhas 3 candidate fields, so the cap does not cost the User filter. Relations after picklists is the pinned order: an object whose picklists already fill the cap keeps exactly its old bar.lookupand auserfield appear and filter by id; (b) the field is offered, asLookupValuePickeralready does, and an unreadable related object lists no options; (c) CONTROL: a picklist-only object gets the same bar; (d) a multi-value relation is not offered; (e) the filter round-trips throughuf_*on reload; plus the relation order. Ablation (relation types emptied): (a), (b), (d), (e) and the order went red, with (c), picklists-keep-slots and no-fields green. (b) and (d) also go red because both assert the single-value chip is present. The restore was proven by blob.main28c9a2cb66app-showcaseplus this branch's console, in Chromium. Organization → Members → View all: User = a member gives 1 record; User = a user removed from the org gives 0; reload keepsuf_user_id.@object-ui/app-shellpatch.sys_member's Title show raw ids, which thesys_membersource documents as a known limit.Next: ready + auto-merge; landing is verified by content on
main.Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gBmain78bd6d732b.78bd6d732bas at the accepted head76f01dd1a2. The merge message carries no model identifier.ObjectDataPage's auto-derived filter bar offers single-valuelookup/master_detail/userfields after the picklists, under the unchanged cap of 4, through the existingLookupValuePicker; a selection filters by the related id and persists asuf_<field>. Multi-value relations, hidden and unreadable fields are not offered; picklist-only objects keep their bar. Measured in a browser: Organization → Members → View all, User = a member gives 1 record, a removed user gives 0, and reload keeps the filter.pm:dispatchedis removed.Generated by Claude Code