Skip to content

Fail-fast on compile errors in refactor convergence loop#945

Merged
chubes4 merged 2 commits intomainfrom
fail-fast-parse-errors
Mar 23, 2026
Merged

Fail-fast on compile errors in refactor convergence loop#945
chubes4 merged 2 commits intomainfrom
fail-fast-parse-errors

Conversation

@chubes4
Copy link
Member

@chubes4 chubes4 commented Mar 23, 2026

Summary

  • Convergence loop fail-fast: Adds a compile check (validate_only) after each convergence iteration. If code no longer compiles (e.g. failed to resolve mod, parse errors), breaks immediately with stopped_compile_failure instead of retrying
  • Stage loop fail-fast: Adds a compile check between planner stages (audit → lint → test). If a stage breaks sandbox compilation, skips remaining stages instead of running lint/test on broken code

Problem

Two layers of wasted CI time on unrecoverable errors:

1. Convergence loop (verify.rs)

The loop retries up to 3 times when fixes don't converge. Each retry is a cold compile in the sandbox. When a fix introduces a parse/resolve error, no amount of retrying will fix it:

apply fixes → re-audit → retry → re-audit → retry → re-audit → fail at final gate

2. Stage loop (planner.rs)

When --from all runs audit → lint → test, if audit fixes break compilation:

  • Lint runs on broken code → bogus findings
  • Test runs on broken code → bogus failures
  • Both stages waste time and produce noise

Fix

Convergence loop

After run_fix_iteration() applies fixes, run validate_only() before the structural re-audit. If compilation fails, log the error and break with stopped_compile_failure.

Before:  apply → re-audit → retry → re-audit → retry → fail
After:   apply → compile check → STOP

Stage loop

After each stage that modifies files, run validate_only() on the sandbox. If broken, log + skip remaining stages.

Before:  audit (breaks) → lint (bogus) → test (bogus) → validate_write → rollback
After:   audit (breaks) → compile check → STOP → validate_write → rollback

Both checks use the existing validate_only() function — no new infrastructure needed.

chubes4 added 2 commits March 23, 2026 04:23
Add a compile check (validate_only) after each convergence iteration
applies fixes. If the code no longer compiles — e.g. 'failed to resolve
mod' parse errors — further iterations cannot recover, so bail
immediately with 'stopped_compile_failure' status.

Previously the loop would retry up to 3 times, each with a cold compile
in the sandbox, burning 20+ minutes of CI time on errors that are
structurally unrecoverable. Now it stops after the first iteration that
breaks compilation.
When the stage loop runs audit → lint → test, if the audit stage's
fixes break compilation in the sandbox, subsequent lint and test stages
run on broken code — producing bogus findings and wasting CI time.

After each stage that modifies files, run validate_only() on the sandbox.
If compilation fails, log the error, record the stage's results, and skip
all remaining stages. The final validate_write() in the planner still
catches the failure on the real tree and rolls back.
@homeboy-ci
Copy link
Contributor

homeboy-ci bot commented Mar 23, 2026

Homeboy Results — homeboy

Audit

Failure Digest

Audit Failure Digest

  • Alignment score: 0.921
  • Severity counts: info: 10, unknown: 3, warning: 38
  • Outliers in current run: 3
  • Parsed outlier entries: 3
  • Drift increased: yes
  • New findings since baseline: 3
    1. intra-method-duplication — Duplicated block in run_audit_refactor — 6 identical lines at line 151 and line 181 (intra-method-duplication::src/core/refactor/plan/verify.rs::IntraMethodDuplicate)
    2. intra-method-duplication — Duplicated block in run_fix_iteration — 18 identical lines at line 470 and line 529 (intra-method-duplication::src/core/refactor/plan/verify.rs::IntraMethodDuplicate)
    3. field_patterns — Repeated field group [category, glob, exclude_sniffs, file, sniffs, errors_only] appears in 3 structs: src/commands/lint.rs::LintArgs, src/core/extension/lint/run.rs::LintRunWorkflowArgs, src/core/refactor/plan/planner.rs::LintSourceOptions (field_patterns::src/core/refactor/plan/planner.rs::RepeatedFieldPattern)
  • Top actionable findings:
    1. src/core/refactor/auto/apply.rs — god_file — File has 1109 lines (threshold: 1000)
    2. src/core/refactor/auto/apply.rs — high_item_count — File has 16 top-level items (threshold: 15)
    3. src/core/refactor/plan/planner.rs — god_file — File has 1212 lines (threshold: 1000)
    4. src/core/refactor/plan/planner.rs — high_item_count — File has 28 top-level items (threshold: 15)
    5. src/core/refactor/auto/apply.rs — intra_method_duplicate — Duplicated block in apply_decompose_plans — 7 identical lines at line 880 and line 954
All parsed audit findings (51)
1. **src/core/refactor/auto/apply.rs** — god_file — File has 1109 lines (threshold: 1000)
2. **src/core/refactor/auto/apply.rs** — high_item_count — File has 16 top-level items (threshold: 15)
3. **src/core/refactor/plan/planner.rs** — god_file — File has 1212 lines (threshold: 1000)
4. **src/core/refactor/plan/planner.rs** — high_item_count — File has 28 top-level items (threshold: 15)
5. **src/core/refactor/auto/apply.rs** — intra_method_duplicate — Duplicated block in `apply_decompose_plans` — 7 identical lines at line 880 and line 954
6. **src/core/refactor/auto/apply.rs** — intra_method_duplicate — Duplicated block in `apply_file_moves` — 5 identical lines at line 988 and line 1002
7. **src/core/refactor/auto/apply.rs** — intra_method_duplicate — Duplicated block in `apply_fixes_chunked` — 6 identical lines at line 684 and line 761
8. **src/core/refactor/auto/apply.rs** — intra_method_duplicate — Duplicated block in `apply_insertions_to_content` — 5 identical lines at line 82 and line 96
9. **src/core/refactor/auto/apply.rs** — intra_method_duplicate — Duplicated block in `apply_new_files_chunked` — 7 identical lines at line 789 and line 804
10. **src/core/refactor/plan/verify.rs** — intra_method_duplicate — Duplicated block in `run_audit_refactor` — 6 identical lines at line 151 and line 181
11. **src/core/refactor/plan/verify.rs** — intra_method_duplicate — Duplicated block in `run_fix_iteration` — 18 identical lines at line 470 and line 529
12. **src/core/refactor/auto/apply.rs** — unreferenced_export — Public function 'apply_new_files' is not referenced by any other file
13. **src/core/refactor/plan/planner.rs** — unreferenced_export — Public function 'analyze_stage_overlaps' is not referenced by any other file
14. **src/core/refactor/plan/planner.rs** — unreferenced_export — Public function 'normalize_sources' is not referenced by any other file
15. **src/core/refactor/plan/planner.rs** — unreferenced_export — Public function 'run_lint_refactor' is not referenced by any other file
16. **src/core/refactor/plan/planner.rs** — unreferenced_export — Public function 'run_test_refactor' is not referenced by any other file
17. **src/core/refactor/plan/planner.rs** — unreferenced_export — Public function 'summarize_plan_totals' is not referenced by any other file
18. **src/core/refactor/plan/planner.rs** — unreferenced_export — Public function 'test_refactor_request' is not referenced by any other file
19. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_decompose_plans' has no corresponding test (expected 'test_apply_decompose_plans')
20. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_file_moves' has no corresponding test (expected 'test_apply_file_moves')
21. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_fixes' has no corresponding test (expected 'test_apply_fixes')
22. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_fixes_chunked' has no corresponding test (expected 'test_apply_fixes_chunked')
23. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_insertions_to_content' has no corresponding test (expected 'test_apply_insertions_to_content')
24. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_new_files' has no corresponding test (expected 'test_apply_new_files')
25. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'apply_new_files_chunked' has no corresponding test (expected 'test_apply_new_files_chunked')
26. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'auto_apply_subset' has no corresponding test (expected 'test_auto_apply_subset')
27. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'insert_before_closing_brace' has no corresponding test (expected 'test_insert_before_closing_brace')
28. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'insert_import' has no corresponding test (expected 'test_insert_import')
29. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'insert_into_constructor' has no corresponding test (expected 'test_insert_into_constructor')
30. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'insert_namespace_declaration' has no corresponding test (expected 'test_insert_namespace_declaration')
31. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'insert_trait_uses' has no corresponding test (expected 'test_insert_trait_uses')
32. **src/core/refactor/auto/apply.rs** — missing_test_method — Method 'insert_type_conformance' has no corresponding test (expected 'test_insert_type_conformance')
33. **src/core/refactor/auto/apply.rs** — orphaned_test — Test method 'test_remove_does_not_touch_unrelated_pub_use' references 'remove_does_not_touch_unrelated_pub_use' which no longer exists in the source
34. **src/core/refactor/auto/apply.rs** — orphaned_test — Test method 'test_remove_from_multiline_pub_use' references 'remove_from_multiline_pub_use' which no longer exists in the source
35. **src/core/refactor/auto/apply.rs** — orphaned_test — Test method 'test_remove_from_single_line_pub_use' references 'remove_from_single_line_pub_use' which no longer exists in the source
36. **src/core/refactor/auto/apply.rs** — orphaned_test — Test method 'test_remove_last_item_deletes_entire_line' references 'remove_last_item_deletes_entire_line' which no longer exists in the source
37. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'analyze_stage_overlaps' has no corresponding test (expected 'test_analyze_stage_overlaps')
38. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'build_refactor_plan' has no corresponding test (expected 'test_build_refactor_plan')
39. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'lint_refactor_request' has no corresponding test (expected 'test_lint_refactor_request')
40. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'normalize_sources' has no corresponding test (expected 'test_normalize_sources')
41. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'run_lint_refactor' has no corresponding test (expected 'test_run_lint_refactor')
42. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'run_test_refactor' has no corresponding test (expected 'test_run_test_refactor')
43. **src/core/refactor/plan/planner.rs** — missing_test_method — Method 'summarize_plan_totals' has no corresponding test (expected 'test_summarize_plan_totals')
44. **src/core/refactor/plan/planner.rs** — orphaned_test — Test method 'test_component' references 'component' which no longer exists in the source
45. **src/core/refactor/plan/planner.rs** — orphaned_test — Test method 'test_refactor_request' references 'refactor_request' which no longer exists in the source
46. **src/core/refactor/plan/planner.rs** — orphaned_test — Test method 'test_tmp_dir' references 'tmp_dir' which no longer exists in the source
47. **src/core/refactor/plan/verify.rs** — missing_test_file — No test file found (expected 'tests/core/refactor/plan/verify_test.rs') and no inline tests
48. **src/core/refactor/plan/planner.rs** — repeated_field_pattern — Repeated field group [category, glob, exclude_sniffs, file, sniffs, errors_only] appears in 3 structs: src/commands/lint.rs::LintArgs, src/core/extension/lint/run.rs::LintRunWorkflowArgs, src/core/refactor/plan/planner.rs::LintSourceOptions
49. **src/commands/docs.rs** — outlier — (outlier)
50. **tests/commands/deploy_test.rs** — outlier — (outlier)
51. **src/core/engine/undo/snapshot.rs** — outlier — (outlier)
- Full audit log: https://github.com/Extra-Chill/homeboy/actions/runs/23421458651

Autofixability classification

  • Overall: auto_fixable
  • Autofix enabled: yes
  • Autofix attempted this run: no
  • Auto-fixable failed commands:
    • audit
  • Failed commands with available automated fixes:
    • audit

Machine-readable artifacts

  • homeboy-lint-summary.json
  • homeboy-test-failures.json
  • homeboy-audit-summary.json
  • homeboy-autofixability.json

⚡ Scope: changed files only

audit (changed files only)

Auto-refactor

ℹ️ Autofix enabled, but no fixable file changes were produced

Failure Digest

Autofixability classification

  • Overall: human_needed
  • Autofix enabled: yes
  • Autofix attempted this run: no
  • Human-needed failed commands:
    • refactor --from all

Machine-readable artifacts

  • homeboy-lint-summary.json
  • homeboy-test-failures.json
  • homeboy-audit-summary.json
  • homeboy-autofixability.json

⚡ Scope: changed files only

refactor --from all

Tooling versions
  • Homeboy CLI: homeboy 0.85.3+7f436db
  • Extension: rust from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: unknown
  • Action: Extra-Chill/homeboy-action@v2

Homeboy Action v1

@chubes4 chubes4 merged commit 982cae4 into main Mar 23, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant