
kmlee1andClaude Opus 4.7
56619a0239
feat(IMP-12): Step 16/17 retry refinement — multi-donor + 3-stage salvage cascade
Extend Step 17 deterministic action surface so donor_slack_insufficient no longer
abort-terminates at zone_ratio_retry. AI is NOT invoked on the normal salvage path.
Source changes (4 files, scope-locked):
- src/phase_z2_retry.py — plan_zone_ratio_retry: single-primary-donor → multi-donor
greedy aggregation (donors_used / aggregate_slack_used / aggregate_slack_available);
new plan/apply pairs: cross_zone_redistribute (wraps fit_verifier.redistribute,
data-role scoped CSS), glue_compression (wraps space_allocator.compute_glue_css_overrides,
data-zone-position scoped), font_step_compression (wraps find_fitting_font_size,
zone-scoped, defensive feasible=False on missing text_metrics).
- src/phase_z2_failure_router.py — classifier inspects salvage_steps[-1] via
SALVAGE_FAILURE_TYPE_BY_ACTION; NEXT_ACTION_BY_FAILURE rewired into
donor_slack_insufficient/no_donor_candidates → cross_zone_redistribute → glue
→ font_step → layout_adjust; 3 IMPLEMENTED salvage status rows added.
- src/phase_z2_router.py — ACTION_IMPLEMENTATION_STATUS registers 3 new salvage
actions as IMPLEMENTED; ACTION_BY_CATEGORY untouched (cascade-only labels).
- src/phase_z2_pipeline.py — new _attempt_salvage_chain() iterates router
next_proposed_action with retry_budget=1 per action; honors IMP-09 dynamic_cols
/ fr_default gate; preserves (b)-revert on all-fail; wires Step 17 telemetry
(salvage_steps / salvage_passed).
Tests (6 new pytest modules):
- test_phase_z2_retry_multi_donor.py — single sufficient (regression), 1st
insufficient + 2nd sufficient (multi-donor PASS), aggregate insufficient FAIL.
- test_phase_z2_cross_zone_redistribute.py — multi-role zone feasible,
single-role zone short-circuits infeasible.
- test_phase_z2_glue_compression.py — feasible asserts emitted CSS contains
[data-zone-position=...] selector and NO global :root/body/.slide rule.
- test_phase_z2_font_step_compression.py — 15.2 → 13 closes excess; 8px floor;
missing text_metrics → defensive infeasible reason.
- test_phase_z2_failure_router_cascade.py — donor_slack_insufficient → cross_zone
(impl=IMPLEMENTED); 3 new failure types → expected next actions; rerender_still_fails
preserves frame_reselect terminus.
- test_phase_z2_step17_salvage_chain.py — end-to-end (a) cross_zone PASS promotes
final.html, (b) cross_zone FAIL + glue PASS promotes 2nd candidate, (c) all-3
FAIL preserves original final.html (revert).
Guardrails preserved:
- AI calls: 0 on normal path (feedback_ai_isolation_contract)
- Spacing direction: no shrink-common-margin; resolve via donor/glue/font-step
within frame envelope (feedback_phase_z_spacing_direction)
- All CSS overrides scoped to [data-role=...] or [data-zone-position=...]
- IMP-09 dynamic_cols / fr_default gate honored in cascade
- (b)-revert preserved if all 3 salvage actions fail
Refs: gitea#12 IMP-12
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 02:07:22 +09:00
..
2026-03-24 17:25:47 +09:00
2026-04-15 16:39:50 +09:00
2026-04-17 13:56:03 +09:00
2026-05-08 09:47:58 +09:00
2026-04-15 16:39:50 +09:00
2026-03-31 08:38:06 +09:00
2026-03-31 08:37:05 +09:00
2026-05-08 09:47:58 +09:00
2026-03-24 17:25:47 +09:00
2026-04-06 05:00:52 +09:00
2026-04-06 05:00:52 +09:00
2026-04-06 05:00:52 +09:00
2026-03-31 08:37:05 +09:00
2026-04-07 04:39:02 +09:00
2026-05-08 09:47:58 +09:00
2026-04-06 05:00:52 +09:00
2026-03-31 08:37:05 +09:00
2026-04-15 16:39:50 +09:00
2026-04-15 16:39:50 +09:00
2026-03-25 19:15:28 +09:00
2026-04-07 06:00:18 +09:00
2026-05-04 17:40:21 +09:00
2026-05-15 22:28:59 +09:00
2026-05-13 01:18:25 +09:00
2026-05-18 02:07:22 +09:00
2026-05-07 05:26:57 +09:00
2026-05-13 15:13:46 +09:00
2026-05-18 02:07:22 +09:00
2026-05-07 05:26:57 +09:00
2026-05-18 02:07:22 +09:00
2026-05-18 02:07:22 +09:00
2026-04-15 16:39:50 +09:00
2026-05-08 09:47:58 +09:00
2026-04-15 16:39:50 +09:00
2026-04-15 16:39:50 +09:00
2026-04-15 16:39:50 +09:00
2026-04-15 16:39:50 +09:00
2026-04-15 16:39:50 +09:00
2026-03-26 13:06:21 +09:00
2026-04-15 16:39:50 +09:00
2026-03-25 18:40:20 +09:00
2026-04-15 16:39:50 +09:00