Dataface Tasks

Add resolved YAML render output format

IDMCP_ANALYST_AGENT-ADD_RESOLVED_YAML_RENDER_OUTPUT_FORMAT
Statuscompleted
Priorityp2
Milestonem1-ft-analytics-analyst-pilot
Ownerdata-ai-engineer-architect
Completed bydave
Completed2026-03-24

Problem

The existing render formats serve different audiences: HTML/SVG for humans, JSON for programmatic access, text for compact AI summaries. But none produce output that is both human-readable AND re-renderable as valid dataface input. AI agents work in YAML — they write it, edit it, iterate on it. A "resolved YAML" format would let agents see exactly what the system decided (chart types, fields, data) in the same language they author dashboards in, and that output could be fed back in as input.

Context

  • dataface/core/render/json_format.py_face_to_dict() already walks the layout, executes queries, resolves charts, returns structured dicts. The YAML format reuses this.
  • dataface/core/render/renderer.py — format dispatch + RENDER_FORMATS tuple
  • The dataface YAML schema supports values: as an inline data source (alternative to sql:). The resolved YAML replaces queries with their executed results as values:.
  • dataface/core/compile/ — normalizer/compiler that the output must be compatible with as input
  • Related: format="json" (PR #623), format="text" (PR #624), playground fixes (PR #625)

Possible Solutions

  1. Recommended — Map resolved dict back to dataface YAML schema. Call _face_to_dict(), then transform the result into valid dataface YAML: top-level title, source, queries (with values: instead of sql:), charts (with resolved types/fields), rows/cols/grid layout. Output via yaml.dump(). The result is a valid .yml file that can be re-compiled and rendered without a database.

  2. Dump _face_to_dict() directly as YAML. Simpler but the output wouldn't be valid dataface input — it uses the internal JSON structure (nested items, chart objects) rather than the user-facing YAML schema (flat charts dict, layout references).

Plan

Files to create: - dataface/core/render/yaml_format.pyrender_face_yaml() that transforms resolved data into dataface YAML schema

Files to modify: - dataface/core/render/renderer.py — add elif format == "yaml" + add to RENDER_FORMATS - dataface/cli/commands/render.py — yaml prints to stdout like json/text - dataface/cli/main.py — update --format help - dataface/ai/tool_schemas.py — add "yaml" to format enum - apps/playground/routes.py — add yaml format case (same as json/text — HTML-wrapped pre block) - apps/playground/static/index.html — add YAML option to dropdown - apps/playground/websocket.py — already handled generically - tests/core/test_yaml_format.py — tests

Key design decisions: - Queries become values: with the executed data rows inline - Auto chart types resolved to concrete types - Auto-detected x/y/color fields filled in explicitly - The output must round-trip: render --format yaml | compile should succeed - Layout preserved as rows/cols/grid references

Steps: 1. Write failing test: render a face with format="yaml", assert output is valid YAML, contains resolved chart type, has values instead of sql 2. Implement render_face_yaml() — reuse _face_to_dict, map to dataface schema 3. Write round-trip test: render to yaml, re-compile, verify success 4. Wire into renderer, CLI, MCP schema, playground 5. Run just ci

Implementation Progress

Approach: Solution 1 — Map resolved dict back to dataface YAML schema

render_face_yaml() reuses _face_to_dict() from json_format.py (shared with text format), then transforms the internal JSON structure into valid dataface YAML schema:

  • Queries: SQL/CSV/HTTP queries become type: values with rows: containing the executed data inline
  • Charts: Auto chart types resolved to concrete types (bar, line, etc.), auto-detected fields (x, y, color) filled in explicitly, referencing their query by name
  • Layout: Preserved as rows: with chart name references
  • Nested faces: Recursively converted and inlined in layout
  • Type coercion: Decimal → int/float, datetime → ISO string, DotDict → dict for clean YAML output

Files created

  • dataface/core/render/yaml_format.pyrender_face_yaml() + _face_to_yaml_dict() + _chart_to_yaml_dict() + _clean_value()
  • tests/core/test_yaml_format.py — 9 tests: basic output, resolved fields, values-not-sql, auto-type resolution, layout preservation, KPI charts, round-trip compile, nested faces, multiple charts with distinct queries

Files modified

  • dataface/core/render/renderer.py — added format == "yaml" dispatch (lazy import)
  • dataface/cli/commands/render.py — added "yaml" to stdout format list
  • dataface/cli/main.py — updated --format help text
  • dataface/ai/tool_schemas.py — added "yaml" to MCP tool format enum with description
  • apps/playground/routes.py — added "yaml" to json/text format handling branch
  • apps/playground/static/index.html — added YAML option to format dropdown

Validation

  • 9/9 YAML format tests pass
  • All 2855+ tests pass (1 pre-existing flaky test in test_ai_service.py)
  • Ruff, Black, Mypy all clean

QA Exploration

N/A — non-UI-rendering task. The playground dropdown was updated but the core feature is a text output format consumed by CLI and MCP.

  • [x] QA exploration completed (or N/A for non-UI tasks)

Review Feedback

  • [ ] Review cleared