Repository navigation
Commit f662c71
docs(skills): objectstack-ui list-views teaches the view filter any-of group
<!-- claude-projects-attribution: {"github_login":"os-tesla"} -->
_Requested by **Tesla** · [project
thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6JaoX9GDX2cb55BEVTSE1eYheJ)_
Fixes #28476
Clause-②: no
Metadata-protocol: none
domain:skills#1 · os-tesla · session_01L9qibz4G9FrLR4TRExx6gn
## 维护者速读
- 改了什么:对外发布的 objectstack-ui 技能包 `rules/list-views.md` § Filtering
补教列表视图过滤器的"任一满足"组 `{ or: [rule, ...] }`——它是 `filter`
列表的一个元素,组内任一条规则命中即命中,组与旁边的元素仍是 AND;组内只放平规则、不能为空;控制台筛选器的 OR
开关存成一个组,组与其他条件并列时生效但在筛选器里只读。附一条 eval,外加一个 changeset。
- 为什么改:`ViewFilterOrGroupSchema` 和控制台读取(PR #28475)都已在 `main`,但技能只教平的 AND
规则,AI 作者遇到"打开的、或最近完成的"要么写两个视图,要么编一个 spec 拒收的 `$or`。
- 风险与回滚:纯文档,不改 schema 或行为;token 天花板一行不动,新增全部以同文件删减支付。回滚 = 撤这个 PR。
- 先看:`skills/objectstack-ui/rules/list-views.md` § Filtering
的新例子和两段说明;同节的运算符清单改成了 spec 的 `VIEW_FILTER_OPERATORS`(旧行列了四个 spec 拒收的拼法,见
Acceptance notes)。
- 两分钟验证:`node scripts/check-skills-token-ratchet.mjs`,预期 `list-views.md`
3106/3129;`git grep -n "or: \["
skills/objectstack-ui/rules/list-views.md
skills/objectstack-ui/evals/views-apps-actions-pages.json` 各至少一处命中。
- 需要你做的:受管面(`skills/**`,Tier H)——席位做 Fable 契约复审并写席位核对后,由 os-zhuang
审批落地;dev 不翻 ready、不请求审阅。
## What changes
One commit, the three files the order names. Nothing under `SKILL.md`,
`rules/pages*`, `references/pages.md` or `references/_index.md`.
| Where | What the skill now says | Read against (`main` 23d1303) |
|:--|:--|:--|
| `skills/objectstack-ui/rules/list-views.md` § Filtering, intro +
example + note | `filter` is a list whose elements must all match; an
element is a rule `{ field, operator, value }` or an any-of group `{ or:
[rule, ...] }` that matches when any of its rules does, still ANDed with
the elements beside it. Example: open OR urgent, AND assigned to
`{current_user_id}`. A group holds flat rules only (no group in a group)
and never `or: []`; `$or`, `any` / `anyOf`, `logic` / `conditions` on a
rule are refused naming the shape. The Console builder saves its OR
toggle as one group and edits a filter that is exactly one group; a
group beside other elements applies but shows read-only. |
`packages/spec/src/ui/view.zod.ts:1106-1123` (`isViewFilterOrGroup`),
`:1189-1223` (`ViewFilterOrGroupSchema`: `.min(1)` refusal, one level),
`:507-534` (`VIEW_FILTER_NESTED_GROUP_GUIDANCE`,
`VIEW_FILTER_OR_SPELLING_GUIDANCE` for `$or` / `any` / `anyOf` / `logic`
/ `conditions`); console lowering
`ui/packages/core/src/utils/filter-converter.ts:1390-1418`
(`viewFilterOrGroupToNode`, `['or', ...]` inside the list's AND);
builder `ui/packages/app-shell/src/views/viewFilterFold.ts:186-190`,
`:228` (`logic: 'or'` folds to `[{ or: rules }]`);
`ui/packages/app-shell/src/views/viewFilterOrGroup.roundTrip-28370.test.tsx:116-156`
(reads back as an OR group; a group beside another condition is shown
read-only); `content/docs/ui/views.mdx` § Base filter |
| same section, the operator line | "Operators (no others)" lists the
spec's `VIEW_FILTER_OPERATORS` verbatim: `equals`, `not_equals`,
`contains`, `not_contains`, `icontains`, `starts_with`, `ends_with`,
`greater_than`, `less_than`, `greater_than_or_equal`,
`less_than_or_equal`, `in`, `not_in` (list values), `is_empty`,
`is_not_empty`, `is_null`, `is_not_null`, `before`, `after`, `between` |
`packages/spec/src/ui/view.zod.ts:315-325` (the enum), `:375-400`
(`VIEW_FILTER_OPERATOR_ALIASES` — none of the four removed spellings is
there either), `:1071` (`z.enum(VIEW_FILTER_OPERATORS)` after the alias
fold) |
| `skills/objectstack-ui/evals/views-apps-actions-pages.json` | eval 12:
an 'Attention' list on `task` (open or urgent, for the signed-in user)
in ONE `listViews` entry whose `filter` carries one `{ or: [...] }`
beside the `{current_user_id}` rule; `must_contain` `listViews`, `or:
[`, `{current_user_id}`; `must_not_contain` `$or`, `logic:`, `anyOf` |
the same schema lines |
| `.changeset/28476-skills-ui-view-filter-any-of-group.md` |
`'@objectstack/skills': patch`, `Clause-②: no`, `Metadata-protocol:
none` | — |
**Premise re-checked on `main` 23d1303:** `git grep -n "or: \["
skills/` finds no teaching of the group (the only `or:` under `skills/`
is prose); `ViewFilterOrGroupSchema` and the console lowering (PR
#28475, #28370) are on `main`, so the skill teaches a group the Console
applies. The spec docblock and `describe` still carry a `[PLANNED — not
yet rendered]` marker that PR #28475 was to lift
(`view.zod.ts:1152-1162`, `:1217`, `filter-rule-array.ts:193-199`): the
skill follows the renderer that is on `main`, not the stale marker —
listed under Acceptance notes.
### Token ratchet — paid by deletion in the same file
`scripts/check-skills-token-ratchet.mjs` prices every `rules/**` file
(`ceil(utf8 bytes / 4)`). `list-views.md` sat at 15 tokens of headroom
after #28488, so every addition is paid inside the file; the eval
fixture is measured, not ratcheted (ruling record 6513306068). No
ceiling row moves.
| File | Tokens before → after (ceiling) | Lines | Bytes | Deletions
that pay |
|:--|:--|:--|:--|:--|
| `skills/objectstack-ui/rules/list-views.md` | 3114 → 3106 (3129) | 309
→ 308 | 12453 → 12423 | ① the flat-view blockquote loses its restated
"not a valid view container" sentence; ② the data-source "Best practice:
Always…" blockquote is condensed to its two rules; ③ the Columns lead-in
sentence (the code comments "Simple" / "Enhanced" say it); ④ the
`tabs`-on-object bullet drops the `ViewTabBar` / "colliding tab bar" /
"untypable at author time" restatements and keeps the rule, the schema
and the lint; ⑤ the omit-`userFilters` bullet drops the "Filter elements
render only when explicitly configured" and "In data mode…" sentences; ⑥
the toolbar-search intro and the blast-radius paragraph are shortened
(same facts: narrows, never widens, refuses, whole search box); ⑦ "a
different key, same view" and the duplicated `(searchableFields)`
pointer; ⑧ the kanban intro's second sentence (the code comments already
say "required on every list view" and "fields shown on each card"); ⑨
the gantt summary-bar paragraph is shortened to its three facts |
| `skills/objectstack-ui/evals/views-apps-actions-pages.json` | 2320 →
2513 (not ratcheted) | 115 → 125 | 9277 → 10051 | eval 12 added |
The gate's bundle total (all shipped files, its own convention) reads
220463 after; before = after − (−8) − 193 = 220278.
## Tests
- `node scripts/check-skills-token-ratchet.mjs` — exit 0: *56 authored
bundle file(s) within their ceilings*; `list-views.md` 3106 / 3129
(headroom 23).
- `skills/objectstack-ui/evals/views-apps-actions-pages.json` parses (12
ids, 1…12), appended in the fixture's own inline-array style.
- The three `os:check` blocks of `list-views.md` are byte-identical to
`main` (checked by extracting the blocks on both sides); the Filtering
snippet is a plain fenced block, as before.
- No ablation: a docs-only diff changes no tested behaviour.
## Acceptance notes
- **In-place fix, same section (os-dev.md bounded exemption, all four
conditions):** the old "Common operators" line taught `this_week`,
`this_month`, `this_quarter` and `last_n_days`, which
`VIEW_FILTER_OPERATORS` (`view.zod.ts:315-325`) and
`VIEW_FILTER_OPERATOR_ALIASES` (`:375-400`) both refuse — an AI author
copying them gets a parse refusal — and omitted eight operators the enum
has. ① Same defect class as the card (§ Filtering teaching what the spec
does not accept); ② mechanical: the line is replaced by the enum,
verbatim; ③ no other claim holds the file (#28488 merged; ui seat 1's
#27059 is on `rules/pages*` / `references/pages.md`); ④ the same gate
family (`check-skills-token-ratchet`, `check:role-word`), no new
verification surface. Evidence: the enum and alias table cited; `git
grep -c "last_n_days\|this_week" packages/spec/src/ui/view.zod.ts` = 1
(a docblock, not a member). The claim's file surface already names this
file.
- **The example uses `priority equals urgent`, not the docs'
`completed_at after {7_days_ago}`.** `{7_days_ago}` appears only in spec
docblocks and `content/docs/ui/views.mdx`; no console resolver reads it
(`ui/packages/core/src/utils/filter-converter.ts` resolves
`{current_user_id}` only). The skill teaches only what runs. Carrier for
the docs' token: `none` — noted for the seat, not filed (a docs card,
not this one's).
- **Stale `[PLANNED — not yet rendered]` marker** on
`ViewFilterOrGroupSchema` (`view.zod.ts:1152-1162`, `:1217-1223`) and in
`filter-rule-array.ts:193-199` ("declared, but no console applies it
yet"): the console half #28370 landed with PR #28475, so the marker and
the describe text are now false. `class: stale-docblock`, `reach:
/meta/types describe text and the spec source`, `carrier: none` — the
seat decides whether #28370 / PR #28475's own follow-up carries it; not
this PR's file surface.
- **No `_index.md` row:** the group is a key inside an existing `filter`
element, not a new rule file or section;
`check:skill-identifier-liveness` and `check:skill-frame-sync` exit 0.
- Out-of-scope findings beyond the two above: none.
## Verification
All readings at head `af460eb4` (worktree
`/home/user/objectstack-28243`, base `origin/main` 23d1303).
<details><summary>Derived gates (<code>dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack</code>, 43 lines, each run with stdin
closed and its exit captured before any pipe)</summary>
Every one of the 43 lines is `:: exit 0`. The record is
`/mnt/project-files/skills-seat-1/r2026-10-31/out/28476-gates-ran-af460eb4.list`
in the seat's project folder.
`dispatch-gates.mjs --repo objectstack-ai/objectstack --ran` on that
record: *43 derived famil(ies) accounted for — 43 run, 0 NOT-MEASURED (a
DERIVED zero — all 43 recorded an exit code and none of them is 3)*,
exit 0.
Readings worth quoting: `node scripts/check-skills-token-ratchet.mjs` —
*56 authored bundle file(s) within their ceilings; 10 generator-owned
file(s) and 28 eval fixture(s) measured, not ratcheted*; `pnpm
check:role-word`, `pnpm check:skill-identifier-liveness`, `pnpm
check:skill-frame-sync`, `pnpm check:skill-compatibility`, `pnpm
check:doc-authoring`, `pnpm check:corpus-claim-drift` — exit 0.
</details>
<details><summary>Owed outside the derivation: the <code>os:check</code>
example compile</summary>
`pnpm --filter @objectstack/spec run check:skill-examples` — exit 0:
*277 marked example(s) across 113 file(s), 3 surface(s)* … *277 prose
examples type-check across 3 surface(s)*. No `os:check` block changed in
this PR; run because the file carries three. Its first two runs exited 3
(PREREQUISITE NOT MET: `packages/spec/dist` and then
`@objectstack/client-react` dist predated the sources after `main`
moved); `pnpm --filter @objectstack/spec build` (79 s) and `pnpm
--filter '@objectstack/client-react...' build` (4m19s) under
`scripts/pm/os-verify-lock.sh` fixed that, and the recorded code is the
re-run's. Recorded in `28476-gates-ran-af460eb4-extras.list` beside the
derived record.
</details>
Every other family is CI's: see this PR's check-runs. No test suite was
run locally: the diff touches no package source.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01L9qibz4G9FrLR4TRExx6gn
---
_Generated by [Claude
Code](https://claude.ai/code/session_01L9qibz4G9FrLR4TRExx6gn)_
---------
Co-authored-by: Claude <noreply@anthropic.com>{ or: [...] } (#28517)1 parent f5e6709 commit f662c71
3 files changed
Lines changed: 56 additions & 37 deletions
File tree
- .changeset
- skills/objectstack-ui
- evals
- rules
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
113 | 123 | | |
114 | 124 | | |
115 | 125 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
35 | | - | |
36 | | - | |
| 34 | + | |
| 35 | + | |
37 | 36 | | |
38 | 37 | | |
39 | 38 | | |
| |||
47 | 46 | | |
48 | 47 | | |
49 | 48 | | |
50 | | - | |
51 | | - | |
52 | | - | |
| 49 | + | |
| 50 | + | |
53 | 51 | | |
54 | 52 | | |
55 | 53 | | |
56 | 54 | | |
57 | | - | |
58 | | - | |
59 | 55 | | |
60 | 56 | | |
61 | 57 | | |
| |||
96 | 92 | | |
97 | 93 | | |
98 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
99 | 99 | | |
100 | 100 | | |
101 | | - | |
102 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
103 | 106 | | |
104 | 107 | | |
105 | 108 | | |
106 | | - | |
107 | | - | |
108 | | - | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
109 | 113 | | |
110 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
111 | 119 | | |
112 | 120 | | |
113 | 121 | | |
| |||
136 | 144 | | |
137 | 145 | | |
138 | 146 | | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
| 147 | + | |
| 148 | + | |
143 | 149 | | |
144 | 150 | | |
145 | 151 | | |
146 | 152 | | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
| 153 | + | |
| 154 | + | |
151 | 155 | | |
152 | 156 | | |
153 | 157 | | |
154 | 158 | | |
155 | 159 | | |
156 | 160 | | |
157 | | - | |
158 | | - | |
159 | | - | |
| 161 | + | |
| 162 | + | |
160 | 163 | | |
161 | 164 | | |
162 | 165 | | |
| |||
190 | 193 | | |
191 | 194 | | |
192 | 195 | | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
197 | | - | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
198 | 199 | | |
199 | 200 | | |
200 | 201 | | |
| |||
208 | 209 | | |
209 | 210 | | |
210 | 211 | | |
211 | | - | |
| 212 | + | |
212 | 213 | | |
213 | 214 | | |
214 | 215 | | |
| |||
226 | 227 | | |
227 | 228 | | |
228 | 229 | | |
229 | | - | |
| 230 | + | |
230 | 231 | | |
231 | 232 | | |
232 | 233 | | |
| |||
258 | 259 | | |
259 | 260 | | |
260 | 261 | | |
261 | | - | |
262 | | - | |
| 262 | + | |
263 | 263 | | |
264 | 264 | | |
265 | 265 | | |
| |||
304 | 304 | | |
305 | 305 | | |
306 | 306 | | |
307 | | - | |
308 | | - | |
309 | | - | |
| 307 | + | |
| 308 | + | |
0 commit comments