# RFC:针对 Cordis 对外服务接口的 JSDoc 完整性门禁 [English](2026-07-04-cordis-jsdoc-completeness-gate.md) | 中文 Status: implemented ## 问题 生成的 Cordis 目录此前强制了事件分发模式,但未强制要求完整的服务与事件契约。方法可以缺少描述,参数或返回值可以在跨插件 API 接口上不写文档——而这恰恰是 IDE 引导最重要的地方。 AGENTS.md 中的规则(「每个导出都有解释语义的 JSDoc」)只能靠评审以行文形式检查;本仓库的既定偏好是将不变式编码为机械门禁。「Cordis 服务函数与事件」这一范围有精确的机器定义,只有目录生成器知道:事件是 `declare module 'cordis'` 内 `interface Events` 的成员,服务接口是每个 `interface Context` 键所指向的类的公开方法。ESLint 规则看不到这层映射;生成器在每次运行时计算它。 ## 决策 扩展 `scripts/gen-cordis-catalog.ts`(同一次遍历、同一个 `@mode` 先例),对其编目的所有内容强制 JSDoc 完整性。`verify-cordis-catalog` 在 `doc-sync`(文档同步门禁)内运行,CI 和 lefthook pre-push 钩子都已执行 `doc-sync`,因此门禁无需新增任何接线(质量门禁原则:单一真源)。 契约如下: - **事件**需要描述性文字,以及为每个**载荷参数**提供非空的 `@param`。载荷参数是携带事件数据的签名参数;`this` 接收者注解和尾部的 waterfall(瀑布式事件) `next` 免检——`next` 是分发机制,其语义已由 `@mode waterfall` 标签(及其结构交叉检查)拥有,逐事件重述只是样板代码。为免检参数写文档是允许的;只有缺失才被检查。 - **服务类**需要类级 JSDoc,每个公开方法需要描述性文字、为每个参数提供非空的 `@param`,以及非空的 `@returns`——除非标注的返回类型是 `void`/`Promise`(此时 `@returns` 可选——resolve 时机有时值得记录——但从不强制要求)。 - **陈旧标签报错**:`@param` 命名了一个不存在的参数即为违规,与 `@mode` 与签名矛盾的检查对称。标签描述必须非空;超出此范围的语义质量由评审负责。 - **遍历可检查的显式性**:门禁是纯 AST 遍历(不使用类型检查器),因此服务方法必须显式标注返回类型(推断的返回类型无法分类),接口参数必须是简单标识符(解构模式没有名称供 `@param` 匹配)。 - **违规聚合**为一条错误信息,列出所有违规项——修复时一次看到完整清单。此前快速失败的 `@mode` 检查也移入同一份聚合报告,消息文本不变。 这些标签**仅用于强制检查**:`parseJsDoc` 现在在遇到第一个块标签时截止描述性文字(标准 JSDoc 语义,同时也防止多行标签描述泄漏到目录中充当正文),因此 `@param`/`@returns` 不会改变渲染出的目录。 `packages/core/agent/tests/gen-cordis-catalog.spec.ts` 中的负路径测试对合成 fixture(测试前置数据)运行 `collectEvents`/`collectServices`,验证每条守卫都会触发且免检规则成立。撰写规则写在根 [AGENTS.md](../../../../AGENTS.md) 的约定条目中,与 `@mode` 规则并列。 ## 曾考虑的替代方案 - **ESLint 规则**:无法看到该范围的机器定义(哪些 `interface Events` 成员、哪些 `ctx.` 类构成 Cordis 对外服务接口);目录生成器在每次运行时恰好计算这层映射,因此门禁放在那里。 - **将标签渲染到目录中**:曾考虑将服务部分重构为逐方法条目,但有意推迟:方法文档的消费场景是源码 JSDoc 加 IDE 悬停,目录保持索引定位。 - **逃逸标签**:不设。该接口面小且经过策展(采纳时 12 个服务、57 个方法、27 个事件),要点在于检查不可豁免。 ## 后果 - 新增事件或服务方法时,若参数或返回值未写文档则无法落地:生成器拒绝重新生成,`verify-cordis-catalog` 在 pre-push 和 CI 中失败。采纳时发现的约 139 处缺口在同一个变更中补齐,门禁以绿色状态落地。 - 服务接口必须显式标注返回类型并使用标识符参数。两项约束在采纳时均未构成限制(所有方法已有标注;不存在解构的 seam 参数);但二者现在是承重要求,违反时会被机械检测到。 - AGENTS.md 中通用的 JSDoc 规则(「一行能说清就用一行」)在此接口上获得了更严格的特例:仅当方法无参数且返回 void 时,一行摘要才足够。 - 为 `next` 或 `this` 写 `@param` 合法但不检查——这是有意的不对称:门禁强制载荷契约,拒绝要求样板代码。 - 渲染出的目录不受这些标签影响(正文在第一个块标签处截止)。如果后续需要方法级渲染,那是一个独立的目录设计决策,而非本门禁的缺口。