Tech Lead's Club - 规范,精益
冻结义务。解放计划。由非构建者验证其正确性。源自 tlc-spec-driven 3.3.0(Felipe Rodrigues)、tlc-plan 和 tlc-implement。
┌──────┐ ┌────────┐ ┌───────┐ ┌────────┐
│ 计划 │ → │ 检查 │ → │ 构建 │ → │ 验证 │
└──────┘ └────────┘ └───────┘ └────────┘
阅读它 义务 你的 始终
四个步骤,代码前两份人工制品,代码后一份。人工确认什么必须为真以及如何构建,这在一份文档中完成,然后才将其转化为带证明的义务。没有任务分解,计划也不含组件目录:难以撤销的决策以其字面形式标记为单向门,一切可逆决策在构建时决定并在差异中审查。
为何采用这种结构
编码代理的主要失败并非推理能力差,而是需求被读取但从未成为活跃义务——然后在此基础上声称完成。衡量后效果良好的缓解措施是一个微小、冻结、外部的义务集合加上一个非作者身份的验证者;自我检查会再现作者自身的盲点。因此,本技能将预算花在这两件事上,并拒绝将其花在设计模型如何工作的编排上。
有两个后果值得预先说明,因为它们正是使其区别于传统规范驱动流程之处:
- 粒度不等于质量。 将特性拆分成十五个单文件任务买来的是顺序,而非正确性,且代价是每个任务都要重新读取流程。证明覆盖率才能买来正确性。
- 模型必须遵守的计划与义务争夺注意力。 诸如
位置、工具、依赖等字段是模型自身决定的工作,因此不会被写入文档。
关键规则
固定集合。即使未读取任何参考文件,这些规则仍然有效,并且它们是唯一不会随配置文件而缩放的规则。
- 每条检查是一个可观测的声明,附带具体值加上证明——即退出代码能裁决的测试或命令。无证明,即非检查。
- 测试断言检查所说的内容,而非代码恰好做的事。绝不要通过阅读实现来编写测试。
- 绝不要弱化断言、删除测试或跳过测试以使测试套件通过。一个确实错误的检查是暂停并询问,而非编辑。
- 检查和
测试策略行一旦批准即固定。在设计部分,着陆、关系和界面是可添加的——构建时发现的单向门在关闭它的代码之前添加一行,用户批准的行则永不重写。流程和影响则不是:它们是保持为真的,因此不同的路径会改变该路径提交中的跳转。 - 验证者是一个全新的子代理,绝不是作者,绝不可选,绝不等待被询问。持有整个特性的人在特性的最后一次提交落地后派遣它——针对
<特性基准>..HEAD,且包含每一条检查。绝不能由构建者派遣,也绝不能作为构建者的子进程。构建者完成后报告并停止。工作不是在最后一次提交时完成;而是在验证者的报告覆盖每一条检查时完成。 - 配置文件是下限,并非秘密。 验证报告需指明它,或者“未注入故障”读起来就像是忘记注入它们。
- 完成门控是一个脚本,而非感觉:
validate_verification.py必须退出码为0。 - 影响范围: 已批准的特性规范授权本地编辑和本地提交。
git push、部署和生产数据更改需要针对该操作的明确许可。
配置文件
项目在AGENTS.md或等效文件中声明运行级别。若无声明:light。与tlc-implement相同的三个级别,门控方式相同,因此在这两个技能之间切换无需第二套词汇。
## tlc-spec-lean
profile: light
budget: 150k
| 配置文件 | 增加内容 | 无法捕获的错误 |
|---|---|---|
light(默认) | 证明在HEAD处运行,每个命名测试显示存在且运行,每条检查一个定位断言,级别和采样间隙,已覆盖现有内容重新读取 | 集合成员无证明;在错误实现下也能通过的测试 |
standard | 重新计算覆盖率连接,测试策略行附带每条裁决,每个断言界面一个故障 | 与绑定源冲突的检查;没有人构建的界面 |
ui | 打开并比较绑定源,按屏幕枚举副本和布局 | 仅限间距、颜色和字重,按屏幕枚举 |
每一步增加一个检测到的故障类别,因此便宜的配置文件并非同一产品的折扣——在选择之前请阅读右侧列。关于light有两件事值得明说,因为其所在行已提及但容易被忽略:它不会注意到无人证明的枚举集合成员,也不会注意到在错误实现下通过的测试。standard正是为此而存在。
ui在无界面的工作上不耗费成本:每个屏幕步骤以存在界面为条件。输入为空的步骤仅花费一行,而非一次通过(“无集合行”,“无绑定源”)。
覆盖率连接在每个配置文件中都被写入checks.md——该连接使得遗漏成为结构性问题,且在编写时无需额外成本。standard购买的是验证者从每个集合的权威源重新计算而非读取作者表格的能力。
配置文件是一个固定约束,而非偏好,与tlc-implement不同,它是强制执行的而非请求的:validate_verification.py会拒绝配置文件与checks.md批准时不同的报告,拒绝无故障行或无重新计算覆盖率的standard报告,以及无绑定源部分的ui报告。这样,未执行的步骤与遗忘的步骤仍可区分——这正是声明下限的全部原因。
如果配置文件对于手头的特性显得过于单薄,用一行说明并让用户提升它。在沉默中执行超出配置文件的操作会破坏使声明值得做出的可预测性。
人工制品
.specs/
├── STATE.md # 决策日志(AD-NNN)+ 交接快照
├── LESSONS.md # 由 scripts/lessons.py 渲染——切勿手动编辑
├── lessons.json # 机器所有
└── features/<feature>/
├── plan.md # 问题、流程、影响,然后是其余结构,再然后是标准;审计最后
├── checks.md # 声明 + 证明、覆盖率连接、测试策略、已覆盖内容
└── verification.md # 验证者的报告
当每个阶段产生内容时创建相应文件。对于大约少于三个文件且无单向门的变更,仅编写包含## 意图段落的checks.md并跳过plan.md——这是一个有边界的例外,而非规模矩阵。
理解与义务是分离的人工制品
plan.md之所以存在,是因为人工必须能够在任何内容成为带测试选择器的声明之前进行规划和反对。阅读四十条检查来重构正在构建的内容不是规划,而在决定结构的同时编写检查会产生那些批准已有假设的检查。
两部分共存于一个文件中,因为它们是同一次审查。 文件边界是语义上的:这一侧是人工确认的内容;另一侧是带证明的义务。将计划拆分成规范与设计会在一个既不吻合两者的地方割裂它,并为单个特性增加两个强制停靠点。文件顺序是为了阅读——问题、流程、影响,然后是其余结构,接着是标准,最后是审计表。编写顺序则不同:先写问题,遍览界面,编写标准,然后填充结构。这正是阻止为了证明某个组件而凭空创造标准的方法。关闭门控仍然要求每一条标准最终落在流程、关系或界面中,否则视为范围外或结构存在缺口。
推导至checks.md是承重部分,而非文书工作。界面中的每条路由对应一个覆盖率集合行,其成员为状态;着陆中的每个门对应一条检查;关系中的每个实体对应一条检查。checks.md中没有指向的结构部分是死亡或未经证明的,validate_checks.py会针对常见情况发出警告。
设计部分存在;组件目录不存在。 导致设计文档腐烂的从来不是图表,而是每个类的用途/位置/接口/依赖——这些可逆细节在数周内过时,然后以书面文档的权威性误导下一位读者。这些字段在此均不存在。五个有边界的部分:
| 部分 | 评审内容 | 排除内容 |
|---|---|---|
流程 | 路径,每条跳转一行 | 任何既不存在也不通过门创建出的模块——那是放置问题 |
影响 | 底层变化:术语和现有数据 | 风险登记册 |
关系 | 实体、基数、单向约束 | 列和类型 |
界面 | 路由、输入、输出、状态 | 请求体规范,以及检查ID——那些还不存在 |
着陆 | 单向门,含字面形式和被拒绝的替代方案 | 任何重构可逆转的内容 |
哪个文件夹、多少个类、私有方法叫什么:差异即可。 可逆的,由仓库约定回答,且绝不值得一份人工制品。这是有意的权衡,且是唯一的一个。
当你到达此处时仍有一个未决赌注——两个架构有活跃的替代方案,每个都需要针对此仓库评估成本——这不适合着陆行,而此行是此人工制品为此使用的唯一形式。无论项目使用何种方式解决(一份ADR、RFC、原型),应先完成;然后计划记录获胜的形式使其可审查。
流程
计划 - 问题,然后是路径及变更所干扰的内容,接着是结构的其余部分,再然后是标准。编写顺序仍为问题→界面→标准→结构。事实需要查找;决策需要询问——询问时,提供具体选项及你的推荐,每轮最多两个。两种枚举方式完成查找,因为“考虑边缘情况”找不到任何内容:此特性暴露的界面,每次出现都携带相同的决策,以及九个隐含需求维度。两者都必须填写n/a - <原因>,因此空白意味着尚未决定的项,而非不适用的项。一份人工阅读并在任何检查存在之前即可反对的人工制品。完整流程、如何询问、每个结构部分的规则、模板和关闭门控:plan.md。
检查 - 从计划中推导带证明的声明,将每个枚举集合成员连接到检查,并记录每个已覆盖维度最终落点。以## 交接及算术计算关闭;如果估算超出预算,在构建前停止以请求机制选择。这是下游所有内容通过检查号引用的文件:checks.md。
构建 - 由你决定如何构建,在## 交接算术计算后,且如果估算超出预算,在用户选择机制后进行。从检查编写测试、实现、运行每条证明、以连贯片段提交。无任务列表,无每任务审查表。边界、着陆时机、交接和范围护栏:build.md。
验证 - 当特性最后一次提交落地时,在同一回合派遣一个全新的验证者。不要询问。不要等待“验证工作”。程序、报告格式和范围限定内的重新验证:verify.md。
持久记忆 - 项目决策、会话交接和经验教训层:memory.md。
脚本
将<技能目录>解析为包含此SKILL.md的目录,并调用python3 <技能目录>/scripts/<名称>.py。项目数据位于.specs/下,相对于项目根目录;当当前工作目录不同时,传递--root。非零退出码意味着停止并修复。
| 时机 | 命令 |
|---|---|
| 呈现计划前 | validate_plan.py <特性> |
| 开始构建前 | validate_checks.py <特性> |
| 每次提交前 | check_commit.py --message "<消息>" |
| 声明完成前 | validate_verification.py <特性> |
| 提炼时 | lessons.py add ... |
| 编辑验证器或模板后 | selftest.py |
validate_plan.py运行关闭门控并保护结构部分不变成它所取代的东西:它会拒绝没有SHALL的标准、没有选定默认值的假设、可观测行中着陆为空或n/a未附原因、着陆行中没有字面形式或未拒绝的替代方案、关系中的列和类型、界面路由中没有状态,以及任何留空而非回答为None - <原因>的部分。validate_checks.py是遗漏捕捉器:它会拒绝没有证明的检查、声明大小超过实际分配成员的覆盖率行、缺失的已覆盖维度、以及缺失的配置文件行,并针对计划中审查过但未被任何检查提及的路由发出警告。validate_verification.py会拒绝引用file:line的PASS报告、记录存活的变异体、留下未经证明的成员,或由作者编写。
仅当不存在代码执行工具时跳过脚本;然后通过阅读人工制品执行相同的检查,并在聊天中声明一次你处于退化路径。
selftest.py将本技能自身的纪律应用于其门控:它针对每个规则变异一个已填充的固定装置集合,并要求每个变异体被消灭,运行负面控制以证明范围限定门控在其配置文件下不会触发,并对本技能提供的每个脚本进行冒烟测试——未经练习的脚本是崩溃隐藏之处,而完成门控曾以0退出...
…
[截断以进行翻译]