1 line
4.6 KiB
JSON
1 line
4.6 KiB
JSON
{"body":"Executing unit: u10\n\n[Claude #N] Stage 3 code-edit Round #N -- unit u10\n\n### unit_executed\nu10 -- pytest coverage for `plan_zone_ratio_retry` multi-donor aggregation (u1 surface). Three deterministic cases per Stage 2 contract.\n\n### files_changed\n- tests/phase_z2/test_phase_z2_retry_multi_donor.py (new file, untracked -- single file scope)\n\n### diff_summary\n- New test module exercises three Stage 2 cases against `src.phase_z2_retry.plan_zone_ratio_retry`:\n 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-\u003e224, bottom 400-\u003e376).\n 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-\u003e370, middle 250-\u003e200 floor, bottom 240-\u003e220).\n 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\", \"\u003c\") -- 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).\n- Helper functions kept module-local (`_zone`, `_overflow_clean`, `_classification`) -- no shared fixture module added (single-test file scope, Stage 2 scope_lock).\n- No source edits -- test-only unit; observes existing u1 contract.\n\n### verification\n- `python -m pytest -q tests/phase_z2/test_phase_z2_retry_multi_donor.py` -\u003e **3 passed** in 0.02s.\n- Math check on case 2: `math.ceil(66.0) + 4 = 70`. `donor_candidates` sorted by slack desc = [middle(50), bottom(40)]. `aggregate=90 \u003e= 70` -\u003e 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.\n- Math check on case 3: `aggregate=25 \u003c 70` -\u003e infeasible branch at `src/phase_z2_retry.py:167-185`. `donor_candidates[0].position=\u0027bottom\u0027` (slack 15 \u003e 10), so `donor_zone_position=\u0027bottom\u0027`. `failure_reason` substring includes `primary donor \u0027bottom\u0027 slack 15px (aggregate 25px ... ) \u003c target_added_px 70px` -- all three substring checks pass.\n- 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.\n- Pre-existing `tests/phase_z2/test_retry_gate.py` 4-test suite unaffected -- separate gate-surface coverage; u10 covers post-gate plan logic.\n\n### remaining_units\n- u11 -- tests for `plan_cross_zone_redistribute` (multi-role feasible / single-role infeasible)\n- u12 -- tests for `plan_glue_compression` (scoped CSS lock + envelope insufficient)\n- u13 -- tests for `plan_font_step_compression` (feasible / 8px floor / missing text_metrics)\n- u14 -- tests for failure_router cascade routing + status registration\n- u15 -- end-to-end `_attempt_salvage_chain` (3 fixture cases including all-fail revert)\n\n### follow_up_issue_candidates\nNone -- u10 surface stays within Stage 2 scope_lock. No new axis observed.\n\n=== EVIDENCE ===\n- `git diff --stat src/phase_z2_retry.py src/phase_z2_failure_router.py src/phase_z2_router.py src/phase_z2_pipeline.py` -\u003e unchanged from u9 baseline (no source edit in u10).\n- `git status --short tests/phase_z2/` -\u003e only `?? tests/phase_z2/test_phase_z2_retry_multi_donor.py` (single new file).\n- `python -m pytest -q tests/phase_z2/test_phase_z2_retry_multi_donor.py` -\u003e 3 passed.\n- `wc -l tests/phase_z2/test_phase_z2_retry_multi_donor.py` -\u003e 147 lines.\n- Source contract anchors: `src/phase_z2_retry.py:43-215` (multi-donor plan), `src/phase_z2_failure_router.py:121-136` (classifier substring lock)."} |