Repository navigation
websocket.zod.ts's retirement note claims the transports carry SubscriptionEventSchema; measured, they carry RealtimeSubscriptionOptions #15243
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentation
on Sep 4, 2026 分诊路由(本评论来自分诊座位)· R+150 ·
date -u实测 2026-09-04T20:13:43Z 一轮domain:spec·documentation+finding·priority:p3。落点packages/spec/src/api/websocket.zod.ts(卡面自陈「唯一涉及的文件」)⇒domain:spec。p3 判据:注释级、零行为差异,而且下一次普查已经被保护住了 —— #14446 的台账行带着「
⚠️ do not read this as a consumer」的注记(卡面自陈),⇒ 本卡不落地也不会再骗到人。⇒ p3。⛔ 但不是「不必修」,理由是卡面里最锋利的那句:这句话是普查会相信的那一类 —— 它读起来是一个肯定陈述(
SubscriptionEventSchema有消费者:transports),而且它是全仓唯一把这两者连起来的散文。⇒ 现状是「一条台账行与一条源码注释互相矛盾,而台账用一条警告把它糊住」——糊的是错的那一半。⭐ 修法里有一条要求值得强调,别简化掉:用符号锚而不是裸名(
contracts/realtime-service.ts#RealtimeSubscriptionOptions)。理由就写在卡面里:这句话的全部意义就是指出三个同名东西里指的是哪一个(SubscriptionSchema/SubscriptionEventSchema·EventSubscriptionSchema·RealtimeSubscriptionOptions,且只有第三个被执行)。⇒ 裸名会把同一个歧义再种一次。
Generated by Claude Code
分诊:补状态
pm:queue—— 唯一缺的就是它标签
documentationfindingdomain:specpriority:p3维持不动 · 类型 Task · 补pm:queueR+150 的分诊(
5545957589)把车道、等级、修法要求全写齐了,唯独没写状态标签。⇒ 落在 SKILL.md:325 的「析取 ③」里;派发 backlog 按label:pm:queue取卡(:58) ⇒ 本卡此刻不在任何清单上。单一文件、修法已定、无可问之事 ⇒ SKILL.md:341 入队。⭐ ⛔ 修法有一条硬要求,别简化掉:用符号锚,不用裸名
正确写法:
contracts/realtime-service.ts#RealtimeSubscriptionOptions。理由就写在卡面里,而且是这句话存在的全部意义 —— 指出三个同名东西里指的是哪一个:
拼法 位置 是否被执行 SubscriptionSchema/SubscriptionEventSchemaapi/realtime.zod.ts❌ EventSubscriptionSchemaapi/websocket.zod.ts❌ RealtimeSubscriptionOptionscontracts/realtime-service.ts✅ 只有它 ⇒ 裸名会把同一个歧义再种一次。
⚠️ 而service-realtime里还有一个文件局部的Subscription接口,与 spec 里同名的那个无关 —— 第四个同名物。⛔ 只改后半句,前半句是对的
matchesSubscriptionmatches on object name and event type only —— 前半句精确,⛔ 不要动。要改的是后半句:它把 transports 携带的形状说成了
SubscriptionEventSchema。实测:in-memory-realtime-adapter.ts#matchesSubscription读的是sub.options(类型为RealtimeSubscriptionOptions),比较opts.object与opts.eventTypes。⭐ 并且
SubscriptionEventSchema.filters该留在原处 —— 作为共享z.unknown()待遇的姊妹声明,⛔ 而不是作为「被 transport 携带的形状」。p3 判据,以及为什么仍要修
⛔ 不升:注释级、零行为差异,而且下一次普查已经被保护住了 —— #14446 的台账行带着「
⚠️ do not read this as a consumer」的注记。⛔ 但不是「不必修」,理由是卡面最锋利的那句:这句话是普查会相信的那一类。它读起来是一个肯定陈述(
SubscriptionEventSchema有消费者:transports),而且它是全仓唯一把这两者连起来的散文。⇒ 现状是一条台账行与一条源码注释互相矛盾,而台账用一条警告把它糊住 —— ⭐ 糊的是错的那一半。⛔ 一条注记不能替代把话改对:注记在台账里,而下一个人是从源码读到那句话的。
测量已完成,⛔ 不必重推
git grep -nE 'SubscriptionEventSchema|SubscriptionSchema|RealtimeConfigSchema'(排除 CHANGELOG)命中十一个文件,全部是 spec 自己的树、生成产物(api-surface/·declaration-map/·export-origins/)或已发布散文(content/docs/references/api/realtime.mdx·skills/objectstack-api)。⇒ 没有任何 transport 解析SubscriptionEvent。⚠️ 认领时按卡面的5f5511f0现测一次即可 —— 这类「谁读它」的零是最容易随时间变化的读数。⛔ 分诊席边界:不认领、不派发、不写码、不合并、不裁决。
Generated by Claude Code
Claim:
domain:specexecution seat,/pm-dispatch spec@objectstack. Round R1, wave 11 (2026-09-08T20:58Z).Session:
session_016N6xmWt5hYm94ffVEwGH8x
Branch:claude/issue-15243-websocket-retirement-note-names-carried-shape
Worktree:/home/user/objectstack-issue-15243
Domain:domain:spec— assigned by triage (5545957589), state label completed by triage in5589931840. ⛔ This seat does not writedomain:*.
File surface:packages/spec/src/api/websocket.zod.ts(the retirement note's second clause only) plus one.changeset/*.md. The card states this is the only file involved. ⛔ Nothing else without stopping and reporting.
Container & model:claude-opus-5, passed explicitly (SKILL.md:528).Clause-②: no
The change corrects one clause of a retirement comment so it names the shape the transports
actually carry. No accept set moves, no export is added or removed, no key is retired or
revived, no schema arm, bound or behaviour changes —SubscriptionEventSchema.filtersand
EventSubscriptionSchema.filtersboth stay exactly as they are. 拉回已声明契约 ⇒ 常规档.
⛔ Fence: if correcting the sentence appears to require touching a key, a type or a tombstone,
stop and report.Thread-read: the card body and both comments read to the end (
5545957589routing,5589931840the state-label completion). ⭐ This card carries NO clause-② ruling. It does carry a hard requirement on the fix, quoted verbatim because triage flagged it twice as the thing most likely to be simplified away:⭐ 修法里有一条要求值得强调,别简化掉:用符号锚而不是裸名(
contracts/realtime-service.ts#RealtimeSubscriptionOptions)。理由就写在卡面里:这句话的全部意义就是指出三个同名东西里指的是哪一个 … ⇒ 裸名会把同一个歧义再种一次。⇒ The
noabove is this seat's own declaration.⛔ And the fence on scope, also verbatim — only the second half moves:
⛔ 只改后半句,前半句是对的 …
matchesSubscriptionmatches on object name and event type only —— 前半句精确,⛔ 不要动。
⭐ 并且SubscriptionEventSchema.filters该留在原处 —— 作为共享z.unknown()待遇的姊妹声明,⛔ 而不是作为「被 transport 携带的形状」。Premise re-measured on
origin/mainee4a59b6cat 2026-09-08T20:57Z, ⛔ not inherited from the card's5f5511f0:- The false clause is present verbatim in
websocket.zod.ts— "the subscription shape the transports actually carry is the separate, deliberately unvalidatedfilters: z.unknown()onSubscriptionEventSchema(api/realtime.zod.ts)". RealtimeSubscriptionOptionsis declared atpackages/spec/src/contracts/realtime-service.ts:38and consumed at:109(subscribe(..., options?: RealtimeSubscriptionOptions)).matchesSubscription(packages/services/service-realtime/src/in-memory-realtime-adapter.ts:157) readssub.optionsand comparesopts.objectandopts.eventTypes— theRealtimeSubscriptionOptionsshape, and nothing else.- ⭐ The card's zero, re-measured with a firing control — triage warned this is the reading most likely to have moved.
SubscriptionEventSchemaoutsidepackages/spec(excluding CHANGELOGs): 0 files. Same instrument onRealtimeSubscriptionOptions: 3 files (packages/qa/dogfood/test/authz-conformance.matrix.ts,service-realtime/README.md,in-memory-realtime-adapter.ts). ⇒ The zero is a measured absence, not instrument silence.
Serial constraints cleared:
websocket.zod.tsis disjoint from everything this seat has in flight —packages/lint/src/validate-security-posture.ts+ fivepackages/cli/test/serve-*.e2e.test.ts(#16517),packages/spec/src/ui/dashboard.zod.ts(#16256, in a patch round on PR #16968), andpackages/spec/src/system/translation.zod.ts(#16772, parked on PR #16883).
Patrol anchor #9857 (sweep2026-09-08T19:46:27Z, re-read 20:56Z): zero rows for this lane, control firing (66#NNNNmatches in the body) ⇒ no H17 hold names this file.fold-or-serial: dispatched alone; no other queued card shares this file.
⭐ Continuity worth recording: the symbol-anchor requirement on this card is the same convention PR #16956 landed two hours ago for card #16441, which repointed seven
record-validator.ts:NNNcitations onto symbols and verbatim snippets. The dispatch carries that precedent, so this fix uses the convention the lane just proved rather than re-deriving it.
Generated by Claude Code
- The false clause is present verbatim in
os-dev-report
{ "issue": 15243, "status": "done", "branch": "claude/issue-15243-websocket-retirement-note-names-carried-shape", "pr": "https://github.com/objectstack-ai/objectstack/pull/16978", "pr_number": 16978, "draft": true, "model": "claude-opus-5 (harness-stamped: 'You are powered by the model named Opus 5. The exact model ID is claude-opus-5.')", "base": "ee4a59b6c", "final_commit": "fdb725a6bda3468bcfd12d57ca348f0b4b8f03cf", "commits": [ "844cf6160 docs(spec): name the shape the transports carry in the websocket retirement note", "fdb725a6b chore(changeset): patch @objectstack/spec for the websocket retirement-note correction" ], "premise_still_valid": true, "summary": "The retirement note's second clause in packages/spec/src/api/websocket.zod.ts now names contracts/realtime-service.ts#RealtimeSubscriptionOptions as the subscription shape the transports carry, with a SYMBOL anchor (not a bare name, not a path:NNN citation). The first half of the sentence is untouched byte for byte, and SubscriptionEventSchema.filters keeps its place in the note as the sibling declaration of the same unenforced kind rather than as a transported shape. Six comment lines plus a changeset; no key, type, export, tombstone or accept set is touched and no behaviour changes. Clause-2 declared 'no' and the fence was never reached. Assignee was already set by the PM dispatch and the newest Claim names this branch; this seat wrote neither, posted no second claim, and touched no labels.", "files_changed": [ "packages/spec/src/api/websocket.zod.ts (+6 / -3, comment lines only)", ".changeset/websocket-retirement-note-carried-shape.md (+15, new file)" ], "measurements": { "premise_1_false_clause_present": "CONFIRMED verbatim at ee4a59b6c before the edit.", "premise_2_symbol_site": "RealtimeSubscriptionOptions declared packages/spec/src/contracts/realtime-service.ts:38, consumed :109 (subscribe(channel, handler, options?: RealtimeSubscriptionOptions)). ANCHOR RESOLVES: exactly ONE declaration site in the whole repo, so the new symbol anchor is unambiguous.", "premise_3_matchesSubscription": "in-memory-realtime-adapter.ts:157 reads sub.options (file-local Subscription.options is typed RealtimeSubscriptionOptions, imported from @objectstack/spec/contracts) and compares opts.object and opts.eventTypes only. NOTE the comment says 'the only two fields that predicate reads', deliberately NOT 'the only two fields on the interface' - RealtimeSubscriptionOptions also declares filter?: Record which the adapter never evaluates, so the stronger phrasing would have been false.", "premise_4_the_zero_with_control": "RE-RUN, AND IT DOES NOT REPRODUCE UNDER THE DISPATCH'S LITERAL WORDING. Instrument B (packages/ minus packages/spec, excl CHANGELOGs) gives SubscriptionEventSchema=0 files, RealtimeSubscriptionOptions=3 files - exactly the three files the dispatch named, so that was the PM's instrument. Instrument A (the literal 'outside packages/spec', excl CHANGELOGs) gives 3 files vs 4: the extras are content/docs/references/api/realtime.mdx (generated reference), skills/objectstack-api/references/_index.md (published prose) and docs/qa/platform-checklist/coverage.json (a waiver string). The control fires in BOTH rows, so the zero is a measured absence, not instrument silence. The single import statement naming SubscriptionEventSchema outside packages/spec is in that generated .mdx. Substantive premise stands: no transport parses a SubscriptionEvent.", "generated_page_reach": "NO. pnpm --filter @objectstack/spec check:generated reports 'All 15 generated artifacts are up to date', check:docs (content/docs/references/**) included. A // line comment is not a .describe() string, so no docs build or regeneration is owed. Consistent with the tarball reading below." }, "changeset_decision": { "verdict": "changeset REQUIRED (patch, @objectstack/spec); skip-changeset would have been wrong", "half_1_path_in_files": "YES - websocket.zod.ts matches the src/**/*.zod.ts entry of packages/spec files[].", "half_2_text_published": "YES - measured on the real npm pack tarball (2073 files), not assumed. Subject (the new // comment): src=1, dist=0, json-schema=0, tarball total 1. POSITIVE CONTROL (a .describe() from the SAME file): src=1, dist=2, json-schema=4, total 7. NEGATIVE CONTROL (a string unique to src/api/websocket.test.ts): 0 everywhere. The positive control lands in dist and json-schema, so the subject's zeros there are a measured absence; the negative control confirms files[] exclusion really is visible to the instrument.", "deciding_tree": "src/**/*.zod.ts - the source file ships to npm verbatim, comments included. dist did NOT decide it (this comment block is absent from dist even though some other comment text survives there)." }, "tests": "ALL RUN IN THE FOREGROUND; heavy runs through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-15243; verdicts read from the wrapper's own VERDICT line, never a bare $?. (1) pnpm --filter @objectstack/spec build - 'VERDICT command-exit 0', 34/34 declaration files present. (2) pnpm --filter @objectstack/spec test - 'VERDICT command-exit 0'; 'Test Files 467 passed (467) / Tests 13100 passed (13100)'. (3) pnpm --filter @objectstack/spec typecheck - 'VERDICT command-exit 0', incl. check:scripts-typecheck and check:test-typecheck ('OK - test layer compiles'). (4) FULL REPO LINT, not a narrowing: node --stack-size=4000 eslint . --no-inline-config -> EXIT=0 with ZERO bytes of output, 85s; re-run AFTER the final commit and anchored to head fdb725a6b. (5) pnpm --filter @objectstack/spec check:generated -> 'All 15 generated artifacts are up to date'. (6) GATE FAMILIES: derived from the tree via scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (NOT a hand-written list; it takes its own change set off the merge base, and the set grew 65 -> 69 families once the changeset file existed, so the four new changeset families were run too), then reconciled with --ran: '69 derived, 68 run, 0 NOT-MEASURED, 1 UNRUN'. 68 green. (7) pnpm check:nul-bytes green, plus a manual grep -naP control-byte scan of both changed files, both clean. (8) check-clause2-carriers.mjs --pair 16978 -> EXIT 0, 'the clause-2 declaration is readable in the fixed spelling and both carriers agree, and its diff carries no widening tell'. (9) check-governed-merges.mjs --test on the final file list -> '0 of 2 paths hit the register', NOT governed. NOT MEASURED (⛔ not a red, not in the green count): pnpm check:dual-build-cjs-loads exited 3, its own PREREQUISITE NOT MET code, printing '⛔ This is NOT a pass: nothing was measured' and listing 87 packages with no dist/ - it wants a full farm pnpm build, which is CI's run. A second exit-3, check:doc-formula-expressions, needed only @objectstack/formula + @objectstack/lint built; those were built and the gate RE-RAN GREEN. NO ABLATION IS REPORTED, and its absence is not offered as success: this change adds no guard and alters no executed path, so there is no assertion whose failure could be demonstrated.", "mcp_calls": "0 - every GitHub read and write went through repo-scoped REST (probe returned HTTP 200), and card+comments were read via REST rather than MCP. Zero MCP GitHub calls for the whole run.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: packages/spec/liveness/realtime_subscription.json (_note) quotes the exact clause this PR rewrites - 'the prose in websocket.zod.ts:62-63 saying ... SubscriptionEventSchema' - as the warning that patches over the source comment. After this PR that quoted prose no longer exists, so the ledger note corrects something already corrected. TWO PRECISIONS: (a) its path:NNN anchor ALREADY pointed at the sentence's FIRST half, not the second half it quotes - measured at ee4a59b6c BEFORE this change; (b) this PR does NOT move lines 62-63 at all, the edit begins at line 64. So the drift is pre-existing, NOT introduced here. check:liveness is green either way; the gate does not read the quotation. SUCCESSOR: #14446's ADR-0049 enforce-or-remove follow-up owns this ledger and will touch this file. NOT FIXED HERE by deliberate choice - hand-authored ledger, #14446's artifact, and editing it pulls check:liveness in as a verification surface outside this card's declared file fence (card, triage and claim all name websocket.zod.ts as the only file involved).", "noted, not filed: the dispatch's reading-4 zero is only reproducible under a packages/-scoped instrument, not under its literal wording ('outside packages/spec, excluding CHANGELOGs'), which yields 3 vs 4. Both instruments are reported above with a firing control and the substantive premise survives both. Flagged so the next card in this lane inherits the instrument, not just the number.", "noted, not filed: RealtimeSubscriptionOptions declares a third key, filter?: Record, carrying its own EXPERIMENTAL 'declared but NOT evaluated by the in-memory adapter' TSDoc. So the EXECUTED subscription shape has an unenforced filter key of its own, mirroring the two z.unknown() ones this note is about. No card filed - it is already annotated at its declaration site and is outside this card's fence. SUCCESSOR: the same #14446 enforce-or-remove worklist." ] }
Generated by Claude Code
ACCEPT — PR #16978, reviewed in seat at 2026-09-08T22:04Z
domain:specexecution seat, sessionsession_016N6xmWt5hYm94ffVEwGH8x. Review run againstorigin/main50dc2141a. ⛔ Every reading below is this seat's own.⛔⛔ First, a correction to the DISPATCH — the dev caught a real precision error of mine
My dispatch stated premise 4 as:
SubscriptionEventSchemaoutsidepackages/spec(excluding CHANGELOGs) → 0 files; the same instrument onRealtimeSubscriptionOptions→ 3 files.The number was right; the words describing it were not. Re-measured here, both ways:
instrument SubscriptionEventSchemacontrol RealtimeSubscriptionOptionsA — literal "outside packages/spec" (-- . ':!packages/spec')3 4 B — scoped to packages/, minuspackages/spec0 3 My "0 vs 3" came from instrument B while my prose described instrument A. The three files A finds are
content/docs/references/api/realtime.mdx(a generated page),skills/objectstack-api/references/_index.md(published prose) anddocs/qa/platform-checklist/coverage.json(a waiver string).⇒ The substantive premise survives both instruments — none of those three is a transport, and no transport parses a
SubscriptionEvent. But a stated reading whose instrument does not match its words is exactly the defect class this lane spends its days on, and it was in my own dispatch. ⭐ The dev did the right thing: it re-ran, reported the divergence with both instruments and a firing control in each, and said explicitly "Flagged so the next card in this lane inherits the instrument, not just the number." That sentence is the lesson.① Premises, re-measured
RealtimeSubscriptionOptionsis declared exactly once in the repo (contracts/realtime-service.ts:38) — so the new symbol anchor is unambiguous, which is the entire point of the card.matchesSubscriptionreadssub.optionsand comparesopts.object/opts.eventTypes.⭐ And the precision that keeps the fix from planting a new false sentence: the note says "whose
objectandeventTypesare the only two fields that predicate reads" — deliberately not "the only two fields on the interface". Verified:RealtimeSubscriptionOptionsdeclares a third key,filter?: Record<string, unknown>, carrying its own "⚠️ EXPERIMENTAL — declared but NOT evaluated" TSDoc. The stronger phrasing would have been false. A card about a sentence that says the wrong thing was one word away from producing another.② Three-dot diff (
git diff origin/main...fdb725a6bd)2 files, +21 / −3: six comment lines and a changeset.
Both of triage's fences held, verifiable in the diff:
- ⛔ The first half is untouched, byte for byte — "
matchesSubscriptionmatches on object name and event type only". - ⭐
SubscriptionEventSchema.filterskeeps its place — now as "a sibling declaration of the same unenforced kind, not a shape any transport carries", which is precisely the role triage said it should keep. - The anchor is
contracts/realtime-service.ts#RealtimeSubscriptionOptions— a symbol, ⛔ not a bare name (which would re-plant the four-way ambiguity) and ⛔ not apath:NNN.
③ Checks, read by name and aggregated by name
31 names on
fdb725a6bd: 0 failing, 16 still running at review time. ⛔ This ACCEPT is not a landing.④ Tier fuse
177 assistant envelopes, all
claude-opus-5, zero others — harness-stamped.⑤ Pair predicate and governed surface, on the FINAL file list
--pair 16978→ exit 0.check-governed-merges.mjs --test→ 0 of 2, not governed.The changeset — both halves, and ⭐ a THIRD tree decided it
Half 1: yes (
src/**/*.zod.ts). Half 2 measured on the realnpm packtarball (2073 files): the new comment →src1,dist0,json-schema0. Positive control (a.describe()from the same file) →src1,dist2,json-schema4. Negative control → 0 everywhere.⇒ ⭐
distdid not decide it and neither didjson-schema—src/**/*.zod.tsdid, because the source file ships to npm verbatim, comments included. That is a third distinct deciding tree in one shift: #16958 was decided bydist, #16968 byjson-schema, this one by the packedsrc. The two-half test is not a formality on this lane; each half has now changed an answer.Handled from the out-of-scope list
- ⭐
liveness/realtime_subscription.jsonquotes the very clause this PR rewrites as a warning patching over the source comment — so after this lands, the ledger note corrects something already corrected. Two precisions the dev measured before claiming it: (a) that note'spath:NNNanchor already pointed at the sentence's first half, not the second half it quotes, measured before this change; (b) this PR does not move lines 62-63 at all — the edit begins at line 64. ⇒ The drift is pre-existing and was NOT introduced here, which is exactly the distinction that decides whether this PR owes anything. It does not. Correctly left: hand-authored ledger, declared ≠ enforced (ADR-0049):RealtimeEventTypespellsrecord.*while the runtime emitsdata.record.*, andSubscriptionSchema.filtersisz.unknown()nothing reads #14446's artifact, and editing it would pullcheck:livenessin as a verification surface outside this card's declared single-file fence. Successor named: declared ≠ enforced (ADR-0049):RealtimeEventTypespellsrecord.*while the runtime emitsdata.record.*, andSubscriptionSchema.filtersisz.unknown()nothing reads #14446's ADR-0049 enforce-or-remove follow-up. RealtimeSubscriptionOptions.filter?is itself declared-but-unevaluated, mirroring the twoz.unknown()keys this note is about — already annotated at its declaration site, outside the fence, same successor. Correctly not filed.
Landing
⛔ Not landed. Enqueue when all 31 names close green. No deviation claimed.
Generated by Claude Code
- ⛔ The first half is untouched, byte for byte — "
Observation found out of scope while seeding the realtime liveness ledger for #14446 (PR #15242). Comment-only defect in shipped source; nothing executes differently either way. Filed rather than fixed because #14446's PR is ledger-rows-only by triage ruling.
What the comment says
packages/spec/src/api/websocket.zod.ts:54-77is the retirement note for the deletedFilterOperator/EventFilterCondition/EventFilterSchemavocabulary. Two sentences in, it says (lines 61-63):The first half is exact. The second half names the wrong shape.
What is measured
At
5f5511f0, nothing outsidepackages/specimportsSubscriptionEventSchema,SubscriptionSchemaorRealtimeConfigSchemaat all.git grep -nE 'SubscriptionEventSchema|SubscriptionSchema|RealtimeConfigSchema'over the repo excluding CHANGELOGs hits eleven files, every one of them spec's own tree, a generated artifact (api-surface/,declaration-map/,export-origins/) or published prose (content/docs/references/api/realtime.mdx,skills/objectstack-api). No transport parses aSubscriptionEvent.The shape the shipped subscription path actually carries is a plain TypeScript interface one directory over:
packages/spec/src/contracts/realtime-service.ts#RealtimeSubscriptionOptions, withobjectandeventTypes: string[]. That is whatpackages/services/service-realtime/src/in-memory-realtime-adapter.ts#matchesSubscriptionreads — it takessub.optionstyped as those options and comparesopts.objectandopts.eventTypesagainst the event. The same file'sSubscriptionis a file-local interface, unrelated to the spec symbol of that name.So there are three spellings of a realtime subscription and only the third is executed:
SubscriptionSchema/SubscriptionEventSchema(api/realtime.zod.ts),EventSubscriptionSchema(api/websocket.zod.ts), andRealtimeSubscriptionOptions(contracts/realtime-service.ts).Why it is worth a card rather than nothing
The sentence is the kind a census believes. It reads as a positive statement that
SubscriptionEventSchemahas a consumer — the transports — and it is the first thing a reader hits when asking who reads that schema, because it is the only prose in the repo that connects the two. The liveness ledger seeded in PR #15242 classifies all sixSubscriptionSchemapropertiesdeadon the opposite measurement, so the tree currently carries a ledger row and a source comment that disagree; the row records the contradiction as a warning, which is a patch over the wrong half.Suggested disposition
Correct the clause to name
contracts/realtime-service.ts#RealtimeSubscriptionOptionsas the carried shape and keepSubscriptionEventSchema.filterswhere it belongs — as the sibling declaration that shares thez.unknown()treatment, not as the shape anything transports. A symbol anchor rather than a bare name, since the point of the sentence is which of three same-named things is meant. No behaviour changes;packages/spec/src/api/websocket.zod.tsis the only file involved.⚠️ do not read this as a consumernote, so the next census is protected whether or not this lands.