""" Questionnaire Schema Defines interactive questionnaires for completing infrastructure specifications. Uses conditional logic and decision trees to ask only relevant questions. Features: - Conditional questions (only ask if certain conditions met) - Smart defaults from AI suggestions - Validation rules per question - Decision tree navigation - Multi-select and single-select support """ import regex # ============================================================================ # Expression Evaluation # ============================================================================ schema Expression: """ Boolean expression for conditional logic Examples: - "deployment_mode == 'HA'" - "has_database and deployment_mode in ['prod', 'staging']" - "postgres_version >= '15.0'" """ expr: str check: len(expr) > 0, "Expression cannot be empty" # ============================================================================ # Question Types and Validation # ============================================================================ schema ValidationRule: """ Validation rule for question answers """ required: bool = False pattern?: str # Regex pattern for validation min_value?: int max_value?: int choices?: [str] # Valid choices (for select/multiselect) custom_validator?: str # Name of custom validator function schema Question: """ Single question in questionnaire """ id: str # Unique identifier kind: "text" | "select" | "multiselect" | "confirm" | "number" message: str # Question text help?: str # Help text/description default?: str # Default value # Conditional display when?: Expression # Only ask if this expression is true depends_on?: [str] # Other question IDs this depends on # Validation validation: ValidationRule = {} # AI assistance ai_suggest: bool = False # Enable AI suggestions? ai_context?: str # Context for AI suggestion check: len(id) > 0, "Question ID required" len(message) > 0, "Message required" # Validate choices if kind is select/multiselect kind not in ["select", "multiselect"] or validation.choices != None, \ "Choices required for select/multiselect questions" # ============================================================================ # Decision Tree Nodes # ============================================================================ schema DecisionNode: """ Single node in decision tree """ question_id: str # Which question to ask next_nodes?: {str: str} # answer -> next_question_id default_next?: str # Default next question if no match schema DecisionTree: """ Decision tree for intelligent questionnaire flow """ root: str # Starting question ID nodes: {str: DecisionNode} # ID -> Node mapping check: len(root) > 0, "Root question required" len(nodes) > 0, "At least one node required" # ============================================================================ # Metadata # ============================================================================ schema Metadata: """ Questionnaire metadata """ name: str version: str description?: str check: len(name) > 0, "Name required" len(version) > 0, "Version required" # ============================================================================ # Complete Questionnaire # ============================================================================ schema Questionnaire: """ Complete questionnaire with questions and decision tree Example: postgres_questionnaire = Questionnaire { metadata: { name: "PostgreSQL Setup" version: "1.0.0" } questions: [ Question { id: "pg_version" kind: "text" message: "PostgreSQL version?" default: "16.0" validation: { pattern: r"^\d+\.\d+$" } ai_suggest: True ai_context: "Suggest latest stable PostgreSQL" } Question { id: "enable_backup" kind: "confirm" message: "Enable automated backups?" default: "true" when: Expression { expr: "deployment_mode in ['prod', 'staging']" } } ] decision_tree: { root: "pg_version" nodes: { "pg_version": { question_id: "pg_version" next_nodes: { "*": "enable_backup" } } "enable_backup": { question_id: "enable_backup" next_nodes: { "true": "backup_strategy", "false": "END" } } } } } """ metadata: Metadata questions: [Question] = [] decision_tree: DecisionTree check: len(questions) > 0, "At least one question required" # ============================================================================ # Question Answer # ============================================================================ schema Answer: """ User answer to a question """ question_id: str value: str | bool | int # Answer value timestamp: str # ISO 8601 when answered schema QuestionnaireResponse: """ Complete questionnaire response """ questionnaire_name: str questionnaire_version: str answers: [Answer] = [] completed: bool = False completion_time?: str # ISO 8601