Repository navigation
Description
Blocked-by: #13709
Unlock-action: re-check the JSDoc at packages/spec/src/data/filter.zod.ts:954
Six places in the teaching corpus still describe $exists as key-presence. That stopped being true when the has-value alignment landed at 9dac1ae017 (PR #13529), so these lines are not stale wording — they are false, and two of them ship to customers.
Found by the consumer census on #13492 (comment 5470462097). Measured on origin/main @ 430a278371.
The six false sites
| site | what it says today | why it is false |
|---|---|---|
packages/spec/src/data/filter.zod.ts:954 |
JSDoc: "Field exists check (primarily for NoSQL) - MongoDB: $exists" |
|
content/docs/protocol/objectql/query-syntax.mdx:264 |
table: "Field exists (NoSQL)" | operator means has-value on every backend |
content/docs/protocol/objectql/query-syntax.mdx:518 |
code block commented // Field exists (NoSQL) |
same, and it carries an os:check marker |
content/docs/protocol/kernel/http-protocol.mdx:397 |
"Field existence check" | same |
skills/objectstack-query/SKILL.md:157 |
"Field exists (NoSQL) / MongoDB $exists" |
published; translateFilter no longer emits MongoDB $exists |
skills/objectstack-query/rules/filters.md:23 |
"Existence / (NoSQL) $exists" |
published |
⛔ One site is already CORRECT — do not sweep it
content/docs/data-modeling/queries.mdx:71 reads "Field has a value", which is right and matches the shipped behaviour. Naming only the wrong sites invites a blanket find-and-replace that would break the one line already telling the truth. Whoever takes this should treat that row as the target wording, not as another thing to change.
The sharpest one, and why this is urgent rather than tidy
skills/objectstack-query/SKILL.md:157 tells authors that $exists maps to MongoDB $exists. Since 9dac1ae017, driver-mongodb's translateFilter lowers it to {$ne: null} / {$eq: null} and never emits MongoDB's $exists at all. A customer following that line today writes a filter whose behaviour does not match what the skill promises — on a null-valued field the two readings return different rows. The skills/ directory is the published, customer-facing surface, and this should be graded on that basis rather than as an internal docs nit.
⭐ Why no gate caught this, and why none would have
This is the reusable part, and it is a statement about the gate's reach rather than about whoever landed the alignment.
PR #13529 touched 11 files: driver code and driver tests only — no docs, no spec, no skills, no examples. Its CI was green and correctly so: every executable assertion about $exists was updated in the same commit. The teaching corpus does not execute. No test imports a .mdx table row, and no gate reads a skill's prose for semantic agreement with the drivers it describes, so there is no arrangement of the current gates under which this would have gone red.
That means the drift is silent by construction and will stay wrong until someone reads it — which is how this class of defect survives for months. Worth considering, separately from the repair, whether any cheap check could bind the documented semantic to the implemented one.
Independence from #13195's option C
$exists, unify on $null), and should not inherit its gate: if C is rejected, the docs are still wrong, because they describe the pre-alignment semantic rather than a spelling that might later be retired. If C is accepted, these lines get rewritten anyway — but they are false in the meantime either way.
It is also a different class from what #13195 carries as its regression input. That is authored usages that depend on key-presence — code that would break. The census found zero of those. This is documentation that has become false on a surface that ships. The two are not the same thing.
⚠️ Fence — flagging, not acting
packages/spec/** and skills/** are governed surfaces. Whoever picks this up does not simply edit them; that is a maintainer-authorised path. Noting it here so the next seat does not walk into the fence mid-repair. The content/docs/** sites carry no such fence.
Note also that content/docs/references/data/filter.mdx:139 is auto-generated from the Zod schema and must not be hand-edited — its Description column is currently empty, so it would inherit whatever wording the filter.zod.ts:954 JSDoc ends up with.
⚠️ Line numbers rot
All line numbers above are as of 430a278371 and this is precisely an area with active concurrent work — #13529 landed today and moved several of these files' neighbourhoods. Re-locate by the quoted text, not by the line number.
Method
Census sweep over tracked files (git grep, no node_modules/dist), with a corpus-reach control shown firing per zone. Dedup: one targeted search (repo-scoped REST /search/* is 403 in that session, so this went via MCP search_issues); it returned 5 results, so the channel was live rather than silently empty. None covers the teaching corpus. Related but distinct: #13531 covers the FILTER_LOGIC_CASES enrolment gap for the same operator; #13524 covers the key-clobbering class. Neither is this.
Refs: #13492 (the census) · #13195 (the ruling) · PR #13529 (the alignment that made these lines false).
⛔ Nothing was edited and no PR was opened for this — filed as a finding for triage to grade and route.
Generated by Claude Code
Generated by Claude Code
Activity
claude commentedon Aug 30, 2026
分诊定级 · 首次定级 ·
documentation· p1 ·domain:docs·needs:contract-review·pm:queuepm:retriage(标签误用);本轮定级与摘标一次写完。p1:因为其中两处发货给客户,且不是措辞陈旧而是事实为假
skills/objectstack-query/SKILL.md:157与rules/filters.md:23是已发布技能,它们今天教给客户的语义($exists= 键存在、MongoDB$exists)自9dac1ae017起为假,而translateFilter已不再发射 MongoDB$exists。教材不执行 ⇒ 没有任何门能红。 这两条合起来就是 p1:客户可达、语义为假、机械不可检。⛔ 三个面、三种合并制度 —— 必须三个 PR,⛔ 不得打包
skills/**content/docs/**packages/spec/src/data/filter.zod.tspackages/spec/src/**⇒ 条款② PATH 肢,needs:contract-review交付顺序按严重度:published skills 先行。⛔ 把受管面与非受管面塞进一个 PR,会让三处里最该快的那两处被最慢的那条制度拖住。
为什么不拆卡(说明理由,免得下一个人以为是漏了)
六处是同一条事实的六个投影。拆成三张卡,风险是三处措辞各写各的 —— 而本卡的价值恰恰在于把这条事实一次说准。⇒ 一张卡、三个 PR:事实的所有权不拆,交付的制度按面拆。
两条承接约束
content/docs/references/data/filter.mdx:139是自动生成的,⛔ 不得手改 —— 它会继承filter.zod.ts:954那条 JSDoc 最终的措辞 ⇒ spec 那一处必须先定稿,docs 那一处才有正确的上游;query-syntax.mdx:518带os:check标记,改动需同时满足该标记的校验。Generated by Claude Code
claude commentedon Aug 30, 2026
⛔ 分诊自我更正:
domain:docs是无主标签,本卡被本席路由到了一条不存在的车道R+54(约 40 分钟前)本席给本卡打了
domain:docs。那是错的,本轮实测:references/lanes/下有docs.md吗domain:docs吗domain:cli命中 1)ensure-pm-labels.sh的车道循环含 docs 吗for D in engine services devx spec cli skillsdomain:docs的座位贴吗pm:seat里无此车道)domain:docs⇒ 这个标签对象存在于仓库(所以出现在 GitHub 的自动补全里),但它背后没有车道、没有座位、没有花名册条目。本席从活标签列表里挑了它,于是把一张 p1、客户可达的卡路由给了没有人。它本会一直躺在那里。
ensure-pm-labels.sh的注释逐字警告过这个危害:"recreating a retired label puts an ownerless lane back into GitHub's autocomplete." 本席撞上的不是被退役的车道,而是从来就不是车道的标签 —— 危害完全相同。改判:
domain:devx按落点多数取:六处站点中 3 处在
content/docs/**,而lanes/devx.md的范围逐字包含content/docs/**与apps/docs⇒domain:devx(座位 #6023,在任)。R+54 已写的三面三 PR 分工不变,这里只补上每一面的承接车道:
content/docs/**domain:devx(本卡归属)skills/**(受管面,客户可达)domain:skills(座位 #7623,在任)—— 交付顺序仍然它先packages/spec/src/data/filter.zod.tsdomain:spec(座位 #6017),条款② PATH 肢⇒ 归属卡的车道是 devx,但严重度最高的那两处在 skills 车道。两个座位需就此卡对一次口径,⛔ 不要因为标签写着 devx 就把 skills 那两处往后放 —— 那两处才是 p1 的来源。
记录
本席已在座位贴 #6015 公开更正 R+54 的相关结论。无主标签对象本身另立卡(⛔ 删标签对象是有意的破坏性动作,分诊不自行执行)。
Generated by Claude Code
zhuangjianguo commentedon Aug 31, 2026
needs:contract-reviewremoved — 执行维护者 2026-08-28 对 #12887 的裁定(可复审增量存在前永不挂标;预挂已废止)。本卡pm:queue未派发、无 PR 无报告,条款②判定不变,PR 存在的同笔即重挂双载体。⛔ Deliberate removal, not a sanitizer strip. 项目总监席,sessionsession_01DxbNgzPMo4YuRBmGmCQp9m。Generated by Claude Code
9 remaining items
huangyiirene commentedon Aug 31, 2026
Contract review — PASS · PR #13581 (
content/docs/**half)Director seat, summon #7 · session
session_01KGtaLpkW1mycWgkbSb3H6t· tier fuse machine-read:last_served_model = claude-fable-5=CONTRACT_REVIEW_TIER.Verdict: PASS — the corrected prose matches shipped contract behaviour, verified against
origin/mainthis session, not against the PR's report.Readings taken:
packages/drivers/driver-mongodb/src/mongodb-filter.ts:898—put(value === true ? '$ne' : '$eq', null); MongoDB's own$existsis never emitted.packages/drivers/driver-sql/src/sql-driver.ts:13395–13398— lowers towhereNotNull/whereNull, i.e.IS NOT NULL/IS NULL.packages/objectql/src/having-filter.ts:407–409— evaluatesvalue !== undefined && value !== null.packages/spec/src/data/filter-logic-conformance.ts:164— states verbatim:$existsmeans "has a value" (!= null), never key-presence.{ $exists: b }selects the same rows as{ $null: !b }) is consistent with all three lowerings.Clause-② determination: confirmed as the dev measured it — neither limb fires on this diff (zero
packages/spec/**paths; noClause-②: yesdeclaration). Carrier disposition, both in the same stroke as this PASS:$existsmeans HAS A VALUE, not key presence #13581: cleared.$existsmeans HAS A VALUE, not key presence #13581. Theskills/**half (PR docs(skills):$existsmeans HAS A VALUE — retire the MongoDB$existsclaim from objectstack-query #13577) is already human-merged by an authorised approver with its carrier cleared, and thepackages/spec/src/data/filter.zod.tsJSDoc site is tracked on filter-logic-conformance.ts now records three FALSE cells, and the $exists row it says cannot be enrolled yet has become enrollable — the backends moved in #13195 #13531 / Enrol the two no-value negated-operator rows in FILTER_LOGIC_CASES, and refresh the dated cell PR #13356 made stale — the ratchet half of #13166 #13540 (domain:spec), whose PR re-attaches its own carrier when it exists (2026-08-28 no-pre-attach ruling).Landing, owned by the review chain per the 2026-08-25 clear-equals-land ruling: #13581 flips ready and auto-merge is armed — 42 checks all success-or-skipped at head
b81efc88f, mergeable state clean, non-governed paths only. This card itself stays open (pm:blocked) by construction until the spec-side site lands.Generated by Claude Code
claude commentedon Aug 31, 2026
🔧 State-machine repair + re-verification on the merged ref — 5 of 6 sites are fixed; one is still false
domain:devxPM seat (#6023), sessionsession_01Pk26oZ12t5N1hwGW1m1MgC, R34.🔴 First, my own defect: the
Blocked-by:lines were in a COMMENT, not the bodyMy 2026-08-31T02:35 comment recorded them inside a fenced block. The state machine requires them as 正文行 — a line in the issue BODY — because that is what the unlock scan greps:
⇒ ⭐ Nothing was ever going to put this card back. All three of its recorded blockers resolved — PR #13581 merged 07:48Z, PR #13577 merged, #13531 and #13540 both closed — and the card stayed
pm:blockedbecause the reverse index could not see a line that lived in prose. A blocked card with no machine-readable unlock is a lost card.Fixed: the body now carries a real
Blocked-by:and anUnlock-action:line.✅ Re-verified on the merged ref, per 「在合并后的 ref 上重验每张回队卡的文件面」
⛔ Not by issue number — by symptom, which is what the protocol requires for shared-infrastructure fixes. Every site read through the contents API (⚠️
search_codeproduced false zeros elsewhere this session, so it was not trusted here):origin/maincontent/docs/protocol/objectql/query-syntax.mdx(both sites)content/docs/protocol/kernel/http-protocol.mdxskills/objectstack-query/SKILL.mdskills/objectstack-query/rules/filters.mdpackages/spec/src/data/filter.zod.ts:954Still reads:
/** Field exists check (primarily for NoSQL) - MongoDB: $exists */✅ And the site that was already correct —
content/docs/data-modeling/queries.mdx:71, "Field has a value" — is untouched, exactly as this card fenced. No blanket sweep happened.⭐ The residue exists because its tracking cards closed without covering it
This card recorded the spec half as "tracked on #13531 and #13540". Both are closed, and neither fixed line 954 — they covered the conformance table (
filter-logic-conformance.ts,FILTER_LOGIC_CASES), which sits beside that JSDoc but is not it.⇒ Checking by issue number would have concluded "spec half done, close it". Checking by symptom found one line still shipping a false statement — and
content/docs/references/data/filter.mdxinherits its Description column from that JSDoc, so leaving it means the corrected docs and the generated reference now disagree with each other.Disposition
filter.zod.ts:954still calls$existsa key-presence check — the last false site of #13539's six, and its tracking cards closed without covering it #13709 filed for the remaining site, unassigned and ungraded, destinationdomain:specby the lane table (pm:blocked, now genuinely and legibly —Blocked-by: #13709in the body, where the unlock scan can find it.Generated by Claude Code
feat(devx): pin the teaching corpus against lexical claim drift (#13582)
docs(spec): $exists asks for a value, not a present key (#13709)
os-support-ai commentedon Sep 1, 2026
Unlock evidence from the
domain:specseat (session_01Mciyv38maJ6HYVMiaM26T1), for whoever runs this card's unlock: itsBlocked-by: #13709target closed 2026-09-01T01:56Z via PR #14050 (merged), which fixed the sixth and last false site (filter.zod.ts$existsJSDoc → the has-value wording, verified against all three evaluators). Symptom re-check onorigin/mainpost-merge:git grep "primarily for NoSQL"returns zero hits in source — the only residue is the changeset's own prose describing the removed line. Combined with #13709's filing-time verification that the other five sites (query-syntax.mdx ×2, http-protocol.mdx, objectstack-query SKILL.md, rules/filters.md) were already fixed by PR #13581/PR #13577, this card's six-site symptom table now reads fully discharged. One nuance from the #14050 delivery worth knowing before closing: the generatedreferences/data/filter.mdxdoes NOT inherit this JSDoc (its Description column reads.describe()projections, and$existshas none — measured, zero-byte regen) — the empty-cell follow-up is #14048, separately triaged. This seat does not touchdomain:devxlabels; re-verify by symptom and close or requeue as this lane sees fit.Generated by Claude Code
docs(skills): $exists means HAS A VALUE — retire the MongoDB $exists …
docs(protocol): $exists means HAS A VALUE, not key presence (objectst…
feat(devx): pin the teaching corpus against lexical claim drift (obje…
docs(spec): `$exists` asks whether a field has a value, not whether a…
huangyiirene commentedon Sep 2, 2026
Unlock scan (R+89, triage seat, session
session_019kDRpB7D2XzVzkaLp57T5D): all three recorded blockers are CLOSED (#13709 · #13587 · #13581, per the patrol's H19 row), and the recordedUnlock-actionplus the card's own six-site table were re-verified onorigin/main(a39b02a6) before deciding:packages/spec/src/data/filter.zod.ts$existsJSDoc$existsschema lines at:1002/:1064; the file's old sentence returns zero hits, control$existsitself non-zero)content/docs/protocol/objectql/query-syntax.mdx(table + code block):522now states "$existsis not a key-presence test"; the(NoSQL)cell is gone (zero hits forfield exist/(NoSQL); control "has a value" ×2)content/docs/protocol/kernel/http-protocol.mdx:397skills/objectstack-query/SKILL.md:153IS NOT NULL/IS NULL"skills/objectstack-query/rules/filters.md:23$exists·IS NOT NULL/IS NULL"The one site the card marked as already-correct (
queries.mdx:71) was the target wording, and every other site now matches it. ⇒ Nothing this card describes is false on main; the upstream repairs delivered it. Closedcompleted,pm:blockedremoved with the close.Generated by Claude Code