feat(cordis): 完成阶段5访问介导与诊断
This commit is contained in:
+59
-4
@@ -1,6 +1,6 @@
|
||||
# ShrinkSDK × Cordis 组织形式改造方案
|
||||
|
||||
> 生成日期:2026-08-16
|
||||
> 生成日期:2026-08-16;独立重读与阶段 5 路线更新:2026-08-17
|
||||
> 参考文献:《Cordis: A Programming Paradigm for Spatiotemporal Composability》(北京大学 / DeepSeek-AI,88 页,`C:\Users\im\Downloads\Cordis_paper_zh-CN.pdf`)
|
||||
> 本文档回答一个问题:**如果按 Cordis 的"时空可组合性"范式重组 ShrinkSDK,目标形态是什么、差距在哪、如何分阶段走过去。**
|
||||
> 现状基线见仓库根目录 `DESIGN.md`。
|
||||
@@ -70,6 +70,19 @@
|
||||
8. **跨领域集成组件不是过渡瑕疵,而是论文 §6.5 的正式答案**。Command-Network、模块-EventBus 这类双向/循环关系应由一个注入双方服务键的薄组件承载,核心包保持互不依赖。真正应淘汰的是隐式反射接桥和安装器包装,不是所有 Integration 包。
|
||||
9. **字符串键仍有碰撞与接口漂移风险**。当前先使用命名空间化键;后续应把包版本约束、结构兼容检查或强类型生成键纳入加载器边界。
|
||||
|
||||
### 1.6 对 ShrinkSDK 的工程判断
|
||||
|
||||
综合论文第 3~6 节与当前实现,我对 Cordis 在 ShrinkSDK 中的定位是:
|
||||
|
||||
1. **它应当是生命周期与组合语义的唯一地基,不是新的业务框架。** EventBus、DataSaver、Network、Command、Tutorial 仍然保留自己的领域 API;Cordis 只负责回答“谁拥有这些副作用、依赖变化时谁该运行、组件退出时如何恢复”。后续不能再新增第三套启动/卸载模型。
|
||||
2. **阶段 0~4 已经覆盖论文最关键的正确性路径。** 当前 `ShrinkContextRuntime` 已具备 provider uid、committed view、惯性转换、部分回滚和 drain-before-inverse;`ShrinkModContextHost` 已把外部 DLL 的组件源、revision 缓存与旧组合恢复纳入同一事务。接下来主要是把这些保证变得可约束、可诊断、可运营,而不是重新实现 fiber。
|
||||
3. **当前最大语义缺口是“声明没有被完全强制”。** `IShrinkComponent.Provide` 目前仍主要依赖作者纪律,运行时没有拒绝组件写入未声明键;字符串键也只提供名义连接,没有类型和版本兼容保证。若不先固定访问契约,intercept 只能成为一层不可靠的包装。
|
||||
4. **当前最大工程缺口是“发生问题时看不见”。** fiber 已有状态和 `LastError`,但缺少稳定的运行时快照、事务阶段、依赖等待链和 revision 常驻统计。动态组合系统一旦发生等待、回滚或程序集常驻增长,必须能从诊断面直接回答原因。
|
||||
5. **intercept 是访问介导,不是安全沙箱。** 它适合表达“社区模组只能只读 DataSaver”“某组件不能访问某类网络能力”等宿主可控策略;但外部 DLL 仍可绕开 ctx 直接调用 CLR/Unity API。不可信代码必须另用进程、WebAssembly 或其他执行隔离,不能把语言层访问控制写成安全边界。
|
||||
6. **程序集不可卸载必须转化为容量策略。** Mono 下 revision 替换只能撤回实例和效应,旧 `Assembly` 仍然常驻。正确做法不是伪装成完全卸载,而是统计历史 revision、估算常驻量、设阈值并给出重启建议。
|
||||
|
||||
因此,阶段 5 的顺序应为:先收紧访问契约和诊断,再实现 isolate/intercept,之后补程序集常驻策略和配置/调试工具。这样后续能力建立在可验证的边界上,而不是继续扩大隐式行为。
|
||||
|
||||
---
|
||||
|
||||
## 2. 概念对照:Cordis ↔ ShrinkSDK 现状
|
||||
@@ -247,8 +260,50 @@ await loader.ApplyConfigAsync(configTree); // 增量协调:diff → reload/u
|
||||
- 真实 fixture 验收覆盖:编译 DLL `valid → changed(fail) → restore`、损坏字节不污染当前 revision、有效 revision 恢复、watcher burst 去抖、删除卸载、依赖 DLL 删除/恢复。`ShrinkModFramework.Tests` **9/9**,全仓 EditMode **180/180**。
|
||||
- 真实 Starter PlayMode 确认 `modCordis=true`、`modLoaded=true`、宿主 7 个模块 active 且无错误。Unity 程序集不可卸载,因此回滚单位仍是组件实例与效应,而不是类型本身。
|
||||
|
||||
### 阶段 5:隔离与拦截(可选增强)
|
||||
- 测试域 isolate(同一份组件在多个隔离域各跑一份);intercept 做访问控制(社区模组只读 DataSaver)。
|
||||
### 阶段 5:生产化边界、隔离与拦截(进行中,2026-08-17 启动)
|
||||
|
||||
#### 阶段 5A:访问契约、诊断与通知索引 ✅ 首批完成(2026-08-17)
|
||||
|
||||
- 运行时强制组件只能向 `Provide` 声明的键写入;根上下文的 ambient 绑定保留为显式系统边界。
|
||||
- 提供稳定的 runtime/fiber 诊断快照:uid、组件名、状态、target、committed provider、realm、是否退役、是否转换中、最近错误。
|
||||
- 提供依赖等待关系与加载器事务诊断,使失败能定位到条目、fiber、阶段和恢复结果。
|
||||
- 将 notify 从遍历全部 fiber 改为 `key → inject fibers` 倒排索引;realm 仍在触发时精确过滤,复杂度由 O(all fibers) 收敛为 O(affected-by-key)。
|
||||
- 强类型/版本键以新增契约逐步引入,不在本阶段强行改写全部现有字符串键调用点。
|
||||
|
||||
**验收:** 未声明供给在 apply 阶段被拒绝并完整回滚;诊断快照能解释 Active/Waiting/Failed/Unloading;索引不会遗漏不同 realm 下的合法依赖者;既有生命周期测试全部保持通过。
|
||||
|
||||
**已落地:** `Provide` 写入约束、`ShrinkKey<T>` 版本键、runtime/fiber/依赖/notify 诊断快照、loader 事务与恢复结果、`key → inject fibers` 倒排索引均已实现。target 仍是 provider uid 视图,但现在保留 inject 声明顺序和重复键,不再退化成无序 provider 集合。
|
||||
|
||||
#### 阶段 5B:isolate 隔离验证与 intercept ✅ 首批完成(2026-08-17)
|
||||
|
||||
- loader 支持隔离域条目;同一组件在多个 realm 中独立运行,替换其中一个 realm 的提供者不扰动另一个 realm。
|
||||
- 补 `ctx.intercept(key, metadata)` 的派生上下文与元数据合并;策略改变依赖的使用方式,不改变满足关系,也不因策略变化触发 fiber 重载。
|
||||
- 访问介导使用明确的服务策略/包装接口,不把 Harmony 或通用反射 AOP 当成默认实现。
|
||||
- 以“社区模组只读 DataSaver”为真实验收:读取允许,写入拒绝,核心组件仍保留完整能力。
|
||||
|
||||
**验收:** 多 realm 激活/替换/卸载互不串扰;intercept 更新不改变 provider uid 和 fiber generation;未声明访问、未激活访问与策略拒绝三类错误可以区分;文档明确其不是不可信代码沙箱。
|
||||
|
||||
**已落地:** loader 条目可携带 isolate 与 intercept;intercept 元数据按上下文链合并并在条目原位更新,不触发 fiber 重载。DataSaver 提供 `Reader / Writer` 能力拆分,社区上下文可取得只读包装,写接口与具体服务请求被策略拒绝。当前 isolate 条目变化仍通过重建该条目生效;运行中 fiber 原位迁移 realm 未实现,也不计入本批完成项。
|
||||
|
||||
#### 阶段 5C:外部 DLL 常驻 revision 策略 ✅ 首批完成(2026-08-17)
|
||||
|
||||
- 暴露当前 revision、历史程序集数量、来源路径与累计载入字节。
|
||||
- 增加软阈值和明确告警;超过阈值时建议 Domain Reload/进程重启,不尝试在 Mono 上伪造程序集卸载。
|
||||
- 长时间回归覆盖连续有效替换、失败恢复、损坏 DLL、删除/恢复与历史 revision 增长。
|
||||
|
||||
**验收:** 每次替换后当前 revision 与生效组件一致;失败 revision 不成为 current;常驻增长可查询、可告警且不影响旧组合恢复。
|
||||
|
||||
**已落地:** `ShrinkModDiagnostics.CaptureExternalAssemblies` 暴露 current/history、路径、程序集、revision、载入字节与软阈值状态;达到 `externalAssemblyRevisionSoftLimit` 时只给出 Domain Reload/进程重启建议。真实 DLL fixture 覆盖有效、失败、再有效三个 revision,确认失败程序集可以常驻但不会成为 current。
|
||||
|
||||
#### 阶段 5D:配置与调试体验
|
||||
|
||||
- 将代码构建的默认组合逐步映射到 ScriptableObject/JSON 条目,并保持代码目录作为组件工厂来源。
|
||||
- 提供 Editor/运行时调试面,查看 active/waiting/failed fiber、provider target、最近事务和常驻程序集统计。
|
||||
- 建立 notify、重载延迟、失败恢复和常驻内存的基准,避免仅以功能测试替代容量判断。
|
||||
|
||||
**阶段 5 明确非目标:** 不在本阶段实现不可信 DLL 沙箱;不承诺已发出的网络数据或外部文件写入可以真正撤回;不删除 ClassicHost 兼容面,除非其调用方已完成独立迁移验证。
|
||||
|
||||
**2026-08-17 验证基线:** Unity 编译 **0 error / 0 warning**;全仓 EditMode **189/189**;PlayMode Test Runner 当前没有测试项,因此另行启动真实 `Assets/Scenes/ShrinkAppEntry.unity` 验收:7 个模块全部 Active、0 Waiting、10 个绑定、3 个 notify 索引键,启动与退出过程无控制台 error。阶段 5D 的配置资产、调试面与容量基准尚未开始。
|
||||
|
||||
---
|
||||
|
||||
@@ -268,4 +323,4 @@ await loader.ApplyConfigAsync(configTree); // 增量协调:diff → reload/u
|
||||
- ShrinkSDK 与 Cordis 的**分层直觉一致**(核心库 / 编排层 / 领域层),差距集中在**核心库的两个原语缺失**:统一可逆效应追踪(时间)与响应式依赖解析(空间)。
|
||||
- 改造的本质不是重写功能模块,而是**把 ShrinkApp 的"一次性安装器"升级为 Cordis 的"持续协调的组件加载器"**,并让七个 Integration 桥接包退化为薄适配直至消失。
|
||||
- Unity 的"程序集不可卸载"不阻塞该范式——可回滚单位是组件实例与效应,而非类型;这与 ModFramework 既有边界声明兼容。
|
||||
- 阶段 0-4 已完成到 Basic Starter 的默认运行主路径与 ModFramework 事务性 HMR;后续若继续推进,应进入阶段 5 的 isolate/intercept 能力或围绕程序集常驻做容量与运维策略,不再新增第三套生命周期。
|
||||
- 阶段 0-4 已完成到 Basic Starter 的默认运行主路径与 ModFramework 事务性 HMR;阶段 5 已完成访问契约、诊断/notify 索引、isolate/intercept 首批能力和程序集常驻策略,下一步是阶段 5D 的配置、调试面与容量基准,不再新增第三套生命周期。
|
||||
|
||||
Reference in New Issue
Block a user