Repository navigation
Archive Plugin Composition 2026 09 CN
本页原样保留阶段说明、图示与当时证据;“当前”“待验收”等措辞均指原日期,不作为现版本覆盖声明。当前插件组合。
Note
当前实现与覆盖边界 · 2026-09-09 本页已由目标预览更新为源码事实说明。Root #2007 批准的有限组合链路已完成并通过集中验收;原图表达的通用插件平台愿景尚未全部实现。 不能把有限链路通过理解为所有接口、任意事件与前端贡献都已统一接入。
源码核对基线:ce355a56a4a3ec91acc627b5691daf06814c1225。已完成的集中测试绑定 2143c8d45676178b754376d6b8f4b552ad7a2b7d,不是当前整个提交的新一轮测试。本轮核对的多贡献清单、授权、受管装配、Hook 内核、事件交付和安装历史治理关键文件相对该测试候选未变。
Important
进程生命周期实现补充 · 2026-09-28:新增 第 9 节 和 Issue #2153。Host 按需启动、安全空闲回收、精确版本需求通知与异常退出证据闭环已实现;本机集中测试与真实90分钟客户端验收均通过,资源回收观察见第9.11节。此前“有限完成”与本轮验收分别记录。
| 原预期 | 当前判断 | 代码事实与边界 |
|---|---|---|
| HostExtension 与受管插件两种治理边界 | 已落地 | HostExtension 可信启动、随宿主重启;旧 RuntimeExtension / CapabilityPlugin 名称与输入分类保留 |
| 同包多贡献、逐贡献执行绑定 | 已落地 | v2 清单包含贡献声明与 execution_bindings,正式安装路径校验贡献与绑定;不等于所有贡献类型都有完整执行器 |
| 注册、依赖、数量、顺序与快照编译 | 已落地 | 复用类型化图、确定性拓扑排序和 Registry 快照;候选需权限与执行绑定就绪才能发布 |
| 权限不由插件自授 | 已落地 | 持久逐贡献授权、撤销和修订;宿主以当前授权检查执行,不能把 manifest 当 grant |
| 接口生命周期接入 | 有限完成 | 正式开放 model_definitions.create 的六个受管阶段;不自动开放所有接口 |
| 插件自行定义事件并相互订阅 | 有限完成 | 固定 Create → A → B/C 链;事件定义、发布者及部分数据权限仍有明确的宿主白名单 |
| 可靠通知、幂等、旧 ACK 拒绝 | 有限完成 | Outbox、逐订阅投递、独立 claim、幂等写入与回执事务;不保证任意外部服务 exactly-once |
| 升级、停用、精确恢复、旧资源退出 | 有限完成 | 新旧快照分开,冻结目标不可偷换;缺旧图或权限时暂停;积压会阻止清理 |
| 受管共享进程按需启动、空闲回收与崩溃续接 | 新方案待实施/验收 | 安装、版本引用、进程、逻辑会话和物理连接分别管理;见第 9 节 |
| 所有供应商、节点、前端组件走同一新总线 | 未完成统一接入验收 | 旧契约继续工作;存在声明类型不能证明已完成所有运行与前端挂载路径 |
| 新插件只声明、实现、安装,宿主无需按名字处理 | 尚未对任意贡献成立 | 受管事件仍检查 acme.composition-a 及 B/C 的固定契约,新增任意事件需要宿主扩展 |
| Rust native 反复热卸载、跨重启自动恢复所有旧处理器 | 不在本次完成范围 | HostExtension 仍按重启管理;无法重建旧执行身份时明确拒绝恢复 |
“有限完成”表示真实安装、授权、执行与故障场景已经闭合,并非只有接口占位;限制在于开放集合与验证范围。源码入口见第 8 节。
flowchart TB
HOST["HostExtension<br/>可信启动装配 · 重启边界"]
PKG["v2 受管包<br/>多贡献声明与逐贡献执行绑定"]
FACT["宿主持久事实<br/>安装 · 工作区分配<br/>逐贡献授权与撤销修订"]
GRAPH["Extension Bus<br/>类型 · 依赖 · 顺序 · 权限校验"]
PLAN["候选编译与完整发布<br/>Graph / Registry / 执行身份"]
HOOK["Interface Kernel<br/>当前受管入口:Create 六阶段"]
WORKER["RuntimeExtensionHost<br/>真实 SDK worker 与进程资源"]
EVENT["Outbox 与事件交付器<br/>当前链路:Create → A → B/C"]
DATA["业务 / PluginData 事务 owner"]
LEGACY["既有 Provider、节点与前端贡献<br/>各自契约继续工作<br/>不宣称全部迁入新受管总线"]
HOST --> GRAPH
PKG --> GRAPH
FACT --> GRAPH
GRAPH --> PLAN
PLAN --> HOOK
PLAN --> EVENT
HOOK --> WORKER
EVENT --> WORKER
EVENT --> DATA
LEGACY -. "Provider 等运行时能力" .-> WORKER
classDef control fill:#ccfbf1,stroke:#0d9488,color:#134e4a;
classDef execute fill:#dbeafe,stroke:#2563eb,color:#172554;
classDef legacy fill:#f1f5f9,stroke:#64748b,color:#0f172a;
class FACT,GRAPH,PLAN control;
class HOOK,WORKER,EVENT,DATA execute;
class HOST,LEGACY legacy;
本图表达当前职责,不要求增加独立总线服务或消息中间件。Extension Bus 协调声明、权限、绑定与快照;业务事务、子进程资源和持久投递仍各有真实 owner。
原来的三个名称仍有意义:HostExtension 表示可信宿主扩展;RuntimeExtension、CapabilityPlugin 保留各自既有分类和入口。新架构把贡献、执行方式和作用域分开建模,没有批量改写旧配置。
普通模型供应商继续使用 v1 manifest + 1flowbase.provider/v2。新受管多贡献包采用 v2 manifest 与 1flowbase.extension-bus/v1,两种版本不是互相替换的同一层协议。
正式包安装
→ 校验 module / contribution / execution binding
→ 分配工作区
→ 保存独立贡献的宿主授权
→ 编译候选图并准备执行绑定
→ 检查候选仍满足当前权限和版本
→ 完整发布有效计划
同一个包中,每项贡献有自己的处理器、执行绑定、所需权限和作用域。不能将贡献甲获得的权限并入贡献乙,也不能凭旧快照、旧 claim 或已入队事件恢复被撤销的权限。
当前清单也能表达节点、前端区块、依赖和数据模型等 payload 引用;清单能表达不等于任意组合已具备端到端运行证据。本次真实受管闭合以 Create Hook、声明式自有数据及 A/B/C 事件处理为主。
宿主提供独立的贡献授权查询、授予、撤销,以及执行状态、恢复和退休操作。它们使用各自 console operation;旧的配置权限不能代替这些治理权限。
当前正式受管入口是创建数据建模定义:
model_definitions.create
POST /api/console/settings/data-models/model-definitions
它不是大语言模型推理或供应商注册。该入口通过真实 HTTP / MCP 路径进入 typed Kernel,开放有限的受管输入视图。
flowchart TB
IN["协议入口与可信认证"]
FREEZE["解析并冻结调用计划<br/>Interface / Binding / Graph / Registry"]
POLICY["Authorization → Admission<br/>核心检查与扩展进一步否决"]
BEFORE["Before<br/>受管 Create:只读检查,可否决"]
BUSINESS["Dispatch → typed Handler<br/>主业务返回成功值或错误"]
AFTER["After:成功回调<br/>受管视图:model_id"]
FAILURE["Failure:拒绝或失败回调<br/>受管视图:classification"]
COMPLETE["适用 Completion<br/>接收终态,记录观察执行结果"]
OUT["保留主结果与 Receipt<br/>协议适配器另行投影响应"]
IN --> FREEZE --> POLICY
POLICY -->|"通过"| BEFORE
POLICY -->|"适用的拒绝路径"| FAILURE
BEFORE -->|"通过"| BUSINESS
BEFORE -->|"拒绝或失败"| FAILURE
BUSINESS -->|"Ok"| AFTER
BUSINESS -->|"Err"| FAILURE
AFTER --> COMPLETE
FAILURE --> COMPLETE
BUSINESS -. "取消 / 超时收尾" .-> COMPLETE
COMPLETE --> OUT
这是主要路径;认证失败、解析失败、取消时点与流式终态的适用规则见请求生命周期。不能推导为每个失败都执行所有 Hook。
| 阶段 | 何时使用 | 当前受管契约 |
|---|---|---|
| Authorization | 权限阶段 | 只能进一步否决,不能推翻核心拒绝 |
| Admission | 准入阶段 | 根据有限 Create 视图增加接纳约束 |
| Before | 主业务执行前 | 只读校验和否决,不允许 patch 请求 |
| After | 主业务返回成功值后 | 接收 model_id,观察成功结果 |
| Failure | 适用的拒绝或失败路径 | 接收失败分类;某些前置拒绝发生时主业务尚未执行 |
| Completion | 适用调用的最终收尾 | 接收终态,不是完整业务结果,也不是事务提交或客户端 ACK |
After / Failure 不负责决定主业务成败。 Kernel 先获得主业务的 Ok / Err,再调用对应回调;主业务结果与观察插件自身结果分别记录。创建成功而观察插件失败时,记录“业务成功、观察失败”,不能据此伪造业务回滚。
观察插件可返回 Observed 或 Failed;后者用于观察执行诊断,不改写主结果。After / Failure / Completion 共用有界收尾预算,错误、panic 或超时不替换主结果。流式调用由唯一 completion owner 等待真正终态并完成收尾,不能把流建立成功当成整个业务成功。
原图中 Before 的“有限输入修改”只是通用接口可能提供的能力,不适用于本次受管 Create;这里已改为实际的只读契约。
当前事件契约明确限定为:
-
model_definition.committed@v1:真实 Create 的提交事实。 -
acme.composition-a.processed@1:A 消费后发布的派生事实。 - B/C 的
apply_processed:消费派生事实并写入各自processed_models。
sequenceDiagram
participant T as Create 业务 owner
participant DB as PostgreSQL / Outbox
participant D as 交付器
participant A as 插件 A
participant BC as 插件 B 或 C
T->>DB: T1:业务变更、提交事实与冻结目标同事务
DB-->>T: 提交成功;原调用不等待订阅者完成
D->>DB: 领取 A 的独立投递 claim
D->>A: Create 事实与宿主绑定身份
A-->>D: 请求发布受限 processed 事实
D->>DB: T2:宿主校验当前授权后持久发布派生事实与目标
D->>DB: 分别领取 B、C 的投递
D->>BC: 派生事件、冻结处理版本和当前授权
BC-->>D: 返回受支持的自有数据效果
D->>DB: 消费事务:自有数据效果与幂等回执原子提交
D->>DB: 使用本次 claim 确认投递
Note over D,DB: ACK 丢失可重投;回执防止重复数据效果,旧 claim 不能确认新投递
B/C 各有独立投递记录,一个失败不要求重做另一个已完成的消费。T1 回滚不会产生可交付的提交事实;T2 是独立事务,不能宣称 A 的派生发布与此前 Create 同事务。
发布、订阅、插件自有数据写入分别校验权限。工作区、安装、贡献和因果关联来自宿主可信上下文;载荷限定为 model_id、status、result_reference 等受约束字段,不开放任意 SQL 或任意业务对象写入。
尚未开放任意插件事件。 当前 is_managed_composition_event、宿主授权策略和发布校验仍明确识别 A/B/C 的固定身份与契约。新事件名、载荷或消费者能力需要扩展宿主契约及装配,不能只改 manifest。
其他事件通道也有不同职责:同步 Hook 受当前调用等待;持久 Outbox 独立交付;运行时必需事件流保持背压;诊断通道允许有界丢弃并记录。进程内 AfterCommit lane 不替代持久 Outbox。幂等保证覆盖当前宿主事务中的效果,不延伸到任意外部服务。
flowchart TB
CHANGE["新安装 / 新版本 / 授权变更"]
CHECK["准备候选 G2<br/>校验权限、制品和逐贡献执行绑定"]
READY{"候选可发布?"}
KEEP["保留 G1<br/>返回阻塞原因"]
PUBLISH["完整发布 G2<br/>新调用使用新计划"]
OLD["旧调用与旧投递<br/>保留原图、处理器、版本和执行身份"]
VALID{"精确目标可用<br/>且当前授权允许?"}
RUN["按原目标完成或显式恢复"]
PAUSE["明确暂停并保留积压<br/>不切换到 latest"]
GC["引用和积压清空<br/>满足退休条件后回收"]
CHANGE --> CHECK --> READY
READY -->|"否"| KEEP
READY -->|"是"| PUBLISH
PUBLISH -. "不改写冻结身份" .-> OLD
OLD --> VALID
VALID -->|"是"| RUN --> GC
VALID -->|"否"| PAUSE
PAUSE -. "满足条件后显式恢复" .-> VALID
- 停用或撤权:阻止相应新执行,保留暂停的持久投递;重新启用或 grant 不自动 resume。
-
精确恢复:指定
event_id、subscriber_id及预期 graph / handler / version,重新校验目标与当前权限。旧 epoch 或图无法重建时拒绝恢复,不转交新版。 - 退休与删除:当前目标不能退休;冻结引用、真实执行与持久积压都有自己的 owner。无法证明积压清空时阻止清理,不能用分页展示的“空列表”代替安全检查。
-
同版本恢复:受管同一
plugin_id + version只接受原始归档字节一致的恢复。改内容、仅改 gzip 时间戳导致 checksum 不同,也不能覆盖原身份;缺可信历史 checksum 时拒绝。 - 历史归属:查询依据持久安装身份、作用域和冻结目标,不依赖当前 manifest 还列不列出旧贡献。未知 legacy 历史保守保留并阻止不安全清理。
- 关闭与资源回收:先停止交付器新批次,等待真实交付与业务执行 owner,再等待冻结引用和 worker 等资源。超时明确报告未完成,不删除数据库积压。
这不承诺 HostExtension 热切换,不承诺所有旧 handler 跨重启自动可用,也不包含数据库与文件系统跨进程崩溃的一体化恢复保证。
此处的引用与积压治理保护精确执行身份及制品,不应推导为每个物理进程必须始终常驻。共享 worker 的空闲回收与异常恢复是另一个资源闭环,实现与验收见第 9 节。
| 模型 | 当前落点 | 不应推导出的结论 |
|---|---|---|
| 微内核与声明式控制面 | 宿主契约、模块声明、图编译与执行 owner 分工 | 不是所有能力已统一成一条通用调用通道 |
| DAG 与确定性拓扑排序 | 编译器用入度和有序集合处理依赖;有环则拒绝 | 拓扑顺序不能自动消除业务副作用冲突 |
| 权限交集、进一步否决 | 核心拒绝不能被扩展 allow 恢复;逐贡献授权限制执行 | 不能把包声明或其他贡献的 grant 当权限来源 |
| 不可变快照、类似 RCU 的思路 | 保留旧 Arc 快照及冻结身份,完整发布新计划 |
不等于实现无锁 RCU,也不证明 native 库可卸载 |
| Transactional Outbox 与幂等消费者 | 提交事实、逐订阅投递、数据效果与回执事务 | 不保证外部服务副作用 exactly-once |
| Lease 与 Fencing | 每次领取独立 claim,过期 ACK 无法确认新 claim | 不意味着所有外部资源都已接入 fencing |
| 背压与有界资源 | 队列、并发、批次、历史查询及关闭等待有边界 | 没有负载测试就不能给出吞吐或稳定积压保证 |
Little 定律 L = λW
|
可用于稳定系统的容量分析 | 本次没有据此完成生产容量建模或性能验收 |
| 状态机与有限故障场景 | 有目标切换、撤权、重装、ACK 丢失等真实测试 | 有限测试不是穷尽模型检查;本轮未取得形式化证明证据 |
下列源码链接固定到本页核对基线,避免后续分支变化让图与依据失去对应关系。
| 要核对的机制 | 源码入口 |
|---|---|
| v2 多贡献与执行绑定校验 | managed_manifest.rs |
| 类型化图与拓扑编译 | compiler.rs |
| 插件事件定义的有限开放 | descriptor.rs |
| 宿主授权上限与固定事件范围 | contribution_authority.rs |
| 持久授权与修订 | plugin_contribution_authority_repository.rs |
| 候选发布与实际装配 | managed_activation.rs |
| Create 的有限 Hook 输入与插件结果 | managed_hook_contract.rs |
| 主结果分支与收尾 | invocation.rs |
| 派生事件发布及事务入口 | managed_event_publication.rs |
| Outbox 领取、确认、暂停与重试 | lifecycle_outbox_dispatcher.rs、lifecycle_outbox_repository.rs |
| 同版本安装身份准入 | plugin_installation_commit_repository.rs |
| 完整机制与资源边界补充 | 本地架构文档的源码副本 |
最终集中 CI 已核实为 completed / success,候选为 2143c8d4。已有独立复核记录 268 个唯一 Rust 测试通过,其中 50 个为必需测试子集;35 个 Node 测试通过。AC-001–010、AUTH-01–10 及 F01 修复在批准的有限矩阵内完成。
Root #2007 当前仍开放等待用户最终验收;本文更新不代替关闭 Root。Root 中记录的 beta SHA 是当时验收候选,当前 beta 已前进到本页核对基线。
本轮采用源码对照、历史差异核对与既有候选证据,没有重新运行全仓测试、性能测试、跨平台发布或真实生产部署验收。本地架构文档仍含当时“尚待 QA”的过程说明,验收状态以绑定候选的 CI 与 Root 记录核对,不能从那句旧说明推断当前实现未完成。
Important
2026-09-28 实现补充,Host/恢复/控制面本机集中测试与真实90分钟客户端验收均通过。 线上唯一新增任务:Issue #2153:按需启动、空闲回收、版本退休与会话恢复。本节完善既有架构,不扩大第 1–8 节的完成声明,不替代 #2007、#2144 的原验收。
问题诊断时观察到 OpenAI 0.2.65 与 0.2.66 同时由 API 父进程持有;新版启动后旧版仍存活约 25 分钟。改造前,共享 worker 的逻辑会话到期不会终止进程,升级切换未显式退休不同版本身份的旧 worker。已存在 supervisor、运行计数、quiesce、kill/reap 与共享 SDK,本次实现完善其闭环。
源码证据绑定 gateway b550ebc4d2bbfa7146db9f3637c2d48311beb7ac,见 加载与退休、共享会话到期、版本切换。初次诊断未重新绑定运行二进制的构建 SHA,因此该段源码分析与进程观察分别结算。本轮冻结候选与实际部署的证据见第9.11节。
目标:受管进程可按需启动、共享、安全退出和重新拉起;会话继续以底座权威状态及恢复证据为依据。优先级为 功能完整性 > 可靠性 > 性能 > 可演进性;保持 映射协议层 → AI Native → 供应商。
| 对象 | Owner / 真值 | 生命周期与影响 |
|---|---|---|
| 对外协议与响应交付 | 映射协议层 | 解析、投影、terminal-once、交付事实;不管理 worker 池或自行重放 |
| 会话历史、工具结果、调用终态 | AI Native 与现有业务持久层 | DB/已有持久恢复资料为真值,主键或索引按需加载;worker 退出不删除历史 |
| 安装、工作区 assignment、权限、有效图 | control-plane / Extension Bus 的既有 owner | 发布带修订的精确版本选择事实;不得让 Host/SDK 查询 PostgreSQL |
| 进程、运行租约、到期队列、generation、kill/reap | RuntimeExtensionHost | 本机 Registry 为运行真值;不靠 Arc 数量、CPU=0 或插件自报无人使用 |
| 通用 stdio、分发、关联、取消、退出协作 | extension-contracts + runtime-extension-sdk | 共享 typed 协议和 runner;SDK 不拥有 TTL 策略、Registry、路由或存储 |
| 上游协议、cursor provenance、socket 与供应商错误 | Provider adapter | 临时连接与优化状态;可重建时回收,connection-bound 状态丢失必须明确报告 |
| 短期高频编排启动资料 | storage/ephemeral | 约 5 分钟热缓存;独立于进程宽限期,不缓存完整持久会话上下文 |
这里的“无状态”指进程不是长期业务状态的唯一持有者,业务状态可由底座在授权范围重建。不要求每次请求重建 HTTP client,也不伪装 socket、进行中的流和 connection-bound cursor 可以复制。保留现有 manifest 名称和协议;不能仅把 stateful_provider_worker 改名就宣称恢复能力已成立。
worker_idle_grace = T_idle:最后一个阻止安全回收的运行占用释放后,保留可丢弃进程缓存多久。它是保温时间,不是启动后活到某个年龄就杀进程,也不是会话寿命。
调用结束 ── 不可安全重建的物理占用已释放 ── t_idle
│
无新调用,等待 T_idle
│
排空 → 退出 → reap
新调用在等待期间到达:原子取消到期任务,复用现有进程
新调用在排空后到达:等待旧 owner 完成清理,再单次拉起下一代
实现配置入口是宿主 API_PROVIDER_WORKER_IDLE_GRACE_SECONDS,启动时注入,默认 90 秒;T_idle=0 表示在安全条件满足后立即回收,不设插件私有重复配置。90 秒是可调整的宿主保温策略,不能表述为生产最优值。计时从执行和物理占用均已确认释放后开始;原有逻辑会话/物理连接租约先由其owner收尾,因此客户端断开到进程退出的总时间不一定只有90秒。32 次本机进程启动到首个 typed reply 样本:p50 0.87ms、p95 1.30ms、最大 4.10ms;它们不包含真实上游推理,也不代表生产端到端 p99。实际使用应结合冷启动、调用间隔、总延迟与尾延迟、RSS/PSS、回收/重启频率调整。不直接照搬缓存 5 分钟,不凭开发机容量猜测任意业务并发或会话上限。
下列符号是设计表达,不是已发布字段:
v = 精确安装/制品/版本身份;p = (v, 安全隔离分区, worker_generation)
A_p = 已接纳且未完成的运行租约(含排队、调用、callback、取消收尾)
U_p = 不可在不损害可观察语义的前提下重建的物理占用
K_p = 对 A_p/U_p 的 owner 状态是否已完整查明
SafeIdle(p,t) = K_p ∧ (A_p=0) ∧ (U_p=0)
D_p = t_idle + T_idle
Reclaim(p,t) = SafeIdle(p,t) ∧ (t≥D_p 或已确认版本无运行需求)
Accept(frame) = ExactBindingMatches ∧ GenerationMatches ∧ CallStillActive
租约是 Host 的显式运行记账。普通 acquire/release 不各增加一趟 IPC;现有 call/result/cancel/callback/transport receipt 提供证据。Host 关闭 admission 与 acquire 必须由同一 Registry owner 串行化,定时事件还需校验 generation、idle revision 和 deadline。timer 先赢则后到请求不能塞入退休进程;acquire 先赢则旧 timer 作废。
Registry + singleflight 启动状态 + 可取消到期队列;优先复用 Tokio DelayQueue,不每次调用扫描全部插件。HashMap 做精确身份索引;到期项带稳定 key/revision。数值规模变化不是引入新依赖或额外服务的理由。
flowchart TB
M["映射协议层:解析与交付投影"] --> N["AI Native:会话/历史/恢复授权"]
N --> P["供应商适配:上游协议与临时连接"]
C["控制面:跨工作区版本绑定/权限/精确引用"] -. "带修订的需求事实" .-> H
N -. "运行 acquire/release" .-> H["RuntimeExtensionHost:Registry/租约/计时/启动/回收"]
H <-->|"现有 stdio typed wire:调用/事件/取消/回执"| S["共享 SDK runner:通信分发与退出协作"]
S --> P
N --> D["DB:历史和恢复资料;按主键/索引加载"]
E["ephemeral:约5分钟启动热数据"] -. "可重建热数据" .-> N
该图的三层是业务语义层,Host/SDK 是执行设施。供应商适配代码可以跨 Host facade 与插件实现部署,不新增一层业务语义。
停止路径先复用既有停止接纳、等待 lease、stdin EOF/进程控制与 cleanup receipt。SDK 已支持 EOF 后在途任务收尾;ACK 只证明控制消息/任务处理,不证明 OS 进程退出。确需显式 ready/drain 控制 frame 时,由 canonical contract 的能力协商/版本演进统一提供,禁止各插件自定义心跳或 drain 协议。
所有检查以精确安装/制品身份为键,不能只比较 provider_code 或 latest:
S_v:所有相关工作区中,仍可选择 v 的有效绑定/执行计划
F_v:冻结但未结束的调用/任务/交付对 v 的实际执行引用
H_v:仍依赖该物理 owner 的有效恢复占用
B_v:必须保留精确版本的历史投递、订阅与恢复/制品引用
DemandKnown(v) ∧ S_v=0 ∧ F_v=0 ∧ H_v=0
⇒ 跳过保温期,退休物理进程
S_v>0 且 SafeIdle(p)
⇒ 仍可按 T_idle 回收进程;后续请求按 v 再启动
DeleteArtifact(v)
需要另行证明 S_v/F_v/H_v/B_v 清空且安装 owner 允许删除
持久积压、休眠订阅和可重建恢复引用要求保留制品,不自动要求常驻进程。恢复记录如果依赖旧 socket,则进入物理占用 H/U 的处理,不能用一句“已持久化”绕过。未知 legacy 引用、查询失败或状态未收敛时,不能断言可立即退休或删除。
控制面从现有全范围 repository 与 graph/frozen-reference owner 取得事实,经稳定 port 通知 Host;Host 不反向依赖 control-plane 或 storage adapter。零需求证明、修订校验和禁止新接纳需要闭合,避免“查到零后新绑定刚发布”的竞态。新绑定晚于退休可以合法冷启动,但不能继续使用已被封闭的旧 generation。
sequenceDiagram
participant C as 原客户端会话
participant N as AI Native
participant H as Host Registry
participant W as Worker 下一代
participant D as DB / 恢复资料 owner
Note over H: 旧 worker generation=g 意外退出;所有旧在途调用获得明确结果
C->>N: 下一次请求,携带原会话关联
N->>D: 按主键读取完整历史/工具结果/精确绑定
N->>H: acquire 精确 v;检查权限/冻结目标
H->>H: 单次合并启动,generation=g+1
H->>W: 拉起同制品进程并确认执行可用
alt 完整上下文或明确可迁移的供应商续接资料
N->>W: 通过现有 contract 授权恢复并执行下一次调用
W-->>N: 新连接结果,按新 generation 关联
N-->>C: 正常协议响应
else 只有旧 socket 绑定游标且无法完整重建
N-->>C: 现有协议允许的明确中断/无法恢复原因
Note over N,W: 不冒充旧连接,不悄悄切 latest,不伪造上下文
end
原会话的逻辑身份继续,进程 generation 和 socket incarnation 变化。新请求是否可以继续由恢复证据判定;不承诺恢复死亡进程中的实时流。已落库历史按需加载,不整体写入 ephemeral,不复制一份到 SDK。
WorkerGeneration(宿主进程代次)、TransportEpoch(AI Native 的连接拥有权栅栏)、SocketIncarnation(供应商物理连接代次)分别记账,不能用一个 generation 字段替代三者。worker 重启由真实退出证据驱动,经现有恢复状态机轮换/fence transport owner,不刷新逻辑调用的预算或 deadline。
已确认物理资源释放的故障会话不能继续受死亡代次的物理期限约束。保留 Faulted 状态,由原恢复入口验证下一次调用;仅当同一 fence 的释放证明已被 Registry 验证且没有在途 invocation 时,维护逻辑身份至原有绝对截止时间:
ReleasedFault = Faulted ∧ ¬Inflight ∧ ValidatedSameFenceLocalRelease
ReleasedFault ⇒ EffectiveDeadline = OriginalLogicalAbsoluteDeadline
这不延长原逻辑寿命、不恢复旧 invocation、不自动重放,也不放开 cursor、commit、replay、调用 deadline 或恢复预算检查。 积压或重试耗尽的 Close 任务取得同代释放证明后直接完成物理收尾,终止通知仍由独立 owner 发布一次;不会向已经释放的代次再发送 Close。只有 ACK 的故障会话仍按 fault lease 到期;有在途调用时继续受原执行和物理期限约束。生命周期测试分别验证超过 fault grace、超过旧物理 hard deadline、原逻辑到期及 ACK-only 负例。
| 死亡时点 | 对当前工作如何处理 |
|---|---|
| 请求尚未分派、能证明未发送 | 保留 deadline 与精确版本,下一代准备完成后接纳;这是首次发送 |
| 前一调用已完成,下一轮尚未开始 | 新代按会话/历史证明继续;不复用失效 socket 或未经证明可迁移的 cursor |
| 已经分派、正在生成或外部副作用可能发生 | 当前调用得到明确终态;只有下述恢复条件全部成立时,AI Native 才可授权重试 |
崩溃发生于当前调用中间时,不能因无首 token 就认定请求未执行:
ReplayAllowed = Transient ∧ ReplaySafe ∧ Reconstructible
∧ ¬Committed ∧ ¬Terminal
∧ BudgetAvailable ∧ BeforeDeadline
复用 #2085 的 AI Native 恢复证明、commit barrier、整体 deadline/预算和 terminal-once;映射层和 Host 不自行重放。已经产生可见语义输出或不能排除工具/外部副作用时,结束当前失败调用,保留可恢复的业务进度;下一次合法调用是新的 admission。
- Tokio DelayQueue:到期队列、Key、reset/remove 与 timer wheel;用于本机计时,不提供业务租约真值或恢复保证。本次核对本地已安装源码与同 tag 上游源码。
- 官方 Codex client.rs:session/turn/connection 分离;连接变化时 reset 连接优化状态,增量请求需验证前序输入匹配。它是 Responses 客户端参照,不是子进程池方案,也不能证明供应商游标跨连接可迁移。
- #1858 的 keyed pool/singleflight/state machine 是仓内复用参照;不复制其插件自管子运行时的职责到供应商,也不继承其固定容量或 TTL 数值。
- #2144/#2145:已有共享 worker 并发与 SDK;本任务补物理进程生命周期,不重复实施并发线。
- #2149:已有临时 transport 数据过期清理;不把缓存清理等同于 worker 回收。
stateDiagram-v2
[*] --> Absent
Absent --> Starting: acquire 精确制品,单次合并启动
Starting --> Active: 进程及已有协议初始化可用
Starting --> Failed: 启动失败,返回已有错误模型
Active --> Idle: 所有安全占用释放
Idle --> Active: acquire 先赢,取消到期项
Idle --> Draining: timer 先赢且重验通过
Active --> Draining: 显式停用或 shutdown,先封闭新接纳
Draining --> Exited: 运行收尾完成,关闭或 kill 后确认 reap
Active --> Failed: 进程意外退出
Idle --> Failed: 进程意外退出
Draining --> Failed: 清理异常,保留未完成证据
Failed --> Exited: cleanup owner 确认 exit/reap
Exited --> Absent: 释放该 generation 的物理资源
这些名称是设计图,不要求把当前 Activating/Active/Quiescing/Inactive/Failed enum 全部改名。Idle 可以由现有状态加租约/到期元数据表达,复用唯一 Registry 和 supervisor。等待 Starting 的多个请求共享同一结果;Draining 中的新请求保持各自 deadline,按现有 admission/backpressure 规则等待或明确失败,不能写入已封闭的 generation。启动失败保留已有退避/恢复预算,禁止每个等待者独立重启。
异常 cleanup 必须最终给出 exit/reap 证据,失败报告未完成;不能仅收到 ACK 或删掉 HashMap 就释放真实进程占用。使用现有可信 OS handle/身份控制,不拿过期 PID 杀进程,避免 PID 复用误伤。
控制面 / Extension Bus RuntimeExtensionHost
全部工作区的精确版本绑定 ──修订──┐
冻结调用 / 执行 / 恢复 owner ───┼──→ 需求事实 + 实际运行租约
持久积压 / 历史制品引用 ────────┘ │
┌───────────┴────────────┐
│ │
物理进程回收 制品可删除性
安全空闲 + 到期 安装 owner 另行证明
│ │
drain → exit/reap 未证明时保留 DB/制品
│ │
└─ 下次仍需旧版时按精确身份重建 ─┘
第 6 节的版本冻结、授权、精确恢复与历史保留继续有效。本节补充“运行进程是可回收执行资源,持久制品是恢复依据”:持久 backlog 可以保留旧制品而不常驻旧进程;真实正在执行的工作和不可重建的物理连接则必须由其 owner 显式收尾。HostExtension 的可信 native 模块仍遵守启动/重启边界,不套用受管子进程 TTL。
推荐 Host 管理的按需资源池、显式租约、singleflight、generation fencing 与可取消空闲期。保守地只处理升级后的零需求旧版,不能覆盖当前版本长期空闲;逐调用短命进程则可能损害连接语义与尾延迟,在功能等价未证明前不作为默认。
Issue #2153 用 Single Issue 保存完整 AC-001–009 与停止条件:
| 验收目标 | 必需证据 |
|---|---|
| 安装数量不等于常驻进程数 | 未调用插件、多个插件按需启动、实际 PID |
| 到期回收且不杀忙进程 | 无后续访问、虚拟时间、长流/callback/cancel 占用正反例 |
| 启动/到期/退出竞态闭合 | 单次启动、generation 与 idle revision、迟到事件 |
| 升级不影响其他工作区 | 跨工作区旧版绑定、冻结调用、精确旧版投递与未知引用负例 |
| kill 后有证据地继续会话 | 完整上下文恢复、connection-bound 游标失败矩阵 |
| 崩溃当前调用不盲重放 | pre/post commit、工具副作用、terminal-once、旧 ACK |
| 通用复杂度归底座/SDK | contract/依赖与插件代码审查;Host/SDK 无数据库依赖 |
| 数值策略有实测依据 | 冷启动及总延迟 p95/p99、RSS/PSS/FD、回收与重启频率 |
本次实现使用受控 fixture 与集中 QA,结果见下节;真实长测未完成时不能宣布全量验收通过。新增持久 schema/迁移、改变业务权限、削弱恢复 guard 或修改客户端协议需要先重定范围。正常客户端不新增 worker 心跳、重启或池管理义务。
已合回并推送当前dev:a0553656b,其他任务的前端提交保留。冻结候选源码 327bff19a0af1e1347d0c234635e588527fc0696,API tree 3b4bd0b7d90f0fe1f62e8c25ef28a21a2eedea21;7800 实际部署的可执行文件 SHA256 898332cbff827a681e67dbe45fe3efba4b41dc55a5e7f2797f266140f626f035。最后一次改动仅增强验收 fixture 的端口与 protected-PID 守卫,没有改变 API 源码。产品修改集中在以下 owner:
| Owner / 文件 | 实现行为 |
|---|---|
| Host provider_host/idle_workers.rs | 一个 DelayQueue 管理 safe-idle 到期;idle_since 锚定截止时间;generation/revision 重验;真实退出通知与 reap 后才能启动后继 |
| Host provider_host/supervisor.rs、stdio_runtime/multiplex.rs | 显式 reservation 和执行/物理占用保留到响应、取消、callback 收尾;串行排队取消不发送请求,已交付 carrier 的后台收尾不会随 caller 丢失 |
| Host provider_host/operations.rs | 已释放且过期的绑定历史可清理;过期时间不能单独证明未释放物理连接已结束 |
| runtime-core Port、Host facade | 暴露精确旧 worker 的确认退出证据和带修订的可选择需求通知,保留 Host 无 SQL 边界 |
| AI Native transport_session_lifecycle.rs、编排 Registry | 无 in-flight 的下一轮接纳前原子核对精确旧代退出证据,沿用既有完整历史/cursor/commit/replay/deadline guards;当前已分派调用不由 Host 重放 |
| control-plane plugin_management/family.rs | 版本切换后查询全部工作区 assignment,发布精确版本可选择事实;查询失败保留 unknown,旧快照不能覆盖新快照;进程回收不删除旧制品 |
| api-server config/bootstrap | 启动阶段注入空闲宽限期,保持一进程内唯一 RuntimeExtensionHost,不新增服务端口 |
共享 SDK 与官方供应商插件源码本轮未改动,不增加插件私有 TTL、心跳或跨工作区查询,也无需发布新的插件版本。
本机集中证据:Host 135 个库测试、5 个生命周期集成测试、1 个编译边界测试;runtime-core 33、SDK 21、transport 35、recovery 15、replay 11、deadline 2、control family 15、API transport 67、config 44 个实际用例通过。Node oracle 15 个用例通过;2 个官方兼容性用例明确 ignored,未计入通过。两个改动的 PostgreSQL 集成测试 target 编译通过,未执行 DB 行为测试;不将本机结果冒充远端发布门禁。隔离的 stale-demand fencing mutation 被新用例拒绝;首次 QA 发现的 released-binding 清理、串行排队取消与过期快照断言均已修复并复核。长测暴露的死亡代次物理期限提前结束逻辑身份、积压 Close 重复访问已释放代次,分别由 original logical deadline 保留规则与已验证释放证明消费修复;原失败样本保留,不计为通过。
真实客户端验收使用安装的 Codex 0.155.1,主模型 gpt-6-luna / max、实际 subagent gpt-6-sol / medium,单一持久 thread 连续工具审计;覆盖显式压缩、校验值工具结果保留、活动 turn steer、两轮之间 SIGKILL、新代继续、流中 SIGKILL 后唯一失败终态与下一次合法调用。客户端 provider 的 request/stream retry 配置均为 0;错误模型、缺少真实事件、不足 5400 秒或静默重放均失败。最终真实长测结果:PASS。2026-09-28 06:51:43–08:32:16 UTC,总时长6033.044秒(100分33秒),首个至最后一个有效工作完成跨度5694.755秒(94分55秒),24个有效turn、195次成功工具执行、3次完成的压缩。实际执行两次指定的subagent spawn/wait/close;活跃turn的插入nonce已处理。thread 01a0e6c8-a37c-7801-898b-c7ef9aee36b4持续使用,oracle错误数0、客户端退出码0。
已安装客户端目录原先不注册 gpt-6-sol;仅 fixture 私有 CODEX_HOME 使用标准 model_catalog_json 注册精确请求名,记录目录 SHA256,并核对实际 spawn model/effort。该目录模板只是客户端元数据适配,不声称真实模型容量,不修改网关模型身份或用户默认配置。原错误模型 bootstrap 保留失败证据,未计入长测时长。
进程替换的实际 PID/startTime 证据、Host WorkerGeneration、AI Native TransportEpoch 与供应商 SocketIncarnation 分别结算;不能用 PID 改变代替全部代次。生产环境资源和 p99 未取证;本地测量仅代表当前受控条件。具体receipt与日志索引随 Issue #2153 更新。
本轮只在允许重启的7800执行,保护7600的进程身份保持不变。两次故障后精确版本PID路径为3517180 → 3554670 → 3599712;流中SIGKILL对应turn只产生一个失败终态,后续合法调用成功。客户端结束后未再人工kill,最后一代在首个无子进程样本中已退出/reap,距客户端结束约182.679秒(10秒采样分辨率);进程空闲宽限期从物理安全占用释放后开始,因此不把该总间隔误写成90秒。后续采样至客户端退出后362.830秒,子进程数保持0;两个故障PID与最终worker的/proc均不存在。7600/7800服务保留,测试client/sampler已结束,专用测试key撤销204、临时认证owner已回收。
| 本轮10秒采样(KiB,FD为个数) | 开始 | 峰值 | 观察结束 |
|---|---|---|---|
| 被测0.2.66子进程数 | 0 | 1 | 0 |
| API RSS | 370192 | 667960 | 468072 |
| API PSS | 304472 | 625612 | 425436 |
| API FD | 141 | 151 | 143 |
| 插件 RSS / PSS / FD | 无进程 | 71164 / 69760 / 11 | 无进程 |
API内存/FD从峰值下降,未完全回到开跑基线;有限共享开发环境观察不能证明长期无泄漏。主turn到首个语义/推理输出n24:p50=11.689秒、p95=19.008秒、经验p99/max=19.633秒,包含上游推理,不能作为纯进程冷启动成本或生产p99。32次bootstrap与上述真实调用分别计量,不由这些有限样本宣称90秒为生产最优值。
本次为本机Dev Acceptance通过;两个PG target仅编译、ignored兼容fixture及生产SLO的限制保持显式。线上Issue保留OPEN与phase:user-acceptance,供用户最终验收,未将本机测试等同于远端CI发布门禁。