Files
C.E.L_Slide_test2/.orchestrator/tmp/u10_comment.md
T

4.4 KiB

Executing unit: u10

[Claude #N] Stage 3 code-edit Round #N -- unit u10

unit_executed

u10 -- pytest coverage for plan_zone_ratio_retry multi-donor aggregation (u1 surface). Three deterministic cases per Stage 2 contract.

files_changed

  • tests/phase_z2/test_phase_z2_retry_multi_donor.py (new file, untracked -- single file scope)

diff_summary

  • New test module exercises three Stage 2 cases against src.phase_z2_retry.plan_zone_ratio_retry:
    1. test_single_donor_sufficient_regression -- single donor with abundant slack (200px) covers target_added_px=24 (excess_y 20 + DEFAULT_SAFETY_MARGIN_PX 4). Asserts backward-compat fields preserved: donor_zone_position, donor_reduced_px, plus new fields donors_used == [{position: bottom, reduced_px: 24, slack_before: 200, slack_after: 176}], aggregate_slack_used=24, aggregate_slack_available=200. Verifies zones_after math (top 200->224, bottom 400->376).
    2. test_multi_donor_pass_primary_insufficient_secondary_covers -- primary donor (middle, slack 50) insufficient for target_added_px=70, but aggregate (middle 50 + bottom 40 = 90) covers. Asserts greedy slack-desc order: primary takes full 50px, secondary takes remaining 20px. Verifies donor_zone_position=middle (primary lock = legacy router classifier substring stability), donor_reduced_px=50, donors_used ordering + per-donor reduced_px, and zones_after (top 300->370, middle 250->200 floor, bottom 240->220).
    3. test_multi_donor_fail_aggregate_insufficient -- all donors combined (middle 10 + bottom 15 = 25) cannot cover target_added_px=70. Asserts feasible=False, donors_used==[], aggregate_slack_used=0, and primary-donor substring preservation in failure_reason (contains "donor", "slack", "<") -- ensures classify_retry_failure still routes through donor_slack_insufficient (failure_router substring contract at src/phase_z2_failure_router.py:121-136). Asserts zones_after unchanged on fail (revert-friendly).
  • Helper functions kept module-local (_zone, _overflow_clean, _classification) -- no shared fixture module added (single-test file scope, Stage 2 scope_lock).
  • No source edits -- test-only unit; observes existing u1 contract.

verification

  • python -m pytest -q tests/phase_z2/test_phase_z2_retry_multi_donor.py -> 3 passed in 0.02s.
  • Math check on case 2: math.ceil(66.0) + 4 = 70. donor_candidates sorted by slack desc = [middle(50), bottom(40)]. aggregate=90 >= 70 -> feasible branch. Greedy: middle.take=min(50,70)=50, remaining=20; bottom.take=min(40,20)=20, remaining=0. Primary=middle, donor_reduced_px=50 OK.
  • Math check on case 3: aggregate=25 < 70 -> infeasible branch at src/phase_z2_retry.py:167-185. donor_candidates[0].position='bottom' (slack 15 > 10), so donor_zone_position='bottom'. failure_reason substring includes primary donor 'bottom' slack 15px (aggregate 25px ... ) < target_added_px 70px -- all three substring checks pass.
  • File line count: 147 total (12-line module docstring + 3 helper fns + 3 test fns). Asserts-per-test density high to lock both legacy and new fields against future regression. Within Stage 2 single-file scope.
  • Pre-existing tests/phase_z2/test_retry_gate.py 4-test suite unaffected -- separate gate-surface coverage; u10 covers post-gate plan logic.

remaining_units

  • u11 -- tests for plan_cross_zone_redistribute (multi-role feasible / single-role infeasible)
  • u12 -- tests for plan_glue_compression (scoped CSS lock + envelope insufficient)
  • u13 -- tests for plan_font_step_compression (feasible / 8px floor / missing text_metrics)
  • u14 -- tests for failure_router cascade routing + status registration
  • u15 -- end-to-end _attempt_salvage_chain (3 fixture cases including all-fail revert)

follow_up_issue_candidates

None -- u10 surface stays within Stage 2 scope_lock. No new axis observed.

=== EVIDENCE ===

  • git diff --stat src/phase_z2_retry.py src/phase_z2_failure_router.py src/phase_z2_router.py src/phase_z2_pipeline.py -> unchanged from u9 baseline (no source edit in u10).
  • git status --short tests/phase_z2/ -> only ?? tests/phase_z2/test_phase_z2_retry_multi_donor.py (single new file).
  • python -m pytest -q tests/phase_z2/test_phase_z2_retry_multi_donor.py -> 3 passed.
  • wc -l tests/phase_z2/test_phase_z2_retry_multi_donor.py -> 147 lines.
  • Source contract anchors: src/phase_z2_retry.py:43-215 (multi-donor plan), src/phase_z2_failure_router.py:121-136 (classifier substring lock).