diff --git a/core/wren/src/wren/genbi/composer.py b/core/wren/src/wren/genbi/composer.py index 726b8d5860..3fdfbaabab 100644 --- a/core/wren/src/wren/genbi/composer.py +++ b/core/wren/src/wren/genbi/composer.py @@ -57,7 +57,18 @@ def _format_model_inventory(models: list[dict]) -> str: return "- (no models found — run `wren context build` first)" lines = [] for model in models: - cols = ", ".join(c.get("name", "?") for c in model.get("columns", [])) + # `columns` is YAML-sourced; only the list container/type is untrusted here. + # Models themselves come from load_models (already dict-filtered). + raw_cols = model.get("columns", []) + if not isinstance(raw_cols, list): + raw_cols = [] + names = [] + for c in raw_cols: + if isinstance(c, dict): + names.append(str(c.get("name", "?"))) + elif isinstance(c, str) and c: + names.append(c) + cols = ", ".join(names) lines.append(f"- **{model.get('name', '?')}**: {cols}") return "\n".join(lines) diff --git a/core/wren/tests/unit/test_genbi_build.py b/core/wren/tests/unit/test_genbi_build.py index 6713cca315..c8b1e34bea 100644 --- a/core/wren/tests/unit/test_genbi_build.py +++ b/core/wren/tests/unit/test_genbi_build.py @@ -94,6 +94,29 @@ def test_build_includes_model_inventory(tmp_path: Path) -> None: assert "duckdb" in result.output +def test_build_inventory_tolerates_non_list_columns(tmp_path: Path) -> None: + """YAML may set columns: to a string; inventory formatting must not crash.""" + from wren.genbi.composer import compose_build_instruction + + models = [ + {"name": "orders", "columns": "id, customer_id"}, + {"name": "customers", "columns": [{"name": "id"}, "bare", 3]}, + ] + text = compose_build_instruction( + app_name="demo", + data_mode="snapshot", + user_prompt="hi", + mdl_path=tmp_path / "mdl.json", + app_dir=tmp_path / "app", + models=models, + data_source="duckdb", + ) + assert "**orders**" in text + assert "**customers**" in text + assert "id" in text + + + def test_build_includes_wasm_wiring_and_final_steps(tmp_path: Path) -> None: project = _make_project(tmp_path)