Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 23s
Step 17 salvage dispatcher previously only ran the 3 actions in
_SALVAGE_FAIL_BY_ACTION (cross_zone_redistribute / glue_compression /
font_step_compression). Any next_proposed_action outside that set hit
salvage_terminal_action and dropped through, so visual_check aborted on
layout_adjust / image_fit / frame_internal_fit_candidate cascades.
u1 — router data surface (src/phase_z2_router.py)
- ACTION_BY_CATEGORY: image_aspect_mismatch -> image_fit (new row),
frame_capacity_mismatch -> frame_internal_fit_candidate (was
frame_reselect).
- ACTION_IMPLEMENTATION_STATUS: layout_adjust / image_fit /
frame_internal_fit_candidate flipped MISSING -> IMPLEMENTED with
inline IMP-88 rationale.
u2 — failure_router cascade surface (src/phase_z2_failure_router.py)
- FAILURE_TYPE_DESCRIPTIONS + SALVAGE_FAILURE_TYPE_BY_ACTION extended
with layout_adjust_insufficient / image_fit_insufficient /
frame_internal_fit_insufficient producers.
- NEXT_ACTION_BY_FAILURE + NEXT_ACTION_RATIONALE +
NEXT_ACTION_IMPLEMENTATION_STATUS rows added; cascade chain becomes
font_step_compression -> layout_adjust -> frame_internal_fit_candidate
-> frame_reselect -> details_popup_escalation (#64 terminal).
u3~u5 — planners + apply helpers (src/phase_z2_retry.py)
- plan_layout_adjust / apply_layout_adjust_layout_css with
_layout_swap_priority across 8-preset LAYOUT_PRESETS (preset switch,
no shared-margin shrink per Phase Z spacing direction).
- plan_image_fit / apply_image_fit_css scoped to frame slot using
existing classifier image_event payload (object-fit + max-w/h
derivation).
- plan_frame_internal_fit_candidate / apply_frame_internal_fit_candidate_css
stays inside declared frame contract envelope; emits infeasible path
when envelope is absent.
u6~u7 — pipeline wiring (src/phase_z2_pipeline.py)
- _SALVAGE_FAIL_BY_ACTION extended; _attempt_salvage_chain gains
layout_adjust distinct-render branch + frame_internal_fit_candidate
CSS-overlay branch + loop cap.
- _attempt_step17_image_fit_single_pass added for image_fit entry.
- §11.7.1 / §11.7.2 entry triggers wired; Step 17/18/19 artifact
refresh + note logging closes the salvage_terminal_action fall-through
for the 3 IMP-88 actions.
Tests
- New: test_router_actions_imp88.py (12),
test_failure_router_imp88_cascade.py (12),
test_phase_z2_retry_layout_adjust.py (10),
test_phase_z2_retry_image_fit.py (13),
test_phase_z2_retry_frame_internal_fit.py (13),
test_phase_z2_pipeline_salvage_imp88.py (8),
test_phase_z2_pipeline_step17_entry_imp88.py.
- Regression-aligned: test_phase_z2_failure_router_cascade.py,
test_phase_z2_step17_salvage_chain.py — pre-existing cascade +
salvage-chain assertions updated to the IMPLEMENTED surface.
Out of scope (separate axes / issues)
- details_popup_escalation terminal body (#64).
- frame_reselect MISSING flip (different axis).
- Step 14/16 detection refinement.
- Stage 0 mdx_normalizer integration (locked 2026-05-08).
- AI fallback activation.
Guardrails respected
- Phase Z spacing direction: layout_adjust switches preset; no shared
margin shrink.
- AI isolation contract: planners + dispatcher are deterministic; zero
AI calls in u1~u7.
- No hardcoding: routing + cascade live in router/failure_router data
rows, not inline conditionals.
- IMP-46 (#62) cache carve-out: untouched.
- 1 commit = 1 decision unit: u1~u7 grouped as a single IMP-88 unit.
Stage 4 verification: 7 IMP-88 test files + 2 modified regression files
PASS (Claude #12 + Codex #12 consensus YES). Full-suite sweep deferred to
a separate step.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
224 lines
11 KiB
Python
224 lines
11 KiB
Python
"""IMP-88 (#88) u1 — Step 17 retry chain router rows + status surface.
|
|
|
|
Stage 2 binding contract (unit u1, data-surface only):
|
|
- NEW row `image_aspect_mismatch → image_fit` in ACTION_BY_CATEGORY.
|
|
Closes the unmapped classifier emission gap at
|
|
src/phase_z2_classifier.py:434-447 where image_aspect_mismatch was
|
|
emitted with proposed_action=None (verified Stage 1).
|
|
- REMAP `frame_capacity_mismatch → frame_internal_fit_candidate`
|
|
(previously frame_reselect) per PHASE-Z-PIPELINE-OVERVIEW.md:321.
|
|
frame_reselect remains a valid downstream action via the
|
|
failure_router cascade (rerender_still_fails → frame_reselect).
|
|
- NEW ACTION_RATIONALE rows for image_aspect_mismatch +
|
|
frame_internal_fit_candidate (rationale text for trace surface).
|
|
- NEW ACTION_IMPLEMENTATION_STATUS rows for image_fit +
|
|
frame_internal_fit_candidate. layout_adjust is also registered.
|
|
u1 initial state was MISSING for all three. u7 completion flips the
|
|
rows to IMPLEMENTED once the end-to-end path (u3/u4/u5 planners +
|
|
u6 dispatcher + u7 Step 17 entry) is wired (same convention as
|
|
IMP-12 u7 cascade rows + IMP-35 u3 details_popup_escalation flip).
|
|
|
|
Out of scope for u1 (locked in Stage 2 exit report):
|
|
- failure_router cascade rows for the three actions → u2.
|
|
- planner stubs (plan_layout_adjust / plan_image_fit /
|
|
plan_frame_internal_fit_candidate) → u3 / u4 / u5.
|
|
- salvage dispatcher branches + Step 17 entry triggers → u6 / u7.
|
|
|
|
Post u7 completion (2026-05-24): status assertions in this file reflect
|
|
the IMPLEMENTED end-state. Test names that previously referenced "_missing"
|
|
are renamed to "_implemented_after_u7" so the surface contract is honest
|
|
about the post-u7 state.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from src.phase_z2_router import (
|
|
ACTION_BY_CATEGORY,
|
|
ACTION_IMPLEMENTATION_STATUS,
|
|
ACTION_RATIONALE,
|
|
route_action,
|
|
route_fit_classification,
|
|
)
|
|
|
|
|
|
# ─── ACTION_BY_CATEGORY rows ──────────────────────────────────────
|
|
|
|
|
|
def test_image_aspect_mismatch_maps_to_image_fit():
|
|
"""u1 — NEW row closes the classifier→router gap.
|
|
|
|
Stage 1 verified that route_action('image_aspect_mismatch') returned
|
|
proposed_action=None with implementation_status='unknown'. u1 must
|
|
register the row so the classifier emission is routable.
|
|
"""
|
|
assert ACTION_BY_CATEGORY["image_aspect_mismatch"] == "image_fit"
|
|
|
|
|
|
def test_frame_capacity_mismatch_remaps_to_frame_internal_fit_candidate():
|
|
"""u1 — REMAP per PHASE-Z-PIPELINE-OVERVIEW.md:321.
|
|
|
|
Spec lock: frame_internal_fit_candidate is the per-zone first-pass
|
|
salvage inside the declared frame envelope. frame_reselect (V4 top-k
|
|
alternate frame swap) remains downstream via the failure_router
|
|
cascade (rerender_still_fails → frame_reselect).
|
|
"""
|
|
assert ACTION_BY_CATEGORY["frame_capacity_mismatch"] == "frame_internal_fit_candidate"
|
|
|
|
|
|
def test_existing_action_by_category_rows_unchanged():
|
|
"""u1 — non-IMP-88 rows must NOT be touched (regression guard).
|
|
|
|
Only two edits are allowed in u1: NEW image_aspect_mismatch row and
|
|
REMAP frame_capacity_mismatch row. Everything else is locked.
|
|
"""
|
|
assert ACTION_BY_CATEGORY["minor_overflow"] == "zone_ratio_retry"
|
|
assert ACTION_BY_CATEGORY["moderate_overflow"] == "layout_adjust"
|
|
assert ACTION_BY_CATEGORY["structural_minor_overflow"] == "zone_ratio_retry"
|
|
assert ACTION_BY_CATEGORY["structural_major_overflow"] == "details_popup_escalation"
|
|
assert ACTION_BY_CATEGORY["tabular_overflow"] == "details_popup_escalation"
|
|
assert ACTION_BY_CATEGORY["layout_zone_mismatch"] == "layout_adjust"
|
|
assert ACTION_BY_CATEGORY["hard_visual_fail"] == "abort"
|
|
|
|
|
|
# ─── ACTION_RATIONALE rows ────────────────────────────────────────
|
|
|
|
|
|
def test_image_aspect_mismatch_rationale_present():
|
|
"""u1 — trace surface must explain *why* image_aspect_mismatch routes
|
|
onto image_fit (frame-scoped, no global image CSS shrink — honors
|
|
feedback_phase_z_spacing_direction)."""
|
|
rationale = ACTION_RATIONALE.get("image_aspect_mismatch", "")
|
|
assert rationale.strip(), "image_aspect_mismatch rationale must be non-empty"
|
|
assert "image" in rationale.lower()
|
|
|
|
|
|
def test_frame_capacity_mismatch_rationale_updated_for_internal_fit():
|
|
"""u1 — rationale text must reflect the new internal-fit-first
|
|
routing. The text must no longer claim frame_reselect as the primary
|
|
action for this category (it's now the downstream cascade step)."""
|
|
rationale = ACTION_RATIONALE.get("frame_capacity_mismatch", "")
|
|
assert rationale.strip(), "frame_capacity_mismatch rationale must be non-empty"
|
|
# Mentions the new internal-fit direction.
|
|
assert "internal" in rationale.lower() or "envelope" in rationale.lower()
|
|
|
|
|
|
# ─── ACTION_IMPLEMENTATION_STATUS rows ────────────────────────────
|
|
|
|
|
|
def test_layout_adjust_status_implemented_after_u7():
|
|
"""u1 registered layout_adjust row (initial MISSING). After u3
|
|
(plan_layout_adjust + apply_layout_adjust_layout_css) + u6 (salvage
|
|
dispatcher branch) + u7 (cascade entry trigger) land the end-to-end
|
|
deterministic path, the status flips to IMPLEMENTED."""
|
|
assert ACTION_IMPLEMENTATION_STATUS["layout_adjust"] == "IMPLEMENTED"
|
|
|
|
|
|
def test_image_fit_status_implemented_after_u7():
|
|
"""u1 registered image_fit row (initial MISSING). After u4 (plan_image_fit
|
|
+ apply_image_fit_css) + u7 (_attempt_step17_image_fit_single_pass entry)
|
|
land the end-to-end deterministic path, the status flips to IMPLEMENTED."""
|
|
assert "image_fit" in ACTION_IMPLEMENTATION_STATUS
|
|
assert ACTION_IMPLEMENTATION_STATUS["image_fit"] == "IMPLEMENTED"
|
|
|
|
|
|
def test_frame_internal_fit_candidate_status_implemented_after_u7():
|
|
"""u1 registered frame_internal_fit_candidate row (initial MISSING). After
|
|
u5 (plan_frame_internal_fit_candidate + apply) + u6 (salvage dispatcher
|
|
branch) + u7 (cascade entry trigger) land the end-to-end deterministic
|
|
path, the status flips to IMPLEMENTED."""
|
|
assert "frame_internal_fit_candidate" in ACTION_IMPLEMENTATION_STATUS
|
|
assert ACTION_IMPLEMENTATION_STATUS["frame_internal_fit_candidate"] == "IMPLEMENTED"
|
|
|
|
|
|
def test_existing_action_implementation_status_rows_unchanged():
|
|
"""u1 — non-IMP-88 status rows must NOT regress. zone_ratio_retry,
|
|
cascade-only salvage actions, details_popup_escalation (IMP-35 u3),
|
|
and frame_reselect must keep their current statuses."""
|
|
assert ACTION_IMPLEMENTATION_STATUS["zone_ratio_retry"] == "IMPLEMENTED"
|
|
assert ACTION_IMPLEMENTATION_STATUS["details_popup_escalation"] == "IMPLEMENTED"
|
|
assert ACTION_IMPLEMENTATION_STATUS["frame_reselect"] == "PARTIAL"
|
|
assert ACTION_IMPLEMENTATION_STATUS["adapter_needed"] == "PARTIAL"
|
|
assert ACTION_IMPLEMENTATION_STATUS["abort"] == "IMPLEMENTED"
|
|
assert ACTION_IMPLEMENTATION_STATUS["cross_zone_redistribute"] == "IMPLEMENTED"
|
|
assert ACTION_IMPLEMENTATION_STATUS["glue_compression"] == "IMPLEMENTED"
|
|
assert ACTION_IMPLEMENTATION_STATUS["font_step_compression"] == "IMPLEMENTED"
|
|
|
|
|
|
# ─── route_action + route_fit_classification integration ──────────
|
|
|
|
|
|
def test_route_action_image_aspect_mismatch_returns_image_fit_implemented():
|
|
"""u1 — route_action surface composes the new mapping correctly.
|
|
|
|
Stage 1 evidence: previously this call returned proposed_action=None
|
|
and implementation_status='unknown'. After u1 + u4 + u7, the call must
|
|
return image_fit with status IMPLEMENTED (end-to-end deterministic path
|
|
via plan_image_fit + apply_image_fit_css + Step 17 single-pass entry)."""
|
|
routing = route_action("image_aspect_mismatch")
|
|
assert routing["proposed_action"] == "image_fit"
|
|
assert routing["implementation_status"] == "IMPLEMENTED"
|
|
assert routing["mapping_source"] == "spec §4 ACTION_BY_CATEGORY"
|
|
assert routing["rationale"], "rationale must be carried through route_action"
|
|
|
|
|
|
def test_route_action_frame_capacity_mismatch_returns_frame_internal_fit_candidate_implemented():
|
|
"""u1 — route_action surface reflects the REMAP. After u1 + u5 + u6 + u7
|
|
the status is IMPLEMENTED (end-to-end deterministic path via
|
|
plan_frame_internal_fit_candidate + apply + salvage dispatcher branch +
|
|
cascade entry trigger)."""
|
|
routing = route_action("frame_capacity_mismatch")
|
|
assert routing["proposed_action"] == "frame_internal_fit_candidate"
|
|
assert routing["implementation_status"] == "IMPLEMENTED"
|
|
assert routing["mapping_source"] == "spec §4 ACTION_BY_CATEGORY"
|
|
|
|
|
|
def test_route_fit_classification_surfaces_imp88_actions_as_implemented():
|
|
"""End-to-end: when classifier emits the two IMP-88 categories alongside
|
|
an already-implemented one, route_fit_classification:
|
|
- attaches proposed_action onto each row
|
|
- lists all three actions in proposed_actions_summary
|
|
- reports an empty missing_actions_pending_impl for the IMP-88 actions
|
|
(u7 completion flipped image_fit + frame_internal_fit_candidate to
|
|
IMPLEMENTED alongside layout_adjust)
|
|
- all three rows count as IMPLEMENTED in the status summary."""
|
|
fit_classification = {
|
|
"visual_check_passed": False,
|
|
"classifications": [
|
|
{
|
|
"source": "image_event",
|
|
"zone_position": "bottom",
|
|
"category": "image_aspect_mismatch",
|
|
},
|
|
{
|
|
"source": "composition",
|
|
"zone_position": "top",
|
|
"category": "frame_capacity_mismatch",
|
|
},
|
|
{
|
|
"source": "clipped_inner",
|
|
"zone_position": "bottom",
|
|
"category": "minor_overflow",
|
|
},
|
|
],
|
|
}
|
|
summary = route_fit_classification(fit_classification)
|
|
assert summary["router_active"] is True
|
|
assert summary["routed_count"] == 3
|
|
assert "image_fit" in summary["proposed_actions_summary"]
|
|
assert "frame_internal_fit_candidate" in summary["proposed_actions_summary"]
|
|
assert "zone_ratio_retry" in summary["proposed_actions_summary"]
|
|
# After u7 completion, both new IMP-88 actions are IMPLEMENTED on the
|
|
# router-surface — they no longer surface as missing pending impl.
|
|
assert "image_fit" not in summary["missing_actions_pending_impl"]
|
|
assert "frame_internal_fit_candidate" not in summary["missing_actions_pending_impl"]
|
|
# All three (zone_ratio_retry IMPLEMENTED + 2 IMP-88 IMPLEMENTED) count
|
|
# together. zone_ratio_retry was IMPLEMENTED since A3 cascade.
|
|
assert summary["implementation_status_summary"].get("IMPLEMENTED", 0) == 3
|
|
assert summary["implementation_status_summary"].get("MISSING", 0) == 0
|
|
# Per-row enrichment carries the new proposed actions onto entries.
|
|
cats = {c["category"]: c for c in fit_classification["classifications"]}
|
|
assert cats["image_aspect_mismatch"]["proposed_action"] == "image_fit"
|
|
assert (
|
|
cats["frame_capacity_mismatch"]["proposed_action"]
|
|
== "frame_internal_fit_candidate"
|
|
)
|