recursive-tdd

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

recursive-tdd

recursive-tdd

Overview

概述

Test-Driven Development is mandatory for all recursive-mode implementation work. This skill ensures test-first discipline is followed rigorously and recorded in a way recursive-mode tooling can verify.
Core Principle: If you didn't watch the test fail, you don't know if it tests the right thing.
The Iron Law for recursive-mode:
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
所有递归模式下的实现工作都必须遵循测试驱动开发(Test-Driven Development,TDD)。本技能确保严格遵循测试优先准则,并以递归模式工具可验证的方式进行记录。
核心原则: 如果你没有看到测试失败,你就无法确定测试是否针对正确的功能。
递归模式铁律:
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

Trigger examples

触发示例

  • Implement Phase 3 for run '<run-id>'
  • Add a failing regression test first, then fix the bug
  • I already wrote the code; now add tests
    (should trigger TDD reset guidance)
  • Follow RED-GREEN-REFACTOR for this change
  • Implement Phase 3 for run '<run-id>'
  • Add a failing regression test first, then fix the bug
  • I already wrote the code; now add tests
    (应触发TDD重置指导)
  • Follow RED-GREEN-REFACTOR for this change

When to Use

使用场景

Always in Phase 3 (Implementation):
  • New features
  • Bug fixes
  • Refactoring
  • Behavior changes
Default rule:
  • Not for "simple" changes
  • Not when "under pressure"
  • Not because "tests after achieve same goals"
Explicit exception path only:
  • If strict RED-first flow is genuinely infeasible, declare
    TDD Mode: pragmatic
    in the Phase 3 artifact
  • Record a concrete exception reason
  • Record compensating validation evidence under
    /.recursive/run/<run-id>/evidence/
  • Treat this as an explicit deviation, not a silent shortcut
第三阶段(实现阶段)必须使用:
  • 新功能开发
  • Bug修复
  • 代码重构
  • 行为变更
默认规则:
  • 不适用于“简单”变更
  • 不适用于“时间紧迫”场景
  • 不接受“事后测试也能达到同样目标”的理由
仅允许明确的例外路径:
  • 如果严格的先红(RED)流程确实不可行,需在第三阶段工件中声明
    TDD Mode: pragmatic
  • 记录具体的例外原因
  • /.recursive/run/<run-id>/evidence/
    下记录补偿性验证证据
  • 将其视为明确的偏差,而非隐性捷径

RED-GREEN-REFACTOR Cycle

RED-GREEN-REFACTOR 循环

dot
digraph tdd_cycle {
    rankdir=LR;
    red [label="RED\nWrite failing test", shape=box, style=filled, fillcolor="#ffcccc"];
    verify_red [label="Verify fails\ncorrectly", shape=diamond];
    green [label="GREEN\nMinimal code", shape=box, style=filled, fillcolor="#ccffcc"];
    verify_green [label="Verify passes\nAll green", shape=diamond];
    refactor [label="REFACTOR\nClean up", shape=box, style=filled, fillcolor="#ccccff"];
    record [label="Record in\nPhase 3 artifact", shape=box];

    red -> verify_red;
    verify_red -> green [label="yes"];
    verify_red -> red [label="wrong\nfailure"];
    green -> verify_green;
    verify_green -> refactor [label="yes"];
    verify_green -> green [label="no"];
    refactor -> verify_green [label="stay\ngreen"];
    verify_green -> record;
}
dot
digraph tdd_cycle {
    rankdir=LR;
    red [label="RED\nWrite failing test", shape=box, style=filled, fillcolor="#ffcccc"];
    verify_red [label="Verify fails\ncorrectly", shape=diamond];
    green [label="GREEN\nMinimal code", shape=box, style=filled, fillcolor="#ccffcc"];
    verify_green [label="Verify passes\nAll green", shape=diamond];
    refactor [label="REFACTOR\nClean up", shape=box, style=filled, fillcolor="#ccccff"];
    record [label="Record in\nPhase 3 artifact", shape=box];

    red -> verify_red;
    verify_red -> green [label="yes"];
    verify_red -> red [label="wrong\nfailure"];
    green -> verify_green;
    verify_green -> refactor [label="yes"];
    verify_green -> green [label="no"];
    refactor -> verify_green [label="stay\ngreen"];
    verify_green -> record;
}

RED - Write Failing Test

RED - 编写失败的测试

Write one minimal test showing what should happen.
Requirements:
  • One behavior per test
  • Clear, descriptive name
  • Test real code (no mocks unless unavoidable)
  • Clear assertion showing expected outcome
<Good> ```typescript test('rejects empty email with clear error message', async () => { const result = await submitForm({ email: '' }); expect(result.error).toBe('Email is required'); }); ``` </Good> <Bad> ```typescript test('email validation works', async () => { const mock = jest.fn().mockResolvedValue({ valid: true }); const result = await validateEmail(mock); expect(mock).toHaveBeenCalled(); }); ``` </Bad>
编写一个最小化的测试,明确预期行为。
要求:
  • 每个测试对应一个行为
  • 清晰、描述性的命名
  • 测试真实代码(除非必要,否则不使用mock)
  • 明确的断言展示预期结果
<Good> ```typescript test('rejects empty email with clear error message', async () => { const result = await submitForm({ email: '' }); expect(result.error).toBe('Email is required'); }); ``` </Good> <Bad> ```typescript test('email validation works', async () => { const mock = jest.fn().mockResolvedValue({ valid: true }); const result = await validateEmail(mock); expect(mock).toHaveBeenCalled(); }); ``` </Bad>

Verify RED - Watch It Fail

验证RED - 确认测试失败

MANDATORY. Never skip.
bash
npm test path/to/test.test.ts
Confirm:
  • Test fails (not errors)
  • Failure message is expected
  • Fails because feature missing (not typos)
Record in Phase 3 artifact:
markdown
undefined
必须执行,绝不跳过。
bash
npm test path/to/test.test.ts
确认内容:
  • 测试失败(而非报错)
  • 失败消息符合预期
  • 失败原因是功能缺失(而非拼写错误)
在第三阶段工件中记录:
markdown
undefined

TDD Cycle for R3 (Email Validation)

R3(邮箱验证)的TDD循环

TDD Mode: strict
RED Evidence:
  • /.recursive/run/<run-id>/evidence/logs/red/<file>.log
GREEN Evidence:
  • /.recursive/run/<run-id>/evidence/logs/green/<file>.log
RED Phase:
  • Test:
    rejects empty email with clear error message
  • Command:
    npm test src/forms/email.test.ts
  • Expected failure: "Email is required" not found
  • Actual failure: [paste output]
  • RED verified: PASS
undefined
TDD Mode: strict
RED证据:
  • /.recursive/run/<run-id>/evidence/logs/red/<file>.log
GREEN证据:
  • /.recursive/run/<run-id>/evidence/logs/green/<file>.log
RED阶段:
  • 测试:
    rejects empty email with clear error message
  • 命令:
    npm test src/forms/email.test.ts
  • 预期失败:未找到"Email is required"
  • 实际失败:[粘贴输出]
  • RED验证:通过
undefined

GREEN - Minimal Code

GREEN - 编写最小化代码

Write simplest code to pass the test.
Rules:
  • Just enough to pass
  • No additional features
  • No "while I'm here" improvements
  • No refactoring yet
<Good> ```typescript function submitForm(data: FormData) { if (!data.email?.trim()) { return { error: 'Email is required' }; } // ... rest of form handling } ``` </Good> <Bad> ```typescript function submitForm( data: FormData, options?: { strictMode?: boolean; customValidators?: Validator[]; onValidationError?: (err: Error) => void; } ) { // YAGNI - over-engineered } ``` </Bad>
Record in Phase 3 artifact:
markdown
**GREEN Phase:**
- Implementation: Added null check for email field
- Command: `npm test src/forms/email.test.ts`
- Result: PASS
- GREEN verified: PASS
编写最简单的代码使测试通过。
规则:
  • 仅满足测试通过的必要代码
  • 不添加额外功能
  • 不进行“顺便优化”
  • 暂不重构
<Good> ```typescript function submitForm(data: FormData) { if (!data.email?.trim()) { return { error: 'Email is required' }; } // ... 其余表单处理逻辑 } ``` </Good> <Bad> ```typescript function submitForm( data: FormData, options?: { strictMode?: boolean; customValidators?: Validator[]; onValidationError?: (err: Error) => void; } ) { // YAGNI - 过度设计 } ``` </Bad>
在第三阶段工件中记录:
markdown
**GREEN阶段:**
- 实现:为邮箱字段添加空值检查
- 命令:`npm test src/forms/email.test.ts`
- 结果:通过
- GREEN验证:通过

REFACTOR - Clean Up

REFACTOR - 代码清理

After green only:
  • Remove duplication
  • Improve names
  • Extract helpers
  • Keep tests green
Never add behavior during refactor.
Record in Phase 3 artifact:
markdown
**REFACTOR Phase:**
- Extracted `validateRequired(field, name)` helper
- Renamed `submitForm` to `processFormSubmission` for clarity
- All tests still passing: PASS
仅在测试变绿后执行:
  • 移除重复代码
  • 优化命名
  • 提取辅助函数
  • 保持测试全部通过
重构期间绝不能添加新行为。
在第三阶段工件中记录:
markdown
**REFACTOR阶段:**
- 提取`validateRequired(field, name)`辅助函数
-`submitForm`重命名为`processFormSubmission`以提升清晰度
- 所有测试仍通过:通过

Common Process Shortcuts (STOP)

常见流程捷径(禁止)

ExcuseReality
"This is just a simple fix, no test needed"Simple code breaks. Test takes 30 seconds.
"I'll test after confirming the fix works"Tests passing immediately prove nothing. You never saw it catch the bug.
"Tests after achieve same goals"Tests-after = "what does this do?" Tests-first = "what should this do?"
"I already manually tested it"Ad-hoc != systematic. No record, can't re-run, no regression protection.
"Deleting working code is wasteful"Sunk cost fallacy. Keeping unverified code is technical debt.
"TDD is dogmatic, I'm being pragmatic"TDD IS pragmatic. Finds bugs before commit, enables refactoring.
"I'll keep the code as reference"You'll adapt it. That's testing after. Delete means delete.
"Test hard = design unclear"Listen to the test. Hard to test = hard to use. Simplify design.
"I need to explore first"Fine. Throw away exploration, start TDD fresh.
"This is different because..."It's not. The rules don't have exceptions.
借口实际情况
"这只是简单修复,不需要测试"简单代码也会出错。编写测试仅需30秒。
"我先确认修复有效,之后再写测试"测试立即通过无法证明任何问题。你从未看到它捕获过bug。
"事后测试也能达到同样目标"事后测试是“这段代码做了什么?”,而先写测试是“这段代码应该做什么?”
"我已经手动测试过了"临时测试不等于系统化测试。没有记录,无法重跑,无法防止回归。
"删除可用代码是浪费"沉没成本谬误。保留未验证的代码会造成技术债务。
"TDD太教条,我这是务实做法"TDD本身就是务实的。它能在提交前发现bug,支持安全重构。
"我留着代码做参考"你会修改它。这属于事后测试。删除就是彻底删除。
"测试难度大=设计不清晰"倾听测试的反馈。难测试的代码也难使用。简化设计。
"我需要先探索一下"没问题。丢弃探索代码,从零开始遵循TDD。
"这个情况不一样,因为..."其实没有区别。规则没有例外。

Red Flags - STOP and Start Over

危险信号 - 停止并重新开始

If you encounter any of these, DELETE CODE and restart with TDD:
  • Code written before test
  • Test passes immediately (not testing what you think)
  • "I'll add tests later"
  • "This is too simple to test"
  • "I know what I'm doing, I don't need the ritual"
  • Can't explain why test failed (or didn't fail)
  • Test testing mock behavior, not real behavior
  • Multiple behaviors in one test ("and" in test name)
如果遇到以下任何情况,请删除代码并重新从TDD开始:
  • 先写代码再写测试
  • 测试立即通过(未测试到你预期的内容)
  • "我之后再补测试"
  • "这个太简单了,不用测试"
  • "我知道自己在做什么,不需要这个流程"
  • 无法解释测试为何失败(或为何未失败)
  • 测试的是mock行为,而非真实行为
  • 一个测试包含多个行为(测试名称中有“and”)

Integration with recursive-mode Phase 3

与递归模式第三阶段的集成

Phase 3 Artifact TDD Section

第三阶段工件的TDD部分

Every Phase 3 artifact must include:
markdown
undefined
每个第三阶段工件必须包含:
markdown
undefined

TDD Compliance Log

TDD合规日志

TDD Mode: strict
RED Evidence:
  • /.recursive/run/<run-id>/evidence/logs/red/<file>.log
GREEN Evidence:
  • /.recursive/run/<run-id>/evidence/logs/green/<file>.log
TDD Mode: strict
RED证据:
  • /.recursive/run/<run-id>/evidence/logs/red/<file>.log
GREEN证据:
  • /.recursive/run/<run-id>/evidence/logs/green/<file>.log

Requirement R1 (Feature X)

需求R1(功能X)

Test:
test/features/x.test.ts
- "should do Y when Z"
  • RED: [timestamp] - Failed as expected: [output]
  • GREEN: [timestamp] - Minimal implementation: [description]
  • REFACTOR: [timestamp] - Cleanups: [description]
  • Final state: PASS - all tests passing
测试:
test/features/x.test.ts
- "当Z时应该执行Y"
  • RED: [时间戳] - 按预期失败:[输出]
  • GREEN: [时间戳] - 最小化实现:[描述]
  • REFACTOR: [时间戳] - 清理内容:[描述]
  • 最终状态:通过 - 所有测试通过

Requirement R2 (Bug Fix)

需求R2(Bug修复)

Regression Test:
test/bugs/issue-123.test.ts
- "reproduces crash on empty input"
  • RED: [timestamp] - Confirmed bug: [output]
  • GREEN: [timestamp] - Fix applied: [description]
  • REFACTOR: [timestamp] - N/A (minimal fix)
  • Final state: PASS - test passes, bug fixed

If strict mode cannot be followed, the artifact must include:

```markdown
回归测试:
test/bugs/issue-123.test.ts
- "复现空输入导致的崩溃"
  • RED: [时间戳] - 确认bug:[输出]
  • GREEN: [时间戳] - 应用修复:[描述]
  • REFACTOR: [时间戳] - 无(最小化修复)
  • 最终状态:通过 - 测试通过,bug已修复

如果无法遵循严格模式,工件必须包含:

```markdown

Pragmatic TDD Exception

务实TDD例外

Exception reason: [specific reason strict RED-first flow was not feasible] Compensating validation:
  • [extra tests, targeted manual verification, diff review, etc.]
  • /.recursive/run/<run-id>/evidence/<supporting-file>
undefined
例外原因:[严格先红流程不可行的具体原因] 补偿性验证:
  • [额外测试、针对性手动验证、差异评审等]
  • /.recursive/run/<run-id>/evidence/<supporting-file>
undefined

Phase 3 Coverage Gate Addition

第三阶段覆盖检查项

markdown
undefined
markdown
undefined

Coverage Gate

覆盖检查

  • Every new function has a corresponding test
  • Every bug fix has a regression test that fails before fix
  • All RED phases documented with failure output
  • All GREEN phases documented with minimal implementation
  • All tests passing (no skipped tests)
  • No production code written before failing test
TDD Compliance: PASS / FAIL
undefined
  • 每个新函数都有对应的测试
  • 每个bug修复都有在修复前会失败的回归测试
  • 所有RED阶段都记录了失败输出
  • 所有GREEN阶段都记录了最小化实现
  • 所有测试通过(无跳过的测试)
  • 没有在失败测试前编写生产代码
TDD合规性:通过 / 不通过
undefined

Phase 3 Approval Gate Addition

第三阶段审批检查项

markdown
undefined
markdown
undefined

Approval Gate

审批检查

  • TDD Compliance: PASS
  • Implementation matches Phase 3 plan
  • No code without preceding failing test
  • All tests documented in TDD Compliance Log
Approval: PASS / FAIL
undefined
  • TDD合规性:通过
  • 实现符合第三阶段计划
  • 没有无前置失败测试的代码
  • 所有测试都记录在TDD合规日志中
审批:通过 / 不通过
undefined

Bug Fix TDD Procedure

Bug修复的TDD流程

  1. Add Regression Test First
    • Write test that reproduces the bug
    • Run test, confirm it fails with expected error
    • Document failure in Phase 3 artifact
  2. Implement Minimal Fix
    • Fix only what's needed to make test pass
    • Run test, confirm it passes
    • Document fix in Phase 3 artifact
  3. Verify No Regressions
    • Run full test suite
    • Confirm nothing else broke
    • Document in Phase 3 artifact
  4. Lock Phase 3
    • TDD Mode is declared
    • TDD Compliance: PASS
    • Approval: PASS
    • Status: LOCKED
  1. 先添加回归测试
    • 编写复现bug的测试
    • 运行测试,确认它按预期报错
    • 在第三阶段工件中记录失败情况
  2. 实现最小化修复
    • 仅修复使测试通过所需的内容
    • 运行测试,确认它通过
    • 在第三阶段工件中记录修复内容
  3. 验证无回归
    • 运行完整测试套件
    • 确认没有其他功能被破坏
    • 在第三阶段工件中记录结果
  4. 锁定第三阶段
    • 声明TDD模式
    • TDD合规性:通过
    • 审批:通过
    • 状态:已锁定

Example: Complete Phase 3 TDD Section

示例:完整的第三阶段TDD部分

markdown
undefined
markdown
undefined

TDD Compliance Log

TDD合规日志

R1: Add email validation

R1:添加邮箱验证

Test:
test/forms/validation.test.ts
RED Phase (2026-02-21T10:15:00Z):
bash
$ npm test test/forms/validation.test.ts
FAIL: Expected 'Email is required', got undefined
RED verified: PASS
GREEN Phase (2026-02-21T10:18:00Z):
  • Added null check in
    submitForm()
    function
  • Test passes GREEN verified: PASS
REFACTOR Phase (2026-02-21T10:22:00Z):
  • Extracted
    validateRequired()
    helper
  • All tests still passing REFACTOR complete: PASS
测试:
test/forms/validation.test.ts
RED阶段(2026-02-21T10:15:00Z):
bash
$ npm test test/forms/validation.test.ts
失败:预期'Email is required',实际得到undefined
RED验证:通过
GREEN阶段(2026-02-21T10:18:00Z):
  • submitForm()
    函数中添加空值检查
  • 测试通过 GREEN验证:通过
REFACTOR阶段(2026-02-21T10:22:00Z):
  • 提取
    validateRequired()
    辅助函数
  • 所有测试仍通过 REFACTOR完成:通过

R2: Fix crash on empty array

R2:修复空数组导致的崩溃

Regression Test:
test/utils/array.test.ts
RED Phase (2026-02-21T10:25:00Z):
bash
$ npm test test/utils/array.test.ts
FAIL: TypeError: Cannot read property 'map' of undefined
RED verified: Bug reproduced PASS
GREEN Phase (2026-02-21T10:27:00Z):
  • Added guard clause in
    processItems()
  • Test passes GREEN verified: PASS
REFACTOR: N/A (minimal 2-line fix)
回归测试:
test/utils/array.test.ts
RED阶段(2026-02-21T10:25:00Z):
bash
$ npm test test/utils/array.test.ts
失败:TypeError: Cannot read property 'map' of undefined
RED验证:bug复现 通过
GREEN阶段(2026-02-21T10:27:00Z):
  • processItems()
    中添加守卫语句
  • 测试通过 GREEN验证:通过
REFACTOR:无(仅2行的最小化修复)

Verification

验证

Full suite run:
npm test
Result: 47 passing, 0 failing
undefined
完整套件运行:
npm test
结果:47个通过,0个失败
undefined

References

参考资料

  • REQUIRED: Follow this skill for all Phase 3 implementation work
  • 必须遵循: 所有第三阶段实现工作都需遵循本技能要求