{
 "use_case": "sar-narrative-desk",
 "title": "SAR narrative desk: an investigator draft with a wrong total, a shifted date and an invented wire",
 "about": "A synthetic structuring case (a transactions CSV, KYC and alert fields, investigator notes) and an investigator draft with citations, in which three things were planted: a total $1,000 too high, a date moved by two days, and a $25,000 wire that is not in the ledger. Check mode makes no drafting call: every number is recomputed from the cited rows and each sentence is judged against what it cites. The three planted sentences must be held, the right figures named, the screen must find structuring, the filing copy must drop the held sentences and the citations, and the signed report must verify and catch a changed status.",
 "licence": "Synthetic: every person, account, business and the bank (Example Community Bank) are fictional, generated by decosa_api/verticals/sar/synth.py. Part of decosa-api, AGPL-3.0-or-later.",
 "inputs": [
  {
   "file": "inputs/transactions.csv",
   "what": "The ledger: id, date, type, direction, amount, channel, location, counterparty, memo."
  },
  {
   "file": "inputs/kyc.json",
   "what": "Customer-profile fields, cited as K.<name>."
  },
  {
   "file": "inputs/alert.json",
   "what": "Alert and case fields, cited as A.<name>."
  },
  {
   "file": "inputs/notes.txt",
   "what": "Investigator notes; each sentence is cited as N1, N2 ..."
  },
  {
   "file": "inputs/draft.txt",
   "what": "The investigator draft to check, each sentence ending with [T3, K.name]-style citations."
  }
 ],
 "steps": [
  {
   "id": "check",
   "method": "POST",
   "path": "/sar/draft",
   "body": {
    "transactions": {
     "$file": "inputs/transactions.csv"
    },
    "kyc": {
     "$file": "inputs/kyc.json"
    },
    "alert": {
     "$file": "inputs/alert.json"
    },
    "notes": {
     "$file": "inputs/notes.txt"
    },
    "mode": "check",
    "narrative": {
     "$file": "inputs/draft.txt"
    },
    "synthetic": true
   }
  },
  {
   "id": "verify",
   "method": "POST",
   "path": "/sar/verify",
   "auth": false,
   "body": {
    "report": {
     "$ref": "check.report"
    },
    "narrative_md": {
     "$ref": "check.narrative_md"
    },
    "narrative_plain": {
     "$ref": "check.narrative_plain"
    },
    "transactions": {
     "$file": "inputs/transactions.csv"
    }
   }
  },
  {
   "id": "tampered",
   "method": "POST",
   "path": "/sar/verify",
   "auth": false,
   "body": {
    "report": {
     "$ref": "check.report"
    }
   },
   "tamper": {
    "at": "report.status",
    "set": "all_checked"
   }
  }
 ],
 "checks": [
  {
   "says": "the run holds sentences back",
   "path": "check.status",
   "equals": "held"
  },
  {
   "says": "the wrong total is held as a number mismatch",
   "path": "check.sentences[sid=what.1][0].reasons",
   "equals": [
    "number_mismatch"
   ]
  },
  {
   "says": "the held total names the figure the rows give",
   "path": "check.sentences[sid=what.1][0].numeric.mentions[status=mismatch][0].detail",
   "contains": "$111,789.00"
  },
  {
   "says": "the shifted date is held as a number mismatch",
   "path": "check.sentences[sid=when.1][0].reasons",
   "equals": [
    "number_mismatch"
   ]
  },
  {
   "says": "the invented wire is held",
   "path": "check.sentences[sid=when.2][0].status",
   "equals": "held"
  },
  {
   "says": "the invented wire is named as not in the case file, not as a number mismatch",
   "path": "check.sentences[sid=when.2][0].reasons",
   "equals": [
    "not_in_source"
   ]
  },
  {
   "says": "two numbers do not match and one is not in the case file at all",
   "path": "check.numbers.mismatch",
   "equals": 2
  },
  {
   "says": "the invented amount is counted as not found",
   "path": "check.numbers.unverified",
   "equals": 1
  },
  {
   "says": "the screen finds structuring",
   "path": "check.screen.indicated",
   "contains": "structuring"
  },
  {
   "says": "the filing copy drops the invented wire",
   "path": "check.narrative_plain",
   "not_contains": "Mexico"
  },
  {
   "says": "the filing copy has no citation brackets",
   "path": "check.narrative_plain",
   "not_contains": "["
  },
  {
   "says": "the signed report verifies",
   "path": "verify.valid_signature",
   "equals": true
  },
  {
   "says": "the report matches the ledger it was run on",
   "path": "verify.ledger_matches",
   "equals": true
  },
  {
   "says": "a report with its status changed to all_checked no longer verifies",
   "path": "tampered.valid_signature",
   "equals": false
  },
  {
   "says": "every model call has a signed receipt",
   "receipts": "signed",
   "min": 5
  }
 ]
}
