Written-by: Dev3 Owner: Dev3 `#1271` 的 **第 4 节**单独拆出来的一张子单。父单 `#1271` 的关单句留给第 1 节(doc 措辞,最后合);本节由 PR `#1274` 用 `Fixes` 关。 ## 要做的 `core/src/host/connector-access.js:148-157`:换 mask 时先 `current?.dispose?.()`(`:149`)、`masks.delete(agent)`(`:150`),再 `restrict({ deny })`(`:154`)。`restrict()` 对 profile 不提供的名字会抛(`@deepseek-ai/dsh-tools` 0.2.0-rc.2 的行为)——一旦某个名字改由 Agent 自有层提供(`schedule_*` 从 profile 挪走就是最现实的场景),catch(`:155-157`)只 `rt.warn`:旧 mask 已 dispose、新 mask 没建,那个 Agent 的工具列表**静默回到全开**。守卫仍拒调用,不是越权,但列表泄了。 ## 选路(已写进 PR 正文) **选 (a)(保留旧 deny)的变体,不是退路**:装 mask 前先把 deny 过一遍全局视图(`ctx.tools.schemas()` 无参)只留能执行的名字,再 `restrict()`;catch 里把上一版 deny 放回去兜底。 ## 判据 一条单测打到 catch 分支:名字还在 `schemas(agent)` 里、但 `restrict()` 拒它(即名字挪进 Agent 自有层;`dsh-tools` 的 `view()` 只把 inherited 放进 `restrictableNames`),断言 `allHidden('room-writer')` **仍含那 8 个名字**,不是断言它变空。现实现下这条必须红。 > 与父单字面路径的差异:从 `live.served` 去掉一个 schedule 名**走不出红**——名字消失后 `denied()` 也不再含它、`restrict()` 不抛;真因是「名字在 `schemas(agent)` 里但 `restrict()` 拒它」。夹具用 `live.own`,Backend 已确认不算偏离判据。 ## 落地 PR `#1274`(分支 `dev3/1271-catch-fail-closed`,tip `a629c933a324527c8a6b1dcd07142daef77b2d42`,6 文件 `+84/−8`)。
Activity
docs: a room's tool mask also covers the sub-agents it starts (ThinkF…
Fix Workflow stage layout and hide ephemeral node chat (ThinkFlowLab#…