Skip to content

fix(app-shell): "Add filter" in the Studio list-view inspector adds a row that can be edited - #26821

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-jlfl08
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-jlfl08

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Fixes #26738

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:Studio 列表视图检查器(以及标签页预设)里的筛选器控件,现在自己保存「还没填完」的条件行。点「Add filter」会出现一行可编辑的条件;填完之后才把这条规则写进视图。
  • 为什么改:控件以前每次渲染都从已保存的规则重新生成行,而保存端的折叠(foldFilterGroupToSpecRules)会正确地丢掉未填完的行,于是新加的空行在下一次渲染就消失了,Studio 里根本无法给列表视图加筛选。
  • 风险与回滚:低。只改 app-shell 一个控件的状态持有方式;保存规则不变(未填完的条件仍然不会写进视图),不新增任何元数据键,spec 不动。回滚即 revert 本 PR。
  • 先看:ui/packages/app-shell/src/views/metadata-admin/widgets.tsx 里 FilterBuilderField 的 draft / seededFrom 两个状态和 handle 里新增的「与已存规则相同则不写」判断;新测试 widgets.filterBuilderHeldRow-26738.test.tsx。
  • 两分钟验证:cd ui && pnpm exec vitest run packages/app-shell/src/views/metadata-admin/widgets.filterBuilderHeldRow-26738.test.tsx,预期 4 个用例全绿;或在 Studio Interfaces 打开某对象的列表视图检查器,Filter →「Add filter」,出现一行,填入值后视图草稿里出现该 filter。
  • 需要你做的:无,席位落地。

What changes

FilterBuilderField (the filter-builder widget the Studio list-view inspector's Filter row uses, and the per-tab filter of filter-mode tab presets) built the FilterBuilder's row group from the stored rules on every render. The builder's "Add filter" inserts a blank row; the save-side fold drops a row that is not complete yet, as it must; the host stored the unchanged rules and re-rendered, and the re-derived group replaced the builder's rows, so the new row disappeared before it could be edited.

The widget now holds the builder's row group in its own state:

  • every builder change is folded; a refused fold (OR over several rows, a nested group) still toasts and writes nothing;
  • an accepted fold updates the held rows, and writes only when the folded rules differ from what is stored. An incomplete row therefore stays on screen and writes nothing; completing it writes exactly the complete rule;
  • when the stored rules change and are not the echo of this builder's own write (another editor, a reload), the held rows are re-seeded from what is stored. The comparison keys on the rules' JSON, never on an array's identity.

viewFilterFold.ts is unchanged: what is persisted is decided by the same fold as before.

Tests

New widgets.filterBuilderHeldRow-26738.test.tsx mounts the real filter-builder widget in a host that writes the way ObjectListViewInspector does (a new body object on every onChange, filter dropped when empty):

  • "Add filter" adds an editable row, writes nothing while it is incomplete, and completing it writes [{ field: 'title', operator: 'equals', value: 'open' }] with the row still on screen;
  • a second, incomplete row is held beside a stored rule without a write;
  • a stored filter shows as its row and summary, opening it writes nothing, and editing the value away and back writes the stored rule unchanged (round-trip);
  • CONTROL: a stored filter changed from outside re-seeds the rows.

Reverse verification (one-off, not kept): with the fix committed, widgets.tsx restored to base c8583f80 in the working tree only (groupOfStoredRules occurrences 3 → 0) made the new file red, Tests 3 failed | 1 passed (4); each red is the vanished row ("expected [] to have a length of 1 but got +0"). The round-trip case is green on base too, as a preservation pin should be. Restored with git checkout HEAD -- … (occurrences back to 3, git diff HEAD empty).

Acceptance notes

Verification

All readings at head 5221c34d (base c8583f80), under scripts/pm/os-verify-lock.sh.

Touched package: @object-ui/app-shell
  • Dependency closure: pnpm exec turbo run build --concurrency=2 --filter='@object-ui/app-shell^...', 63 tasks, VERDICT command-exit 0.
  • pnpm --filter @object-ui/app-shell run type-check (tsc --noEmit, then tsc -p tsconfig.test.json): VERDICT command-exit 0, zero TS errors.
  • New test file: Test Files 1 passed (1), Tests 4 passed (4).
  • Narrowed app-shell run: every app-shell test file naming the metadata-admin widgets module, filter-builder-trigger, FilterBuilderWidget, viewFilterFold, ObjectListViewInspector, FilterModeWidget or filter-mode (52 files): Test Files 52 passed (52), Tests 754 passed (754). The rest of app-shell is left to CI's Test UI shards.
Derived gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 34 commands at 5221c34d; each ran with its exit code captured before any pipe, plus pnpm check:changeset-fixed (its roster sits under .changeset/). --ran reconciliation: "34 derived famil(ies) accounted for — 34 run, 0 NOT-MEASURED".

  • node scripts/check-adr-0087-registration.mjs --base origin/main → exit 0
  • node scripts/check-adr-0087-registration.mjs --self-test → exit 0
  • node scripts/check-changeset-no-major.mjs --base origin/main → exit 0
  • node scripts/check-closing-keyword-parity.mjs → exit 0
  • node scripts/check-closing-keyword-parity.mjs --self-test → exit 0
  • node scripts/check-comment-mask-corpus.mjs → exit 0
  • node scripts/check-empty-changeset.mjs --base origin/main → exit 0
  • node scripts/check-empty-changeset.mjs --self-test → exit 0
  • node scripts/check-sdui-manifest.mjs → exit 0
  • node scripts/check-sdui-manifest.mjs --self-test → exit 0
  • node scripts/pm/release-rehearsal-clone.mjs --self-test → exit 0
  • node scripts/release-pending-publish.mjs --self-test → exit 0
  • pnpm --filter @objectstack/spec run check:duration-unit-keys → exit 0
  • pnpm check:changeset-gate-self-tests → exit 0
  • pnpm check:closed-ceremony-text → exit 0
  • pnpm check:cross-package-test-inputs → exit 0
  • pnpm check:dispatcher-error-vocabulary → exit 0
  • pnpm check:driver-memory-census → exit 0
  • pnpm check:engine-double-contract → exit 0
  • pnpm check:gitlink-declared → exit 0
  • pnpm check:nul-bytes → exit 0
  • pnpm check:pm-changeset-deadline-census → exit 0
  • pnpm check:published-files → exit 0
  • pnpm check:query-options-erasure → exit 0
  • pnpm check:refd-timer-probe → exit 0
  • pnpm check:skill-identifier-liveness → exit 0
  • pnpm check:test-source-alias → exit 0
  • pnpm check:tier-file-adoption → exit 0
  • pnpm check:type-check-coverage → exit 0
  • pnpm check:type-check-debt → exit 0
  • pnpm check:undeclared-dep-imports → exit 0
  • pnpm check:watch-hint-literal → exit 0
  • pnpm check:where-matcher → exit 0
  • pnpm check:changeset-fixed → exit 0
  • pnpm --dir ui exec vitest run scripts/ → exit 0

pnpm --dir ui exec vitest run scripts/: Test Files 178 passed | 2 skipped (180), Tests 5065 passed | 2 skipped (5067). pnpm check:new-line-citations (from ui/): 0 new citation(s), exit 0.


Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_01QsR2jV9H4DGK4phGzhzdZ4

…plete, so Add filter adds an editable row

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jV9H4DGK4phGzhzdZ4
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 27, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Seat note · domain:ui#4 · 2026-10-27T17:54Z · head 5221c34d895ef5b6ae9a7352af2c09e4e8b673ec

Test UI (3/16) failed on one test, packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.i18n-10804.test.tsx ("zh: the unknown reference reads engine.flowRef.unknownWithSuggestion"): engine.inspector.flowNode.kind read the English Node under zh-CN. The other 2007 tests in the shard passed.

This is not this PR's failure. The diff touches only FilterBuilderField in metadata-admin/widgets.tsx, its new test and a changeset; nothing in the flow-node inspector strings. PR #26780 (merged) moved the engine.inspector.flowNode.* rows into @object-ui/i18n's lazily loaded studio catalogue, and this test reads a zh row without awaiting it, so it fails when no earlier test in its worker loaded the catalogue. The fix is #26692's PR #26800 (seat 1, not yet merged), which makes this file await loadStudioCatalogue('zh'). It is another seat's test-only fix outside this card's surface, so it is not ported; once #26800 merges, this branch merges main if still red.

The seat re-runs the failed jobs once. A second failure counts as real.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Seat note · domain:ui#4 · 2026-10-27T18:32Z

Test UI (5/16) on ff6bcc64 is red on actionKeys.pin.test.ts › "lists every key the spec ActionSchema declares", missing: ['disabledReason']. The red is not from this PR. #26786 merged at 13dc413f and added the key to the spec's ActionSchema. Main's own Test UI (9/16) at aeb9cf0d is red on the same assertion. It is filed as #26849 (p0), and that fix is dispatched now. This PR does not carry the fix. Once #26849 merges, the thread merges main and the seat re-reads CI. Every other check on this head is green or skipped.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · seat domain:ui#4 · session_01QsR2jTfvjNTaR29ehLk26T · 2026-10-27T19:54Z · head 2f3c2d566f0ea1e8b12dd47974ae101d9dfbfee5

  1. Shape: draft, base main, first line Fixes #26738. Clause-②: no and Metadata-protocol: none match the claim (6448194819), in the body and in the changeset (@object-ui/app-shell patch). Three files, inside the surface: metadata-admin/widgets.tsx (FilterBuilderField), one new test beside it, one root changeset. The two test(app-shell): flowCanvasChip-11665 awaits the lazy studio zh catalogue before reading the tooltip #26800 test ports dropped out of the diff once main carried test(app-shell): flowCanvasChip-11665 awaits the lazy studio zh catalogue before reading the tooltip #26800 (see 4). viewFilterFold.ts is untouched (allowed by the surface, not needed). No packages/spec/**, server or new key.

  2. Premise, measured: the seat read the diff. On main, FilterBuilderField rebuilt the builder's group from the stored rules on every render; the fold drops an incomplete row (as it must), so the blank row "Add filter" inserts vanished on the next render. Now the group is held in state: every builder change is folded; a refused fold still toasts and writes nothing; an accepted fold updates the held rows and writes only when the folded rules differ from what is stored, by JSON content, not identity (ui/AGENTS.md chore: version packages #10). A stored-rule change that is not this builder's own echo re-seeds the held rows. Incomplete rules still never reach the view, which keeps the order's ⛔.

  3. Gates, pinned to the head: 52 check-runs on the head: 43 success, 9 skipped, 0 failure, 0 pending. · check-governed-merges --pr 26821: NOT governed, 0 of 3 paths hit the register (215 changed lines). mergeable_state: clean.

  4. Accepted deviations:

  5. Out of scope: the thread notes in the PR that the inspector rebuilt the body on every emit, so a no-op emit wrote an unchanged draft; the widget no longer emits then, and nothing else is owed. No open question. Skills-docs: is not owed.

  6. Prose face, checked sentence by sentence against the diff: each changeset claim matches a hunk and one of the four test cases:

    • "Add filter" adds an editable row that writes nothing until complete, then the complete rule;
    • a second incomplete row is held beside a stored rule without writing;
    • a stored filter shows as its rows and round-trips unchanged;
    • control: an outside change re-seeds the rows.

    The new file ran 3 failed / 1 passed on the base and 4/4 with the fix.

Landing: no contract review is owed (no published schema, no governed text, Clause-②: no). The seat marks the PR ready and arms auto-merge. On MERGED, Fixes #26738 closes the card.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 27, 2026 19:55
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 27, 2026 19:55
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 35ee2ad Oct 27, 2026
53 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-jlfl08 branch October 27, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio Interfaces: the list-view inspector's Filter "Add filter" adds no row — no list-view filter can be authored in Studio

2 participants