Repository navigation
Replies: 1 comment
|
Thanks for writing this up with the failure history and the evidence scope attached — that is more than most reports carry. I am not a maintainer; I write external plugins for this harness (and I hit the same wall from a different direction), so what follows is measurements rather than a roadmap, and I will say plainly which of your points I can speak to and which are core-side. The main ask: what I can measure about writing informational eventsThe mechanism you describe reproduces exactly, and the version I can add is why it is a deferred failure rather than a pending one:
On the question you asked the maintainers — a new constrained entry point, or "store it separately"? The harness already has the sanctioned path, and it is public: To make my claim checkable rather than argued, I built and published what was missing around that seam — a plugin, from outside core, over public seams only:
It judges a type before it is written on both paths, audits stored sessions through the same validated read seam a restart uses (so the answer is the reader's, not a prediction), observes live Your acceptance scenario 1–3 is, almost line for line, this package's test suite: write through the real JSONL backend, flush, close, then read it back in a separate process that does not import the plugin at all ( Your five secondary boundaries1. A pre-write observation extension point (fs). I did not measure this one, so I will not pretend to. What you describe is a property of that policy holding a single decision position and not calling 2. Paired fork examples for both entries. Also core/docs rather than plugin-mountable — a plugin cannot make two entries agree on a history prefix; it can only avoid re-implementing the rule, which is what you did in the end. Worth saying explicitly in such an example: "the plugin coordinates file restoration" is the correct division, and your point that authors otherwise maintain two 3. Connecting service and module identity diagnostics. This one I have hit, and it may be the same face: the field symptom is "I registered it, why is it not found", and the cause is frequently two copies of the same runtime, not one. Two examples from the report history with concrete signatures: a second copy of 4. A real-process boundary template for external plugins. Agreed, and this is the part I would most like to see made official. My own suite is one instance of the shape you describe: the published package is installed into a scratch tree pinned to each harness line ( 5. Actionable recovery when the config watcher fails. Two things worth folding into that path. First, a failure one level below the one you are looking at: when a watcher is closed and something in it still rejects, that rejection is unhandled — chokidar's own promise belongs to no one after the close — and an unhandled rejection in that position kills the whole process instead of degrading. So a degraded mode that closes the old watcher and starts a polling one has to also own whatever that watcher left pending, or the "recovery" is fatal. Second, agreed on not turning the source tree into a high-frequency poll: Splitting itI think your instinct to pull the event-write part into a focused RFC first is right, and for a reason beyond size: it is the only item here where the contract already exists ( |
Uh oh!
There was an error while loading. Please reload this page.
[Ideas] 来自 FileSnap 实践的插件开发体验建议:安全事件写入、写前观察与真实宿主测试
我是非官方插件
dsh-filesnap的作者。最初给 Codex 做回滚时,我把文件快照与恢复抽成了 FileSnap,再尝试把它接到 DSH,让文件与对话一起回到之前的状态。开发过程中,我遇到过监听器被事件决策链截断、自定义事件落盘后冷加载失败,以及浏览器/命令入口使用不同 fork 边界等问题。部分是我对契约的误解或插件实现错误,部分反映了外部插件作者仍然不容易跨过的接口边界。
感谢近期对 unarchive、精确 fork、启动诊断及模块解析的改进。这些能力已有对应实现,下面不再把它们作为缺失功能提出。我希望讨论的是:怎样让外部插件更容易使用公共接口,并更早验证用户实际会经过的安装、重启和卸载路径。
**核查范围:**历史故障主要发生于 2026-08-27 至 09-11;2026-09-28 核查过发布版
0.1.7-rc.2,起草本帖时于 09-29 又检查了官方固定提交4878cdabd87d的相关源码。以下现状判断限定于这些证据,并非在该提交上重新运行了所有故障复现。建议中的接口与流程只是讨论方向。最希望先推进:外部插件安全写入信息性事件
旧版 FileSnap 曾向 Session 写入
filesnap/point等自定义事件。类型扩展使调用能够编译,当前进程也可以工作;但新进程加载日志时会遇到未知事件错误。我一度修改内部KNOWN_SESSION_EVENT_TYPES集合绕过检查,后来发现它仍依赖插件是否已加载、以及读取方是不是同一个模块实例。当前已知事件集合的设计说明明确指出,外部事件的兼容性应依靠持久化的
ignorable标记,而不能依赖当前插件组合;但我检查的Session.append()仍只接收 surface 元数据,构造并冻结的 envelope 中没有对外开放这个标记的写入入口。FileSnap 从
0.3.0起已移除修改集合的 hack,改用独立 RPC/UI 和插件状态存储,再关联原生轮次与 fork 血缘。这让插件避开了这个缺口,但外部作者仍可能因为“事件类型可扩展”而误以为写入与后续读取也有完整契约。**初步方向:**考虑为可安全省略的信息事件提供受约束的公共写入路径,明确命名空间、payload 版本和省略语义,并由宿主在冻结之前生成兼容 envelope。不能让任意核心状态事件都通过加一个
ignorable获得放行;不支持的未知事件应在写入边界给出诊断,避免延迟到重启才失败。如果官方倾向于让这类状态一律独立存储,也希望在类型扩展文档和 append 诊断中把这一边界讲清楚。建议验收场景:
这里希望确认的是受支持的扩展方式,不要求放宽核心事件校验,也不希望将修改内部集合变成推荐用法。
其他值得继续改善的边界
1. 为写前观察提供明确的扩展点
快照插件需要在变更前取得文件内容。当前
fs-observation-policy在 write/edit intent 上占据单个决策位置,不调用next();这是现有契约,后置观察器收不到调用不能简单归为 bug。FileSnap 通过
prepend: true前置捕获,再next()交还决策。希望考虑把受支持的路径表达成“决策检查 → 等待写前观察 → 执行变更 → 报告结果”,让观察器不承担授权决定,并明确多观察器顺序、取消和捕获失败策略。验收可以同时挂两个观察器与一个拒绝策略:拒绝时不写入;允许时捕获先于变更;观察失败有定义好的结果。还需要说明并发边界,避免把一个 hook 理解成文件锁,或声称它能覆盖 shell 等其他写入路径。
2. 提供浏览器与 headless 入口共用 fork 的完整示例
当前已有
SessionStore.fork和buildForkSeed。我曾在命令入口复制截断逻辑,导致与浏览器行为不同,这是插件自己的实现与维护问题。建议先给外部作者一组成对、绑定发布版本的示例,覆盖边界选择、冷会话、preset、workspace、子会话创建及失败清理。如果示例仍必须复制大量 controller 编排,再考虑提取公共服务。验收是两个入口产生一致的历史前缀和合成尾部,作者不用维护两套
slice()规则;文件恢复仍由插件自行协调。3. 让服务与模块身份诊断连起来
官方已有启动诊断和宿主实例共享规则。遇到错误依赖声明或旧 profile 残留副本时,外部作者仍可能只看到“明明注册了却找不到”。
建议在现有诊断上展示服务提供者/消费者、所属 fiber、等待原因,以及关键运行时从宿主和插件两侧解析到的真实路径、版本、入口与实例身份;对打包内联或应声明为 peer 的依赖给出针对性提示。验收是故意引入第二份必须共享身份的运行时后,诊断能指出冲突来源,而不是把所有合法的多版本依赖都当成错误。
4. 把真实进程边界测试做成外部插件模板
我曾有 104 个绿色测试证明“事件已经注册”,却没有一个启动未加载插件的新进程读取日志。测试选错边界是插件作者的责任;好的模板能让这类遗漏更容易暴露。
官方已有
dsh-loader-smoke,其中 production-profile helper 也说明了仓库内使用的边界。建议基于这些能力,提供独立插件仓库能运行的模板:安装 tarball 到临时 profile,用无密钥回放/mock LLM 驱动真实轮次,再验证重启、卸载后读取和必要的 client 产物。验收是模板能发现漏打包客户端、重复运行时,以及必须加载插件才能读取的历史数据;可按插件能力选择场景、固定已发布宿主版本运行 CI,不要求每个小插件跑全部宿主测试。
5. 配置 watcher 失败时提供可执行的恢复选择
Headless 默认不再强制启用 HMR,polling 也已有支持。剩余建议针对启用监听的环境:当前配置 watcher 错误路径中,启动时错误使 ready 拒绝;该文件内未看到资源错误自动降级逻辑。
建议识别
ENOSPC等错误,指出配置监听/源码监听中的具体失败位置,并给出关闭 HMR 或切换 polling 的对应配置。可考虑显式启用、仅针对少量配置文件的降级选项,切换时完整关闭旧 watcher 并记录状态;不要默认把整棵源码树改成高频轮询。验收应覆盖失败、降级和卸载,避免泄漏或无限重试。希望维护者帮助明确的方向
如果先推进一项,我会优先选外部信息事件的安全写入契约,因为它直接关系到用户已经保存的会话能否继续使用。
想请教:信息性扩展事件更适合新增受约束的写入入口,还是明确推荐独立存储?其余建议中,哪些已有推荐入口或正在进行的工作,值得外部作者直接复用?如果适合拆分讨论,我倾向于先把事件写入独立成一个聚焦的 RFC,再分别补示例与测试模板的设计。
All reactions