untracked files on main: dceb101 feat(#63): IMP-34 R1 donor capacity measured bound (u1+u2)

This commit is contained in:
2026-05-21 22:07:41 +09:00
commit 8f085a28d3
3220 changed files with 985495 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
[Claude #N] Stage 3 code-edit Round #N -- unit u13
### unit_executed
u13 -- pytest coverage for `plan_font_step_compression` / `apply_font_step_compression_css` (u6 surface). Three deterministic cases per Stage 2 contract: feasible (15.2→13 closes excess), infeasible (FONT_SIZE_STEPS exhausted at 8px floor), and defensive `text_metrics missing` guard.
### files_changed
- tests/phase_z2/test_phase_z2_font_step_compression.py (new file, untracked -- single file scope)
### diff_summary
- New test module exercises three Stage 2 cases against `src.phase_z2_retry.plan_font_step_compression` / `apply_font_step_compression_css`:
1. `test_feasible_15_2_to_13_closes_excess` -- `current_font_px=15.2, excess_after_glue_px=20.0, available_lines=10, chars_per_line=40, zone_position="bottom_l"`. Math at `src/space_allocator.py:997-1012` (`find_fitting_font_size`): 14.0 candidate saves `(15.2*1.6 - 14.0*1.6)*10 = 19.2` < 20.0 (skip); 13.0 candidate saves `(24.32 - 20.8)*10 = 35.2` >= 20.0 → return 13.0. Asserts plan fields (`action="font_step_compression"`, `zone_position`, `current_font_px=15.2`, `excess_after_glue_px=20.0`, `available_lines=10`, `chars_per_line=40`, `font_floor_px=8.0`), `feasible=True`, `target_font_px=13.0`, and `"failure_reason" not in plan`. On `apply_font_step_compression_css(plan)`: asserts `[data-zone-position="bottom_l"]` selector + `font-size: 13.0px` value + scope-lock (none of `":root"`, `"body "`, `".slide"`, `".zone"` substrings appear -- per `feedback_phase_z_spacing_direction`).
2. `test_infeasible_font_floor_exhausted` -- `current_font_px=15.2, excess_after_glue_px=200.0, available_lines=10, chars_per_line=40, zone_position="top"`. All `FONT_SIZE_STEPS = [15.2, 14.0, 13.0, 12.0, 11.0, 10.0, 9.0, 8.0]` candidates fall short; at 8.0px floor `(24.32 - 12.8)*10 = 115.2 < 200`. `find_fitting_font_size` returns `None` → hits `src/phase_z2_retry.py:391-396` branch. Asserts `feasible=False`, `target_font_px is None`, `font_floor_px == 8.0`, and four substrings in `failure_reason`: `"font_step floor"`, `"8.0px"`, `"200.0px"`, `"FONT_SIZE_STEPS exhausted"` (matches `SALVAGE_FAILURE_TYPE_BY_ACTION` action-based classifier surface in `src/phase_z2_failure_router.py:85-89`). Asserts `apply_font_step_compression_css(plan) == ""` (no CSS on infeasible -- prevents render-time mutation on revert path).
3. `test_text_metrics_missing_defensive_infeasible` -- `available_lines=0, chars_per_line=40` exercises the defensive guard at `src/phase_z2_retry.py:380-382` BEFORE `find_fitting_font_size` is invoked. Asserts `feasible=False`, `target_font_px is None`, and two substrings in `failure_reason`: `"text_metrics missing"` + `"available_lines/chars_per_line required"`. Asserts `apply_font_step_compression_css(plan) == ""`.
- Helper-free design (function-arg API takes simple keyword primitives) -- module is 77 total lines (`wc -l`) including docstring + 3 tests. No shared fixtures introduced (single-test-file scope per Stage 2 scope_lock).
- No source edits -- test-only unit; observes existing u6 contract.
### verification
- `python -m pytest -q tests/phase_z2/test_phase_z2_font_step_compression.py`**3 passed in 0.02s**.
- Math cross-checked against `src/space_allocator.py:997-1012` (`find_fitting_font_size`): case 1 picks 13.0 (35.2px savings ≥ 20px excess), case 2 exhausts all steps including 8.0px (115.2px max savings < 200px excess).
- Scope-lock check on emitted CSS: `apply_font_step_compression_css` at `src/phase_z2_retry.py:400-409` wraps `font-size: <target_font_px>px;` in `[data-zone-position="<zone_position>"] { ... }` only. The test asserts each forbidden global selector substring (`:root`, `body `, `.slide`, `.zone`) is absent.
- Action-name & status surface: `src/phase_z2_failure_router.py:85-89` maps `"font_step_compression"``"font_step_insufficient"`, and `:142-149` registers `"font_step_compression": "IMPLEMENTED"` (u6 wired). The test uses `action="font_step_compression"` verbatim so classifier wiring (u7) is honored.
- No regressions in adjacent u-tests: prior Stage 3 cascade tests untouched.
- Guardrails honored: deterministic (no AI), zone-scoped CSS only (no global mutation), single source surface (u6), Stage 2 estimate (50 lines) respected (77 with docstring + assertions).
### remaining_units
[u14, u15]
### follow_up_issue_candidates
None — u13 stays within Stage 2 scope_lock. Observation: `font_step_compression` emits only a `font-size` override; if zones with table/text-grid frames need synchronized line-height adjustment to match the line-height assumption (font_size * 1.6), that would land as a new axis on IMP-12 or a fresh issue. Not a u13 blocker — the math in `find_fitting_font_size` already accounts for the constant 1.6 multiplier on both sides of the difference, so the CSS-emitted single property is correct for the current model.