Continue 仓库的 Stale & Misleading Comments 检查:四类过时注释检出模式与 .continue/checks 执行机制
本文以 Continue 仓库自身的检查定义文件 stale-comments.md 为主体,完整解读这条"过时与误导性注释"检查的四类检出模式、检查范围与排除规则,并结合 CLI 源码剖析 .continue/checks/ 目录下的检查文件是如何被发现、解析并在 cn review / cn checks 工作流中执行的。读完后你可以理解这条检查的每一类反例如何判定,并能在自己的仓库中复用同款检查定义。
一、检查文件的定位:Continue 的自我审查配置
stale-comments.md 位于仓库根目录的 .continue/checks/ 目录下,是 Continue 团队为自己代码库编写的 agent 检查(check)定义。它使用 YAML frontmatter 声明检查的名称与用途:
---
name: Stale & Misleading Comments
description: Flag comments that no longer match the code they describe.
---
.continue/ 目录是 Continue 仓库自己的"dogfooding"配置区,与这条检查相关的结构如下:
.continue/checks/— 存放 7 个检查定义,除 stale-comments.md 外还有 anti-slop.md、react-best-practices.md、security-audit.md、setup-scripts.md、update-agents-md.md、update-continue-docs.md;.continue/agents/— 存放 agent 定义(如 breaking-change-detector.md、security-review.md 等);.continue/environment.json— 声明环境安装命令,当前内容仅为"install": "npm i",即 agent 会话初始化时执行npm i准备依赖。
背景:为什么需要这条检查
文档的 Context 一节给出了动机:在一个快速迭代、贡献者众多的 TypeScript monorepo 中,注释会频繁地与其描述的代码脱节。更关键的是文档中的一句判断——一条有误导性的注释比没有注释更糟糕:它不仅不提供帮助,还会主动把开发者引向错误的理解并由此引发 bug。这条检查的目标,就是捕获那些"与代码矛盾、不再匹配、或歪曲了相邻代码"的注释。
二、四类检出模式(完整继承原文档判定标准)
以下四个小节完整保留原文档定义的检出模式与正/反例,它们是这条检查的全部判定依据。
模式一:与代码相矛盾的注释
检查对象是内联注释(//)与块注释(/* */)中"描述已不再符合代码实际行为"的情况。
BAD —— 注释说会重试,代码却没有重试:
// Retry the request on failure
const result = await fetch(url);
BAD —— 注释描述的是旧的参数列表:
// Takes a model name and returns the provider
function getProvider(config: ModelConfig, context: ContextManager) {
GOOD —— 注释与实际行为一致:
// Resolve provider from full model configuration and context
function getProvider(config: ModelConfig, context: ContextManager) {
这三组例子给出了一个清晰的判定范式:注释声明的行为("on failure 重试"、参数是"model name")必须能在紧邻的代码中得到印证;签名已演进为 (config, context) 后,旧的单参数描述即为过时注释。
模式二:针对已完成工作的 TODO/FIXME/HACK
当 TODO、FIXME、HACK 注释所描述的工作在周边代码中显然已经完成时,应被标记。
BAD —— TODO 要求补充输入校验,但校验代码已经存在:
// TODO: add input validation
if (!input || typeof input !== "string") {
throw new Error("Invalid input");
}
这类残留注释的典型危害是误导后续贡献者重复劳动,或让人误以为校验尚未就绪。
模式三:带有误导性注释的被注释代码
被注释掉的代码块若带有"暗示自己仍被需要"的注释,而实际功能已被替代或移除,则应被标记。
BAD —— 注释声称"保留用于回退",但回退逻辑实际已被现代实现取代:
// Keep this for fallback support
// const oldProvider = new LegacyProvider(config);
// oldProvider.initialize();
const provider = new ModernProvider(config);
判定要点在于"注释声称的用途"与"当前代码路径"是否矛盾:ModernProvider 已成为唯一路径时,"keep for fallback"的说法就是误导。
模式四:JSDoc 与函数签名不匹配
检查 JSDoc 注释中的 @param、@returns、@throws 标签是否与实际函数签名一致——参数名、类型、返回类型都要对得上。
BAD —— 文档描述了一个并不存在的参数:
/**
* @param modelName - The model to use
* @returns The completion text
*/
async function complete(config: AutocompleteConfig): Promise<Result> {
签名参数是 config: AutocompleteConfig,而文档却声称有 modelName 参数,二者不匹配即为检出项。
三、检查范围与排除规则
原文档明确界定了这条检查应聚焦的代码区域与不应触碰的区域。
重点检查目录
| 目录 | 说明 |
|---|---|
core/ |
所有扩展共享的核心逻辑 |
extensions/vscode/src/ |
VS Code 扩展源码 |
extensions/cli/src/ |
CLI 扩展源码 |
gui/src/ |
React GUI 组件 |
packages/ |
共享 npm 包 |
这与本仓库的实际目录结构一致(见仓库根目录的 core/、extensions/、gui/、packages/ 各子目录),说明该检查是贴合 Continue 这个 TypeScript monorepo 的实际布局编写的。
排除项(Exclusions)
以下场景不应被标记,避免误报:
- 许可证头(license headers)与版权声明;
- 生成文件、vendored 代码或
node_modules中的注释; - 测试文件中用于描述"预期(故意写错的)行为"的注释——测试代码常常需要注释说明反例为何是错的;
- 作为测试数据使用的测试 fixture 中被注释掉的代码。
四、源码级解析:检查文件如何被发现与执行
本节从 CLI 源码出发,说明 .continue/checks/ 目录中的这份定义文件在 Continue 工具链中的实际角色。以下结论均可在对应源码中直接验证。
4.1 发现的三级顺序
resolveReviews.ts 中的 resolveReviews() 函数实现了检查/agent 的解析,注释中明确了三级优先级:
- CLI
--agent标志(最高优先级):显式指定的 agent 路径直接生效,isLocalPath()会识别以.、/、~开头或以.md/.yaml/.yml结尾的路径(含 Windows 盘符路径); - Hub API:当前实现中
resolveFromHub()已被移除,直接返回空数组(见 resolveReviews.ts 的注释 "Hub review resolution has been removed"); - 本地回退:扫描
.continue/agents/*.md与.continue/checks/*.md两个目录下的全部 Markdown 文件。
其中几个值得注意的实现细节(见 resolveReviews.ts 的 resolveFromLocal()):
- 目录优先级:先扫
agents/再扫checks/,若两个目录存在同名文件,agents/中的版本胜出; - 显示名规则:文件名去掉扩展名后,将
-和_替换为空格——因此stale-comments.md在结果列表中显示为 "Stale Comments",frontmatter 中的name字段则作为检查自身的元数据描述其用途; - 目录不存在或读取失败时静默跳过,不中断解析。
测试用例 resolveReviews.test.ts 中有专门的用例 "discovers files from .continue/checks/",验证了从 checks 目录发现检查文件的行为,并覆盖了 agents/checks 同名文件时 agents 优先的场景。
4.2 cn checks 命令:查看与处理检查结果
checks.ts 实现了 cn checks 命令,该命令在 index.ts 中以 checks [action] [pr-url] 形式注册,支持三种用法:
cn checks [pr-url] # 列出某 PR 的检查结果(含 diff)
cn checks accept [pr-url] # 接受所有待处理建议
cn checks reject [pr-url] # 拒绝所有待处理建议
从源码结构看,其工作流为:
- PR 解析:优先使用命令行传入的 PR URL;缺省时
detectPrUrl()从当前 git 分支 + 远程 URL 出发,通过 GitHub API(pulls?head=owner:branch&state=open)自动探测对应 PR,可选GITHUB_TOKEN环境变量提供鉴权(见 checks.ts); - 状态查询:
listChecks()请求api/checks/status?pullRequestUrl=...,打印每个检查的状态图标(success / failure / pending)、描述、提交信息与建议状态,有 commit 的检查还会拉取agents/{sessionId}/diff展示 diff; - 建议处置:
acceptChecks()/rejectChecks()对处于pending且带 commit 的检查逐一下发agents/{sessionId}/accept或/reject请求; - 退出码约定:全部通过为 0、存在失败为 1、仍有 pending 为 2(见 checks.ts),这使该命令可以直接嵌入 CI 脚本做门禁判断;认证缺失时抛出
AuthenticationRequiredError并以退出码 1 结束。
4.3 与 GitHub Actions 的集成
仓库还提供了 actions/general-review/action.yml 这个复合 Action("Continue PR Review"),展示了 checks 类工作流在 PR 自动化中的典型接入方式:
- 输入为
continue-api-key、continue-org、continue-agent三项; - 触发门控:draft PR 直接跳过;仅允许具有 admin/maintain/write 权限的贡献者(PR 作者或评论触发
@continue-review的评论者)运行,API 查询失败时回退到author_association白名单(OWNER/MEMBER/COLLABORATOR); - 执行阶段通过
gh pr diff与gh pr view --json title,author,body,files收集 PR 上下文,生成 review prompt 后以 headless 方式运行timeout 360 cn --agent "$CONTINUE_ORG/$CONTINUE_AGENT" -p "@$PROMPT_FILE" --allow Bash,并对输出做 ANSI 清理; - 结果以带
<!-- continue-agent-review -->标记的"粘性评论"写回 PR:一小时内更新同一条评论,超过一小时则新建评论以保留历史; - 对
CONTINUE_ORG/CONTINUE_AGENT做了正则白名单校验(^[a-zA-Z0-9_-]+$/^[a-zA-Z0-9_/-]+$)以防止命令注入。
五、如何在自己的仓库复用这条检查
基于原文档与源码结构,在自己的 TypeScript 仓库中复用 Stale & Misleading Comments 检查的方式如下(仅涉及查看与配置,不修改 Continue 仓库本身):
- 在仓库根目录创建
.continue/checks/stale-comments.md,按 frontmatter 格式写入name与description,正文可参考 stale-comments.md 的四类模式、"Key Files to Check" 与 "Exclusions" 三段式结构,将目录清单替换为自己仓库的布局; - 通过
--agent .continue/checks/stale-comments.md显式指定运行,或在登录 Hub / 未登录时依赖本地回退自动发现(见 4.1 节的三级顺序); - 若需查看运行产物,用
cn checks [pr-url]列出结果,cn checks accept [pr-url]接受建议;CI 中可利用其 0/1/2 退出码做状态判断; - 维护排除规则时保留原文档的四类 Exclusions(许可证头、生成代码、测试中的故意错误行为注释、fixture 中被注释代码),这是控制误报率的关键。
六、参考文件汇总
| 文件 | 作用 |
|---|---|
.continue/checks/stale-comments.md |
本检查的完整定义(四类模式、范围、排除项) |
.continue/environment.json |
环境安装声明(npm i) |
extensions/cli/src/commands/review/resolveReviews.ts |
checks/agents 的三级解析与本地发现逻辑 |
extensions/cli/src/commands/review/resolveReviews.test.ts |
"discovers files from .continue/checks/" 等用例 |
extensions/cli/src/commands/checks.ts |
cn checks 的 list/accept/reject 实现与退出码 |
extensions/cli/src/index.ts |
checks [action] [pr-url] 命令注册处 |
actions/general-review/action.yml |
PR 自动审查复合 Action 示例 |
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00