Dataset Status State Machine (#464)¶
Mapping from Drift Classification (#382) to Dataset Status (#439).
Status names are the canonical set from
ADR 0005 and
kpubdata.core.status.DatasetStatus; classifications are
kpubdata.core.status.DriftClassification. tests/unit/test_status_vocabulary.py
fails when this page uses a name the code does not define.
State Diagram¶
┌─────────────────────────────────┐
│ retired (terminal) │
│ (manual transitions only) │
└─────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ production │
│ (manual promotion only) │
└─────────┬────────────────┬───────────────┬──────────────┘
│ │ │
SCHEMA_CHANGED RATE_LIMIT / AUTH /
PARAMETER_CHANGED SERVICE_DOWN / APPLICATION_
ENDPOINT_CHANGED UNKNOWN (≥3) REQUIRED (≥1)
(≥1, immediate) │ │
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────┐ ┌──────────────────┐
│ broken │ │unstable │ │application_required│
└──────┬──────┘ └────┬────┘ └──────────────────┘
│ │
HEALTHY (≥1) HEALTHY (≥3)
+ fixture │
re-record │ (restore previous)
│ │
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ fixture_ │ │ previous status │
│ verified │ │ (or live_verif.)│
└─────────────┘ └─────────────────┘
Transition Rules¶
| Current Status | Drift Classification | Streak | Next Status |
|---|---|---|---|
production |
RATE_LIMIT, SERVICE_DOWN, UNKNOWN |
1–2 | (no change, record only) |
production |
RATE_LIMIT, SERVICE_DOWN, UNKNOWN |
≥3 | unstable |
production |
SCHEMA_CHANGED, PARAMETER_CHANGED, ENDPOINT_CHANGED |
≥1 | broken (immediate) |
production |
AUTH, APPLICATION_REQUIRED |
≥1 | application_required |
production |
NO_DATA |
≥3 | unstable |
production |
RETIRED |
≥1 | (no change; drift issue filed — a person retires it) |
live_verified |
(same as production) | — | (same as production) |
fixture_verified |
any failure | ≥1 | fixture_verified (no auto downgrade) |
unstable |
HEALTHY |
≥3 | restore previous_status |
unstable |
SCHEMA_CHANGED, PARAMETER_CHANGED, ENDPOINT_CHANGED |
≥1 | broken (immediate) |
unstable |
any failure (cumulative) | ≥7 | broken |
broken |
HEALTHY |
≥1 | fixture_verified (requires fixture re-record) |
application_required |
HEALTHY |
≥1 | restore previous_status (application approved) |
retired |
all inputs | — | (no transitions; manual only) |
Core Principles¶
- Schema/Parameter/Endpoint changes break immediately — user code breaks, no delay
- Transient failures (429, 5xx) use a 3-strike rule — prevents false positives.
The number is
TRANSIENT_FAILURE_STREAK; LIVE_PROBE.md files its drift issue on the same count brokennever auto-restores toproduction— a human must re-record fixtures and pass contract testsretiredis terminal — only manual transitions
Decisions¶
previous_status storage¶
Yes — stored in fixtures/<dataset>/status_history.json alongside the existing meta.
Simple, co-located with the data it describes, and inspectable without GitHub API calls.
Transition history location¶
fixtures/<dataset>/status_history.json:
[
{"from": "live_verified", "to": "unstable", "reason": "SERVICE_DOWN", "streak": 3, "at": "2026-09-29"},
{"from": "unstable", "to": "live_verified", "reason": "HEALTHY", "streak": 3, "at": "2026-09-30"}
]
Drift Issue Title convention¶
Example:[drift] datago.apt_trade: live_verified → broken (SCHEMA_CHANGED)
Labels: type:bug, epic:trust, plus severity:major for broken, severity:minor for unstable.
구현 (#625)¶
이 절의 결정은 scripts/drift_detect.py 가 구현하고, live-probe 워크플로의 drift 잡이
매일 밤 실행한다. 드리프트 상태(스트릭·previous_status·누적 실패)는 drift-state.json
아티팩트로 밤사이 이어지고, 전이가 일어나면 위 규약대로 이슈를 연다 — 같은 데이터셋에
열려 있는 [drift] 이슈가 있으면 다시 열지 않는다. status_history.json 기록은
--write-history 에서 담당하며, nightly 에는 끈다: 게이트가 저장소에 쓸 수는 없으므로
이슈 본문에 추가할 항목을 싣고, 사람(또는 에이전트)이 적용한다. RETIRED 는 상태를
움직이지 않지만 이슈는 연다 — 폐기는 사람의 판단이다.
Pure Function¶
def transition(
current: DatasetStatus | str,
classification: DriftClassification | str,
streak: int,
cumulative_failures: int = 0,
previous_status: DatasetStatus | str | None = None,
) -> DatasetStatus:
"""Compute the next dataset status from drift signal."""
Implemented as kpubdata.core.status.transition() (#625), with the vocabulary
(DatasetStatus, DriftClassification, TRANSIENT_FAILURE_STREAK). restore
previous_status falls back to live_verified when there is none, or when it names a
fault. tests/unit/core/test_status_transition.py runs every row of the table above
against the function, so the table and the code cannot drift apart.