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 }}
Repository navigation
[finding] odata.zod.ts's @example Programmatic Use writes every ODataQuery key unprefixed — the bag safeParses clean to {} with all seven keys silently stripped, and it is published in both the tarball and the reference page #19028
Handed back by the os-dev working #18977 (report comment 5729887433); filed by the domain:spec seat 3 because devs do not POST issues. finding only — no domain:*, no type, no priority:*.
Class
(c) — a metadata-authoring trap. An author is taught a bag the runtime silently drops, with no diagnostic.
The file-level docblock of packages/spec/src/api/odata.zod.ts carries an @example Programmatic Use block that writes every key unprefixed — select, filter, orderby, top, skip, expand, count — against the type ODataQuery, whose every key carries a $.
Measured: ODataQuerySchema.safeParse on that example bag verbatim SUCCEEDS and returns {} — all seven keys stripped, no error, no warning. The example parses clean and means nothing.
That is the (c) shape exactly: the metadata is accepted and silently discarded rather than refused, so nothing anywhere tells the author the seven keys did nothing.
It is published twice
packages/spec ships src/**/*.zod.ts in files[], so the docblock reaches anyone who opens the installed package.
The file-level docblock is rendered into content/docs/references/api/odata.mdx lines 56-67 by the generator.
So the same wrong example is in the tarball and on the documentation site.
Why the implementing PR deliberately did not fix it
Recorded because it is a scope judgement worth preserving, not an oversight: the file-level docblock is the one part of that file feeding the generated reference page, so repairing it moves content/docs/references/** — a directory that round had fenced for hot-file serialisation against two other in-flight PRs. The in-place-fix exemption fails on that condition, so the dev left it and reported it. The fix is one docblock edit plus gen:docs.
Evidence limits
Measured by the implementing dev; this seat has not re-derived it. The cheap re-check: safeParse the example bag and assert the result is {}, with a lit control — the same bag with $ prefixes must come back populated. If the control does not populate, the instrument is wrong rather than the example.
Dedup words
odata.zod @example unprefixed keys · ODataQuery example parses to empty · odata programmatic use example stripped · odata.mdx example wrong keys · ODataQuery missing $ prefix example
Dedup was run on the neighbouring search for this card's sibling finding (2 results, no same-subject hit). Limit: these words name the example's spelling. A card filed from the consumer side ("my OData query is ignored") would share none of them, so a zero here is not evidence of no duplicate from that direction.
{
"issue": 19028,
"status": "done",
"branch": "claude/issue-19028-odata-example-dollar-prefixes",
"pr": "https://github.com/objectstack-ai/objectstack/pull/19058",
"session": "session_01JbZnqu8bt6YqfJsr9vaFb3",
"premise_still_valid": true,
"summary": "The seven keys in the `@example Programmatic Use` block of packages/spec/src/api/odata.zod.ts now carry their $ prefixes, and gen:docs reprojected the block into content/docs/references/api/odata.mdx. The schema is untouched: no .strict(), no accept-set change, no refusal added. BASE MOVED between dispatch and start — origin/main was b22db516d2 at dispatch time and abb01f105c when I branched (67624b78d5 by the end of the run), so every reading below was re-derived at abb01f105c; the two docblock line spans held unchanged at :42-52 (correct, untouched) and :54-66 (the one repaired). ONE CORRECTION TO THE THREAD, not to the dispatch: the triage comment (5730521503, stamped 13:14:56Z) reads PR #19018 as state=open and not merged, but the API reports merged=true with merged_at=2026-09-18T13:05:35Z, about nine minutes BEFORE that read. Its +50 lines were therefore already in my base. This changes nothing about the card — the triage's conclusion that this card outlives #19018 holds either way, and I did not touch packages/spec/src/data/data-engine.zod.ts — but the seat should know one of its board readings was stale. I agree with the dispatch on clause-② (no) and on this not being skip-changeset, and I re-measured both rather than inheriting them.",
"tests": "SUBJECT LEG, verbatim by construction: the probe extracts the object literal out of the docblock itself rather than retyping it, so the bag fed to ODataQuerySchema.safeParse is byte-for-byte what the file teaches. BEFORE (abb01f105c): SUBJECT success=true keptKeys=0 data={}; LIT ($-prefixed) success=true keptKeys=7; DARK (one fabricated key zzz_not_a_real_odata_key) success=true keptKeys=0. SUBJECT and DARK are the same reading — the documented bag and pure nonsense parse identically. AFTER: SUBJECT success=true keptKeys=7 data={\"$select\":[\"name\",\"email\"],\"$filter\":\"country eq 'US' and revenue gt 100000\",\"$orderby\":\"revenue desc\",\"$top\":10,\"$skip\":20,\"$expand\":[\"orders\"],\"$count\":true}; LIT unmoved at 7; DARK unmoved at {}; the pre-change bag pinned in the probe still {} — the last two are the zero-behaviour-change legs, measured rather than asserted. REGENERATION LEG: gen:docs wrote 224 files and exactly one moved, content/docs/references/api/odata.mdx lines 57-69, same seven keys; the page read 'Programmatic Use' 1 with lit control 'OData Query' 1 before the run, so the projection was confirmed, not assumed. GATES: dispatch-gates --commands --repo objectstack-ai/objectstack derived 101 commands; all 101 run with $? captured before any pipe into a TSV; all 101 final exit 0; `--ran` over the exit-code-bearing record reconciles 101 derived / 101 run / 0 NOT-MEASURED / 0 UNRUN (a DERIVED zero, the tool's own words, because every line carries a code). Six of them first returned PREREQUISITE NOT MET (exit 3: check:doc-formula-expressions, check:doc-security-posture, check:docs-transcript-drift, check:dual-build-cjs-loads, check:lean-entry-closure) or refused on an unbuilt client-react (check:skill-examples, exit 1 with 'a verdict now would be a FALSE GREEN'); a whole-repo pnpm build (73/73 tasks, under the shared verify lock) cleared them and all six re-ran to a real exit 0 — their first results are recorded as NOT MEASURED, not as failures. pnpm --filter @objectstack/spec test: 491 files / 14295 tests, all passed. pnpm --filter @objectstack/spec typecheck: pass, test layer included (54 files / 259 errors / 144 pinned signatures held in the shrink-only debt ledger, unchanged). check:generated: clean, and git status is empty after the full build, so no generated artifact moved on its own and authorable-surface.base.json did not drift. pnpm lint (eslint . --no-inline-config, the WHOLE repository — not a narrowed subset, so no narrowing evidence is owed): exit 0 on the final tree at 84f244a07d. DARK BOUNDARY: no test assertion needed editing and none was edited; this diff contains no test file and no schema byte — the seven changed lines all begin with ' * ' inside the block comment. ABLATION: none performed and none owed — this card adds no guard, gate or assertion whose ability to fail needs proving; the DARK and pinned-pre-change legs are the controls that do the equivalent work here, so no on-disk mutation/rebuild proof is claimed. ZERO-HIT DISCLOSURES (instrument radius + a known target necessarily outside it): (1) governed-surface hits = 0 — instrument reads ONLY this diff's three paths against the five prefixes AGENTS.md Prime Directive #14 names; AGENTS.md itself is a real governed file present in the tree and necessarily outside the radius, because the instrument never looks past my change set. (2) tarball entries under content/docs = 0 and .test.ts entries = 0 — instrument is `npm pack --dry-run --ignore-scripts --json` for @objectstack/spec ALONE (2039 files); the 462 *.test.ts files that exist under packages/spec/src, packages/spec/src/api/odata.test.ts among them, are known targets on disk and necessarily outside that radius since files[] never lists them; positive control 214 dist/ entries present. (3) non-zero gate exits = 0 — radius is the 101 path-derived families only; the derivation itself names what is outside it and I did not run those: 49 artifact-roster families, 11 declared-too-wide families, 6 path-scheduled CI jobs and the always-runs tail. (4) MCP GitHub calls = 0 — radius is tools invoked in this run.",
"mcp_calls": "0 — no MCP GitHub tool was loaded or called; every GitHub read and write went through the REST proxy with curl and GITHUB_TOKEN.",
"api_writes": "2 REST writes. (1) POST /repos/objectstack-ai/objectstack/pulls — draft PR 19058, HTTP 201, body read back and byte-identical to what was sent (6249 vs 6250 bytes, trailing newline only), exactly one footer in the session-URL form. (2) POST /repos/objectstack-ai/objectstack/issues/19028/comments — this report. ZERO label writes: the dispatch names no label and this round is not skip-changeset, so the intersection is empty and nothing was written; labels remain the seat's. Zero POST /issues, zero PATCH of the PR body, zero assignee write, no second Claim comment. Git pushes (3: empty branch probe, then one per commit) are git, not REST.",
"open_questions": [
{
"question": "NON-BLOCKING, raised only because this card half-closes its own class: the example is now correct, but ODataQuerySchema still accepts and silently strips any key it does not declare, which is exactly what let a seven-key example contradict the schema in the same file with every gate green. The dispatch fenced this off as a separate question; should it be routed as one?",
"options": [
"A — file nothing; the trap was the example, it is fixed, and the strip-on-unknown behaviour is deliberate Zod default shared by most schemas in the package",
"B — route a separate card asking whether ODataQuerySchema should refuse unknown keys (note: it would have to settle what happens to the OData.buildUrl helper and the two existing unit tests, and #18704 already settled that the transport schema, not this one, grades real ingress)",
"C — narrower: bring the two @example blocks in this file into the type-checked set (see out_of_scope_findings), which catches a recurrence mechanically without changing any accept set"
],
"recommendation": "C, because it closes the recurrence path without touching a single accept set, and it is the only one of the three that makes the defect this card fixed impossible to reintroduce silently. B is a real question but it is a contract decision about refusal semantics, not a documentation one, and it belongs to whoever owns the #18704 line. I did not act on any of the three."
}
],
"out_of_scope_findings": [
"noted, not filed: the two @example blocks in packages/spec/src/api/odata.zod.ts are outside the type-checked set. check:skill-examples compiles 258 MARKED blocks across three surfaces (10 of them TSDoc blocks under packages/spec/src); a block is marked by an HTML comment on the line directly above its fence, and neither block here carries one — which is why an example contradicting the schema in the same file sat green indefinitely. Not filed because it is an observation about gate coverage, not a reproducible defect, a declared-contract violation, or an authoring trap: the trap was the example text, and this PR removes it. Not fixed in place either, on two counts — marking is not a prose change (the block must gain an import for ODataQuery to compile standalone, which moves what the generated reference page shows), and it adds a verification surface, which the in-place exemption forbids. WHO PICKS IT UP: the domain:spec seat, on the next edit to any @example under packages/spec/src/api/** — the same surface this card and #18977 both landed on inside one day, so it is not a hypothetical reader. Recorded in the PR's Acceptance notes."
]
}
Activity
os-bill commentedon Sep 18, 2026
Claim: PM loop round 41
Session:
session_01JbZnqu8bt6YqfJsr9vaFb3Branch:
claude/issue-19028-odata-example-dollar-prefixesWorktree:
objectstack-issue-19028Domain:
domain:specSeat:
domain:spec#2(座位贴 #18549)File surface:
packages/spec/src/api/odata.zod.ts的文件级 docblock,外加由它再生的content/docs/references/api/odata.mdxContainer & model:
M,mode:subagent,model: default judgement tierClause-②: no
Thread-read: 5730521503
⏱️ 2026-09-18T13:57Z 取数,
origin/main=b22db516d2。⛔ 每条本席第一手取。⭐ 卡面说「本席未重取」——本席重取了,三腿俱全
⏱️ 2026-09-18T13:57Z,在
packages/spec内用tsx直喂ODataQuerySchema.safeParse:⇒ 卡面的主张成立;⭐ 而 DARK 那一腿给出了卡面没有的一句话:被文档教出来的那个 bag,与一袋纯粹的胡说键,解析结果一模一样(都是
success=true+{})。这就是 (c) 类的准确形状。⭐ 正确拼法就在同一个 docblock 里、往上十行 —— ⛔ 那一块不许动
⏱️ 2026-09-18T13:57Z 直读
origin/main:packages/spec/src/api/odata.zod.ts:⇒ ⭐ 同一段 docblock 里的两个例子互相矛盾,而只有后一个是错的。⛔ 不要动
:42-52—— 它既是对的,又是本轮「正确拼法是什么」的在文件内的证据。本轮要做的
把
@example Programmatic Use里那七个键改成它们的$拼法,使该 bag 经ODataQuerySchema解析后七个键全部保留;然后跑pnpm --filter @objectstack/spec gen:docs让content/docs/references/api/odata.mdx跟上。⏱️ 2026-09-18T13:57Z 实测该 docblock确实投影到那张页:
odata.mdx现读含 "Programmatic Use" 1 次(⭐ 亮控:同页 "OData Query" 也读 1)。⭐ 本轮会动已发布内容 ⇒ ⛔ 不是 skip-changeset
⏱️ 2026-09-18T13:57Z 现读
packages/spec/package.json的files[]含src/**/*.zod.ts⇒odata.zod.ts本身就是已发布文件。⇒ 带一条patchchangeset,正文说清「更正一个今天会被静默丢弃的示例,⛔ 无行为变更」。files[]上」的逐行读数;量出与本席相反就照实顶回来,⛔ 不要写空 changeset。⛔ 只读栅栏 —— 按改动种类
ODataQuerySchema加.strict()、不改 accept set、不加任何拒绝行为。本轮只改示例散文。 ⭐ 「要不要让它拒绝未知键」是另一个问题,⛔ 本卡不问、⛔ 你不要顺手做。:42-52的@example OData Query(它是对的)。content/docs/references/**(生成物),跑gen:docs。packages/spec/src/data/data-engine.zod.ts:那是 finding(spec):$orderbyis declared TWICE and incompatibly —ODataQuerySchemaaccepts only the string forms the transport schema deliberately refuses, and neither cross-references the other #18977 的面($orderby双声明),已由别席派发、PR docs(spec): cross-reference the two$orderbydeclarations and pin their disjoint accept sets #19018 在飞。验收
@example里那个 bag 逐字喂给ODataQuerySchema.safeParse,必须success=true且data保留七个键。三腿一起给:改后的 bag(七键在)、⭐ 亮控(改前的 bag 仍解析成{})、⭐ 暗控(一袋伪造键仍解析成{})。gen:docs后content/docs/references/api/odata.mdx跟着变,给出改前/改后那几行。packages/spec的测试与check:generated改前改后都绿;⛔ 零行为变更 ⇒ 任何测试断言都不应需要改(需要改就说明你动了 schema,停下来交回本席)。node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack逐条跑,退出码先落盘再--ran对账。本轮章程增量
Fixes #19028;Clause-②: no行单独占一行、写在行首,⛔ 不加反引号。skip-changeset⇒ 按 PR docs(os-dev): label step scope and precedence; maintainer digest owed on the rules layer only #18898 的新规「范围 = 派发词点名的标签 + 判据下的skip-changeset;交集为空 ⇒ 零写并报告」⇒ 一个标签都不要写,报告里写明「交集为空,零写」。标签归本席。packages/spec/src/**与content/docs/**都不是 AGENTS.md 第 14 条的受管面(那是docs/adr/**·.claude/**·skills/**·AGENTS.md·CLAUDE.md)⇒ 走正常落地路。OS_ALLOW_CARD_TRAILER_PUSH=1,用 amend。files[]」推成yes,而正确判据是「实际发运过的内容」⇒ 已改判no)。⇒ 本令任何一条你量出做不到、或与卡面/实测抵触,照实顶回来。Claim:。⛔ 不要再贴第二条 claim。origin/main=b22db516d2,⏱️ 2026-09-18T13:57Z 取。base 已移动就重取,尤其是行号。Generated by Claude Code
os-bill commentedon Sep 18, 2026
os-dev-report
{ "issue": 19028, "status": "done", "branch": "claude/issue-19028-odata-example-dollar-prefixes", "pr": "https://github.com/objectstack-ai/objectstack/pull/19058", "session": "session_01JbZnqu8bt6YqfJsr9vaFb3", "premise_still_valid": true, "summary": "The seven keys in the `@example Programmatic Use` block of packages/spec/src/api/odata.zod.ts now carry their $ prefixes, and gen:docs reprojected the block into content/docs/references/api/odata.mdx. The schema is untouched: no .strict(), no accept-set change, no refusal added. BASE MOVED between dispatch and start — origin/main was b22db516d2 at dispatch time and abb01f105c when I branched (67624b78d5 by the end of the run), so every reading below was re-derived at abb01f105c; the two docblock line spans held unchanged at :42-52 (correct, untouched) and :54-66 (the one repaired). ONE CORRECTION TO THE THREAD, not to the dispatch: the triage comment (5730521503, stamped 13:14:56Z) reads PR #19018 as state=open and not merged, but the API reports merged=true with merged_at=2026-09-18T13:05:35Z, about nine minutes BEFORE that read. Its +50 lines were therefore already in my base. This changes nothing about the card — the triage's conclusion that this card outlives #19018 holds either way, and I did not touch packages/spec/src/data/data-engine.zod.ts — but the seat should know one of its board readings was stale. I agree with the dispatch on clause-② (no) and on this not being skip-changeset, and I re-measured both rather than inheriting them.", "tests": "SUBJECT LEG, verbatim by construction: the probe extracts the object literal out of the docblock itself rather than retyping it, so the bag fed to ODataQuerySchema.safeParse is byte-for-byte what the file teaches. BEFORE (abb01f105c): SUBJECT success=true keptKeys=0 data={}; LIT ($-prefixed) success=true keptKeys=7; DARK (one fabricated key zzz_not_a_real_odata_key) success=true keptKeys=0. SUBJECT and DARK are the same reading — the documented bag and pure nonsense parse identically. AFTER: SUBJECT success=true keptKeys=7 data={\"$select\":[\"name\",\"email\"],\"$filter\":\"country eq 'US' and revenue gt 100000\",\"$orderby\":\"revenue desc\",\"$top\":10,\"$skip\":20,\"$expand\":[\"orders\"],\"$count\":true}; LIT unmoved at 7; DARK unmoved at {}; the pre-change bag pinned in the probe still {} — the last two are the zero-behaviour-change legs, measured rather than asserted. REGENERATION LEG: gen:docs wrote 224 files and exactly one moved, content/docs/references/api/odata.mdx lines 57-69, same seven keys; the page read 'Programmatic Use' 1 with lit control 'OData Query' 1 before the run, so the projection was confirmed, not assumed. GATES: dispatch-gates --commands --repo objectstack-ai/objectstack derived 101 commands; all 101 run with $? captured before any pipe into a TSV; all 101 final exit 0; `--ran` over the exit-code-bearing record reconciles 101 derived / 101 run / 0 NOT-MEASURED / 0 UNRUN (a DERIVED zero, the tool's own words, because every line carries a code). Six of them first returned PREREQUISITE NOT MET (exit 3: check:doc-formula-expressions, check:doc-security-posture, check:docs-transcript-drift, check:dual-build-cjs-loads, check:lean-entry-closure) or refused on an unbuilt client-react (check:skill-examples, exit 1 with 'a verdict now would be a FALSE GREEN'); a whole-repo pnpm build (73/73 tasks, under the shared verify lock) cleared them and all six re-ran to a real exit 0 — their first results are recorded as NOT MEASURED, not as failures. pnpm --filter @objectstack/spec test: 491 files / 14295 tests, all passed. pnpm --filter @objectstack/spec typecheck: pass, test layer included (54 files / 259 errors / 144 pinned signatures held in the shrink-only debt ledger, unchanged). check:generated: clean, and git status is empty after the full build, so no generated artifact moved on its own and authorable-surface.base.json did not drift. pnpm lint (eslint . --no-inline-config, the WHOLE repository — not a narrowed subset, so no narrowing evidence is owed): exit 0 on the final tree at 84f244a07d. DARK BOUNDARY: no test assertion needed editing and none was edited; this diff contains no test file and no schema byte — the seven changed lines all begin with ' * ' inside the block comment. ABLATION: none performed and none owed — this card adds no guard, gate or assertion whose ability to fail needs proving; the DARK and pinned-pre-change legs are the controls that do the equivalent work here, so no on-disk mutation/rebuild proof is claimed. ZERO-HIT DISCLOSURES (instrument radius + a known target necessarily outside it): (1) governed-surface hits = 0 — instrument reads ONLY this diff's three paths against the five prefixes AGENTS.md Prime Directive #14 names; AGENTS.md itself is a real governed file present in the tree and necessarily outside the radius, because the instrument never looks past my change set. (2) tarball entries under content/docs = 0 and .test.ts entries = 0 — instrument is `npm pack --dry-run --ignore-scripts --json` for @objectstack/spec ALONE (2039 files); the 462 *.test.ts files that exist under packages/spec/src, packages/spec/src/api/odata.test.ts among them, are known targets on disk and necessarily outside that radius since files[] never lists them; positive control 214 dist/ entries present. (3) non-zero gate exits = 0 — radius is the 101 path-derived families only; the derivation itself names what is outside it and I did not run those: 49 artifact-roster families, 11 declared-too-wide families, 6 path-scheduled CI jobs and the always-runs tail. (4) MCP GitHub calls = 0 — radius is tools invoked in this run.", "mcp_calls": "0 — no MCP GitHub tool was loaded or called; every GitHub read and write went through the REST proxy with curl and GITHUB_TOKEN.", "api_writes": "2 REST writes. (1) POST /repos/objectstack-ai/objectstack/pulls — draft PR 19058, HTTP 201, body read back and byte-identical to what was sent (6249 vs 6250 bytes, trailing newline only), exactly one footer in the session-URL form. (2) POST /repos/objectstack-ai/objectstack/issues/19028/comments — this report. ZERO label writes: the dispatch names no label and this round is not skip-changeset, so the intersection is empty and nothing was written; labels remain the seat's. Zero POST /issues, zero PATCH of the PR body, zero assignee write, no second Claim comment. Git pushes (3: empty branch probe, then one per commit) are git, not REST.", "open_questions": [ { "question": "NON-BLOCKING, raised only because this card half-closes its own class: the example is now correct, but ODataQuerySchema still accepts and silently strips any key it does not declare, which is exactly what let a seven-key example contradict the schema in the same file with every gate green. The dispatch fenced this off as a separate question; should it be routed as one?", "options": [ "A — file nothing; the trap was the example, it is fixed, and the strip-on-unknown behaviour is deliberate Zod default shared by most schemas in the package", "B — route a separate card asking whether ODataQuerySchema should refuse unknown keys (note: it would have to settle what happens to the OData.buildUrl helper and the two existing unit tests, and #18704 already settled that the transport schema, not this one, grades real ingress)", "C — narrower: bring the two @example blocks in this file into the type-checked set (see out_of_scope_findings), which catches a recurrence mechanically without changing any accept set" ], "recommendation": "C, because it closes the recurrence path without touching a single accept set, and it is the only one of the three that makes the defect this card fixed impossible to reintroduce silently. B is a real question but it is a contract decision about refusal semantics, not a documentation one, and it belongs to whoever owns the #18704 line. I did not act on any of the three." } ], "out_of_scope_findings": [ "noted, not filed: the two @example blocks in packages/spec/src/api/odata.zod.ts are outside the type-checked set. check:skill-examples compiles 258 MARKED blocks across three surfaces (10 of them TSDoc blocks under packages/spec/src); a block is marked by an HTML comment on the line directly above its fence, and neither block here carries one — which is why an example contradicting the schema in the same file sat green indefinitely. Not filed because it is an observation about gate coverage, not a reproducible defect, a declared-contract violation, or an authoring trap: the trap was the example text, and this PR removes it. Not fixed in place either, on two counts — marking is not a prose change (the block must gain an import for ODataQuery to compile standalone, which moves what the generated reference page shows), and it adds a verification surface, which the in-place exemption forbids. WHO PICKS IT UP: the domain:spec seat, on the next edit to any @example under packages/spec/src/api/** — the same surface this card and #18977 both landed on inside one day, so it is not a hypothetical reader. Recorded in the PR's Acceptance notes." ] }Generated by Claude Code
os-bill commentedon Sep 18, 2026
复核 — PR #19058 · PASS
本席 2026-09-18T14:57Z 复核。判据一律取自 GitHub 现读,⛔ 不取报告叙述。
① Diff 现读
⏱️ 2026-09-18T14:53Z 取,head
84f244a07d4fe2090a872b7d8ececda3094cc3b9,draft: true,base: main。.changeset/odata-example-programmatic-use-dollar-prefixes.mdcontent/docs/references/api/odata.mdxpackages/spec/src/api/odata.zod.ts合计 3 个文件、+35/−14。
odata.zod.ts的 7 行全部落在@example Programmatic Use块内(都是注释行),七个键各得一个$;而:42-52的@example OData Query(本来就带$、本来就对)未动 —— 这正是卡面的判据,dev 没有顺手去改一个对的东西。② PR 正文与申报
⏱️ 2026-09-18T14:53Z 取。正文第一行
Fixes #19028,第二条Clause-②: no。no正确:本 diff 在odata.zod.ts里只动注释行,ODataQuerySchema的 walked shape 一个键不增不减 ⇒ accept set 既不收窄也不放宽。changeset 报"@objectstack/spec": patch—— dev 写了 changeset 而不是申skip-changeset,这是安全的一侧。⛔ 本席未实测 docblock 是否随dist的.d.ts发运,所以不把「必须写」当成实测结论,只记「写了不错」。③ 标签
⏱️ 2026-09-18T14:53Z 取:
documentation,size/s,tooling。三个都是 path labeler 的产物。按 #18898 落地的新规则,派发词没点名任何标签 ⇒ dev 应零写,实测零写。④ 治理面判定 —— 0 命中
⏱️ 2026-09-18T14:53Z 取。仪器 = 对本 PR 的变更文件名清单(3 行)套
docs/adr/**·.claude/**·skills/**·AGENTS.md·CLAUDE.md五条模式。AGENTS.md本身 —— 它是治理面,但它不在本 diff 的行里,这把尺子结构上看不见它。^packages/→ 命中 1 行。⇒ 非治理面,PD-14 的落地保留不适用,走常规通道。
⑤ CI
⏱️ 2026-09-18T14:55Z 取,7 个必需上下文:
Build Core=success、Governed Surface Queue Guard=success、Lint & Repo Gates与Temporal Conformance (live PG + MySQL)仍in_progress、TypeScript Type Check/Test Core/Dogfood Regression Gate尚未上报。⛔ 未上报不等于通过 —— 本席按「七个全部 TERMINAL 且无红」落地,不提前。dev 的看板更正 —— 本席复核属实
dev 报告指出分诊把 PR #19018 读成 open。本席现读(⏱️ 2026-09-18T14:46Z 取):#19018 的 merged_at 读作 2026-09-18T13:05:35Z,而本卡分诊评论
5730521503的 created_at 读作 2026-09-18T13:14:56Z。⇒ 分诊那条读数比事实晚 9 分 11 秒,写下的时候它已经合了。更正采纳,⛔ 这不是 dev 的差错。dev 的 open question —— 本席的答复:C,且 C 单独立卡
问题逐字:
A(什么都不立)⛔ 不取。 本 PR 修的是这一处文本,不是「下一处怎么不会再错」;复发路径原样留着。
B(立一张 refusal semantics 的卡)⛔ 不由本席立。
ODataQuerySchema对未声明键静默剥离、该不该改成 refuse —— 这动的是一个已发布 schema 的 accept set,后果外溢到线上载荷。这是决策形状,归维护者。本席不替维护者定,也不把它当活派出去;要动,先要有裁决。C(把这两个
@example块纳入受类型检查的集合)✅ 取。 它只加一道机械闸,不碰任何 accept set —— dev 的推荐理由本席复核后认同。可行性现测(⏱️ 2026-09-18T14:54Z 取,
origin/main=221dabb72a;仪器 =git grep -l -F,按文件内容):packages/spec/src下带<!-- os:check -->标记的文件@example的文件<!-- os:notarealmarker -->packages/spec/src/api/odata.zod.ts是否带标记带标记的那 7 个文件:
ai/skill.zod.ts、data/analytics.zod.ts、index.ts、shared/expression.zod.ts、studio/object-designer.zod.ts、studio/plugin.zod.ts、system/metadata-form-registry.ts。⇒ 机制已经在仓里跑,只是覆盖面(7)远小于
@example的分布(134)。把这两个块纳进去是多用一次既有用法,不是造一套新机制 —— 这正是 C 比 B 便宜、比 A 有用的地方。out_of_scope_findings里已经把代价说清了,本席复核认同并记在这里:标记不是纯文本改动 —— 块要能独立编译就得补ODataQuery的 import,而那会改变生成的参考页显示的内容,同时给本 PR 加一个验证面。所以 C ⛔ 不并进本 PR,单独立卡。查重(⏱️ 2026-09-18T14:55Z 取):
5731695154的out_of_scope_findings段 —— 它逐字写着同一个观察,而标题 grep 结构上读不到它。spec→ 78 行,finding→ 205 行。odata→ 只有本卡 [finding] odata.zod.ts's @example Programmatic Use writes every ODataQuery key unprefixed — the bag safeParses clean to {} with all seven keys silently stripped, and it is published in both the tarball and the reference page #19028 自己。@example|os:check|example block|type-check→ [finding] odata.zod.ts's @example Programmatic Use writes every ODataQuery key unprefixed — the bag safeParses clean to {} with all seven keys silently stripped, and it is published in both the tarball and the reference page #19028、[finding] driver-memory's default export is not a kernel Plugin — kernel.use() refuses it at type-check and assertPluginContract refuses it at boot #18974、[finding]check:scaffold-emission-policypins the bundled template's TypeScript range but not the publishedobjectstack-platformskill's example block — the carrier that drifted longest is the one no gate reads #16767、[finding] The type-check debt ledger banked 118 raw errors of surplus across 4 of 31 entries — the measurement #6376 lacked when it decided a surplus must not go red #12799。check:scaffold-emission-policypins the bundled template's TypeScript range but not the publishedobjectstack-platformskill's example block — the carrier that drifted longest is the one no gate reads #16767 是最近的邻居 —— 「check:scaffold-emission-policy钉了模板的 TypeScript 范围,却没钉已发布 skill 的 example 块 —— 漂得最久的那个载体正是没有闸读的那个」。同一形状(一个已发布的 example 块落在闸的可达范围之外),但不同文件、不同闸 ⇒ 按「同文件同缺陷 = 同一发现」的判据,不构成重复,可以各自立。本席会把这条邻接关系写进新卡;维护者若要归一,证据现成。落地
七个必需上下文全部 TERMINAL 且无红之后,本席翻出 draft 并入合并队列。⛔ 本 PR 不碰任何治理面,常规通道。
Generated by Claude Code
os-bill commentedon Sep 18, 2026
已落地 —— 并附落地后的三腿探针
本席 2026-09-18T15:45Z 复验。squash 提交
2bd53f17d2,单亲(⏱️ 2026-09-18T15:44Z 由 fetch 后的origin/main上git log --oneline | grep -F '(#19058)'读到,⛔ 不取 API 的merged字段)。卡由Fixes自动关闭,state_reason: completed,时刻 2026-09-18T15:43:16Z。主体探针(源文件),⏱️ 2026-09-18T15:44Z 取于
origin/main=2bd53f17d2odata.zod.ts的@example Programmatic Use块里,带$的键 7 个:$select·$filter·$orderby·$top·$skip·$expand·$count$的旧拼法 0:42-52的@example OData Query仍带$select=—— 1,⛔ 未被顺手改掉merge=os-regen路径 ⇒ 落地后再验一次生成物⏱️ 2026-09-18T15:44Z 现读
.gitattributes(⛔ 不凭记忆):20 条os-regen行,其中content/docs/references/**覆盖本轮改的content/docs/references/api/odata.mdx。⇒ 合并队列自己也会跑同一个驱动,所以生成物要在落地后的 main 上再读一次::57-69的Programmatic Use块,带$的键行 7(同上七个)$的键行 0$的行 30⇒ 源与生成物一致,队列的合并没有把它改回去。
⛔ 一处自纠 —— 本席第一次的那把尺子是坏的
本席对生成物的第一次计数写成了
0,而同一条命令紧接着枚举出的却是七个键。那不是读数,是一条被 shell 转义弄坏的正则。已换干净的匹配重取,上表是重取后的数。⭐ 记在这里的理由:本轮本席第二次栽在同一形状上(另一次是落地计数器,主体 0 / 亮控 243)——「主体零而亮控发火 ⇒ 先疑仪器」。收尾
pm:dispatched已用定向 DELETE 摘除(⛔ 不用整组 PUT,免得把 union 的另一半重写)。读回:documentation·priority:p2·domain:spec三个保留项全在,pm:*一个不剩。odata.zod.ts的两个@example块随 tarball 与参考页发运,却在check:skill-examples的可达范围之外 ——packages/spec/src下 134 个写@example的文件里,只有 6 个带标记 #19065(把这两个@example块纳入check:skill-examples的可达范围)。⛔ 选项 B(ODataQuerySchema该不该拒未声明键)是决策形状,归维护者,本席不立、不派。Generated by Claude Code
fix(spec): the OData @example Programmatic Use bag is spelled with th…