wip: phase_z2 evidence 파이프라인 + matching 실험(phase2~26) + 프론트 trace 패널 진행분 스냅샷
- src: phase_z2 composition/mapper/pipeline/placement_planner/retry, ai_fallback(prompts/schema/validate), mdx_text_atoms 신규 - Front: PipelineTracePanel 신규, FramePanel/SlideCanvas/Home/designAgentApi 등 갱신 + 테스트 4종 추가 - templates/phase_z2: catalog(component_expansion_registry, node_slot_mapping 신규), frames, families, slide_base 갱신 - tests/matching: phase2~26 매칭 실험 스크립트·리포트·온톨로지 전체 (미커밋 진행분) - tests: b4_v4 evidence, task5~28.5 시리즈, regression(imp95 baseline) 등 신규 테스트 대량 추가 - docs/reference: MDX 구조 인벤토리, MDX→Frame 구조 계약 문서 - scripts: mdx 계약/parity/coverage/viewport 체크, gitea comment, run sync 유틸 - .gitignore: tmp*.json, chromedriver, .orchestrator, *.pkl, Front_test* 등 임시/스냅샷 제외 미완성 작업의 보존용 스냅샷 커밋 (2026-07-02) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,8 +29,12 @@ SYSTEM_PROMPT = (
|
||||
f" 3. proposal_kind MUST be one of: {_ALLOWED_KINDS}.\n"
|
||||
f" 4. Do NOT propose any of: {_FORBIDDEN_KINDS}.\n"
|
||||
" 5. Do NOT change frame_id — V4 rank-1 frame is locked.\n"
|
||||
" 6. Keep declared frame slots (text/table/image/details) populated.\n"
|
||||
" 7. Respect Internal Region containment; place content units within "
|
||||
" 6. Preferred Task-12 output is proposal_kind='design_adaptation_plan': "
|
||||
"plan frame/layout/repeat changes only; do NOT output final text slots.\n"
|
||||
" 7. Do NOT create titles, labels, summaries, body text, or slot content. "
|
||||
"The code layer will place MDX verbatim text.\n"
|
||||
" 8. Keep declared frame slots (text/table/image/details) accounted for.\n"
|
||||
" 9. Respect Internal Region containment; place content units within "
|
||||
"the declared region only."
|
||||
)
|
||||
|
||||
@@ -73,6 +77,27 @@ def build_ai_fallback_prompt(
|
||||
"figma_partial_json": figma_partial_json,
|
||||
"internal_region": internal_region,
|
||||
"mdx_text_READ_ONLY": mdx_text,
|
||||
"task12_output_contract": {
|
||||
"preferred_proposal_kind": ProposalKind.DESIGN_ADAPTATION_PLAN.value,
|
||||
"allowed_operation_examples": [
|
||||
"increase_repeat_count",
|
||||
"split_group_across_repeat_blocks",
|
||||
"rebalance_zone_ratio",
|
||||
"compact_spacing",
|
||||
"use_repeatable_frame",
|
||||
],
|
||||
"forbidden_content_fields": [
|
||||
"text",
|
||||
"title",
|
||||
"label",
|
||||
"body",
|
||||
"slots",
|
||||
"mdx_text",
|
||||
"summary",
|
||||
"raw_html",
|
||||
"raw_css",
|
||||
],
|
||||
},
|
||||
}
|
||||
return {
|
||||
"system": SYSTEM_PROMPT,
|
||||
|
||||
@@ -4,6 +4,7 @@ Whitelisted proposal kinds (Stage 2 plan):
|
||||
- builder_options_patch : zone/frame builder option overrides
|
||||
- partial_overrides : Internal Region / Frame Slot content overrides
|
||||
- slot_mapping_proposal : restructuring proposal (content unit mapping)
|
||||
- design_adaptation_plan : structure-only plan; code applies verbatim MDX
|
||||
|
||||
Forbidden output forms (rejected by validator):
|
||||
- mdx_text (MDX read-only — `feedback_ai_isolation_contract`)
|
||||
@@ -23,6 +24,7 @@ class ProposalKind(str, Enum):
|
||||
BUILDER_OPTIONS_PATCH = "builder_options_patch"
|
||||
PARTIAL_OVERRIDES = "partial_overrides"
|
||||
SLOT_MAPPING_PROPOSAL = "slot_mapping_proposal"
|
||||
DESIGN_ADAPTATION_PLAN = "design_adaptation_plan"
|
||||
|
||||
|
||||
FORBIDDEN_KINDS: frozenset[str] = frozenset(
|
||||
|
||||
@@ -27,6 +27,43 @@ class AiFallbackValidationError(ValueError):
|
||||
|
||||
_SLOT_KINDS = (ProposalKind.PARTIAL_OVERRIDES, ProposalKind.SLOT_MAPPING_PROPOSAL)
|
||||
|
||||
_DESIGN_PLAN_FORBIDDEN_CONTENT_KEYS: frozenset[str] = frozenset(
|
||||
{
|
||||
"body",
|
||||
"label",
|
||||
"labels",
|
||||
"mdx_text",
|
||||
"new_text",
|
||||
"raw_css",
|
||||
"raw_html",
|
||||
"slot_payload",
|
||||
"slots",
|
||||
"summary",
|
||||
"text",
|
||||
"title",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _find_forbidden_design_plan_keys(value: Any, path: str = "payload") -> list[str]:
|
||||
"""Return content-bearing keys that would let AI generate text.
|
||||
|
||||
Task 12 contract: design_adaptation_plan may describe structure changes,
|
||||
but code remains the sole layer that maps MDX verbatim text into slots.
|
||||
"""
|
||||
hits: list[str] = []
|
||||
if isinstance(value, dict):
|
||||
for key, nested in value.items():
|
||||
key_str = str(key)
|
||||
nested_path = f"{path}.{key_str}"
|
||||
if key_str in _DESIGN_PLAN_FORBIDDEN_CONTENT_KEYS:
|
||||
hits.append(nested_path)
|
||||
hits.extend(_find_forbidden_design_plan_keys(nested, nested_path))
|
||||
elif isinstance(value, list):
|
||||
for idx, nested in enumerate(value):
|
||||
hits.extend(_find_forbidden_design_plan_keys(nested, f"{path}[{idx}]"))
|
||||
return hits
|
||||
|
||||
|
||||
def validate_proposal(
|
||||
proposal: AiFallbackProposal,
|
||||
@@ -73,6 +110,19 @@ def validate_proposal(
|
||||
"from payload.slots (text/table/image/details must remain populated)."
|
||||
)
|
||||
|
||||
if proposal.proposal_kind is ProposalKind.DESIGN_ADAPTATION_PLAN:
|
||||
operations = payload.get("operations")
|
||||
if not isinstance(operations, list) or not operations:
|
||||
raise AiFallbackValidationError(
|
||||
"design adaptation plan: payload.operations must be a non-empty list."
|
||||
)
|
||||
forbidden_paths = _find_forbidden_design_plan_keys(payload)
|
||||
if forbidden_paths:
|
||||
raise AiFallbackValidationError(
|
||||
"design adaptation plan: AI must not emit content-bearing fields "
|
||||
f"{forbidden_paths}; code maps MDX verbatim text."
|
||||
)
|
||||
|
||||
region_id = payload.get("region_id")
|
||||
if region_id is not None and internal_region is not None:
|
||||
declared_region_id = internal_region.get("id")
|
||||
|
||||
Reference in New Issue
Block a user