SubprocessHandle loses dispose(graces) and SubprocessDisposeGraces: the stdin-EOF→SIGTERM→SIGKILL sequence is teardown POLICY encoding one consumer's cooperation shape, not process vocabulary — the seam keeps kill/terminate/waitForExit, and waitForExit(signal?) is the quiescence probe a consumer ladder needs. dsh-subagent-acp owns disposeAcpChild() over those public verbs (tier tests move into its suite; a never-exits stub pins the fail-loud path); dsh-subprocess-local sheds the ladder, its deadline import, and the dsh-timeout dependency. Every future backend now owes four verbs and no teardown policy. New bilingual ladder-ownership Agent Note records the decision; catalogs regenerated.
2.6 KiB
Agent Note: dispose 阶梯归其消费方所有,而非 subprocess seam
Status: implemented
English | 中文
问题
SubprocessHandle.dispose(graces) 与 SubprocessDisposeGraces 把一整套拆卸策略——等待 stdin EOF、再 SIGTERM、再 SIGKILL,每一层由调用方提供的时间窗约束——放在了一个其余动词均为单一机制的 seam 上。它始终只有一个调用方(ACP subagent 后端);bash 走 terminate() 与服务拆卸,LSP 主机运行自己的协议优先关闭流程。然而每个未来后端都必须实现该阶梯才能满足接口,实现包也仅为阶梯的层级时限背上了 dsh-timeout 依赖。
决策
阶梯移入其唯一消费方。dsh-subagent-acp 拥有 disposeAcpChild(child, eofGraceMs, graceMs),完全构建在 seam 的公开动词之上:关闭 stdin,以 eofGraceMs 约束一次 waitForExit,随后 terminate()(其 SIGTERM→spec 宽限期→SIGKILL 升级已编码了信号层级),最后进行有界的整树等待,若仍有存活进程则抛出。seam 保留 kill/terminate/waitForExit——机制而非策略——而 waitForExit(signal?) 恰是消费方阶梯在每一层确认进程树真正退出所需的停稳探针。dsh-subprocess-local 卸下 dsh-timeout 依赖;seam 的句柄少了一个方法和一个导出接口。
曾考虑的替代方案
**把阶梯作为便利方法留在句柄上。**否决:一个每个实现都必须提供的 seam 方法不是便利,而是契约表面——而这一个把某一消费方的配合形状(stdin EOF 打头)当作进程词汇来编码。seam 自己的 README 早已不得不加注「依赖其他信号停稳的子进程需要自己的第一阶」,这本身就是承认该阶梯是策略。
**把阶梯移到共享辅助包。**否决:只有一个消费方。当第二个具有相同 stdin EOF 配合形状的进程外后端出现时,可以再把 disposeAcpChild 提升为共享代码;现在抽取只会重造 dsh-subagent-subprocess——这组堆叠变更刚刚删掉的那个单一用途库。
后果
买到的:seam 少了一个方法和一个类型;实现只欠四个动词,不欠拆卸策略;dsh-subprocess-local 少了一个依赖;阶梯的层级时间窗与调节它们的配置字段住在一起。代价:未来想要 EOF 打头拆卸的后端需针对这些动词写约 20 行(或直接搬 ACP 的辅助函数);阶梯的层级测试从 seam 套件移入 ACP 套件,seam 套件转而钉住阶梯所组合的动词(升级前后有界 waitForExit 先假后真),而非组合后的策略。