Main TDD loop: 1. Run tests 2. If fail: ask model to fix 3. Repeat until pass or MAX_TDD_ITERATIONS
(source_path, test_path, yolo=True)
| 87 | ) |
| 88 | |
| 89 | def run_tdd_loop(source_path, test_path, yolo=True): |
| 90 | """ |
| 91 | Main TDD loop: |
| 92 | 1. Run tests |
| 93 | 2. If fail: ask model to fix |
| 94 | 3. Repeat until pass or MAX_TDD_ITERATIONS |
| 95 | """ |
| 96 | from core.agent import run_agent |
| 97 | from core.context import load_file |
| 98 | from utils import config as _cfg |
| 99 | _cfg.AGENT_CONFIG['confirm_write'] = False |
| 100 | _cfg.AGENT_CONFIG['confirm_shell'] = False |
| 101 | source_p = Path(source_path) |
| 102 | test_p = Path(test_path) |
| 103 | if not test_p.exists(): |
| 104 | show_error(f'Test file not found: {test_path}') |
| 105 | return |
| 106 | test_code = test_p.read_text() |
| 107 | history = [] |
| 108 | # If source doesn't exist yet, generate it from tests |
| 109 | if not source_p.exists(): |
| 110 | info(f'Generating {source_p.name} from tests...') |
| 111 | load_file(str(test_p)) |
| 112 | prompt = build_generate_prompt(source_path, test_path, test_code) |
| 113 | _, history = run_agent(prompt, history, yolo=True) |
| 114 | # Verify file was actually written with content |
| 115 | if not source_p.exists() or source_p.stat().st_size < 10: |
| 116 | show_error(f"{source_p.name} was not created or is empty. Retrying...") |
| 117 | _, history = run_agent( |
| 118 | f"You must create {source_p.name} using write_file with actual Python code. " |
| 119 | f"The file does not exist yet. Write the implementation now.", |
| 120 | history, yolo=True |
| 121 | ) |
| 122 | # TDD loop |
| 123 | for iteration in range(1, MAX_TDD_ITERATIONS + 1): |
| 124 | info(f'Running tests — iteration {iteration}/{MAX_TDD_ITERATIONS}...') |
| 125 | result = run_tests(test_path) |
| 126 | show_tdd_status(iteration, MAX_TDD_ITERATIONS, |
| 127 | result.passed, result.failed + result.errors, result.total) |
| 128 | show_shell(f'pytest {test_p.name} -v', result.output, |
| 129 | error=not result.all_pass) |
| 130 | if result.all_pass and result.total > 0: |
| 131 | show_tdd_complete(result.passed, result.total, iteration) |
| 132 | show_response( |
| 133 | f'All {result.total} tests pass. ' |
| 134 | f'{source_p.name} is complete after {iteration} iteration(s).' |
| 135 | ) |
| 136 | return |
| 137 | if iteration == MAX_TDD_ITERATIONS: |
| 138 | break |
| 139 | # Show failures and ask model to fix |
| 140 | for name, error in result.failures[:2]: |
| 141 | show_tdd_failure(name, error) |
| 142 | if source_p.exists(): |
| 143 | source_code = source_p.read_text() |
| 144 | load_file(str(source_p)) |
| 145 | else: |
| 146 | source_code = '' |
no test coverage detected