79일차 운영 데이터 기반 Ops Assistant: 실습 15개 · 강의(개요 30장 · 단계 문서 · 4단계 정리 · 05 바이브), 정답본 LAB-A · answers · VIBE-A · tops 포함

This commit is contained in:
mcchae committed 2026-11-03 20:54:35 +09:00
1 parent 9ce9aceba6
commit 6f0ecd59a9
156 files changed
+31640

No files matched your search

+110
View File
@@ -0,0 +1,110 @@
{
"webhook": "my-ops-facts",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"after": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "지난주 영역별 상태",
"body": {},
"expect": {
"equals": {
"health.runs": "red",
"health.alerts": "yellow",
"health.dlq": "red",
"health.quality": "yellow",
"health.cost": "yellow",
"health.release": "red",
"overall": "red"
}
}
},
{
"name": "빨강 · 노랑 목록 (정해진 순서)",
"body": {},
"expect": {
"equals": {
"red": [
"runs",
"dlq",
"release"
],
"yellow": [
"alerts",
"quality",
"cost"
]
}
}
},
{
"name": "첫 주: 오류는 없지만 답 못 함 · 카나리 비교 불가",
"request": "requests/week1.json",
"expect": {
"equals": {
"health.runs": "yellow",
"health.release": "yellow",
"red": [
"dlq"
]
}
}
},
{
"name": "예산을 늘리면 비용은 초록",
"before": [
{
"url": "http://localhost:8800/budget",
"body": {
"daily_usd": 1
}
}
],
"body": {},
"expect": {
"equals": {
"health.cost": "green",
"cost.used_ratio": 0.0736
}
}
},
{
"name": "parked를 처리하면 DLQ는 노랑",
"before": [
{
"url": "http://localhost:8800/dlq/update",
"body": {
"dlq_id": 1,
"remove": true
}
},
{
"url": "http://localhost:8800/dlq/update",
"body": {
"dlq_id": 2,
"remove": true
}
}
],
"body": {},
"expect": {
"equals": {
"health.dlq": "yellow",
"red": [
"runs",
"release"
]
}
}
}
]
}
+77
View File
@@ -0,0 +1,77 @@
{
"webhook": "my-ops-facts",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
},
{
"url": "http://localhost:8800/admin/fault",
"body": {
"usage": "error"
}
}
],
"after": [
{
"url": "http://localhost:8800/admin/fault",
"body": {
"usage": "ok"
}
}
],
"cases": [
{
"name": "비용 출처가 멈춰도 200 · 모르는 것은 모른다고",
"body": {},
"expect": {
"equals": {
"cost": null,
"sources_down": [
"cost"
],
"health.cost": "unknown",
"unknown": [
"cost"
]
}
}
},
{
"name": "다른 영역은 그대로",
"body": {},
"expect": {
"equals": {
"dlq.size": 3,
"health.dlq": "red",
"red": [
"runs",
"dlq",
"release"
],
"overall": "red"
}
}
},
{
"name": "출처가 돌아오면 다시 노랑",
"before": [
{
"url": "http://localhost:8800/admin/fault",
"body": {
"usage": "ok"
}
}
],
"body": {},
"expect": {
"equals": {
"sources_down": [],
"unknown": [],
"health.cost": "yellow",
"cost.used_ratio": 0.9201
}
}
}
]
}
+72
View File
@@ -0,0 +1,72 @@
{
"webhook": "my-ops-facts",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "두 주 (10/19~10/30)",
"request": "requests/two-weeks.json",
"expect": {
"equals": {
"runs.total": 666,
"runs.errors": 21,
"runs.error_rate": 0.0315,
"runs.top_failure.count": 16
}
}
},
{
"name": "하루 (10/26)",
"request": "requests/monday.json",
"expect": {
"equals": {
"runs.total": 70,
"runs.errors": 16,
"runs.top_failure.node": "Search FAQ"
}
}
},
{
"name": "빈 기간 (11/02~11/06) · 0건이어도 200",
"request": "requests/empty-week.json",
"expect": {
"equals": {
"runs.total": 0,
"runs.error_rate": 0,
"runs.p95_ms": 0,
"runs.top_failure": null,
"release.active_repeat_rate": null,
"release.canary_repeat_rate": null
}
}
},
{
"name": "기간을 비우면 지난주 (기본)",
"body": {},
"expect": {
"equals": {
"period.from": "2026-10-26",
"period.to": "2026-10-30",
"runs.total": 357
}
}
},
{
"name": "기간과 상관없는 '지금' 숫자는 그대로",
"request": "requests/empty-week.json",
"expect": {
"equals": {
"alerts.count": 6,
"dlq.size": 3,
"quality.avg_score": 0.6583,
"cost.used_ratio": 0.9201,
"release.active": "1.1.0"
}
}
}
]
}
+96
View File
@@ -0,0 +1,96 @@
{
"webhook": "my-ops-facts",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"after": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "지난주 실행 (기본 기간)",
"body": {},
"expect": {
"equals": {
"period.from": "2026-10-26",
"runs.total": 357,
"runs.errors": 21,
"runs.error_rate": 0.0588,
"runs.p95_ms": 2598,
"runs.top_failure.node": "Search FAQ",
"runs.top_failure.count": 16
}
}
},
{
"name": "지금 상태 · 알림 · DLQ · 품질",
"body": {},
"expect": {
"equals": {
"alerts.count": 6,
"alerts.high": 3,
"alerts.by_reason.low_quality": 2,
"dlq.size": 3,
"dlq.parked": 2,
"quality.avg_score": 0.6583,
"quality.last_score": 1,
"quality.quarantine": 1
}
}
},
{
"name": "비용 · 릴리스",
"body": {},
"expect": {
"equals": {
"cost.requests": 156,
"cost.used_ratio": 0.9201,
"cost.top_user.user": "test-bot",
"cost.top_user.share": 0.3699,
"release.active": "1.1.0",
"release.canary_release": "1.2.0",
"release.canary_repeat_rate": 0.625,
"release.active_repeat_rate": 0.0773
}
}
},
{
"name": "첫 주 (기간을 바꾸면 실행만 바뀜)",
"request": "requests/week1.json",
"expect": {
"equals": {
"runs.total": 309,
"runs.errors": 0,
"runs.top_failure": null,
"release.canary_repeat_rate": null,
"dlq.size": 3
}
}
},
{
"name": "상태가 바뀌면 숫자도 (DLQ #3 처리)",
"before": [
{
"url": "http://localhost:8800/dlq/update",
"body": {
"dlq_id": 3,
"remove": true
}
}
],
"body": {},
"expect": {
"equals": {
"dlq.size": 2,
"dlq.waiting": 0
}
}
}
]
}
+82
View File
@@ -0,0 +1,82 @@
{
"webhook": "my-ops-ask",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "낱말이 없는 비용 질문",
"body": {
"question": "이번 주에 AI 쓰는 데 얼마나 나갔어?"
},
"expect": {
"equals": {
"area": "cost",
"router": "llm",
"refused": false,
"numbers_ok": true
}
}
},
{
"name": "낱말이 없는 DLQ 질문",
"body": {
"question": "어젯밤에 접수 못 하고 남은 건 몇 건이야?"
},
"expect": {
"equals": {
"area": "dlq",
"router": "llm",
"numbers_ok": true
},
"contains": {
"answer": "3"
}
}
},
{
"name": "낱말이 없는 릴리스 질문",
"body": {
"question": "새 판을 일부 사용자에게 먼저 내보낸 거 어떻게 되고 있어?"
},
"expect": {
"equals": {
"area": "release",
"router": "llm",
"numbers_ok": true
},
"contains": {
"answer": "62.5"
}
}
},
{
"name": "LLM도 운영 밖이면 거절",
"body": {
"question": "점심 메뉴 추천해 줘"
},
"expect": {
"equals": {
"refused": true,
"reason": "out_of_scope",
"router": "llm"
}
}
},
{
"name": "낱말이 있으면 LLM을 부르지 않음",
"body": {
"question": "지난주 오류율이 얼마야?"
},
"expect": {
"equals": {
"area": "runs",
"router": "keyword"
}
}
}
]
}
+80
View File
@@ -0,0 +1,80 @@
{
"webhook": "my-ops-ask",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "작업 요청",
"body": {
"question": "DLQ 1번 다시 돌려 줘"
},
"expect": {
"equals": {
"refused": true,
"reason": "read_only"
}
}
},
{
"name": "운영 밖",
"body": {
"question": "점심 메뉴 추천해 줘"
},
"expect": {
"equals": {
"refused": true,
"reason": "out_of_scope"
}
}
},
{
"name": "답한 질문",
"body": {
"question": "지난주 오류율이 얼마야?"
},
"expect": {
"equals": {
"area": "runs",
"refused": false
}
}
},
{
"name": "감사 기록 세 줄 · 거절 이유와 함께",
"url": "http://localhost:8800/audit/list",
"body": {},
"expect": {
"equals": {
"events.0.kind": "ops-ask",
"events.0.reason": "read_only",
"events.0.area": "action",
"events.1.reason": "out_of_scope",
"events.1.router": "llm",
"events.2.area": "runs",
"events.2.refused": false,
"events.2.numbers_ok": true,
"events.3": null
}
}
},
{
"name": "응답은 그대로 (감사는 곁가지)",
"body": {
"question": "DLQ 1번 다시 돌려 줘"
},
"expect": {
"equals": {
"area": "action",
"router": "keyword"
},
"contains": {
"answer": "읽기만"
}
}
}
]
}
+84
View File
@@ -0,0 +1,84 @@
{
"webhook": "my-ops-ask",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "'에러' → 실행",
"body": {
"question": "에러 많이 났어?"
},
"expect": {
"equals": {
"area": "runs",
"router": "keyword",
"refused": false
}
}
},
{
"name": "'장애' 는 낱말 목록에 없음 → 운영 밖으로 거절",
"body": {
"question": "장애 났어?"
},
"expect": {
"equals": {
"area": "unknown",
"refused": true,
"reason": "out_of_scope"
}
}
},
{
"name": "두 영역이 한 번씩 → 앞의 영역 (알림)",
"body": {
"question": "알림이랑 DLQ 둘 다 알려 줘"
},
"expect": {
"equals": {
"area": "alerts"
}
}
},
{
"name": "'꺼 줘' → 작업 요청으로 거절",
"body": {
"question": "카나리 꺼 줘"
},
"expect": {
"equals": {
"area": "action",
"refused": true,
"reason": "read_only"
}
}
},
{
"name": "'배포'(1) 보다 '상태 · 요약'(2) → 전체",
"body": {
"question": "배포 상태 요약해 줘"
},
"expect": {
"equals": {
"area": "overview"
}
}
},
{
"name": "낱말 없는 비용 질문 → 거절 (과제 1에서 LLM 라우터로)",
"body": {
"question": "AI 쓰는 데 얼마나 나갔어?"
},
"expect": {
"equals": {
"refused": true,
"reason": "out_of_scope"
}
}
}
]
}
+96
View File
@@ -0,0 +1,96 @@
{
"webhook": "my-ops-ask",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "실행 · 오류율",
"body": {
"question": "지난주 오류율이 얼마야?"
},
"expect": {
"equals": {
"area": "runs",
"refused": false
},
"contains": {
"answer": "5.88"
}
}
},
{
"name": "DLQ · parked",
"body": {
"question": "DLQ에 parked 된 건 몇 건이야?"
},
"expect": {
"equals": {
"area": "dlq",
"refused": false
},
"contains": {
"answer": "2"
}
}
},
{
"name": "운영과 상관없는 질문은 거절",
"body": {
"question": "점심 메뉴 추천해 줘"
},
"expect": {
"equals": {
"area": "unknown",
"refused": true,
"reason": "out_of_scope"
}
}
},
{
"name": "작업 요청은 거절 (읽기만)",
"body": {
"question": "DLQ 1번 다시 돌려 줘"
},
"expect": {
"equals": {
"refused": true,
"reason": "read_only"
}
}
},
{
"name": "비용 · 숫자 확인",
"body": {
"question": "오늘 LLM 비용이 예산의 몇 퍼센트야?"
},
"expect": {
"equals": {
"area": "cost",
"numbers_ok": true
},
"contains": {
"answer": "92"
}
}
},
{
"name": "릴리스 · 숫자 확인",
"body": {
"question": "카나리 버전 문제 있어?"
},
"expect": {
"equals": {
"area": "release",
"numbers_ok": true
},
"contains": {
"answer": "62.5"
}
}
}
]
}
+117
View File
@@ -0,0 +1,117 @@
{
"webhook": "my-ops-brief",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "아침 그대로",
"body": {},
"expect": {
"equals": {
"red": [
"runs",
"dlq",
"release"
],
"actions.0.area": "runs",
"actions.1.area": "dlq"
}
}
},
{
"name": "parked 둘을 처리하면 → DLQ는 노랑, 먼저 볼 것에 알림",
"before": [
{
"url": "http://localhost:8800/dlq/update",
"body": {
"dlq_id": 1,
"remove": true
}
},
{
"url": "http://localhost:8800/dlq/update",
"body": {
"dlq_id": 2,
"remove": true
}
}
],
"body": {},
"expect": {
"equals": {
"red": [
"runs",
"release"
],
"actions.1.area": "release",
"actions.2.area": "alerts"
},
"contains": {
"markdown": "| DLQ | 🟡 | 1건 (parked 0) |"
}
}
},
{
"name": "카나리를 끄면 → 릴리스는 초록",
"before": [
{
"url": "http://localhost:8800/releases/helpdesk",
"body": {
"canary": null
}
}
],
"body": {},
"expect": {
"equals": {
"red": [
"runs"
],
"actions.1.area": "alerts",
"actions.2.area": "dlq"
},
"contains": {
"markdown": "| 릴리스 | 🟢 | 1.1.0 |"
}
}
},
{
"name": "예산을 올리면 → 비용도 초록",
"before": [
{
"url": "http://localhost:8800/budget",
"body": {
"daily_usd": 0.2
}
}
],
"body": {},
"expect": {
"equals": {
"red": [
"runs"
],
"yellow": [
"alerts",
"dlq",
"quality"
]
}
}
},
{
"name": "남은 빨강은 실행 하나 (사람이 고칠 일)",
"body": {},
"expect": {
"equals": {
"overall": "red",
"actions.0.area": "runs"
}
}
}
]
}
+59
View File
@@ -0,0 +1,59 @@
{
"webhook": "my-ops-eval",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "골든 질문 8개",
"request": "requests/ops-golden.json",
"expect": {
"equals": {
"total": 8,
"area_ok": 8,
"refused_ok": 8
},
"range": {
"score": [
0.875,
1
]
}
}
},
{
"name": "틀린 기대는 잡아냄",
"body": {
"cases": [
{
"question": "알림이 몇 건 와 있어?",
"area": "cost",
"numbers": [
"6"
]
}
]
},
"expect": {
"equals": {
"total": 1,
"passed": 0,
"failed.0.area": "alerts",
"failed.0.area_ok": false
}
}
},
{
"name": "빈 목록 → 400",
"body": {
"cases": []
},
"expect": {
"status": 400
}
}
]
}
+84
View File
@@ -0,0 +1,84 @@
{
"webhook": "my-ops-eval",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "기준을 안 주면 0.9",
"body": {
"cases": [
{
"question": "알림이 몇 건 와 있어?",
"area": "alerts",
"numbers": [
"6"
]
}
]
},
"expect": {
"equals": {
"min_score": 0.9,
"gate": "pass",
"score": 1
}
}
},
{
"name": "골든 8 · 기준 0.8 → 통과",
"request": "requests/ops-golden-gate.json",
"expect": {
"equals": {
"total": 8,
"gate": "pass",
"min_score": 0.8
},
"range": {
"score": [
0.875,
1
]
}
}
},
{
"name": "틀린 기대 · 기준 0.9 → 실패",
"body": {
"cases": [
{
"question": "알림이 몇 건 와 있어?",
"area": "cost",
"numbers": [
"6"
]
}
],
"min_score": 0.9
},
"expect": {
"equals": {
"score": 0,
"gate": "fail"
}
}
},
{
"name": "실패하면 알림 한 건",
"url": "http://localhost:8800/alerts/list",
"body": {
"reason": "eval_below"
},
"expect": {
"equals": {
"count": 1,
"alerts.0.workflow": "ops-eval",
"alerts.0.score": 0
}
}
}
]
}
+39
View File
@@ -0,0 +1,39 @@
{
"webhook": "my-ops-brief",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "요약 세 문장 · 숫자 확인",
"body": {},
"expect": {
"equals": {
"numbers_ok": true,
"overall": "red"
},
"contains": {
"markdown": "## 요약"
}
}
},
{
"name": "요약에 급한 곳",
"body": {},
"expect": {
"contains": {
"summary": [
"DLQ",
"릴리스",
"카나리",
"실행",
"오류"
]
}
}
}
]
}
+72
View File
@@ -0,0 +1,72 @@
{
"webhook": "my-ops-brief",
"before": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"after": [
{
"url": "http://localhost:8800/ops-reset",
"body": {}
}
],
"cases": [
{
"name": "전체 · 먼저 볼 것 셋",
"body": {},
"expect": {
"equals": {
"overall": "red",
"red": [
"runs",
"dlq",
"release"
],
"actions.0.area": "runs",
"actions.1.area": "dlq",
"actions.2.area": "release"
}
}
},
{
"name": "표에 숫자",
"body": {},
"expect": {
"contains": {
"markdown": "| DLQ | 🔴 | 3건 (parked 2) |"
}
}
},
{
"name": "할 일은 규칙에서",
"body": {},
"expect": {
"contains": {
"markdown": "카나리 끄기 · 되돌리기 검토 (74일차)",
"actions.1.action": "parked"
}
}
},
{
"name": "DLQ를 비운 뒤",
"before": [
{
"url": "http://localhost:8800/dlq-clear",
"body": {}
}
],
"body": {},
"expect": {
"equals": {
"red": [
"runs",
"release"
],
"actions.2.area": "alerts"
}
}
}
]
}