mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-23 03:18:09 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
# ADR-0152:Generation 绑定的原子 Plugin Package Task Reconciliation
|
||||
|
||||
- 状态:Accepted(双方言原子仓库、ownership、receipt、最小权限入口与真实
|
||||
PostgreSQL 门已实现;生产 materialization coordinator、故障注入级 HA receipt
|
||||
证明和引用感知 retention 尚未实现)
|
||||
- 日期:2026-07-26
|
||||
- 关联:ADR-0089、ADR-0091 至 ADR-0093、ADR-0149 至 ADR-0151、
|
||||
QL-RFC-0001 D-144/D-145/D-146
|
||||
|
||||
## 背景
|
||||
|
||||
ADR-0151 已能按 `generationDigest` 持久化一份完整、不可变的 Package semantic
|
||||
revision,但 TaskDefinition consumer 仍有三个未关闭的错误窗口:
|
||||
|
||||
- 一代包含多个 Task 时,逐条调用通用 Task repository 会暴露部分 generation;
|
||||
- upgrade 删除一个 Task 时,直接删除历史会破坏 Run、execution revision 和审计引用,
|
||||
不处理又会让旧任务继续可调度;
|
||||
- Package publisher 与人工/其他 publisher 竞争同一个 `taskId` 时,只有 revision CAS
|
||||
不足以表达长期 ownership。
|
||||
|
||||
此外,active pointer、materialized revision、Task head 和 execution revision 位于不同
|
||||
耐久边界。publisher 必须在同一提交内证明“正在提交的仍是当前 active generation”,
|
||||
并保存可精确重放、可恢复、可审计的 generation receipt。
|
||||
|
||||
## 决策
|
||||
|
||||
### 1. 不新增 workspace package
|
||||
|
||||
纯规划与共享 repository contract 放入既有
|
||||
`@qinglong/runtime-core/plugin-package-task-reconciliation`。SQLite adapter 放入
|
||||
`@qinglong/local-sqlite/plugin-package-task-reconciliation` 显式 subpath;
|
||||
PostgreSQL adapter 只从 `@qinglong/cluster-postgres/package-executor` 导出。
|
||||
|
||||
该切片没有独立部署、依赖、版本或供应链生命周期,因此不创建只有一两个文件的新
|
||||
workspace importer。它不新增第三方依赖、timer、watcher、socket、连接池或常驻缓存;
|
||||
`packages/` 仍保持 21 个 importer。
|
||||
|
||||
### 2. generation 是唯一批次,receipt 是提交事实
|
||||
|
||||
新增 `qinglong/plugin-package-task-reconciliation@v1` receipt。每份 receipt 精确绑定:
|
||||
|
||||
- Project、Package、generation、lock digest 和 previous lock digest;
|
||||
- active `generationDigest` 与 materialized revision digest;
|
||||
- 该 generation 的完整 Task item 集合;
|
||||
- 每项最终 `taskId`、revision、content digest 与 disposition;
|
||||
- domain-separated receipt digest 和数据库提交时间。
|
||||
|
||||
任务 identity 固定为 `pkg:<packageName>:<resourceId>`。单次 reconciliation 最多处理
|
||||
512 项;输入 facts 必须与“当前 materialized Task 集合 ∪ 上一代 receipt item 集合”
|
||||
完全相等,少项、多项、重复项或外来项均失败关闭。
|
||||
|
||||
disposition 只有:
|
||||
|
||||
- `created`;
|
||||
- `retained`;
|
||||
- `updated`;
|
||||
- `disabled`;
|
||||
- `already_disabled`。
|
||||
|
||||
upgrade 中消失的 Task 不删除,而是以新不可变 revision 设置 `enabled=false`;已禁用
|
||||
任务不重复写 revision。语义未变的 Task 保留原 revision,不因 generation 变化制造
|
||||
写放大。
|
||||
|
||||
### 3. 规划是纯函数,提交重新复验全部 fence
|
||||
|
||||
runtime-core planner 只接受规范化 materialized revision、上一代 receipt 和数据库
|
||||
观察到的 Task/ownership facts,产生确定性 mutation ID、TaskDefinition writes、
|
||||
execution plans 与 receipt。它不取得数据库、文件、网络或 active pointer authority。
|
||||
|
||||
adapter 在提交前和事务内都要复验:
|
||||
|
||||
1. materialized revision identity;
|
||||
2. active install 的 installation、generation、lock 与 previous lock;
|
||||
3. 上一代 receipt chain;
|
||||
4. Task head revision/content digest;
|
||||
5. Package ownership;
|
||||
6. 完整 item/write/execution-plan coverage。
|
||||
|
||||
任何 fence 漂移都必须整体回滚。相同 generation、相同 receipt 是 exact replay;同一
|
||||
generation 绑定不同 receipt 是 conflict。
|
||||
|
||||
### 4. Task ownership 是长期数据库事实
|
||||
|
||||
双方言新增 `plugin_package_task_ownerships`,以
|
||||
`Project + taskId` 为主键并保存 `packageName`、首次 claim generation digest 与时间。
|
||||
ownership 不随 disable、upgrade 或安装历史回收而删除。
|
||||
|
||||
首次 create 必须在创建 Task head 的同一事务 claim ownership;后续只有相同 Package
|
||||
可以更新。其他 Package、人工 publisher 或通用 Task repository 不得接管。SQLite 和
|
||||
PostgreSQL 的通用 TaskDefinition append 入口都在事务内拒绝已被 Package claim 的
|
||||
Task,避免绕过专用 publisher。
|
||||
|
||||
### 5. SQLite 使用一个 `BEGIN IMMEDIATE`
|
||||
|
||||
SQLite 新增:
|
||||
|
||||
- `QingLong3PluginPackageTaskOwnerships`;
|
||||
- `QingLong3PluginPackageTaskReconciliations`;
|
||||
- `QingLong3PluginPackageTaskReconciliationItems`。
|
||||
|
||||
`0047-plugin-package-task-reconciliations` 安装三表、索引、CHECK、FK 和 owned trigger;
|
||||
`0048-capability-v24` 把 local capability 推进至 v24。catalog 当前为 43 张 owned
|
||||
table。
|
||||
|
||||
repository 复用既有单 operation authority,在一个 `BEGIN IMMEDIATE` 中完成:
|
||||
|
||||
- active generation 与上一代 receipt 复验;
|
||||
- Task head/revision CAS;
|
||||
- command Task 的 local execution revision;
|
||||
- ownership claim;
|
||||
- receipt 和 item 明细。
|
||||
|
||||
事务中任一步失败都不得留下 Task、execution plan、ownership 或 receipt 的部分状态。
|
||||
|
||||
### 6. PostgreSQL 只允许 Package executor 调用受审函数
|
||||
|
||||
PostgreSQL `pg-0026-plugin-package-task-reconciliations` 增加同义三表,并把
|
||||
`control-core` capability 推进至 v25;migration stream 为 26 条,catalog 为 41 张表。
|
||||
|
||||
`ql3_package_executor` 没有对 Task head/revision、execution revision、ownership 或
|
||||
receipt 表的原始 INSERT/UPDATE/DELETE authority。唯一写入口是:
|
||||
|
||||
```sql
|
||||
ql3.commit_plugin_package_task_reconciliation(
|
||||
char(64), char(64), jsonb, jsonb, jsonb
|
||||
)
|
||||
```
|
||||
|
||||
该 `SECURITY DEFINER` 函数固定 `search_path`、复验 `session_user` 属于
|
||||
`ql3_package_executor`、锁定 active install/Task heads,并在一个数据库事务内执行与
|
||||
SQLite 同义的 fence、CAS、ownership、execution revision 和 receipt 提交。
|
||||
|
||||
runtime、admin、package-manager、worker-ingress、PUBLIC 均无函数执行权和新表写权;
|
||||
manager 不能把公开管理请求提升为 execution authority,常驻 runtime 也不能直接发布
|
||||
Package Task。
|
||||
|
||||
### 7. 当前只关闭 TaskDefinition 发布缺口
|
||||
|
||||
本 ADR 不注册 Tool handler,不激活 Workflow/Prompt,不绑定 Secret,也不把
|
||||
materialized revision 自动接入生产启动。生产 coordinator 仍须按以下顺序显式装配:
|
||||
|
||||
1. 读取 active generation;
|
||||
2. 精确读取 immutable materialized revision;
|
||||
3. 调用专用 reconciliation repository;
|
||||
4. 再次观察 active generation;
|
||||
5. 只有 receipt 与当前 generation 一致时才允许后续 consumer admission。
|
||||
|
||||
在 coordinator、startup recovery 与用户可见状态完成前,该能力保持显式 subpath、
|
||||
默认不可达。
|
||||
|
||||
## Profile 影响
|
||||
|
||||
- edge/standalone:没有后台 reconciliation;每次显式安装/恢复只使用一个 SQLite
|
||||
writer transaction。未变化 Task 不新增 revision,适合低性能路由设备。
|
||||
- cluster:多个 executor 可竞争,但数据库锁、CAS、ownership 和 generation receipt
|
||||
使同一代只产生一个结果。executor 无原始表写权限。
|
||||
- worker:不导入 planner/repository,不读取 receipt,不取得 Package 发布 authority。
|
||||
|
||||
## 被否决方案
|
||||
|
||||
1. **为 planner、receipt 或双方言 adapter 分别新建 package**:没有独立生命周期,
|
||||
会继续把 `packages/` 拆成单文件包;现有 package 的显式 subpath 已满足隔离。
|
||||
2. **逐 Task 调用通用 repository**:一代中途失败会产生部分可见状态,也无法原子保存
|
||||
generation receipt。
|
||||
3. **删除 upgrade 中移除的 Task**:会破坏历史 Run/execution/audit 引用;禁用新
|
||||
revision 保留审计连续性。
|
||||
4. **以 namespace 字符串代替 ownership 表**:字符串约定不能阻止通用 publisher 或
|
||||
并发 Package 抢占。
|
||||
5. **给 executor 原始表写权限**:应用层校验可被绕过,无法证明 item/write/receipt
|
||||
同成同败。
|
||||
6. **把 Task revision 直接嵌入 materialized revision 当作已发布**:语义事实不等于
|
||||
当前 Task head,也不能给 scheduler/executor 提供既有 CAS 和 execution revision。
|
||||
|
||||
## 验证
|
||||
|
||||
- runtime-core:两代 create/retain/update/disable 规划、receipt digest、完整 coverage、
|
||||
ownership collision、head drift 和确定性 mutation identity;
|
||||
- SQLite:真实 `DatabaseSync` 共享 contract、exact replay、第二代 retain/disable/create、
|
||||
active generation 漂移整体回滚、通用 Task publisher 旁路拒绝;
|
||||
- PostgreSQL 18.4 arm64 真库:26 条 migration 后两代 reconciliation 与 exact replay
|
||||
通过,完整集成测试 34 pass、0 fail、1 个环境能力相关 skip;
|
||||
- PostgreSQL package:146 pass、0 fail、1 个真库条件 skip;
|
||||
- PostgreSQL physical HA:timeline 1→2、`remote_apply`、旧主先 fencing、standby
|
||||
promotion、旧主 `pg_rewind` 只读重入以及 promotion 前后 package-executor v25
|
||||
readiness/ACL 均通过,最终 `gates.passed=true`。
|
||||
|
||||
上述 HA 结果证明 schema、函数 identity 和最小权限契约可随 WAL/promotion 保持 ready,
|
||||
但本轮没有在分区或 COMMIT-response-loss 窗口中提交 reconciliation receipt,因此不能
|
||||
宣称已经取得 Task reconciliation 事务级故障注入证明。
|
||||
|
||||
## 后续
|
||||
|
||||
1. 实现唯一 production materialization coordinator 与 bounded startup recovery;
|
||||
2. 把 reconciliation receipt 纳入 PostgreSQL HA 的 COMMIT-response-loss 与 promotion
|
||||
durable inspection matrix;
|
||||
3. 建立 immutable Tool registry generation snapshot;
|
||||
4. 建立 Workflow/Prompt 版本仓库和 activation contract;
|
||||
5. 在 Run/execution 引用图完整后设计 Package Task 与 materialized revision 的
|
||||
retention/GC;此前禁止删除 ownership、receipt 或历史 revision。
|
||||
Reference in New Issue
Block a user