from __future__ import annotations from src.phase_z2_mapper import load_frame_contracts from src.phase_z2_composition import CompositionUnit from src.phase_z2_pipeline import ( _build_verbatim_cards_n_grid, _build_verbatim_three_parallel_requirements, _build_verbatim_three_persona_benefits, compute_zone_layout_cols, ) def test_task11a_dynamic_cardinality_metadata_present_for_repair_frames(): contracts = load_frame_contracts() expected = { "three_parallel_requirements": ("pillars", "card", True), "three_persona_benefits": ("personas", "card", True), "construction_bim_three_usage": ("categories", "row", True), "bim_dx_comparison_table": ("rows", "table_row", True), "bim_issues_quadrant_four": ("quadrants", "card", True), "pre_construction_model_info_stacked": ("pills", "list_row", True), "sw_dependency_four_problems": ("problems", "card", True), "construction_goals_three_circle_intersection": ("circles", "fixed_diagram", False), } for template_id, (axis, policy, repeatable) in expected.items(): dynamic = contracts[template_id].get("dynamic_cardinality") assert dynamic is not None, template_id assert dynamic["repeat_axis"] == axis assert dynamic["expand_policy"] == policy assert dynamic["repeatable"] is repeatable assert dynamic["preserve_source_order"] is True def _unit_with_groups(count: int) -> CompositionUnit: raw = "\n\n".join( f"- **Group {i}**\n - Item {i}" for i in range(1, count + 1) ) return CompositionUnit( source_section_ids=["S1"], merge_type="single", frame_template_id="three_parallel_requirements", frame_id="frame", frame_number=1, confidence=1.0, label="use_as_is", phase_z_status="matched_zone", raw_content=raw, title="Title", ) def test_task11c_verbatim_builders_do_not_truncate_extra_groups(): unit = _unit_with_groups(6) pillars = _build_verbatim_three_parallel_requirements(unit)["pillars"] personas = _build_verbatim_three_persona_benefits(unit)["personas"] cards = _build_verbatim_cards_n_grid( unit, slot_count=4, label_pattern="pill_{n}_label", body_pattern="pill_{n}_body", ) assert len(pillars) == 6 assert len(personas) == 6 assert cards["_slot_count"] == 6 assert cards["pill_6_label"] == "Group 6" def test_task11d_verbatim_builder_uses_headings_as_groups_without_empty_padding(): unit = CompositionUnit( source_section_ids=["x-1"], merge_type="single", title="Title", raw_content="### A\nalpha\nbeta\n\n### B\ngamma", frame_id="frame", frame_number=1, frame_template_id="three_parallel_requirements", confidence=0.0, label="reject", phase_z_status="fallback_candidate", v4_rank=1, selection_path="fit_error_recovered_by_code_verbatim", score=0, ) payload = _build_verbatim_three_parallel_requirements(unit) assert [p["label_main"] for p in payload["pillars"]] == ["A", "B"] assert payload["pillars"][0]["sections"][0]["text_lines"] == [ {"text": "alpha", "indent": 0}, {"text": "beta", "indent": 0}, ] def test_task11d_column_layout_keeps_zero_weight_track_visible(): layout = compute_zone_layout_cols( [ { "position": "left", "template_id": "heavy", "content_weight": {"score": 10}, }, { "position": "right", "template_id": "light", "content_weight": {"score": 0}, }, ], total_width=1180, gap=14, ) assert layout["widths_px"][1] >= 260 assert sum(layout["widths_px"]) == 1166