Land the production + test surface for the Step 17 cascade POPUP terminal (DETERMINISTIC -> POPUP -> AI_REPAIR -> USER_OVERRIDE) per Stage 2 plan R2. u11 (baseline-red invariance gate) was already landed in7c93031ahead of this commit; this commit completes u1~u10 plus the Stage 3 R7 follow-up anchor re-pin for test_imp17_comment_anchor.py. Implementation units (Stage 2 R2 contract): u1 frame_reselect_insufficient failure_type + post-frame remeasure (q4) - src/phase_z2_failure_router.py, src/phase_z2_pipeline.py u2 NEXT_ACTION_BY_FAILURE row + impl_status flip - src/phase_z2_failure_router.py u3 Router details_popup_escalation MISSING->IMPLEMENTED + executor stub - src/phase_z2_router.py u4 step17.py AI split-decision contract (POPUP cascade_stage + route_for_label + skip_reason); API gated - src/phase_z2_ai_fallback/step17.py u5 Step 17 POPUP gate executor; popup_escalation_plan + has_popup marker - src/phase_z2_pipeline.py, src/phase_z2_ai_fallback/step17.py u6 Composition popup binding -- yaml strategy -> zone payload - src/phase_z2_composition.py u7 Pipeline composer -> render_slide wiring (popup_html / preview_text / has_popup) - src/phase_z2_pipeline.py u8 slide_base.html <details>/<summary> popup wrapper - templates/phase_z2/slide_base.html u9 display_strategies.yaml inline_preview + popup metadata - templates/phase_z2/regions/display_strategies.yaml u10 MDX preservation invariant: popup=full source / body=summary or subset (asserted by tests/phase_z2/test_popup_mdx_preservation.py) u11 (already in7c93031) -- baseline-red invariance gate Stage 3 R7 follow-up (anchor re-pin, test-only): - tests/orchestrator_unit/test_imp17_comment_anchor.py Pre-anchor additions in src/phase_z2_pipeline.py (u1 / u5 / u7) shifted the restructure/reject route-hint comments 578/579 -> 586/587. Re-pinned the two guard tests (and docstring re-pin lineage 564 -> 570 -> 578 -> 586). Production code untouched. Verification (Stage 4 R1): pytest -q tests/orchestrator_unit/test_imp17_comment_anchor.py -> 2 passed / 0.02s pytest -q <10 IMP-35 unit files in tests/phase_z2 + tests/phase_z2_ai_fallback> -> 136 passed / 15.94s Baseline-red invariance gate (tests/test_imp47b_step12_ai_wiring.py + tests/test_phase_z2_ai_fallback_config.py) -> 4 failed / 6 passed; FAILED set === IMP35_BASELINE_RED_NODE_IDS (frozen registry from7c93031). Contract holds. Codex Stage 4 R1 = YES (independent verify). Guardrails honored: - MDX content preservation: popup carries full source, body holds summary or subset only (CLAUDE.md 자세히보기 원칙; feedback_phase_z_spacing_direction -- capacity expanded, no margin shrink). - AI isolation contract: Step 17 POPUP gate is deterministic; AI hook surface is split-decision contract only, API call gated. - No hardcoding: escalation thresholds derived from existing overflow detector outputs; preview_chars deterministic from container px. - 1 commit = 1 decision unit: u1~u10 land together as the planned production surface; u11 was deliberately split into7c93031as Stage 3 R7 carve-out, and the R7 anchor re-pin rides with this commit because it is the direct shift consequence of the u1/u5/u7 pre-anchor additions. - Scope-locked: .claude/settings.json explicitly excluded (Stage 4 exit report contract). Out of scope (per Stage 1 + Stage 2): - AI_REPAIR API activation (post IMP-35 axis). - IMP-34 zone resize, IMP-36 responsive fit (chain partners, separate issues). - Print-time auto-expand JavaScript for <details>. - Popup escalation in stages other than Step 17. - Baseline-red body repair (4 frozen failures) -- separate follow-up issue; u11 only guards the count. - frame_reselect algorithm changes (entry point only). - templates/phase_z2/slide_base.html path rename. source_comment_ids: Stage 1: claude_stage1_problem_review_imp35, codex_stage1_verification_imp35_yes Stage 2: Claude #4 R2 plan, Codex #5 R2 YES Stage 3: Claude #86 (R7 anchor re-pin), Codex #87 YES Stage 4: Claude #88 R1, Codex #89 R1 YES Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
4.2 KiB
YAML
87 lines
4.2 KiB
YAML
# Phase Z Display Strategy Catalog
|
|
#
|
|
# User lock (2026-05-07) — Step 8-A:
|
|
# Display strategy vocabulary — how to present content within a region.
|
|
# Source: docs/architecture/PHASE-Z-CONTENT-OBJECT-SUBZONE-SPEC.md (4 entry).
|
|
#
|
|
# Axis separation:
|
|
# region_layouts.yaml = how to divide zone into regions (structure axis)
|
|
# display_strategies.yaml (this file) = how to display content within region (policy axis)
|
|
# The two axes are orthogonal — same region layout can use different strategies.
|
|
#
|
|
# Absolute user locks (must NOT be violated):
|
|
# - Original text/table/image/details content is NEVER dropped or summarized.
|
|
# - 오답노트 #5: 텍스트 압축 / trim / restructure 금지.
|
|
# - IMPROVEMENT-REDESIGN.md line 110: "본문은 preview, 원문은 popup/detail 무손실 보존".
|
|
# - "dropped" applies ONLY to decorative elements — strict forbidden_for enforcement.
|
|
#
|
|
# Per-entry fields:
|
|
# description: str
|
|
# applies_to: list[str] (content types that can use this strategy)
|
|
# forbidden_for: list[str] (content types that MUST NOT use this strategy)
|
|
# preserves_original: bool (true = original content kept somewhere — popup/detail)
|
|
# preview_chars: int | null (IMP-35 u9 — soft char budget for the inline body
|
|
# shown alongside the popup trigger; null when the
|
|
# strategy has no popup. The popup body itself
|
|
# ALWAYS holds the FULL original — preview_chars
|
|
# governs only the inline preview/summary surface.)
|
|
# popup_target_slot: str | null
|
|
# (IMP-35 u9 — frame Layer B slot identifier the
|
|
# popup trigger anchors to. null when the strategy
|
|
# has no popup. See CLAUDE.md "위계 + 용어" →
|
|
# "Frame Slot" / "Layer B" for the slot vocabulary.)
|
|
|
|
|
|
inline_full:
|
|
description: Content fully inline — entire content rendered within region.
|
|
applies_to: [text_block, table, image, details, decorative_element]
|
|
forbidden_for: []
|
|
preserves_original: true # all content is inline, original = inline
|
|
# IMP-35 u9 — inline_full has no popup → both popup-wiring fields are null.
|
|
preview_chars: null
|
|
popup_target_slot: null
|
|
|
|
|
|
inline_preview_with_details:
|
|
description: Partial inline preview + remaining content in details/popup.
|
|
applies_to: [text_block, table, details]
|
|
forbidden_for: [decorative_element]
|
|
preserves_original: true # User lock — original content kept in popup
|
|
# IMP-35 u9 — partial preview body inline; popup body holds FULL original.
|
|
preview_chars: 240
|
|
popup_target_slot: primary
|
|
detail_trigger:
|
|
placement: top-right # 본문 흐름 방해 X / 보조 동작 위치 / 안정 (user 2026-05-07)
|
|
label: details # identifier — display text 는 partial/UI 별 axis
|
|
preserves_original_note: "버튼은 원문 대체 X — 원문 전체 진입문"
|
|
|
|
|
|
details_only:
|
|
description: Summary inline only, full content in popup.
|
|
applies_to: [text_block, table, details]
|
|
forbidden_for: [decorative_element]
|
|
preserves_original: true # User lock — full content in popup
|
|
# IMP-35 u9 — summary-only inline surface (smaller char budget); popup body
|
|
# holds FULL original. preview_chars > 0 because details_only still emits a
|
|
# short summary line — it is NOT a "no body" surface (that is `dropped`).
|
|
preview_chars: 80
|
|
popup_target_slot: primary
|
|
detail_trigger:
|
|
placement: top-right # user lock — popup 진입 일관 위치
|
|
label: details
|
|
preserves_original_note: "버튼은 원문 대체 X — 원문 전체 진입문"
|
|
|
|
|
|
dropped:
|
|
description: |
|
|
Decorative element omitted due to space constraints.
|
|
USER LOCK: applies ONLY to decorative_element.
|
|
NEVER drop text_block / table / image / details — original content preservation
|
|
is absolute (오답노트 #5, IMPROVEMENT-REDESIGN.md §3.6 line 110).
|
|
applies_to: [decorative_element]
|
|
forbidden_for: [text_block, table, image, details]
|
|
preserves_original: false # decorative only — no original to preserve
|
|
# IMP-35 u9 — dropped has no popup and no body surface → both fields null.
|
|
preview_chars: null
|
|
popup_target_slot: null
|