Repository navigation
driver-memory 测试面替代:项目内测试后端迁到 sqlite :memory:(#5499 重启条件 · memory 半边,维护者 2026-08-06 立项) #5704
Description
Activity
认领:PM 循环第 7 轮(drivers 车道)— Phase 1: Survey(逐文件处置表)
会话:session_01WyvqvKMG6asi9aXjKE6xtx
分支:无(本阶段纯读分析,零文件改动,产出为本单评论的处置表)
域:程序锚点在domain:drivers(#5499 重启条件);后续各包迁移 sub-issue 按落点包分域,由分诊补标
文件面:无写入;读取面为正文清单的 41 个测试文件 + 各包 package.jsonPhase 2(按包迁移)待 survey 处置表产出后拆单派发。
Generated by Claude Code
- addedpriority:p0Critical: blocker, must ship before MVPCritical: blocker, must ship before MVP
on Aug 6, 2026 Phase 1(Survey)交付(os-dev 只读调查,基线
a58c0b5;PM 复核收下)。核心发现:正文的隐含假设被证伪
41 文件计数精确,但其中只有 3 个真
import @objectstack/driver-memory当存储后端跑;29 个是本地手写替身(objectql/rest/plugin-approvals/trigger/spec 五个包的package.json连 driver-memory 依赖都没有 —makeMemoryDriver()是误导性命名,部分注释甚至自述「driver-sql 同形」);7 个是域外面伪装(provisioning registry ×3、CLI registry ×1、spec 声明面 ×1、banner 标签 ×1、降级链 mock ×1)— 它们的命运分属 #5499 的 carve-out 与 ADR-0087 退役流程,不是测试后端迁移。净真替换面:3 个文件。分类 数 处置方向 A 真依赖 3(qa/dogfood ×1 ✅纯机械、runtime ×2 含语义块) 换 SqlDriver :memory:B 本地替身 29 待裁决(见下) 域外伪装 7 从迁移面剔除,理由已逐个记录 纯注释 2(+41 外附录 2) 不动 无环核验通过:driver-sql 不依赖 objectql,加 devDep 无循环。最高风险 5 文件:
query-expression-conformance(10 处插入序断言 + 6 处stores.set同步播种 + 删 aggregate 能力,1249 行)、undeclared-field-write-driver-split(测试目的就是双族分歧)、secret-fields(12 处落盘形态直读)、engine-filter-alias(6 处)、datasource-autoconnect(#4083 持久化块)。批次结构与裁决依赖
- 批次 0(已派发,与裁决无关):qa/dogfood 删 memory 数组条目 +
datasource-autoconnect主体换 SqlDriver:memory:,其中 datasource-autoconnect 的联邦查询测试在本地必现失败:ext_note 读到 6~12 行而非 2 行(CI 绿,需第二台机器复核) #4083 块按 PM 裁定 Q3-B 处理:改写为等价的「内存库不落盘、重启为空」保证(ADR-0062 D1 验收的是运行时属性非实现细节;工厂层的 datasource-autoconnect 的联邦查询测试在本地必现失败:ext_note 读到 6~12 行而非 2 行(CI 绿,需第二台机器复核) #4083 钉点已由 service-datasource 测试独立覆盖 — 验证策略类,PM 自决,否决窗口开放)。 - 批次 1(本评论即执行):7 个域外文件从迁移面剔除 —
runtime/standalone-stack、service-datasource/__tests__/default-datasource-driver-factory、cli/utils/storage-driver(三者 = id→驱动映射的 registry 面)、spec/data/driver/memory.test.ts(spec 声明面,归 ADR-0087)、cli/serve-driver-banner(标签字符串)、service-datasource/sqlite-driver-fallback(降级链 vi.mock)、spec/data/driver.test.ts(纯注释)。 - 批次 2/3/4:等两项维护者裁决(已在 PM 会话呈报):
- Q1:29 个 B 类替身 — 仅改名去误导(
makeStubDriver)/ 全量真迁 / 分层(objectql 22 仅改名 + 3 包 7 个*.integration.test.ts真迁)。Survey 三轴推荐分层 C:objectql 的替身是刻意的单元测试隔离手段(真迁会削弱指向性),而挂着 integration 名字跑假驱动的 7 个有真实缺口;改名本身结构性消除「grep driver-memory 系统性高估」的度量陷阱。 - Q2:
undeclared-field-write-driver-split的无 schema 参照臂 — 推荐保留 driver-memory 仅此一处(它是分歧护栏的一半,冻结令冻投资不冻使用;加注释声明「刻意保留,非迁移目标」),次选 mongodb 顶替(CI 成本上升),反对删臂(静默拆护栏)。
- Q1:29 个 B 类替身 — 仅改名去误导(
裁决落地后:批次 3(7 文件合一单)→ 4a(objectql 18 低风险)→ 4b(4 高风险逐例)依序派发;若 Q1 裁「仅改名」,批次 3/4 坍缩为一条纯机械改名单,Phase 2 规模 34 → 5 文件。
逐文件处置表(43 行,点开)
路径 分类 关键事实 → 处置 objectql/bulk-write-per-row-hooks B 本地 stub → 改名 objectql/engine-audit-anchor-write B 注释自述「driver-sql 同形」→ 改名 objectql/engine-autonumber-runtime-owned B ⚠️ 单 stub 建模两族(nativeAutonumber 切 name)→ 真迁需拆两套装配 objectql/engine-cascade-delete B → 改名 objectql/engine-dangling-reference-audit B 2 处 store 读 → 改名 objectql/engine-data-events B → 改名 objectql/engine-default-value-tokens B → 改名 objectql/engine-filter-alias B ⚠️ 6 处 store 直读钉「写路径未越写」(#4346)→ 真迁需改驱动读 objectql/engine-lookup-referential-integrity B → 改名 objectql/hook-condition-bulk-previous B 含 syncSchema → 改名 objectql/hook-condition-fail-loud B → 改名 objectql/hook-condition-merged-record B → 改名 objectql/hook-condition-previous-scope B reads计数器真驱动上语义会变 → 改名objectql/hook-input-shape-contract B → 改名 objectql/protocol-clone-real-engine B → 改名 objectql/protocol-recorded-by-null B → 改名 objectql/protocol-registry-shadow B → 改名 objectql/protocol-save-meta-repo-path-real-engine B → 改名 objectql/protocol-unknown-query-param B 1 处 stores.set同步播种 → 真迁需 bulkCreate+建表objectql/protocol-unregistered-object B 同上 objectql/query-expression-conformance B ⚠️ 最高危1249 行;6 处 stores.set+ 10 处 INSERTION_ORDER +delete driver.aggregateobjectql/secret-fields B ⚠️ 12 处密文落盘直读 runtime/datasource-autoconnect A+C 真 import;主体可换;#4083 块按 Q3-B 改写 runtime/sandbox/nested-write.canary B → 改名 runtime/sandbox/nested-write.integration B → 改名 runtime/sandbox/undeclared-field-write-driver-split A+C ⚠️ 分歧测试本体 → Q2 待裁 runtime/standalone-stack 域外 provisioning registry 面 → 剔除 rest/export-integration B → 批次 3 rest/import-integration B → 批次 3 rest/import-job-integration B → 批次 3 plugin-approvals/record-lock-multi-update.integration B → 批次 3 plugin-approvals/record-lock-schedule-run.integration B → 批次 3 plugin-approvals/status-mirror-cascade.integration B → 批次 3 spec/data/driver.test 纯注释 不动 spec/data/driver/memory.test 域外(C) spec 声明面,归 ADR-0087 → 剔除 service-datasource/default-datasource-driver-factory 域外 工厂 registry + #4083 钉点 → 剔除 service-datasource/sqlite-driver-fallback B+域外 降级链 vi.mock → 随降级链去留 cli/serve-driver-banner B 标签字符串纯函数 → 随 banner 分支去留 cli/utils/storage-driver 域外 CLI registry 面 → 剔除 trigger-record-change/record-change-integration B → 批次 3 qa/dogfood/read-coercion-conformance A✅ SQL 臂已存在且绿 → 批次 0,删 memory 条目 (附录)objectql/protocol-batch-atomic 纯注释 不动 (附录)objectql/protocol-data 纯注释 不动
Generated by Claude Code
- 批次 0(已派发,与裁决无关):qa/dogfood 删 memory 数组条目 +
批次 0 复核:ACCEPT → PR #5715 已转 ready 并挂 auto-merge 入队(CI 全绿,唯一红为标签竞态旧 run、已被取代)。留档要点:
- 恰好 2 文件(+120/-47),零 package.json 改动(依赖面与 survey 预判一致);
read-coercion-conformance删 memory 臂,文件头覆盖声明同步修真(「SQL + memory」→ 实话);datasource-autoconnect:3 处默认后端统一makeDefaultDriver()(仓库规范形态);声明面同步driver:'sqlite'(否则 D1 改写空转 — dev 自查到位);schemaMode:'external'下ext_note表按 ADR-0015 走带外execute()建表 — 声明而非放松断言,是这次迁移买到的保真度;- Q3-B 改写落地且经缺陷注入验证:两条新断言(
.objectstack/**双次 boot 不存在、新池连表都没有)在注入 datasource-autoconnect 的联邦查询测试在本地必现失败:ext_note 读到 6~12 行而非 2 行(CI 绿,需第二台机器复核) #4083 同形缺陷时各自独立见红,还原后 11/11 绿; - 锚点纪律自觉:顺手产生的
authorable-surface.base.json重锚已剔出 diff(os-regen 驱动指示的gen:schema在 merge 未 commit 时运行,会把 authorable-surface 锚点倒退回旧 merge-base —— 生成器写入、门全绿、静默撤销 main 的锚点推进 #5370); - erasure 天花板 267 未涨;runtime 1436 / dogfood 513 全绿;
- 顺手立单 datasource
pool声明在 sqlite / sqlite-wasm 驱动臂被静默丢弃(pg / mysql 生效) #5714(datasourcepool在 sqlite 臂静默丢弃 — 实测证据 + 三选项不带猜,决策类,待分诊); - 收口备忘(dev 记录,PM 确认):qa/dogfood 的 driver-memory devDep 已无消费,留到本单收口阶段摘除;runtime 的必须保留(Q2 待裁 + 域外文件仍消费)。
批次 1(域外剔除)已随 Phase 1 评论完成。批次 2/3/4 等 Q1/Q2 裁决(已呈维护者)。
Generated by Claude Code
- added a commit that references this issue
on Aug 6, 2026 裁决落档(维护者 2026-08-06,PM 会话拍板) — 批次 2/3 解锁:
- Q1 = C(分层):29 个 B 类本地替身分两路 — ① objectql 22 个 + runtime sandbox nested-write 2 个仅改名(
makeMemoryDriver→makeStubDriver,消除误导性命名;它们是刻意的单元测试隔离手段,真迁反而稀释指向性);② 3 包 7 个*.integration.test.ts真迁 driver-sql + better-sqlite3:memory:(rest ×3、plugin-approvals ×3、trigger-record-change ×1 — 名为集成测试却跑手写替身,名不副实,真迁有实际收益)。 - Q2 = B(仅此一处保留):
undeclared-field-write-driver-split.integration.test.ts保留 driver-memory 作无 schema 语义参照臂 — 它是「SQL 族整条拒绝 / 无 schema 族照单全收」分歧护栏的一半;文件头加注释声明刻意保留、非迁移遗漏。[裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 冻结令冻的是缺陷修复投入,不禁止作参照物使用。推论:runtime 的 driver-memory devDep 长期保留(仅此一个消费点);qa/dogfood 的 devDep 收口时摘除(批次 0 复核已记)。
执行结构:两条 sub-issue,file-disjoint 并行 — 批次 2(改名 + Q2-B 注释:
packages/objectql+packages/runtime)、批次 3(真迁:packages/rest+packages/plugins/plugin-approvals+packages/triggers/trigger-record-change)。收口预告:两单落地 → 迁移面清零 → 回 #5499 执行重启条件(#5433/#5440/#5442/#5444/#5354 批量关闭 not planned),包本体退役另请维护者单独裁决。
Generated by Claude Code
- Q1 = C(分层):29 个 B 类本地替身分两路 — ① objectql 22 个 + runtime sandbox nested-write 2 个仅改名(
收口执行记录(批次 2/3 已合并,2026-08-06 07:5xZ)
迁移面清零达成,main(
2a607d2)实测:- 全仓
makeMemoryDriver归零 ✓(PR test(objectql,runtime): B 类替身改名 makeMemoryDriver→makeStubDriver(26 文件)+ Q2-B 保留注释 #5797 改名 26 文件、test(rest,plugin-approvals,trigger-record-change): 7 个 integration 测试真迁 driver-sql sqlite :memory:(#5704 批次 3) #5806 真迁 7 文件,与 test(runtime,dogfood): 批次 0 —— 两个真依赖测试后端迁到 sqlite:memory:#5715 批次 0 合计 3 个 PR 覆盖全部处置面); - 测试文件真 import driver-memory 的:
undeclared-field-write-driver-split(Q2-B 裁定保留 ✓)+ 1 个 survey 后新落地的消费者plugin-auth/src/auth-contains-filter.test.ts(plugin-auth: better-auth 的contains被译成裸$regex,用户输入当正则求值 —— 且是$regex退役唯一挡路的生产者 #5710/fix(plugin-auth): better-auth 的contains下译为$contains,比较值不再当正则求值 (#5710) #5812,今晨 identity 车道合入,连带 plugin-auth 新增 devDep)— 已立 finding 交分诊裁处置(迁 sqlite vs 刻意保留),不改变本程序结论; - [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 重启条件已执行:driver-memory analytics 面的
generateSql对in/notIn/set/notSet输出错误 SQL:回退成=且只取第一个值($in: ['100','200']→WHERE code = '100') #5433 / driver-memory analytics 面:同一字段上的多个算子互相覆盖,{qty: {$gte:150, $lte:250}}只剩最后一个 —— 区间塌成单边,结果被放大 #5440 / driver-memory analytics 面:flattenFilterCondition对所有算子一律摊平数组比较数,{qty: {$eq: [100]}}变成$eq: 100(find()取 0 行,analytics 取 1 行) #5442 / driver-memory analytics 面的generateSql把contains回显成LIKE 'et'(没有%通配符)—— 回显的是等值匹配,执行的是子串匹配 #5444 / driver-memory 的两个过滤面对**比较值的种类**给出相反答案:{f: /re/}(正则)与{f: ['x']}(数组)各差一个方向 —— 实测 #5354 批量关闭(not planned),依据各单留档; - 尾项立单派发:qa/dogfood devDep 摘除 + 两处附录散文清扫(见 sub-issue);
- 包本体退役决策已呈维护者(独立决策,不在本单代裁)。
本单在尾项清理单落地后关闭。
Generated by Claude Code
- 全仓
程序终结(2026-08-06 08:0xZ) — 尾单 #5829(PR #5836)已 MERGED,3 张 sub-issue 全部闭合,本单关闭(completed)。
最终账:
- 4 个 PR 全部合并:test(runtime,dogfood): 批次 0 —— 两个真依赖测试后端迁到 sqlite
:memory:#5715(批次 0,2 真依赖迁移)→ test(objectql,runtime): B 类替身改名 makeMemoryDriver→makeStubDriver(26 文件)+ Q2-B 保留注释 #5797(批次 2,26 文件替身改名 + Q2-B 注释)→ test(rest,plugin-approvals,trigger-record-change): 7 个 integration 测试真迁 driver-sql sqlite :memory:(#5704 批次 3) #5806(批次 3,7 个 integration 测试真迁 sqlite)→ chore(qa,objectql): 摘除 dogfood 无消费的 driver-memory devDep + 清扫 1 处 stub 注释散文 (#5829) #5836(收口:dogfood devDep 摘除 + 散文清扫); - 验收线(main 实测):全仓
makeMemoryDriver归零;driver-memory 的测试真消费仅存 Q2-B 裁定的参照臂(undeclared-field-write-driver-split,注释留档)+ plugin-auth: better-auth 的contains被译成裸$regex,用户输入当正则求值 —— 且是$regex退役唯一挡路的生产者 #5710 pin 测试(处置归 finding [finding] #5704 收口后仓内新增一个 driver-memory 测试消费者:plugin-auth/auth-contains-filter.test.ts(#5710 pin 测试,与 #5704 程序不变量的张力,请分诊裁处置) #5830);qa/dogfood 依赖声明清零,runtime devDep 按 Q2-B 长期保留; - [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 重启条件已执行:driver-memory analytics 面的
generateSql对in/notIn/set/notSet输出错误 SQL:回退成=且只取第一个值($in: ['100','200']→WHERE code = '100') #5433/driver-memory analytics 面:同一字段上的多个算子互相覆盖,{qty: {$gte:150, $lte:250}}只剩最后一个 —— 区间塌成单边,结果被放大 #5440(+driver-memory analytics 面的generateSql把contains回显成LIKE 'et'(没有%通配符)—— 回显的是等值匹配,执行的是子串匹配 #5444)/driver-memory analytics 面:flattenFilterCondition对所有算子一律摊平数组比较数,{qty: {$eq: [100]}}变成$eq: 100(find()取 0 行,analytics 取 1 行) #5442/driver-memory 的两个过滤面对**比较值的种类**给出相反答案:{f: /re/}(正则)与{f: ['x']}(数组)各差一个方向 —— 实测 #5354 批量关闭 not planned; - 包本体裁决:维护者 2026-08-06 裁 A — 维持冻结、暂不退役(落档 [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499),退役重议的前置清单已留档;
- 断言零缩水,语义分叉处置全部「声明而非放松」,过程中顺产 2 张独立发现单(datasource
pool声明在 sqlite / sqlite-wasm 驱动臂被静默丢弃(pg / mysql 生效) #5714、[finding] #5704 收口后仓内新增一个 driver-memory 测试消费者:plugin-auth/auth-contains-filter.test.ts(#5710 pin 测试,与 #5704 程序不变量的张力,请分诊裁处置) #5830)交分诊。
Generated by Claude Code
- 4 个 PR 全部合并:test(runtime,dogfood): 批次 0 —— 两个真依赖测试后端迁到 sqlite
2 remaining items
- added a commit that references this issue
on Aug 22, 2026 - added a commit that references this issue
on Aug 25, 2026 - added a commit that references this issue
on Aug 29, 2026 - added 4 commits that reference this issue
on Sep 1, 2026 - added a commit that references this issue
on Sep 1, 2026 - added a commit that references this issue
on Sep 4, 2026 - added a commit that references this issue
on Sep 9, 2026 - added a commit that references this issue
on Sep 20, 2026
立项依据:#5499 裁决原文「driver-memory 是早期为测试便利设计的组件,方向已定为 sqlite 内存模式替代……替代迁移若立项,在本单登记排期」+ 维护者 2026-08-06 在 PM 会话确认(「driver-memory 在项目内的测试应该被替换为 sqlite 的内存模式」)。完成即触发 #5499 的 memory 侧重启条件:名下 5 张挂起缺陷单(#5433/#5440/#5442/#5444/#5354)整批关闭(not planned),包本体的退役决策另行交维护者。
mongodb 侧不在本单:维护者同日确认 mongodb 维持暂停。
实测消费面(origin/main @ 2026-08-06 01:2x Z)
测试文件引用 driver-memory / MemoryDriver(外部,共 41 个文件 / 9 包):
packages/objectqlmakeMemoryDriver()本地定义(22 处),其中部分是手写同形 stub(如注释 "same shape driver-memory uses, small enough to assert against"),并非全部真依赖包 — 逐文件分诊是第一步packages/runtimepackages/restpackages/plugins/plugin-approvalspackages/specpackages/services/service-datasourcepackages/clipackages/triggers/trigger-record-changepackages/qa/dogfoodpackage.json 依赖声明:cli、plugin-dev、qa/dogfood、runtime、service-datasource、examples/embed-objectql(+包自身)。
⛔ 明确不在本单范围(它们不是「测试」,归包退役决策):runtime provisioning 偏好序里的
memory注册名回退(http-dispatcher)、plugin-dev 的开发默认后端、examples/embed-objectql(该示例的主题就是内嵌 memory driver)、driver-memory 自己的 15 个测试文件。替代目标
@objectstack/driver-sql+better-sqlite3:memory:(examples/app-crm、app-showcase 与cli db clean已采用的同款形态,#5499 事实核查确认)。阶段结构
domain:*按落点包由分诊补):objectql 一单(最重),runtime+rest 一单,其余小包合批或独立由 survey 结果定。风险如实声明
{f: /re/}(正则)与{f: ['x']}(数组)各差一个方向 —— 实测 #5354/$exists的比较值不是布尔时,三个后端面给出三个答案,driver-memory 自己的两个面在'yes'上就已分叉 —— 实测,$null(#5347)的同族另一轴 #5369/非否定路径上的$ne/$nin/$notContains:driver-sql 排除 NULL 行,driver-memory / formula 返回它们(#5146 只裁定了$not) #5298/driver-memory 与 formula 对「字段没有值」给出三处不同答案:$notContains(null 值)、$exists(键在值为 null)、$nin(缺键) #5299 一族正是此类)— 这是设计内收益(测试从此压真语义),但意味着迁移单不是纯机械改,每个红都要有处置记录。domain:engine-core车道(现空缺),是吞吐瓶颈 — 执行模型待分诊/维护者定(车道逐单 vs epic 委托)。排期登记与本单互链见 #5499 评论。