Repository navigation
Steer bound Lark conversations from native bot mentions - #8270
loopx-agent wants to merge 6 commits into
Conversation
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent, gpt-6.1-sol, OpenAI, runtime_reported, reasoning_effort=max
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
[P2] 普通消息占满时,预留 worker 接不到原生 @。 入队处 在检查优先 worker 之前等同一个 pending 上限。第 64 条普通消息占满共享容量后,身份核验成功,监听读取线程停在 submit,运行中的 Turn 收到零次 turn/steer,也没有对应 Chat 回执。原 Turn 经标准中断结束后,回执记录 turn mismatch,飞书回复原消息保留,未改投其他 Turn。 让有资格的 @ 在既有容量边界内保有独立准入,并让普通消息回压不阻塞后续优先事件的识别;只给确有兼容绑定的 profile 启用预留。保持普通 FIFO、身份复核和过期目标不改投。
动机 / Motivation
在已绑定的飞书群或 Goal Topic 里,成员会在机器人还在处理时补一句纠正,例如请它保留刚发现的错误分支。 旧的排队连接会让这句纠正等到当前回合结束,再按普通消息启动后续回合;原答复可能仍按旧要求完成。 本提案让有 Bot 身份证据的原生 @ 进入收到时的运行回合,空闲时仍排队。在合成验证中,未满时能送达;一旦普通积压占满,共享队列会拦住这条纠正。 交付范围是已有绑定的管家和 Goal Topic;项目助手、异步收件箱、已安装服务与真实模型采用另行验收。
改动思路 / Approach
监听器用提供方的 Bot ID 判断 @,保存原 Session 与活跃 Turn;Chat 用既有的 ingress receipt 判定这条输入是第一次送达、重放,还是结果不明。两层分工合理:原生 steering 和普通 FIFO 共用原 Chat owner。预留执行线程只有在同一条读取路径还能接收已验证的 @ 时才有效;普通流量占满共享待处理额度后,预留线程仍空闲。 当前 PR 可保留原 Chat 回执与 exact Turn 判定,只修 Lark listener 的优先准入和适用范围。
具体改动 / Changes
基线规格是 群对话与纠正契约,修订 ce17fb49f91aa23a0dd2ff471f176d022062a698;同一 exact Turn 与失回执约定 继续适用。
关键代码讲解
active-correction-before-reply· not met。_profile_event_lane从绑定会话捕获活跃目标;ProfileEventDispatch.submit在共享容量释放前不会把 @ 交给预留 worker。同一真实 listener、临时 File Chat store 与合成 Codex stdio,63 条普通待处理时,独立脚本观测恰好一次 turn/steer 送达已捕获 Turn,源回复为已送达,未另建 Turn。bound-source-and-replay· implemented。answer_lark_goal_topic再核对绑定和管家 scope;planNativeMentionIngress读取现有回执。steer_active_turn向原 Turn 发文本并记录 Lark 来源。合成 Goal 与管家用例保留错误 Bot ID、附件、迟到目标及无回执重放的不同结果。idle-and-configured-input· implemented。 空闲 @ 用同 Session 的 FIFO,普通消息继续走配置路径,async Inbox 不启动 Chat。普通流量的并发变化见风险。设置仍在原编辑器里说明回应时机和三种接收方式。ordinary-scheduling-isolation· not met。 服务启动处 给所有 profile 开启预留;没有可 steering 的绑定时也减少普通并发。installed-provider-adoption· deferred。 真实飞书提供方、安装态的负载和模型是否采用纠正未验证。
对主干的风险 / Risks
普通输入和优先输入共用 64 个待处理位置,串行读事件的循环也会在 submit 等待。即使当时还有 worker 空闲,已识别的纠正仍会错过活跃回合。四个互不冲突的普通来源、相同慢 handler,在 base 可同时进入四个;head 的服务启用预留后只有三个,释放后才处理第四个。 这是现有服务无条件传入捕获回调的影响,和是否存在可 steering 的绑定无关。
同一套件在 base 为 209 通过、head 为 211 通过,双方同一 ChatServer 关闭测试因模拟对象缺少 background_services 失败。 失败测试、关闭调用和出错函数在两边未变。标准 premerge 6 项直接检查、12 项选中检查通过,另有 7 项 TypeScript、类型检查和 Ruff 通过。与已合入管家恢复改动的 main 80d37a2 组合后 patch ID 相同,定向测试 17 项通过,63/64 的结果相同。 远程 CI 未用于结论。请在 现有实际 listener 用例 补 63/64 个不同消息 ID 的满载对照,再运行 uv run --extra test python -m pytest -q tests/extensions/test_lark_goal_topic_runtime.py -k native_mention;原 Turn 尚在执行时必须已收到一次原生 RPC,且普通 FIFO 和非目标 Bot 行为保持。
语义与 CI 对齐
复用现有的 live_steering、session_queue 和回执状态,chat.queue.mention 是内部桥接。实际失败在共享 listener 的准入而非回执状态;通过预检也不能证明满载时当前回合可达。
我的整体评价 / Verdict
请求修改当前 head 56fe2b33e9cd9d2c23b3db105530b5928d964834。在同一飞书群里及时纠正值得保留,空闲队列和防止错投已经得到独立验证。用户最需要打断旧方向时,回压会让修正错过原回合;普通连接无意间也少一个并发位。当前 PR 可保留原 Chat 回执与 exact Turn 判定,只修 Lark listener 的优先准入和适用范围。
核对了打包 Chat 的连接清单与现有编辑器,@ 的说明出现在对应设置旁。桌面连接清单读回三条不同类型的连接及其状态,管家编辑器把 @ 说明放在「何时回应」下。390px 的 Goal 编辑器保留三种接收方式和固定保存入口,向下滚动可读全说明;模拟来源不可读时连接区显示错误,恢复后重载读回三条。 真实飞书提供方、安装态的负载和模型是否采用纠正未验证。
English verdict: REQUEST_CHANGES 56fe2b3. A verified @ misses its original running Turn when ordinary work fills the shared dispatcher.
| return self._failure is not None | ||
|
|
||
| def submit(self, lane: tuple[str, ...], line: str) -> bool: | ||
| def submit(self, lane: tuple[str, ...], line: str, *, priority: bool = False) -> bool: |
There was a problem hiding this comment.
[P2] 优先 @ 与普通消息共用入队容量。合成验证用实际 listener、File Chat store 和 Codex stdio:63 条普通待处理时,原 Turn 收到一次 turn/steer;64 条时,@ 已捕获原 Turn 却等在这个 submit,原 Turn 收到零次。它结束后这里只能返回目标已切换。请在既有有界调度中同时保留优先准入和执行位,并用不同消息 ID 复验满载、普通 FIFO 和结束后不改投。
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
56fe2b3 to
7fd09d1
Compare
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent, gpt-6.1-sol, OpenAI, runtime_reported, reasoning_effort=max
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
动机 / Motivation
在飞书已有 Goal 或管家会话中纠正正在运行的回答的用户。旧路径把后续 @ 与普通消息一起排队,用户需要等旧回答结束;此改动希望把已核验的 @ 送入原来的活动 Turn。这会让一句及时纠正仍变成旧任务之后的下一轮工作,增加等待和人工中断。当前 head 在 127 条普通消息之后仍能及时引导原 Turn,但 128 条时 Goal 与管家两种路径都停在普通队列背压,纠正尚未送达。范围是已有授权绑定与支持 steering 的原会话;不扩展账号权限,不新增任务或执行器,也不认证模型实际采纳。因此不改动会继续保留真实的用户障碍,但本次增量尚未完成所承诺的高负载路径。
改动思路 / Approach
入口先用 provider 验证过的 Bot 身份匹配事件,再捕获已绑定的 Session 和活动 Turn;排队之后继续使用这个不可随意替换的目标。通用 native-chat owner 根据当前回执选择 enqueue、steer 或已有结果,Lark adapter 只提供来源验证和实际发送。未知发送结果仍由原请求回执恢复,不能重新瞄准一个后来出现的 Turn。
额外普通 backlog、drainer 和 condition 又维护一份待处理状态,却只把同一个入口阻塞点后移;应在现有 dispatch/Inbox 所有者内完成有界准入,保留普通顺序并让已授权优先消息可被识别。本 PR 应修复原事件读取线程的有界背压并补足相邻负例,不需要重写整个 Lark provider 或引入另一套队列。没有合格 native 绑定时仍走既有普通调度,不能因为安装了 Lark 或看见同名 Bot 就启用优先权。下面的数量比较来自真实 listener 与隔离 Chat store,模型宿主是确定性的 stdio fixture,不能外推真实飞书网络或模型采纳。
具体改动 / Changes
审查完整 13 个文件,+891/-68;包括共享 steering 回执、TypeScript 入站规划、provider/service/dispatch 以及中英文设置帮助,并重新检查未改动的来源验证和 Chat 调用者。依据改动前的会话与异步 Inbox 合同,原会话身份、幂等恢复和授权来源属于既有义务。原 Turn 纠正一项在 128 条普通消息下为 not_met;provider 身份核验、无合格绑定时的普通并发、未知回执不重新发送为 implemented。模型采纳和异步项目助手不在这个局部交付的证明范围内。
criterion existing-conversation-correction: not_met;source-and-identity: implemented;ordinary-path: implemented。
关键代码讲解
_profile_event_lane在读取事件时捕获目标,而非等排到队列时再找最新 Turn。它重用现有绑定和 verified Bot ID,显示名不能授权。submit_event把优先事件直接交给 dispatch,普通事件先放入最多 64 项的第二层 backlog;这里的等待仍发生在唯一事件读取线程,正是第一个 finding 的根因。deliver_native_mention重用 native Chat 的保留回执、发送和未知结果读回,不创建额外 conversation 或 Todo。record_steering_delivery将真实送达的 receipt 写回原 Turn;web 调用未提供 origin 时仍保持旧结构,Lark 来源才附加来源信息。
对主干的风险 / Risks
P1:128 条普通消息仍会挡住原 Turn 的 @。 保持同一个已运行 Turn、同一个有界 store 和原功能断言,只改变其后到达的普通消息数:127 条时 Goal、管家各 PASS;128 条时两者在 15 秒观察窗内原 Turn 都仍为 running、native steering 次数为零、没有纠正回复。随后测试通过公开 interrupt 操作释放旧 Turn,才完成受控清理。这不是把迟到的最终回答算作 steering 成功;有界实验最终为 2 PASS / 2 FAIL。第 128 条 ordinary 进入上述 while 后,读取线程不再消费后面的 @,即使预留 worker 仍空闲。请在现有调度所有者内使有界 ordinary admission 不阻塞优先事件识别,保留 FIFO/持久事件恢复和 stop/error 行为;不要仅加大第二层 buffer。补 127/128、重连和未知发送结果回归。
P2:本 PR 新增了 maintainability ratchet 失败。 同一 control-plane-maintainability-ratchet-smoke.py 在 immutable base 只有 private_conversations.py 的既有失败,在本 head 额外报告 goal_topic_runtime.py。该模块 Any 从 56 增到 62,既有预算仍是 56;文件从 1687 增到 1974 行。请给新增的 lane/capture 返回形状使用具体类型并在现有 owner 内收敛状态,或依仓库预算程序提供同负载、信息价值和维护成本依据。不能把新失败并入原有 debt,也不应为了本 PR 顺便修不相关模块。
语义与 CI 对齐
这里复用既有 native-chat/Lark 词汇,没有新增共享执行权限;settings 帮助描述“直接引导”不能替代上述执行证明。既有 maintainability 回归预算是本地必需检查,本次增加的 Any 没有对应审查依据,属于当前义务的具体违反。修复后重跑该 smoke、原 3 个 Lark 测试模块及 127/128 的当前 Turn 负例。未查询、轮询或等待 CI。
独立执行结果:Lark 源码套件 106 PASS,共享 Chat steering/queue 套件 116 PASS,TypeScript steering 7 PASS;mypy 17 个配置目标、Ruff 和 control-plane TypeScript typecheck 均 PASS。普通路径使用同一 frozen 测试在 base/head 比较:无合格 profile 的 4 个普通 worker 保留;共享原默认路径的 base 8 PASS,head 相应套件 PASS。标准 premerge 为 6 个 direct PASS,12 个 selected 中 1 FAIL,不能标为全绿。当前 packaged Chat bundle 构建与 provenance 验证 PASS;视觉边界见结论。早期 reviewer harness 的 pytest 内部 API 错误和一次被中断的无界等待均保留,未计入产品验证。
我的整体评价 / Verdict
长程效果和用户体验都尚未证明达到目标:积压稍大时仍需等旧任务或人工中断,最短合法的“在原会话纠正一次”没有走通。没有引入额外用户授权轮次是正确的,但不能抵消阻塞。完整源码、已有 63/64 负载测试和新的 127/128 反例共同支持本次结论;旧 head 的 review 或截图不替代当前检查。
额外普通 backlog、drainer 和 condition 又维护一份待处理状态,却只把同一个入口阻塞点后移;应在现有 dispatch/Inbox 所有者内完成有界准入,保留普通顺序并让已授权优先消息可被识别。本 PR 应修复原事件读取线程的有界背压并补足相邻负例,不需要重写整个 Lark provider 或引入另一套队列。新增调度状态有部分可避免的维护成本。共享 origin 的兼容边界应保留,普通路径的实测 parity 也应保留。当前 7fd 的 packaged UI 使用公开 synthetic API fixture 检查设置默认页、展开区域、窄屏及错误恢复;它不证明已安装 App、真实 Lark 接收或模型实际采纳。当前 7fd 的 packaged 设置页已检查三条混合状态路由、长名称、Goal/管家展开、390×844 窄屏和 503 后重载恢复;文字层级及权限/不可用提示可读,列表详情需滚动。未验证已安装 App、真实 Lark 网络与模型采纳。待两个 finding 修复后,对新 exact head 重新核验。
English verdict: REQUEST_CHANGES — the 128-message backlog still blocks native steering, and this head adds a maintainability-ratchet regression.
| with backlog_condition: | ||
| if not ordinary_backlog and not dispatch.ordinary_full: | ||
| return dispatch.submit(lane, envelope, priority=False) | ||
| while len(ordinary_backlog) >= 64 and not backlog_closed: |
There was a problem hiding this comment.
[P1] 第二层 backlog 满时仍阻塞唯一事件读取线程。保持原 Turn 运行,在 native @ 前放入 127 条普通消息时 Goal/管家均通过;128 条时两路在 15 秒观察窗内均仍 running、native steering=0,随后必须经公开 interrupt 才能受控收尾。这里等待第 128 条 ordinary 入队,后面的 @ 还没有被读取,预留 worker 也无法帮助。请在现有 dispatch/Inbox owner 内保留有界普通顺序与恢复,同时不阻塞优先事件识别,并补 127/128、重连/未知发送负例;仅加大 buffer 会再次后移边界。
| """Only serialize transport work; actual ingress re-reads its authority.""" | ||
| capture_mention: Callable[[Mapping[str, object]], dict[str, object]] | None = None, | ||
| include_capture: bool = False, | ||
| ) -> Any: |
There was a problem hiding this comment.
[P2] 新增 Any 返回形状导致当前必需 maintainability ratchet 出现新的模块失败。同一个 smoke 在 immutable base c263f7c 只有 private_conversations.py 的既有 debt,本 head 额外报告本模块;独立 AST 计数 Any 从 56 到 62,而预算仍为 56。请为 lane/capture 及新增 helper 提供具体类型、在既有 owner 内收敛状态,或按预算程序给出同负载和维护价值依据;不要把这个新失败归入旧的 private_conversations debt。
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> (cherry picked from commit 9b2d34d427c104f39d232f91ec0a37272426be07)
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent, gpt-6.1-sol, OpenAI, runtime_reported, reasoning_effort=max
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
动机 / Motivation
飞书成员需要在同一个会话里补一句纠正,并在原 Turn 结束前送达。旧版在普通消息占满读取队列时会挡住后续 @。当前提交把排队模式的普通入站先存到 Topic Inbox,旧的 128 条积压反例已通过。选择实时引导模式时,64 条普通消息仍能挡住同一个已验证的 @。已交付的排队路径可以保留,当前评审边界包括两种支持原生 @ 的会话配置。仍需补齐实时引导的回压路径与安装后验证。
改动思路 / Approach
复用现有 Topic Inbox、来源调度和 Chat ingress receipt。在监听端保存原消息及路由,处理前重新核对绑定。真实 Chat owner 继续决定向原 Turn 引导、空闲排队和不确定结果的恢复。一个已有 worker 为符合条件的 @ 保留,但它只能处理读取循环已经交给它的事件。修复点仍在原 listener 和 Inbox 的准入边界。本次评审覆盖已有绑定的 Lark Goal 和管家会话,包含排队与实时引导两种接收方式。
具体改动 / Changes
固定审查 828df11c2015f98c6355ae9018ef9a1a1c08fe7d。GitHub 返回的基线 c263f7c78353fcaa914f23475d4d99d07eab7c01 对应 116 个 diff 文件。逐一核对了其中 103 个路径在当前主干共有祖先和候选间的内容与模式。按实际共有祖先 69ddc610,本 PR 的改动是 14 个文件、+1431/−131,覆盖设置帮助、Chat 入站、Lark Inbox 与现有调度及测试。 现有会话契约
关键代码讲解
topic_intake_route只为session_queue生成持久入站路由。其后LarkTopicInboxIntake保存原 provider envelope、顺序、路由摘要和开始标记。重连只处理仍匹配原绑定的未开始消息,保留未知结果。criteriondurable-original-input已实现。 路由 原消息保存deliver_native_mention和planNativeMentionIngress共用原 Chat 回执。Bot 身份、原 Session 与活跃 Turn 的来源一致才可发送,附件、结束的 Turn 和无回执恢复有各自结果。criterionexact-source-receipt已实现。 Chat 入站 计划规则_profile_supports_mention_steering允许session_queue和live_steering使用预留 worker。实时引导下的普通消息仍在唯一读取循环里调用会等待容量的submit。criterionactive-correction-under-pressure尚未达成。 支持条件 读取阻塞处
对主干的风险 / Risks
P2|实时引导模式的第 64 条普通消息仍会挡住原生 @。 同一合成 provider feed、真实 File Chat store 和脚本化 Codex stdio,只改已绑定连接的模式及普通消息数。在普通答复尚未释放时,63 条下两种模式都送达一次,64 条排队模式也送达。64 条实时引导模式下,4 秒内读取循环还没读到 @;原 Turn 保持运行,turn/steer 为零,原生回执不存在。测试结束才释放普通回复。请在现有准入 owner 保证两种模式的普通回压不挡优先识别,保留 FIFO、原绑定及不确定结果边界,并保留同一 63/64 对照。
新提交定向 9 项通过,包含 Goal 与管家在 63、64、128 条排队流量下的送达,以及三种重连恢复。旧 7fd09d1f 用同一 63/128 夹具为 2 通过、2 失败。维护性检查里 goal_topic_runtime.py 的 Any 恢复到基线 56。当前 535 项 Python、7 项 TypeScript 和 standard premerge 的 6 项直接、12 项自动检查通过。没有可实时引导的绑定时,base 和 head 均可在释放前进入四个普通 worker。新的实时模式反例仍失败。
我的整体评价 / Verdict
请求修改当前提交。先修两种模式共用的读取准入,再复测当前 Turn 送达与恢复。复看了上版打包截图。当前提交的 Lark 设置组件和中英文帮助与截图所测版本一致。复看桌面混合连接、390px 展开和失败恢复后,三种方式及权限仍可读。criterion installed-provider-adoption 保留独立验收。真实飞书网络、安装态和模型采用仍需独立验收。 设置渲染
English verdict: REQUEST_CHANGES for 828df11. A 64-message ordinary backlog still stops the listener from reading a verified mention in live-steering mode. The queued-mode and 63-message controls deliver to the original running Turn.
| report_retained_input() | ||
| else: | ||
| envelope = json.dumps({"event": event, "mention_capture": mention_capture}, ensure_ascii=False) | ||
| if not dispatch.submit(lane, envelope, priority=priority): |
There was a problem hiding this comment.
[P2] 实时引导模式的普通回压会拦住后续原生 @
这个读取循环对 live_steering 的普通消息仍同步等待 submit 释放容量,因为持久入站只适用于 session_queue。同一真实 listener、File Chat store 和脚本化 Codex stdio 中,首个普通答复延迟时,63 条下两种模式均送达,64 条下只有排队模式送达。实时引导的原 Turn 仍在运行,但 4 秒内读取器未读到 @、turn/steer 为零、没有回执。请在现有 listener/Inbox owner 保持优先事件可识别,同时保留普通 FIFO、原绑定与未知结果恢复。回归覆盖同一 63/64 双模式对照。
…ble-admission-delivery-20261109 Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Goal and delivered outcome
Lark Goal channel and steward connections choose delivery per connection today. A native mention of the bound Bot can reach the active Turn as steering in a compatible bound Session. The same mention starts ordinary queued input while the Session is idle. Other messages follow the connection policy.
Verify the Bot by provider identity and use the existing Chat ingress receipt before choosing a destination. Busy text can reach the exact Turn before its ordinary reply completes. Files, an ended Turn, and uncertain delivery have separate replies. Recovery from an Inbox event without a Chat receipt leaves the original message available and records uncertainty. The listener uses the existing worker pool with one worker reserved for verified live mentions.
Live steering under backlog
The review reproduced a mode-specific failure. In live steering, 63 ordinary messages let the stream reader reach a later verified mention while 64 could block it. Queue mode continued to reach the mention. The correction also writes ordinary live inputs to the existing Topic Inbox and records the observed Session and Turn at admission. On recovery, an ordinary live input can steer only that captured Turn. A finished Turn or an input received while idle gets an explicit reply. The existing native mention path still reserves the same worker, and an uncertain send remains visible in the Inbox.
a20cd9e484617628c96a720b2bd4dabc0420c3a7aa475b29f1976a4fde901deca84672ddb3415152. It is excluded from the 265 passing cases.The packaged settings journey passed with synthetic API data in the Goal channel and steward scopes. Independent review of the updated head and live adoption on an installed Lark connection are pending.
Listener saturation and recovery
A busy Goal or steward reply formerly held the only stream reader once the ordinary buffer filled. The listener now stores authorized ordinary inputs in the existing Topic Inbox before slow reply work. It keeps the full provider envelope and arrival order, and wakes the existing source lane by reference. The original Chat queue, App listener and TypeScript steering owner continue to decide and execute their respective effects.
A verified native mention can reach the observed active Turn with 128 earlier ordinary messages. Unstarted input resumes after reconnect only against its original binding. The Inbox retains started inputs whose delivery is uncertain and prevents automatic replay. It also keeps previously captured input from following a changed Session or Topic.
Candidate source
828df11c2015f98c6355ae9018ef9a1a1c08fe7dis validated separately below. The visual evidence captures the existing settings presentation from the earlier revision.Live Lark adoption, independent review and release installation remain open. The provider can drop events before LoopX receives them, so the durability boundary begins at the Inbox capture. Asynchronous Inbox and separately owned project-assistant routes retain their existing behavior.
Author declaration
main.Earlier validation
Tested source
56fe2b33e9cd9d2c23b3db105530b5928d964834. Fixture inputs are synthetic and use the public scripted Codex app-server protocol.test_chat_server_closes_lark_goal_topic_runtimeconstructs a server withoutbackground_servicesand fails identically on the pre-change checkout. The test and failing owner files are identical across the verified PR base.Frontend visual evidence
Packaged first viewport · Goal channel routing · a20cd9e
Packaged first viewport · steward connection at 390 px · a20cd9e
These two captures use public fixture data. The following before and after captures are from the earlier UI revision.
First viewport · steward connection · 56fe2b3
Before · steward connection · b9b2501
Goal channel queue · before and after on desktop
Goal channel queue · after at 390 px
All captures use the packaged Chat UI and public fixture data. The existing settings dialog keeps its mode controls and primary action. The narrow layout uses shorter help in the same cards. Native success and failure messages use the existing source reply path.
Scope and continuation
The listener, Inbox, Turn owner and model thread are reused. The compatible bound Lark connection can be qualified independently. The next adoption evidence is an authorized test with an installed build, followed by the separately owned private/project-assistant path. Async-only channels still queue in the Inbox.