$ uv run tools/flow.py test cases/lab03-limit.json -v
✔ before: POST http://localhost:8800/budget/reset · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0, "remaining_usd": 1.0, "over": fal
    → request  POST http://localhost:8800/budget/reset
      {}
    ← response HTTP 200
      {
        "daily_usd": 1.0,
        "user_limit_per_min": 20,
        "max_question_chars": 500,
        "used_usd": 0,
        "remaining_usd": 1.0,
        "over": false
      }
✔ before: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 0}
    → request  POST http://localhost:8800/usage-clear
      {}
    ← response HTTP 200
      {
        "cleared": 0
      }
✔ before: POST http://localhost:8800/budget · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 2, "max_question_chars": 500, "used_usd": 0, "remaining_usd": 1.0, "over": fals
    → request  POST http://localhost:8800/budget
      {
        "user_limit_per_min": 2
      }
    ← response HTTP 200
      {
        "daily_usd": 1.0,
        "user_limit_per_min": 2,
        "max_question_chars": 500,
        "used_usd": 0,
        "remaining_usd": 1.0,
        "over": false
      }
POST http://localhost:5678/webhook/my-cost · 4 case(s) × 1
✔ 이준호 1번째 · 1.3s · 자동 답변 · 1 call · $0.000156
    → request  POST /webhook/my-cost
      {
        "question": "VPN 접속이 자꾸 끊겨요. 어떻게 하나요?",
        "user": "이준호"
      }
    ← response HTTP 200
      {
        "route": "자동 답변",
        "answer": "VPN 접속 오류는 VPN 클라이언트를 최신 버전으로 업데이트하고, 인증서 만료 여부를 확인한 뒤 다시 접속하시기 바랍니다. 현재 접수된 관련 티켓은 없습니다. 추가 도움이 필요하시면 담당자가 도와드리겠습니다.",
        "sources": [
          "FAQ-003"
        ],
        "llm_calls": 1,
        "usage": {
          "prompt_tokens": 165,
          "completion_tokens": 56,
          "by_step": {
            "answer": {
              "model": "gpt-4.1-mini",
              "prompt_tokens": 165,
              "completion_tokens": 56,
              "cost_usd": 0.0001556
            }
          }
        },
        "cost_usd": 0.0001556,
        "trimmed": false,
        "question_chars": 24,
        "recorded": true
      }
✔ 이준호 2번째 · 1.6s · 자동 답변 · 1 call · $0.000152
    → request  POST /webhook/my-cost
      {
        "question": "프린터 출력이 안 돼요",
        "user": "이준호"
      }
    ← response HTTP 200
      {
        "route": "자동 답변",
        "answer": "프린터 전원과 네트워크 연결을 확인하고, 인쇄 대기열을 비운 뒤 다시 출력해 보시기 바랍니다. 현재 접수된 관련 문의는 없습니다. 추가 도움이 필요하시면 담당 직원이 도와드리겠습니다.",
        "sources": [
          "FAQ-004"
        ],
        "llm_calls": 1,
        "usage": {
          "prompt_tokens": 164,
          "completion_tokens": 54,
          "by_step": {
            "answer": {
              "model": "gpt-4.1-mini",
              "prompt_tokens": 164,
              "completion_tokens": 54,
              "cost_usd": 0.000152
            }
          }
        },
        "cost_usd": 0.000152,
        "trimmed": false,
        "question_chars": 12,
        "recorded": true
      }
✘ 이준호 3번째 · 1분에 2번 넘음 · 1.3s · 자동 답변 · 1 call · $0.000156 · took 1.3s (expected at most 1s); status 200 (expected 429); route = 자동 답변 (expected 잠시 후); cost_usd = 0.0001556 (expected 0)
    → request  POST /webhook/my-cost
      {
        "question": "VPN 접속이 자꾸 끊겨요. 어떻게 하나요?",
        "user": "이준호"
      }
    ← response HTTP 200
      {
        "route": "자동 답변",
        "answer": "VPN 접속 오류는 VPN 클라이언트를 최신 버전으로 업데이트하고, 인증서 만료 여부를 확인한 뒤 다시 접속하시기 바랍니다. 현재 접수된 관련 티켓은 없습니다. 추가 도움이 필요하시면 담당자가 도와드리겠습니다.",
        "sources": [
          "FAQ-003"
        ],
        "llm_calls": 1,
        "usage": {
          "prompt_tokens": 165,
          "completion_tokens": 56,
          "by_step": {
            "answer": {
              "model": "gpt-4.1-mini",
              "prompt_tokens": 165,
              "completion_tokens": 56,
              "cost_usd": 0.0001556
            }
          }
        },
        "cost_usd": 0.0001556,
        "trimmed": false,
        "question_chars": 24,
        "recorded": true
      }
✔ 다른 사람은 그대로 · 1.2s · 자동 답변 · 1 call · $0.000136
    → request  POST /webhook/my-cost
      {
        "question": "비밀번호를 잊어버렸어요. 재설정은 어떻게 하나요?",
        "user": "한지훈"
      }
    ← response HTTP 200
      {
        "route": "자동 답변",
        "answer": "비밀번호 재설정은 사내 포털 로그인 화면의 '비밀번호 찾기'에서 휴대폰 인증 후 새 비밀번호를 설정하시면 됩니다. 추가 도움이 필요하시면 문의해 주세요.",
        "sources": [
          "FAQ-001"
        ],
        "llm_calls": 1,
        "usage": {
          "prompt_tokens": 169,
          "completion_tokens": 43,
          "by_step": {
            "answer": {
              "model": "gpt-4.1-mini",
              "prompt_tokens": 169,
              "completion_tokens": 43,
              "cost_usd": 0.0001364
            }
          }
        },
        "cost_usd": 0.0001364,
        "trimmed": false,
        "question_chars": 27,
        "recorded": true
      }
Passed 3/4
report: runs/lab03-limit-20261028-210727.json
✔ after: POST http://localhost:8800/budget/reset · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.0005996, "remaining_usd": 0.999400
    → request  POST http://localhost:8800/budget/reset
      {}
    ← response HTTP 200
      {
        "daily_usd": 1.0,
        "user_limit_per_min": 20,
        "max_question_chars": 500,
        "used_usd": 0.0005996,
        "remaining_usd": 0.9994004,
        "over": false
      }
✔ after: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 4}
    → request  POST http://localhost:8800/usage-clear
      {}
    ← response HTTP 200
      {
        "cleared": 4
      }
