docs(spec): stub due-date extraction spec for post-slice work

Captures the design skeleton, hypotheses, and open questions for the
hybrid (rule-based first → AI fallback) Korean date-phrase extractor.
Schema impact, prompt change, UX copy, and library tradeoffs are
sketched but deferred — formalization waits for slice v0.4 dogfood
Pass and the H1 (time-phrase frequency ≥ 30%) check in week-1 retro.

Cross-link added to dogfood-strategy daily-metric table so the H1
data is collected during dogfood, and to README docs map.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
altair823
2026-04-25 17:07:20 +09:00
parent df56661f4f
commit c5e5975a12
3 changed files with 191 additions and 0 deletions

View File

@@ -163,6 +163,7 @@ inkling.md 원본 제품 브리프 v1.4
| 심리학 전략 | `docs/superpowers/strategy/strategy.md` | 행동 변화 모델, 회복 친화 스트릭 |
| Dogfooding 전략 | `docs/superpowers/strategy/dogfood-strategy.md` | 2주 자기 dogfood 운영안 |
| 슬라이스 설계 | `docs/superpowers/specs/2026-04-24-inkling-vertical-slice-design.md` | v0.4 spec, 부하 전달 결정의 출처 |
| Due Date 추출 (stub) | `docs/superpowers/specs/2026-04-25-due-date-extraction-design.md` | 슬라이스 dogfood 후 정식화할 후속 spec 골격 |
| 구현 계획 | `docs/superpowers/plans/2026-04-24-inkling-vertical-slice.md` | 33-task TDD 플랜 |
| 핸드오프 | `docs/handoff/2026-04-25-linux-to-windows.md` | Linux→Windows 전환 메모 |

View File

@@ -0,0 +1,189 @@
# Inkling — Due Date 추출 설계 문서 (Stub)
**작성일:** 2026-04-25 (v0.1, stub)
**저자:** 김태현 (dlsrks0734@gmail.com)
**상태:** ⚠️ Stub — 슬라이스 v0.4 dogfood 종료 후 정식 작성. 본 문서는 후속 spec 의 골격과 결정 대기 항목만 담는다.
**선행 문서:**
- `docs/superpowers/specs/2026-04-24-inkling-vertical-slice-design.md` v0.4 (슬라이스 종료 후 본 spec 시작)
- `docs/superpowers/strategy/strategy.md` §2.2 (Clarify 단계의 의미 부여), §7-원칙4 (AI 확신도 낮게)
- `docs/superpowers/strategy/dogfood-strategy.md` (1주차 회고에서 due_date 필요성 검증 항목)
---
## 0. 목적
캡처된 노트 본문에 시간 표현이 들어가면 (`오늘`, `내일`, `이번 주`, `다음 주`, `다음 달`, `N일 뒤`, `N월 N일`, `금요일까지` 등) 로컬 KST 기준으로 ISO 날짜를 추출해 `due_date` 후보로 제안한다. AI 가 단정하지 않고 사용자가 수락·편집·무시할 수 있는 **제안형 라벨**로 노출한다 (Strategy §7-원칙4).
---
## 1. 가설
| # | 가설 | 측정 |
|---|------|------|
| H1 | 슬라이스 dogfood 노트 중 시간 표현 포함 비율이 ≥ 30% | 1주차 dogfood 로그 회고에서 본인 노트 분류 |
| H2 | 규칙 기반 파서가 일상 한국어 시간 표현의 ≥ 80% 를 정확히 변환 | 골든 픽스처 50건 + 단위 테스트 |
| H3 | due_date 후보 수락률 ≥ 60% (제안 중 사용자가 그대로 수락한 비율) | post-launch 측정 |
H1 이 미달이면 본 spec 자체가 불필요 — dogfood 회고에서 먼저 H1 부터 판정한다.
---
## 2. 범위
### 2.1 In-scope
- **하이브리드 추출**: 규칙 기반 파서가 1차 시도 → 매칭 없을 시에만 AI 프롬프트에 위임. 슬라이스의 비동기 AI 단계와 동일 큐에서 동작.
- **상대 표현**: `오늘`, `내일`, `모레`, `이번 주 *요일`, `다음 주`, `다음 달`, `N일/N주/N개월 뒤`.
- **절대 표현**: `N월 N일`, `YYYY-MM-DD`, `MM/DD`. 연도 미명시 시 가까운 미래로 해석.
- **기준 시점**: KST 자정 (`Date.now()` + `Asia/Seoul` 시간대). ContinuityService 의 KST 주 경계 정의와 동일 라이브러리 재사용.
- **UI**: NoteCard 에 `📅 YYYY-MM-DD` 작은 회색 라벨. AI 라벨 정책과 동일하게 사용자 편집 시 라벨 사라짐. 인라인 편집/삭제 가능.
- **수정 추적**: `due_date_edited_by_user` 컬럼 추가, AI 재실행이 사용자 편집을 덮어쓰지 않음 (slice §3.3 invariant 2 와 동일 패턴).
### 2.2 Out-of-scope
- 캘린더 알림·스케줄러 (별도 spec)
- 시각 단위 추출 (`오후 3시`, `15:30`) — 본 spec 은 날짜만, 시각은 후속
- 음력 / 절기 / "월말", "주말 안에" 같은 모호 표현 — AI 위임으로만 처리, 정확도 보장 안 함
- 반복 일정 (`매주 월요일`)
- 외부 캘린더 연동 (Google, Outlook)
---
## 3. 파서 vs AI 분기 정책
```
입력 텍스트
규칙 파서 (정규식 + chrono-style)
매칭 있음? ──→ ISO 날짜 + confidence: high
└─ 매칭 없음 + 시간 후보 어휘 감지 ──→ AI 프롬프트 확장 (due_date 필드)
AI 응답에 ISO 있음? ──→ confidence: medium
AI 응답 비었음? ──→ due_date null
```
규칙 파서는 동기·결정론적·테스트 가능. AI 분기는 슬라이스의 AiWorker 큐를 그대로 사용 (별도 호출 추가 안 함, 같은 generate 응답에 필드 추가).
`confidence` 메타는 DB 에 저장하지 않고 UI 라벨 색조로만 표현 (high = 진한 회색, medium = 옅은 회색).
---
## 4. 데이터 변경
### 4.1 Migration v2 (forward-only)
```sql
ALTER TABLE notes ADD COLUMN due_date TEXT;
ALTER TABLE notes ADD COLUMN due_date_edited_by_user INTEGER NOT NULL DEFAULT 0;
```
`due_date` 형식: `YYYY-MM-DD` (KST 자정 기준). null = 추출 안 됨.
### 4.2 NoteRepository 변경
- `updateAiResult` 시그니처에 `dueDate?: string | null` 추가, edited-flag CASE WHEN 가드 적용
- `setDueDate(noteId, date)` 사용자 수정 메서드 신설, `due_date_edited_by_user = 1`
### 4.3 zod 스키마 확장
`AiResponse``due_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional()` 추가. AI 가 빈 응답 또는 잘못된 형식 반환 시 정상 누락 처리 (스키마 검증 실패로 전체 응답 reject 안 함 → strict → loose 변환).
---
## 5. 프롬프트 변경 (AI 분기 시에만)
기존 프롬프트 끝에 추가:
```
입력 텍스트에서 마감일 또는 일정 날짜를 의미하는 표현이 있으면 ISO 형식 (YYYY-MM-DD) 으로 추출. KST 기준 오늘은 {{TODAY_KST}}. 추출 불가능하면 null.
```
`{{TODAY_KST}}``LocalOllamaProvider.generate` 시점에 주입. 시간대 처리는 main process 에서.
---
## 6. UX 카피 (Strategy 준수)
| 상황 | 카피 |
|------|------|
| 추출 성공 | `📅 {YYYY-MM-DD}` (작은 회색 라벨) |
| 사용자 편집 후 | `📅 {YYYY-MM-DD}` (회색 → 검정, AI 라벨 제거) |
| 만료 임박 (≤ 1일) | `📅 {YYYY-MM-DD}` 노란 배경 |
| 만료됨 | `📅 {YYYY-MM-DD}` 회색 + 취소선. **"실패", "지각", "놓침" 같은 단어 금지** (slice §1.1 카피 정책 상속) |
만료 노트 처리 정책은 본 spec 에서 결정 — 자동 삭제 ❌, 자동 done ❌, 단지 시각적 표시만.
---
## 7. 결정 대기 항목 (dogfood 회고 후 결론)
본 spec 을 정식화하기 전 1주차 dogfood 로그에서 답해야 할 질문:
1. **얼마나 자주 시간 표현이 들어가나?** (H1 검증)
2. **"오늘 PR 리뷰"** 같은 노트는 due 가 정말 오늘인가, 아니면 단순 맥락어인가? — false positive 비율 추정
3. **due_date 가 있는 노트를 다시 보고 싶은 트리거는 무엇인가?** (Inbox 자체 / 별도 뷰 / 알림)
4. **`📅` 라벨이 NoteCard 의 어느 슬롯에 붙어야 자연스러운가?** (제목 옆, 태그 옆, 별도 줄)
5. **AI 가 추출한 due_date 가 틀렸을 때 사용자가 어떻게 알아채나?** — 카피·색조로 confidence 차이를 충분히 전달할 수 있나
6. **만료된 노트를 별도 필터로 보고 싶은가, 아니면 인라인 처리만으로 충분한가?**
---
## 8. 단계별 산출물
본 spec 정식화 후 plan 작성 시 예상 task 묶음 (본 stub 시점에선 추정만):
- **데이터:** migration v2, NoteRepository 시그니처 확장 (단위 테스트 포함)
- **추출:** `DateExtractor` 모듈 (정규식 + 자체 KST 변환). 골든 픽스처 50건. AI 위임 분기 라우팅
- **AI:** schema/prompt 확장, AiWorker 응답 매핑 변경
- **UI:** NoteCard 라벨 슬롯, EditableField 재사용, 만료 색조
- **마이그레이션 안전성:** 기존 노트의 `due_date_edited_by_user = 0` 디폴트, `due_date NULL` 처리 검증
---
## 9. Slice 와의 관계
본 spec 은 **슬라이스 v0.4 dogfood Pass 판정 후에만 시작.** 이유:
- 슬라이스의 3 가설 (3초 마찰 / AI 품질 / 행동 루프) 중 어느 것도 due_date 없이 검증 가능
- migration v2 + 컬럼 2개 + UI 슬롯 = 작지 않은 변화. 슬라이스 invariant 6 ("AI 재실행은 user-edited 필드 덮어쓰기 금지") 의 적용 표면을 확장하므로 dogfood 안정성 검증 후 진입이 안전
- dogfood 1주차 회고에서 H1 (시간 표현 빈도 ≥ 30%) 이 미달이면 본 spec 자체가 폐기되고, 30% 이상이면 본 stub 을 v0.2 로 정식화
---
## 10. 라이브러리 후보
| 라이브러리 | 평가 |
|-----------|------|
| `chrono-node` | 영어·한국어 일부 지원, 활성. 한국어 커버리지가 핵심 표현 외에는 약함 |
| 자체 정규식 | 핵심 표현 (`오늘`, `내일`, `N일 뒤`) 만 6~8개 패턴으로 충분. 결정론적·테스트 쉬움. 권장 |
| `dayjs` + 사용자 정의 파서 | 한국어 표현은 직접 처리, 시간대 변환은 dayjs 의 `tz` 플러그인. 의존성 증가 |
권장: **자체 정규식 + Intl.DateTimeFormat + KST 변환 헬퍼.** 외부 의존성 추가 없음, 슬라이스의 ContinuityService 가 이미 KST 변환 로직 보유 → 재사용.
---
## 부록 A. 골든 픽스처 후보 (정식화 시 확장)
```
"오늘 PR 리뷰" → null 또는 today (양가)
"내일 회의 준비" → tomorrow
"다음 주 월요일까지 슬라이드" → next-mon
"3일 뒤 데모" → today+3
"5월 1일 휴가 신청" → 2026-05-01
"이번 주 안에 리팩터링" → 이번 주 일요일
"월말 마감" → 해당 월 말일 (AI 위임 후보)
"주말까지" → 이번 주 일요일 (AI 위임 후보)
"퇴근 전" → today (시각 단위는 본 spec 범위 밖이지만 fallback)
```
각 케이스의 confidence 등급 + 사용자 가설 행동(수락 / 편집 / 무시)을 dogfood 회고에서 본인이 직접 라벨링한다. 이 라벨링이 H2 / H3 측정의 근거.
---
## 부록 B. 미정 정책
- "오늘" 의 시간대 — 자정 기준인가, 24시간 후인가? (KST 자정으로 잠정 결정, dogfood 후 검증)
- 사용자 명시적 due_date 와 AI 추출 due_date 의 시각적 구분 (현재 안: AI 라벨 색조)
- due_date 검색·필터 UI — 본 spec 범위 vs 별도 spec

View File

@@ -96,6 +96,7 @@ dogfood 첫 날 시작 전, 환경을 한 번에 정렬한다.
| 트리거 응답률 | 회의 후·퇴근 전 트리거에 실제로 캡처한 횟수 / 트리거 발생 횟수 | 본인 카운트 |
| AI 수용률 | AI 생성 필드를 그대로 둔 노트 수 / 전체 캡처 수 | Inbox 의 "AI" 라벨 잔존율 |
| `pending` 스택 | 24시간 이상 `pending` 상태로 남은 노트 수 | Inbox PendingBanner |
| 시간 표현 포함 노트 수 | `오늘`/`내일`/`N일 뒤`/`N월 N일` 등 시간 어휘가 들어간 노트 수 — due-date-extraction spec H1 (≥ 30%) 검증용 | 본인 라벨링 (로그 §6 자유 메모) |
### 3.2 주간 지표 (일요일 갱신)