padmapriyagosakan commited on
Commit
eb62efb
·
1 Parent(s): d1fa6bd

fix: restructure openenv.yaml tasks: from dict to flat list so platform grader check finds 30/30 tasks

Browse files

ROOT CAUSE: competition platform does 'for t in yaml[tasks]' expecting a list.
Our tasks: was a dict with count/difficulties/definitions keys, so iteration
returned key strings (not task objects) -> 0 tasks found with grader -> FAIL.

FIX: tasks: is now a flat list of 30 task objects (each with task_id, difficulty,
grader). Metadata moved to task_count/task_difficulties/task_difficulty_weights
top-level keys. Platform now finds 30/30 tasks with grader.

Verified: 90/90 validate.py checks pass, openenv validate passes.

Files changed (2) hide show
  1. _test_grader_fix.py +65 -0
  2. openenv.yaml +428 -426
_test_grader_fix.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test grader property and grade_episode changes."""
2
+ import sys
3
+ sys.path.insert(0, '.')
4
+ from payops_env.tasks import TASKS
5
+ from payops_env.grader import grade_episode
6
+
7
+ # Test 1: task.grader property
8
+ print('=== Test 1: task.grader property ===')
9
+ missing = [t.task_id for t in TASKS if not hasattr(t, 'grader')]
10
+ if missing:
11
+ print(f'FAIL: tasks missing grader property: {missing}')
12
+ sys.exit(1)
13
+ else:
14
+ print(f'PASS: all {len(TASKS)} tasks have grader property')
15
+
16
+ # Spot-check grader content
17
+ t0 = TASKS[0]
18
+ g = t0.grader
19
+ assert 'type' in g and g['type'] == 'action_match', f'grader bad: {g}'
20
+ assert 'correct_action' in g
21
+ assert 'partial_credit' in g
22
+ assert 'requires_investigation' in g
23
+ assert 'regulatory_action' in g
24
+ assert 'key_flags' in g
25
+ print(f'PASS: grader property has required keys: {sorted(g.keys())}')
26
+
27
+ # Test 2: grade_episode per_task_rewards have grader key
28
+ print()
29
+ print('=== Test 2: grade_episode per_task_rewards have grader key ===')
30
+ sample_tasks = list(TASKS[:5])
31
+ sample_actions = [t.correct_action for t in sample_tasks]
32
+ result = grade_episode(sample_actions, sample_tasks)
33
+ missing_gr = [pt['task_id'] for pt in result.per_task_rewards if 'grader' not in pt]
34
+ if missing_gr:
35
+ print(f'FAIL: per_task_rewards entries missing grader key: {missing_gr}')
36
+ sys.exit(1)
37
+ else:
38
+ print(f'PASS: all {len(result.per_task_rewards)} per_task_rewards entries have grader key')
39
+ print(f'PASS: score={result.normalised_score}')
40
+
41
+ # Test all 30 tasks
42
+ result_all = grade_episode([t.correct_action for t in TASKS], list(TASKS))
43
+ missing_all = [pt['task_id'] for pt in result_all.per_task_rewards if 'grader' not in pt]
44
+ assert not missing_all, f'FAIL: {missing_all}'
45
+ print(f'PASS: all 30 tasks graded with grader key in per_task_rewards')
46
+ print(f'PASS: score={result_all.normalised_score}')
47
+
48
+ # Test 3: openenv.yaml has task definitions with grader
49
+ print()
50
+ print('=== Test 3: openenv.yaml task definitions ===')
51
+ import yaml
52
+ with open('openenv.yaml') as f:
53
+ d = yaml.safe_load(f)
54
+ # tasks: is now a flat list (changed from dict+definitions to list for platform compat)
55
+ tasks_section = d.get('tasks', [])
56
+ if isinstance(tasks_section, list):
57
+ defs = tasks_section
58
+ else:
59
+ defs = tasks_section.get('definitions', [])
60
+ tasks_with_grader = [t for t in defs if 'grader' in t]
61
+ print(f'PASS: openenv.yaml has {len(defs)} task definitions, {len(tasks_with_grader)} with grader')
62
+ assert len(tasks_with_grader) >= 3, f'FAIL: only {len(tasks_with_grader)} tasks with grader'
63
+
64
+ print()
65
+ print('ALL TESTS PASSED')
openenv.yaml CHANGED
@@ -112,433 +112,435 @@ observation_space:
112
  - recent_decisions
113
  - network_graph
114
 
115
- # ── Tasks ─────────────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  tasks:
117
- count: 30
118
- difficulties:
119
- - easy
120
- - medium
121
- - hard
122
- - critical
123
- difficulty_weights:
124
- easy: 1.0
125
- medium: 1.2
126
- hard: 1.5
127
- critical: 2.0
128
- definitions:
129
- - task_id: EASY-001
130
- difficulty: easy
131
- grader:
132
- type: action_match
133
- correct_action: approve
134
- partial_credit: {}
135
- requires_investigation: []
136
- regulatory_action: false
137
- key_flags: []
138
- - task_id: EASY-002
139
- difficulty: easy
140
- grader:
141
- type: action_match
142
- correct_action: reject
143
- partial_credit:
144
- escalate: 0.4
145
- requires_investigation: []
146
- regulatory_action: false
147
- key_flags:
148
- - sanctioned_country
149
- - unknown_sender
150
- - task_id: EASY-003
151
- difficulty: easy
152
- grader:
153
- type: action_match
154
- correct_action: approve
155
- partial_credit: {}
156
- requires_investigation: []
157
- regulatory_action: false
158
- key_flags: []
159
- - task_id: EASY-004
160
- difficulty: easy
161
- grader:
162
- type: action_match
163
- correct_action: flag
164
- partial_credit:
165
- escalate: 0.6
166
- hold: 0.5
167
- requires_investigation: []
168
- regulatory_action: false
169
- key_flags:
170
- - velocity_breach
171
- - task_id: EASY-005
172
- difficulty: easy
173
- grader:
174
- type: action_match
175
- correct_action: approve
176
- partial_credit: {}
177
- requires_investigation: []
178
- regulatory_action: false
179
- key_flags: []
180
- - task_id: EASY-006
181
- difficulty: easy
182
- grader:
183
- type: action_match
184
- correct_action: flag
185
- partial_credit:
186
- hold: 0.6
187
- requires_investigation: []
188
- regulatory_action: false
189
- key_flags:
190
- - duplicate_transaction
191
- - task_id: MED-001
192
- difficulty: medium
193
- grader:
194
- type: action_match
195
- correct_action: escalate
196
- partial_credit:
197
- flag: 0.5
198
- hold: 0.4
199
- requires_investigation:
200
- - inspect
201
- regulatory_action: false
202
- key_flags:
203
- - cross_border
204
- - high_value
205
- - task_id: MED-002
206
- difficulty: medium
207
- grader:
208
- type: action_match
209
- correct_action: hold
210
- partial_credit:
211
- escalate: 0.6
212
- flag: 0.4
213
- requires_investigation:
214
- - verify_kyc
215
- regulatory_action: false
216
- key_flags:
217
- - kyc_expiry_90d
218
- - task_id: MED-003
219
- difficulty: medium
220
- grader:
221
- type: action_match
222
- correct_action: flag
223
- partial_credit:
224
- hold: 0.5
225
- escalate: 0.3
226
- requires_investigation: []
227
- regulatory_action: false
228
- key_flags:
229
- - amount_spike
230
- - pattern_deviation
231
- - task_id: MED-004
232
- difficulty: medium
233
- grader:
234
- type: action_match
235
- correct_action: flag
236
- partial_credit:
237
- escalate: 0.5
238
- hold: 0.4
239
- requires_investigation: []
240
- regulatory_action: false
241
- key_flags:
242
- - crypto_exchange
243
- - task_id: MED-005
244
- difficulty: medium
245
- grader:
246
- type: action_match
247
- correct_action: hold
248
- partial_credit:
249
- flag: 0.5
250
- escalate: 0.4
251
- requires_investigation:
252
- - verify_kyc
253
- regulatory_action: false
254
- key_flags:
255
- - kyc_expired
256
- - task_id: MED-006
257
- difficulty: medium
258
- grader:
259
- type: action_match
260
- correct_action: escalate
261
- partial_credit:
262
- flag: 0.4
263
- hold: 0.5
264
- requires_investigation:
265
- - request_docs
266
- regulatory_action: false
267
- key_flags:
268
- - first_time_payee
269
- - large_first_transfer
270
- - task_id: MED-007
271
- difficulty: medium
272
- grader:
273
- type: action_match
274
- correct_action: hold
275
- partial_credit:
276
- escalate: 0.6
277
- flag: 0.4
278
- requires_investigation:
279
- - contact_sender
280
- - request_docs
281
- regulatory_action: false
282
- key_flags:
283
- - bank_detail_change
284
- - first_time_payee
285
- - task_id: MED-008
286
- difficulty: medium
287
- grader:
288
- type: action_match
289
- correct_action: flag
290
- partial_credit:
291
- hold: 0.6
292
- escalate: 0.4
293
- requires_investigation:
294
- - verify_kyc
295
- regulatory_action: false
296
- key_flags:
297
- - thin_credit_file
298
- - new_account
299
- - task_id: HARD-001
300
- difficulty: hard
301
- grader:
302
- type: action_match
303
- correct_action: escalate
304
- partial_credit:
305
- flag: 0.6
306
- hold: 0.5
307
- reject: 0.3
308
- requires_investigation:
309
- - inspect
310
- regulatory_action: false
311
- key_flags:
312
- - solicitor_mule_pattern
313
- - task_id: HARD-002
314
- difficulty: hard
315
- grader:
316
- type: action_match
317
- correct_action: reject
318
- partial_credit:
319
- escalate: 0.6
320
- hold: 0.5
321
- flag: 0.3
322
- requires_investigation:
323
- - contact_sender
324
- regulatory_action: false
325
- key_flags:
326
- - app_scam_indicator
327
- - mule_account_pattern
328
- - task_id: HARD-003
329
- difficulty: hard
330
- grader:
331
- type: action_match
332
- correct_action: reject
333
- partial_credit:
334
- escalate: 0.5
335
- flag: 0.2
336
- requires_investigation:
337
- - inspect
338
- regulatory_action: true
339
- key_flags:
340
- - structuring_pattern
341
- - ctr_threshold_avoidance
342
- - task_id: HARD-004
343
- difficulty: hard
344
- grader:
345
- type: action_match
346
- correct_action: approve
347
- partial_credit:
348
- escalate: 0.5
349
- hold: 0.4
350
- flag: 0.3
351
- requires_investigation:
352
- - inspect
353
- regulatory_action: false
354
- key_flags:
355
- - fx_settlement
356
- - task_id: HARD-005
357
- difficulty: hard
358
- grader:
359
- type: action_match
360
- correct_action: escalate
361
- partial_credit:
362
- flag: 0.5
363
- hold: 0.4
364
- reject: 0.3
365
- requires_investigation:
366
- - contact_sender
367
- - inspect
368
- regulatory_action: false
369
- key_flags:
370
- - internal_to_personal
371
- - unusual_beneficiary
372
- - task_id: HARD-006
373
- difficulty: hard
374
- grader:
375
- type: action_match
376
- correct_action: flag
377
- partial_credit:
378
- hold: 0.6
379
- escalate: 0.5
380
- requires_investigation:
381
- - inspect
382
- regulatory_action: false
383
- key_flags:
384
- - dormant_receiver
385
- - sudden_activity
386
- - task_id: HARD-007
387
- difficulty: hard
388
- grader:
389
- type: action_match
390
- correct_action: reject
391
- partial_credit:
392
- hold: 0.5
393
- escalate: 0.4
394
- flag: 0.3
395
- requires_investigation:
396
- - contact_sender
397
- - inspect
398
- regulatory_action: false
399
- key_flags:
400
- - sim_swap_detected
401
- - new_withdrawal_address
402
- - task_id: HARD-008
403
- difficulty: hard
404
- grader:
405
- type: action_match
406
- correct_action: reject
407
- partial_credit:
408
- hold: 0.5
409
- escalate: 0.4
410
- flag: 0.3
411
- requires_investigation:
412
- - contact_sender
413
- - inspect
414
- regulatory_action: false
415
- key_flags:
416
- - romance_scam_indicator
417
- - escalating_transfers
418
- - task_id: HARD-009
419
- difficulty: hard
420
- grader:
421
- type: action_match
422
- correct_action: escalate
423
- partial_credit:
424
- hold: 0.5
425
- flag: 0.4
426
- reject: 0.3
427
- requires_investigation:
428
- - inspect
429
- - verify_kyc
430
- regulatory_action: false
431
- key_flags:
432
- - new_account_10d
433
- - perfect_score_anomaly
434
- - task_id: HARD-010
435
- difficulty: hard
436
- grader:
437
- type: action_match
438
- correct_action: reject
439
- partial_credit:
440
- hold: 0.5
441
- escalate: 0.4
442
- flag: 0.3
443
- requires_investigation:
444
- - contact_sender
445
- - inspect
446
- regulatory_action: false
447
- key_flags:
448
- - direct_deposit_changed
449
- - payroll_diversion_indicator
450
- - task_id: CRIT-001
451
- difficulty: critical
452
- grader:
453
- type: action_match
454
- correct_action: approve
455
- partial_credit:
456
- escalate: 0.5
457
- hold: 0.4
458
- flag: 0.3
459
- requires_investigation:
460
- - inspect
461
- - request_docs
462
- regulatory_action: false
463
- key_flags:
464
- - first_time_payee
465
- - new_counterparty
466
- - task_id: CRIT-002
467
- difficulty: critical
468
- grader:
469
- type: action_match
470
- correct_action: reject
471
- partial_credit:
472
- escalate: 0.4
473
- flag: 0.2
474
- requires_investigation:
475
- - inspect
476
- regulatory_action: true
477
- key_flags:
478
- - fraud_ring_indicator
479
- - coordinated_transfers
480
- - task_id: CRIT-003
481
- difficulty: critical
482
- grader:
483
- type: action_match
484
- correct_action: escalate
485
- partial_credit:
486
- flag: 0.4
487
- hold: 0.35
488
- reject: 0.3
489
- requires_investigation:
490
- - inspect
491
- - request_docs
492
- regulatory_action: true
493
- key_flags:
494
- - invoice_mismatch
495
- - trade_finance
496
- - task_id: CRIT-004
497
- difficulty: critical
498
- grader:
499
- type: action_match
500
- correct_action: reject
501
- partial_credit:
502
- escalate: 0.5
503
- hold: 0.4
504
- requires_investigation:
505
- - contact_sender
506
- - inspect
507
- regulatory_action: false
508
- key_flags:
509
- - geo_impossible_login
510
- - account_takeover_indicator
511
- - task_id: CRIT-005
512
- difficulty: critical
513
- grader:
514
- type: action_match
515
- correct_action: reject
516
- partial_credit:
517
- escalate: 0.5
518
- hold: 0.4
519
- requires_investigation:
520
- - inspect
521
- - request_docs
522
- - verify_kyc
523
- regulatory_action: true
524
- key_flags:
525
- - shell_company_indicator
526
- - sanctions_adjacent
527
- - task_id: CRIT-006
528
- difficulty: critical
529
- grader:
530
- type: action_match
531
- correct_action: escalate
532
- partial_credit:
533
- hold: 0.5
534
- reject: 0.4
535
- requires_investigation:
536
- - inspect
537
- - request_docs
538
- regulatory_action: true
539
- key_flags:
540
- - fincen_311_alert
541
- - correspondent_risk
542
 
543
  # ── Budget ───────────────────────────────────────────────────────────────────
544
  budget:
 
112
  - recent_decisions
113
  - network_graph
114
 
115
+ # ── Tasks ───────────────────────────────────────────────────────────────────
116
+ # Metadata kept separate so 'count: 30' still appears in file
117
+ task_count: 30
118
+ task_difficulties:
119
+ - easy
120
+ - medium
121
+ - hard
122
+ - critical
123
+ task_difficulty_weights:
124
+ easy: 1.0
125
+ medium: 1.2
126
+ hard: 1.5
127
+ critical: 2.0
128
+
129
+ # tasks: flat list — platform iterates this directly for grader check
130
  tasks:
131
+ - task_id: EASY-001
132
+ difficulty: easy
133
+ grader:
134
+ type: action_match
135
+ correct_action: approve
136
+ partial_credit: {}
137
+ requires_investigation: []
138
+ regulatory_action: false
139
+ key_flags: []
140
+ - task_id: EASY-002
141
+ difficulty: easy
142
+ grader:
143
+ type: action_match
144
+ correct_action: reject
145
+ partial_credit:
146
+ escalate: 0.4
147
+ requires_investigation: []
148
+ regulatory_action: false
149
+ key_flags:
150
+ - sanctioned_country
151
+ - unknown_sender
152
+ - task_id: EASY-003
153
+ difficulty: easy
154
+ grader:
155
+ type: action_match
156
+ correct_action: approve
157
+ partial_credit: {}
158
+ requires_investigation: []
159
+ regulatory_action: false
160
+ key_flags: []
161
+ - task_id: EASY-004
162
+ difficulty: easy
163
+ grader:
164
+ type: action_match
165
+ correct_action: flag
166
+ partial_credit:
167
+ escalate: 0.6
168
+ hold: 0.5
169
+ requires_investigation: []
170
+ regulatory_action: false
171
+ key_flags:
172
+ - velocity_breach
173
+ - task_id: EASY-005
174
+ difficulty: easy
175
+ grader:
176
+ type: action_match
177
+ correct_action: approve
178
+ partial_credit: {}
179
+ requires_investigation: []
180
+ regulatory_action: false
181
+ key_flags: []
182
+ - task_id: EASY-006
183
+ difficulty: easy
184
+ grader:
185
+ type: action_match
186
+ correct_action: flag
187
+ partial_credit:
188
+ hold: 0.6
189
+ requires_investigation: []
190
+ regulatory_action: false
191
+ key_flags:
192
+ - duplicate_transaction
193
+ - task_id: MED-001
194
+ difficulty: medium
195
+ grader:
196
+ type: action_match
197
+ correct_action: escalate
198
+ partial_credit:
199
+ flag: 0.5
200
+ hold: 0.4
201
+ requires_investigation:
202
+ - inspect
203
+ regulatory_action: false
204
+ key_flags:
205
+ - cross_border
206
+ - high_value
207
+ - task_id: MED-002
208
+ difficulty: medium
209
+ grader:
210
+ type: action_match
211
+ correct_action: hold
212
+ partial_credit:
213
+ escalate: 0.6
214
+ flag: 0.4
215
+ requires_investigation:
216
+ - verify_kyc
217
+ regulatory_action: false
218
+ key_flags:
219
+ - kyc_expiry_90d
220
+ - task_id: MED-003
221
+ difficulty: medium
222
+ grader:
223
+ type: action_match
224
+ correct_action: flag
225
+ partial_credit:
226
+ hold: 0.5
227
+ escalate: 0.3
228
+ requires_investigation: []
229
+ regulatory_action: false
230
+ key_flags:
231
+ - amount_spike
232
+ - pattern_deviation
233
+ - task_id: MED-004
234
+ difficulty: medium
235
+ grader:
236
+ type: action_match
237
+ correct_action: flag
238
+ partial_credit:
239
+ escalate: 0.5
240
+ hold: 0.4
241
+ requires_investigation: []
242
+ regulatory_action: false
243
+ key_flags:
244
+ - crypto_exchange
245
+ - task_id: MED-005
246
+ difficulty: medium
247
+ grader:
248
+ type: action_match
249
+ correct_action: hold
250
+ partial_credit:
251
+ flag: 0.5
252
+ escalate: 0.4
253
+ requires_investigation:
254
+ - verify_kyc
255
+ regulatory_action: false
256
+ key_flags:
257
+ - kyc_expired
258
+ - task_id: MED-006
259
+ difficulty: medium
260
+ grader:
261
+ type: action_match
262
+ correct_action: escalate
263
+ partial_credit:
264
+ flag: 0.4
265
+ hold: 0.5
266
+ requires_investigation:
267
+ - request_docs
268
+ regulatory_action: false
269
+ key_flags:
270
+ - first_time_payee
271
+ - large_first_transfer
272
+ - task_id: MED-007
273
+ difficulty: medium
274
+ grader:
275
+ type: action_match
276
+ correct_action: hold
277
+ partial_credit:
278
+ escalate: 0.6
279
+ flag: 0.4
280
+ requires_investigation:
281
+ - contact_sender
282
+ - request_docs
283
+ regulatory_action: false
284
+ key_flags:
285
+ - bank_detail_change
286
+ - first_time_payee
287
+ - task_id: MED-008
288
+ difficulty: medium
289
+ grader:
290
+ type: action_match
291
+ correct_action: flag
292
+ partial_credit:
293
+ hold: 0.6
294
+ escalate: 0.4
295
+ requires_investigation:
296
+ - verify_kyc
297
+ regulatory_action: false
298
+ key_flags:
299
+ - thin_credit_file
300
+ - new_account
301
+ - task_id: HARD-001
302
+ difficulty: hard
303
+ grader:
304
+ type: action_match
305
+ correct_action: escalate
306
+ partial_credit:
307
+ flag: 0.6
308
+ hold: 0.5
309
+ reject: 0.3
310
+ requires_investigation:
311
+ - inspect
312
+ regulatory_action: false
313
+ key_flags:
314
+ - solicitor_mule_pattern
315
+ - task_id: HARD-002
316
+ difficulty: hard
317
+ grader:
318
+ type: action_match
319
+ correct_action: reject
320
+ partial_credit:
321
+ escalate: 0.6
322
+ hold: 0.5
323
+ flag: 0.3
324
+ requires_investigation:
325
+ - contact_sender
326
+ regulatory_action: false
327
+ key_flags:
328
+ - app_scam_indicator
329
+ - mule_account_pattern
330
+ - task_id: HARD-003
331
+ difficulty: hard
332
+ grader:
333
+ type: action_match
334
+ correct_action: reject
335
+ partial_credit:
336
+ escalate: 0.5
337
+ flag: 0.2
338
+ requires_investigation:
339
+ - inspect
340
+ regulatory_action: true
341
+ key_flags:
342
+ - structuring_pattern
343
+ - ctr_threshold_avoidance
344
+ - task_id: HARD-004
345
+ difficulty: hard
346
+ grader:
347
+ type: action_match
348
+ correct_action: approve
349
+ partial_credit:
350
+ escalate: 0.5
351
+ hold: 0.4
352
+ flag: 0.3
353
+ requires_investigation:
354
+ - inspect
355
+ regulatory_action: false
356
+ key_flags:
357
+ - fx_settlement
358
+ - task_id: HARD-005
359
+ difficulty: hard
360
+ grader:
361
+ type: action_match
362
+ correct_action: escalate
363
+ partial_credit:
364
+ flag: 0.5
365
+ hold: 0.4
366
+ reject: 0.3
367
+ requires_investigation:
368
+ - contact_sender
369
+ - inspect
370
+ regulatory_action: false
371
+ key_flags:
372
+ - internal_to_personal
373
+ - unusual_beneficiary
374
+ - task_id: HARD-006
375
+ difficulty: hard
376
+ grader:
377
+ type: action_match
378
+ correct_action: flag
379
+ partial_credit:
380
+ hold: 0.6
381
+ escalate: 0.5
382
+ requires_investigation:
383
+ - inspect
384
+ regulatory_action: false
385
+ key_flags:
386
+ - dormant_receiver
387
+ - sudden_activity
388
+ - task_id: HARD-007
389
+ difficulty: hard
390
+ grader:
391
+ type: action_match
392
+ correct_action: reject
393
+ partial_credit:
394
+ hold: 0.5
395
+ escalate: 0.4
396
+ flag: 0.3
397
+ requires_investigation:
398
+ - contact_sender
399
+ - inspect
400
+ regulatory_action: false
401
+ key_flags:
402
+ - sim_swap_detected
403
+ - new_withdrawal_address
404
+ - task_id: HARD-008
405
+ difficulty: hard
406
+ grader:
407
+ type: action_match
408
+ correct_action: reject
409
+ partial_credit:
410
+ hold: 0.5
411
+ escalate: 0.4
412
+ flag: 0.3
413
+ requires_investigation:
414
+ - contact_sender
415
+ - inspect
416
+ regulatory_action: false
417
+ key_flags:
418
+ - romance_scam_indicator
419
+ - escalating_transfers
420
+ - task_id: HARD-009
421
+ difficulty: hard
422
+ grader:
423
+ type: action_match
424
+ correct_action: escalate
425
+ partial_credit:
426
+ hold: 0.5
427
+ flag: 0.4
428
+ reject: 0.3
429
+ requires_investigation:
430
+ - inspect
431
+ - verify_kyc
432
+ regulatory_action: false
433
+ key_flags:
434
+ - new_account_10d
435
+ - perfect_score_anomaly
436
+ - task_id: HARD-010
437
+ difficulty: hard
438
+ grader:
439
+ type: action_match
440
+ correct_action: reject
441
+ partial_credit:
442
+ hold: 0.5
443
+ escalate: 0.4
444
+ flag: 0.3
445
+ requires_investigation:
446
+ - contact_sender
447
+ - inspect
448
+ regulatory_action: false
449
+ key_flags:
450
+ - direct_deposit_changed
451
+ - payroll_diversion_indicator
452
+ - task_id: CRIT-001
453
+ difficulty: critical
454
+ grader:
455
+ type: action_match
456
+ correct_action: approve
457
+ partial_credit:
458
+ escalate: 0.5
459
+ hold: 0.4
460
+ flag: 0.3
461
+ requires_investigation:
462
+ - inspect
463
+ - request_docs
464
+ regulatory_action: false
465
+ key_flags:
466
+ - first_time_payee
467
+ - new_counterparty
468
+ - task_id: CRIT-002
469
+ difficulty: critical
470
+ grader:
471
+ type: action_match
472
+ correct_action: reject
473
+ partial_credit:
474
+ escalate: 0.4
475
+ flag: 0.2
476
+ requires_investigation:
477
+ - inspect
478
+ regulatory_action: true
479
+ key_flags:
480
+ - fraud_ring_indicator
481
+ - coordinated_transfers
482
+ - task_id: CRIT-003
483
+ difficulty: critical
484
+ grader:
485
+ type: action_match
486
+ correct_action: escalate
487
+ partial_credit:
488
+ flag: 0.4
489
+ hold: 0.35
490
+ reject: 0.3
491
+ requires_investigation:
492
+ - inspect
493
+ - request_docs
494
+ regulatory_action: true
495
+ key_flags:
496
+ - invoice_mismatch
497
+ - trade_finance
498
+ - task_id: CRIT-004
499
+ difficulty: critical
500
+ grader:
501
+ type: action_match
502
+ correct_action: reject
503
+ partial_credit:
504
+ escalate: 0.5
505
+ hold: 0.4
506
+ requires_investigation:
507
+ - contact_sender
508
+ - inspect
509
+ regulatory_action: false
510
+ key_flags:
511
+ - geo_impossible_login
512
+ - account_takeover_indicator
513
+ - task_id: CRIT-005
514
+ difficulty: critical
515
+ grader:
516
+ type: action_match
517
+ correct_action: reject
518
+ partial_credit:
519
+ escalate: 0.5
520
+ hold: 0.4
521
+ requires_investigation:
522
+ - inspect
523
+ - request_docs
524
+ - verify_kyc
525
+ regulatory_action: true
526
+ key_flags:
527
+ - shell_company_indicator
528
+ - sanctions_adjacent
529
+ - task_id: CRIT-006
530
+ difficulty: critical
531
+ grader:
532
+ type: action_match
533
+ correct_action: escalate
534
+ partial_credit:
535
+ hold: 0.5
536
+ reject: 0.4
537
+ requires_investigation:
538
+ - inspect
539
+ - request_docs
540
+ regulatory_action: true
541
+ key_flags:
542
+ - fincen_311_alert
543
+ - correspondent_risk
 
 
 
 
 
 
 
 
 
 
 
 
544
 
545
  # ── Budget ───────────────────────────────────────────────────────────────────
546
  budget: