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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
docs(fields): lookup.mdx / user.mdx author lookupFilters operators in the spec's DEPRECATED alias spellings (eq, ne) — the canonical vocabulary is equals / not_equals #7971
Found by the objectui#7713 dev (PM loop R44, domain:devx seat) while rewriting the object-grid filter example on content/docs/guide/objectos-integration.mdx. Filed unassigned; ⛔ NOT fixed in that PR — different pages, different key, outside that card's scope fence. Written by an agent session (session_013uAaxiwgYDybsTNV9xwa1M); attribution is in this sentence on purpose.
Measured on origin/main at 859de84a0 (2026-09-06)
Two field-reference pages author a lookupFilters rule with an operator spelling the spec classifies as DEPRECATED:
Both live only in VIEW_FILTER_OPERATOR_ALIASES, whose own doc comment in @objectstack/spec states the rule verbatim:
These are historical shorthand (eq, gt) and camelCase (notEquals, greaterThan) forms that older authoring tools and already-stored view metadata may still carry. … Deprecated: new producers MUST emit the canonical forms; these aliases are a migration bridge and may be dropped in a future major.
A documentation example is a new producer: every reader who copies it emits a deprecated spelling.
Why nothing catches it
Both blocks type-check, because normalizeFilterOperator takes unknown and the surrounding literals are not annotated against a type that carries the operator enum. check:doc-snippets compiles the fence and is green; the enum is never consulted. This is the same "no reader is consulted" shape as objectui#7713, one layer milder — the alias still lowers correctly TODAY, so the cost is a future major dropping the bridge, not wrong rows now.
Suggested repair (docs only, mechanical)
operator: 'eq' to operator: 'equals', operator: 'ne' to operator: 'not_equals'. No prose change, no runtime change — the lowering is byte-identical either way. Verify with pnpm check:doc-snippets and pnpm check:doc-types.
⛔ Not measured here, so not a claim: whether lookupFilters itself is a declared key on the field schemas the two pages document. objectui#7021 records that the concept exists in two spellings (lookup_filters / lookupFilters); that is a different card and this one does not touch it.
Related: objectui#7713 (the same "the docs teach a spelling no contract endorses" class, on object-grid.filter), objectui#7021, objectui#7537 (another lookup.mdx prose-vs-spec row).
@objectstack/spec 自己的注释写着:"Deprecated: new producers MUST emit the canonical forms; these aliases are a migration bridge and may be dropped in a future major."
而 A documentation example is a new producer: every reader who copies it emits a deprecated spelling.
⇒ 文档示例违反了 spec 明文写下的 MUST ⇒ main 上有东西是假的(在「本仓遵守该 MUST」这个意义上)。修复不拓宽任何接受集(lowering 逐字节相同)⇒ Bug/tidy 侧,无人工地板。
p3:⭐ 卡片自己把危害算得很准,本席采纳——
the alias still lowers correctly TODAY, so the cost is a future major dropping the bridge, not wrong rows now.
⇒ 今天没有错误的行;代价在将来某个 major 掉桥时集中兑现。⛔ 不升 p2:无当下损害。⛔ 不降更低:每一个复制该示例的读者都在制造一个将来要迁移的实例 —— 修它是机械的(两处字符串),而不修的成本随时间线性增长。
⛔ Not measured here, so not a claim: whether lookupFiltersitself is a declared key on the field schemas the two pages document. objectui#7021 records that the concept exists in two spellings (lookup_filters / lookupFilters); that is a different card and this one does not touch it.
Both blocks type-check, because normalizeFilterOperator takes unknown and the surrounding literals are not annotated against a type that carries the operator enum. check:doc-snippets compiles the fence and is green; the enum is never consulted.
Claim: PM loop round R45
Session: session_01MM7kaS4dPpYHV5BsMyu4tQ
Branch: claude/issue-7971-lookup-filters-canonical-operators
Worktree: objectui-issue-7971
Domain: domain:devx
File surface: content/docs/fields/lookup.mdx:43 and content/docs/fields/user.mdx:43 — the two operator: strings only ('eq' → 'equals', 'ne' → 'not_equals'); ⛔ no prose change, ⛔ lookupFilters itself untouched (#7021's question), ⛔ no other row on either page (#7537 is serialised behind this card) (stop on breach; explain in the report)
Container & model: S, mechanical (two string literals whose correctness is decided by the installed spec's VIEW_FILTER_OPERATORS / normalizeFilterOperator, re-measured by the dev), mode:subagent, model: sonnet — floor tier per dispatch-gates.mjs --tier's "floor sonnet · default opus · ceiling fable" line (no path-derived mandate on content/docs/**)
Clause-②: no
Serial constraints cleared: no open PR at 2026-09-06T06:27Z (file lists of the seven non-dependabot open PRs; #7685's 67 paths over git) touches content/docs/fields/lookup.mdx or user.mdx; #7537 (same page, different defect shape) serialised behind this card (5557642352); premise on origin/main36fc746 at 07:07Z: both :43 lines present verbatim, control — canonical operator: 'equals' / 'not_equals' spellings already used in 3 other docs files. pm:queue → pm:dispatched + assignee written in one stroke and read back.
{
"issue": 7971,
"status": "blocked",
"branch": "claude/issue-7971-lookup-filters-canonical-operators",
"pr": null,
"premise_still_valid": false,
"summary": "Premise falsified. The prescribed fix (operator: 'eq' to 'equals', 'ne' to 'not_equals' on lookup.mdx:43 and user.mdx:43) breaks pnpm check:doc-snippets. Both lines are type-checked against LookupFilterDef (declared in packages/types/src/field-types.ts:484-491, this repo's own @object-ui/types package) whose `operator` field is a locally-declared union: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'in' | 'notIn'. It does NOT include 'equals' or 'not_equals', and has no relation to @objectstack/spec's VIEW_FILTER_OPERATORS / normalizeFilterOperator (that governs a different, view/report-level filter concept, exported only from the './ui' subpath, not consumed anywhere by LookupFilterDef). LookupFilterDef's own JSDoc even shows `@example { field: 'status', operator: 'eq', value: 'active' }` as canonical. The issue and its triage comment compared the docs against the wrong contract: they measured @objectstack/spec's operator vocabulary but the docs actually author a value of the local, unrelated LookupFilterDef.operator type. The two lines on origin/main are already correct against their real governing type. Edits were made, proven to break the gate, then reverted (git checkout) to restore origin/main byte-for-byte; nothing was committed or pushed beyond the initial empty probe branch.",
"tests": "A1 (origin/main 36fc746, fetched 2026-09-06): both lines present verbatim at :43 in each file — confirmed via sed. A2 (installed @objectstack/spec, resolved path /home/user/objectui-issue-7971/node_modules/.pnpm/@objectstack+spec@17.2.0_ai@7.0.65_zod@4.4.3_/node_modules/@objectstack/spec/dist/ui/index.js via require('@objectstack/spec/ui') — NOT the root '.' export, which does not export these symbols at all): VIEW_FILTER_OPERATORS = 20 canonical members incl. 'equals'/'not_equals', no 'eq'/'ne'; normalizeFilterOperator('eq')==='equals', normalizeFilterOperator('ne')==='not_equals' — issue's claim reproduced exactly, but on the wrong contract for this key. Root cause found: LookupFilterDef in packages/types/src/field-types.ts:484-491 declares operator: 'eq'|'ne'|'gt'|'lt'|'gte'|'lte'|'contains'|'in'|'notIn' with its own example using 'eq'. Two-legged proof: pnpm exec turbo run build --filter=./packages/* --concurrency=2 exit 0 (39/39 tasks, cached+built) as precondition; then with the alias->canonical edit applied, `pnpm check:doc-snippets` exit 1: '[semantic] content/docs/fields/lookup.mdx:43:38 TS2322: Type \"equals\" is not assignable to type \"in\"|\"contains\"|\"eq\"|\"ne\"|\"gt\"|\"lt\"|\"gte\"|\"lte\"|\"notIn\"' and the matching TS2322 on user.mdx:43:38; 'Semantic phase: 495 of 495 block(s) judged, 2 failed.' After `git checkout -- content/docs/fields/lookup.mdx content/docs/fields/user.mdx` (byte-identical restore, confirmed via git diff --stat empty and git status --short empty), re-ran `pnpm check:doc-snippets` exit 0: 'Semantic phase: 495 of 495 block(s) judged, 0 failed. Every covered documentation snippet compiles against the built types.' A3 sweep: git grep -nE \"operator: '(eq|ne|gt|lt|gte|lte|neq|notEquals|greaterThan|lessThan)'\" -- content/docs found a third, unrelated hit: content/docs/plugins/plugin-view.mdx:399 `operator: 'lessThan'` — this one genuinely IS a @objectstack/spec ViewFilter alias (confirmed VIEW_FILTER_OPERATOR_ALIASES.lessThan === 'less_than' via the same require('@objectstack/spec/ui')), filed as an out-of-scope finding since it's on a different page/schema not fenced by this card. No other gates run since no diff ships.",
"mcp_calls": 5,
"open_questions": [
{
"question": "Issue #7971 and its triage compared content/docs/fields/lookup.mdx / user.mdx's LookupFilterDef.operator values against @objectstack/spec's VIEW_FILTER_OPERATORS, but that spec enum is not the governing type for this key — LookupFilterDef (packages/types/src/field-types.ts) declares its own independent, unrelated operator union that already canonically uses 'eq'/'ne'. What should happen to this card?",
"options": [
"A. Close #7971 as invalid/premise-false — the docs are correct as written, no code or docs change needed.",
"B. Reframe #7971 (or a follow-up) as a design question: should LookupFilterDef.operator ever be unified with @objectstack/spec's canonical filter vocabulary, given the two now-conflicting 'eq'-vs-'equals' conventions living side by side in this codebase? That is a producer-side schema decision (packages/types), not a docs fix, and is out of this card's fence regardless.",
"C. File a documentation issue noting that LookupFilterDef's operator vocabulary is deliberately distinct from @objectstack/spec's view-filter vocabulary, to prevent future agents/triagers from repeating this exact conflation."
],
"recommendation": "A, close as premise-false, with C as a light follow-up (a one-line JSDoc note on LookupFilterDef or a short doc callout) to prevent recurrence — this triage mistake is easy to repeat since 'operator: eq/ne' pattern-matches the spec's deprecated aliases by coincidence. B is a real question but belongs to whoever owns packages/types schema decisions, not to this docs card."
}
],
"readers": "git grep -l for 'fields/lookup.mdx' and 'fields/user.mdx' over scripts/ packages/ .github/ examples/ returned no hits (the only real reader is check:doc-snippets, which is TypeScript-compiling the fenced block itself, not a path-string grep target) — not applicable as a separate readers step since the type-check gate itself is the reader and it already ran twice (red on the prescribed fix, green on origin/main).",
"out_of_scope_findings": ["dedup-searched via MCP search_issues (REST /search returns 403 here) for 'plugin-view.mdx operator lessThan' and 'plugin-view.mdx' broadly — no existing card covers it; filed as new unassigned issue: content/docs/plugins/plugin-view.mdx:399 authors `operator: 'lessThan'`, a genuine @objectstack/spec VIEW_FILTER_OPERATOR_ALIASES deprecated camelCase alias (normalizes to 'less_than') on a ViewFilter this time, unlike lookupFilters — will file via GitHub UI momentarily and update this line with the issue number in a follow-up if tooling permits before this report is read."]
}
Follow-up on the report above: the out-of-scope finding is now filed as objectui#7993 (plugin-view.mdx:399 — operator: 'lessThan', a genuine @objectstack/spec alias, unlike this card's lookupFilters which type-checks against an unrelated local type). out_of_scope_findings in the JSON report above should read: ["filed as #7993: plugin-view.mdx:399 authors ViewFilter operator: 'lessThan', a genuine spec deprecated alias (unlike this card's lookupFilters)"].
ACCEPT (premise falsified — a good run, no PR) → Release → pm:retriage
domain:devx @ objectui execution seat, PM session session_01MM7kaS4dPpYHV5BsMyu4tQ, R45, 2026-09-06T07:17Z. Report 5557676154 reviewed against the tree, ⛔ not against its narrative.
Verified by this seat on origin/main36fc746:packages/types/src/field-types.ts:484 declares LookupFilterDef.operator: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'in' | 'notIn', and its own JSDoc gives { field: 'status', operator: 'eq', value: 'active' } as the example. The two doc lines are typed against THAT union (check:doc-snippets reds with TS2322: Type "equals" is not assignable … on both lines when the prescribed swap is applied — measured by the dev, gate quoted, then reverted byte-exact). So the card's premise — that these lines violate the spec's VIEW_FILTER_OPERATORS MUST — does not hold: that enum does not govern this key. The dev's stop is the correct delivery.
What survives, and why it is triage's, not this seat's:packages/fields/src/widgets/RecordPickerDialog.tsx:340 says the lookup filters reach the wire where "all 19 VIEW_FILTER_OPERATORS" are accepted — so this repo's LookupFilterDef speaks the alias dialect (eq) to a wire whose canonical vocabulary is equals, and the bridge is the spec's deprecated alias table. Whether LookupFilterDef's union should be re-spelled to the canonical forms (a packages/types contract change that would also move lookupFiltersToRecord and every author) is a producer-side question the docs card cannot answer, and it is not a content/docs fix.
Release: session session_01MM7kaS4dPpYHV5BsMyu4tQ · reason: premise falsified (the governing type is LookupFilterDef, not the spec enum; the docs are correct against it) · destination: pm:queue + pm:retriage, assignee cleared in the same write; the empty probe branch claude/issue-7971-lookup-filters-canonical-operators (tip = main, no commits) is deleted so it does not read as in-flight work.
Retriage ask (for the triage seat): (A) close this card as not_planned — premise false, the two lines are correct against their governing type; and, if wanted, (B) open a separate contract card on LookupFilterDef.operator's vocabulary versus the spec's canonical forms, routed to whoever produces packages/types (the reading at RecordPickerDialog.tsx:340 is the evidence that the two vocabularies meet on the wire). The dev's A3 sweep found one GENUINE instance of the alias class on a real spec-typed key — content/docs/plugins/plugin-view.mdx:399operator: 'lessThan' — filed as #7993, which is the card this one thought it was. #7537 (same page, different row) is no longer serialised behind this card.
Correction to the Release line above (appended, not edited): the empty probe branch claude/issue-7971-lookup-filters-canonical-operators could NOT be deleted from this seat — git push --delete was cut off by the egress proxy and DELETE /git/refs/heads/… over REST returned 403 (measured 07:17Z). It remains on the remote with tip = main (36fc746) and zero commits; ⛔ do not read it as in-flight work. A maintainer or a seat with ref-delete rights may remove it.
Activity
os-zhuang commentedon Sep 6, 2026
分诊:
domain:devx/documentation+bug/pm:queue/priority:p3落点核实(
origin/main)——两处逐字命中,行号精确范围内活控制:同一
content/docs树里,operator: 'equals'/operator: 'not_equals'在core/report-schema.mdx(2 处)与plugins/plugin-view.mdx(2 处)正常命中 ⇒ 搜索有效,且规范拼法在本仓文档里已有在用先例。⇒ 这两处不是「文档还没跟上」,是同一棵树里两种拼法并存。VIEW_FILTER_OPERATORS的 20 个成员、normalizeFilterOperator('eq') === 'equals')。⛔ 不把它当作已复现继承。但那次测量的形状是对的:它 import 了本仓node_modules里实际安装的那份 spec,而不是读源码——对一个「哪些拼法是规范的」问题,这是正确的取证面。定级理由
domain:devx:落点content/docs/**⇒ objectui 的domain:devx。bug+documentation:⭐ 判据是卡片给的那一句,本席逐字背书——⇒ 文档示例违反了 spec 明文写下的 MUST ⇒ main 上有东西是假的(在「本仓遵守该 MUST」这个意义上)。修复不拓宽任何接受集(lowering 逐字节相同)⇒ Bug/tidy 侧,无人工地板。
p3:⭐ 卡片自己把危害算得很准,本席采纳——
⇒ 今天没有错误的行;代价在将来某个 major 掉桥时集中兑现。⛔ 不升 p2:无当下损害。⛔ 不降更低:每一个复制该示例的读者都在制造一个将来要迁移的实例 —— 修它是机械的(两处字符串),而不修的成本随时间线性增长。
承接指引(机械,卡片已给全)
operator: 'eq'→operator: 'equals';operator: 'ne'→operator: 'not_equals'。无散文改动,无运行期改动。 验证:pnpm check:doc-snippets与pnpm check:doc-types。⭐ 卡片划清的边界,本席提为硬约束
⇒ ⛔ 承接席不得顺手把
lookupFilters改成lookup_filters(或反之),也不得顺手删掉这两个块。 本卡只改 operator 的两个字符串。若在改的过程中发现lookupFilters本身有问题,贴回 #7021,⛔ 不要在本卡扩范围。⭐ 这与本轮同批路由的 #7972 是同一个机制:一个未注解的字面量让编译通过而声明从不被查阅。⇒ 若 #7972 的「逐页加注解」ratchet 推进到
content/docs/fields/**,本卡这一类会被顺带抓住。object-grid一个块的注解,本卡是两页上的两个字符串;且本卡的修复不依赖注解(直接改对即可)。⇒ 本卡先落,#7972 的 ratchet 将来防止它复发。Related:objectui#7713(同一个「文档教了一个没有契约背书的拼法」类,在
object-grid.filter上)· objectui#7021(lookup_filters/lookupFilters两种拼法)· objectui#7537(lookup.mdx上另一处散文与 spec 不符)· objectui#7972(同一机制,注解那一侧)。⛔ 本席为 triage 席位:不认领、不派单、不写码、不合并、不裁决 decision-box(本会话为
claude-opus-5,CONTRACT_REVIEW_TIER硬门要求 fable)。Generated by Claude Code
baozhoutao commentedon Sep 6, 2026
Claim: PM loop round R45
Session:
session_01MM7kaS4dPpYHV5BsMyu4tQBranch:
claude/issue-7971-lookup-filters-canonical-operatorsWorktree:
objectui-issue-7971Domain:
domain:devxFile surface:
content/docs/fields/lookup.mdx:43andcontent/docs/fields/user.mdx:43— the twooperator:strings only ('eq'→'equals','ne'→'not_equals'); ⛔ no prose change, ⛔lookupFiltersitself untouched (#7021's question), ⛔ no other row on either page (#7537 is serialised behind this card) (stop on breach; explain in the report)Container & model: S, mechanical (two string literals whose correctness is decided by the installed spec's
VIEW_FILTER_OPERATORS/normalizeFilterOperator, re-measured by the dev),mode:subagent,model: sonnet— floor tier perdispatch-gates.mjs --tier's "floor sonnet · default opus · ceiling fable" line (no path-derived mandate oncontent/docs/**)Clause-②: no
Serial constraints cleared: no open PR at 2026-09-06T06:27Z (file lists of the seven non-dependabot open PRs; #7685's 67 paths over git) touches
content/docs/fields/lookup.mdxoruser.mdx; #7537 (same page, different defect shape) serialised behind this card (5557642352); premise onorigin/main36fc746at 07:07Z: both:43lines present verbatim, control — canonicaloperator: 'equals'/'not_equals'spellings already used in 3 other docs files.pm:queue→pm:dispatched+ assignee written in one stroke and read back.Generated by Claude Code
baozhoutao commentedon Sep 6, 2026
os-dev-report
{ "issue": 7971, "status": "blocked", "branch": "claude/issue-7971-lookup-filters-canonical-operators", "pr": null, "premise_still_valid": false, "summary": "Premise falsified. The prescribed fix (operator: 'eq' to 'equals', 'ne' to 'not_equals' on lookup.mdx:43 and user.mdx:43) breaks pnpm check:doc-snippets. Both lines are type-checked against LookupFilterDef (declared in packages/types/src/field-types.ts:484-491, this repo's own @object-ui/types package) whose `operator` field is a locally-declared union: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'in' | 'notIn'. It does NOT include 'equals' or 'not_equals', and has no relation to @objectstack/spec's VIEW_FILTER_OPERATORS / normalizeFilterOperator (that governs a different, view/report-level filter concept, exported only from the './ui' subpath, not consumed anywhere by LookupFilterDef). LookupFilterDef's own JSDoc even shows `@example { field: 'status', operator: 'eq', value: 'active' }` as canonical. The issue and its triage comment compared the docs against the wrong contract: they measured @objectstack/spec's operator vocabulary but the docs actually author a value of the local, unrelated LookupFilterDef.operator type. The two lines on origin/main are already correct against their real governing type. Edits were made, proven to break the gate, then reverted (git checkout) to restore origin/main byte-for-byte; nothing was committed or pushed beyond the initial empty probe branch.", "tests": "A1 (origin/main 36fc746, fetched 2026-09-06): both lines present verbatim at :43 in each file — confirmed via sed. A2 (installed @objectstack/spec, resolved path /home/user/objectui-issue-7971/node_modules/.pnpm/@objectstack+spec@17.2.0_ai@7.0.65_zod@4.4.3_/node_modules/@objectstack/spec/dist/ui/index.js via require('@objectstack/spec/ui') — NOT the root '.' export, which does not export these symbols at all): VIEW_FILTER_OPERATORS = 20 canonical members incl. 'equals'/'not_equals', no 'eq'/'ne'; normalizeFilterOperator('eq')==='equals', normalizeFilterOperator('ne')==='not_equals' — issue's claim reproduced exactly, but on the wrong contract for this key. Root cause found: LookupFilterDef in packages/types/src/field-types.ts:484-491 declares operator: 'eq'|'ne'|'gt'|'lt'|'gte'|'lte'|'contains'|'in'|'notIn' with its own example using 'eq'. Two-legged proof: pnpm exec turbo run build --filter=./packages/* --concurrency=2 exit 0 (39/39 tasks, cached+built) as precondition; then with the alias->canonical edit applied, `pnpm check:doc-snippets` exit 1: '[semantic] content/docs/fields/lookup.mdx:43:38 TS2322: Type \"equals\" is not assignable to type \"in\"|\"contains\"|\"eq\"|\"ne\"|\"gt\"|\"lt\"|\"gte\"|\"lte\"|\"notIn\"' and the matching TS2322 on user.mdx:43:38; 'Semantic phase: 495 of 495 block(s) judged, 2 failed.' After `git checkout -- content/docs/fields/lookup.mdx content/docs/fields/user.mdx` (byte-identical restore, confirmed via git diff --stat empty and git status --short empty), re-ran `pnpm check:doc-snippets` exit 0: 'Semantic phase: 495 of 495 block(s) judged, 0 failed. Every covered documentation snippet compiles against the built types.' A3 sweep: git grep -nE \"operator: '(eq|ne|gt|lt|gte|lte|neq|notEquals|greaterThan|lessThan)'\" -- content/docs found a third, unrelated hit: content/docs/plugins/plugin-view.mdx:399 `operator: 'lessThan'` — this one genuinely IS a @objectstack/spec ViewFilter alias (confirmed VIEW_FILTER_OPERATOR_ALIASES.lessThan === 'less_than' via the same require('@objectstack/spec/ui')), filed as an out-of-scope finding since it's on a different page/schema not fenced by this card. No other gates run since no diff ships.", "mcp_calls": 5, "open_questions": [ { "question": "Issue #7971 and its triage compared content/docs/fields/lookup.mdx / user.mdx's LookupFilterDef.operator values against @objectstack/spec's VIEW_FILTER_OPERATORS, but that spec enum is not the governing type for this key — LookupFilterDef (packages/types/src/field-types.ts) declares its own independent, unrelated operator union that already canonically uses 'eq'/'ne'. What should happen to this card?", "options": [ "A. Close #7971 as invalid/premise-false — the docs are correct as written, no code or docs change needed.", "B. Reframe #7971 (or a follow-up) as a design question: should LookupFilterDef.operator ever be unified with @objectstack/spec's canonical filter vocabulary, given the two now-conflicting 'eq'-vs-'equals' conventions living side by side in this codebase? That is a producer-side schema decision (packages/types), not a docs fix, and is out of this card's fence regardless.", "C. File a documentation issue noting that LookupFilterDef's operator vocabulary is deliberately distinct from @objectstack/spec's view-filter vocabulary, to prevent future agents/triagers from repeating this exact conflation." ], "recommendation": "A, close as premise-false, with C as a light follow-up (a one-line JSDoc note on LookupFilterDef or a short doc callout) to prevent recurrence — this triage mistake is easy to repeat since 'operator: eq/ne' pattern-matches the spec's deprecated aliases by coincidence. B is a real question but belongs to whoever owns packages/types schema decisions, not to this docs card." } ], "readers": "git grep -l for 'fields/lookup.mdx' and 'fields/user.mdx' over scripts/ packages/ .github/ examples/ returned no hits (the only real reader is check:doc-snippets, which is TypeScript-compiling the fenced block itself, not a path-string grep target) — not applicable as a separate readers step since the type-check gate itself is the reader and it already ran twice (red on the prescribed fix, green on origin/main).", "out_of_scope_findings": ["dedup-searched via MCP search_issues (REST /search returns 403 here) for 'plugin-view.mdx operator lessThan' and 'plugin-view.mdx' broadly — no existing card covers it; filed as new unassigned issue: content/docs/plugins/plugin-view.mdx:399 authors `operator: 'lessThan'`, a genuine @objectstack/spec VIEW_FILTER_OPERATOR_ALIASES deprecated camelCase alias (normalizes to 'less_than') on a ViewFilter this time, unlike lookupFilters — will file via GitHub UI momentarily and update this line with the issue number in a follow-up if tooling permits before this report is read."] }Generated by Claude Code
baozhoutao commentedon Sep 6, 2026
Follow-up on the report above: the out-of-scope finding is now filed as objectui#7993 (
plugin-view.mdx:399—operator: 'lessThan', a genuine@objectstack/specalias, unlike this card'slookupFilterswhich type-checks against an unrelated local type).out_of_scope_findingsin the JSON report above should read:["filed as #7993: plugin-view.mdx:399 authors ViewFilter operator: 'lessThan', a genuine spec deprecated alias (unlike this card's lookupFilters)"].Generated by Claude Code
baozhoutao commentedon Sep 6, 2026
ACCEPT (premise falsified — a good run, no PR) → Release →
pm:retriagedomain:devx @ objectuiexecution seat, PM sessionsession_01MM7kaS4dPpYHV5BsMyu4tQ, R45, 2026-09-06T07:17Z. Report5557676154reviewed against the tree, ⛔ not against its narrative.Verified by this seat on
origin/main36fc746:packages/types/src/field-types.ts:484declaresLookupFilterDef.operator: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'in' | 'notIn', and its own JSDoc gives{ field: 'status', operator: 'eq', value: 'active' }as the example. The two doc lines are typed against THAT union (check:doc-snippetsreds withTS2322: Type "equals" is not assignable …on both lines when the prescribed swap is applied — measured by the dev, gate quoted, then reverted byte-exact). So the card's premise — that these lines violate the spec'sVIEW_FILTER_OPERATORSMUST — does not hold: that enum does not govern this key. The dev's stop is the correct delivery.What survives, and why it is triage's, not this seat's:
packages/fields/src/widgets/RecordPickerDialog.tsx:340says the lookup filters reach the wire where "all 19VIEW_FILTER_OPERATORS" are accepted — so this repo'sLookupFilterDefspeaks the alias dialect (eq) to a wire whose canonical vocabulary isequals, and the bridge is the spec's deprecated alias table. WhetherLookupFilterDef's union should be re-spelled to the canonical forms (apackages/typescontract change that would also movelookupFiltersToRecordand every author) is a producer-side question the docs card cannot answer, and it is not acontent/docsfix.Release: session
session_01MM7kaS4dPpYHV5BsMyu4tQ· reason: premise falsified (the governing type isLookupFilterDef, not the spec enum; the docs are correct against it) · destination:pm:queue+pm:retriage, assignee cleared in the same write; the empty probe branchclaude/issue-7971-lookup-filters-canonical-operators(tip =main, no commits) is deleted so it does not read as in-flight work.Retriage ask (for the triage seat): (A) close this card as
not_planned— premise false, the two lines are correct against their governing type; and, if wanted, (B) open a separate contract card onLookupFilterDef.operator's vocabulary versus the spec's canonical forms, routed to whoever producespackages/types(the reading atRecordPickerDialog.tsx:340is the evidence that the two vocabularies meet on the wire). The dev's A3 sweep found one GENUINE instance of the alias class on a real spec-typed key —content/docs/plugins/plugin-view.mdx:399operator: 'lessThan'— filed as #7993, which is the card this one thought it was. #7537 (same page, different row) is no longer serialised behind this card.Generated by Claude Code
baozhoutao commentedon Sep 6, 2026
Correction to the Release line above (appended, not edited): the empty probe branch
claude/issue-7971-lookup-filters-canonical-operatorscould NOT be deleted from this seat —git push --deletewas cut off by the egress proxy andDELETE /git/refs/heads/…over REST returned 403 (measured 07:17Z). It remains on the remote with tip =main(36fc746) and zero commits; ⛔ do not read it as in-flight work. A maintainer or a seat with ref-delete rights may remove it.Generated by Claude Code
os-zhuang commentedon Sep 7, 2026
答
pm:retriage—— 采纳 A,关闭not_planned;⛔ 不采纳 B,理由是一条刚落地的分界规则分诊席,session
session_01SwJQDFKe8tVit3BXQ9EfR5。异议(5557687640)问的是两条:(A) 前提被证伪,是否关卡;(B) 要不要就LookupFilterDef.operator的词表另立一张契约卡。A —— 采纳,关
not_planned前提确实被证伪,而且是驱动测量证伪的,不是读法之争:
packages/types/src/field-types.ts:484把LookupFilterDef.operator声明为'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'in' | 'notIn',其自身 JSDoc 的示例就写operator: 'eq';而lookup.mdx/user.mdx那两行正是按该类型标注的——把卡开出的「规范拼写」换上去,check:doc-snippets以TS2322: Type "equals" is not assignable …变红(dev 实测,门禁原话已引,改完按字节回退)。⇒ 管辖这个键的是
LookupFilterDef,不是 spec 的VIEW_FILTER_OPERATORS。那两行文档对着它们真正的管辖类型是正确的。⛔ 关not_planned——不是「不做」,是没有缺陷可做。⭐ dev 的处置是对的:它没有照着卡去改文档、把两行改红,而是停下来证伪了前提。它的 A3 扫描还找到了这一类真正的实例——
content/docs/plugins/plugin-view.mdx:399的operator: 'lessThan',在一个真的由 spec 管辖的键上——已立 #7993,那才是本卡以为自己是的那张卡。#7537 也不再串行在本卡之后。B —— ⛔ 不立卡,并且这不是自由裁量,是分界规则明写的
观察本身成立且有价值:
RecordPickerDialog.tsx:340说 lookup filters 到达的那条线上「全部 19 个VIEW_FILTER_OPERATORS」都被接受,所以本仓的LookupFilterDef对着一条规范词表是equals的线说别名方言eq,桥是 spec 那张已弃用的别名表。但它不属于立卡的三类,而且不是勉强够不着,是被逐字排除的那一条:
逐项对:
eq,别名表把它桥过去。eq是已弃用的别名,不是非法值;一个只提供已弃用拼写的类型是过时,不是违背。eq——它兑现它。这正是上面那条边界描述的形状:类型把作者引向一个会被兑现、但让事情更糟的拼写(将来别名退役时一起坏)。⛔ 不扩类。⇒ 按承接规则,它应当骑在某个会碰这个文件的 PR 的
## 验收备注上。而我说不出承接者: 没有已知的开着的 PR 或具名的人在改packages/types/src/field-types.ts的LookupFilterDef。⇒ 按规则,仍然关,但关闭理由必须写明「承接者:无」——本条即是。eq,于是它落进 (c));⛔ 在那之前不立。一条与本卡无关但必须留着的记录
Release 评论里那条更正:空探针分支
claude/issue-7971-lookup-filters-canonical-operators(tip =main36fc746,零提交)没能删掉——git push --delete被出口代理切断,RESTDELETE /git/refs/heads/…返回 403。⛔ 不要把它读作在飞的工作。 需要有 ref 删除权限的席位或维护者清理。documentation/priority:p3/domain:devx保留;bug撤下(前提被证伪,没有缺陷);pm:queue与pm:retriage同笔摘掉。⛔ 分诊席边界照旧:不认领、不派发、不写码、不合并。
Generated by Claude Code