Skip to content

DriverCapabilities.streaming 在 findStream 退休后指向不存在的能力,且从来没有读者(ADR-0049,#4484 收尾发现) #4634

Closed

Description

@os-zhuang

做 #4484(退休 IDataDriver.findStream)时闭合调用图,发现能力标志 DriverCapabilities.streaming 是同一处死声明的另一半,单独留下会比原来更糟。未在 #4484 里一并处理,是因为它的爆炸半径不同(每个 driver 的能力字面量,含三方 driver),值得单独定夺。

位置

packages/spec/src/data/driver.zod.ts:273-276:

  /**
   * Whether the driver supports streaming large result sets.
   */
  streaming: z.boolean().default(false).describe('Supports result streaming (cursors/iterators)'),

证据

  1. 零读者。 全仓(framework + cloud,排除 node_modules / dist)没有任何一处读 supports.streaming / capabilities.streaming。命中全部是写:
packages/plugins/driver-memory/src/memory-driver.ts:202     streaming: true,   // 注释原文曾是 "Implemented via findStream()"
packages/plugins/driver-mongodb/src/mongodb-driver.ts:115   streaming: true,
packages/plugins/driver-sql/src/sql-driver.ts:552           streaming: false,
packages/spec/src/api/registry.example.ts:219               streaming: false,
packages/core/API_REGISTRY.md:306                           streaming: false,

没有查询规划、没有能力协商、没有 REST discovery 字段读它。它是纯粹写进去就再没人看的一位。

  1. 写进去的值本身就是错的,而且没人发现——这正是零读者的直接后果:SqlDriver 声明 streaming: false 却实现了 findStream;InMemoryDriver 声明 streaming: true,实现却是 await this.find() 之后再逐条 yield(把整表读进内存,恰好是 streaming 的反面)。三个 driver 里只有 mongo 的 true 是名副其实的,而它现在也随 IDataDriver.findStream 没有任何调用方,两个 driver 的实现还正好做了它承诺要避免的事(ADR-0049 enforce-or-remove) #4484 一起删掉了。

  2. IDataDriver.findStream 没有任何调用方,两个 driver 的实现还正好做了它承诺要避免的事(ADR-0049 enforce-or-remove) #4484 之后它指向空。 findStream 是这个标志唯一可能描述的东西(memory driver 的注释直说了 // Implemented via findStream())。契约方法删掉后,streaming: true 描述的是一个平台不再声明的能力——下一个读到它的人(或 agent)会据此推断存在一条流式读路径,这正是 IDataDriver.findStream 没有任何调用方,两个 driver 的实现还正好做了它承诺要避免的事(ADR-0049 enforce-or-remove) #4484 要消除的假可供性,只是往上挪了一层。

处置倾向

remove,理由与 #4484 同源。真要做流式读,路径是"先有调用方,再有契约方法,再有描述它的能力位",而不是留一个描述空洞的布尔。

需要先定夺的是范围:DriverCapabilitiesSchema 有近 30 个位,streaming 未必是唯一一个零读者的(queryCache、preparedStatements、vectorSearch、geospatialQuery 值得一并查)。两条路:

  1. 只删 streaming——干净、与 IDataDriver.findStream 没有任何调用方,两个 driver 的实现还正好做了它承诺要避免的事(ADR-0049 enforce-or-remove) #4484 同源、当天可完成;代价是同一份审计要再做一遍。
  2. 对整个 DriverCapabilities 做一次活性审计,按 ADR-0049 一次性处置所有零读者的位;代价是范围大得多,且要处理三方 driver 的能力字面量(删一个 key 会让写它的对象字面量报 excess-property 错误)。

我倾向 先做 2 的审计、再按结果一次性 remove:逐位退休会让每个 driver 作者被迫改三四次能力字面量,而一次审计只改一次。

相关

未指派 —— 按 AGENTS.md 的约定,这是一条记录下来的 finding,谁开工谁认领。

Activity

  1. self-assigned this
    on Aug 3, 2026
  2. os-zhuang commented on Aug 3, 2026

    @os-zhuang
    ContributorAuthor

    🔒 认领:PM 会话 session_0176qgxgCXTJCUv4YFLtusP9,分支 claude/issue-4634-driver-capabilities-liveness。

    ADR-0049 队列接派(前序 #4579 → PR #4764 已合并)。范围按本单自述倾向执行:先对 DriverCapabilitiesSchema 全部能力位做一次活性审计,再按结果一次性 remove 零读者位(逐位退役会让每个 driver 作者改三四次能力字面量);审计如发现活位以外的大范围问题,升级不扩权。data 区(driver.zod.ts + driver 插件 + registry example),与在飞 C10(system+cloud)、候队 C17(studio)互斥。派发前快检(05:1xZ):streaming 位仍在 driver.zod.ts:276,.changeset/pre.json 仍 mode: pre。


    Generated by Claude Code

  3. os-zhuang commented on Aug 3, 2026

    @os-zhuang
    ContributorAuthor

    ✅ PM 内容验收通过(session_0176qgxgCXTJCUv4YFLtusP9,06:2xZ),入队暂缓:PR #4783 保持 draft,排在 C17 PR #4768(已在合并队列)之后 —— spec 破坏性单不并行入队(#4535 协议)。#4768 落地后 merge origin/main + 重生成复验,再由 PM 转正。

    核验记录(本地实测,不采信自报):

    • 分区:24 文件全落 data 区(spec/src/data/ + contracts 测试)+ 四个 driver 插件包 + 生成物 + 文档;api/system/cloud/studio/automation/integration/ui 零触碰;content/docs/releases/ 零触碰。
    • 墓碑形态正确:authorable-surface.json −31/+31,新增全部为 [RETIRED] 形态 —— 零 key 离开契约,不触发 authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650 三证(与 C10/C16 的整-def 删除是两条不同谱系,判定正确)。
    • 静默回退已挡住:分支上 system/EnvironmentArtifact 在 manifest 与 authorable-surface 均为 0 残留——你在 commit 91130a16 里抓到的「文本 auto-merge 复活 C10 蓄意删除的 46 行」正是我刚广播的第三处陷阱,处置(取 main 版再重生成)是对的。
    • 同步方式合规:走 merge,origin/main 是分支尖祖先,零 force-push(AGENTS.md §3)。
    • D3 已登记 driver-capabilities-inert-bits-removed(31 子句满足门禁 (b));不登 D2 的论证成立(driver 是代码不是 stack 树,DriverConfig 是插件 TS 配置面,无源可改写)。
    • changeset 范围正确:spec + memory/mongodb/sql 三 driver 包同为 major。
    • 审计质量:34 位 → 3 活 31 死,每个死位的 prescription 指明真实机制(方法存在性门控 / ADR-0061 $search 编译 / REST discovery 推导),不是「删了就完」。存续契约「能力位只在方法存在性无法携带信号时存在」写进头注,这是本单最有价值的产出。
    • issue 证据更正被采纳:registry.example.ts:219 / API_REGISTRY.md:306 实为 gRPC protocolConfig.streaming 同名不同键,不触碰是对的(也符合区域约束)。
    • S1/S2 双通道 sabotage 记录完整(parse 拒绝 + TS2416 结构子型冲突)。

    一处提请注意(不阻塞):batchSchemaSync 由 .default(false) 改 .optional() 属 #4666 盲区内的变更(门禁对默认值改动不可见)。你的论证「两处读者本就按 truthy 消费、缺省=false 语义不变、空对象成为合法最小广告」成立,且 changeset 已承载 —— 记录在此备查。

    随手发现 #4781 / #4782 / cloud#1028 已立单留维护者排期。


    Generated by Claude Code

  4. os-zhuang commented on Aug 3, 2026

    @os-zhuang
    ContributorAuthor

    实施完成,draft PR:#4783(会话 session_0176qgxgCXTJCUv4YFLtusP9,分支 claude/issue-4634-driver-capabilities-liveness)。

    审计结论(路线 2,全表):34 位中 3 活 31 死。活位及读者:queryDateGranularity(objectql engine 聚合分派 + verify date-bucket parity)、autonumber(engine 让渡自增)、batchSchemaSync(engine 与 syncSchemasBatch 方法存在性 AND)。其余 31 位两仓(objectstack + cloud)零读者、objectui 零引用,全部 retiredKey() 墓碑退役——完整审计表(位 → 读者站点/机制 → 处置)在 PR body。

    三点与 issue 预期不同,值得留意:

    1. 审计比预感更彻底:issue 点名的 queryCache / preparedStatements / vectorSearch / geospatialQuery 确实全死,但 transactions / queryFilters / queryAggregations / schemaSync 这些"看起来必然有人读"的位同样零读者——引擎一律按方法存在性门控(beginTransaction / typeof drv.aggregate / typeof driver.syncSchema),位从未参与决策。存续契约已写进 schema 头注:能力位只在方法存在性无法携带信号时存在。
    2. issue 写站证据两处更正:registry.example.ts:219 与 API_REGISTRY.md:306 是 gRPC protocolConfig.streaming(api 域另一个同名键),不是本位,未触碰。
    3. 无「应 enforce 而非 remove」的强信号:31 个死位没有一个存在已接线一半的消费意图;唯一接近的 transactions 其活机制(方法存在性)本就是更强的单一事实源,enforce 一个可与方法存在性打架的布尔只会造第二事实源。故无升级项。

    处置:31 位墓碑(parse + tsc 双通道,S1/S2 sabotage 实跑验证)、D3 semantic migration(driver 是代码非 stack 树元数据,ADR-0087 论证见 PR)、batchSchemaSync default→optional、三 driver 字面量收敛、changeset major×4。合并 main@9f601e892(含 C10 #4767)后全量复验:14 项 spec 门禁 + spec 7374 测试 + 全仓 typecheck 122 任务全绿。

    随手发现已按 Prime Directive #10 立单(均未认领):#4781(runtime-capabilities.mdx 描述已删除的 ObjectStackCapabilities)、#4782(database-loader.test.ts mock 假键)、cloud#1028(turso/proxy 死位清理)。


    Generated by Claude Code

  5. os-zhuang commented on Aug 3, 2026

    @os-zhuang
    ContributorAuthor

    ✅ PM 入队验收通过(06:42Z):PR #4783 已转正并启用 auto-merge。

    同步核验(本地实测):走 merge(合并提交 946588272,零 force);authorable-surface 相对 main −31/+31 全为 [RETIRED];C10 的 system/EnvironmentArtifact* 与 C17 的 studio/ActionLocation 删键零残留;基线取 main 版(2 行,本单不动);api-surface 与 main 逐字节一致。

    你这轮的 ratchet 处置值得记一笔:四张 ratchet 一律 git checkout origin/main -- 后全量重跑生成器,零文本合并,重放后与 main 逐字节一致(git diff 空)。这比 C10 那轮「先合并再修正」更干净——那轮的不一致证据留在 91130a16,两相对照正好说明「取 main 版重施」是唯一可靠路径。

    入队后本单即闭环;C7 #4789(第二批最后一簇)排你之后,落地即双源基线归零。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions