{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://github.com/gobing-ai/spur/schemas/state-machine-workflow.schema.json",
    "title": "@gobing-ai/ts-dual-workflow-engine State-machine Workflow",
    "type": "object",
    "additionalProperties": false,
    "required": ["name", "initialState", "states", "transitions"],
    "properties": {
        "$schema": {
            "type": "string"
        },
        "kind": {
            "const": "state-machine"
        },
        "name": {
            "type": "string",
            "minLength": 1
        },
        "version": {
            "type": "string",
            "minLength": 1,
            "description": "Optional behavior-neutral identity tag (0756). Absent = unversioned; present = a non-empty opaque literal surfaced as explicit(<literal>). Not parsed, ordered, or compatibility-checked; no registry."
        },
        "description": {
            "type": "string"
        },
        "initialState": {
            "type": "string",
            "minLength": 1
        },
        "terminalStates": {
            "type": "array",
            "items": {
                "type": "string",
                "minLength": 1
            }
        },
        "failureStates": {
            "type": "array",
            "items": {
                "type": "string",
                "minLength": 1
            },
            "description": "Subset of terminalStates whose reach finalizes the run as failed. Absent \u21d2 every terminal is a success."
        },
        "iterationBound": {
            "type": "integer",
            "exclusiveMinimum": 0
        },
        "vars": {
            "type": "object",
            "propertyNames": {
                "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
            },
            "additionalProperties": {
                "type": "string"
            }
        },
        "env": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "allow": {
                    "type": "array",
                    "items": {
                        "type": "string",
                        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
                    }
                }
            }
        },
        "extensions": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "actions": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/relativeExtensionPath"
                    }
                },
                "guards": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/relativeExtensionPath"
                    }
                }
            }
        },
        "states": {
            "type": "array",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "required": ["id"],
                "properties": {
                    "id": {
                        "type": "string",
                        "minLength": 1
                    },
                    "description": {
                        "type": "string"
                    },
                    "pause": {
                        "type": "boolean",
                        "description": "When true, the engine pauses the run at this state for HITL (E3); resume with `spur workflow continue`."
                    },
                    "onEnter": {
                        "type": "array",
                        "items": {
                            "$ref": "#/$defs/action"
                        }
                    },
                    "onExit": {
                        "type": "array",
                        "items": {
                            "$ref": "#/$defs/action"
                        }
                    }
                }
            }
        },
        "transitions": {
            "type": "array",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "required": ["from", "to"],
                "properties": {
                    "from": {
                        "type": "string",
                        "minLength": 1
                    },
                    "to": {
                        "type": "string",
                        "minLength": 1
                    },
                    "description": {
                        "type": "string"
                    },
                    "trigger": {
                        "type": "string"
                    },
                    "guard": {
                        "$ref": "#/$defs/guard"
                    }
                }
            }
        }
    },
    "$defs": {
        "action": {
            "type": "object",
            "additionalProperties": false,
            "required": ["kind"],
            "properties": {
                "kind": {
                    "type": "string",
                    "minLength": 1
                },
                "options": {
                    "type": "object",
                    "additionalProperties": true
                },
                "onError": {
                    "type": "string",
                    "enum": ["fail", "continue"],
                    "description": "Per-action error handling policy: 'fail' halts the run; 'continue' logs the failure and proceeds so transition guards can route the outcome."
                }
            }
        },
        "guard": {
            "type": "object",
            "additionalProperties": false,
            "required": ["kind"],
            "properties": {
                "kind": {
                    "type": "string",
                    "minLength": 1
                },
                "options": {
                    "type": "object",
                    "additionalProperties": true
                }
            }
        },
        "relativeExtensionPath": {
            "type": "string",
            "minLength": 1,
            "description": "Relative module path; absolute paths and '..' traversal are forbidden.",
            "not": {
                "anyOf": [
                    {
                        "pattern": "^[/\\\\]"
                    },
                    {
                        "pattern": "^[A-Za-z]:[/\\\\]"
                    },
                    {
                        "pattern": "(^|[/\\\\])\\.\\.([/\\\\]|$)"
                    }
                ]
            }
        }
    }
}
