--- id: SG-1 family: RT-SG level: core profiles: [runtime] posture: normative-target added: "1.0" changed: "1.0" source: https://flowdrop.io/spec/rules/rt-sg/sg-1 specification: FlowDrop Workflow Specification 1.0-draft licence: CC BY 4.0 --- # SG-1 — State merges field by field, and a state value is never mutated *RT-SG (Part II) · level: core · profiles: runtime · added in 1.0* ## The rule > **Normative.** This is the rule. > > 1. A state update is merged into the current state field by field: `messages` appends, `data` and `metadata` merge key by key, and every other field is replaced. > > 2. A field the update omits keeps its current value. > > 3. The merge yields a new state; the state it was applied to is not modified. ## What it means Only two fields get anything like a deep merge, and even those merge one level, not recursively without limit: `messages` appends, `data` and `metadata` merge key by key. Every other field — a loop's current node, its iteration count — is replaced outright by whatever the update carries, never combined with what was there. A field the update leaves out is not reset to a default; it keeps whatever the current state already holds. The merge never touches the state it started from. Applying an update produces a new state; the state it was applied to still reads exactly as it did before, so anything else still holding a reference to it sees no change. ## Example A state carries `{"existing": "value"}` under `data` and an empty `currentNodeId`, and receives this update: ```json title="The update applied to it" {"data": {"new": "data"}, "currentNodeId": "node_2"} ``` ```json title="What the merge yields" verdict="merged" {"data": {"existing": "value", "new": "data"}, "currentNodeId": "node_2"} ``` `data` comes out holding both keys; `currentNodeId` comes out holding only the update's value. The state the update was applied to still reads `currentNodeId` as `""` — the merge used it without changing it. ## Related rules - Names: SG-3 - Referenced by: SG-2, SG-3 --- Rule identifiers are permanent and are never renumbered. This specification carries no implementation status: each implementation publishes its own standing against these rules. Licensed CC BY 4.0.