# Iteration 1 — graph model serializer — Implementation Plan > **Parent spec:** `docs/specs/0026-graph-render-redesign.md` > > **For agentic workers:** REQUIRED SUB-SKILL: use the `implement` skill to run this > plan. Steps use `- [ ]` checkboxes for tracking. **Goal:** Add a read-only Rust serializer `model_to_json(&Composite) -> String` that turns the harness root composite + every distinct composite type into the canonical, deterministic JSON graph model the viewer (iteration 2) will consume. **Architecture:** A new `crates/aura-engine/src/graph_model.rs`, hand-rolled deterministic JSON in the `RunReport::to_json` house style (no serde). It walks the blueprint via the existing read-only accessors and emits a model with two top-level keys: `root` (the harness scope) and `composites` (each distinct composite type once). Read-only (C9): the function takes `&Composite`, returns `String`, and never calls `eval`/`compile`/`bootstrap`. **Tech Stack:** aura-engine (`blueprint.rs` accessors, `harness::Edge`, `report.rs` JSON idiom), aura-core (`NodeSchema`/`PortSpec`/`FieldSpec`/`ParamSpec`/ `Firing`/`ScalarKind`). --- ## Model shape (the contract this iteration produces) Resolved against the **types** (recon) and spec acceptance criterion 3, where the spec's abridged example was prototype-flavoured: ``` { "root": , "composites": { "": , ... } // first-seen order } ``` - **scope** = `{ "nodes": { "": , ... }, "edges": [ , ... ] }` - **composite-def** = `{ "inputs": [ , ... ], "outputs": [ [name,kind], ... ], "nodes": {...}, "edges": [...] }` - **node** (one of): - primitive: `{ "prim": { "type":