etch-loop 0.4.5__tar.gz → 0.4.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {etch_loop-0.4.5 → etch_loop-0.4.6}/PKG-INFO +1 -1
  2. {etch_loop-0.4.5 → etch_loop-0.4.6}/pyproject.toml +1 -1
  3. etch_loop-0.4.6/src/etch/__init__.py +1 -0
  4. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/analyze.py +30 -22
  5. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/signals.py +11 -3
  6. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/templates/BREAK.md +8 -6
  7. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/templates/ETCH.md +8 -9
  8. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/templates/SCAN.md +8 -6
  9. etch_loop-0.4.5/src/etch/__init__.py +0 -1
  10. {etch_loop-0.4.5 → etch_loop-0.4.6}/.github/workflows/workflow.yml +0 -0
  11. {etch_loop-0.4.5 → etch_loop-0.4.6}/README.md +0 -0
  12. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/agent.py +0 -0
  13. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/cli.py +0 -0
  14. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/display.py +0 -0
  15. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/git.py +0 -0
  16. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/loop.py +0 -0
  17. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/prompt.py +0 -0
  18. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/report.py +0 -0
  19. {etch_loop-0.4.5 → etch_loop-0.4.6}/src/etch/templates/RUN.md +0 -0
  20. {etch_loop-0.4.5 → etch_loop-0.4.6}/tests/__init__.py +0 -0
  21. {etch_loop-0.4.5 → etch_loop-0.4.6}/tests/test_git.py +0 -0
  22. {etch_loop-0.4.5 → etch_loop-0.4.6}/tests/test_loop.py +0 -0
  23. {etch_loop-0.4.5 → etch_loop-0.4.6}/tests/test_prompt.py +0 -0
  24. {etch_loop-0.4.5 → etch_loop-0.4.6}/tests/test_signals.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etch-loop
3
- Version: 0.4.5
3
+ Version: 0.4.6
4
4
  Summary: Run Claude Code in a fix-break loop until your codebase is clean
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "etch-loop"
3
- version = "0.4.5"
3
+ version = "0.4.6"
4
4
  requires-python = ">=3.11"
5
5
  description = "Run Claude Code in a fix-break loop until your codebase is clean"
6
6
  readme = "README.md"
@@ -0,0 +1 @@
1
+ __version__ = "0.4.6"
@@ -179,9 +179,12 @@ For each issue, include the file path, line number (if known), and a one-line de
179
179
  5. List each confirmed issue on its own line, e.g.:
180
180
  - src/auth.py:42 — crashes with empty token string (no guard)
181
181
  - src/api.js:108 — unhandled promise rejection will silently fail
182
- 6. End your output with EXACTLY one of these tokens on its own line:
183
- - `ETCH_ISSUES_FOUND` if you found confirmed bugs worth fixing
184
- - `ETCH_ALL_CLEAR` if the code looks solid or you found nothing certain
182
+ 6. Before the signal token, write this line it appears directly in the terminal:
183
+ `ETCH_SUMMARY: <one sentence, max 80 chars, e.g. "3 bugs found — null deref in auth.py:42, off-by-one in parser.py:88">`
184
+ `ETCH_SUMMARY: no confirmed bugs found`
185
+ 7. End with EXACTLY one of these on its own line:
186
+ `ETCH_ISSUES_FOUND`
187
+ `ETCH_ALL_CLEAR`
185
188
 
186
189
  ## Scope
187
190
 
@@ -210,18 +213,21 @@ Scan the codebase for:
210
213
  ## Rules
211
214
 
212
215
  1. Fix only what you find — do not refactor, rename, or reorganize
213
- 2. One logical fix per commit (the harness will commit for you)
214
- 3. Do not add comments explaining what you fixed
215
- 4. If you find nothing, make no changes
216
+ 2. Do not add comments explaining what you fixed
217
+ 3. If you find nothing, make no changes
216
218
 
217
219
  ## Scope
218
220
 
219
221
  {scope}
220
222
 
221
- ## Commit format
223
+ ## Terminal output (required)
222
224
 
223
- The harness commits automatically. Each commit will be:
224
- fix(edge): <short description of what was fixed>
225
+ After making changes (or deciding there is nothing to fix), write this line — it appears directly in the terminal and is used as the commit message:
226
+ `ETCH_SUMMARY: <one sentence, max 80 chars>`
227
+
228
+ Examples:
229
+ `ETCH_SUMMARY: fixed 3 issues — null guard in auth.py, bounds check in parser.py, timeout in agent.py`
230
+ `ETCH_SUMMARY: nothing to fix — all reported issues were already handled`
225
231
  """
226
232
 
227
233
 
@@ -250,9 +256,12 @@ Be adversarial — think like someone actively trying to make this code fail.
250
256
 
251
257
  1. DO NOT edit any files — read only
252
258
  2. Report your findings clearly, one per line
253
- 3. End your output with EXACTLY one of these tokens on its own line:
254
- - `ETCH_ISSUES_FOUND`if you found anything worth fixing
255
- - `ETCH_ALL_CLEAR` if the code looks solid
259
+ 3. Before the signal token, write this line it appears directly in the terminal:
260
+ `ETCH_SUMMARY: <one sentence, max 80 chars, e.g. "2 issues unguarded empty list in sorter.py:14, exception swallowed in loader.py:67">`
261
+ `ETCH_SUMMARY: no issues found code looks solid`
262
+ 4. End with EXACTLY one of these on its own line:
263
+ `ETCH_ISSUES_FOUND`
264
+ `ETCH_ALL_CLEAR`
256
265
 
257
266
  ## Scope
258
267
 
@@ -292,16 +301,15 @@ You are a test engineer. The fixer has just made changes. Your job is to write t
292
301
 
293
302
  1. You MAY edit test files — that is your job
294
303
  2. Do NOT touch production code — only tests
295
- 3. After running, report clearly:
296
- - If ALL tests pass:
297
- - `ETCH_SUMMARY: <e.g. "wrote 4 tests, all 51 passed">`
298
- - `ETCH_ALL_CLEAR`
299
- - If ANY test fails due to a bug in the production code:
300
- - `ETCH_SUMMARY: <what failed and why>`
301
- - Include the relevant error output
302
- - `ETCH_ISSUES_FOUND`
303
- - If tests fail because the tests themselves are wrong (flawed test logic):
304
- - Fix the test and re-run before reporting
304
+ 3. If tests fail because of flawed test logic, fix the test and re-run before reporting
305
+ 4. When done, write this line — it appears directly in the terminal:
306
+ `ETCH_SUMMARY: <one sentence, max 80 chars>`
307
+ Examples:
308
+ `ETCH_SUMMARY: wrote 4 tests, all 51 passed`
309
+ `ETCH_SUMMARY: 2 tests failed TypeError in test_auth.py:38, production bug in token.py:12`
310
+ 5. End with EXACTLY one of these on its own line:
311
+ `ETCH_ALL_CLEAR` — if all tests pass
312
+ `ETCH_ISSUES_FOUND` if tests reveal a bug in production code
305
313
  """
306
314
 
307
315
 
@@ -35,14 +35,22 @@ def parse(output: str) -> str:
35
35
  def extract_commit_message(output: str, fallback: str) -> str:
36
36
  """Extract a short commit message from fixer output.
37
37
 
38
- Looks for the first substantive line that describes what was changed.
39
- Falls back to `fallback` if nothing useful is found.
38
+ Tries ETCH_SUMMARY first (the explicit summary line), then falls back to
39
+ scanning for the first substantive line that describes what was changed.
40
40
  Returns a string starting with 'fix(edge): '.
41
41
  """
42
42
  if not isinstance(output, str) or not output.strip():
43
43
  return fallback
44
44
 
45
- _SKIP_STARTS = ("i ", "i've ", "i have ", "here ", "the following", "done", "no ")
45
+ # Prefer the explicit ETCH_SUMMARY line
46
+ summary = extract_summary(output)
47
+ if summary:
48
+ msg = summary[:72].rstrip(".,;:")
49
+ if not msg.lower().startswith("fix"):
50
+ msg = f"fix(edge): {msg[0].lower()}{msg[1:]}"
51
+ return msg
52
+
53
+ _SKIP_STARTS = ("i ", "i've ", "i have ", "here ", "here's", "the following", "done", "no ", "summary", "below")
46
54
  _SKIP_WORDS = {"ok", "done", "nothing", "complete", "finished"}
47
55
 
48
56
  for line in output.splitlines():
@@ -19,12 +19,14 @@ Be adversarial — think like someone actively trying to make this code fail.
19
19
 
20
20
  1. DO NOT edit any files — read only
21
21
  2. Report your findings clearly, one per line
22
- 3. Before the signal token, write one line starting with `ETCH_SUMMARY:` summarising what you found:
23
- - `ETCH_SUMMARY: 2 issues — unguarded empty list in sorter.py:14, exception swallowed in loader.py:67`
24
- - `ETCH_SUMMARY: no issues found — code looks solid`
25
- 4. End your output with EXACTLY one of these tokens on its own line:
26
- - `ETCH_ISSUES_FOUND` if you found anything worth fixing
27
- - `ETCH_ALL_CLEAR` if the code looks solid
22
+ 3. Before the signal token, write this line it appears directly in the terminal:
23
+ `ETCH_SUMMARY: <one sentence, max 80 chars>`
24
+ Examples:
25
+ `ETCH_SUMMARY: 2 issues unguarded empty list in sorter.py:14, exception swallowed in loader.py:67`
26
+ `ETCH_SUMMARY: no issues found code looks solid`
27
+ 4. End with EXACTLY one of these on its own line:
28
+ `ETCH_ISSUES_FOUND`
29
+ `ETCH_ALL_CLEAR`
28
30
 
29
31
  ## Scope
30
32
 
@@ -15,19 +15,18 @@ Scan the codebase for:
15
15
  ## Rules
16
16
 
17
17
  1. Fix only what you find — do not refactor, rename, or reorganize
18
- 2. One logical fix per commit (the harness will commit for you)
19
- 3. Do not add comments explaining what you fixed
20
- 4. If you find nothing, make no changes
18
+ 2. Do not add comments explaining what you fixed
19
+ 3. If you find nothing, make no changes
21
20
 
22
21
  ## Scope
23
22
 
24
23
  Focus on: [edit this to narrow your scope, e.g. "src/auth/", "the payment module"]
25
24
 
26
- ## Output format
25
+ ## Terminal output (required)
27
26
 
28
- After making your changes, write one line at the end of your output:
29
- ETCH_SUMMARY: <concise summary, e.g. "fixed 3 issues — added null guards in auth.py, guarded empty input in parser.py">
30
- ETCH_SUMMARY: no changes — nothing to fix
27
+ After making changes (or deciding there is nothing to fix), write this line it appears directly in the terminal and is used as the commit message:
28
+ `ETCH_SUMMARY: <one sentence, max 80 chars>`
31
29
 
32
- The harness commits automatically. Each commit will be:
33
- fix(edge): <short description of what was fixed>
30
+ Examples:
31
+ `ETCH_SUMMARY: fixed 3 issues null guard in auth.py, bounds check in parser.py, timeout in agent.py`
32
+ `ETCH_SUMMARY: nothing to fix — all reported issues were already handled`
@@ -23,12 +23,14 @@ For each issue, include the file path, line number (if known), and a one-line de
23
23
  5. List each confirmed issue on its own line, e.g.:
24
24
  - src/auth.py:42 — crashes with empty token string (no guard)
25
25
  - src/api.js:108 — unhandled promise rejection will silently fail
26
- 6. Before the signal token, write one line starting with `ETCH_SUMMARY:` summarising what you found in plain English:
27
- - `ETCH_SUMMARY: found 3 issues — null dereference in auth.py:42, off-by-one in parser.py:88, unhandled OSError in git.py:31`
28
- - `ETCH_SUMMARY: no confirmed bugs found`
29
- 7. End your output with EXACTLY one of these tokens on its own line:
30
- - `ETCH_ISSUES_FOUND` if you found confirmed bugs worth fixing
31
- - `ETCH_ALL_CLEAR` if the code looks solid or you found nothing certain
26
+ 6. Before the signal token, write this line it appears directly in the terminal:
27
+ `ETCH_SUMMARY: <one sentence, max 80 chars>`
28
+ Examples:
29
+ `ETCH_SUMMARY: 3 bugs found null deref in auth.py:42, off-by-one in parser.py:88, missing guard in git.py:31`
30
+ `ETCH_SUMMARY: no confirmed bugs found`
31
+ 7. End with EXACTLY one of these on its own line:
32
+ `ETCH_ISSUES_FOUND`
33
+ `ETCH_ALL_CLEAR`
32
34
 
33
35
  ## Scope
34
36
 
@@ -1 +0,0 @@
1
- __version__ = "0.4.5"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes