From bc8a2c94ba67ae758c132a17baf5d93e304e41e9 Mon Sep 17 00:00:00 2001 From: Amir Fathi Date: Mon, 17 Aug 2026 18:47:40 +0000 Subject: [PATCH] fix(skills): wrap generate-mdl SKILL.md's relationships.yml example under the required key Step 3 of the generate-mdl skill showed a bare top-level YAML list for relationships.yml. load_relationships() only reads a top-level `relationships:` mapping key, so a bare list silently loads as zero relationships; validate_project() (run by default before `wren build`) does catch it with an explicit error, but only because a fail-loud guard was added for hand-edited files after this example was written, not because the example itself was ever correct. Fixes #2672 --- .../wren/skills_content/generate-mdl/SKILL.md | 13 +++--- core/wren/tests/unit/test_context.py | 41 +++++++++++++++++++ 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/core/wren/src/wren/skills_content/generate-mdl/SKILL.md b/core/wren/src/wren/skills_content/generate-mdl/SKILL.md index bb87f98c91..0b5915dda1 100644 --- a/core/wren/src/wren/skills_content/generate-mdl/SKILL.md +++ b/core/wren/src/wren/skills_content/generate-mdl/SKILL.md @@ -213,12 +213,13 @@ From foreign key constraints discovered in Phase 2: ```yaml # relationships.yml -- name: orders_customers - models: - - orders - - customers - join_type: many_to_one - condition: "orders.customer_id = customers.customer_id" +relationships: + - name: orders_customers + models: + - orders + - customers + join_type: many_to_one + condition: "orders.customer_id = customers.customer_id" ``` Join type mapping: diff --git a/core/wren/tests/unit/test_context.py b/core/wren/tests/unit/test_context.py index 49f45ba666..ffcb6677b1 100644 --- a/core/wren/tests/unit/test_context.py +++ b/core/wren/tests/unit/test_context.py @@ -2011,6 +2011,47 @@ def test_validate_project_reports_relationships_bare_root(tmp_path: Path) -> Non ) +def _extract_fenced_yaml(markdown: str, heading: str) -> str: + """Pull the first ```yaml fenced block under a markdown heading.""" + after_heading = markdown[markdown.index(heading) :] + start = after_heading.index("```yaml") + len("```yaml") + end = after_heading.index("```", start) + return after_heading[start:end] + + +def test_generate_mdl_skill_step3_example_round_trips(tmp_path: Path) -> None: + """The generate-mdl skill's own Step 2/Step 3 examples, fed to the real + loader/validator, must produce a clean project. Regression for #2672: Step 3 + used to ship a bare top-level list, which load_relationships silently drops + and validate_project rejects.""" + from wren.skills_delivery import get_skill # noqa: PLC0415 + + skill = get_skill("generate-mdl") + models_yaml = _extract_fenced_yaml(skill, "### Step 2 — Write model files") + relationships_yaml = _extract_fenced_yaml(skill, "### Step 3 — Write relationships") + + _make_v2_project(tmp_path) + (tmp_path / "models" / "orders").mkdir(parents=True) + (tmp_path / "models" / "orders" / "metadata.yml").write_text( + models_yaml, encoding="utf-8" + ) + (tmp_path / "models" / "customers").mkdir(parents=True) + (tmp_path / "models" / "customers" / "metadata.yml").write_text( + "name: customers\n" + "table_reference:\n table: customers\n" + "primary_key: customer_id\n" + "columns:\n - name: customer_id\n type: INTEGER\n", + encoding="utf-8", + ) + (tmp_path / "relationships.yml").write_text(relationships_yaml, encoding="utf-8") + + rels = load_relationships(tmp_path) + assert len(rels) == 1 + assert rels[0]["name"] == "orders_customers" + + assert validate_project(tmp_path) == [] + + def test_validate_project_relationship_indices_match_file(tmp_path: Path) -> None: """Junk at [0] must not renumber a later unnamed relationship's warnings.""" (tmp_path / "wren_project.yml").write_text("schema_version: 1\n", encoding="utf-8")