Skip to content

Published skill objectui/guides/data-integration.md teaches a QueryParams shape the adapters silently drop — unprefixed keys plus a direction sort key #6006

Description

@yinlianghui

Found while implementing #5293 (the ObjectViewProps.views[].sort spelling rename). Filed unassigned, not claiming. Deliberately NOT fixed there — #5293's fence is the views prop, and this is a different surface (QueryParams / DataSource.find) inside the published skills/ package, which carries its own expansion-budget discipline. Recording it so it is not lost.

Verified on origin/main @ 8d3a5294a.

Two independent defects in one documented example

skills/objectui/guides/data-integration.md is a customer-published skill — the artifact AI authors read as authority when composing against ObjectUI.

1. The sort key is spelled direction; SortConfig spells it order

:67   sort?: SortConfig[];            // ORDER BY [{field, direction}]
:272  sort: [{ field: 'name', direction: 'asc' }],

SortConfig (packages/types/src/objectql.ts:212-217) declares field and order. The shared sink convertSortToQueryParams (packages/core/src/utils/sort-query.ts) folds each entry as entry.order === 'desc' ? 'desc' : 'asc', so a direction-spelled entry yields ascending, always — the same silent-wrong-answer mechanism #5293 was filed about, here on the QueryParams surface rather than the views prop.

2. Every query option is documented without its $ prefix

:64   interface QueryParams {
:65     filter?: Record<string, any>;   // WHERE conditions
:66     sort?: SortConfig[];
:67     limit?: number;
:68     offset?: number;
:69     fields?: string[];
:70     expand?: string[];
:71   }

The real QueryParams (packages/types/src/data.ts:43) declares $select, $filter, $orderby, $top, … — every option $-prefixed. This is a known live defect class: #5458 fixed four such calls in repo code, and its changeset states the mechanism plainly — an unprefixed key "reaches no branch and is dropped — no throw, no warning, and it type-checks because the type carries [key: string]: any". The same changeset records that a dropped limit yields an unbounded read, because the platform's GET list route has no default page size.

So the published example at :270-274 — dataSource.find('contacts', { filter: {...}, sort: [...], limit: 20 }) — documents a call in which all three options are dropped: unfiltered, unsorted, and unbounded, with no failure signal.

Consequence

An AI author following the published skill writes a query that type-checks, runs, returns data, and silently ignores every option it was given. #5458 repaired the instances of this inside the repo; the artifact that teaches the broken shape to everyone outside it was not part of that sweep.

Counter-probe

grep -n "\$filter\|\$orderby\|\$top" skills/objectui/guides/data-integration.md returns 0 hits, while grep -c "sort\|filter" on the same file returns many — so the absence of the prefixed spelling is a reading, not a bad grep.

Scope note for whoever takes this

skills/** is a customer-published surface under the maintainer's 2026-08-21 ruling (「对外发布的 skills 是整个平台的最大价值,尤其要整体考虑和评估。」 / 「……不能为了一个小功能扩写很多。」). Current size, for a net-change budget: skills/objectui/guides/data-integration.md is 437 lines; the package's single SKILL.md is 155 lines. This should be a correction, not an expansion — the fix is re-spelling keys in two code blocks, not adding new guidance.

Dedup

Searched open issues (published skill QueryParams drift, data-integration guide, sort direction spelling, unprefixed query params) — nothing on this. Related: #5458 (the unprefixed-key defect class, fixed in repo code), #5293 (the same direction-vs-order spelling defect on the views prop), #4869 (the sort-sink convergence family).

Activity

  1. added theissue type on Aug 24, 2026
  2. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    Contributor

    Triage: lands in skills/objectui/guides/data-integration.md (published skill package) → domain:skills, type Bug, pm:queue. Rationale: a published teaching artifact instructing the exact silent-drop shape #5458 repaired in repo code is a correction with settled direction — both halves inherit recorded outcomes (#5458's $-prefix mechanism; the sort sink reads order).

    Dispatch constraints:


    Generated by Claude Code

  3. self-assigned this
    on Aug 29, 2026
  4. os-litant commented on Aug 29, 2026

    @os-litant
    Collaborator

    Claim: skills 席派发认领(定级 MEDIUM-HIGH——发布 skills 教的查询三选项全被静默丢弃,含无界读)。
    Session: session_01MnijPVVDakqK2J335JoJtq · Branch: claude/issue-6006-data-integration-contract · Worktree: ../objectui-6006-dataint(dev 自建)
    File surface: skills/objectui/guides/data-integration.md(发布 skills,维护者 2026-08-21 整包裁定适用:修正不扩写,PR 附前后两行数读数)。本派单同笔折入 #5947(同文件::78 QueryResult 声明先修、:275 用法后修,与本卡 :64-71/:272 两处互不重叠但同一治理预算)——一次事务,两卡各挂 Part of。#5947 的 pm:retriage 由本席以 skills 巷道自派权收拢(routing 判为 domain:skills 主 + domain:ui 留归属),记录于此。
    Container & model: os-dev 子代理;无 tier 声明面 ⇒ PM 判:opus 执行。
    Clause-② limb: 文档修正对齐真实契约,不改代码行为——不触发。
    Serial: data-integration.md 串行独占至本卡落地。md 文件 ⇒ 交付后 draft 双推维护者审。


    Generated by Claude Code

  5. os-litant commented on Aug 29, 2026

    @os-litant
    Collaborator

    os-dev-report

    {
      "issues": [6006, 5947],
      "status": "done",
      "branch": "claude/issue-6006-data-integration-contract",
      "worktree": "/home/user/objectui-6006-dataint (removed at task end)",
      "pr_url": "https://github.com/objectstack-ai/objectui/pull/6737",
      "pr_number": 6737,
      "draft": true,
      "premise_still_valid": true,
      "head_sha": "29e9685",
      "line_counts": {
        "file_before": 437,
        "file_after": 440,
        "file_net": 3,
        "published_package_before": 5673,
        "published_package_after": 5676,
        "published_package_files": 18
      },
      "edits": [
        "QueryParams sketch: all six options re-spelled with the $ prefix (filter to $filter, sort to $orderby, limit to $top, offset to $skip, fields to $select, expand to $expand), matching packages/types/src/data.ts:43 verbatim; added the real index-signature line, which is the mechanism that makes an unprefixed key type-check and then be dropped.",
        "QueryResult sketch (fixed FIRST, it is the root cause of the bad usage): records? and pageNumber? replaced by the real required data plus page?; metadata? added. Matches packages/types/src/data.ts:139.",
        "Worked dataSource.find example: $filter / $orderby / $top, sort entry key direction becomes order, and return result.records becomes return result.data. Same line count.",
        "RestApiAdapter sample: reads params.$filter / $top / $skip / $orderby instead of the unprefixed keys it was reading off a real QueryParams; returns data: rather than records:; local const data renamed body so the returned key is unambiguous. Outgoing query-string names left alone, they are the adapter's own REST wire format. Same line count.",
        "One bullet added to the existing 'Common data integration mistakes' list naming the silent-drop trap. This is the only added prose."
      ],
      "gates": [
        "check:skills-paths EXIT=0 -- 'check-skills-paths: OK (93/94 stated path(s) resolve across 18 guide file(s); 1 baselined).'",
        "check:control-bytes EXIT=0 -- 'check-control-bytes: OK (scanned 5593 tracked text file(s); skipped 85 binary).'",
        "check:doc-fences EXIT=0 -- 'check:doc-fences: every TypeScript block in 223 document(s) is fenced ts/tsx/typescript ...'",
        "changeset-presence EXIT=0 -- 'No source of a released package changed in this range, so no changeset is owed.'",
        "NOT APPLICABLE, measured not assumed: check-doc-snippet-types and check-doc-component-types do not scan skills/. Proved by calling the gate's own listDocuments(): 223 documents in surface, 0 under skills/, target file absent.",
        "NOT RUN, and nothing owed: lint / type-check / test. The diff touches one markdown file under skills/ and no package source."
      ],
      "tests": "No test suite applies: the diff is one published markdown guide, no package source. Correctness was established by reading the three real declarations rather than by a runtime check, because no gate compiles snippets under skills/ (proved above). Real shapes read at 546f610: QueryParams packages/types/src/data.ts:43 ends in an index signature; QueryResult packages/types/src/data.ts:139 has a REQUIRED data plus total/page/pageSize/hasMore/cursor/metadata; SortConfig packages/types/src/objectql.ts:311 spells the key order. convertSortToQueryParams (packages/core/src/utils/sort-query.ts) folds entry.order === 'desc' ? 'desc' : 'asc', which is the mechanism by which a direction entry silently sorts ascending. Gate union re-run after the final commit and reports tree 29e9685.",
      "mcp_calls": "5 (create_pull_request, pull_request_read, search_issues, update_pull_request, add_issue_comment). Repo-scoped REST is 403 on this seat and gh is absent, so card reads and read-backs went through the zero-quota web payload channel instead.",
      "stopped": false,
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT filed as new, already on file as #5465 (open, pm:dispatched): check-doc-snippet-types' scan surface excludes skills/, so the TypeScript in the published skills is compiled by nothing. Deduped before filing; opening another would have been a duplicate. Both cards in this transaction are instances of that gap."
      ],
      "notes": "Card line numbers had drifted and were re-derived as instructed: SortConfig is at objectql.ts:311, not :212. Both cards verified OPEN with subIssuesSummary total 0, so Fixes is correct for both. No skip-changeset label applied (phantom in this repo) and no changeset added, on the gate's own verdict. PR left as draft: no ready flip, no reviewers, no auto-merge. One platform behaviour worth knowing, not corrected by me: on create, the platform APPENDED its own horizontal rule plus a second Generated-by footer after mine. I did not write it and did not revert it; the later body edit replaced the body, and the session URL now lives in the body prose as the durable attribution copy."
    }

    Generated by Claude Code


    Generated by Claude Code

  6. os-litant commented on Aug 29, 2026

    @os-litant
    Collaborator

    判决:ACCEPT(含折叠的 #5947)。PM 收件复审已做正向抽查:sketch 六键、index-signature 行、QueryResult 必填 data、SortConfig.order、$orderby 类型行——逐一与 packages/types/src/data.ts / objectql.ts 现行声明比对一致($orderby 行为 data.ts:93 逐字)。RestApiAdapter 的扫尾修正(卡未点名、同类缺陷)在范围内;净 +3 行属修正自付(一条 mistakes 弹 + 两个接口各补一真实字段),整包读数已附。dev 上报的 Fixes/Part-of 冲突裁定:取 Fixes——两卡均无子卡且被本 PR 完整解决,合并代关,PM 落地笔只补摘标。
    PR #6737 保持 draft,已双推 os-zhuang + hotlong 审核(md 文件按 08-28 裁定走人审)。批准钉 head 后本席翻 ready + 挂 auto-merge;直合亦可。


    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

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions