Files
qinglong/docs/adr/ADR-0321-plugin-package-install-domain-ownership.md
T

108 lines
7.9 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-0321Plugin Package Install 领域归属与 Package/Module 粒度
- 状态:Accepted
- 日期:2026-08-10
- 关联 RFCQL-RFC-0001 D-05、D-06、D-17、D-87、D-257
- 关联 ADRADR-0087、ADR-0267、ADR-0276、ADR-0295、ADR-0303、ADR-0312、ADR-0316、ADR-0317
## 背景
QingLong 3.0 曾把 use case、authority 和 adapter 都默认表达成 workspace package,最多达到 32 个 importer。连续
收敛后当前只剩 16 个 package,并由 hard cap 禁止无决策地增长。当前 818 个 TypeScript source 中只有 25 个位于
`src/` 根层、793 个位于领域目录;`singleSourcePackages=[]``shallowSourcePackages=[]`。因此现阶段的主要问题
已经不是“每个文件一个 package”,而是少数 package 内的大文件仍混合多种 ownership。
`@qinglong/runtime-core``pluginPackageInstall.ts` 就是这类问题:原 2,586 行同时拥有公开 schema/repository port、
严格 codec、manifest/source/approval lock、install record/receipt、transition/event 和 repository command/pagination。
这些职责共享一个公开 subpath,但演进原因并不相同,继续平铺会迫使任一修改触碰整份安装协议。
编辑前 GitNexus impact 已逐 symbol 执行并告警:`InvalidPluginPackageInstallError`
`PluginPackageInstallTransitionConflictError``PluginPackageInstallUnavailableError` 为 CRITICAL
`InvalidPluginPackageLockError``PluginPackageInstallMutationConflictError``exactKeys``contentDigest`
`normalizePluginPackageLock` 为 HIGH。最高累计上游为 147,相关安全校验进入 3 条执行流程。因此本轮只移动
ownership,不重写 schema、digest、transition 或 repository 语义。
## 决策
### 1. Package 与内部 module 使用不同判据
workspace package 只表达至少一项真实边界:独立部署/发布或 binary、不同 authority、生产依赖隔离、可替换 adapter、
至少两个 production consumer 的稳定 contract,或独立供应链/版本责任。一个 use case、一个文件、一个 class 或一个
未来可能复用的猜测都不能单独创建 package。
package 内部的领域目录表达共同变化的 ownership。`src/` 根层只允许受审 public facade、public export 或 binary entry
实现下沉并不意味着“一函数一文件”,共享同一状态机、事务或安全协议的代码必须保留在一起。文件数和 LOC 只触发
评审,不能代替 dependency、authority、consumer 和 artifact closure 证据。
### 2. Plugin Install 保持一个 package、一个 public subpath
不新增第 17 个 package,不新增公共 subpath。原入口收敛为 32 行纯 facade,内部按职责形成:
```text
plugin-package/installation/
├── pluginPackageInstall.ts # 稳定 public facade
└── plugin-package-install/
├── contracts.ts # schema、type、repository port、error identity
├── codec.ts # strict validator、canonical digest primitives
├── lock.ts # manifest/source/approval/plan/lock
├── record.ts # install record、failure、activation receipt
├── transition.ts # event、state transition、commit
└── repository.ts # create command、pagination/cursor、recovery action
```
`pluginPackageInstallCreate` 与 create command/cursor 一起归 repository,避免 transition 反向依赖 repository
transition 只拥有状态机与 commit。所有原公开 export 仍从同一 subpath 暴露,27 个公开 error/function export 与 owning
module 是同一个 runtime object,保持 `instanceof`、函数 identity 和调用路径不变。
### 3. 薄 package 不按文件数机械合并
当前较薄边界仍必须用真实拓扑解释。例如 `local-command-file` 只有 2 个 source,但被 Application、Owner CLI 和
Maintenance 三个生命周期闭包共同复用;`local-secret` 被 3 个 production package 复用并持有密文/keyring authority
`local-owner-maintenance` 虽只有 6 个 source,却是不得进入常驻 Profile 的独立 destructive binary。若这些条件消失,
再新增 ADR 合并;不能仅为了减少 package 数破坏权限或制品防火墙。
## 小设备与集群影响
最小 Edge/Standalone 仍只加载 49 个模块,AI 基础档仍为 50,说明包内拆分不会使路由设备加载未 import 的能力。
Application 档真实使用 Plugin Install public subpath,因此从 ADR-0320 的 110/109 增至 116/115 个 loaded modules
这是 6 个职责模块的可观测成本,不隐藏为零。最大实测 RSS delta 仍低于 24 MiB Application 门限,所有 pack/file/RSS
预算 compatible。
Cluster 仍通过同一个 Runtime Core contract 使用 PostgreSQL adapter;没有新增 dependency、数据库连接、进程、timer、
listener、部署单元或角色。此次不改 SQL、migration、PostgreSQL/Cluster runtime 和部署资源,因此不重复 PostgreSQL
HA Docker 门。
## 被否决方案
1. **六个职责各建一个 workspace package**:没有独立部署、依赖或 consumer closure,拒绝。
2. **只保留 2,586 行单文件**:公开 contract、codec、状态机与 repository 继续共同变化,拒绝。
3. **每个 schema/function 一个文件**:制造导航噪声并拆断状态机协议,拒绝。
4. **按 LOC 自动合并所有薄 package**:会把 destructive、secret 或 adapter authority 带入错误制品,拒绝。
5. **用动态 import 隐藏 Application module 增量**:会改变同步 contract 与失败面,且当前资源预算没有要求,拒绝。
## 验收证据
- facade 2,586→32 行;contract 361、codec 202、lock 930、record 560、transition 397、repository 295 行。
- 27 个公开 error/function export 的 facade/owner runtime identity 全部相同;Runtime Core 445/445。
- 完整 16-package clean topology build/test 在允许 loopback TLS 与 crash 子进程的门环境最终退出 0;AI 为
209 pass/3 skipOwner CLI 134/134Application 40 pass/3 skip。沙箱内 Worker 的 3 个 `listen EPERM` 明确归因于
环境禁止 `127.0.0.1`,不是产品失败。
- package boundary 为 16 package、818 source、25 root、793 nested`singleSourcePackages=[]`
`shallowSourcePackages=[]`、findings 为空;Runtime Core 为 119 source、1 root/118 nested。Edge import、Cluster
dependency 和 Cluster deployment 均 compatible。
- Edge/Standalone 为 3,636,968/3,637,004 bytes、337 files、49 modulesAdopted 为
4,247,060/4,247,120 bytes、382 files、50 modulesApplication 为 4,744,909/4,745,029 bytes、441 files、
116 modules。AI 基础档为 5,032,279/5,032,327 bytes、416 files、50 modulesApplication AI 为
6,140,286/6,140,418 bytes、520 files、115 modules。十档全部 compatible。
- 强制重建后的 GitNexus 为 43,999 nodes/100,193 edges/1,726 clusters/274 flows。post-impact 中公开 install error
为 CRITICAL82 direct/146 total),`normalizePluginPackageLock` 为 CRITICAL15/41、2 flows),`exactKeys`
为 HIGH20/70、3 flows),record normalizer 为 HIGH13/24),transition 为 MEDIUM5/7),repository create
为 LOW(1/1);高风险关系没有因换文件消失。`detect_changes` all/compare `develop` 仍只映射已跟踪 Legacy
baseline 的 12/31 与 14/34、low/0 process,未跟踪 QL3 孵化树不能用该结果代替上述完整索引和测试证据。
## 后续约束
后续不以“package 少”或“文件短”作为完成标准。每轮优先审计仍同时混合 contract、codec、持久化和 coordinator 的实现,
保持 public facade 与 package 数稳定;纯 schema declaration 和共享同一事务/状态机的协议不机械拆分。若新增 package,
必须给出 deployment/authority/dependency/consumer/supply-chain 证据,并同步收紧或明确调整 16-package hard cap。