Files
dingtalk-workspace-cli/docs/pr-860-multi-im-optimization-analysis.md

87 KiB
Raw Permalink Blame History

PR #860 Multi IM 优化:合并后完整代码分析与跨场景复用报告

PR #860:DingTalk-Real-AI/dingtalk-workspace-cli#860

#860 当前标题:feat(im): harden Multi IM and publish complete Chat Schema

#860 当前状态:Open、可合并;核对时共 14 个提交、129 个变更文件,+69,391 / -13,045。

唯一分析范围:main@6376f294dab0d0a7bd2f5904077aab89383684d1...codex/multi-im-optimization@33ceab6000d5f18eddbc1c0c97544233f5dd42d6。

报告原则:只分析当前 PR #860 的合并后整体代码。提交来源和中间分支不再作为独立分析单元;所有规模、架构、文件、风险和复用结论均以当前 #860 的完整 diff 为准。

1. 核心优化思路

1.1 一句话结论

PR #860 的本质不是增加一批 IM 命令,而是把 Chat/Event 能力从“分散、可调用”升级为“意图可路由、目标可确定、执行有边界、输出有契约、风险可确认、能力可发现、文档与代码可持续校验”的完整产品链路。

整体优化链路可以概括为:

用户意图
  -> Golden Route 唯一入口
  -> Typed Resolver 确定目标
  -> Identity / Capability Preflight
  -> Bounded Runtime + Typed Confirmation
  -> Versioned Result / Error Ledger
  -> Authored Registry + Selection/Metadata
  -> Generated Schema + Skill/Reference
  -> Policy + Drift + Coverage Gates

1.2 核心方法总览

原有问题 核心优化方法 PR #860 整体落地 可复用价值
同一意图有多条相似入口 Golden Route:每个意图只推荐一个默认入口 统一发送、回复、读取、搜索、建群和监听入口,原始命令只作有理由的 fallback 通讯录、文档等领域都可先按意图收敛入口
名称、ID、URL 等目标解析分散 Typed Resolver:业务执行前先得到规范化目标 新增 targetresolver,全分页检索、精确匹配、歧义和不完整结果均 fail closed 可扩展为 DirectoryResolver、DocumentTargetResolver
调用前才发现参数、身份或能力不支持 Local Validation + Capability Check 建立 user/bot/webhook 能力矩阵,并前置校验时间、页大小、回溯窗口和目标互斥 适用于邀请、删除、文档覆盖、权限修改等写操作
输出依赖原始 API 或展示文本 Versioned Contract:输出稳定的机器契约 建立并发布 im.message-list.v1,统一消息、引用、资源、reaction 和 continuation 可定义联系人、文档、云盘的 v1 投影
分页、导出、下载可能截断或留下半成品 Bounded Execution:限制页数、条数、超时并支持原子提交 实现游标停滞检测、完整性账本、安全下载、no-clobber 和跨平台原子替换 适用于批量导出、备份、迁移和同步
高风险命令示例可能绕过确认 Typed Confirmation:Runtime 强制停下,确认后才执行 写入/破坏型 Schema metadata 与 Runtime gate 对齐,危险示例不预填 --yes 可用于删除联系人、覆盖文档、权限变更等高风险动作
能力可运行但 Agent 不可发现 Authored Registry + Generated Schema Chat Shortcut 达到 97/97;完整 Catalog 为 26 products / 898 tools 适用于任何具有大量组合命令的产品域
文档、Schema、Runtime 各自演化 Consistency Gates:把一致性变成 CI 规则 增加 Skill Chain、Schema compatibility、interface integrity、generated drift 和 changed-code coverage 可抽象为所有领域共用的质量框架

1.3 八个可复用的优化原则

原则一:从“API 优先”转为“意图优先”

先定义用户究竟要完成什么,再为每个意图选择唯一 Golden Route。底层 API、历史命令和兼容别名可以保留,但不应继续出现在默认发现路径中。这样能够显著减少 Agent 在多个相似工具之间随机选择的问题。

原则二:把目标解析变成独立基础设施

所有操作先经过统一 Resolver,将名称、ID、手机号、URL 等输入转换为类型明确的 canonical target。业务命令只消费解析结果,不再各自实现搜索、歧义处理或 ID 猜测。

原则三:把写操作拆成“计划”和“执行”

执行前明确目标、身份、能力、副作用和恢复方式。高风险操作只有在目标唯一且能力满足时才进入执行阶段。这种拆分既降低误操作风险,也让 dry-run、确认和审计更容易实现。

原则四:用版本化域模型隔离上游变化

列表、搜索、读取和写回执都投影到稳定的领域契约。调用方依赖 messageId、canonicalId、nextCursor 等规范字段,而不是供应商原始响应或终端展示文字。

原则五:所有长流程都必须有边界和恢复语义

分页、导出、下载、批量发送不能只保证 happy path;还要定义最大页数、最大条数、游标推进、临时文件、原子替换、checkpoint、部分失败和幂等重试。

原则六:让错误直接驱动下一步动作

错误需要区分未命中、歧义、身份不匹配、能力不足、权限不足、限流和服务端故障,并明确是否可重试以及建议动作。对 Agent 而言,错误是控制流的一部分,而非日志文本。

原则七:把知识一致性纳入工程门禁

Skill 负责路由,Reference 负责细节,Schema 负责机器发现,Runtime 负责真实行为,Policy 负责检查四者闭环。任何新增能力都应同步更新并由测试验证。

原则八:把“正式发布”定义为独立交付阶段

Runtime 中存在一个命令,不等于 Agent 已经能够正确使用它。能力还必须进入 authored Registry,具备 use/avoid hints、风险和确认 metadata,生成 Schema/Agent metadata,并退出临时 exclusion。PR #860 将这一原则具体化为 Chat 97/97、public Shortcut 265/265 和完整 Catalog 898 tools。

1.4 标准执行链路

用户自然语言意图
  |
  v
Golden Route:选择唯一推荐入口
  |
  v
Typed Resolver:解析用户、群、会话、消息等目标
  |
  v
Preflight Plan:固化 profile、身份、能力和副作用
  |
  v
Bounded Runtime:在分页、超时、数量和文件边界内执行
  |
  v
Versioned Result / Typed Error Ledger:返回可消费、可恢复结果
  |
  v
Authored Registry + Selection/Metadata:正式发布并指导选择
  |
  v
Generated Schema + Skill/Reference + Policy:持续防止契约漂移

1.5 复用时应迁移整条链路

不建议只复制某个 shortcut 或 Resolver。若新领域仍缺少稳定输出、错误分类和一致性门禁,局部复用很快会重新产生分散实现。通讯录、文档、云盘、知识库等场景应至少成组迁移以下能力:

意图清单 + Golden Route
  -> 统一 Resolver
  -> Plan / Capability Check
  -> 有界 Runtime
  -> 版本化结果与结构化错误
  -> 分层文档、Schema 与 Policy

2. 分析范围与阅读导航

2.1 变更规模与边界

本报告只使用一个三点对比范围:6376f294...33ceab60。它表示 PR #860 当前 head 相对当前 PR base 的完整净变化:

指标 当前 PR #860
状态 Open / mergeable
提交数 14
变更文件 129
新增 / 删除 +69,391 / -13,045
生产 Go 文件 38(+4,028 / -737)
Go 测试文件 30(+4,343 / -88)
Skill Markdown 30(+1,166 / -1,577)
主要生成 Schema 文件 6(+57,215 / -9,229)

#860 变更横跨:

  • Runtime:internal/app、internal/shortcut、internal/helpers、internal/errors。
  • 目标解析:新增 internal/shortcut/targetresolver。
  • Schema:chat/event 的 catalog、agent metadata、hints、registry。
  • Skill:mono、chat、event、shared 四类文档链路。
  • Policy:新增 Multi IM Skill Chain 检查并扩展上下文预算检查。
  • 测试:单元测试、契约测试、mock MCP smoke test、live audit 辅助脚本。

这种范围说明优化目标不是“让某几个命令能跑”,而是建立可持续扩展的产品契约。

69,391 行新增中,大量内容来自 Schema catalog 和 Agent metadata 等生成物,不能把总行数等同于手写业务逻辑。人工设计变更主要集中在:

  • Chat Shortcut 的 authored CommandRegistry、selection hints 和风险 metadata;
  • 本地参数校验、确认门禁、cursor 修复、shorthand 和跨平台路径;
  • Schema 完整性、目标消歧、分页、原子文件及跨平台 changed-code 覆盖测试;
  • Chat、Event、Shared 和 Mono 四层文档链路重构。

2.2 文档阅读导航

阅读目标 建议章节
快速掌握本次优化的方法论 第 1 章“核心优化思路”
理解为什么需要改造 第 3 章“优化前的典型问题”
理解 Skill、Runtime、Schema、Policy 如何协同 第 4 章“总体架构”
查看具体代码机制 第 5 章“核心代码优化分析”
查看文档组织变化 第 6~8 章
查看验证方法与质量门禁 第 9 章
复用到通讯录、文档、云盘和知识库 第 10~12 章
查看当前风险收口和整体结论 第 13~14 章
查看 Schema 发布、Runtime 收口和文件分类 第 15~18 章
查看 Go 生产代码和测试代码的专项总结 第 19 章
查看当前 #860 的整体价值与建议 第 20~21 章

2.3 结论类型说明

为避免把“PR 已实现内容”和“建议复用方案”混在一起,后文按以下方式理解:

  • 本次落地:能够在该 PR 的代码、Schema 或文档变更中找到直接依据。
  • 分析判断:根据多处变更归纳出的设计意图或工程影响。
  • 复用建议:面向通讯录、文档等新领域给出的迁移设计,并非声称已在本 PR 中实现。

3. 优化前的典型问题

3.1 同一意图存在多条入口

发送消息、查看群消息、回复消息等意图可能分别出现在 shortcut、底层 OpenAPI 命令、脚本和多份教程中。模型或用户容易选中功能相似但约束不同的路径,导致参数漂移、行为差异和排障困难。

3.2 目标解析散落在业务命令中

用户可能输入 conversation ID、openConversationId、群名、用户 ID、手机号或自然语言名称。若每条命令各自解析,就会出现:

  • 同一个名称在不同命令中命中不同对象;
  • 多结果时有的命令报错、有的静默选第一个;
  • ID 类型混用;
  • profile、tenant 或身份上下文不一致;
  • 新增一种目标类型时需要修改大量命令。

3.3 列表输出面向人而非机器

原始 API 数据结构大而不稳定,字段含义不统一,分页元信息可能丢失。Agent 需要猜测正文、发送者、消息 ID 和时间字段,后续回复、导出和审计难以可靠衔接。

3.4 长流程缺少完整性边界

消息列表、成员列表、导出、下载等操作天然包含分页或文件写入。如果没有最大页数、最大条数、下一页游标、临时文件和原子替换机制,容易发生无限翻页、半文件、重复结果或悄然截断。

3.5 文档与 Runtime 独立演化

命令已经变更但文档仍指向旧路径,或者 Skill 声称支持某个字段而 Runtime 没有对应输出。问题往往到真实 Agent 调用时才暴露。

4. 总体架构:四层协同

4.1 Skill 层:告诉 Agent 应该走哪条路

Skill 的职责不是罗列所有命令,而是完成意图路由、默认值选择、风险提示和按需加载 Reference。它应该短、稳定、偏决策,不应复制完整 API 手册。

4.2 Runtime 层:保证行为确定且可测试

Runtime 负责统一解析目标、执行能力校验、分页、结果投影、原子文件操作和结构化错误。即使调用者没有阅读文档,Runtime 也应保持安全边界。

4.3 Schema 层:提供机器可发现的真实能力

Schema catalog、agent metadata、selection hints 和 command registry 必须共同描述参数、枚举、返回值和入口选择。Schema 不是生成物附件,而是 Agent 运行时能力的一部分。

4.4 Policy 层:防止三层再次漂移

Policy 检查关键意图是否同时存在合法 Runtime 路由、Schema 暴露和文档说明,并控制 Skill 的上下文体积。它把系统设计转化为可持续执行的合并门槛。

5. 核心代码优化分析

本章按照“目标识别—路由决策—读取契约—长流程执行—错误与兼容治理”的顺序展开。各项机制之间不是孤立关系:Resolver 提供可靠目标,身份/能力矩阵选择执行路径,版本化投影稳定结果,分页与原子写保证完整性,错误和 profile 契约负责失败恢复与上下文一致性。

分析主题 主要代码区域 解决的问题
Target Resolver internal/shortcut/targetresolver 统一名称、ID 和自然语言目标解析
身份与能力路由 internal/shortcut/chat/*contract.go、unified_send.go 在执行前选择合法发送身份和路径
消息投影 chat_message.go、smart/chat_messages.go 将异构响应转换为稳定消息模型
分页与导出 conversation/message/group/export 相关实现 防止静默截断、无限翻页和半成品文件
事件监听 internal/app/event_listen_im.go 将 IM 事件封装为显式生命周期能力
错误与上下文 internal/errors、failure classifier、profilectx 提供可行动错误并防止跨 profile 漂移
兼容治理 参数别名、Schema metadata、selection hints 保持旧调用可用,同时引导新调用走 Golden Route

5.1 统一 Target Resolver

新增的 internal/shortcut/targetresolver/resolver.go 将目标识别从各业务命令抽离。Resolver 的价值在于把“输入是什么”与“接下来执行什么业务”分开。

统一解析应遵循如下优先级:

  1. 显式类型化 ID 优先,避免把合法 ID 当名称搜索。
  2. 显式 target kind 优先于启发式判断。
  3. 自然语言名称进入搜索,并保留候选集。
  4. 唯一命中才自动继续;多结果返回可选择候选。
  5. 未命中返回稳定错误码和建议动作。
  6. 解析结果携带 profile、tenant、来源和置信信息。

这样做带来三个直接收益:

  • chat、send、history、members 等命令共享完全一致的目标语义;
  • 新增手机号、邮箱、unionId 等输入方式时只扩展 Resolver;
  • 解析阶段可以独立测试,不需要触发真实写操作。

向通讯录迁移

可建立 DirectoryResolver:

输入:姓名 / 手机号 / 邮箱 / userId / unionId / 部门名 / deptId
输出:TypedDirectoryTarget
  kind: user | department
  canonicalId
  displayName
  matchedBy
  candidates
  profileContext

删除、调岗、批量邀请等高风险动作只接受唯一、类型确定的解析结果。

向文档迁移

可建立 DocumentTargetResolver:

输入:URL / docId / workspaceId / spaceId / 标题 / 路径
输出:TypedDocumentTarget
  product: doc | drive | wiki
  resourceType
  canonicalId
  containerId
  matchedBy
  candidates

这可消除文档 URL、知识库节点 ID、云盘文件 ID 混用造成的问题。

5.2 Unified Send 与身份/能力矩阵

unified_send.go、identity_contract.go 和 im_contract.go 将发送动作从“按 API 名称选命令”提升为“按目标、身份与消息能力选择执行器”。

推荐的决策维度包括:

维度 示例
目标 单聊、群聊、机器人会话
身份 用户身份、机器人身份、应用身份
内容 text、markdown、card、media
能力 是否允许主动发送、是否支持回复、是否支持卡片更新
上下文 profile、tenant、conversation

这种能力矩阵比在每条命令内写条件分支更易审计。发生能力不匹配时,应在真正发起网络请求前失败,并返回建议使用的 route。

可复用原则

通讯录中的“读取、邀请、修改、删除”,文档中的“读取、创建、编辑、分享、删除”,都应建立身份与能力矩阵。调用者表达的是业务意图,Runtime 决定具体执行入口。

5.3 im.message-list.v1 消息投影

消息列表相关代码将上游异构响应投影成稳定的版本化结构。核心思想是:保留原始信息的同时,提供统一的机器字段。

典型规范字段包括:

  • messageId
  • conversationId
  • senderId / senderName
  • messageType
  • text 或规范化内容
  • createdAt
  • replyToMessageId
  • raw(必要时用于诊断)
  • hasMore / nextCursor

版本号的意义是允许未来增加或调整字段,而不破坏依赖 v1 的 Agent 与脚本。

可复用原则

  • 通讯录:定义 directory.user-list.v1、directory.department-list.v1。
  • 文档:定义 document.search-result.v1、document.block-list.v1。
  • 云盘:定义 drive.file-list.v1、drive.transfer-result.v1。

不要让自动化直接依赖供应商原始响应;应通过投影层建立稳定域模型。

5.4 分页完整性与有界执行

PR 统一增强了消息、会话和成员列表的分页处理。一个健壮的列表命令至少需要:

  • 明确单页与自动翻页模式;
  • 返回 hasMore 和 nextCursor;
  • 支持 maxPages、maxItems 等硬边界;
  • 检测游标不前进或循环;
  • 去重并保持稳定顺序;
  • 明确结果是完整集合还是截断集合;
  • 在中途失败时返回已完成量和失败位置。

分页不是 UI 细节,而是数据完整性契约。尤其在“先查再写”的 Agent 流程中,静默截断会导致错误对象被操作。

当前需关注的问题

本次分析发现 +conversation-list 的单页模式存在一个边界风险:代码可能在解析下一页游标前提前退出,最终出现 hasMore=true 但 nextCursor=0。这不会否定整体设计,但应在合并前补回归测试并修复。

5.5 原子导出与资源下载

新增或强化的消息导出、资源下载路径采用“临时文件 -> 完整写入 -> 校验 -> 原子替换”的思路,避免失败时留下看似成功的残缺文件。

推荐流程:

解析目标
  -> 校验输出路径与权限
  -> 创建同目录临时文件
  -> 有界分页拉取/流式下载
  -> 校验数量、大小或摘要
  -> fsync/close
  -> 原子 rename 到最终路径
  -> 返回 typed receipt

失败时删除临时文件,保留已有最终文件,并返回失败阶段、已处理数量及是否可重试。

可复用原则

该模式适用于:通讯录批量导出、文档离线备份、附件下载、云盘迁移、知识库归档以及审批记录导出。

5.6 +chat-create 与 +messages-reply

补齐这类语义型 shortcut 的意义在于构建完整 Golden Route:用户不需要先理解底层产品 API,再自己拼接参数。命令命名直接对应业务意图,Schema 则描述必要约束。

设计原则是:

  • Shortcut 只暴露稳定、常用的业务参数;
  • 复杂底层参数放入高级 Reference;
  • 输出统一 envelope;
  • 目标解析复用 Resolver;
  • 写操作具备 preflight、明确身份和结构化回执。

5.7 event +listen-im

新增 IM 事件监听入口,将底层事件总线能力收敛为 Agent 易理解的生命周期命令。文档进一步拆出 keys、lifecycle、operations、output 四个主题,说明事件能力被视为长期运行流程,而不只是一次 API 调用。

事件监听需要明确:

  • start、status、stop 的生命周期;
  • profile 与租户隔离;
  • endpoint/key 的稳定标识;
  • 前台与后台模式;
  • 超时、重连和退出语义;
  • 事件 envelope 与消息投影;
  • 重复事件、顺序和幂等边界。

可复用原则

通讯录变更事件、文档协作事件、云盘文件事件都可以复用同一监听骨架,只替换事件类型与投影器。

5.8 结构化错误与服务端失败分类

internal/errors 与 server_failure_classifier.go 将错误从一段不可解析文字升级为类型化结果。稳定错误至少应包含:

  • code
  • message
  • stage
  • retryable
  • details
  • suggestedAction
  • 必要的 request/trace 标识

关键分类包括:参数错误、目标未命中、目标歧义、身份不匹配、能力不支持、权限不足、限流、服务端失败、分页协议异常和文件提交失败。

错误分类的主要消费者不只是人,还包括 Agent 的下一步决策。因此 suggestedAction 应可执行,例如“提供 conversationId”“选择一个候选用户”“切换 bot identity”,而非笼统写“请重试”。

5.9 Profile 一致性

新增 profilectx 并调整 auth/profile 相关逻辑,目的是保证目标解析、API 调用和事件监听使用相同的身份上下文。跨 profile 漂移是多租户 CLI 中非常隐蔽的风险:解析可能在 A 租户命中对象,写操作却在 B 租户执行。

可复用规则:

  1. profile 在入口解析一次并向下传递;
  2. Resolver 结果记录 profile/tenant;
  3. 执行器不得静默回退到另一个默认 profile;
  4. 批处理账本记录每项使用的 profile;
  5. 事件监听 key 包含足够的上下文隔离信息。

5.10 隐藏兼容别名

PR 保留必要的参数或命令别名,但通过 metadata/schema 控制它们不再成为 Agent 的首选入口。这实现了“兼容旧调用,但不继续传播旧范式”。

正确的兼容策略应区分:

  • Runtime compatibility:旧命令仍可运行;
  • Discovery visibility:新用户和 Agent 默认看不到旧入口;
  • Documentation priority:文档只推荐 Golden Route;
  • Deprecation observability:能够统计旧入口使用情况;
  • Removal criteria:达到明确阈值后再移除。

5.11 Shortcut 部分修改详解

当前 #860 共修改 44 个 internal/shortcut 文件,其中 26 个生产 Go 文件、18 个测试文件。它不是简单增加命令数量,而是把 Shortcut 从“调用 MCP 的便捷包装”升级为以下分层执行系统:

Shortcut 声明与 Cobra 编译
  -> 本地参数/约束校验
  -> 自然目标解析与全量预检
  -> 身份/能力路由
  -> MCP 读写隔离与 dry-run
  -> 有界分页或批量执行
  -> 统一领域投影
  -> 完整性/失败 ledger
  -> 原子导出或安全资源落盘

5.11.1 Shortcut 框架:声明能力,而不是在命令里重复装配 Cobra

internal/shortcut/types.go 和 internal/shortcut/runner.go 扩展了通用声明模型:

修改 Runtime 行为 价值
Flag.Shorthand 所有 flag 类型统一通过 Cobra 的 BoolP/IntP/StringP/StringSliceP 注册 --output 可安全提供 -o,不需要每个命令单独实现
Shortcut.Aliases 将兼容命令映射到同一个执行实现 保留旧调用,但 canonical Schema 和文档仍只推荐主入口
SinglePositionalAliasFor 单个位置参数在校验前归一化为指定 flag;与显式 flag 同时出现时拒绝 为搜索类命令提供兼容体验,同时避免形成第二套参数契约
Constraint at_least_one、exactly_one、mutually_exclusive 由 Runner 统一执行并投影到 Runtime Schema Help、Runtime 与 Agent Schema 共用参数关系
Changed、StrFirst、IntFirst 能区分“用户显式输入”和“默认值”,并统一处理兼容别名 防止默认值错误覆盖旧参数或触发不适用校验

Runner 的执行顺序也被固定为:位置参数归一化 → required/enum 校验 → 跨参数约束 → 自定义校验 → 风险确认 → Execute。这样可以保证明显错误和未确认写操作不会到达 MCP。

读写调用进一步分离:CallMCPData 只允许符合只读命名契约的工具在 dry-run 中执行;CallMCPWriteData 在 dry-run 下直接 fail closed。多步写 Shortcut 必须自己输出 plan,不能借“为了拿返回值”之名在预览阶段执行写入。

5.11.2 Target Resolver:把名称解析变成共享基础设施

internal/shortcut/targetresolver/resolver.go 新增了独立解析层,核心类型包括:

  • Status:resolved、ambiguous、not_found、incomplete;
  • IdentityRequirement:区分下游需要 userId、openDingTalkId 或任一稳定身份;
  • UserResolution / ChatResolution:返回规范目标、匹配方式和 profile;
  • Reader:只依赖只读 CallMCPData,便于 Smart Shortcut、事件入口和测试共同复用。

群目标解析采用以下 fail-closed 算法:

  1. cid... 形式直接识别为稳定 openConversationId,不做名称搜索;
  2. 群名调用 im/search_groups,每页 10 条,最多 40 页;
  3. 对候选按稳定 ID 去重;精确名称优先,但多个精确同名仍然算歧义;
  4. hasMore=true 时必须存在且推进 nextCursor;
  5. 满页但无分页元数据、游标停滞或达到页数上限时返回 resolution_incomplete;
  6. 只有完整候选集中的唯一目标才允许继续执行。

批量解析 ResolveUsers/ResolveChats 会先解析全部目标并收集结构化失败;任一目标未命中或有歧义,就在写操作开始前整体停止。它解决了过去每个 +dm、+send-to-group、+group-members 自己搜索并默认取首项的问题。

需要注意:群名解析已经显式证明跨页候选完整;用户解析目前依赖 search_contact_by_key_word 单次响应提供完整候选,后续若通讯录接口引入分页,应把相同的完整性规则扩展到用户 Resolver。

5.11.3 身份与能力契约:先判断能不能做,再选择工具

internal/shortcut/chat/identity_contract.go 把 user、bot、webhook 三种身份的能力声明为矩阵,而不是散落在各分支的隐含知识:

身份 目标 内容 自然目标 幂等 批量 ledger
user 群、单聊 user/openDingTalkId text、markdown、image、file,audio/video 按 file 发送 群名、姓名 支持 否
bot 单群、多群、批量单聊 text、markdown 不支持 不支持 多群支持
webhook token 所属群 text、markdown 不支持 不支持 否

internal/shortcut/chat/im_contract.go 同时把“不支持什么”也变成可测试契约,例如 thread write、bot rich media、card action callback 和 Range 续传明确标记为不支持,并给出替代路径。这一点很重要:Agent 不应通过试错来发现能力边界。

5.11.4 +messages-send:统一发送入口内部做严格能力路由

internal/shortcut/chat/unified_send.go 将 user、bot、webhook 的发送入口合并为一个语义命令,但没有把底层差异抹平:

  • user 目标必须在群、群名、userId、姓名、openDingTalkId 中恰好选择一个;
  • bot 必须提供 robot-code,且群目标与批量单聊目标必须二选一;
  • webhook 的目标由 token 决定,拒绝额外群或用户目标;
  • @ 参数按身份和群聊/单聊分别校验;
  • uuid/idempotency-key 仅允许下层真实支持的 user 路径;
  • bot/webhook 在网络调用前拒绝 image/file/audio/video;
  • 内容正文、media-id 和本地文件互斥,并自动推导 msg-type。

user 的文件发送被拆成上传与消息发送两个动作,上传超时为 10 分钟;dry-run 只输出两步 plan。bot 多群发送最多 100 个目标,groups-file 必须是工作区内不超过 1 MiB 的普通文件,解析后去重,再通过 im.batch-write.v1 返回逐目标成功/失败账本。

batch_write.go 保持输入顺序,单项失败后继续其余项,但不自动重试写操作,因为远端报错时投递状态可能未知。代价是当前批量执行为顺序调用,优先可审计性和限流安全,而不是最大吞吐量。

5.11.5 Smart Shortcut 变薄:只组合公共能力

Smart 层的主要变化不是继续增加本地业务逻辑,而是把已有命令改造成公共组件的适配器:

Shortcut/文件 修改后的职责
smart/dm.go 解析自然用户目标后,委托统一 user markdown 发送器
smart/send_to_group.go 解析群名或稳定 ID 后,委托同一发送器
smart/search_msg.go 在搜索前完成群和发送者消歧,再使用公共消息投影
smart/at_me.go 使用公共目标、分页和消息结果语义
smart/thread_replies.go 复用 ProjectMessageV1,不再维护线程专属返回结构
smart/resolve.go 旧局部解析辅助函数迁移到 targetresolver

这使 Golden Route 保持语义清晰,同时底层身份、消息字段和失败行为只维护一份。

5.11.6 消息读取:从“返回数组”升级为 im.message-list.v1

internal/shortcut/chatmsg/chatmsg.go 建立所有列表、搜索、mget、@me 和线程读取共享的投影核心 ProjectMessageV1。消息行统一包含可获得的:

messageId / conversationId / threadId
sender / senderId / senderType
messageType / text / createTime / updateTime
reactions / quotedMessage / forwarded / resourceRefs

投影层做了几项关键防御:

  • 同一语义字段兼容不同下层 key,但不会猜测缺失的 sender type;
  • 富文本卡片只提取已识别的正文块,普通文本中的 JSON 片段保持原样;
  • 无法解密的密文显示为明确标记,不把 base64 当正文;
  • 引用消息做一层投影,避免递归链或循环;
  • 合并转发递归使用同一投影;
  • 资源从当前、引用和转发子消息中深度提取,并生成可执行下载参数;
  • reaction 使用下层已内联的数据,不额外制造网络请求。

Envelope 默认保守地令 complete=false。只有拿到可靠分页事实时才允许证明完整;消息接口真正可继续执行的边界是末条消息的 createTime,因此 nextPage 发布 time + direction,而不是盲目把下层 cursor 暴露成 CLI 参数。

5.11.7 有界分页:完整、截断和失败必须可区分

smart/chat_messages.go 将消息读取拆为目标编译、单页收集、全量收集、投影、资源下载和导出六个阶段。全量模式具备:

  • page-limit 默认 50、硬上限 500;
  • max-results 结果上限;
  • 稳定 messageId 跨页去重;
  • 时间边界停滞检测;
  • hasMore=true 但空页、缺边界或缺分页元数据时停止;
  • stopReason 区分 source_complete、single_page、page_limit、result_limit、read_failure 和 pagination_error;
  • 中途失败保留已读结果,并用 partial/failures/failedCount 显式标记。

chat_conversation.go 为会话列表加入同类的 page-all/page-limit、稳定 ID 去重和游标停滞检测,同时修正一个关键顺序问题:即使只读取一页,也必须在退出前解析 nextCursor,否则会出现 hasMore=true 却无法继续的结果。

smart/group_members.go 则建立 im.group-members.v1:用户和机器人分别进入 bucket;用户成员自动翻页并按 openDingtalkId 去重,机器人按下层全量结果投影。一个 bucket 失败时,另一个成功 bucket 仍可返回,但整体必须标记 partial 和 failures。

5.11.8 本地校验、导出和下载:错误尽量发生在网络调用前

新增的 smart/local_chat_validation.go 集中支持:

  • RFC3339、YYYY-MM-DD HH:mm:ss、YYYY-MM-DD 三种时间格式;
  • 显式 limit/count/days 必须为正数;
  • 分页默认值只在值为零时回退;
  • 本地验证错误携带稳定 reason 和可执行 action。

消息 JSON 导出与资源下载共享文件安全边界:

  1. 只接受工作目录内相对路径;
  2. 同时识别 Unix 根路径、Windows 盘符、反斜杠和 portable .. 逃逸;
  3. 解析父目录 symlink,防止最终路径逃出工作区;
  4. 默认 no-clobber,覆盖必须显式声明;
  5. 先写同目录临时文件,完成写入、sync、close 后再原子发布;
  6. 失败时删除临时文件,不留下看似成功的半成品。

资源下载明确采用整文件重试而非 Range 续传。这个限制被写入能力契约,避免文档或 Agent 宣称不存在的断点续传能力。

5.11.9 新增和强化的 Golden Route

  • +chat-create:先解析所有自然成员和可选群主,整体预检成功后只创建一次;默认群主必须能从当前 profile 中取得并加入成员集合。
  • +chat-update:群名或稳定 ID 统一解析,只承诺当前真实支持的改名能力。
  • +messages-reply:可先读取原消息自动补齐引用发送者;dry-run 返回引用上下文和真实 transport plan;成功后补充消息、会话、线程、幂等和 delivery status。
  • +chat-members-list:统一群目标,区分 users/bots,提供 bucket 完整性。
  • +chat-messages:统一群聊/单聊自然目标、分页、消息投影、资源和导出。
  • +messages-send:作为高级统一发送入口;+dm 和 +send-to-group 继续承担更窄、更易选路的常用入口。

这体现了 Golden Route 的正确含义:不是强迫所有意图只剩一个巨型命令,而是为每类意图保留一个推荐入口,公共执行逻辑在下层复用。

5.11.10 测试重点与整体评价

18 个 Shortcut 测试文件主要固定以下不变量:

  • 自然目标零命中、多命中、跨页同名和游标停滞时禁止写入;
  • dry-run 中写调用为零,确认后写调用次数精确;
  • canonical 参数与隐藏 alias 生成相同 MCP payload;
  • 消息身份、正文、引用、转发、reaction、资源和分页投影一致;
  • 页数/结果上限、中途失败和部分结果不会被标记为完整;
  • Unix/Windows 路径、symlink、no-clobber 和原子发布边界;
  • 所有公开 Shortcut 均进入 Schema 或有精确、受评审的 exclusion。

Shortcut 改造的核心价值可以概括为:语义入口仍然轻量,但目标解析、能力判断、完整性证明和安全落盘已经成为 Runtime 强约束。 当前仍需持续关注三点:unified_send.go 参数面较大、下层仍大量使用 map[string]any 做兼容投影、用户自然目标的候选完整性尚未像群目标一样显式分页证明。

6. 文档架构优化

本次文档改造的核心是“分层而非堆叠”:

SKILL.md
  负责意图识别、入口选择和最短路径
    |
    +-- intent-guide.md
    |     负责意图到命令的系统映射
    |
    +-- contracts.md / runtime-contract.md
    |     负责稳定输入输出与错误约束
    |
    +-- product/reference docs
          负责参数细节、边界与复杂示例

这类结构可以降低主 Skill 的上下文消耗,同时避免同一规则复制到多处后发生漂移。

7. 逐文档总结(30 份)

文档变更可以先按职责理解,再查看逐文件细节:

文档组 数量 主要职责 优化方向
Mono 4 全产品入口和产品索引 同步 Golden Route,避免复制领域细节
Chat Skill 与总览 6 IM 意图路由、总览和公共合同 收敛入口,建立独立 contracts
Chat 卡片 4 卡片模型与生命周期 按 create/update/callback/schema 拆分
Chat 领域子文档 6 bot、会话、群、消息及旧工作流 对齐新 Runtime,删除重复路由源
Event 6 IM 事件监听 按 keys/lifecycle/operations/output 分层
Shared 4 跨产品运行约束 统一错误、profile 和 Runtime contract

下面每份文档均按“改了什么—为什么—如何复用”三个问题进行总结。

7.1 Mono 文档

1. skills/mono/SKILL.md

  • 调整 IM 意图的默认路由和入口说明。
  • 将运行时已具备的统一消息、会话和事件能力呈现给单体 Skill。
  • 强调优先使用稳定 shortcut,底层命令作为高级或兼容入口。
  • 复用价值:任何全产品聚合 Skill 都应只维护意图索引,不复制领域手册。

2. skills/mono/references/best_practices/01-messaging.md

  • 更新消息发送、回复、读取等最佳实践。
  • 将自然目标解析、身份选择和分页边界纳入标准流程。
  • 复用价值:最佳实践文档应描述决策原则,不只是展示命令样例。

3. skills/mono/references/products/chat.md

  • 对齐新的 chat shortcut、统一输出和能力边界。
  • 收敛旧脚本路径,避免文档继续引导 Agent 选择已被 Runtime 吸收的脚本。
  • 复用价值:产品 Reference 必须与 Schema 的可发现能力同步更新。

4. skills/mono/references/products/event.md

  • 引入 event +listen-im 及其生命周期说明。
  • 明确事件监听与普通一次性命令的差异。
  • 复用价值:所有长生命周期能力都应提供 start/status/stop 和恢复语义。

7.2 Chat Skill 与总览文档

5. skills/multi/dingtalk-chat/SKILL.md

  • 重构 chat 的核心意图路由,突出 Golden Route。
  • 增加统一发送、会话创建、消息回复、列表、导出等入口。
  • 将详细合同和高级示例下沉到 Reference,降低主入口复杂度。
  • 当前版本为 9,928 bytes,已进入 10,000 bytes 上下文预算,但只剩 72 bytes 余量,应继续把细节下沉到 Reference。
  • 复用价值:领域 Skill 应是“路由器”,不是完整 API 百科。

6. skills/multi/dingtalk-chat/references/01-messaging.md

  • 更新端到端消息操作最佳实践。
  • 强调先解析目标、再做能力判断、最后执行写操作。
  • 补充分页、回复、文件处理等边界。
  • 复用价值:将“解析—计划—执行—回执”固化为跨产品写操作模板。

7. skills/multi/dingtalk-chat/references/chat.md

  • 大幅重构 chat 总参考,覆盖新的 shortcut 和 Runtime 契约。
  • 统一参数命名、输出结构、错误处理和高级入口定位。
  • 减少与子文档的重复,将细节按主题拆分。
  • 复用价值:领域总览应负责导航和共享概念,具体操作落到子 Reference。

8. skills/multi/dingtalk-chat/references/intent-guide.md

  • 建立用户意图到 Golden Route 的明确映射。
  • 说明目标是人、群、会话或消息时分别如何选择命令。
  • 降低“多个命令看起来都能完成任务”造成的路由不确定性。
  • 复用价值:通讯录和文档也应维护机器可校验的 intent-route 表。

9. skills/multi/dingtalk-chat/references/contracts.md

  • 新增集中式契约文档。
  • 固定消息列表、写操作回执、批处理账本和错误 envelope 等公共结构。
  • 将契约与教程分离,便于版本化和自动检查。
  • 复用价值:每个领域都应有唯一的 contract source of truth。

10. skills/multi/dingtalk-chat/references/chat-emoji-list.md

  • 对齐 emoji 相关命令、目标和消息标识参数。
  • 使轻量功能也遵循统一会话/消息身份语义。
  • 复用价值:边缘功能不能绕过统一 Resolver 和契约。

7.3 Chat 卡片文档

11. skills/multi/dingtalk-chat/references/card/create.md

  • 新增卡片创建流程说明。
  • 区分卡片定义、实例创建和消息投递,避免一步调用承载过多隐式行为。
  • 复用价值:复杂对象创建应拆成资源定义、实例化和发布阶段。

12. skills/multi/dingtalk-chat/references/card/update.md

  • 新增卡片更新操作说明。
  • 强调实例标识、可更新字段和生命周期边界。
  • 复用价值:文档更新、表格更新等都应区分 create contract 与 update contract。

13. skills/multi/dingtalk-chat/references/card/callback.md

  • 新增卡片回调与交互事件说明。
  • 将回调输入视为结构化事件,而不是普通消息文本。
  • 复用价值:交互式文档组件、审批回调也可复用事件 envelope。

14. skills/multi/dingtalk-chat/references/card/schema.md

  • 新增卡片 Schema 说明。
  • 集中描述字段结构和约束,减少 create/update 文档重复。
  • 复用价值:把数据模型与操作教程分开,Schema 可单独校验和演进。

7.4 Chat 领域子文档

15. skills/multi/dingtalk-chat/references/chat/chat-bot.md

  • 更新机器人发送、广播及身份能力说明。
  • 旧脚本能力被收敛进 Runtime,文档不再要求 Agent 拼装脚本流程。
  • 注意:文档部分位置使用 results,而 Runtime 实际批处理字段为 succeeded,需统一。
  • 复用价值:文档字段名必须由合同或测试生成,避免手工漂移。

16. skills/multi/dingtalk-chat/references/chat/chat-conversation.md

  • 更新会话创建、列表和目标标识说明。
  • 补充游标、分页和会话类型边界。
  • 复用价值:任何容器类资源都应区分 canonical ID、display name 与 page cursor。

17. skills/multi/dingtalk-chat/references/chat/chat-group.md

  • 更新群成员、群信息与群目标解析流程。
  • 统一群名与群 ID 的解析/歧义处理。
  • 复用价值:部门名、空间名、目录名同样需要唯一解析和候选返回。

18. skills/multi/dingtalk-chat/references/chat/chat-message.md

  • 更新消息读取、回复、导出和资源下载说明。
  • 对齐 im.message-list.v1 投影及分页元数据。
  • 复用价值:把列表 contract 与后续动作需要的 canonical ID 同时输出。

19. skills/multi/dingtalk-chat/references/chat/chat-workflows.md(删除)

  • 删除与 SKILL、intent guide 和领域子文档大量重叠的工作流集合。
  • 旧文档容易形成第二套意图路由源。
  • 复用价值:当工作流可由 Golden Route 与合同组合推导时,不应继续维护重复手册。

20. skills/multi/dingtalk-chat/references/lite-recipes.md(删除)

  • 删除过短且容易过时的 recipe 集合。
  • 将典型路径并入主 Skill 或更权威的 Reference。
  • 复用价值:减少“看似方便但缺少边界”的示例,避免模型只复制 happy path。

7.5 Event 文档

21. skills/multi/dingtalk-event/SKILL.md

  • 增加 IM 监听的意图入口与生命周期路由。
  • 将普通事件命令和长期监听操作区分开。
  • 复用价值:事件领域 Skill 应首先判断用户要“查询配置”还是“启动持续进程”。

22. skills/multi/dingtalk-event/references/event-im.md

  • 大幅更新 IM 事件总参考。
  • 串联配置、启动、运行、输出、停止和排错。
  • 将细节拆到四个新子文档,自己承担导航职责。
  • 复用价值:长流程总文档应提供生命周期地图而非重复所有参数。

23. skills/multi/dingtalk-event/references/event-im-keys.md

  • 新增 endpoint、listener、profile 等关键标识说明。
  • 明确 key 的生成、引用和隔离边界。
  • 复用价值:后台任务、同步任务、订阅任务都需要稳定 task key。

24. skills/multi/dingtalk-event/references/event-im-lifecycle.md

  • 新增启动、运行、状态、停止等生命周期说明。
  • 描述前后台模式及退出后的状态语义。
  • 复用价值:将长任务统一建模为显式状态机。

25. skills/multi/dingtalk-event/references/event-im-operations.md

  • 新增常见操作和运维流程说明。
  • 将查看状态、诊断、停止等操作从概念说明中拆出。
  • 复用价值:后台服务文档应提供可操作 runbook。

26. skills/multi/dingtalk-event/references/event-im-output.md

  • 新增监听输出格式及字段解释。
  • 明确事件 envelope 与 IM 消息投影之间的关系。
  • 复用价值:通讯录、文档事件应共享 envelope,仅替换 payload contract。

7.6 Shared 文档

27. skills/multi/dws-shared/SKILL.md

  • 更新多产品共享约束和 Reference 导航。
  • 将 Runtime contract 与错误码作为跨领域公共基础设施。
  • 复用价值:共享 Skill 只承载真正跨域的稳定规则,领域语义仍留在各自 Skill。

28. skills/multi/dws-shared/references/error-codes.md

  • 扩展结构化错误类别、可重试性和建议动作。
  • 支撑 Target Resolver、服务端失败分类和文件流程。
  • 复用价值:错误码应跨产品统一命名,领域细节放入 details。

29. skills/multi/dws-shared/references/global-reference.md

  • 更新全局参数、profile、输出和运行约束。
  • 明确公共规则的权威来源,减少 chat/event 文档重复。
  • 复用价值:全局 Reference 应稳定且少变,产品差异通过链接下沉。

30. skills/multi/dws-shared/references/runtime-contract.md

  • 新增 Runtime 公共契约说明。
  • 固定 envelope、错误、批处理、分页和 profile 传播等跨产品行为。
  • 复用价值:通讯录、文档、云盘接入时应直接复用,而非重新设计返回结构。

8. 被删除脚本的意义

PR 删除 mono 与 multi chat 下的以下脚本:

  • bot_broadcast.py
  • chat_export_messages.py
  • chat_history_with_user.py

删除并不意味着能力减少,而是能力已进入可测试、可发现、可治理的 Runtime。脚本适合验证原型,但长期作为 Agent 主路径会带来参数契约不可发现、错误格式不一致、身份上下文丢失和重复分页逻辑等问题。

迁移准则:当一个脚本成为稳定业务能力后,应将核心逻辑提升到 Runtime,生成 Schema,补充契约测试,然后从主 Skill 中撤下脚本入口。

9. Policy 与测试体系

9.1 Multi IM Skill Chain Policy

新增 scripts/policy/multi-im-skill-chain,通过意图测试数据检查关键路径是否在 Skill、Reference、Schema 与 Runtime 之间闭环。其价值是防止以下回归:

  • 文档推荐了不存在的命令;
  • Runtime 已新增命令但 Schema 未暴露;
  • 兼容别名重新成为首选;
  • 同一意图再次出现多个 Golden Route;
  • 关键参数或输出字段只在某一层存在。

当前 intent manifest 包含 9 个关键意图路由;PR 描述记录 make policy 通过。本文对代码和配置进行了静态核对,没有把该记录扩展表述为 GitHub CI 全绿。

9.2 Context Budget Policy

Skill 上下文预算检查用于控制入口文档大小。渐进披露只有在主 Skill 足够短时才有效。当前 chat Skill 为 9,928 bytes,刚好回到 10,000 bytes 预算内;架构方向正确,但余量很小,内容仍需继续去重或下沉。

9.3 测试分层

本次变更配套测试覆盖:

  • Resolver 的唯一命中、多命中、未命中与输入类型;
  • unified send 的目标和身份选择;
  • 消息投影字段;
  • 分页边界与兼容行为;
  • 结构化错误和服务端失败分类;
  • event 命令注册与生命周期;
  • Schema/shortcut contract;
  • mock MCP 端到端冒烟路径。

PR 描述记录 internal/app、internal/shortcut/chat 和 internal/shortcut/smart 等重点测试通过。本文分析的是远端 head 的 Git 对象,没有在当前 main 工作区切换分支重新运行完整测试;当前 GitHub CI 结论仍应以第 21 章列出的 workflow 状态为准。

10. 面向通讯录场景的复用蓝图

通讯录复用的重点不是照搬 IM 命令,而是把“找群/找人后执行动作”的模式转换为“找用户/找部门后执行动作”。核心差异在于通讯录写操作通常权限更高、影响范围更大,因此 Resolver 的唯一性和执行前计划需要更严格。

10.1 建议 Golden Routes

contact +resolve
contact +user-get
contact +user-list
contact +department-list
contact +member-list
contact +invite
contact +update
contact +export
event +listen-contact

10.2 Directory Resolver

集中接受姓名、手机号、邮箱、userId、unionId、部门名称和 deptId。输出唯一 canonical target 或候选列表,不允许高风险写操作在歧义状态下继续。

10.3 类型化契约

建议定义:

  • directory.user.v1
  • directory.user-list.v1
  • directory.department.v1
  • directory.member-list.v1
  • directory.batch-write-result.v1
  • directory.change-event.v1

10.4 风险分级

  • 只读查询:可在唯一命中后自动执行。
  • 邀请/修改:必须显示 preflight plan。
  • 删除/批量调岗:要求显式确认、严格唯一目标和可审计账本。

10.5 批处理账本

每条记录包含 input、resolved target、action、status、error、retryable 和 profile。这样部分失败可安全重试,不需要重跑已成功项目。

11. 面向文档、云盘和知识库的复用蓝图

文档类场景与 IM 的共同点是目标输入多样、读取结果需要稳定投影、长流程需要完整性保证;不同点是文档还涉及版本冲突、层级容器、权限继承和内容覆盖。因此在复用 Resolver 与 Runtime contract 的同时,应额外引入 revision/etag 和并发控制。

11.1 建议 Golden Routes

doc +resolve
doc +create
doc +read
doc +update
doc +export
doc +share
drive +download
drive +upload
wiki +resolve-node
event +listen-document

11.2 Document Target Resolver

统一解析 URL、docId、fileId、spaceId、workspaceId、知识库节点 ID、标题和路径。解析输出必须包含 product/resource type,避免将同形 ID 传给错误产品接口。

11.3 Plan/Execute 分离

写文档、覆盖文件、调整权限、移动知识库节点前先生成计划:

{
  "target": {"type": "document", "id": "..."},
  "action": "replace-content",
  "identity": "user",
  "expectedRevision": "...",
  "sideEffects": ["overwrite content"],
  "recoverability": "revision-history"
}

计划可以独立验证权限、版本冲突和副作用;确认后才执行。

11.4 列表与搜索契约

搜索结果必须区分 exact、fuzzy 和 candidate,返回 canonical URL/ID、容器、资源类型、权限摘要以及分页状态。不要只返回标题字符串。

11.5 原子输出与并发控制

  • 导出使用临时文件和原子替换。
  • 更新使用 revision/etag 防止覆盖他人修改。
  • 上传返回摘要、大小和最终资源 ID。
  • 长迁移返回 checkpoint 与逐项账本。

12. 可复用的落地模板

12.1 新领域接入步骤

  1. 列出用户真实意图,而非先列 API。
  2. 为每个意图指定唯一 Golden Route。
  3. 设计统一 Target Resolver 和 canonical target。
  4. 建立身份/能力矩阵。
  5. 定义版本化输入、列表、写回执和错误契约。
  6. 为长流程增加 maxItems、maxPages、timeout、checkpoint。
  7. 将写操作拆为 plan 和 execute。
  8. 生成或同步 Schema metadata/hints/registry。
  9. 编写短 Skill、意图指南、合同和分主题 Reference。
  10. 增加意图链路、上下文预算、Schema 和契约测试。

12.2 推荐目录结构

skills/multi/dingtalk-<domain>/
  SKILL.md
  references/
    intent-guide.md
    contracts.md
    <domain>.md
    <topic-a>.md
    <topic-b>.md

internal/shortcut/
  <domain>/
  <domain>resolver/

scripts/policy/
  <domain>-skill-chain/

12.3 Golden Route 评审问题

  • 一个自然语言意图是否只有一个默认入口?
  • shortcut 是否隐藏了供应商 API 的非必要复杂度?
  • 兼容入口是否仍可运行但不会被 Agent 优先发现?
  • Resolver 是否统一处理 ID、名称、URL 和多候选?
  • 写操作是否在执行前完成身份和能力校验?
  • 输出是否有稳定版本?
  • 列表是否明确完整、截断与下一页状态?
  • 错误是否能指导 Agent 下一步动作?
  • Skill、Reference、Schema 与 Runtime 是否有自动一致性检查?

13. PR #860 当前风险收口状态

评审问题 当前整体实现 判断
+conversation-list 单页模式丢失 nextCursor 将 cursor 解析移动到单页退出判断之前,并补充失败边界测试 已修复
hasMore=true 但 cursor 缺失、无效或不前进 增加 missing/invalid/stalled cursor 测试 已强化
Chat Shortcut 未全部进入 Schema 从 50/97 提升到 97/97,删除 47 项临时 exclusion 已解决
高风险示例直接展示 --yes 文档和命令示例改为先运行或 --dry-run,由 Runtime 要求确认后再追加 --yes 已改善
跨平台输出路径判断和覆盖替换不完整 统一处理 Unix/Windows 路径语义,并以 build tags 分离 os.Rename 与 windows.Rename 已加固
chat bot 文档 results 与 Runtime succeeded 可能不一致 当前 diff 中未见由单一 typed source 自动生成这两个名称 仍需确认
Chat Skill 上下文预算偏紧 已通过拆分 Reference 和删除重复文档缩短主 Skill,仍应持续由 budget policy 约束 持续治理
兼容别名缺少退出观测 已增强 alias/canonical payload 等价测试,但未建立使用量观测或移除阈值 长期项
真实线上语义 单元测试和 mock MCP 能证明本地契约,不能证明真实权限、MCP 响应和服务端可用性 需要受控 E2E

14. PR #860 整体架构结论

PR #860 的核心贡献,是把 IM 能力从“散落的命令和教程”升级为“可解析、可计划、可执行、可验证的意图系统”。其最重要的架构资产包括:

  • Resolver:统一对象身份;
  • Golden Route:统一意图入口;
  • Capability Matrix:统一身份与能力判断;
  • Versioned Contract:统一机器输出;
  • Bounded Execution:统一分页和长流程边界;
  • Typed Error Ledger:统一失败处理与恢复;
  • Progressive Documentation:统一知识组织;
  • Policy Gates:统一防漂移机制。

这些模式与 IM 本身无强绑定。通讯录的“找人/找部门”、文档的“找资源/改内容”、云盘的“找文件/迁移”、知识库的“找节点/调整结构”都面临同一类问题。复用时应迁移完整链路,而不是只复制某个 shortcut:

意图设计
  -> Resolver
  -> Golden Route
  -> Plan/Capability Check
  -> Bounded Runtime
  -> Versioned Result/Error
  -> Documentation + Schema + Policy

只有整条链路同时落地,才能真正降低 Agent 的选择成本、减少误操作,并让新领域能力持续演进而不重新陷入命令、文档和实现相互漂移的问题。


15. 产品化交付闭环

15.1 为什么 Runtime 完成不等于 PR 完成

PR #860 同时处理两类问题:一类是命令行为本身,另一类是 Agent 能否发现、正确选择并安全执行这些行为。只有 Runtime、Registry、Schema、selection hints、风险 metadata、Skill、Policy 和测试同时闭环,才能把“隐藏在代码里的能力”升级为“可交付产品能力”。

大行数主要来自重新生成并提交的 Schema catalog 和 Agent metadata,不能等同于 6 万余行手写业务逻辑。评审时应将 authored source、Runtime、generated artifacts、文档和测试分开看。

15.2 五个交付收口方向

  1. 能力发布完整化:剩余 47 个公开 Chat Shortcut 从临时 exclusion 转为正式 Registry 和 Schema 能力,使 Chat 达到 97/97。
  2. 安全元数据类型化:为 47 个命令逐一声明 effect、risk、confirmation、idempotency、interface mode 和 runtime gate。
  3. 参数前置校验:时间、页大小、回溯窗口等明显错误在本地拒绝,不再发起无效远端调用。
  4. 运行时边界收口:修复单页 cursor、补 -o、增强跨平台输出路径并扩大目标消歧测试。
  5. 交付证据闭环:重新生成 Schema/Agent metadata,强化生成漂移、契约完整性和 changed-code coverage 门禁。

16. Schema 发布与能力治理

16.1 从 50/97 到 97/97

PR #860 在 internal/cli/schema_command_registry/products/chat.json 中补齐 47 个 canonical shortcut,并从 schema_command_exclusions.json 删除整个 chat-shortcuts-pending-schema-curation 临时排除组。

这一步的意义不是单纯“数字补齐”,而是完成以下状态转换:

公开可执行、但 Schema 暂未评审
  -> authored Registry 有正式记录
  -> selection hints 能指导 Agent 何时用/何时不用
  -> metadata 声明风险和确认方式
  -> generated catalog/Agent metadata 可发现
  -> completeness test 保证不再退回临时排除

关键指标变化:

指标 改造前 PR #860 当前 head
Chat Schema Shortcut 50 97
全部公开 Shortcut Schema 覆盖 218 / 265 265 / 265
Schema catalog 工具数 850 898
Agent metadata 覆盖工具数 850 898
hint tools 1,852 1,948
reviewed Agent examples — 1,108(1,084 contract + 24 dry-run)

16.2 新发布的 47 个 Shortcut

为便于理解,可按业务域归为五组:

会话分类(3)

  • +category-add-conversation
  • +category-list-conversations
  • +category-remove-conversation

群管理(13)

  • +chat-add-bot
  • +chat-audit-join
  • +chat-get-by-id
  • +chat-members-get
  • +chat-mute-member
  • +chat-quit
  • +chat-remove-bot
  • +chat-role-remove
  • +chat-role-remove-user
  • +chat-transfer-owner
  • +chat-update
  • +chat-update-icon
  • +chat-update-settings

会话状态(7)

  • +conversation-clear-messages
  • +conversation-clear-red-point
  • +conversation-hide
  • +conversation-mark-read
  • +conversation-mark-unread
  • +conversation-mute
  • +conversation-set-top

Feed 与收藏(4)

  • +feed-group-query-item
  • +flag-cancel
  • +flag-create
  • +flag-list

消息与资源(20)

  • +messages-add-emoji
  • +messages-add-text-emotion
  • +messages-batch-recall-by-bot
  • +messages-batch-send-by-bot
  • +messages-combine-forward
  • +messages-create-text-emotion
  • +messages-forward
  • +messages-forward-topic
  • +messages-list
  • +messages-recall
  • +messages-recall-by-bot
  • +messages-remove-emoji
  • +messages-remove-text-emotion
  • +messages-resource-download
  • +messages-resource-url
  • +messages-send-by-bot
  • +messages-set-pin
  • +messages-set-top
  • +messages-unset-pin
  • +messages-unset-top

16.3 风险与确认元数据

47 个新增 metadata 的分布非常清晰:

类型 数量 confirmation runtime gate
只读 / low 8 not_required none
写操作 / medium 36 user_required typed_yes
破坏性 / high 3 user_required typed_yes

三个 high-risk 命令是:

  • chat.shortcut_chat_remove_bot
  • chat.shortcut_chat_role_remove
  • chat.shortcut_conversation_clear_messages

八个只读命令包括分类列表、按 ID 查群、成员获取、Feed 查询、收藏列表、消息列表、资源 URL 和资源下载。其余 39 个命令全部要求用户确认并由 Runtime 的 typed_yes 门禁执行。

这种分类实现了三个层面的一致性:

  1. Agent 在选择工具时能看到风险;
  2. 示例不会把确认当成默认参数;
  3. Runtime 即使被直接调用,也会阻止未经确认的写操作。

16.4 Authored Source 与生成物分离

PR #860 的权威编辑源主要是:

  • schema_command_registry/products/chat.json:命令身份和 canonical path;
  • schema_hints/selection/chat.json:use_when、avoid_when 和 source refs;
  • schema_hints/metadata/chat.json:effect、risk、confirmation 等运行语义。

随后由生成流程更新:

  • schema_catalog/catalog.json
  • schema_catalog/tools/chat.json
  • schema_agent_metadata/chat.json
  • schema_agent_metadata/index.json
  • schema_agent_metadata_audit.json
  • runtime-surface-completeness.json

复用到其他产品时,应优先评审 authored source 的准确性,再验证生成物无漂移。直接手改大型 catalog 会削弱可追溯性。

16.5 Selection Hints 的价值

每个新 Shortcut 都有独立的 use_when、avoid_when 和 source_refs。三者分别解决:

  • 什么时候用:把用户意图映射到该工具;
  • 什么时候不用:避免和相近工具误路由;
  • 依据是什么:从生成结果追溯到 Registry 和文档锚点。

这比只提供命令描述更适合 Agent,因为工具选择的难点通常不是“工具做什么”,而是“在几个相似工具中为什么选这个”。

17. Runtime 安全与正确性加固

17.1 本地参数校验

新增 internal/shortcut/smart/local_chat_validation.go,集中实现:

  • 默认分页上限归一化;
  • RFC3339、YYYY-MM-DD HH:mm:ss、YYYY-MM-DD 三类时间格式检查;
  • 带稳定 reason 和 suggested action 的本地 validation error。

落地命令及边界:

命令 新增校验
+chat-messages --time 格式;--limit/--size/--page-size > 0
+thread-replies 时间格式;显式 --limit > 0
+at-me --days 为 1~3650;--limit > 0
+unread-chats 显式 --count > 0

核心原则是“能够在本地确定错误,就不要把它推给远端”。这样能减少无效请求,并让 Schema 约束、CLI 错误和测试保持一致。

17.2 破坏性确认门禁

internal/helpers/chat.go 为以下底层命令补上真实 Runtime 检查:

  • chat category delete
  • chat clear-messages

缺少 --yes 时,命令返回 confirmation_required,列出确认目标和再次执行方式,并保证没有任何下游工具调用。补充测试同时验证:确认前零写入、确认后仅发生一次预期调用。

此外,群解散和升级外部群等示例不再直接展示 --yes;升级示例改用 --dry-run。这是一个重要的提示工程原则:

文档示例应该展示安全的第一步,而不是展示绕过交互确认的最终一步。

17.3 单页会话 cursor 修复

+conversation-list 的旧实现曾在非 --page-all 模式下先退出循环,再解析 nextCursor,可能返回 hasMore=true 但游标为零。PR #860 将 cursor 解析提前到退出判断之前。

修复后的行为:

  • 单页结果保留可执行的下一页游标;
  • hasMore=true 但游标缺失、无效或停滞时记录 pagination failure;
  • --page-all 才继续拉下一页;
  • --page-limit 保持有界。

这说明分页契约的完整性不仅适用于“拉完全部”,单页模式同样必须提供可靠 continuation。

17.4 通用 shorthand 支持

shortcut.Flag 新增 Shorthand 字段,统一注册逻辑从 Cobra 的 Bool/Int/StringSlice/String 切换到对应的 *P 版本。+chat-messages --output 因而获得 -o。

该改动是框架级能力,不只服务于当前命令。后续复用时需增加同一命令内 shorthand 唯一性检查,避免不同 flag 争用同一个短参数。

17.5 跨平台资源路径加固

原实现主要依赖当前操作系统的 filepath.IsAbs/Clean。在 Unix 上,Windows 盘符路径或反斜杠逃逸未必会按预期识别。PR #860 增加 portable 归一化:

  • 将反斜杠转换为 / 后再检查;
  • 识别 Unix 绝对路径;
  • 识别 Windows C: 等盘符;
  • 统一拒绝 .. 和 ../ 逃逸;
  • 在父目录、相对路径和最终解析阶段复用同一判断。
  • 用 file_replace.go 与 file_replace_windows.go 的 build tags 分离平台实现:非 Windows 使用 os.Rename,Windows 使用 windows.Rename,保证覆盖写仍是原子替换。

该模式可直接用于文档导出、云盘下载、通讯录 CSV 导出和任何工作区内文件写入能力。

17.6 目标消歧与 fail-closed 测试

Resolver 实现与测试共同固定以下关键语义:

  • 稳定 ID 永远不按名称搜索;
  • 自然目标走 Resolver;
  • 同名精确匹配仍保持歧义,不能偷偷选一个;
  • 必须翻完候选页后才判断是否唯一;
  • cursor 无法推进时 fail closed;
  • 结构化错误保留候选对象;
  • 外部联系人只要有可用 openDingTalkId 也可参与解析。

最重要的改进是“跨页后再唯一判定”。如果只看第一页就认为唯一,在第二页存在同名对象时会产生高风险误操作。

17.7 删除过时 hint 子命令

删除 dws chat send 和 dws chat history 两个仅用于提示的伪子命令。Golden Route 已通过 Shortcut 和 Schema 正式发布后,继续保留 hint 命令会污染命令树并形成第二套发现路径。

兼容不等于永远保留所有提示层。若入口已经由结构化 discovery 接管,应删除无法执行真实业务、只输出迁移提示的旧节点。

18. PR #860 文件分类总结

18.1 129 个文件按职责归类

文件组 数量 主要内容
生产 Go 38 App、错误、Resolver、Chat/Smart Runtime、契约、Policy 与生成别名
Go 测试 30 Resolver、分页、确认、文件安全、事件、契约及 coverage
Skill Markdown 30 Mono、Chat、Event、Shared 四层知识链路
Schema / metadata / JSON 17 Registry、selection、risk metadata、catalog、Agent metadata 与 intent manifest
Skill 脚本 6 删除已被 Runtime 替代的重复 Python 路径
生成/审计脚本 6 Skill 生成、Policy 检查、live audit 及其测试
CI / Makefile 2 接入 Policy、兼容性、覆盖率及平台 race 验证

18.2 Schema 文件逐项总结

文件 总结
schema_command_registry/products/chat.json 补齐 canonical Shortcut,成为 Chat 发布权威源
schema_command_exclusions.json 删除 47 项“待 Schema 评审”临时豁免,反向完整性转为硬约束
schema_hints/selection/chat.json 为 Chat 工具补齐 use/avoid/source refs,强化 Agent 路由
schema_hints/metadata/chat.json 为 Chat 工具声明 effect、risk、confirmation、idempotency 和 runtime gate
schema_hints/runtime-surface-completeness.json 更新 Runtime surface 覆盖指纹与统计
schema_catalog/catalog.json 重新生成全局 catalog 索引
schema_catalog/tools/chat.json 重新生成 Chat 的完整工具契约和示例
schema_agent_metadata/chat.json 生成 Chat Agent 决策元数据
schema_agent_metadata/index.json 更新全产品 metadata 索引和 898 工具统计
schema_agent_metadata_audit.json 更新 coverage、source/surface hash 和审计结果

18.3 Runtime 文件逐项总结

文件 总结
internal/helpers/chat.go 为删除分类、清空消息补确认门禁;安全化危险示例;删除旧 hint 子命令
shortcut/chat/chat_conversation.go 修复单页模式 nextCursor 丢失
shortcut/chat/resource_download.go 统一 Unix/Windows 绝对路径和 .. 逃逸判断
shortcut/chat/file_replace.go 非 Windows 构建使用 os.Rename 作为原子替换边界
shortcut/chat/file_replace_windows.go Windows 构建使用 windows.Rename 支持覆盖已有目标
shortcut/runner.go 所有 flag 类型支持 shorthand 注册
shortcut/types.go Flag 契约增加 Shorthand
smart/local_chat_validation.go 新增共享时间、页大小和结构化本地错误辅助函数
smart/chat_messages.go 新增时间/页大小校验及 -o,复用默认 page limit
smart/at_me.go 限定 days 和 limit,组合资源下载校验
smart/thread_replies.go 限定时间格式和 limit
smart/unread_chats.go 限定 count 为正数
smart/group_members.go 复用统一默认 page limit 逻辑

18.4 Policy 文件总结

scripts/policy/multi-im-skill-chain/main.go 将工作目录、进程退出、文件打开和 Registry build/bind 抽成可注入函数。行为本身没有改变,但各种 setup failure、I/O failure 和 binding failure 现在可在单元测试中稳定覆盖。

这是一种值得复用的“测试接缝”设计:对进程边界做最小注入,不为测试重写业务逻辑。

18.5 安全示例收口示例

1. skills/mono/references/best_practices/01-messaging.md

  • 将发送、机器人批量发送和消息转发示例中的默认 --yes 去掉。
  • 明确 Runtime 会先返回确认要求;用户确认后才以相同参数追加 --yes。
  • 保留唯一目标解析、同 profile 稳定 ID 和未知投递状态停止重发等规则。
  • 复用价值:所有写操作最佳实践都应展示“安全第一步 + 确认后续步骤”,不能把确认令牌写进首个示例。

2. skills/mono/references/products/chat.md

  • 将“普通群升级为外部群”的正式执行示例改为 --dry-run。
  • 删除直接带 --yes 的示例,保留 extension JSON 的预演方式。
  • 复用价值:不可逆转换、权限变更和内容覆盖应优先展示 dry-run/preflight。

18.6 测试体系总结

PR #860 的 30 个 Go 测试文件主要覆盖:

  • 265/265 public Shortcut Schema 覆盖和 Chat 97/97;
  • metadata 风险与 Runtime confirmation truth;
  • 时间、页大小、回溯窗口等本地无网络校验;
  • natural target、稳定 ID、同名候选和跨页消歧;
  • 单页/全量分页、cursor 停滞、边界失败和部分结果保留;
  • 资源下载的绝对路径、反斜杠、symlink、原子 no-clobber;
  • 确认前零写调用、确认后精确一次调用;
  • alias 到 canonical payload 的等价性;
  • Multi IM Policy 的配置、I/O 和失败矩阵;
  • 跨平台 changed-code coverage。

测试名大量增加 CrossPlatformCoverage 前缀,是为了让平台覆盖门禁识别相关测试。其积极意义是证据可追踪;长期应避免让命名约定取代真正的覆盖映射机制。

19. Go 文件优化专项总结

19.1 总体规模与演进主线

PR #860 的 Go 变更应按“生产实现”和“验证实现”分开理解:

类型 文件数 新增 / 删除 主要任务
生产 Go 38 +4,028 / -737 建立 Resolver、IM Runtime 契约、事件监听、错误/Profile、平台文件替换和 Policy 基座
Go 测试 30 +4,343 / -88 固定正常路径、失败边界、安全不变量、Schema/Runtime 一致性与跨平台覆盖

整体演进不是把更多逻辑堆进单个命令,而是逐步形成以下 Go 代码分层:

Cobra / App 层
  负责命令注册、参数装配、profile 与进程生命周期
        |
        v
Shortcut / Smart 层
  负责 Golden Route、业务校验、计划和结果组织
        |
        v
Target Resolver / Contract 层
  负责规范目标、身份能力、版本化结果和错误语义
        |
        v
Helper / Transport 调用层
  负责下游工具调用,不重复业务决策
        |
        v
Policy + Tests
  验证 Runtime、Schema、文档和安全元数据保持一致

19.2 App、错误与上下文文件

Go 文件 主要优化 设计价值
internal/app/event_command.go 注册新的 event +listen-im 入口 将 IM 事件监听纳入正式内建命令树
internal/app/event_listen_im.go 新增监听计划编译、自然目标解析、事件类型映射及 consume 生命周期委托 把长期事件订阅从参数拼装提升为可验证的计划执行
internal/app/runner.go 增强多 profile 执行和错误结果组织 批量或多身份运行时保留逐 profile 的失败语义
internal/app/server_failure_classifier.go 新增服务端业务失败分类器 将后端文本/元数据转换为稳定 reason、retryable 和行动建议
internal/auth/profiles.go 收敛 profile 选择和传播方式 减少解析与执行使用不同租户身份的风险
internal/profilectx/profile.go 新增轻量 profile context 让 Resolver、Shortcut 和调用层共享明确身份上下文
internal/errors/errors.go 扩展 typed error、server diagnostics 和结构化输出字段 使错误可被 Agent 解析并驱动后续动作
internal/cli/param_aliases_generated.go 发布新增 IM 参数别名 兼容旧参数拼写,同时维持 canonical payload
internal/helpers/aisearch.go 补齐搜索目标兼容与参数映射 为自然人名解析提供更稳定的下层搜索入口
internal/helpers/chat.go 对齐 Chat 底层命令边界、参数与确认相关行为 使 shortcut 与底层 helper 的真实能力一致

这一组文件的核心优化是:把 profile、错误和生命周期从“隐式全局状态”变为显式上下文与类型化结果。通讯录、文档等领域若只复用 Resolver 而不复用这些基础设施,仍可能出现跨租户误操作或不可恢复错误。

19.3 Chat Runtime 与契约文件

Go 文件 主要优化 设计价值
internal/shortcut/chat/identity_contract.go 新增用户、机器人、webhook 等身份契约 把“谁在执行”从命令分支提升为显式类型
internal/shortcut/chat/im_contract.go 新增 IM 列表、写结果与公共字段契约 为消息、会话和批处理提供稳定域模型
internal/shortcut/chat/unified_send.go 重构统一发送的目标解析、身份路由、批量发送和能力拒绝 用户表达发送意图,Runtime 决定合法执行器
internal/shortcut/chat/batch_write.go 统一批量写去重、成功/失败账本和未知状态 支持部分失败审计与安全重试
internal/shortcut/chat/chat_conversation.go 增强会话列表分页、投影和完整性字段 单页与全量模式都返回可执行 continuation
internal/shortcut/chat/chat_group.go 对齐群目标、成员和群操作的输入输出 群名与稳定 ID 共用同一解析语义
internal/shortcut/chat/chat_message.go 统一消息读取、回复及消息字段投影 后续回复、转发、下载使用 canonical message identity
internal/shortcut/chat/message_export.go 新增消息 ledger 的临时写入、校验和原子发布 失败时不留下伪成功的半成品文件
internal/shortcut/chat/resource_download.go 对齐资源下载与安全输出流程 下载与导出共享工作区相对路径和原子提交原则
internal/shortcut/chat/file_replace.go 非 Windows 平台使用 os.Rename 提供覆盖替换 保持平台默认的原子替换语义
internal/shortcut/chat/file_replace_windows.go Windows 平台使用 windows.Rename 修复 os.Rename 无法覆盖既有目标的差异
internal/shortcut/chat/lark_alignment.go 补齐创建群、回复等对齐型 Shortcut 将常用意图封装成稳定 Golden Route
internal/shortcut/chatmsg/chatmsg.go 大幅增强 im.message-list.v1 投影、消息身份、引用、资源、reaction 和分页 隔离下游消息响应差异,为 Agent 提供稳定机器结构

这组文件形成了一条清晰的数据流:

Target + Identity
  -> Unified Route
  -> 下层调用
  -> Message/Conversation Projection
  -> Typed Ledger
  -> Atomic Export / Resource Reference

其中 identity_contract.go、im_contract.go 和 chatmsg.go 是最值得跨领域复用的部分:前两者展示如何建立类型化边界,后者展示如何把供应商响应投影成稳定领域模型。

19.4 Smart Shortcut 与 Resolver 文件

Go 文件 主要优化 设计价值
internal/shortcut/targetresolver/resolver.go 新增统一用户/群目标解析、候选去重、精确匹配、跨页搜索和结构化歧义错误 消除各命令独立猜测 ID/名称的根因
internal/shortcut/smart/resolve.go 将旧的局部解析逻辑收敛到共享 Resolver 降低重复实现和规则漂移
internal/shortcut/smart/chat_messages.go 重构自然群/用户目标、typed 分页、去重、结果上限与导出 将消息历史变为有界、可证明完整的读取流程
internal/shortcut/smart/group_members.go 统一群解析、用户/机器人分桶、用户分页和稳定 ID 去重 对复杂成员列表公开完整性和失败信息
internal/shortcut/smart/at_me.go 对齐群目标解析、消息投影与资源引用 特殊消息查询仍复用公共契约
internal/shortcut/smart/search_msg.go 统一群与发送者自然目标解析 多条件搜索在远端调用前完成消歧
internal/shortcut/smart/dm.go 将单聊发送收敛到统一身份和目标规则 避免单聊维护另一套发送实现
internal/shortcut/smart/send_to_group.go 将群发送收敛到 unified send 群名、群 ID 和身份选择走同一路由
internal/shortcut/smart/thread_replies.go 对齐线程回复的消息投影和资源字段 线程场景不再产生独立返回结构
internal/shortcut/runner.go 增强 shortcut flag、约束、隐藏兼容参数和确认处理 Runtime metadata 能真实映射到 Cobra 行为
internal/shortcut/types.go 扩展 Shortcut/Flag 类型信息 为 Schema 生成和 Runtime 装配提供统一源数据

这一层最重要的代码优化是“业务适配器变薄”。Smart 命令不再负责全部搜索、能力选择、分页和投影,而是组合共享 Resolver、contract 和执行器。这种组合方式比复制命令模板更适合通讯录和文档扩展。

19.5 Policy Go 文件

scripts/policy/multi-im-skill-chain/main.go

该文件新增了一套可执行的一致性检查器,读取意图 manifest、有效 CommandRegistry、selection hints 和 Markdown marker,验证:

  • 每个关键意图是否有唯一 preferred tool;
  • fallback 是否有明确 reason code;
  • forbidden default 是否不会重新成为首选;
  • source refs 和文档 marker 是否存在;
  • typed contract 与 event handoff 参考是否漂移;
  • 已退休脚本是否被重新发布;
  • confirmation metadata 是否被降级。

它把“评审规则”实现成 Go 程序,能够直接加载项目真实 Registry,而不是靠文本搜索猜测命令是否存在。这种 Policy-as-Code 模式可抽象成通讯录、文档等产品共用的领域 manifest 校验器。

19.6 边界收口类生产 Go 文件逐项总结

除新增核心抽象外,PR #860 还对既有 Runtime 的关键边界做了系统收口:

Go 文件 主要优化 整体价值
internal/helpers/chat.go 为删除会话分类、清空消息增加真实 --yes 门禁;安全化示例;删除旧 hint 命令 补齐 Runtime confirmation truth 和 Golden Route 收口
internal/shortcut/chat/chat_conversation.go 在单页退出前解析 nextCursor 修复 #860 的 continuation 缺陷
internal/shortcut/chat/resource_download.go 兼容 Windows 盘符、反斜杠和 portable .. 逃逸检查 将 #860 文件安全扩展到跨平台
internal/shortcut/runner.go 所有 flag 类型改用 Cobra *P 注册 提供通用 shorthand 基础能力
internal/shortcut/types.go Flag 新增 Shorthand 让 Runtime、Schema 和 CLI 共享短参数定义
internal/shortcut/smart/local_chat_validation.go 新增时间格式、默认 page limit 和结构化本地错误辅助函数 将散落校验收敛为公共层
internal/shortcut/smart/chat_messages.go 增加时间/页大小校验和 -o;复用默认分页函数 阻止无效远端调用,改善常用导出体验
internal/shortcut/smart/at_me.go 校验 1~3650 天及正数 limit 为特殊读取命令建立明确资源边界
internal/shortcut/smart/thread_replies.go 校验时间格式和正数 limit 与消息列表使用相同本地校验语义
internal/shortcut/smart/unread_chats.go 校验显式 count 大于 0 避免负数/零值被静默当作默认值
internal/shortcut/smart/group_members.go 复用统一默认 page limit 去除重复默认值分支
scripts/policy/multi-im-skill-chain/main.go 对 getwd、exit、open、Registry build/bind 增加可注入接缝 不改变生产行为的前提下完整覆盖失败分支

这组代码体现了三种“小而关键”的优化:

  1. 修顺序:cursor 必须先提取,再决定是否继续翻页。
  2. 提公共函数:时间和分页校验不在多个 Smart 命令中复制。
  3. 建测试接缝:只对进程/I/O 边界注入,不侵入业务逻辑。

19.7 Go 测试文件优化总结

核心架构行为测试

首先建立新能力的行为基线:

  • targetresolver/resolver_test.go:唯一命中、多命中、稳定 ID 和结构化候选;
  • unified_send_resolution_test.go:身份、自然群目标、批量发送和写入前失败;
  • chatmsg_test.go:消息身份、正文、引用、reaction、资源和分页投影;
  • conversation/message/group 相关测试:typed list、分页和兼容字段;
  • event listen 测试:计划编译、事件映射、生命周期和清理回滚;
  • failure classifier/errors 测试:JSON、人类输出和服务端诊断;
  • Multi IM Policy 测试:意图路由、Reference、retired script 和 contract marker。

边界与交付证据测试

其次将测试从“新增功能验证”扩展到“边界与交付证据”:

  • 将 public Shortcut Schema 覆盖固定为 265/265、Chat 固定为 97/97;
  • 验证 47 个新增 Schema 项的风险分类与 Runtime gate;
  • 验证确认前零调用、确认后精确一次调用;
  • 覆盖 cursor 缺失、无效、停滞、page limit 和后续页失败;
  • 覆盖跨页同名目标仍保持歧义;
  • 覆盖 Unix/Windows 路径、symlink、原子写和 no-clobber;
  • 覆盖 shorthand、alias payload 等价和本地参数失败;
  • 通过 CrossPlatformCoverage 测试集合证明 changed-code coverage。

测试策略可概括为:

行为测试:证明新架构“能正确工作”
交付测试:证明所有公开入口“都被发布、都受约束、所有失败边界都不会越权执行”

19.8 Go 层面的核心可复用模式

模式 Go 实现方式 适用场景
Typed Resolver 独立 package + canonical result + structured candidates 通讯录用户/部门、文档/空间、云盘文件
Thin Adapter Smart Shortcut 组合 Resolver、contract 和 executor 所有自然语言 Golden Route
Contract Projection 独立 projector 将 map[string]any 转为稳定 v1 envelope 列表、搜索、事件、批处理结果
Fail Closed cursor/目标/身份不完整时停止,不猜测默认值 写操作和需要完整集合的读取
Bounded Collector page limit、max results、seen cursor、stable dedupe 成员、文档块、文件、审批记录
Atomic Publisher temp file、close/check、rename、no-clobber 导出、下载、备份和迁移
Typed Confirmation metadata 声明 + Runtime 强制 gate + 零调用测试 删除、覆盖、转移、权限修改
Injectable Boundary 将 getwd/open/exit/build 等边界封装为函数变量 CLI、Policy 和后台任务的失败分支测试
Policy as Code Go 加载真实 Registry/manifest 并做语义校验 跨产品 Schema、Skill 和 Runtime 一致性

Go 文件层面的核心结论是:PR #860 同时完成“抽象公共机制”“收紧运行边界”和“补齐验证证据”。复用到其他领域时,应优先复制 package 边界、类型契约和测试不变量,而不是复制具体命令函数。

20. 当前 #860 的整体价值与跨场景复用

20.1 从“运行时能力”到“可交付产品能力”

PR #860 定义了一个更完整的 Done:

完成层级 判断标准 对应 PR
能执行 Runtime 有真实实现 #860
行为稳定 Resolver、分页、typed result/error 有契约 #860
可发现 Registry 和 Schema 正式发布 #860
会选择 selection hints 有 use/avoid 语义 #860
执行安全 local validation、capability 和 typed confirmation 生效 #860
可维护 文档分层、生成漂移、Policy 和覆盖门禁闭环 #860

因此,新领域不能把“代码合入”当成交付完成。一个通讯录或文档 Shortcut 只有同时满足上表六层,才真正适合 Agent 使用。

20.2 通讯录复用重点

在 DirectoryResolver 蓝图之上,应补充 PR #860 展示的发布治理:

  • 每个 user/department Shortcut 都进入 authored Registry;
  • selection hints 区分“查人”“查关注的人”“查某人最近消息”等易混意图;
  • 删除、调岗、批量邀请标记为 write/high 并使用 typed confirmation;
  • 手机号、邮箱格式和分页大小在本地校验;
  • 联系人导出路径使用 portable workspace-relative 规则;
  • completeness test 禁止公开 Shortcut 依赖长期 exclusion。

20.3 文档与云盘复用重点

在原有 DocumentTargetResolver、revision/etag 和原子导出蓝图之上,应补充:

  • read、write、destructive 风险 metadata;
  • 覆盖、删除、权限回收必须 typed confirmation;
  • 示例默认使用 dry-run 或 plan,不直接带确认参数;
  • 文档 URL、路径和目标 revision 在本地尽可能校验;
  • 导出/下载同时识别 Unix 与 Windows 路径语义;
  • 生成 catalog 必须能追溯到 authored Registry 和 contract Reference。

20.4 推荐的跨产品发布清单

  1. Runtime 已实现且有单元测试。
  2. 目标解析支持稳定 ID 和自然目标,并对歧义 fail closed。
  3. 列表返回完整性与 continuation。
  4. 写操作声明 effect/risk/idempotency。
  5. Runtime gate 与 metadata 的 confirmation 完全一致。
  6. Registry 有 canonical path。
  7. Selection hints 有 use/avoid/source refs。
  8. Schema 和 Agent metadata 已生成且 drift clean。
  9. 文档第一示例不绕过确认。
  10. public shortcut completeness、policy 和 changed-code coverage 通过。

21. 综合验证、剩余风险与最终结论

21.1 验证事实需要分层理解

PR #860 当前描述中记录的验证包括:

  • DWS_PACKAGE_VERSION=0.0.0-test go test ./internal/app -count=1
  • DWS_PACKAGE_VERSION=0.0.0-test go test ./internal/shortcut/chat ./internal/shortcut/smart -count=1
  • make policy
  • generated drift clean
  • Schema compatibility 与 authoritative interface integrity 通过
  • 26 products / 898 tools
  • 176 个 Runtime confirmation gate
  • 1,108 个 reviewed Agent examples

上述是 PR 作者提供的本地验证记录。本报告通过 GitHub 状态另行确认:head 33ceab60... 的 AI Behavior 为 success,但 PR-triggered CI workflow run #1802 已完成且结论为 failure。因此不能把 PR 描述中的本地验证等同于“GitHub CI 全绿”;失败原因需结合 Actions job/log 单独排查。

21.2 仍需关注的风险

  1. CI 未全绿:当前 PR 仍为 Open,CI run #1802 显示 failure,应追踪失败 job,确认是否为基础设施、覆盖门禁或真实回归。
  2. 大型生成物审查成本:5 万余行增量主要是生成物,应持续保证 authored source、hash 和 drift check 可重建。
  3. Skill 上下文预算:当前 Chat Skill 为 9,928 bytes,已回到 10,000 bytes 预算内,但余量仅 72 bytes,应继续把细节下沉到 Reference。
  4. 字段文档漂移:results / succeeded 等批处理字段仍需合同化校验。
  5. Shorthand 冲突:框架支持 shorthand 后,应增加每个命令内唯一性和保留字符检查。
  6. 确认不是幂等:39 个写命令的 idempotency 仍为 unknown;确认只能降低误触发,不能解决重试重复写入。
  7. 命名式覆盖标记:大量测试依赖 CrossPlatformCoverage 前缀,长期可考虑用测试清单或覆盖映射替代命名耦合。

21.3 最终结论

PR #860 将“可靠执行 IM 意图”和“完整、安全、可发现地交付能力”合并为同一套工程系统。其核心方法是:

Intent First
  -> Golden Route
  -> Typed Target Resolver
  -> Local Validation + Preflight Capability Check
  -> Typed Confirmation
  -> Bounded Runtime
  -> Versioned Result / Error Ledger
  -> Authored Registry + Selection/Metadata
  -> Generated Schema / Agent Metadata
  -> Policy + Drift + Coverage Gates

这条链路可以直接作为通讯录、文档、云盘、知识库等新领域的标准交付模板。最关键的认知是:Runtime 正确只是起点;只有发现、选择、安全、契约和门禁同时闭环,能力才真正完成产品化。