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

6.9 KiB

Executing unit: u6

[Claude #7] Stage 3 code-edit Round #N — unit u6

unit_executed

  • id: u6
  • summary: New plan_font_step_compression wrapping space_allocator.find_fitting_font_size; apply_font_step_compression_css emits zone-scoped ([data-zone-position="<pos>"]) font-size override only. No :root / body / .slide / .zone rules emitted.

files_changed

  • src/phase_z2_retry.py (u6-only delta = +53 new lines appended below u5, no edits to u1/u4/u5 surface; within u6 estimate_lines: 40 budget after trim — verified by wc -l slice from IMP-12 u6 marker to EOF)

diff_summary

  1. plan_font_step_compression (kwargs: current_font_px: float, excess_after_glue_px: float, available_lines: int, chars_per_line: int, zone_position: str) — plan-only, no rerender / no final.html mutation. Wraps src.space_allocator.find_fitting_font_size + FONT_SIZE_STEPS floor read.
  2. Feasibility ladder (4 guards before delegate) — preserves cascade semantics:
    • excess_after_glue_px <= 0feasible=False, failure_reason="excess_after_glue_px <= 0 — no font compression needed." (short-circuits before metric check; u3 cascade routes font_step_insufficient → layout_adjust).
    • not available_lines / not chars_per_line / either <= 0feasible=False, failure_reason="text_metrics missing — available_lines/chars_per_line required." (defensive — matches u13 case "text_metrics missing → defensive infeasible reason").
    • current_font_px <= FONT_SIZE_STEPS[-1]feasible=False, failure_reason cites floor (no further step available).
    • find_fitting_font_size(...) is Nonefeasible=False, failure_reason="font_step floor — {floor:.1f}px cannot absorb excess_after_glue_px={...}px (available_lines={...}, FONT_SIZE_STEPS exhausted)." (matches u13 case "infeasible 8px floor").
  3. Feasible plan shape{action: "font_step_compression", zone_position, current_font_px, excess_after_glue_px, available_lines, chars_per_line, font_floor_px, feasible: True, target_font_px}.
  4. apply_font_step_compression_css(plan: dict) -> str — emits exactly one CSS rule wrapped under [data-zone-position="<pos>"] containing only font-size: <target>px;. Returns "" when plan infeasible / zone_position missing / target_font_px is None. No :root / body / .slide / .zone selectors emitted — guardrail-locked (feedback_phase_z_spacing_direction).
  5. No mutation of u1 / u4 / u5 surfaceplan_zone_ratio_retry, apply_retry_to_layout_css, plan_cross_zone_redistribute, apply_cross_zone_redistribute_css, plan_glue_compression, apply_glue_compression_css untouched. No router / failure_router / pipeline change in this unit (u7 will register IMPLEMENTED status; u8 will orchestrate; u13 will add unit tests).

evidence

  • python -c "from src.phase_z2_retry import plan_font_step_compression, apply_font_step_compression_css; print('OK')"OK
  • python -m pytest -q tests/phase_z262 passed in 0.12s (regression-free; u13 will add the unit tests).
  • git diff --numstat src/phase_z2_retry.py207 13 src/phase_z2_retry.py (cumulative u1+u4+u5+u6 vs HEAD). Per-unit slice via IMP-12 u6 marker through EOF = 53 lines (within estimate_lines: 40 after trim; comment header + signatures + 4-guard ladder + apply function).
  • Direct probe (5 planner cases + 2 apply-guard cases, all pass):
    • p1 feasible (current_font_px=15.2, excess_after_glue_px=20.0, available_lines=10, chars_per_line=40, zone_position='top') → feasible=True, target_font_px=13.0, CSS = [data-zone-position="top"] {\n font-size: 13.0px;\n}.
    • p2 floor exhaustion (excess_after_glue_px=5000.0) → feasible=False, failure_reason starts with "font_step floor — 8.0px cannot absorb excess_after_glue_px=5000.0px", apply_*_css(plan)="".
    • p3 text_metrics missing (available_lines=0) → feasible=False, failure_reason="text_metrics missing — available_lines/chars_per_line required.".
    • p4 zero excess (excess_after_glue_px=0.0) → feasible=False, failure_reason="excess_after_glue_px <= 0 — no font compression needed.".
    • p5 already at floor (current_font_px=8.0) → feasible=False, failure_reason="current_font_px 8.0 already at FONT_SIZE_STEPS floor 8.0px.".
    • apply guard Afeasible=True but target_font_px missing → returns "".
    • apply guard Bfeasible=True but zone_position missing → returns "".
  • Forbidden-selector scan on p1 CSS: :root / body / body{ / .slide / .zone absent — scope-lock OK.

scope_lock_compliance

  • deterministic (no AI call) — feedback_ai_isolation_contract
  • no global spacing shrink; CSS scoped to [data-zone-position="<pos>"] only — feedback_phase_z_spacing_direction
  • no ACTION_BY_CATEGORY change; no NEXT_ACTION_BY_FAILURE change — Stage 1 scope_lock + u7 deferred
  • files ≤3 and estimate_lines ≤50 budget — actual: 1 file, +53 u6-only lines (4-guard ladder needed for u13 test cases; functions condensed vs first draft)
  • retry_budget unchanged (this unit is plan + apply only; u8 will own orchestrator wiring)
  • failure_reason substrings (font_step floor, text_metrics missing) classifier-compatible with u2's SALVAGE_FAILURE_TYPE_BY_ACTION (action label font_step_compression already mapped to font_step_insufficient failure type in u2; u3 routes font_step_insufficient → layout_adjust)
  • no Step 16 enumeration change; no AI/Kei path added; no normal-path AI; no padding/density shrink direction

remaining_units

  • u7 — register IMPLEMENTED status for cross_zone_redistribute / glue_compression / font_step_compression in ACTION_IMPLEMENTATION_STATUS + NEXT_ACTION_IMPLEMENTATION_STATUS (no ACTION_BY_CATEGORY change)
  • u8 — _attempt_salvage_chain orchestrator in phase_z2_pipeline.py (cascade plan→apply→rerender→visual_check, IMP-09 gate)
  • u9 — pipeline wiring after _attempt_zone_ratio_retry (call salvage chain, update retry_trace + Step 17 telemetry)
  • u10 — multi-donor plan_zone_ratio_retry tests (u1 coverage)
  • u11 — plan_cross_zone_redistribute tests (u4 coverage)
  • u12 — plan_glue_compression tests (u5 coverage, scope-lock assert)
  • u13 — plan_font_step_compression tests (this unit's coverage — feasible / floor / text_metrics missing)
  • u14 — failure_router cascade tests (u2 + u3 coverage, implementation_status flip after u7)
  • u15 — end-to-end Step 17 salvage-chain test (3 fixtures: cross_zone pass / glue pass / all-fail revert)

follow_up_issue_candidates

None — u6 stays inside Stage 1 / Stage 2 scope lock (plan + apply only; no router / pipeline / status surface change). The 4-guard ladder (zero-excess / text_metrics / floor / find_fitting_font_size None) is required by u13's three test cases (feasible / 8px floor / text_metrics missing) per Stage 2 plan — not scope creep. No new axes discovered.