Resolves the long-pending dose variant decision before Phase 1 schema work:
- habit.dose_variants[] added (id/label/dose_text/context_tags/condition_tags/is_minimum), no cardinality cap.
- tracker_entry gains variant_id + context_snapshot{location,condition}.
- reflection gains weekly minimum_ratio (hint-only).
- data-model.md: R9 (≤4) retired; new R9 (no cap, UX-side enforcement) + R10 (weekly minimum_ratio hint, no threshold).
- docs/adr/0001-dose-variants.md captures rationale + alternatives.
Why now: Phase 1 (#204) needs the final schema shape before Drift DDL is drawn.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
67 lines
3.6 KiB
Markdown
67 lines
3.6 KiB
Markdown
# ADR-0001: Dose Variants (상황·컨디션별 도즈 옵션)
|
||
|
||
> **상태**: Accepted
|
||
> **날짜**: 2026-06-11 · **결정자**: 사용자 (joungmin) + AI 합의 · **관련 이슈**: #204
|
||
|
||
## 맥락 (Context)
|
||
|
||
기존 데이터 모델은 `tracker_entry.value` 가 `done` / `blank` 2값(R5)이고,
|
||
`habit.min_dose` / `target_dose` 가 단일 문자열이었다. 사용자가 컨디션이 나쁘거나
|
||
환경(짐 vs 집, 출장 등)이 풀 도즈와 안 맞을 때, "할 수 없으면 0(blank)"이라는
|
||
이분법이 강요됐다. 결과: blank → lapse → 자책 → abandonment 사이클 위험.
|
||
|
||
BJ Fogg *Tiny Habits* 의 "If tired, do tiny" + Lally 2010 의 자동화 곡선 모두
|
||
"빈도 > 강도" 를 가리킨다. 본 시스템의 "Never miss twice" 가드레일과도 맞물려,
|
||
*상황별 가변 도즈*가 본질적으로 필요하다.
|
||
|
||
## 결정 (Decision)
|
||
|
||
`habit` 에 `dose_variants[]` 배열을 추가한다. 각 variant 는
|
||
`{ id, label, dose_text, context_tags?, condition_tags?, is_minimum? }` 구조.
|
||
`tracker_entry` 에 `variant_id` 와 `context_snapshot { location, condition }` 추가.
|
||
체크인 UX 는 **장소 1탭 + 컨디션 1탭 → 매칭 variant 추천 + override** 흐름.
|
||
|
||
운영 규칙:
|
||
- **R9 신규**: `dose_variants[]` 개수 제한 없음 (기존 R9 ≤4 폐기). `is_minimum=true` 권장이나 강제 X.
|
||
- **R10 신규**: 주간 `reflection.minimum_ratio` 표시 — `is_minimum=true` variant 선택 비율.
|
||
강제 임계값 없음 (SDT autonomy 존중), hint 만.
|
||
|
||
기존 단일 `min_dose` / `target_dose` 필드는 호환성을 위해 보존하되
|
||
`dose_variants` 사용 시 deprecated.
|
||
|
||
## 근거 (Rationale)
|
||
|
||
- **다양성 + 상황 매칭** 둘 다 잡음 (사용자 명시 요구). 옵션 A (3단계 enum) 는
|
||
"다양"이 약함, 옵션 C (매트릭스) 는 가드레일 #2 위반 위험.
|
||
- **체크인 ≤ 60초 (R8) 유지**: "1탭 × 2" 입력 후 자동 추천이므로 마찰 작음.
|
||
- **자유 태그**: 사용자별 컨텍스트(예: '출장-호텔', '주말-새벽') 무한 확장.
|
||
- **is_minimum 플래그**: tiny 가드 계산을 위한 최소한의 메타데이터. enum 강제 안 함.
|
||
- **R10 hint-only**: 강제 임계값은 결정 피로 + 자율성 침해. 데이터만 제공.
|
||
|
||
## 결과 (Consequences)
|
||
|
||
- **긍정**:
|
||
- Never miss twice 가드 강화 (tiny variant 로도 스트릭 유지).
|
||
- 5-Tier Reward T1 (3회 스트릭) 진입 확률 ↑.
|
||
- 컨텍스트 스냅샷 누적으로 향후 자동 추천 학습 가능.
|
||
- **부정 / 비용**:
|
||
- 체크인 UI 가 2-step (상황 입력 + variant 선택) 으로 늘어남. 데이터 1탭 추가.
|
||
- `tracker_entry` 통계가 done/blank 단순 카운트가 아닌, variant level 분석 필요.
|
||
- 사용자가 처음 habit 만들 때 variant 1개 이상 정의해야 하는 onboarding 부담.
|
||
- **후속 작업**:
|
||
- Phase 1 schema 작업 (`#204`) 에 dose_variants 반영.
|
||
- 4개 SoT 마크다운 (huberman / methodologies / breaking / nutrition) 에
|
||
"도즈 변동" 가이드 짧게 추가 (별도 후속).
|
||
- `seed/` 카탈로그 데이터에 권장 variant 예시 포함.
|
||
|
||
## 검토한 대안 (Alternatives Considered)
|
||
|
||
- **옵션 A — 3단계 enum (tiny/normal/strong) + context_tags**
|
||
- 기각 사유: "다양"이라는 사용자 요구가 3단계로 제한됨.
|
||
- **옵션 C — condition × context 2축 매트릭스**
|
||
- 기각 사유: 입력 마찰 큼, 가드레일 #2 (≤2분/일) 위반 위험.
|
||
- **Tiny 가드 — Streak 가중치 (tiny=0.5x)**
|
||
- 기각 사유: "점수화" 느낌이 5-Tier Reward Ladder 의 "행동 단순 카운트" 원칙과 충돌.
|
||
- **Tiny 가드 — 장치 없음**
|
||
- 부분 채택: 강제는 안 함. 다만 reflection 비율 표시는 유지 (정보 제공만).
|