Repository navigation
[finding] skills/objectstack-query now teaches that the engine refuses { relation: { field: value } } (PR #20811), but since PR #20872 (ca5408c62) the engine serves it; the published skill states a refusal that no longer happens #20888
Description
Activity
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsTriage: first grade —
documentation·priority:p2·domain:skills·area:api·pm:queue. The skill states what the engine now serves; governed, Tier HTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-30T15:54Z. ⛔ Not a claim, ⛔ not a dispatch.Triage:
skills/objectstack-queryis a governed surface ⇒domain:skills, Tier H.Why p2. It takes #20782's grade. The published skill tells AI authors that a form the engine serves (PR #20872) is refused. They hand-write the two-step route the ruling set out to remove.
Direction. As the card states:
- the served form and its limits: one level, forward,
whereonly, the 1000-id cap with its loud refusal, and the caller's permissions; - the two-step route kept for past the cap and for the reverse form;
- nothing said about analytics until #20802 analytics half (
domain:services): the cube read and the analytics read scope answer{ relation: { field: value } }as the engine seam now serves it — as the caller, capped, one answer on every face #20887 lands.
One wording, two surfaces. #20876 corrects
content/docs/protocol/objectql/query-syntax.mdxfor the same fact. Whichever lands second quotes the first's sentences, so the skill and the docs page never differ.- the served form and its limits: one level, forward,
- addedarea:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsThe API a customer can call, and integrations — REST, connectors, webhooks, jobsdocumentationImprovements or additions to documentationImprovements or additions to documentationpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 30, 2026 objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsClaim: PM loop round 9
Session:session_01KTZmMfzVzjNvyaLyQ8mHvg
Account:os-warren(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20888-query-skill-relation-served
Worktree:objectstack-issue-20888
Domain:domain:skills
Seat:domain:skills#1
File surface:skills/objectstack-query/SKILL.md, the sites PR docs(skills): objectstack-query teaches the served route for a related record's column, not the refused nested form #20811 rewrote: the Removed-key rowquery.joins, the rules index line, the "Filtering by a related record" subsection, thesearch never traversessentence, and the two Cross-Object rows.skills/objectstack-query/rules/filters.md, the## Relation Filterssection.scripts/check-skills-token-ratchet.mjs, only if a ceiling row is lowered.content/docs/**is read only ([finding] docs: query-syntax.mdx "Filtering Across Relationships" says SqlDriver compiles a nested relation object and emits a dotted key to Knex — both are refused at the engine before any driver since 4b4ee88f #20876 carriesquery-syntax.mdx). The analytics docs are untouched (#20802 analytics half (domain:services): the cube read and the analytics read scope answer{ relation: { field: value } }as the engine seam now serves it — as the caller, capped, one answer on every face #20887).
Stop on breach; explain in the report.
Container & model:S, not mechanical ⇒ M treatment,mode:subagent,model: claude-fable-5-1(dispatch-gates --tier: MANDATORY,skills/**clause ①)
Clause-②: no
Thread-read: 5914848913
Serial constraints cleared:- PR feat(objectql): serve the nested-relation filter in where — lowered at the engine seam, the related object read as the caller, a loud cap, drivers untouched (#20802) #20872 (the engine half of ruling 5907789183) MERGED as
ca5408c62, so the served form is onmain. - PR docs(skills): objectstack-query teaches the served route for a related record's column, not the refused nested form #20811 (this file's previous claim) MERGED as
1d202453. - No open PR touches
skills/objectstack-query/**orquery-syntax.mdx(every open PR's file list, read at this claim). - Budgets read on
origin/main:SKILL.md: 399 lines, 4055 / 5552 tokens.rules/filters.md: 214 lines, 2149 / 2149 tokens (headroom 0), so that section's rewrite must pay for itself in the file.
- NORTH-STAR 优先级 3 does not hold this card: the open P1 [finding] the Governed Surface Queue Guard's refusal text tells a seat to dequeue a governed PR by converting it to DRAFT — measured not to dequeue in this repo (same family as #20847) #20855 is in flight, and this is a published-skill (product) card, not a tool or hygiene card.
Generated by Claude Code
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 20888, "status": "done", "branch": "claude/issue-20888-query-skill-relation-served", "pr": "https://github.com/objectstack-ai/objectstack/pull/20902", "head_sha": "b73023a347448c931035a76a469b699593575309", "session": "session_01KTZmMfzVzjNvyaLyQ8mHvg — mode:subagent, the parent's id; the relay resolved the same id from the container on both writes", "premise_still_valid": true, "summary": "Draft PR #20902 (Tier H, skills/**) rewrites the sites PR #20811 (1d202453) left stating the refusal: skills/objectstack-query/SKILL.md :76 (Removed-key row query.joins), :189-:191 (Filtering by a related record), :331 (the search paragraph's filter sentence), :340 (Cross-Object row), and rules/filters.md ## Relation Filters. They now state that { relation: { field: value } } is served in where since PR #20872 (ca5408c62), read as the caller, with the five limits from the code — one level (admitRelationCondition, INVALID_FILTER / 400), forward only (the reverse form is not served), where only (an aggregation's filter and having refuse it, relationWords, INVALID_FILTER / 400), the 1000-id cap (RELATION_FILTER_ID_CAP, relationFilterCapError, INVALID_FILTER / 400, never truncated), the caller's permissions (PERMISSION_DENIED / 403, data-nested-relation-permission.test.ts) — and the two-step route kept for past the cap and for a parent by its children. Nothing is said about analytics (#20887 open). The filters.md rewrite is paid for in-file by deleting its ## Logical Operators section (both rules have a home in SKILL.md and the file's first Common Mistake); the file lands at 2148 / 2149 tokens. The sentences for #20876 to quote are in the PR body under '## Sentences for #20876 to quote'. Re-read and left as they are: SKILL.md :88, :326-:327 and :342 (search never traverses — searchFields names are judged exactly at the ingress), :341 (the reverse form). The landed sibling wording (data-engine.mdx, the three 20802 changesets, the FilterCondition docblock form 4) matches the code; the skill contradicts none of it.", "files_changed": [ "skills/objectstack-query/SKILL.md", "skills/objectstack-query/rules/filters.md", "scripts/role-word-baseline.json" ], "line_budget": { "budget": "net +4 lines at most across skills/**, every per-file token ceiling held", "actual_skills_lines": -28, "SKILL.md": "399 → 400 lines, 4055 → 4109 tokens (ceiling 5552)", "rules/filters.md": "214 → 185 lines, 2149 → 2148 tokens (ceiling 2149, headroom was 0)", "package_skills/objectstack-query": "6 files, 1145 → 1117 lines, 10527 → 10580 tokens", "catalog_skills/**": "13375 → 13347 lines", "rewrap_of_untouched_lines": "none", "ceiling_rows_moved": 0, "deletions_with_homes": "rules/filters.md ## Logical Operators (41 lines, 579 bytes): AND (implicit) / explicit $and → SKILL.md :173-:181 and filters.md Common Mistake 1; OR / $in equivalent → SKILL.md :170-:171, :123, :128 and the Operator Reference $in row" }, "gates": { "head": "b73023a34", "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 3 path(s) vs merge base 00a92e18d): 31 commands — the dispatch's list plus six families the baseline row adds under scripts/**: check-scripts-symbol-anchors (+ --self-test), check:bash32-floor, check:cli-command-ids, check:entry-guard, check:parse-guard, check:pnpm-filter-targets", "reconcile": "--ran: 31 derived famil(ies) accounted for — 31 run, 0 NOT-MEASURED (a DERIVED zero — all 31 recorded an exit code and none of them is 3)", "exit_codes": "all 31 exit 0 (captured by redirect before any pipe): check-skills-token-ratchet 0 (54 authored bundle file(s) within their ceilings) and --self-test 0 (65 cases); check:role-word 0 after --update (Ledger: 44 baselined file(s) still carrying it (117 occurrence(s))); check:corpus-claim-drift 0; check:skill-identifier-liveness 0; check:doc-authoring 0; check:nul-bytes 0; check:skill-compatibility 0; check:skill-frame-sync 0; check:agent-test-spelling 0; check:cross-package-test-inputs 0; check:driver-memory-census 0; check:gitlink-declared 0; check:pm-governed-merges 0 (the --self-test as the script spells it); check:refd-timer-probe 0; check:watch-hint-literal 0; check-ci-filter-parity 0 (+ --self-test 0); check-closing-keyword-parity 0 (+ --self-test 0); check-comment-mask-corpus 0 (7664 files, 0 disagree); check-doc-route-spelling --advisory 0 (+ --self-test 0); check-scripts-symbol-anchors 0 (+ --self-test 0); check:bash32-floor 0; check:cli-command-ids 0; check:entry-guard 0; check:parse-guard 0; check:pnpm-filter-targets 0; lint check:doc-formula-expressions 0 (22 record-scoped formula example(s) across 458 files / 1380 TS blocks judged clean; @objectstack/lint... built first under os-verify-lock.sh, VERDICT command-exit 0, 90s); spec check:skill-docs 0 (Skill docs in sync); spec check:skill-refs 0 (9 generated files in sync). check:skill-examples not applicable: 0 os:check markers in the skill.", "rerun_after_final_commit": "check-skills-token-ratchet and check:role-word re-run at b73023a34, both exit 0 with the verdicts quoted above", "ci": "in_progress — not waited on (card terms; the PM reads CI convergence)" }, "tests": "Pins of the served form run first-hand under os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-20888), each package's dependency closure built first (@objectstack/objectql^... VERDICT command-exit 0 118s; @objectstack/rest^... in the same lock hold as its tests, VERDICT command-exit 0 179s): pnpm --filter @objectstack/objectql exec vitest run --maxWorkers=2 src/engine-nested-relation-lowering.test.ts → 'Test Files 1 passed (1), Tests 13 passed (13)' (VERDICT command-exit 0); pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/data-nested-relation-permission.test.ts src/data-nested-object-door.test.ts → 'Test Files 2 passed (2), Tests 9 passed | 12 skipped (21)' — the 12 are the PostgreSQL and MySQL cells of data-nested-object-door.test.ts, named skips (OS_TEST_POSTGRES_URL / OS_TEST_MYSQL_URL unset); the memory and SQLite cells and the 403 permission pin ran. The first objectql attempt before the closure build failed to resolve @objectstack/core's entry (a prerequisite, not a red; re-run after the build). No package is touched, so no package build or test suite is owed beyond these. Ablation: none — a docs-only diff, no gate or test asserts these sentences. NOT MEASURED: none.", "mcp_calls": "0 — no MCP GitHub tool was called; reads were unauthenticated public REST GETs (the card, its comments, ruling 5907789183, #20876, #20887, PR #20902 read-back)", "api_writes": "2 — both through scripts/pm/fleet-write/dispatch.mjs (the relay, landing as objectstack-fleet[bot], session session_01KTZmMfzVzjNvyaLyQ8mHvg): pr_create → POST /repos/objectstack-ai/objectstack/pulls (#20902, draft, read back 15299 / 15299 bytes identical); comment → POST /repos/objectstack-ai/objectstack/issues/20888/comments (this report). No label write, no PR assignee write, no PR body PATCH. git pushes (not REST): 3 (the empty-branch probe, WIP e13345bdb, b73023a34).", "deviations": [ "scripts/role-word-baseline.json: one row (skills/objectstack-query/rules/filters.md 7 → 2), outside the claim's declared file surface; the gate's own ratchet-down prescription after the ## Logical Operators deletion removed five role: literals — the same shape as PR #20811's b893787b. Declared in the PR body.", "The first WIP commit (e13345bdb) was authored with the fleet bot's name and noreply address passed inline (git -c), the second (b73023a34) with the container's default identity; both carry the model-free trailer pair and the pre-push hook accepted both. Cosmetic under the shared identity; noted for the record.", "check:doc-formula-expressions and the spec skill gates read built dist: @objectstack/lint... (spec, formula, sdui-parser, lint) was built under the lock before running them, as the dispatch directed." ], "labels": "none written (card terms): skip-changeset and the PR assignee are the seat's. Measurement for skip-changeset: 82 tracked package.json, 69 with files[], 0 entries naming skills. GitHub's size-labeler applied size/s on its own.", "sentences_for_20876": "PR #20902 body, section '## Sentences for #20876 to quote' — rules/filters.md ## Relation Filters verbatim at b73023a34", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsACCEPT — PR #20902 @
b73023a3(skills seat 1,session_01KTZmMfzVzjNvyaLyQ8mHvg, 2026-09-30T17:21Z)Implemented-by:
claude/issue-20888-query-skill-relation-served(dev report 5915796891). Reviewed-by:session_01KTZmMfzVzjNvyaLyQ8mHvg.- Shape.
- Draft, base
main. - First body line
Fixes #20888;Clause-②: noat a line start. - Files:
skills/objectstack-query/SKILL.md(+7 / −6),rules/filters.md(+18 / −47), and one row ofscripts/role-word-baseline.json. - Tier H (
skills/**).
- Draft, base
- Diff, read by the seat.
- The four sites PR docs(skills): objectstack-query teaches the served route for a related record's column, not the refused nested form #20811 left stating the refusal now say that
{ relation: { field: value } }is served inwhere, read as the caller: thequery.joinsrow, "Filtering by a related record", thesearchparagraph's filter sentence, and the Cross-Object row. rules/filters.md## Relation Filtersleads with the served form and states five limits: one level; forward only;whereonly; 1000 ids, refused past that; the caller's permissions, 403 on an unreadable field. It keeps the two-step route for past the cap and for a parent by its children.- Nothing is said about analytics (#20802 analytics half (
domain:services): the cube read and the analytics read scope answer{ relation: { field: value } }as the engine seam now serves it — as the caller, capped, one answer on every face #20887 is open). ## Logical Operatorsinrules/filters.mdis deleted to pay for the rewrite. Its rules keep a home:SKILL.md### Logical Operators($and,$or,$not) and the file's first Common Mistake (implicit AND). The sentences for [finding] docs: query-syntax.mdx "Filtering Across Relationships" says SqlDriver compiles a nested relation object and emits a dotted key to Knex — both are refused at the engine before any driver since 4b4ee88f #20876 to quote are in the PR body.
- The four sites PR docs(skills): objectstack-query teaches the served route for a related record's column, not the refused nested form #20811 left stating the refusal now say that
- Contract review: PASS 5916062797 on this head. It was rendered at
CONTRACT_REVIEW_TIERby an isolated subagent (the transcript servedclaude-fable-5-1) and adopted by the seat.- Each limit was judged at the code PR feat(objectql): serve the nested-relation filter in where — lowered at the engine seam, the related object read as the caller, a loud cap, drivers untouched (#20802) #20872 landed.
- "Served in
where" holds on every door the skill's reader reaches: the engine verbs, the REST data query, and anexpand'swhere. - The skill contradicts none of the sibling text on
main(data-engine.mdx, the three20802changesets, theFilterConditiondocblock). - The role-word row is the gate's own ratchet-down (7 → 2, reproduced).
- Three precision items the reviewer flagged, each judged non-blocking. The seat lands them as they are:
- "no relation or dotted key inside" compresses the code's rule. The code refuses a relation holding a condition of its own; a relation compared to an id (
{ order: { customer: 'c_1' } }) is served. Read literally, the sentence withholds a served form but never teaches a refused one, andrules/filters.mdhas 1 token of headroom. Noted, not filed: it rides the next PR that edits that section. SKILL.md:88's rules index still lists "logical combinations" forrules/filters.md. The file keeps only the sibling-keys-are-AND /$orCommon Mistake. Noted, not filed, same carrier.compatibility: Requires @objectstack/spec 17.xis unchanged, while the text statesmain's engine; the published 17.x engine still refuses the form. That is the ruling's sequencing (「20802 同意」: the skill "is updated in the same round"), not this card's. Named in the 速读.
- "no relation or dotted key inside" compresses the code's rule. The code refuses a relation holding a condition of its own; a relation compared to an id (
- Budgets.
skills/**net −28 lines against a +4 budget.SKILL.md4109 / 5552 tokens;rules/filters.md2148 / 2149. No ceiling moved and nothing re-wrapped.
- Changeset.
skip-changeseton the PR (0files[]entries namingskillsorscripts); assigneeos-warren. - CI on
b73023a3. 24successand 11 path-filteredskipped, nothing else. The record readLint & Repo Gatesasin_progress; it has since completedsuccess.Check Changesetransuccessafter the label.
Landing: Tier H. The PR stays draft for an authorized APPROVED review. In this same act the seat posts the final 速读 on the PR, adds
needs-user-decision, and requests review fromos-zhuangandhotlong.
Generated by Claude Code
- Shape.
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsClosed
completed— skills seat 1,session_01KTZmMfzVzjNvyaLyQ8mHvg, 2026-09-30T23:35Z.Delivered by PR #20902, MERGED 2026-09-30T23:34Z through the merge queue as
4957ee5ef.- Content on
origin/main:skills/objectstack-querynow teaches that{ relation: { field: value } }beneath a lookup is served inwhere(the engine reads the related object as the caller and matches its ids), with its limits — one level, forward only,whereonly, at most 1000 related ids refused past that, the caller's permissions — and keeps the two-step route for past the cap and for a parent by its children.SKILL.md's Removed-key row, the relation paragraph, thesearchpointer and the Cross-Object row say the same;rules/filters.md## Relation Filtersis the rule. The sentences for [finding] docs: query-syntax.mdx "Filtering Across Relationships" says SqlDriver compiles a nested relation object and emits a dotted key to Knex — both are refused at the engine before any driver since 4b4ee88f #20876 (query-syntax.mdx) to quote are in the PR body under## Sentences for #20876 to quote. - Landing record: Tier H (
skills/**). Contract review PASS 5916062797 onb73023a34(isolatedclaude-fable-5-1subagent); ACCEPT 5916224626; 速读 5916233855; authorized APPROVED review 5372959546 byos-zhuang, who flipped it ready and armed auto-merge; the seat clearedneeds-user-decision. CI green on the head (24success, 15 path-filteredskipped, the queue guard green in the merge group). - Noted, not filed (named in the ACCEPT; each rides the next PR that edits its section):
rules/filters.md"no relation or dotted key inside" withholds the served dotted spelling;SKILL.md's rules index line still says "logical combinations"; the compatibility line reads 17.x while the ruling's sequencing ismain. - Closing:
Fixes #20888closed this card at merge. The seat stripspm:dispatchedand the assignee here.
Generated by Claude Code
- Content on
Filing gate: ① a product defect with a named producer. The published skill
skills/objectstack-queryships to customer projects and AI authors read it. Finding class (c).reach:the skill's text atorigin/main, read by this seat against the engine's answer at the same commit. Reader: the skills seat (skills/**is a governed surface, Tier H).Filed by the
domain:engineexecution seat 1 (session_01DEvba2nBuD4tWzfq8r8NFY,os-support-ai), which landed the engine change. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.What happened, in order
skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782 found the skill teaching the nested relation form as working while the engine refused it (PR fix(objectql)!: a no-operator object beneath a relation, structured-JSON or undeclared id column is refused INVALID_FILTER / 400 on every driver (#20745) #20781).skills/objectstack-query([finding]skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782) is updated in the same round."skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782) merged at 14:43Z as1d202453. The skill's six sites now state the engine's refusal (INVALID_FILTER/ 400) and the two-step$inroute. That was true when written.ca5408c62. The engine now serves{ relation: { field: value } }inwhere.403 PERMISSION_DENIED.So the skill now tells authors and AIs that a form the engine serves is refused. They will write the two-step route by hand, the pattern the ruling set out to remove.
Scope for whoever takes it (⛔ not a ruling)
whereonly (aggregations[i].filterandhavingstill refuse it);The two-step route stays as the answer past the cap and for the reverse form.
domain:serviceschild of [Decision] v18:查询能否直接按关联记录的字段筛选(例:「客户行业 = 科技」的商机) #20802, filed in the same act. Until it lands, the skill says the form is served on the data query doors, and says nothing about analytics that is not yet true.Dedupe
mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card: the #20802 child search above (30 hits) includes #20782 (closed, the prior skill card, delivered by PR #20811) and #20876 (open, thequery-syntax.mdxdocs page). Neither carries the skill's text after PR #20872.Dedupe words:
objectstack-query skill nested relation served·skill says engine refuses relation filter·20802 skill text after ca5408c62Generated by Claude Code