交互原语改 host 注册开放 registry + 移除四个能力位(ADR-0030 整份落地) #109
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/104-open-interaction-registry"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #104
ADR-0030 整份落地。core 不再理解
poke/reaction这两个 QQ 概念:交互原语的渲染改成 host 按
kind注册的开放 registry,四个具名能力位、两个 core 工具、两个
EgressPort方法一并删除。趁两个 host 仓对 arise 零命中做这批破坏性变更。交付
ConversationInput.interaction改开放形状{kind, target_is_self, actor_id, target_id, payload},封闭的InteractionKindLiteral 删除;旧的target_message_id/emoji收进payload。ArisePorts.interaction_renderers;core 只拥固定信封<interaction kind=… sender_id=… sender_name=… time=…>{host 渲染内容}</interaction>。IngressPort.to_interaction+ 一个@event_postprocessor入口,让这条链在生产里真的可达。
target_is_self=True→ 统一评估管线;False→ 转EnvironmentSignal走旁观。poke/poke_send/reaction_receive/reaction_send四个能力位、POKE_SEND/REACTION_SEND两个 core 工具、EgressPort.poke_send/reaction_send。三处文档没说、按 grill 结论做的
actor_id/target_id照 ADR 建全五个字段。 它们一度看着像"零读者字段"(本仓点名过的反模式),review 之后不再是:第三方那条路把它们喂给
EnvironmentSignal.actor_id/subject_id,正是 ADR-0030 决策节点名的那层复用。零 host 的今天免费,ob11 接入后就是两边协调迁移——与本票自己的立论一致。
测试适配器给了真实的 OB11
PokeNotifyEvent实现(不是像其它几个 stub 那样恒返回
None),所以整条链在测试里是真的走通的。kind的行为沿用tags.py先例:整条剔除、不留占位。两轴 review:13 条 finding 全部存活,0 条被驳回
blocker(两轴独立撞上同一处):「未注册 kind 整条剔除」原先只做在渲染层,
入口不查 registry——事件照样入队、跑完两级门控、发起一次 LLM 调用,而那一轮的
context 里一条 user 消息都没有,模型凭空编一句发出去。空 registry 是
ports.py明说的合法配置("不是错误配置"),所以这是任何没注册交互原语的部署都会撞上的路径。与
tags.py那条先例的差别在于:未注册的 inline 标签只是从已经决定要发的一段文本里被抠掉,而这里被抠掉的是触发本身的全部内容。
闸已提到入口。
Spec 轴抓到我写了一个可证伪的理由:
target_is_self=False原先只做了"不进反应式批次",我给的不做理由是"core 造不出
EnvironmentSignal,那个类型要plugin/action"。复核实跑推翻了它——action就是kind,chat_id/time都在手上,只差
plugin一个 core 自选常量。这属于本仓记过七次的「给不做的分支配一个听起来合理但错误的理由」,第八次。已按 ADR 实现完整路由。
其余:5 处把已删符号当现存事物引用的散文(含两处过期计数「六个裸的平台调用」,
按 issue #88/#102 确立的处置删数字而不是改数字)、一条承诺大于覆盖的守卫
docstring、一段被抽走后悬空的注释。
有意不改,交评估侧
戳一戳不撤销沉默窗口。 若
chat_id上有一条不经_pending_flushes的待发消息正在沉默窗口里等(环境信号 tier-2 / Callback 送回 / 即刻追问三条路都是
这样),一次戳一戳不会撤掉它,于是那条和本轮回复会一前一后都发出去;换成一条
普通消息则会被
_interrupt_silence_window_on_any_message撤掉。不改的理由:CONTEXT.md 给沉默窗口写的触发条件是"窗口内这个 chat 里任何人发言
即撤销,补位而非抢话",戳一戳不是发言——把它算进去是扩展一条已拍板机制的触发面,
不该由实现方在本票里顺手定。理由已记在
_enqueue_for_debounced_turn的 docstring里。这条需要评估侧决定要不要开票。
同一形状的相邻缺口:
_handle_environment_signal与_handle_presence_events同样直接 await host 回调、同样没有 try/except,而
_apply_event_postprocessors把全部 postprocessor 交给同一个
anyio.create_task_group()——任一子任务抛出会取消同组其余任务(外层那个
catch只记日志)。本票给自己新加的入口兜住了,那两条既有的没动,同样交评估侧。
验证
ruff check干净。target_is_self半闸 / 去掉interaction is None半闸 / 未注册 kind 返回空信封 / 去掉上下文组装的 None 过滤 / 信封丢掉 kind 属性 /
去掉入口 try/except / 把
poke_send无条件加回工具表 / 把poke能力位加回来 /去掉入口的 registry 闸 / 第三方分支改回直接丢弃。
每次变异都先断言"真写进去了",还原后 md5 全部一致、哨兵残留 0。
尚未做
文档同步(
docs分支,按规则永不推送):ADR-0030 追加"已实现"更新节、ADR-0004 与它的矛盾、CONTEXT.md 两条术语,以及 review 补出来的
ADR-0012 两处过期计数与 ADR-0020:125 的过期先例引用。落在后续提交。
🤖 Generated with Claude Code
ADR-0030 整份落地。core 不再理解 poke/reaction 这两个 QQ 概念: - `ConversationInput.interaction` 改开放形状 `{kind, target_is_self, actor_id, target_id, payload}`,封闭的 `InteractionKind` Literal 删除。 - 新增 `ArisePorts.interaction_renderers`,host 按 kind 注册渲染函数;core 只拥固定信封 `<interaction kind=… sender_id=… sender_name=… time=…>`。 未注册 kind 整条剔除、不留占位(同 tags.py 既有先例)。 - 新增 `IngressPort.to_interaction` 与一个 `@event_postprocessor` 入口, 让这条链在生产里真的可达;`target_is_self=False` 不进反应式批次。 - 删除四个能力位(poke/poke_send/reaction_receive/reaction_send)、两个 core 工具(POKE_SEND/REACTION_SEND)、两个 EgressPort 方法。 趁两个 host 仓对 arise 零命中做这批破坏性变更。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>