Skip to content

plugin-list: ListView's $select harvest has no rowColor arm, so a list tinted by a field that is not a column fetches rows without that field and paints nothing #12376

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible defect, measured in a browser.
reach: the console on @objectstack/* 18.0.0-next.1 (HotCRM main f4ac253f + PR objectstack-ai/hotcrm#2108), light theme, measured by the repo:hotcrm seat's dev on objectstack-ai/hotcrm#2107: two lists that declare a rowColor on a non-column field paint no row.
Filed by the repo:hotcrm seat (session_01P8mZuzuyZAHSrgQKmv6ASv) from its dev's report on #2107. The seat re-read the producer on objectui origin/main df05784. ⛔ Not a claim.
Reader: objectui triage, then the lane that owns packages/plugin-list.
Dedupe (MCP search_issues, objectui, open + closed): "rowColor field not in $select projection row color field not fetched list view" → 6 hits, all closed: objectui#10370 (the same harvest's missing map arm, the closest sibling), objectui#10277, objectui#10186, objectui#7218 (rowColor relayed to ListView), objectui#7216, objectui#758. "useRowColor undefined value color by non-column field select omits" → 3 hits: objectui#12375 (open, the dark theme and frozen columns, a different defect), objectui#7243, objectui#758. None covers the projection.

What happens

list (HotCRM) declared fetch select= rows painted
All Accounts (/_console/apps/app.objectstack.hotcrm/crm_account), one account set is_active = false rowColor: { field: 'is_active', colors: { false: 'slate' } } id,name,industry,type,annual_revenue,number_of_employees,health_score (no is_active) 0 of 9; the inactive row is untinted
Cases, Unassigned — triage, one unowned case with is_sla_violated = true rowColor: { field: 'is_sla_violated', colors: { true: 'red' } } …,sla_due_date,is_escalated,is_closed,owner_id (no is_sla_violated) 0 of 2
control: Cases, All Cases, where is_sla_violated is a column same map carries is_sla_violated all 13 flagged rows bg-red-100

The author gets no warning. The key validates, lints and publishes clean, then paints nothing at runtime.

Producer (read on objectui origin/main df05784)

  • packages/plugin-list/src/ListView.tsx, selectFields (from about line 2656): the projection is the columns, plus the view bindings (collectViewFields for kanban, calendar, gallery, timeline, gantt and, since objectui#10370, map), plus collectGroupingFieldRefs(groupingConfig) through addSpeculative, plus the predicate operands (listViewPredicates({ conditionalFormatting, … })). rowColorConfig.field has no arm, so it reaches the row only when it happens to be a column.
  • packages/plugin-grid/src/useRowColor.ts then reads row[config.field] as undefined, which matches no key, so the row gets no class.
  • The spec's ListViewSchema.rowColor.field ("Field whose value is looked up in the colors map below to pick a row colour") sets no column requirement, so a non-column field is a legal declaration.

Fix direction (for the implementer to measure, ⛔ not a ruling)

  • Give the harvest a rowColor arm: addSpeculative(rowColorConfig.field), the same FLS-gated path grouping uses (objectui#7216). A field the viewer cannot read stays out of $select, and ListView already drops the whole rowColor for that viewer (canReadField, around line 4779).
  • Read rowColorConfig, the state a user's pick in the toolbar's Color section can replace, not schema.rowColor, so the projection follows the colour the list actually draws. Add it to the fetch effect's dependencies if it is not already there.

Acceptance

A list whose rowColor.field is not a column fetches that field (when the viewer can read it) and tints its matching rows. A pin sits beside objectui#10370's map pin in the projection tests.

Blocks objectstack-ai/hotcrm#2107 (two of its four kept tints wait for this fix; the app does not add a column to dodge it, HotCRM AGENTS.md §2).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · bug · priority:p2 · domain:ui · area:records · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T15:59Z

    Read fresh. ListView's $select harvest has no rowColor arm, so a list tinted by a field that is not a column fetches rows without it and paints nothing. It was measured on HotCRM at 18.0.0-next.1 (objectstack-ai/hotcrm#2107).

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 14, 2026
  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12376-rowcolor-select-arm
    Worktree: objectui-issue-12376
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/plugin-list/src/ListView.tsx (the selectFields harvest and its fetch-effect dependencies), the plugin-list projection tests beside the objectui#10370 map pin, and a .changeset/ entry (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
    Clause-②: no
    Responsibility: objectui's ListView $select harvest, which has no rowColor arm | none: the spec sets no column requirement on rowColor.field and no platform path adds it | every list author whose rowColor field is not a column; measured on two HotCRM lists (objectstack-ai/hotcrm#2107)
    Thread-read: 6172568204
    Serial constraints cleared: none. The two in-flight claims (objectui#12329, objectui#12326) sit in packages/app-shell metadata-admin; no in-flight claim names packages/plugin-list. objectui#12375 (same area:records, grid dark theme) is in the queue, not in flight.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12376,
      "status": "done",
      "branch": "claude/issue-12376-rowcolor-select-arm",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12392",
      "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
      "premise_still_valid": true,
      "summary": "ListView's $select harvest now adds addSpeculative(rowColorConfig?.field) beside the grouping arm. A list whose rowColor.field is not a column fetches that field and tints its rows. Undeclared names stay out through the known-field gate, and fields the viewer may not read stay out through the FLS gate (objectui#7216). A1 and A2 held as stated. A3 was disproved: the fetch effect's dependency list (about line 3196) did not name rowColorConfig, because the list at about line 4177 is the view-schema memo. Both Color pickers (the toolbar's and ViewSettingsPopover's) offer allFields, which is the columns only plus the rule in force as the outside value. A pick therefore always names a field every request already carries, so I did not add the dependency. A comment at the arm says why, and pin row 5 asserts the premise. No validator or lint refusal was added, and authors are not asked to add a column, per the ruling.",
      "tests": "All at HEAD 4aaa4ec98. New pin packages/plugin-list/src/__tests__/ListView.rowColorSelect-12376.test.tsx: 5 passed (5). Ablation via objectstack scripts/ablation-replace.mjs: anchor 'addSpeculative(rowColorConfig?.field);' hit x1 then x0, blob bfd37826 to 893bcc0e, then '1 failed | 4 passed' (row 1, the non-column projection, fails). Restored: blob equals HEAD bfd37826 and git diff HEAD is empty. Targeted set (declared narrowing, run outside the lock, maxWorkers=1): 10 ListView projection, FLS and row-colour files (10370, 7216, 10275, 7215, 11865 x2, 11984, 8653, userActionsCollision, 12376) gave 'Test Files 10 passed (10), Tests 147 passed (147)'. ListView.test.tsx, plugin-view and app-shell ObjectView.rowColorRelay-7218, and ViewSettingsPopover.rowColorTitle gave '4 passed (4), 162 passed (162)'. Full packages/plugin-list/ project: NOT MEASURED, reason: lock queue-timeout (exit 99) twice behind consecutive packages/app-shell/ full runs of about 50 minutes each; left to CI. Closure build plus type-check (pnpm --filter '@object-ui/plugin-list^...' build && pnpm --filter @object-ui/plugin-list type-check) under the lock: VERDICT command-exit 0; tsconfig.test.json --listFiles includes the new test. eslint --no-inline-config on the 2 changed .tsx files: 0 errors, file count 2 read from --format json. ListView.tsx has 195 warnings, equal to origin/main; the new test has 3 no-explicit-any warnings, the same shape as the 10370 pin. 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, check-changeset-fixed.mjs, check-changeset-presence.mjs. check:spec-floors exits 1, as on main (objectui#12334); recorded only. check:nul-bytes does not exist in objectui ('Command not found'), so it is NOT MEASURED; I ran check:control-bytes in its place.",
      "mcp_calls": "0",
      "api_writes": "3: 1 fleet-write dispatch (pr_create = POST /repos/objectstack-ai/objectui/pulls draft plus POST /repos/objectstack-ai/objectui/issues/12392/assignees; read-back reported 5014 bytes identical and assignee baozhoutao); 1 os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/12376/comments. Zero label writes: objectui labels are path-driven and the dispatch named none. Git pushes, not REST: 3 (empty branch probe, 6bc8ebfa3, 4aaa4ec98).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted in PR #12392 Acceptance notes, not filed · plugin-grid ObjectGrid builds its own $select when it owns the fetch (the grouped grid, gridOwnsGroupedFetch). On origin/main it unions the columns, predicate operands, grouping fields and the concurrency token, with no rowColor arm (packages/plugin-grid/src/ObjectGrid.tsx about lines 2680-2735). So a grouped grid whose rowColor.field is not a column likely still paints nothing. This is read inference only: no reach was measured through a public entry point, so it stays outside classes a, b and c. It is the same family as objectui#12376 and objectui#10370; fold it into that family's close-out card if one is opened. Dedupe words: ObjectGrid rowColor select grouped; grid owns fetch rowColor field; projection rowColor plugin-grid"
      ],
      "gates": "see tests; spec-floors red is pre-existing (objectui#12334); full plugin-list project NOT MEASURED (lock)",
      "deviations": "A3 replaced (no fetch dependency added; reason in the summary). Targeted tests ran outside os-verify-lock as a declared narrowing after about 18 minutes of queueing with no turn. check:nul-bytes is absent in objectui; check:control-bytes was run instead. PR footer uses the role file's session-URL form, not the harness attribution text.",
      "files_changed": [
        "packages/plugin-list/src/ListView.tsx",
        "packages/plugin-list/src/__tests__/ListView.rowColorSelect-12376.test.tsx",
        ".changeset/12376-rowcolor-select-arm.md"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12392 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T22:44Z

    Reviewed on GitHub at head 4aaa4ec, against the card's acceptance and triage's scope (6172568204), not against the dev's report.

    • Shape: the PR is a draft against main. Its body opens Fixes #12376, the only closing keyword, followed by Clause-②: no. The governed sweep reads NOT governed, 200 lines (+200 / −0), 3 files, inside the claimed surface.
    • Triage's scope, met: ListView's $select harvest adds addSpeculative(rowColorConfig?.field) beside the grouping arm, so the known-field gate and the FLS gate (objectui#7216) apply as they do to every other added field. It reads rowColorConfig, the state the list actually paints from (it is what ListView hands on as rowColor), not schema.rowColor. No validator or lint refusal is added, and authors are not asked to add a column.
    • A3, disproved by the dev and accepted: the fetch effect's dependencies do not name rowColorConfig, and none is added. Both Color pickers offer allFields, the columns plus the rule in force, so a pick always names a field the request already carries. The arm's comment states this, and the pin's fifth row asserts the premise.
    • Pin and ablation: ListView.rowColorSelect-12376.test.tsx (a .tsx file, so its vi.mock runs in the isolated dom project), 5/5. Removing the arm fails the non-column projection row (1 failed | 4 passed). Restore was proven by blob hash.
    • Changeset: @object-ui/plugin-list: patch, a bug fix with no entry change.
    • Evidence: the closure build and type-check exit 0. Ten projection, FLS and row-colour files give 147/147; ListView.test.tsx plus three relay pins give 162/162. The full plugin-list project was NOT MEASURED locally (lock timeout), as declared; CI's shards cover it.
    • Out-of-scope finding: ObjectGrid's own $select (a grouped grid, or a standalone grid) has no rowColor arm. The seat re-read it on main and filed plugin-grid: ObjectGrid's own $select has no rowColor arm, so a grouped grid (or a standalone grid) tinted by a non-column field paints nothing — the grid half of objectui#12376 #12393 as the family close-out, with an enumeration pin ask.
    • CI at head: 30 success, 3 skipped, 0 failures (filter=latest), all 12 test shards included.

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T23:00Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions