payops_env / PayOps_v2.postman_collection.json
padmapriyagosakan's picture
Initial Commit
d727210
Raw
History Blame Contribute Delete
65 kB
{
"info": {
"_postman_id": "payops-v2-full-suite",
"name": "PayOps v2 — Full Test Suite",
"description": "Complete Postman collection for PayOps v2.0.0 environment.\nGroups: Infrastructure · Tasks · Reset · Terminal Actions · Wrong Actions · Investigation · State · Grader · Replay · Baseline · Analytics · Leaderboard · Edge Cases · Perfect Episode · Budget Mechanics\n\nBase URL variable: {{base_url}} = http://localhost:8000",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{
"key": "base_url",
"value": "http://localhost:8000",
"type": "string"
},
{
"key": "episode_id",
"value": "",
"type": "string"
}
],
"item": [
{
"name": "A — Infrastructure",
"item": [
{
"name": "A-01 Health check",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('Status 200', () => pm.response.to.have.status(200));",
"pm.test('status=ok', () => pm.expect(pm.response.json().status).to.eql('ok'));",
"pm.test('version=2.0.0', () => pm.expect(pm.response.json().version).to.eql('2.0.0'));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/health", "host": ["{{base_url}}"], "path": ["health"]}
}
},
{
"name": "A-02 Schema — models present",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('Status 200', () => pm.response.to.have.status(200));",
"const body = pm.response.text();",
"pm.test('PayOpsAction in schema', () => pm.expect(body).to.include('PayOpsAction'));",
"pm.test('PayOpsObservation in schema', () => pm.expect(body).to.include('PayOpsObservation'));",
"pm.test('PayOpsState in schema', () => pm.expect(body).to.include('PayOpsState'));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/schema", "host": ["{{base_url}}"], "path": ["schema"]}
}
},
{
"name": "A-03 Schema — all 10 action types",
"event": [{"listen": "test", "script": {"exec": [
"const body = pm.response.text();",
"['approve','reject','flag','escalate','hold','inspect','request_docs','verify_kyc','contact_sender','file_sar'].forEach(a => {",
" pm.test(`action ${a} in schema`, () => pm.expect(body).to.include(a));",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/schema", "host": ["{{base_url}}"], "path": ["schema"]}
}
}
]
},
{
"name": "B — Tasks Endpoint",
"item": [
{
"name": "B-01 Tasks — count=20",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('Status 200', () => pm.response.to.have.status(200));",
"const d = pm.response.json();",
"pm.test('count=20', () => pm.expect(d.count).to.eql(20));",
"pm.test('tasks array length=20', () => pm.expect(d.tasks.length).to.eql(20));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/tasks", "host": ["{{base_url}}"], "path": ["tasks"]}
}
},
{
"name": "B-02 Tasks — all 4 difficulty tiers",
"event": [{"listen": "test", "script": {"exec": [
"const tasks = pm.response.json().tasks;",
"const diffs = tasks.map(t => t.difficulty);",
"['easy','medium','hard','critical'].forEach(d => {",
" pm.test(`tier '${d}' present`, () => pm.expect(diffs).to.include(d));",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/tasks", "host": ["{{base_url}}"], "path": ["tasks"]}
}
},
{
"name": "B-03 Tasks — task structure fields",
"event": [{"listen": "test", "script": {"exec": [
"const t = pm.response.json().tasks[0];",
"['task_id','difficulty','correct_action','requires_investigation','regulatory_action','chain_total'].forEach(f => {",
" pm.test(`field '${f}' present`, () => pm.expect(t).to.have.property(f));",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/tasks", "host": ["{{base_url}}"], "path": ["tasks"]}
}
},
{
"name": "B-04 Tasks — chain_total >= 1 on all",
"event": [{"listen": "test", "script": {"exec": [
"const tasks = pm.response.json().tasks;",
"pm.test('all tasks have chain_total >= 1', () => {",
" tasks.forEach(t => pm.expect(t.chain_total).to.be.at.least(1));",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/tasks", "host": ["{{base_url}}"], "path": ["tasks"]}
}
}
]
},
{
"name": "C — Reset",
"item": [
{
"name": "C-01 Reset — first observation",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('Status 200', () => pm.response.to.have.status(200));",
"const d = pm.response.json();",
"pm.test('first task is EASY-001', () => pm.expect(d.task_id).to.eql('EASY-001'));",
"pm.test('done=false', () => pm.expect(d.done).to.eql(false));",
"pm.test('budget_remaining=5.0', () => pm.expect(d.budget_remaining).to.eql(5.0));",
"pm.test('risk_score present', () => pm.expect(d).to.have.property('risk_score'));",
"pm.test('ml_confidence present', () => pm.expect(d).to.have.property('ml_confidence'));",
"pm.test('chain_total present', () => pm.expect(d).to.have.property('chain_total'));",
"pm.test('steps_remaining present', () => pm.expect(d).to.have.property('steps_remaining'));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/reset", "host": ["{{base_url}}"], "path": ["reset"]}
}
},
{
"name": "C-02 State after reset",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('episode_id set', () => pm.expect(d.episode_id).to.be.a('string').and.not.empty);",
"pm.collectionVariables.set('episode_id', d.episode_id);",
"pm.test('step_count=0', () => pm.expect(d.step_count).to.eql(0));",
"pm.test('budget_spent=0', () => pm.expect(d.budget_spent).to.eql(0));",
"pm.test('correct_decisions=0', () => pm.expect(d.correct_decisions).to.eql(0));",
"pm.test('investigation_actions_used is array', () => pm.expect(d.investigation_actions_used).to.be.an('array'));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/state", "host": ["{{base_url}}"], "path": ["state"]}
}
}
]
},
{
"name": "D — Terminal Actions (Correct)",
"item": [
{
"name": "D-01 EASY-001 approve → reward=1.0",
"event": [
{"listen": "prerequest", "script": {"exec": ["// ensure fresh episode"], "type": "text/javascript"}},
{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=1.0', () => pm.expect(d.reward).to.eql(1.0));",
"pm.test('advances to EASY-002', () => pm.expect(d.task_id).to.eql('EASY-002'));"
], "type": "text/javascript"}}
],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-02 EASY-002 reject → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-E002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-03 EASY-003 approve → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-E003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-04 EASY-004 flag → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-E004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-05 MED-001 escalate → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"escalate\", \"transaction_id\": \"TXN-M001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-06 MED-002 hold → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"hold\", \"transaction_id\": \"TXN-M002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-07 MED-003 flag → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-M003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-08 MED-004 flag → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-M004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-09 MED-005 hold → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"hold\", \"transaction_id\": \"TXN-M005\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-10 MED-006 escalate → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"escalate\", \"transaction_id\": \"TXN-M006\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-11 HARD-001 escalate → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"escalate\", \"transaction_id\": \"TXN-H001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-12 HARD-002 reject → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-H002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-13 HARD-003 reject → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-H003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-14 HARD-004 approve → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-H004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-15 HARD-005 escalate → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"escalate\", \"transaction_id\": \"TXN-H005\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-16 HARD-006 flag → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-H006\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-17 CRIT-001 approve → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-C001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-18 CRIT-002 reject → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-C002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-19 CRIT-003 escalate → reward=1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=1.0', () => pm.expect(pm.response.json().reward).to.eql(1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"escalate\", \"transaction_id\": \"TXN-C003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "D-20 CRIT-004 reject → reward=1.0 + done=true",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=1.0', () => pm.expect(d.reward).to.eql(1.0));",
"pm.test('episode done', () => pm.expect(d.done).to.eql(true));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-C004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
}
]
},
{
"name": "E — Wrong Actions & Partial Credit",
"item": [
{
"name": "E-00 Reset before wrong-action tests",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reset ok', () => pm.response.to.have.status(200));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/reset", "host": ["{{base_url}}"], "path": ["reset"]}
}
},
{
"name": "E-01 Approve legit EASY-001 (correct, advance)",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "E-02 Approve fraud EASY-002 → reward=-1.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=-1.0 for fraud approval', () => pm.expect(pm.response.json().reward).to.eql(-1.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-E002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "E-03 Reject legit EASY-003 → reward=-0.5",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('reward=-0.5 for wrong reject', () => pm.expect(pm.response.json().reward).to.eql(-0.5));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-E003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "E-04 Flag EASY-004 correct → reward=1.0",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-E004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "E-05 Partial credit — flag instead of escalate (MED-001)",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('partial credit reward > -1 and < 1', () => {",
" pm.expect(d.reward).to.be.greaterThan(-1.0);",
" pm.expect(d.reward).to.be.lessThan(1.0);",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-M001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
}
]
},
{
"name": "F — Investigation Sub-Actions",
"item": [
{
"name": "F-00 Reset before investigation tests",
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/reset", "host": ["{{base_url}}"], "path": ["reset"]}
}
},
{
"name": "F-01 inspect → reward=0.15, notes populated, budget=4.9",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=0.15', () => pm.expect(d.reward).to.eql(0.15));",
"pm.test('task unchanged (EASY-001)', () => pm.expect(d.task_id).to.eql('EASY-001'));",
"pm.test('inspection_notes populated', () => pm.expect(d.inspection_notes).to.be.a('string').and.not.empty);",
"pm.test('budget_remaining=4.9', () => pm.expect(d.budget_remaining).to.eql(4.9));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"inspect\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-02 inspect again (duplicate) → reward=0.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('duplicate inspect reward=0.0', () => pm.expect(pm.response.json().reward).to.eql(0.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"inspect\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-03 approve EASY-001 (advance to E-002)",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-04 request_docs → reward=0.15, docs_notes, budget-0.2",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=0.15', () => pm.expect(d.reward).to.eql(0.15));",
"pm.test('docs_notes populated', () => pm.expect(d.docs_notes).to.be.a('string').and.not.empty);",
"pm.test('budget decreased by 0.2', () => pm.expect(d.budget_remaining).to.be.closeTo(4.6, 0.01));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"request_docs\", \"transaction_id\": \"TXN-E002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-05 request_docs again (duplicate) → reward=0.0",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('duplicate request_docs reward=0.0', () => pm.expect(pm.response.json().reward).to.eql(0.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"request_docs\", \"transaction_id\": \"TXN-E002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-06 reject EASY-002 (advance to E-003)",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"reject\", \"transaction_id\": \"TXN-E002\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-07 verify_kyc → reward=0.15, kyc_notes, budget-0.2",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=0.15', () => pm.expect(d.reward).to.eql(0.15));",
"pm.test('kyc_notes populated', () => pm.expect(d.kyc_notes).to.be.a('string').and.not.empty);",
"pm.test('budget decreased by 0.2', () => pm.expect(d.budget_remaining).to.be.closeTo(4.2, 0.05));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"verify_kyc\", \"transaction_id\": \"TXN-E003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-08 approve EASY-003 (advance to E-004)",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"approve\", \"transaction_id\": \"TXN-E003\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-09 contact_sender → reward=0.15, contact_notes, budget-0.3",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=0.15', () => pm.expect(d.reward).to.eql(0.15));",
"pm.test('contact_notes populated', () => pm.expect(d.contact_notes).to.be.a('string').and.not.empty);",
"pm.test('budget decreased by 0.3', () => pm.expect(d.budget_remaining).to.be.lessThan(4.2));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"contact_sender\", \"transaction_id\": \"TXN-E004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-10 flag EASY-004 (advance to M-001)",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"flag\", \"transaction_id\": \"TXN-E004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "F-11 file_sar → reward=0.15, docs_notes has SAR, budget-0.05",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=0.15', () => pm.expect(d.reward).to.eql(0.15));",
"pm.test('docs_notes contains SAR', () => pm.expect(d.docs_notes).to.include('SAR'));",
"pm.test('budget_remaining updated', () => pm.expect(d.budget_remaining).to.be.lessThan(5.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"file_sar\", \"transaction_id\": \"TXN-M001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
}
]
},
{
"name": "G — State Endpoint",
"item": [
{
"name": "G-01 State — all required fields",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('status 200', () => pm.response.to.have.status(200));",
"['episode_id','step_count','budget_spent','budget_limit','investigation_actions_used','correct_decisions','wrong_high_cost','recent_decisions'].forEach(f => {",
" pm.test(`field '${f}' present`, () => pm.expect(d).to.have.property(f));",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/state", "host": ["{{base_url}}"], "path": ["state"]}
}
},
{
"name": "G-02 State — budget_spent reflects investigation costs",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('budget_spent > 0', () => pm.expect(pm.response.json().budget_spent).to.be.greaterThan(0));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/state", "host": ["{{base_url}}"], "path": ["state"]}
}
},
{
"name": "G-03 State — investigation_actions_used is array",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('investigation_actions_used is array', () => pm.expect(pm.response.json().investigation_actions_used).to.be.an('array'));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/state", "host": ["{{base_url}}"], "path": ["state"]}
}
}
]
},
{
"name": "H — Grader Endpoint",
"item": [
{
"name": "H-01 Grader — full result structure",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('status 200', () => pm.response.to.have.status(200));",
"['normalised_score','total_reward','max_possible_reward','budget_spent','budget_penalty','per_task','passed'].forEach(f => {",
" pm.test(`field '${f}' present`, () => pm.expect(d).to.have.property(f));",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/grader", "host": ["{{base_url}}"], "path": ["grader"]}
}
},
{
"name": "H-02 Grader — per_task has reward_breakdown",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('per_task is array', () => pm.expect(d.per_task).to.be.an('array'));",
"if (d.per_task.length > 0) {",
" pm.test('per_task[0] has reward_breakdown', () => pm.expect(d.per_task[0]).to.have.property('reward_breakdown'));",
" pm.test('per_task[0] has difficulty', () => pm.expect(d.per_task[0]).to.have.property('difficulty'));",
"}"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/grader", "host": ["{{base_url}}"], "path": ["grader"]}
}
},
{
"name": "H-03 Grader — normalised_score in [0,1]",
"event": [{"listen": "test", "script": {"exec": [
"const s = pm.response.json().normalised_score;",
"pm.test('score in [0,1]', () => { pm.expect(s).to.be.at.least(0); pm.expect(s).to.be.at.most(1); });"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/grader", "host": ["{{base_url}}"], "path": ["grader"]}
}
}
]
},
{
"name": "I — Replay Endpoint",
"item": [
{
"name": "I-01 Replay — 20 all-correct actions → score=1.0",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('normalised_score=1.0', () => pm.expect(d.normalised_score).to.eql(1.0));",
"pm.test('passed=true', () => pm.expect(d.passed).to.eql(true));",
"pm.test('budget_spent=0.0', () => pm.expect(d.budget_spent).to.eql(0.0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\n \"actions\": [\n \"approve\", \"reject\", \"approve\", \"flag\",\n \"escalate\", \"hold\", \"flag\", \"flag\", \"hold\", \"escalate\",\n \"escalate\", \"reject\", \"reject\", \"approve\", \"escalate\", \"flag\",\n \"approve\", \"reject\", \"escalate\", \"reject\"\n ]\n}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "I-02 Replay — with inspect sub-actions → budget_spent=0.1",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('budget_spent=0.1', () => pm.expect(d.budget_spent).to.eql(0.1));",
"pm.test('per_task present', () => pm.expect(d.per_task).to.be.an('array'));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\n \"actions\": [\n \"inspect\", \"approve\", \"reject\", \"approve\", \"flag\",\n \"escalate\", \"hold\", \"flag\", \"flag\", \"hold\", \"escalate\",\n \"escalate\", \"reject\", \"reject\", \"approve\", \"escalate\", \"flag\",\n \"approve\", \"reject\", \"escalate\", \"reject\"\n ]\n}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "I-03 Replay — with confidences",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('accepts confidences, returns score', () => pm.expect(pm.response.json()).to.have.property('normalised_score'));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\n \"actions\": [\"approve\", \"reject\"],\n \"confidences\": [0.95, 0.88]\n}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "I-04 Replay — all-wrong actions → score very low",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('all-wrong score < 0.3', () => pm.expect(d.normalised_score).to.be.lessThan(0.3));",
"pm.test('passed=false', () => pm.expect(d.passed).to.eql(false));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\n \"actions\": [\n \"reject\", \"approve\", \"reject\", \"reject\",\n \"reject\", \"reject\", \"reject\", \"reject\", \"reject\", \"reject\",\n \"reject\", \"approve\", \"approve\", \"reject\", \"reject\", \"reject\",\n \"reject\", \"approve\", \"reject\", \"approve\"\n ]\n}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "I-05 Replay — invalid action → 422",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('422 or error body', () => {",
" const ok = pm.response.code === 422 || (pm.response.code === 400);",
" const hasError = pm.response.text().includes('Invalid') || pm.response.text().includes('detail');",
" pm.expect(ok || hasError).to.be.true;",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"actions\": [\"delete\", \"approve\"]}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "I-06 Replay — empty actions list",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('handles empty list gracefully', () => pm.expect(pm.response.json()).to.have.property('normalised_score'));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"actions\": []}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "I-07 Replay — does NOT alter live server state",
"event": [
{"listen": "prerequest", "script": {"exec": [
"// capture current state to compare after replay",
"pm.sendRequest(`${pm.collectionVariables.get('base_url') || 'http://localhost:8000'}/state`, (err, res) => {",
" if (!err) pm.collectionVariables.set('state_before', JSON.stringify(res.json().step_count));",
"});"
], "type": "text/javascript"}},
{"listen": "test", "script": {"exec": [
"pm.sendRequest(`${pm.collectionVariables.get('base_url') || 'http://localhost:8000'}/state`, (err, res) => {",
" const before = pm.collectionVariables.get('state_before');",
" const after = JSON.stringify(res.json().step_count);",
" pm.test('server state unchanged after replay', () => pm.expect(before).to.eql(after));",
"});"
], "type": "text/javascript"}}
],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"actions\": [\"approve\", \"reject\"]}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
}
]
},
{
"name": "J — Baseline Endpoint",
"item": [
{
"name": "J-01 Baseline — full result",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('status 200', () => pm.response.to.have.status(200));",
"['normalised_score','total_reward','steps','scores'].forEach(f => {",
" pm.test(`field '${f}' present`, () => pm.expect(d).to.have.property(f));",
"});",
"pm.test('score > 0.5', () => pm.expect(d.normalised_score).to.be.greaterThan(0.5));",
"pm.test('steps = 20', () => pm.expect(d.steps).to.eql(20));",
"pm.test('scores length = 20', () => pm.expect(d.scores.length).to.eql(20));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/baseline", "host": ["{{base_url}}"], "path": ["baseline"]}
}
},
{
"name": "J-02 Baseline — passed=true",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('passed=true', () => pm.expect(pm.response.json().passed).to.eql(true));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/baseline", "host": ["{{base_url}}"], "path": ["baseline"]}
}
}
]
},
{
"name": "K — Analytics Endpoint",
"item": [
{
"name": "K-01 Analytics — structure",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('status 200', () => pm.response.to.have.status(200));",
"const d = pm.response.json();",
"const hasMsg = d.message !== undefined;",
"const hasData = d.episodes_completed !== undefined;",
"pm.test('returns message or episode data', () => pm.expect(hasMsg || hasData).to.be.true);"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/analytics", "host": ["{{base_url}}"], "path": ["analytics"]}
}
},
{
"name": "K-02 Analytics — after completed episode",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('episodes_completed >= 1', () => pm.expect(d.episodes_completed).to.be.at.least(1));",
"pm.test('best_score present', () => pm.expect(d).to.have.property('best_score'));",
"pm.test('avg_score present', () => pm.expect(d).to.have.property('avg_score'));",
"pm.test('by_difficulty present', () => pm.expect(d).to.have.property('by_difficulty'));",
"pm.test('easy accuracy present', () => pm.expect(d.by_difficulty).to.have.property('easy'));",
"pm.test('critical accuracy present', () => pm.expect(d.by_difficulty).to.have.property('critical'));"
], "type": "text/javascript"}},
{"listen": "prerequest", "script": {"exec": [
"// Run a complete episode first so analytics has data",
"const base = pm.collectionVariables.get('base_url') || 'http://localhost:8000';",
"const actions = [",
" ['approve','TXN-E001'],['reject','TXN-E002'],['approve','TXN-E003'],['flag','TXN-E004'],",
" ['escalate','TXN-M001'],['hold','TXN-M002'],['flag','TXN-M003'],['flag','TXN-M004'],",
" ['hold','TXN-M005'],['escalate','TXN-M006'],",
" ['escalate','TXN-H001'],['reject','TXN-H002'],['reject','TXN-H003'],['approve','TXN-H004'],",
" ['escalate','TXN-H005'],['flag','TXN-H006'],",
" ['approve','TXN-C001'],['reject','TXN-C002'],['escalate','TXN-C003'],['reject','TXN-C004']",
"];",
"// Note: triggering via test runner means sequence matters — this prerequest",
"// runs before the actual GET /analytics is sent."
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/analytics", "host": ["{{base_url}}"], "path": ["analytics"]}
}
},
{
"name": "K-03 Analytics — current_episode present",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('current_episode field present', () => pm.expect(pm.response.json()).to.have.property('current_episode'));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/analytics", "host": ["{{base_url}}"], "path": ["analytics"]}
}
}
]
},
{
"name": "L — Leaderboard Endpoint",
"item": [
{
"name": "L-01 Leaderboard — structure",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('status 200', () => pm.response.to.have.status(200));",
"pm.test('count field present', () => pm.expect(d).to.have.property('count'));",
"pm.test('entries field present', () => pm.expect(d).to.have.property('entries'));",
"pm.test('entries is array', () => pm.expect(d.entries).to.be.an('array'));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/leaderboard", "host": ["{{base_url}}"], "path": ["leaderboard"]}
}
},
{
"name": "L-02 Leaderboard — entry structure",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"if (d.entries.length > 0) {",
" const e = d.entries[0];",
" ['episode_id','normalised_score','timestamp','budget_spent'].forEach(f => {",
" pm.test(`entry has field '${f}'`, () => pm.expect(e).to.have.property(f));",
" });",
"} else {",
" pm.test('no entries yet (ok before completing episode)', () => true);",
"}"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/leaderboard", "host": ["{{base_url}}"], "path": ["leaderboard"]}
}
},
{
"name": "L-03 Leaderboard — after baseline run, count >= 1",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('at least one entry after baseline', () => pm.expect(pm.response.json().count).to.be.at.least(1));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/leaderboard", "host": ["{{base_url}}"], "path": ["leaderboard"]}
}
}
]
},
{
"name": "M — Budget Mechanics",
"item": [
{
"name": "M-00 Reset for budget test",
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/reset", "host": ["{{base_url}}"], "path": ["reset"]}
}
},
{
"name": "M-01 contact_sender (cost=0.3) → budget=4.7",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('budget_remaining=4.7', () => pm.expect(pm.response.json().budget_remaining).to.be.closeTo(4.7, 0.01));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"contact_sender\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "M-02 request_docs (cost=0.2) → budget=4.5",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('budget_remaining=4.5', () => pm.expect(pm.response.json().budget_remaining).to.be.closeTo(4.5, 0.01));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"request_docs\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "M-03 verify_kyc (cost=0.2) → budget=4.3",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('budget_remaining=4.3', () => pm.expect(pm.response.json().budget_remaining).to.be.closeTo(4.3, 0.01));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"verify_kyc\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "M-04 file_sar (cost=0.05) → budget=4.25",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('budget_remaining=4.25', () => pm.expect(pm.response.json().budget_remaining).to.be.closeTo(4.25, 0.01));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"file_sar\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "M-05 Grader shows non-zero budget_spent",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('budget_spent > 0', () => pm.expect(pm.response.json().budget_spent).to.be.greaterThan(0));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/grader", "host": ["{{base_url}}"], "path": ["grader"]}
}
},
{
"name": "M-06 Replay — heavy investigation causes budget_penalty",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('budget_overspend > 0', () => pm.expect(d.budget_overspend).to.be.greaterThan(0));",
"pm.test('budget_penalty > 0', () => pm.expect(d.budget_penalty).to.be.greaterThan(0));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\n \"actions\": [\n \"contact_sender\",\"contact_sender\",\"contact_sender\",\"contact_sender\",\n \"contact_sender\",\"contact_sender\",\"contact_sender\",\"contact_sender\",\n \"contact_sender\",\"contact_sender\",\"contact_sender\",\"contact_sender\",\n \"contact_sender\",\"contact_sender\",\"contact_sender\",\"contact_sender\",\n \"contact_sender\",\"contact_sender\",\n \"approve\",\"reject\",\"approve\",\"flag\",\n \"escalate\",\"hold\",\"flag\",\"flag\",\"hold\",\"escalate\",\n \"escalate\",\"reject\",\"reject\",\"approve\",\"escalate\",\"flag\",\n \"approve\",\"reject\",\"escalate\",\"reject\"\n ]\n}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
}
]
},
{
"name": "N — Edge Cases & Errors",
"item": [
{
"name": "N-01 Unknown action_type → 422",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('error response', () => {",
" const code = pm.response.code;",
" pm.expect([400, 422]).to.include(code);",
"});"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\": \"nuke\", \"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "N-02 Missing action_type → 422",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('422 for missing field', () => pm.expect([400, 422]).to.include(pm.response.code));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"transaction_id\": \"TXN-E001\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "N-03 Empty POST body → 422",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('422 for empty body', () => pm.expect([400, 422]).to.include(pm.response.code));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "N-04 Replay with partial confidences (shorter than actions)",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('handles partial confidences gracefully', () => pm.expect(pm.response.json()).to.have.property('normalised_score'));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"actions\": [\"approve\", \"reject\", \"approve\"], \"confidences\": [0.9]}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
},
{
"name": "N-05 Replay with invalid JSON → 422",
"event": [{"listen": "test", "script": {"exec": [
"pm.test('error on invalid JSON', () => pm.expect([400, 422]).to.include(pm.response.code));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{broken json}"},
"url": {"raw": "{{base_url}}/replay", "host": ["{{base_url}}"], "path": ["replay"]}
}
}
]
},
{
"name": "O — Perfect Episode (Full Run)",
"item": [
{
"name": "O-00 Reset (start fresh)",
"request": {
"method": "POST",
"url": {"raw": "{{base_url}}/reset", "host": ["{{base_url}}"], "path": ["reset"]}
}
},
{"name": "O-01 EASY-001 approve", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"approve\",\"transaction_id\":\"TXN-E001\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-02 EASY-002 reject", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"reject\",\"transaction_id\":\"TXN-E002\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-03 EASY-003 approve", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"approve\",\"transaction_id\":\"TXN-E003\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-04 EASY-004 flag", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"flag\",\"transaction_id\":\"TXN-E004\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-05 MED-001 escalate", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"escalate\",\"transaction_id\":\"TXN-M001\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-06 MED-002 hold", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"hold\",\"transaction_id\":\"TXN-M002\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-07 MED-003 flag", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"flag\",\"transaction_id\":\"TXN-M003\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-08 MED-004 flag", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"flag\",\"transaction_id\":\"TXN-M004\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-09 MED-005 hold", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"hold\",\"transaction_id\":\"TXN-M005\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-10 MED-006 escalate", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"escalate\",\"transaction_id\":\"TXN-M006\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-11 HARD-001 escalate", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"escalate\",\"transaction_id\":\"TXN-H001\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-12 HARD-002 reject", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"reject\",\"transaction_id\":\"TXN-H002\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-13 HARD-003 reject", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"reject\",\"transaction_id\":\"TXN-H003\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-14 HARD-004 approve", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"approve\",\"transaction_id\":\"TXN-H004\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-15 HARD-005 escalate", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"escalate\",\"transaction_id\":\"TXN-H005\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-16 HARD-006 flag", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"flag\",\"transaction_id\":\"TXN-H006\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-17 CRIT-001 approve", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"approve\",\"transaction_id\":\"TXN-C001\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-18 CRIT-002 reject", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"reject\",\"transaction_id\":\"TXN-C002\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{"name": "O-19 CRIT-003 escalate", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\"action_type\":\"escalate\",\"transaction_id\":\"TXN-C003\"}"}, "url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}}},
{
"name": "O-20 CRIT-004 reject → done=true",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('reward=1.0', () => pm.expect(d.reward).to.eql(1.0));",
"pm.test('done=true', () => pm.expect(d.done).to.eql(true));"
], "type": "text/javascript"}}],
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"action_type\":\"reject\",\"transaction_id\":\"TXN-C004\"}"},
"url": {"raw": "{{base_url}}/step", "host": ["{{base_url}}"], "path": ["step"]}
}
},
{
"name": "O-21 Grader — score=1.0 after perfect episode",
"event": [{"listen": "test", "script": {"exec": [
"const d = pm.response.json();",
"pm.test('normalised_score=1.0', () => pm.expect(d.normalised_score).to.eql(1.0));",
"pm.test('passed=true', () => pm.expect(d.passed).to.eql(true));",
"pm.test('budget_penalty=0', () => pm.expect(d.budget_penalty).to.eql(0.0));"
], "type": "text/javascript"}}],
"request": {
"method": "GET",
"url": {"raw": "{{base_url}}/grader", "host": ["{{base_url}}"], "path": ["grader"]}
}
}
]
}
]
}