feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,177 @@
# ADR-0150:有界 Plugin Package 语义物化
- 状态:Accepted(纯领域物化、POSIX staging reader 与 Cluster OCI reader 已实现;
ADR-0151 已实现 SQLite/PostgreSQL immutable revision repositoryTask 批量发布与
全局 Tool snapshot 尚未实现)
- 日期:2026-07-25
- 关联:ADR-0091、ADR-0132 至 ADR-0135、ADR-0149、QL-RFC-0001
D-90/D-130/D-131/D-133/D-144
## 背景
ADR-0149 已经让本地 pointer rename 与 Kubernetes ConfigMap CAS 原子发布一份
`PluginPackageResourceGeneration`。它能回答“哪个 Package 的哪一代、哪些路径当前
生效”,但不能回答:
- 每个路径采用什么格式;
- Task、Workflow、Prompt、Tool 如何规范化;
- Package 内引用和已审批权限如何复验;
- staging/OCI 的实际字节怎样与 generation content tree 对账;
- 路由设备如何避免扫描、watcher 和一次读入 64 MiB bundle
- Cluster 多副本怎样得到相同的不可变语义,而不是各自动态注册。
若 consumer 直接把 JSON/YAML 交给 Task repository 或 Tool registry,它会在资源之间
产生部分发布;若由 pointer publisher 顺便解析,又会把字节发布、业务语义和执行
authority 合并。
## 决策
### 1. 语义契约继续留在 runtime-core subpath
新增
`@qinglong/runtime-core/plugin-package-resource-materialization`,不新增 workspace
package、第三方依赖、数据库、timer、watcher、socket 或动态 import。它只接收:
- ADR-0149 的 active generation
- 与 generation 精确匹配的完整 `PluginPackageLock@v2`
- lock 摘要绑定的 canonical `package.json`
- 一次 caller-owned byte session 顺序读取的 exact resource bytes
- 受信 composition root 提供的不可变 TaskSpec semantic registry。
物化前后各观察一次 active generation;中途发生 upgrade、disable 或 pointer 漂移时
失败关闭。读取 session 必须显式 `open → read → close`,实现不得在 close 后保留
authoritative cache、watcher 或 timer。
### 2. v1 资源只接受严格 UTF-8 JSON
四类文件必须位于 Manifest/generation 已锁定的路径,文件名以 `.json` 结尾,每个最大
1 MiB,全部业务资源合计最大 8 MiB:
- `qinglong/plugin-package-task-resource@v1`
- `qinglong/plugin-package-workflow-resource@v1`
- `qinglong/plugin-package-prompt-resource@v1`
- `qinglong/plugin-package-tool-resource@v1`
JSON 只负责作者输入;物化结果按核心规范化,不要求作者手工排序 object key。输入必须
是严格 UTF-8、exact shape、无未知字段。每项保存实际 source bytes 和 SHA-256,全部
entry 再按 path 重算 ADR-0135 content tree,必须与 generation/lock 一致。
### 3. Task v1 只开放既有 command 语义
Task 资源提供 package-local id、name、description、labels、enabled、kind 与 spec。
核心生成稳定 `pkg:{packageName}:{id}` Task identity,并通过 ADR-0091 的同一
`TaskSpecSemanticRegistry` 规范化。
首版只接受 `kind=command``qinglong/command@v1`,且 Manifest 必须已审批
`system.command`。Package Secret requirement 目前只有声明,没有 Project SecretRef
绑定 ceremony;因此含 secret environment 的 Package Task 必须失败关闭,不能把
bundle 中写死的 SecretRef 当作已审批绑定。
物化层只输出 `PluginPackageTaskDefinitionDraft`。它不逐项调用
`appendTaskDefinitionRevision`,因为当前单项 Repository 无法证明一代 Package 的
多 Task 原子可见。
### 4. Workflow 与 Prompt 是可审计定义,不冒充执行引擎
Workflow v1 最多 128 个 step。step id 唯一,`needs` 必须引用同 Workflow step
图必须无环;`task` 只能引用同一 Package generation 中存在的 Task id。首版不允许
跨 Package、current/latest、任意 Tool/Prompt 动态引用。
Prompt v1 只提供 text template 和最多 64 个参数;template 最大 512 KiB,声明参数
`{{name}}` placeholder 必须 exact 一致。它不选择模型、不读取 Secret、不调用
Tool,也不声称已经存在 Prompt executor。
### 5. Tool 只形成 Definition,不注入 handler
Tool 文件包裹 ADR-0133 的 exact `ToolDefinition`
- name 必须以 `{packageName}.` 命名空间开头;
- Package 内 identity 不得重复;
- required Project permission 只允许映射到 Manifest 已审批的
artifact/run/secret/task 权限;
- 一代 Package 最多 128 个 Tool,继续服从全局 immutable registry 上限。
物化层输出 `ToolDefinition` 供后续受信 composition 使用,不接受 handler、execute、
module path 或 runtime register。Definition 存在不等于 Tool 可执行。
### 6. revision 自包含且不成为第二个 active pointer
`qinglong/plugin-package-materialized-revision@v1` 完整保存:
- active generation
- immutable lock
- canonical Manifest 与 Manifest digest
- 与 generation 一一对应的 source bytes/digest 和规范化资源;
- domain-separated `revisionDigest`
normalizer 重验 generation↔lock、Manifest↔lock、Manifest↔resource references、
source descriptors↔content tree、Package 引用、权限和 revision digest。revision 以
`generationDigest` 为 immutable key;未来 repository 只允许 create/exact replay。
consumer 仍先读 active generation,再找同 generation 的 revision,不引入第二个
“current”指针。
本 ADR 定义 repository portADR-0151 已在后续实现 SQLite/PostgreSQL durable
store。跨 Package 全局 Tool snapshot 与 Task/Workflow/Prompt 发布事务仍未完成。
### 7. 两种 Profile 使用不同 byte adapter、共享同一语义
本地 `@qinglong/local-admin/package-resource-materialization`
- 一次打开 owner-only 0700 staging generation
- 一次解析最大 64 KiB receipt
- 验证目录 device/inode、0600 no-follow blob、exact inventory、bytes/digest
- 每个 path 最多读取一次,close 后丢弃 session 元数据。
Cluster 复用
`@qinglong/cluster-admin/plugin-package-oci-stage` 的 allowlisted HTTPS、exact registry
credential、Manifest/config/referrer signature 与 canonical bundle inspector。同一
OCI layer 只流式取得一次,sink 最多保留 8 MiB 目标资源,并在 reader close 时清理
未消费 Buffer。它不把 resource reader 接入常驻 `cluster-control`
## Profile 影响
- edge/standalone:只有显式物化请求才打开 staging;没有目录扫描、后台线程或新
数据库连接。8 MiB 是单次业务资源输入硬上限,不是常驻保留目标。
- cluster:每次短生命周期 admin materialization 重新验证 digest-pinned OCI source
多副本可以竞争未来 immutable revision create,但不能覆盖 active pointer 或注入
进程内动态 registry。
- worker:不导入管理 byte adapter;未来只消费已发布、与 execution revision 绑定的
结果。
## 被否决方案
1. **为 materializer 新增 workspace package**:没有独立部署、权限或依赖生命周期,
会继续把 `packages/` 拆碎。
2. **按路径逐项注册 Task/Tool**:中途失败会让同一 generation 部分生效。
3. **在 active pointer 中嵌入解析结果**:会突破 ConfigMap/路由器 pointer 预算,并让
pointer publisher 获得业务语义 authority。
4. **运行时扫描 staging 或 watch ConfigMap**:扫描不是审批事实,watcher 又制造常驻
资源和 stale cache。
5. **Package 自带 JS handler 或 dynamic import**Definition 会变成控制面代码注入。
6. **现在发明 SecretRef 模板替换**:没有安装绑定审批、rotation 与审计 ceremony
会把字符串替换误写成安全 Secret authority。
## 验证
- runtime-core:四种 schema、Task command registry、Prompt parameter、Workflow DAG/
引用、Tool namespace/permission、source/content/revision digest、strict UTF-8、
active generation 双观察与 root/subpath 隔离;
- local-admin:真实 0700/0600 stage、单 session exact read、重复/越界、blob tamper、
unknown inventory 和 close
- cluster-admin:同一受信 OCI inspector 的资源 capture、lock source、exact read、
digest/allowlist/credential 既有负向回归;
- ADR-0151SQLite/PostgreSQL create/exact replay、损坏数据 fail-closed、双方言
schema/readiness/ACL、真实 PostgreSQL 18.4 与 physical HA
- architectureworkspace importer 仍为 21,不新增第三方依赖或常驻 Profile root。
## 后续
ADR-0151 已实现以 `generationDigest` 为键的 SQLite/PostgreSQL immutable revision
repository 与 create/exact-replay contract。下一阶段分别设计:
1. Package TaskDefinition 多资源原子 reconciliation
2. 全部 active generation 的 immutable Tool registry snapshot
3. Workflow/Prompt 独立版本仓库和执行器;
4. Package Secret requirement 到 Project SecretRef 的强认证、可审计绑定 ceremony。
在这些 Gate 完成前,物化结果可验证但仍不进入生产执行路径。