C-001 임상 검토 게이트 보강
This commit is contained in:
parent
391fb9f4d0
commit
6988280b30
18 changed files with 1896 additions and 67 deletions
214
data/clinical/crisis-protocol-validation.schema.json
Normal file
214
data/clinical/crisis-protocol-validation.schema.json
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "vignette.clinical_crisis_review.v1",
|
||||
"title": "Vignette P1 crisis protocol external clinical review contract",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"protocol_id",
|
||||
"version",
|
||||
"scope",
|
||||
"technical_status",
|
||||
"clinical_status",
|
||||
"external_review_boundary",
|
||||
"review_case_set",
|
||||
"review_case_set_id",
|
||||
"review_case_set_version",
|
||||
"sources",
|
||||
"review_sequence",
|
||||
"technical_gates",
|
||||
"approval"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": { "const": "vignette.clinical_crisis_review.v1" },
|
||||
"protocol_id": { "const": "p1-suicide-ideation-response" },
|
||||
"version": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}\\.[0-9]+$" },
|
||||
"scope": { "type": "string", "minLength": 1 },
|
||||
"technical_status": { "const": "verified" },
|
||||
"clinical_status": {
|
||||
"enum": ["pending_external_review", "approved", "conditional", "rejected"]
|
||||
},
|
||||
"external_review_boundary": {
|
||||
"const": "공식 근거와 자동 검사는 기술 안전 범위만 확인하며 외부 임상 검토와 승인을 대신하지 않는다."
|
||||
},
|
||||
"review_case_set": { "const": "data/clinical/p1-crisis-review-cases.json" },
|
||||
"review_case_set_id": { "const": "p1-crisis-review-cases" },
|
||||
"review_case_set_version": { "type": "string", "minLength": 1 },
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"minItems": 4,
|
||||
"uniqueItems": true,
|
||||
"items": { "$ref": "#/$defs/source" }
|
||||
},
|
||||
"review_sequence": {
|
||||
"type": "array",
|
||||
"minItems": 6,
|
||||
"items": { "type": "string", "minLength": 1 }
|
||||
},
|
||||
"technical_gates": {
|
||||
"type": "array",
|
||||
"minItems": 6,
|
||||
"items": { "type": "string", "minLength": 1 }
|
||||
},
|
||||
"approval": { "$ref": "#/$defs/approval" }
|
||||
},
|
||||
"$defs": {
|
||||
"nullableString": {
|
||||
"anyOf": [
|
||||
{ "type": "null" },
|
||||
{ "type": "string", "minLength": 1 }
|
||||
]
|
||||
},
|
||||
"nullableSha256": {
|
||||
"anyOf": [
|
||||
{ "type": "null" },
|
||||
{ "type": "string", "pattern": "^[0-9a-f]{64}$" }
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["source_id", "authority", "title", "url", "applied_to"],
|
||||
"properties": {
|
||||
"source_id": { "type": "string", "minLength": 1 },
|
||||
"authority": { "type": "string", "minLength": 1 },
|
||||
"title": { "type": "string", "minLength": 1 },
|
||||
"url": { "type": "string", "pattern": "^https://" },
|
||||
"applied_to": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "type": "string", "minLength": 1 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"approval": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"reviewer",
|
||||
"organization",
|
||||
"reviewed_at",
|
||||
"decision",
|
||||
"notes",
|
||||
"evidence_ref",
|
||||
"evidence_sha256",
|
||||
"reviewed_protocol_version",
|
||||
"reviewed_case_set_sha256"
|
||||
],
|
||||
"properties": {
|
||||
"reviewer": { "$ref": "#/$defs/nullableString" },
|
||||
"organization": { "$ref": "#/$defs/nullableString" },
|
||||
"reviewed_at": {
|
||||
"anyOf": [
|
||||
{ "type": "null" },
|
||||
{ "type": "string", "format": "date" }
|
||||
]
|
||||
},
|
||||
"decision": {
|
||||
"anyOf": [
|
||||
{ "type": "null" },
|
||||
{ "enum": ["approved", "conditional", "rejected"] }
|
||||
]
|
||||
},
|
||||
"notes": { "$ref": "#/$defs/nullableString" },
|
||||
"evidence_ref": { "$ref": "#/$defs/nullableString" },
|
||||
"evidence_sha256": { "$ref": "#/$defs/nullableSha256" },
|
||||
"reviewed_protocol_version": { "$ref": "#/$defs/nullableString" },
|
||||
"reviewed_case_set_sha256": { "$ref": "#/$defs/nullableSha256" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": { "clinical_status": { "const": "pending_external_review" } },
|
||||
"required": ["clinical_status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"approval": {
|
||||
"properties": {
|
||||
"reviewer": { "type": "null" },
|
||||
"organization": { "type": "null" },
|
||||
"reviewed_at": { "type": "null" },
|
||||
"decision": { "type": "null" },
|
||||
"notes": { "type": "null" },
|
||||
"evidence_ref": { "type": "null" },
|
||||
"evidence_sha256": { "type": "null" },
|
||||
"reviewed_protocol_version": { "type": "null" },
|
||||
"reviewed_case_set_sha256": { "type": "null" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"clinical_status": { "enum": ["approved", "conditional", "rejected"] }
|
||||
},
|
||||
"required": ["clinical_status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"approval": {
|
||||
"properties": {
|
||||
"reviewer": { "type": "string", "minLength": 1 },
|
||||
"organization": { "type": "string", "minLength": 1 },
|
||||
"reviewed_at": { "type": "string", "format": "date" },
|
||||
"decision": { "enum": ["approved", "conditional", "rejected"] },
|
||||
"evidence_ref": { "type": "string", "minLength": 1 },
|
||||
"evidence_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
||||
"reviewed_protocol_version": { "type": "string", "minLength": 1 },
|
||||
"reviewed_case_set_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "clinical_status": { "const": "approved" } },
|
||||
"required": ["clinical_status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"approval": { "properties": { "decision": { "const": "approved" } } }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "clinical_status": { "const": "conditional" } },
|
||||
"required": ["clinical_status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"approval": {
|
||||
"properties": {
|
||||
"decision": { "const": "conditional" },
|
||||
"notes": { "type": "string", "minLength": 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "clinical_status": { "const": "rejected" } },
|
||||
"required": ["clinical_status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"approval": {
|
||||
"properties": {
|
||||
"decision": { "const": "rejected" },
|
||||
"notes": { "type": "string", "minLength": 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue