{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.cuddler.dev/standards/document-role/process/v1.0.0/questionnaire.schema.json",
  "title": "Cuddler Questionnaire",
  "type": "object",
  "additionalProperties": false,
  "examples": [
    {
      "$schema": "https://www.cuddler.dev/standards/document-role/process/v1.0.0/questionnaire.schema.json",
      "questionnaireId": "capture-context",
      "title": "Capture Context",
      "summary": "Extract the facts needed for the rest of the workflow.",
      "instructions": "# Capture Context\n\nRun this step as a structured questionnaire. Ask each question, wait for the user to complete the conversation, then evaluate the question output using the question's for-ai guidance and routing rules.",
      "format": "markdown",
      "entryQuestionId": "customer-name",
      "questions": [
        {
          "questionId": "customer-name",
          "title": "Who is the customer?",
          "answerType": "short-text",
          "outputKey": "customerName",
          "conversation": [
            {
              "messages": [
                {
                  "role": "system",
                  "content": "You are running the Capture Context workflow step."
                },
                {
                  "role": "assistant",
                  "content": "Who is the customer for this request?"
                },
                {
                  "role": "user",
                  "content": "The customer is Contoso Manufacturing."
                }
              ]
            }
          ],
          "routing": {
            "default": {
              "nextQuestionId": "requested-service"
            }
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when evaluating the completed conversation for this question.",
              "input": "",
              "output": "Return the normalized customer name captured from the completed conversation as a short text value."
            }
          ]
        },
        {
          "questionId": "requested-service",
          "title": "What service was requested?",
          "answerType": "long-text",
          "outputKey": "requestedService",
          "conversation": [
            {
              "messages": [
                {
                  "role": "system",
                  "content": "You are running the Capture Context workflow step."
                },
                {
                  "role": "assistant",
                  "content": "Describe the service or outcome the customer asked for."
                },
                {
                  "role": "user",
                  "content": "They asked for a phishing simulation and a short readiness review."
                }
              ]
            }
          ],
          "routing": {
            "default": {
              "nextQuestionId": "deadline-known"
            }
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when evaluating the completed conversation for this question.",
              "input": "",
              "output": "Summarize the requested service or outcome in one normalized long-text answer."
            }
          ]
        },
        {
          "questionId": "deadline-known",
          "title": "Is there a known deadline?",
          "answerType": "select-one",
          "outputKey": "deadlineKnown",
          "options": [
            {
              "value": "known",
              "label": "Known",
              "description": "The customer gave a concrete deadline or date."
            },
            {
              "value": "unknown",
              "label": "Unknown",
              "description": "No concrete deadline was provided."
            }
          ],
          "conversation": [
            {
              "messages": [
                {
                  "role": "system",
                  "content": "You are running the Capture Context workflow step."
                },
                {
                  "role": "assistant",
                  "content": "Did the customer give a concrete deadline? Answer known or unknown."
                },
                {
                  "role": "user",
                  "content": "known"
                }
              ]
            }
          ],
          "routing": {
            "default": {
              "nextQuestionId": "blockers"
            },
            "rules": [
              {
                "condition": {
                  "operator": "equals",
                  "value": "known"
                },
                "target": {
                  "nextQuestionId": "deadline"
                }
              },
              {
                "condition": {
                  "operator": "equals",
                  "value": "unknown"
                },
                "target": {
                  "nextQuestionId": "blockers"
                }
              }
            ]
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when evaluating the completed conversation for this question.",
              "input": "",
              "output": "Return either known or unknown based on whether the completed conversation established a concrete deadline."
            }
          ]
        },
        {
          "questionId": "deadline",
          "title": "What is the deadline?",
          "answerType": "date",
          "outputKey": "deadline",
          "conversation": [
            {
              "messages": [
                {
                  "role": "system",
                  "content": "You are running the Capture Context workflow step."
                },
                {
                  "role": "assistant",
                  "content": "What is the deadline date for this request?"
                },
                {
                  "role": "user",
                  "content": "2026-04-15"
                }
              ]
            }
          ],
          "routing": {
            "default": {
              "nextQuestionId": "blockers"
            }
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when evaluating the completed conversation for this question.",
              "input": "",
              "output": "Return the normalized deadline date in ISO 8601 full-date form when the completed conversation provides one."
            }
          ]
        },
        {
          "questionId": "blockers",
          "title": "Are there blockers or constraints?",
          "answerType": "long-text",
          "outputKey": "blockers",
          "conversation": [
            {
              "messages": [
                {
                  "role": "system",
                  "content": "You are running the Capture Context workflow step."
                },
                {
                  "role": "assistant",
                  "content": "List any blockers, constraints, or dependencies that were mentioned."
                },
                {
                  "role": "user",
                  "content": "They still need approval from legal and want the simulation scoped to one department."
                }
              ]
            }
          ],
          "routing": {
            "default": {
              "nextQuestionId": "unanswered-questions"
            }
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when evaluating the completed conversation for this question.",
              "input": "",
              "output": "Return the blockers or constraints mentioned in the completed conversation as normalized long text."
            }
          ]
        },
        {
          "questionId": "unanswered-questions",
          "title": "What is still unanswered?",
          "answerType": "long-text",
          "outputKey": "unansweredQuestions",
          "conversation": [
            {
              "messages": [
                {
                  "role": "system",
                  "content": "You are running the Capture Context workflow step."
                },
                {
                  "role": "assistant",
                  "content": "What questions are still open after this intake conversation?"
                },
                {
                  "role": "user",
                  "content": "We still need the internal sponsor, the preferred test window, and the list of approved mail domains."
                }
              ]
            }
          ],
          "routing": {
            "default": {
              "complete": true
            }
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when evaluating the completed conversation for this question.",
              "input": "",
              "output": "Return the remaining unanswered questions or missing facts that still need follow-up."
            }
          ]
        }
      ]
    }
  ],
  "required": [
    "$schema",
    "questionnaireId",
    "title",
    "entryQuestionId",
    "questions"
  ],
  "properties": {
    "$schema": {
      "type": "string",
      "const": "https://www.cuddler.dev/standards/document-role/process/v1.0.0/questionnaire.schema.json",
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Canonical application-level schema locator for a *.process.json source document."
        }
      ]
    },
    "questionnaireId": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Stable lowercase kebab-case identifier for the owning step. Semantic validation must confirm that this value matches the step id in workflow.manifest.json."
        }
      ]
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Human-readable title for the step prompt. It MAY differ from workflow.manifest.json.steps[].title when the workflow and prompt surfaces need different labels."
        }
      ]
    },
    "summary": {
      "type": "string",
      "minLength": 1,
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Optional short explanation of the step prompt's purpose."
        }
      ]
    },
    "instructions": {
      "type": "string",
      "minLength": 1,
      "contentMediaType": "text/markdown",
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Optional step-level operational notes authored as Markdown. Keep question-specific capture, evaluation, and routing rules in the typed questions rather than burying them here."
        }
      ]
    },
    "format": {
      "type": "string",
      "const": "markdown",
      "default": "markdown",
      "examples": [
        "markdown"
      ],
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Optional explicit content format for instructions. In v1 the only supported value is markdown, and omitted values are treated as markdown by convention when instructions are present."
        }
      ]
    },
    "entryQuestionId": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Stable question identifier for the first question that should be asked when this questionnaire starts."
        }
      ]
    },
    "questions": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/question"
      },
      "for-ai": [
        {
          "instruction": "Use this guidance when preparing a valid value for this schema node.",
          "input": "",
          "output": "Ordered authored question definitions for this prompt. Each question declares its answer type, conversation as a JSON array of JSONL-style record objects, output evaluation guidance, and routing rules."
        }
      ]
    }
  },
  "$defs": {
    "forAiEntry": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "instruction",
        "input",
        "output"
      ],
      "properties": {
        "instruction": {
          "type": "string",
          "minLength": 1
        },
        "input": {
          "type": "string"
        },
        "output": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "message": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "role",
        "content"
      ],
      "properties": {
        "role": {
          "type": "string",
          "enum": [
            "system",
            "user",
            "assistant"
          ],
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Role of the message within the JSONL-style conversation record."
            }
          ]
        },
        "content": {
          "type": "string",
          "minLength": 1,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Message content for the JSONL-style conversation record."
            }
          ]
        }
      }
    },
    "conversationRecord": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "messages"
      ],
      "properties": {
        "messages": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/message"
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "One JSONL-style conversation transcript for the question, represented as one record object inside the JSON conversation array."
            }
          ]
        }
      }
    },
    "answerOption": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "value",
        "label"
      ],
      "properties": {
        "value": {
          "type": "string",
          "minLength": 1,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Stable machine value for one select-type answer option."
            }
          ]
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Human-readable label for one select-type answer option."
            }
          ]
        },
        "description": {
          "type": "string",
          "minLength": 1,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Optional short explanation of when to use the option."
            }
          ]
        }
      }
    },
    "routeCondition": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "operator"
      ],
      "properties": {
        "operator": {
          "type": "string",
          "enum": [
            "always",
            "equals",
            "not-equals",
            "includes-any",
            "includes-all",
            "greater-than",
            "greater-than-or-equal",
            "less-than",
            "less-than-or-equal",
            "is-empty",
            "is-not-empty"
          ],
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Deterministic operator used to evaluate the derived question output when selecting the next question."
            }
          ]
        },
        "value": {
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "array",
              "minItems": 1,
              "items": {
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  }
                ]
              }
            }
          ],
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Comparison value used by the routing condition when the operator requires one."
            }
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "operator": {
                "enum": [
                  "always",
                  "is-empty",
                  "is-not-empty"
                ]
              }
            },
            "required": [
              "operator"
            ]
          },
          "then": {
            "not": {
              "required": [
                "value"
              ]
            }
          },
          "else": {
            "required": [
              "value"
            ]
          }
        }
      ]
    },
    "routingTarget": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "nextQuestionId": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Stable identifier of the next question to ask when this route is selected."
            }
          ]
        },
        "complete": {
          "type": "boolean",
          "const": true,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Terminal route marker meaning the questionnaire is complete after this question."
            }
          ]
        }
      },
      "oneOf": [
        {
          "required": [
            "nextQuestionId"
          ]
        },
        {
          "required": [
            "complete"
          ]
        }
      ]
    },
    "routingRule": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "condition",
        "target"
      ],
      "properties": {
        "condition": {
          "$ref": "#/$defs/routeCondition"
        },
        "target": {
          "$ref": "#/$defs/routingTarget"
        }
      }
    },
    "routing": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "default"
      ],
      "properties": {
        "default": {
          "$ref": "#/$defs/routingTarget"
        },
        "rules": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/routingRule"
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Ordered routing rules evaluated before the default route when selecting the next question."
            }
          ]
        }
      }
    },
    "question": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "questionId",
        "title",
        "answerType",
        "outputKey",
        "conversation",
        "routing",
        "for-ai"
      ],
      "properties": {
        "questionId": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Stable lowercase kebab-case identifier for this question."
            }
          ]
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Human-readable title or label for this question."
            }
          ]
        },
        "summary": {
          "type": "string",
          "minLength": 1,
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Optional short explanation of what this question captures."
            }
          ]
        },
        "answerType": {
          "type": "string",
          "enum": [
            "select-one",
            "select-many",
            "number",
            "short-text",
            "long-text",
            "date",
            "percentage"
          ],
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Type of answer that the completed conversation should produce for this question. Allowed values are select-one, select-many, number, short-text, long-text, date, and percentage."
            }
          ]
        },
        "options": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/answerOption"
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Explicit allowed answer options for select-one and select-many questions."
            }
          ]
        },
        "outputKey": {
          "type": "string",
          "pattern": "^[A-Za-z][A-Za-z0-9]*(?:[._-][A-Za-z0-9]+)*$",
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Stable key used to store the evaluated question output in downstream process context."
            }
          ]
        },
        "conversation": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/conversationRecord"
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "A JSON array containing one or more JSONL-style conversation record objects that show how the question is asked and what a completed conversation transcript looks like."
            }
          ]
        },
        "routing": {
          "$ref": "#/$defs/routing"
        },
        "for-ai": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/forAiEntry"
          },
          "for-ai": [
            {
              "instruction": "Use this guidance when preparing a valid value for this schema node.",
              "input": "",
              "output": "Question-level Alpaca guidance that tells the AI how to evaluate the completed conversation into the question output."
            }
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "answerType": {
                "enum": [
                  "select-one",
                  "select-many"
                ]
              }
            },
            "required": [
              "answerType"
            ]
          },
          "then": {
            "required": [
              "options"
            ]
          }
        }
      ]
    }
  },
  "for-ai": [
    {
      "instruction": "Use this guidance when preparing a valid value for this schema node.",
      "input": "",
      "output": "Schema for the canonical *.process.json questionnaire document used by one Cuddler workflow step. In v1 this document is a typed question graph with conversation stored as a JSON array of JSONL-style record objects, output evaluation guidance, and deterministic routing."
    }
  ]
}
