Autopilot
一个可移植的自主循环,因为它询问工作「完成」意味着什么,而不是假设——并且直到该答案被满足才会停止。
这项技能旨在使以下三个声明无法成立:
- 「它工作了」——但实际上从未运行过。
- 「它完成了」——而唯一的评判者就是完成它的人。
- 「我干过这个」——却没有尝试过什么、失败了什么、以及为什么的记录。
主题无关紧要。重构、迁移、报告、数据集、渲染农场、集群:下面的循环是一样的,只有检查不同。
0. 引导——每个项目只需一次
下面的 <skill> 是此文件所在的目录——CLI 安装后是 .agents/skills/autopilot,或者它被克隆到的位置。所有命令都从项目根目录运行。
node <skill>/scripts/discover.mjs # 检查、内存家园、危险信号
node <skill>/scripts/bootstrap.mjs # 如果不存在则创建分类账本
node <skill>/scripts/skills.mjs # 技能库——选择此项目的专长领域
node <skill>/scripts/tools.mjs # 此机器已经能触及的:MCP 服务器、插件
discover 会打印项目自身的检查命令。该命令是下面每次迭代的完成定义。
如果它打印出 checks: [],请先别相信。发现过程只读取声明了检查的文件;项目的真实检查通常以纯文本形式命名。在它列出的所有 memoryHomes 路径以及 README 和 CI 配置中,grep 一个可运行的命令——曾经有一个项目的 checks: [] 旁边是一个 CLAUDE.md,其中指定了 ./tests/run_all.sh,它在四秒钟内运行了 63 个测试,而一个代理本来可能会发明 (node --check) 的检查在一个死应用上显示为绿色。
只有当该搜索返回空结果时,项目才真正没有自动检查——这对于散文写作、研究和运维很常见,并且不是评判自己工作的许可。在第一次迭代之前商定一个验收检查,并将其写入目标(第 1 节)。以下任何一项都可以作为检查;「我审查过了,看起来没问题」则不是:
| 工作 | 一个不是你自己意见的检查 |
|---|---|
| 代码 | 在前台运行、退出码为 0 的命令 |
| 文档 | 逐声明列出,每个声明附带源或命令的列表 |
| 数据 | 别人可以重新运行并返回预期形状的查询 |
| 基础设施/运维 | 来自系统本身的前后观察 |
| 研究 | 产生数字的查询或提取,加上你提前注册的作为反驳的结果——两者都可由其他人重新运行 |
在接触任何东西之前阅读发现的内容:
memoryHomes——持久知识已经存在的地方。使用这些文件。永远不要创建第二个CHANGELOG.md、第二个学习目录、第二个AGENTS.md。一种知识的第二个家园是代理使仓库变得更糟的最常见方式。signals.envFilesPresent和signals.remote——在第一次迭代之前,询问工作环境是否指向生产环境。它曾经在项目中没有说明任何信息且每次本地运行看起来无害的情况下指向了生产环境。在被告知其他情况之前,假设是的。signals.vcs——none表示没有撤销操作。在第一次迭代之前将输入复制到安全的地方,并在goal.md中说明位置;第 8 节的「提交绿色的内容」在这里没有意义,而这正是工作丢失的确切时刻。signals.dirty——未提交的工作是别人的。创建分支,绝不要在此基础上构建。
在第一次迭代之前武装自己
skills.mjs 是值得拥有的公共技能的简短列表,按专长领域标记。这些标签是词汇表——每个项目上都有 any 和 review,然后根据项目的实际需要添加 web、react、db、docs、perf、a11y、mac、infra、research、design。
node <skill>/scripts/skills.mjs # 目录及其标签
node <skill>/scripts/skills.mjs --install any --dry-run # 它会运行什么
node <skill>/scripts/skills.mjs --install any # 永远有用的集合
node <skill>/scripts/skills.mjs --install react,perf,db # 这个项目的专长领域
选择,不要囤积。 每个安装的技能的描述在每次轮次中都会加载:一百个技能并不是一百个能力,而是一个更小的窗口和一个略读的模型。
安装就是用你的权限运行第三方代码,所以这是一个公告行为:先 --dry-run,说明你要添加什么以及为什么,然后安装。如果项目与目录中的任何专长领域都不匹配,那么 any 就是正确的答案——并且 find-skills 是目录中内容较少的专长领域(研究、基础设施、数据目前内容较少)的入口点。
然后衡量你刚刚花费了多少。 skill-cleaner 随 any 集合一起提供,它是「选择,不要囤积」从建议变成实际行动的方式:
node --experimental-strip-types <skills-root>/skill-cleaner/scripts/skill-cleaner.ts \
--root .agents/skills --root-only --no-logs
它会报告已安装描述所占用的预算、重复项(两个技能回答一个问题——这个循环在更高一层要追捕的缺陷)以及值得压缩的长描述。对此采取行动:卸载此项目未使用的技能,合并重复项而不是同时保留两者。你阅读但忽略的审计与没有审计消耗相同的上下文。
技能只是一半——另一半是可触及范围
skills.mjs 说明了代理知道什么。tools.mjs 说明了它可以触及什么:它在能够读取的配置文件中找到的 MCP 服务器、携带更多内容的插件,以及磁盘上没有任何东西能告诉你的。空结果意味着「不在这些文件中」,而不是「不在这台机器上」。
node <skill>/scripts/tools.mjs
你缺乏的能力不是缩小目标的理由。 它是一个阶梯——已经可触及 → 应用自身的 CLI → 公共服务器 → 连接器(搁置,第 6 节)→ 用 new-mcp.mjs 编写一个。每一级、每一级的成本以及其中的陷阱都在 references/tooling.md 中;在构建任何东西之前阅读它,因为它防止的两个失败从这里看不到:断定能力缺失而它实际上已经配置好了,以及构建已经回答的问题的第二个答案。
最会咬人的一个: 大多数框架在启动时读取其 MCP 配置,因此运行中途编写的服务器通常对编写它的会话不可见。这就是为什么脚手架也是一个 CLI——node server.mjs --call <tool> '<json>',相同的处理器。现在就使用这种形式,让下一个会话获得服务器。「重启后继续」是一个持有文件的停滞循环。
然后,在整个过程中:你在这里学到的东西会成为一个自身的技能(第 5 节),由循环编写并在同一会话中使用——而它缺乏的能力会成为自身的工具,以相同方式使用。
1. 目标——循环一直运行直到满足的东西
在第一次迭代之前,写下一个可证伪的句子和 2-5 个完成标准。写入 goal.md,或者发现已持有的任何文件中。
- 可证伪的:「让 X 变得更好」不行。「每一笔花钱的路径都处于显式的开关后面,并且每个路径都由一个类型或一个失败的测试所持有」可以。
- 每个标准必须可以由不是你的人检查——与第 0 节相同的标准。只有你能确认的标准不是标准;重写它。
- 未知因素是允许的,作为它们自己的标准:「我们知道 N 是否是原因」是研究的合法完成标准。
- 一个大目标是通过小目标实现的,而标准正是这种分解——每个切片都可以独立落地、检查和验证。一个对于一次迭代来说太大的标准会被拆分成它自己的标准;深度是可以的,并且每一级都保持相同的标准(可以由不是你的人检查)。不再可证伪的级别是一个计划,而不是一个标准。
- 你缺乏的能力是一个标准,而不是一个绕行。 「循环可以无人值守地驱动 X,由一个往返证明」放在它解锁的工作旁边(
references/tooling.md)。写下来后,构建一个工具是有边界的,并且它的缺失是可见的;没写下来,它就会变成一个下午,没有产生任何标准,并被视为进展。 - 如果没有人给你一个目标——「продовжуй」而没有其他东西——第一次迭代的唯一输出是一个提议的
goal.md和向人类提出的问题。你编写然后满足的标准是上面的声明 #2,穿着检查清单的外衣。 goal.md还包含固定状态:检查命令、其基线输出、对生产问题的回答、分支(或输入副本的位置)以及安装了哪些技能。一个必须重新推导这些内容的恢复并没有恢复。
然后循环运行直到每个标准都被满足并验证。 而不是直到模型感觉完成,也不是直到审查者安静下来——他们永远不会。每次迭代结束时在 goal.md 中标记哪个标准移动了以及什么证明了它。
仅因第 6 节(询问)、第 7 节(折腾)和第 8 节(上下文)中的原因才提前停止循环。
2. 迭代
一次迭代 = 一次落地变更、检查、验证、记录。不是一次文件,也不是一次轮次。
选择。 从目标中未满足的标准中挑选。如果多个是开放的,选择那个失败会使最多其他工作无效的标准——按风险×影响范围排序,而不是按容易程度。
在缩短之前先理解。 端到端地追踪真实事物。然后,在构建任何新东西之前,询问它是否已经存在——参见 references/premise-check.md,这项技能中收益最高的习惯,也是学习时间最长的习惯。
构建实际上正确的最小东西。根本原因,而不是请求命名的症状:首先找到所有其他具有相同形状的地方,并在它们全部通过的地方修复它。
证明。 运行发现的检查,在前台,读取运行它的 shell 中的退出码——或者更好的是,让不是编写摘要的东西为你读取它:
node <skill>/scripts/prove.mjs --record -- npm run verify # 检查、其真实状态,写入 goal.md
node <skill>/scripts/prove.mjs --times 3 -- <check> # 与自己不一致的检查是脆弱的
证明和验证是模型可以叙述的两个步骤——其他步骤会留下一个文件、一个提交或一个差异,而「检查通过了」和「审查者同意了」都是由希望它们为真的上下文编写的文本。运行器回答第一个:它在没有 shell 的情况下生成,因此它报告的状态是子进程自身的;它拒绝其 npm 脚本包含管道的检查(`