Files
qinglong/docs/adr/ADR-0292-local-sqlite-run-persistence-support-module.md
T

88 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-0292Local SQLite Run Persistence Support 内部模块
- 状态:Accepted
- 日期:2026-08-09
- 关联:D-85、D-87、D-213、D-257、ADR-0007、ADR-0069、ADR-0280、ADR-0290、ADR-0291
## 上下文
ADR-0291 已把具名 `LocalSqliteRunReader` 移到独立文件,但 `runRepository.ts` 仍同时持有 Run/Attempt/Event/Retry
列声明、SELECT/INSERT/UPDATE SQL builder、row codec、SQLite driver error mapping、有界 query helper、Transaction、
Security/Secret 映射和产品 Facade。Reader 为避免复制,通过一个冻结 support 对象从 Facade 文件接收这些函数;这只是
安全的过渡边界,并没有消除反向依赖。
强制完整 GitNexus 索引表明五个 scalar/JSON codec 为 CRITICAL,最大 13 direct/88 total、2 processes/7 modules
`mapSqliteError``queryRows``singleRow` 和 SQLite code/number 解码为 HIGH,最大 17 direct/46 total、1 process/
4 modules。Facade 仍为 CRITICAL30 direct/63 total),Reader 为 HIGH15/40),Transaction 为 HIGH15/37)。
因此本批次必须是逐字语义保留的模块抽取,不能同时泛化不同领域的 SQLite codec。
## 决策
1. 在既有 `@qinglong/local-sqlite/src/run/` 下新增 package-private `runPersistence.ts`,集中:
- Run/Attempt/Event/Retry column metadata 和 SELECT/INSERT/UPDATE SQL 常量;
- write value normalization、row scalar/JSON/enum/blob/boolean codec 与 Run record 映射;
- SQLite error code/number/message 分类、`mapSqliteError`、event payload 上限;
- `queryRows` 和 duplicate-identity `singleRow`
2. 所有被迁移函数体、错误类型、错误文本、NULL/undefined/empty-string 处理、JSON parsing、enum 集合、column 顺序、
SQL 文本和 payload byte 计算逐字保持。不得借重构修改协议或“统一”错误。
3. `LocalSqliteRunReader` 直接导入 persistence support,不再接收函数对象;构造器恢复只接收同一 `DatabaseSync`
`LocalSqliteRunTransaction` 继续继承 ReaderFacade 继续通过唯一 `LocalSqliteOperationAuthority` 调度两者。
4. `LocalSqliteRunRepository`、Transaction 和现有 Security/Secret 映射只改为 import 同一 support。公开构造器、
runtime-core ports、root/subpath exports、事务边界、close/error mapping 和消费者不变。
5. 新模块不得从 `package.json#exports``index.ts``runtime.ts` 导出,也不得创建 connection、transaction、queue、
timer、watcher、cache、listener 或后台工作。
6. Completion Receipt、Task Definition、Owner、Tool 等模块的相似 helper 具有不同 empty/null/error 语义,本批次不合并;
后续只有在先冻结共同 contract 后才可共享,不能按函数名相同机械去重。
7. 不新增 workspace package、生产 dependency、migration、表、索引、进程或部署单元;19-package ledger 与 Edge/
Standalone 制品和 RSS 上限保持不变。
## 被拒绝的方案
- **建立 package-wide 万能 row codec**:不同领域对空字符串、NULL、错误类型和错误文本要求不同,会造成静默语义漂移。
- **继续由 Facade 向 Reader 注入函数对象**:可以运行,但让只读模块的基础依赖反向由产品 Facade 组装,长期难以演进。
- **复制 support 到 Reader/Transaction**:会复制列顺序、SQL projection 和 normalization,读写路径可能分叉。
- **把 support 拆成新 workspace package**:没有独立部署、权限、依赖或消费者 closure,只增加低配设备 importer/SBOM。
- **同时移动 Transaction 或 Security/Secret authority**:会把机械 support 抽取扩大为事务 ownership 重构,无法归因回归。
## 接受条件
1. 原 support 函数和常量只存在于 `runPersistence.ts`Reader/Fascade/Transaction 没有复制;源码与错误文本保持等价。
2. Reader 恢复单参数构造,Transaction 写方法与 Facade BEGIN/COMMIT/ROLLBACK、enqueue/close 完全不变。
3. Run、startup recovery、dispatch/control、Security Audit、Project Policy、Local Secret 和 corruption/error 定向测试通过;
Local SQLite 全量零回归。
4. 完整 19-package clean build/test、backend、六项架构/部署审计及十档 artifact/RSS 门通过;package 仍为 19 个、
`singleSourcePackages=[]`,公开 exports、依赖与 migration chain 不变。
5. 强制完整 GitNexus 索引后重查全部 CRITICAL/HIGH helper、Facade/Reader/Transaction 和执行流,再运行
`detect_changes` all/compare `develop`。如果 support 丢失可索引性、生产流程扩散或风险上升,ADR 不得 Accepted。
## 接受证据
- `runPersistence.ts` 为 551 行,成为 Run 子域唯一的 column/SQL/codec/error/query support`runRepository.ts`
从 1,990 行降至 1,457 行,`runReader.ts` 从 762 行降至 667 行。Reader 恢复只接收同一 `DatabaseSync`,旧
`LocalSqliteRunReaderSupport` 注入对象已删除;Transaction 写方法、BEGIN/COMMIT/ROLLBACK、Facade enqueue/close、
runtime-core port 和 package exports 均未改变。
- 跨 Run/Startup/Dispatch/Control/Execution Revision/Security Audit/Policy/Secret 的定向回归 74/74、Local SQLite
192/192、完整 19-package clean build/test 与 backend 1,1101,108 pass/2 skip)通过;cluster dependency、package
boundary、Edge import、cluster deployment、CloudNativePG 与 local image 六项审计均 `compatible:true`
- workspace 保持 19 个 package、765 个 source、49 个受审根入口和 716 个领域内嵌套实现,
`singleSourcePackages=[]`Local SQLite 为 153/3/150。没有新增生产 dependency、migration、表、索引、进程、
部署单元或公开 specifier。
- 十档制品/RSS 门全部 compatible。最小 Edge 为 3,623,406 bytes/329 files/45 loaded modulesRSS delta
11,599,872 bytes;最大 Standalone Application AI 为 6,111,027 bytes/488 files/101 loaded modulesRSS delta
21,250,048 bytes,均低于硬上限。
- 强制完整索引为 43,173 nodes/98,227 edges/1,693 clusters/265 flows。五个既有 scalar/JSON helper 仍为 CRITICAL
最大 `requiredString` 17 direct/108 total、`requiredInteger` 19/107`mapSqliteError``queryRows` 和 SQLite
code/number decoder 仍为 HIGH,最大 20/70`singleRow` 为 MEDIUM13/42)。直接调用数比 support-object 基线更
完整,是删除间接注入后图谱恢复可见性,不是新消费者或执行流;其风险等级没有升级。Facade 为 CRITICAL30/64)、
Reader 为 HIGH15/40)、Transaction 为 HIGH15/38),全部仍为 0 affected process;其余 persistence helper
最高 MEDIUM。
- 本批次只改变 Local SQLite package 内源码组织,未触及 PostgreSQL、Cluster、migration 或 HA 状态,因此不重复执行
与变更无关的物理 PostgreSQL HA;对应结构、依赖和部署审计已覆盖其不变性。
- `detect_changes` all/compare `develop` 分别为 12 files/31 symbols 与 14/34,均为 low/0 affected processQL3
孵化树大部分仍 untracked,因此该结果只作为逐符号 impact、完整测试、审计与制品门的补充证据。
## 后续边界
- Security/Secret authority 仍在 Run Facade 内是下一项真实职责问题,但必须先按共同授权事实和事务围栏建模。
- 其他领域的重复 scalar helper 只能按明确 contract 分组迁移,不能把本 ADR 当成全 package 泛化授权。