{
 "use_case": "typed-judgment",
 "title": "Typed judgment: route a support ticket with four typed questions",
 "about": "A fictional customer's support ticket: a kettle arrived cracked, they want their money back before Friday, and delivery was charged twice. Four typed questions (yes/no, choice, score, labels) must come back with answers and probabilities (refund yes, the returns team, urgency this week or sooner, tags damaged and double-charge), and the signed record must verify against the ticket and catch a changed answer.",
 "licence": "Fictional: the customer, the shop and the order are made up for Decosa. Part of decosa-api, AGPL-3.0-or-later.",
 "inputs": [
  {
   "file": "inputs/ticket.txt",
   "what": "The context to judge: any text (a ticket, a page, a screen state)."
  },
  {
   "file": "inputs/questions.json",
   "what": "The typed questions: {key: {type: yesno | choice | score | labels, question, options | levels | labels}}."
  }
 ],
 "steps": [
  {
   "id": "judge",
   "method": "POST",
   "path": "/judgment/judge",
   "body": {
    "context": {
     "$file": "inputs/ticket.txt"
    },
    "questions": {
     "$file": "inputs/questions.json"
    },
    "method": "single",
    "stream": false
   }
  },
  {
   "id": "verify",
   "method": "POST",
   "path": "/judgment/verify",
   "auth": false,
   "body": {
    "record": {
     "$ref": "judge.record"
    },
    "context": {
     "$file": "inputs/ticket.txt"
    }
   }
  },
  {
   "id": "tampered",
   "method": "POST",
   "path": "/judgment/verify",
   "auth": false,
   "body": {
    "record": {
     "$ref": "judge.record"
    }
   },
   "tamper": {
    "at": "record.questions[id=refund].answer",
    "set": "no"
   }
  }
 ],
 "checks": [
  {
   "says": "the customer asks for a refund: yes",
   "path": "judge.answers.refund.answer",
   "equals": "yes"
  },
  {
   "says": "the refund answer carries a probability of at least 0.8",
   "path": "judge.answers.refund.probability",
   "min": 0.8
  },
  {
   "says": "the returns team handles it first",
   "path": "judge.answers.team.answer",
   "equals": "returns"
  },
  {
   "says": "urgency is 'this week' or 'within two days'",
   "path": "judge.answers.urgency.answer",
   "in": [
    2,
    3
   ]
  },
  {
   "says": "the tags include damaged and double-charge",
   "path": "judge.answers.tags.answer",
   "all_in": [
    "damaged",
    "double-charge",
    "angry"
   ],
   "contains": [
    "damaged",
    "double-charge"
   ]
  },
  {
   "says": "every tag has its own probability",
   "path": "judge.answers.tags.probabilities",
   "has_keys": [
    "damaged",
    "double-charge",
    "late",
    "angry"
   ]
  },
  {
   "says": "the signed record verifies",
   "path": "verify.valid_signature",
   "equals": true
  },
  {
   "says": "the record matches the ticket",
   "path": "verify.context_matches",
   "equals": true
  },
  {
   "says": "a record with the refund answer changed no longer verifies",
   "path": "tampered.valid_signature",
   "equals": false
  },
  {
   "says": "every model call has a signed receipt",
   "receipts": "signed",
   "min": 4
  }
 ]
}
