fix(lark): isolate Agent Goal Channel binding resolution - #3992
Conversation
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
评审 head:c67354f47a12b5cf05d681dd82a0e045b9421314。结论:Request changes;不是合并许可。
动机
原有 periodic-report 已有阶段完成触发、编辑输入、冻结产物、投递 Todo 和发布链路,但在 Goal Channel 中对某个 Agent 说“请生成周报”没有接到这条链路。本 PR 增加手动入口,减少用户切换到 CLI 的成本。这个方向有价值,但它是 Goal Channel 报告入口,不是新增 Personal Workspace 前端交互,不应仅为了 v1.0 发布赶进主干。
改动思路
Lark extension 保留原始消息及 provider 身份证据,只向 capability 返回带 Goal/Agent、请求摘要和 binding revision 的中立 observation。quota 注入 reader,将请求投影为 governed capability intent;consume-pending 复用现有 editorial、generation bundle、Workspace projection、publication candidate 和 delivery Todo。只有持久化 delivery_ready receipt 后才 ACK,ACK 失败时复用 receipt 重试,不重复建 Todo。
正向路径已通过现有 CLI 集成测试:单一原生 mention → request → quota governed action → editorial_required(不 ACK)→ 编辑响应 → delivery_ready + 一个投递 Todo → ACK 后请求消失。consume 本身没有执行远端发送;实际发送仍由已有投递链路负责。关闭订阅时 capability 不调用 reader,Lark reader/settler 也通过 drain/ack activation 门禁;安装或发现 provider 不等于授权。
具体改动
periodic_report_request.py:_resolved_request_context绑定注册 Agent、Goal Channel、target、inbox;_explicit_weekly_report_request判定自然语言;read/settle 负责 observation 和 ACK,新增生产模块 423 行。event_inbox.py、group_history.py、goal_topic_runtime.py:传递 sender_type、原生 mention 数量及 addressing_source,保留消息来源判断所需证据;原始文本不进入 capability observation。pending_intent.py:_manual_request_intent复用 preset/trigger;合并 provider 请求与已有 sidecar;consume 复用已有冻结产物和投递 Todo,增加 settlement-only retry。- capability
post_writeback_hook.py校验 manual request schema/摘要/actor/addressing,复用既有 trigger 评估;capabilitycli.py、顶层cli.py、cli_commands/lark_inbox.py、quota.py注入 reader/settler,确有生产调用路径,不是测试专用模块。 - 共享
cli_commands/post_writeback.py新增 identity 不完整时的 neutral skip:不调用 hook、不产生 failure。这是独立的共享行为变化,需要单独评估与报告触发的必要关系。 - protocol 文档描述新入口和边界;四个测试文件覆盖 provider 路由、CLI 全链路、消费重试、identity skip 和 sender type。
总计 16 文件、+1919/-40:生产 +897/-39,测试 +984/-1,文档 +38。复用既有产物/投递链路是正确的;最高价值简化不是重建另一套报告服务,而是缩小入口识别和 binding 解析责任,并拆出不必要的共享 dispatcher 行为变更。
对主干的风险
[P1] 讨论/询问被升级成报告生成请求
位置:loopx/extensions/lark/periodic_report_request.py 的 _REPORT_ACTION 与 _explicit_weekly_report_request(约 43–86 行)。当前规则是任意位置命中“周报”与“写”等动作子串,再排除少量否定/完成问句。
独立通过真实 ingest → read 路径复现:带单一原生 Agent mention 的“我写过周报,想讨论一下格式”和“how to write a weekly report?” 均返回 manual request,而应保持普通讨论。它不是单纯文案误判:现有下游会把该 observation 提升为 governed action,要求 consume,再进入已有订阅授权的生成/投递链路。不能把“消息确实对这个 Bot 说”当成“用户要求生成报告”。
最小修复:对明确命令建立收敛的完整意图解析结果(例如 request/discussion/ambiguous);无法确认则不升级。不要继续累加零散 substring 黑名单。加入这两个反例、明确中文/英文命令正例和取消反例,验证讨论不会产生 pending intent、生成或 ACK。
[P2] 另一个 Agent 的不同 target 使当前 Agent 的有效请求不可见
位置:loopx/extensions/lark/periodic_report_request.py:169 的 binding_for_goal(... provider_target=target, connection_id=...)。
独立反例先验证只有 alpha connection 时返回一个有效请求;再加入注册的 beta Agent connection 和单独的 beta provider target,alpha 原请求读取抛出 Goal Channel provider target does not match target_ref。原因是现有 binding_for_goal 先对所有 sibling connection 用 alpha target 执行解析,再按 connection_id 筛选。上层 pending_periodic_report_intents 捕获 ValueError 后将 provider observations 置空,使正确请求在 quota 中静默消失;beta 不应影响 alpha。
最小修复:先按明确 connection 选定原始 binding,再用该 binding 的 target 解析;复用已有精确选择思路,不要把单个 target 传给全连接集合。加入不同 target 的双 Agent 正例,以及当前 Agent 自身配置错误仍拒绝的反例。#3983 的 reconnect root 路径已经暴露过同类解析边界,但其局部修复不会自动覆盖本入口。
验证与剩余边界
本地在上述 exact head 跑四个改动测试模块:83 passed;另加 3 个独立语义探针:3 failed,分别对应上述两个问题。远端该 head 的 Python shards/aggregate、Windows、checks、build、DCO、dependency、Sonar 已成功;发布专用任务跳过。绿色 CI 没有覆盖这两个反例。
尚未独立完成所有共享面的 pre-change/disabled/enabled 配对验证:尤其 event inbox 新增持久字段和 identity-incomplete dispatcher 返回值,不能仅凭关闭订阅后没有报告来声称 default-off 全隔离。此项仍是 unverified,批准前应补齐或把共享行为拆出明确披露;作者声明的完整 canary/TS 检查不冒充本次独立执行。未执行真实 Lark 外发,也未进行无授权的线上验证。
我的整体评价
复用已有报告链路、内容无关 observation、持久回执后 ACK 和 ACK-only retry 都是正向设计;但入口现在把讨论当命令,又会被别的 Agent 的 target 阻断,未达到 PR 声明的明确请求与 Agent 隔离条件。建议先修这两个边界,再补齐共享 default-off 配对验证。改动比例仍需结合共享 dispatcher 拆分重新判断,当前不批准,不建议作为个人工作区 v1.0 的抢合并项。
English verdict: REQUEST_CHANGES at c67354f. The existing report pipeline is reused well, but addressed discussion is promoted to a manual generation request, and an unrelated Agent connection with another target breaks the valid current-Agent request. 83 focused tests pass; three independent semantic probes fail. Remote CI is green, but full shared-surface default-off counterfactual validation remains unverified. No merge performed.
Implementation update at
|
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
评审 exact head:d3ea96ef95b0b879f5807501d11364231eea766c。这是对扩展后完整 23 文件 diff 的重新评审;结论仍是 Request changes,不是合并许可。
动机
本 PR 想让用户在 Goal Channel 中对某个 Agent 发出明确的“生成周报”请求,并复用现有 periodic-report 的编辑、冻结产物、投递 Todo、发布和回执链路。新 head 进一步把原先 composition root 对 Lark reader/settler 的直接认识,改成 extension manifest 声明、运行时发现、capability 组合的 provider adapter。方向上,“入口留在 provider、报告状态机留在 capability、kernel 不依赖 Lark”是正确的边界。
但原始用户问题只是一个手动报告入口。目前完整改动达到 23 文件、+2603/-61(生产约 +1352/-60、测试 +1184/-1、文档 +67),并引入新的通用 manifest schema、动态 import/factory、端口组合和多 provider 结算语义。相对原问题,这个机制成本和长期维护面尚未被证明成比例;新抽象还出现了未定义的多 provider 所有权行为,并且原有两个行为 blocker 没有修复。
改动思路
正向路径是:安装并启用且 doctor-ready 的 Lark extension → [[hook_adapters]] 声明 reader/settler ports → discover_extension_hook_adapters 校验权限、激活态、factory 和精确端口集合 → build_quota_interaction_projection_hooks 把 reader 注入已有 pending-intent hook → 原生 mention/reply 被转为内容无关 manual request → quota 投影 governed capability intent → consume-pending 复用既有 editorial、generation bundle、Workspace projection、publication candidate 与 delivery Todo → durable receipt 写入后重新发现 settler 并 ACK provider inbox。
负向路径中,未安装或已禁用 extension 时 discovery 不返回 ports;factory/activation 失败被隔离成 hook failure,base periodic-report hook 保留。生命周期测试覆盖 absent → enabled → disabled,extension runtime 与 import-boundary 测试通过。顶层 CLI、quota 和 scheduler follow-up 已移除 Lark-specific reader 构造,新增模块有真实生产调用点,不是测试专用脚手架。
不过多 provider 组合丢失了 observation 的 adapter/port provenance;settlement 只能按注册顺序盲试 handler。这个状态机无法区分“不是我的请求”和“我是 owner 但暂时失败”,因此并未完成它公开宣称的 provider-neutral 组合契约。
具体改动
loopx/extensions/manifest.py、loopx/extensions/hook_adapters.py:新增hook_adaptersschema、权限/phase/token/port 校验、动态 factory 发现以及 failure hook 隔离。loopx/capabilities/interaction_hooks.py:把 extension ports 组合为 periodic-report reader/settler,并为 quota/scheduler 提供统一 hooks。loopx/extensions/lark/extension.toml、provider.py、periodic_report_request.py:Lark v1.6.0 声明 adapter,解析 Agent/Goal Channel/inbox binding,识别请求并提供 read/settle ports。pending_intent.py、post_writeback_hook.py、cli.py:把 manual request 绑定到既有 preset/trigger,复用 durable report 链路并支持 settlement-only retry。event_inbox.py、group_history.py、goal_topic_runtime.py:保留 sender、原生 mention 和 verified reply 所需证据;原始消息不进入 capability observation。quota.py、quota_scheduler_followup.py、顶层 CLI 路径:改为 capability-owned discovery,不再直接 import Lark request adapter。- 两份协议/extension 文档说明启用、doctor、权限、失败隔离和升级要求;六个测试文件覆盖 manifest、lifecycle、CLI、intent、Goal Channel 与 import boundary。
行为变更有文档披露;通用 hook/port 命名没有夸大 Agent authority,也没有给 extension 新增隐式写权限。machine obligation 在形成 governed intent 后是明确的,问题不在“guidance”措辞,而在此前的自然语言分类会把非请求错误提升为强制动作。
对主干的风险
[P1] 讨论/教程询问仍会被提升为报告生成请求
位置:loopx/extensions/lark/periodic_report_request.py 的 _REPORT_ACTION / _explicit_weekly_report_request。规则仍是任意位置分别命中“周报/weekly report”和“写/write”等子串,再排除少量黑名单。
在当前 exact head 经真实 ingest → read 独立复现:“我写过周报,想讨论一下格式”和“how to write a weekly report?” 都产生 manual request。下游会把它变成 must_attempt 的 governed capability intent,并进入已有订阅授权的生成/投递链路。最小修复是使用收敛的 typed intent 结果(request/discussion/ambiguous),不确定时不升级;加入这两个反例及中英文明确命令、取消、完成查询的成组测试。
[P1] 多 provider settlement 会被首个非 owner 的失败结果永久截断
位置:loopx/capabilities/interaction_hooks.py 的 _compose_request_settler。它在第一个 handler 返回任意 Mapping 时立即返回,即使结果是 {"ok": false, "status": "request_not_owned"}。因此后面的真实 owner 永远收不到 ACK;durable receipt 每次 retry 都重复同样顺序,provider 请求会永久处于 settlement pending。
独立两-provider probe 以第一个 handler 返回 non-owner failure、第二个返回 settled,当前实现只调用第一个并失败。不能简单把所有 ok=false 都忽略,否则会吞掉真实 owner 的 retryable failure。最小修复是让 reader observation 持久携带受校验的 extension/adapter ownership provenance,并把 settlement 精确路由到同一 binding;或定义 typed not_owned 与 owned_but_failed 结果并测试顺序无关、owner 失败重试和重复 ACK。
[P1] Lark extension 版本升级破坏现有 Miaoda CLI 合同,required CI 已失败
位置:loopx/extensions/lark/extension.toml 将 bundled provider 升到 1.6.0,但 tests/extensions/test_periodic_report_miaoda.py 的 delivery/sink fixture 仍绑定 1.5.0。安装当前 bundled extension 后执行 periodic-report publish-miaoda 返回 active Lark extension does not match the Miaoda sink binding,而不是预期 preview 成功。
远端 required test-shard (1) 因同一测试失败,aggregate pytest 随之失败;本地单测也稳定复现。最小修复是更新并集中复用 canonical bundled Lark version,使已有 Miaoda binding 测试继续证明精确版本契约,而不是放宽生产版本匹配。
[P2] 另一个 Agent 的不同 target 仍会使当前 Agent 的有效请求不可见
位置:periodic_report_request.py 的 _resolved_request_context 调用 binding_for_goal(... provider_target=target, connection_id=...)。底层在按 connection id 过滤前,先用 alpha target 解析所有 sibling connection;加入 beta Agent 的独立 target 后 alpha 读取抛出 Goal Channel provider target does not match target_ref,上层捕获后静默丢掉 observations。
最小修复仍是先精确选择当前 Agent/connection 的 raw binding,再用它自己的 target 解析;加入双 Agent/不同 target 正例和当前 Agent 自身配置漂移的负例。
默认关闭隔离目前只有 discovery lifecycle 的局部配对:absent/disabled 不提供 ports,enabled 提供 ports;尚未把 pre-change、disabled、enabled 在 quota、scheduler、consume-pending、help/schema 与 persisted projection 上做完整 paired counterfactual。新增 framework 的 scope-fit 有真实 caller,但 change proportionality 仍为 not yet proven:对一个手动入口引入 415+ 行通用生产机制,却缺少稳定的多 provider ownership contract;这是独立阻塞条件。
我的整体评价
复用现有 periodic-report 状态机、provider 私有消息不越界、durable receipt 后 ACK、通过 manifest 移除 composition-root 的 Lark import,这些都是正向设计。新增 schema 校验、doctor/permission gate 和 failure isolation 也有可维护价值。
但当前 head 不能合并:两个已发布行为 blocker 原样存在,又新增了多 provider settlement 截断;bundled version bump 还让 required CI 和现有 Miaoda CLI 合同直接失败。建议先做最小行为修复并补齐回归;再决定通用 adapter framework 是否保留。若保留,必须先定义可验证的 observation ownership/settlement 路由,完成 disabled/enabled 全共享面 counterfactual,并说明其相对原问题的比例价值;否则回退到更窄的 provider/capability seam。
当前 exact-head 独立验证:extension runtime + control-plane import boundary 75 passed;四个独立负向 probe 4 failed(两条讨论误判、sibling Agent target、multi-provider settlement);Miaoda preview 单测另有 1 failed,与远端 test-shard (1) 失败一致。远端 DCO、dependency、build、checks、Windows、shard 2 成功,但 required Python aggregate 不通过。未发送真实 Lark 消息,也未执行外部写入。
English verdict: REQUEST_CHANGES at d3ea96e. The manifest-based provider boundary has real callers and 75 focused runtime/import tests pass, but discussion is still promoted to generation, a sibling Agent target still hides valid input, multi-provider settlement stops at the first non-owner failure, and the v1.6.0 bundled-version bump breaks the existing Miaoda preview contract and required CI. Four independent negative probes plus the focused Miaoda test fail. Proportionality and full default-off counterfactual evidence remain blocking; no merge performed.
d3ea96e to
abc0449
Compare
Signed-off-by: huangruiteng <huangrt01@163.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
评审 exact head:abc0449d44766bf96a2220a8618ce84feaa333a9。结论:Request changes;不是合并许可。
动机
这个 PR 把此前较大的 Goal Channel 周报入口改动收窄成一个通用 binding 修复:当同一 Goal 有多个 Agent connection、每个 connection 引用不同 provider target 时,读取指定 connection 不应先拿它的 target 去解析所有 sibling binding。旧行为会让一个无关 sibling 的 target mismatch 抛错,进而隐藏当前 Agent 的有效 binding。问题真实、影响现有 setup/doctor/notification/topic 等生产调用,拆成 2 文件的窄修复是正向的。
改动思路
binding_for_goal 现在先用不带 provider target 的 bindings_for_goal 读取 raw candidates,再按 connection_id、agent_id 或 default connection 选中一个,最后只对该 selected binding 调用 _resolve_goal_binding。正向路径中 alpha target 只解析 alpha connection,beta sibling 不再干扰;负向路径中显式选择 beta 却传 alpha target 仍抛 does not match target_ref,失败归属保持在被选中的 binding 边界。
这个 decision boundary 比“先解析全集、再筛选”正确,也没有增加新 schema、权限或 provider 写动作。它是默认生效的 bug fix,不声称 default-off;authority 名称、guidance/obligation 和领域文案均未变化。
具体改动
loopx/extensions/lark/goal_channel_contracts.py:binding_for_goal改为 select-then-resolve;connection_id优先于agent_id,缺省时仍读取 stored default,最后统一返回_resolve_goal_binding(selected, provider_target=...)。_resolve_goal_binding和bindings_for_goal未改变:前者仍校验 target name/provider/channel/identity 并保留 goal-local pinned message;后者仍负责 v0 单 binding 与 v0 connection-set 的兼容读取。tests/extensions/test_lark_goal_channel_binding_isolation.py:新增双 Agent/双 target fixture,覆盖目标 Agent 成功解析和错误 target 仍 fail-closed 两条路径。
关键代码讲解
binding_for_goal:从“resolve every candidate then select”改成“select one raw candidate then resolve”,消除了 sibling connection 对当前选择的非局部影响。_resolve_goal_binding:仍是 provider target 解析和身份/channel 合并的唯一 owner;本 PR 没有复制 target 校验规则。test_binding_resolution_isolates_selected_agent_from_sibling_target:证明 intended positive/negative contract,但尚未覆盖当前 main 新增的 invalid-default deterministic fallback 合同。
精确 diff 为 2 文件、+93/-22:生产 +31/-22,测试 +62,没有机械搬移、文档、生成文件或私密材料。scope fit 有多处真实生产 caller,改动规模与问题成比例;未来向前看的最小重构就是在 rebase 时保留 default fallback 的单一确定性规则,不需要再加一层抽象。
对主干的风险
[P1] 当前 head 与 main 冲突,并会回退刚合入的确定性 fallback 合同
GitHub 当前 mergeStateStatus=DIRTY。main 的 6abf5b289 已把失效 default_connection_id 的读侧 fallback 改成 min(connection_id),与 disconnect writer 的 promotion 规则一致;本 head 在同一函数把 fallback 写回 candidates[0]。独立 probe 用三个按非排序 insertion order 存储的 connection,当前 head 选择 lark_f598...,而 main/writer 合同要求 lark_2b2c...,matches=False。
这不是可忽略的文本冲突:若解决冲突时保留本 PR chunk,notify/setup/automation read 可能在 stale default 下选到与 writer 不同的 Agent topic;若只保留 main chunk,原 sibling-target 隔离修复又会丢失。最小修复是 rebase 当前 main,并合并两条规则:先 raw select;default 缺失时 min(connection_id);只对最终 selected binding resolve provider target。请保留/扩展 main 的 invalid-default fixture,并加一个组合 fixture,证明 non-sorted siblings + invalid default + provider target 同时满足 deterministic fallback 与 target isolation。
本地 exact-head 验证:新 fixture、shared-target 和 Goal Topic connection suites共 39 passed;Ruff 与 git diff --check 通过。远端当前 head 没有 status checks。未执行真实 Lark 写入;测试只读/合成状态足以验证纯 binding selector,但在冲突解决后的新 head 仍需重跑这些 focused suites 与 required CI。
我的整体评价
select-then-resolve 是正确且最小的修复,拆掉此前与 periodic-report 入口混杂的大范围改动也显著改善了可审阅性。我支持保留这 31 行生产改动及 focused fixture;当前唯一实质 blocker 是与最新 main 的同函数冲突会造成跨 Agent 路由回退。rebase 后把 min(connection_id) 与新 selection boundary 组合起来、补一条组合回归并跑绿 CI,即可快速复审。当前不合并。
English verdict: REQUEST_CHANGES at abc0449d44766bf96a2220a8618ce84feaa333a9 (author-owned PR, so published as COMMENTED). The select-then-resolve fix is narrow and correct, and 39 focused tests plus Ruff pass. However, the head is merge-conflicted and restores insertion-order candidates[0], regressing current main commit 6abf5b289 where invalid defaults deterministically fall back to min(connection_id) to match the disconnect writer. Rebase and combine both rules, add the combined regression, then rerun required CI; no merge performed.
abc0449 to
3901256
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
评审 exact head:3901256d3c472717b36ac677d8a08ed01cce3a34。结论:Approve;由于这是 author-owned PR,GitHub 不允许正式自我批准,因此以 COMMENTED 发布,不是额外的合并授权。
动机
同一 Goal 可以绑定多个 Agent connection,并且每个 connection 可以引用不同的 Lark provider target。旧实现会先把调用方提供的单个 target 应用到所有 sibling binding,再按 connection/Agent 选择;因此一个无关 sibling 的 target mismatch 就能阻断当前 Agent 的有效 binding。这个问题会破坏跨 Agent 隔离,修复目标明确且直接对应生产调用路径。
改动思路
当前实现改为 select-then-resolve:先读取不带 provider target 解析的 raw candidates,再按显式 connection_id、agent_id 或 default 选择唯一 binding,最后只对被选中的 binding 调用 _resolve_goal_binding(..., provider_target=...)。这样 sibling target 不再污染当前选择,同时当前 binding 自身 target 错配仍然 fail closed。
此前复审指出 rebase 冲突会把失效 default 的确定性 fallback 从 min(connection_id) 回退为 insertion-order candidates[0]。本 head 已同时保留 main 的 min(connection_id) 规则和本 PR 的 select-then-resolve 边界,因此读侧 fallback 继续与 disconnect writer 的 promotion 规则一致。
具体改动
goal_channel_contracts.py:binding_for_goal先选 raw connection,后做 provider target 解析;显式 connection 优先于 Agent,缺省读取 stored default,default 失效时按最小 connection id 确定性选择。_resolve_goal_binding仍是 target name/provider/channel/identity 校验的唯一 owner,没有复制校验逻辑,也没有放宽错误 target。- 新增隔离测试覆盖 alpha connection 不受 beta target 干扰,以及为 beta 错传 alpha target 时继续拒绝。
- 保留既有 invalid-default 与 disconnect promotion 回归。独立组合 probe 进一步覆盖 non-sorted siblings + invalid default + 每个 connection 不同 target:fallback 选择最小 connection id、只用其 target 解析,错误 target 仍被拒绝。
精确 diff 为 2 文件、+98/-26,属于 Lark extension 内的窄 bug fix,没有新增 schema、provider 写动作、权限或抽象层。
对主干的风险
风险较低且边界清晰。默认生效是因为它修复现有 binding selector,而不是新增 activation surface;typed state、authority、default-off activation、guidance/obligation 语义均未变化。主要风险是 selector 优先级或 stale-default 行为回退,但当前实现和测试同时守住了显式 connection/Agent 选择、确定性 fallback、selected-target 校验三条合同。
独立验证结果:focused suites 42 passed;Ruff 与 git diff --check 通过;组合语义 probe 通过。远端 12 项 checks 全部完成且成功(发布任务按预期 skipped),GitHub 当前报告 MERGEABLE,BLOCKED 仅来自 review requirement。未执行真实 Lark 写入。
我的整体评价
这是正向且成比例的修复。它把解析边界放在正确位置,消除了 sibling connection 的非局部干扰,同时保留 main 已建立的确定性 fallback,不需要顺带引入新抽象。我批准当前 exact head;heartbeat 本身不执行合并。
English verdict: APPROVE at 3901256d3c472717b36ac677d8a08ed01cce3a34 (published as COMMENTED because GitHub blocks formal self-approval on an author-owned PR). The select-then-resolve boundary correctly isolates sibling Agent targets, preserves deterministic min(connection_id) fallback, and keeps wrong-target resolution fail-closed. Forty-two focused tests, Ruff, diff-check, an independent combined semantic probe, and all remote required checks pass. No merge performed.
- 255295f lark agent goal channel 绑定隔离 (loopx-project#3992) - 64a0ab6 长程定位精修 + 1.0 工作区指南 (loopx-project#4008) - 89ac4d5 workspace Goal 目录优先渲染 (loopx-project#4007) 文档融合: README.md 采用上游官方中文版(678 行)升为主文件, 修复其中 English/zh-CN 链接与双语表述;readme-demo-surface-smoke 断言按新官方中文内容适配(语义等值)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
Summary
main;Scope
This PR is intentionally limited to the generic Goal Channel binding fix. It does not classify report requests, scan inbox messages, create periodic-report intents, or add report-delivery behavior.
The Agent-authorized provider-neutral report action and manifest-discovered adapter are split into follow-up PR #4001.
Validation
loopx canary premerge --from-git-diff --git-diff-base origin/main --goal-id loopx-meta: 9/9 checks passed;cqr_ea034623f4c57841068b;ea034623f4c57841068b04d0e8145e2cee05ee8e51dfd9f3424f1efd7bc2f4ad;git diff --check origin/main...HEADpassed.No real Lark message was sent. This PR will wait for independent review and will not be self-merged.