{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://inferenslab.org/research-protocol-schema.json",
  "title": "InferensLab versioned research protocol",
  "description": "Public contract for a versioned InferensLab protocol. Conformance describes a preregistered method, not execution or results.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "$schema",
    "schema_version",
    "domain",
    "id",
    "order",
    "version",
    "program_id",
    "protocol_status",
    "execution_status",
    "results_status",
    "registered_on",
    "updated",
    "behavioral_results_published",
    "routes",
    "artifact",
    "canonical_sources",
    "dependencies",
    "study_design",
    "freeze_requirements",
    "metrics",
    "decision_rules",
    "validity_threats",
    "publication_requirements",
    "fr",
    "en"
  ],
  "properties": {
    "$schema": {
      "const": "https://inferenslab.org/research-protocol-schema.json"
    },
    "schema_version": {
      "const": "1.0.0"
    },
    "domain": {
      "const": "inferenslab.org"
    },
    "id": {
      "$ref": "#/$defs/slug"
    },
    "order": {
      "type": "integer",
      "minimum": 1
    },
    "version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
    },
    "program_id": {
      "$ref": "#/$defs/slug"
    },
    "protocol_status": {
      "enum": [
        "preregistered",
        "superseded",
        "withdrawn"
      ]
    },
    "execution_status": {
      "enum": [
        "not-started",
        "running",
        "completed",
        "halted"
      ]
    },
    "results_status": {
      "enum": [
        "none-published",
        "results-published",
        "null-results-published",
        "non-identifiable-published"
      ]
    },
    "registered_on": {
      "$ref": "#/$defs/date"
    },
    "updated": {
      "$ref": "#/$defs/date"
    },
    "behavioral_results_published": {
      "type": "boolean"
    },
    "routes": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "fr",
        "en"
      ],
      "properties": {
        "fr": {
          "type": "string",
          "pattern": "^/fr/protocoles/[a-z0-9-]+/$"
        },
        "en": {
          "type": "string",
          "pattern": "^/en/protocols/[a-z0-9-]+/$"
        }
      }
    },
    "artifact": {
      "type": "string",
      "pattern": "^/protocols/[a-z0-9-]+/[0-9]+\\.[0-9]+\\.[0-9]+\\.json$"
    },
    "canonical_sources": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "fr",
        "en"
      ],
      "properties": {
        "fr": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://gautierdorval\\.com/"
        },
        "en": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://gautierdorval\\.com/en/"
        }
      }
    },
    "dependencies": {
      "type": "array",
      "minItems": 4,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "pattern": "^/"
      }
    },
    "study_design": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "study_type",
        "pilot_scope",
        "unit_of_analysis",
        "comparison_dimensions",
        "sampling",
        "execution_sequence"
      ],
      "properties": {
        "study_type": {
          "$ref": "#/$defs/slug"
        },
        "pilot_scope": {
          "const": "descriptive-pilot-no-population-inference"
        },
        "unit_of_analysis": {
          "$ref": "#/$defs/localizedText"
        },
        "comparison_dimensions": {
          "type": "array",
          "minItems": 2,
          "items": {
            "$ref": "#/$defs/localizedItem"
          }
        },
        "sampling": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "entity_selection",
            "entity_count",
            "query_family_count",
            "queries_per_family",
            "model_panel_count",
            "access_mode_count",
            "planned_condition_count",
            "repetitions_per_planned_cell",
            "planned_response_units",
            "collection_window_days",
            "stopping_rule",
            "judge_count",
            "agreement_metric",
            "agreement_threshold",
            "disagreement_resolution",
            "agreement_failure_rule",
            "model_panel_snapshot_required",
            "access_modes_recorded"
          ],
          "properties": {
            "entity_selection": {
              "$ref": "#/$defs/localizedText"
            },
            "entity_count": {
              "type": "integer",
              "minimum": 2
            },
            "query_family_count": {
              "type": "integer",
              "minimum": 3
            },
            "queries_per_family": {
              "type": "integer",
              "minimum": 1
            },
            "model_panel_count": {
              "type": "integer",
              "minimum": 2
            },
            "access_mode_count": {
              "type": "integer",
              "minimum": 1
            },
            "planned_condition_count": {
              "type": "integer",
              "minimum": 1
            },
            "repetitions_per_planned_cell": {
              "type": "integer",
              "minimum": 2
            },
            "planned_response_units": {
              "type": "integer",
              "minimum": 1
            },
            "collection_window_days": {
              "type": "integer",
              "minimum": 1
            },
            "stopping_rule": {
              "$ref": "#/$defs/localizedText"
            },
            "judge_count": {
              "type": "integer",
              "minimum": 2
            },
            "agreement_metric": {
              "$ref": "#/$defs/slug"
            },
            "agreement_threshold": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "disagreement_resolution": {
              "$ref": "#/$defs/localizedText"
            },
            "agreement_failure_rule": {
              "$ref": "#/$defs/localizedText"
            },
            "model_panel_snapshot_required": {
              "const": true
            },
            "access_modes_recorded": {
              "const": true
            }
          }
        },
        "execution_sequence": {
          "type": "array",
          "minItems": 4,
          "items": {
            "$ref": "#/$defs/localizedItem"
          }
        }
      }
    },
    "freeze_requirements": {
      "type": "array",
      "minItems": 6,
      "uniqueItems": true,
      "items": {
        "$ref": "#/$defs/slug"
      }
    },
    "metrics": {
      "type": "array",
      "minItems": 4,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "scale",
          "direction",
          "fr",
          "en"
        ],
        "properties": {
          "id": {
            "$ref": "#/$defs/slug"
          },
          "scale": {
            "$ref": "#/$defs/slug"
          },
          "direction": {
            "enum": [
              "higher-is-better",
              "lower-is-better",
              "context-only"
            ]
          },
          "fr": {
            "type": "string",
            "minLength": 20
          },
          "en": {
            "type": "string",
            "minLength": 20
          }
        }
      }
    },
    "decision_rules": {
      "type": "array",
      "minItems": 4,
      "items": {
        "$ref": "#/$defs/localizedItem"
      }
    },
    "validity_threats": {
      "type": "array",
      "minItems": 3,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "fr",
          "en",
          "mitigation"
        ],
        "properties": {
          "id": {
            "$ref": "#/$defs/slug"
          },
          "fr": {
            "type": "string",
            "minLength": 20
          },
          "en": {
            "type": "string",
            "minLength": 20
          },
          "mitigation": {
            "$ref": "#/$defs/localizedText"
          }
        }
      }
    },
    "publication_requirements": {
      "type": "array",
      "minItems": 8,
      "uniqueItems": true,
      "items": {
        "$ref": "#/$defs/slug"
      }
    },
    "fr": {
      "$ref": "#/$defs/localizedProtocol"
    },
    "en": {
      "$ref": "#/$defs/localizedProtocol"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "results_status": {
            "const": "none-published"
          }
        },
        "required": [
          "results_status"
        ]
      },
      "then": {
        "properties": {
          "behavioral_results_published": {
            "const": false
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "results_status": {
            "enum": [
              "results-published",
              "null-results-published",
              "non-identifiable-published"
            ]
          }
        },
        "required": [
          "results_status"
        ]
      },
      "then": {
        "properties": {
          "behavioral_results_published": {
            "const": true
          }
        }
      }
    }
  ],
  "$defs": {
    "slug": {
      "type": "string",
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
    },
    "date": {
      "type": "string",
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
    },
    "localizedText": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "fr",
        "en"
      ],
      "properties": {
        "fr": {
          "type": "string",
          "minLength": 20
        },
        "en": {
          "type": "string",
          "minLength": 20
        }
      }
    },
    "localizedItem": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "fr",
        "en"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/slug"
        },
        "fr": {
          "type": "string",
          "minLength": 20
        },
        "en": {
          "type": "string",
          "minLength": 20
        }
      }
    },
    "localizedProtocol": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "title",
        "program_title",
        "meta_description",
        "summary",
        "research_question",
        "design_summary",
        "evidence_state",
        "boundaries"
      ],
      "properties": {
        "title": {
          "type": "string",
          "minLength": 10
        },
        "program_title": {
          "type": "string",
          "minLength": 5
        },
        "meta_description": {
          "type": "string",
          "minLength": 55,
          "maxLength": 170
        },
        "summary": {
          "type": "string",
          "minLength": 60
        },
        "research_question": {
          "type": "string",
          "minLength": 40
        },
        "design_summary": {
          "type": "string",
          "minLength": 60
        },
        "evidence_state": {
          "type": "string",
          "minLength": 40
        },
        "boundaries": {
          "type": "array",
          "minItems": 3,
          "items": {
            "type": "string",
            "minLength": 20
          }
        }
      }
    }
  }
}
