diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json new file mode 100644 index 0000000..547459b --- /dev/null +++ b/.codex-plugin/plugin.json @@ -0,0 +1,36 @@ +{ + "name": "working-diary", + "version": "4.2.0", + "description": "Record AI coding sessions as Markdown diaries or task-based Notion entries.", + "author": { + "name": "solzip", + "url": "https://github.com/solzip" + }, + "homepage": "https://github.com/solzip/claude-code-hooks-diary", + "repository": "https://github.com/solzip/claude-code-hooks-diary", + "license": "MIT", + "keywords": [ + "diary", + "productivity", + "work-log", + "notion", + "codex", + "claude-code" + ], + "skills": "./skills/", + "interface": { + "displayName": "Working Diary", + "shortDescription": "Record Codex work sessions to Markdown or Notion.", + "longDescription": "Working Diary adds Codex skills for writing manual Markdown diary entries and pushing task-sized session records to a hierarchical Notion database. It keeps project, purpose, task group, branch, status, categories, files, commands, commits, and dependencies available as filterable Notion columns.", + "developerName": "solzip", + "category": "Productivity", + "capabilities": [ + "Interactive", + "Write" + ], + "defaultPrompt": [ + "Use $diary to record this session.", + "Use $diary-notion to push this session to Notion." + ] + } +} diff --git a/.gitignore b/.gitignore index 56d1a7a..4eb513a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ Thumbs.db # Original archive (source already extracted) claude-code-working-diary.tar.gz + +# /diary-notion 임시 JSON (Claude가 cwd에 작성 → CLI가 자동 삭제 / 부분 실패 시 보존) +.diary-notion-*.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d6f638..496f963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [Unreleased] + +### Added +- **`/diary-notion` 슬래시 커맨드**: 현재 세션을 작업 단위로 분리해 Notion 업무일지 DB에 push + - 계층 구조: 루트 페이지 → 연도 페이지 → 단일 Entries DB (자동 생성) + - 작업 분리: branch 경계 → 의미 단위 (semantic-first) + - LLM은 슬래시 커맨드 안의 Claude가 처리 — 별도 Anthropic API 키 불필요 + - 멱등성: Session ID + Task Index 컬럼으로 skip, `--force` 시 archive&recreate + - 에러 분기: 401/403 fail fast, 400 skip, 429/5xx retry, 404 자동 재생성 +- **`claude-diary diary-notion init`**: 대화형 셋업 (token + 페이지 URL/ID + 권한 검증) +- **`claude-diary diary-notion push --input ` `--force`**: 임시 JSON 파일 받아 Notion에 push +- **Codex 표준 지원**: `$diary`, `$diary-notion` skills + `.codex-plugin/plugin.json` +- **중립 CLI alias**: `working-diary` 명령을 `claude-diary`와 동일하게 제공 +- **DB 자동 생성 스키마**: Name, Date, Work Period, Project, Purpose, Branch, Status, Task Group, Parent Task, Sub-items, Depends On, Priority, Next Action, Blocked, Block Reason, Carryover, Review Status, Last Reviewed, Categories, Files, Commits, Lines, Session ID, Task Index +- **Notion native 하위항목 연결**: push가 부모-자식을 Notion **native sub-item 관계**(UI에서 1회 활성화, locale 이름 예 `상위 항목`/`하위 항목`)에 기록해 실제 접기/펼치기 nesting을 구동. 코드가 native 관계를 이름 하드코딩 없이 자동 탐지(소거법 + locale 토큰). `ensure`가 `작업 계층` view를 native 관계로 연결하고 기존 `Parent Task` 데이터를 native로 이전(멱등). native 미활성 시 작업 기록은 진행하고 활성화 안내 출력. 기존 영문 `Parent Task`/`Sub-items` 관계는 legacy로 유지·숨김, `Depends On`은 선행 관계로 유지 +- **접힌 근거 중심 Notion 본문**: page body를 핵심 callout 1개, 결과 체크리스트, 작업 한눈에 표, 영향 bullet, 검증 checklist, 리스크/다음 액션, 접힌 부록 구조로 압축 +- **Working Diary OS 비전 문서**: Structure → Views → Operations → Intelligence → Multi-project OS로 확장하는 최고모델 설계, 최소 명령 원칙, 전날 todo 기반 `today-plan`, schema/view conflict drift 관리 방향 추가 +- **2차 View 설계 문서**: `working-diary diary-notion ensure`, `--year`, `--dry-run`과 Core Views 5개, operating views 5개, `Work Period`와 `Sub-items` 기반 schema v7 방향, 하위 항목 데이터 구조, sub-item UI best-effort/fallback, partial failure/exit code 정책 정리 +- **`working-diary diary-notion ensure` 구현**: schema v7 `Work Period`, native sub-item relation, Priority/Blocked/Review 운영 컬럼 보장, Core Views 5개와 Operating Views 5개 생성/검증/update, `--year`, `--dry-run`, required setting repair 지원 +- **`claude-diary write --input `**: Codex skill이 생성한 JSON으로 수동 Markdown 일지 작성 +- **`lib/notion_cache.py`**: 연도 페이지/DB/행 ID 캐시 (root_page_id 변경 시 자동 무효화) +- **`lib/git_info.py` 확장**: `get_branch_for_commit`, `get_head_branch`, `get_commit_info`, `get_diff_stat_for_commits` +- **테스트 보강**: Notion Purpose, Codex plugin/skills, Codex JSON input 경로 검증 (전체 583 통과) + +### Changed +- `cli/setup.py` 일반화: `SLASH_COMMANDS` dict로 다중 슬래시 커맨드 관리 +- `formatter.py`: Notion API blocks 빌더 (`build_notion_blocks`) 추가 및 compact executive body 렌더링 보강 +- 설계 문서: [`docs/02-design/features/diary-notion-hierarchical.design.md`](docs/02-design/features/diary-notion-hierarchical.design.md) + ## [4.1.0] - 2026-03-17 (Phase D) ### Added diff --git a/MANIFEST.in b/MANIFEST.in index 15bbabd..ee03dfa 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,3 +3,5 @@ include CHANGELOG.md include SECURITY.md include README.md include README.en.md +recursive-include .codex-plugin *.json +recursive-include skills *.md *.yaml diff --git a/README.en.md b/README.en.md index b789c50..07972ac 100644 --- a/README.en.md +++ b/README.en.md @@ -114,9 +114,37 @@ For when you want to record an entry mid-session without waiting for the Stop Ho **Usage:** - Inside a Claude Code session: type `/diary` — reads the current cwd's transcript and writes the entry +- Inside a Codex session: type `$diary` — writes the current conversation/tool context through the same manual diary path - Or from the terminal: `claude-diary write` `claude-diary install` installs `~/.claude/commands/diary.md` so `/diary` works in every project. Re-run it once if you installed before this feature shipped (it's idempotent). `claude-diary uninstall` removes it (preserves user-modified files). +Codex skills can be installed from the Codex plugin in this repo or with `claude-diary install --codex`. + +## Notion Work Diary — `/diary-notion` / `$diary-notion` + +Push the current session to a hierarchical Notion database as task-sized rows. Use `/diary-notion` in Claude Code and `$diary-notion` in Codex. + +``` +[Notion root page: "Working Diary"] + └── 2026 (auto-created) + └── Entries (inline DB, auto-created) + ├── "Decide Notion DB schema" | Project: claude-diary | Purpose: Planning + ├── "Refactor git_info.py" | Project: claude-diary | Purpose: Refactor + └── ... +``` + +Rows include filterable/groupable/relational/operating columns for `Project`, `Purpose`, `Task Group`, `Parent Task`, `Sub-items`, `Depends On`, `Branch`, `Status`, `Work Period`, `Priority`, `Blocked`, `Next Action`, `Review Status`, and `Categories`. `Project` is the command cwd folder name; if a task JSON omits it or writes `unknown`, the CLI falls back to the cwd folder. Run `working-diary diary-notion ensure` to create or verify schema v7, native sub-items, 5 core views, and 5 operating views. +Hierarchy nests through Notion's **native sub-item relation**, which can only be enabled in the Notion UI (locale-named, e.g. `Parent item`/`Sub-item` or `상위 항목`/`하위 항목`): open the year's `Entries` DB → ⋯ menu → Sub-items, once. push then writes each child's parent link into that native relation (auto-detected without hardcoded names), `ensure` points the 작업 계층 view at it and migrates legacy `Parent Task` links over. Until it is enabled, rows are still recorded and push prints a hint; the legacy `Parent Task`/`Sub-items` relation never drove native nesting and is kept hidden. `Depends On` is limited to prerequisite links between large top-level tasks. Do not connect subtasks with dependency relations. `working-diary diary-notion ensure` repairs required core/operating view settings, while `--dry-run` reports update plans without writing. Operating views cover today priority, previous unfinished work, blocked work, review-needed work, and task groups. Each Notion page body stays compact with one top summary callout, checked result items, a work-at-a-glance table, impact bullets, checked verification items, risks/next actions, and appendix toggles. Developer evidence such as code changes, files, commands, Git, and original prompts is hidden in the appendix. Code changes are high-signal summaries, not full diffs; include only behavior, schema, CLI, user workflow, or verification-scope changes. +Titles and narrative body content are written in Korean. File paths, commands, branches, commit hashes, code identifiers, and `Purpose`/`Status` enum values remain literal or English. + +```bash +claude-diary diary-notion init +working-diary diary-notion ensure +/diary-notion # Claude Code +$diary-notion # Codex +``` + +Purpose values use stable English labels: `Feature`, `Bugfix`, `Refactor`, `Docs`, `Test`, `Infra`, `Planning`, `Research`, `Review`, `Release`, `Support`, `Maintenance`, `General`. ## Diary Example @@ -177,6 +205,7 @@ export CLAUDE_DIARY_TZ_OFFSET="-5" # EST (UTC-5) ```bash claude-diary write # Write current session diary on demand (also via `/diary` slash command) +working-diary write # Neutral alias for the same CLI claude-diary search "keyword" # Keyword search claude-diary filter --project my-app # Filter by project claude-diary trace src/main.py # File change history diff --git a/README.md b/README.md index 2cc36e8..a844e97 100644 --- a/README.md +++ b/README.md @@ -114,9 +114,181 @@ cd claude-code-hooks-diary/working-diary-system **사용법:** - Claude Code 세션에서 `/diary` 입력 → 현재 cwd의 transcript를 읽고 기록 +- Codex 세션에서 `$diary` 입력 → 현재 대화/도구 사용 내역을 JSON으로 정리해 같은 경로에 기록 - 또는 터미널에서 `claude-diary write` `claude-diary install` 시 `~/.claude/commands/diary.md`가 함께 설치되어 모든 프로젝트에서 `/diary` 사용 가능. 이미 설치한 적 있다면 한 번 더 실행해서 슬래시 커맨드만 추가하세요 (멱등). `claude-diary uninstall` 시 함께 제거됩니다 (사용자가 수정한 파일은 보존). +Codex skill은 repo의 Codex plugin으로 설치하거나 `claude-diary install --codex`로 `~/.codex/skills`에 설치할 수 있습니다. + +## Notion 업무일지 — `/diary-notion` / `$diary-notion` + +현재 세션을 **작업 단위로 분리**해 Notion DB에 push합니다. Claude Code에서는 `/diary-notion`, Codex에서는 `$diary-notion`을 사용합니다. 별도 LLM API 키 없이 현재 에이전트 세션 컨텍스트로 동작하며, Notion 무료 플랜에서도 동작. + +``` +[Notion 루트 페이지: "Working Diary"] + └── 📄 2026 (자동 생성) + └── 🗄️ Entries (인라인 DB, 자동 생성) + ├── "Notion DB 컬럼 스키마 결정" | Project: claude-diary | Branch: feat/notion + ├── "git_info.py 리팩토링" | Project: claude-diary | Purpose: Refactor + └── ... +``` + +한 세션의 의논/구현이 의미 단위로 N개 행으로 분리되어 들어갑니다. branch가 바뀌면 무조건 새 task로 분리합니다. `Project`, `Purpose`, `Task Group`, native 하위항목 관계, `Depends On`, `Work Period`, `Priority`, `Blocked`, `Next Action` 컬럼으로 Notion에서 필터/그룹/관계/운영 상태 조회가 가능합니다. + +현재 구현 기준: + +| 항목 | 동작 | +|------|------| +| `/diary-notion`, `$diary-notion` | 현재 세션을 작업 row로 분리해 Notion에 push | +| `working-diary diary-notion ensure` | schema v7, native sub-items 연결, core views 5개, operating views 5개 보장 | +| 하위항목 (native sub-item) | push가 부모 링크를 Notion **native sub-item 관계**(예: `상위 항목`/`하위 항목`)에 기록 → 실제 접기/펼치기 nesting. native 관계가 없으면 기록만 하고 활성화 안내 | +| `Parent Task` / `Sub-items` (legacy) | 과거에 쓰던 영문 관계. native가 아니라 nesting을 못 구동. `ensure`가 native로 데이터 이전 후 view에서 숨김 | +| `Depends On` | 하위 작업이 아니라 큰 메인 작업끼리의 선행 연결성 | +| `Project` | task JSON에 없거나 `unknown`이면 명령 실행 cwd 폴더명으로 보정 | +| Page body | compact executive body. 결과/작업 한눈에/영향/검증/리스크/부록 순서 | + +`$diary-notion`과 `/diary-notion`은 작업 row push에 집중합니다. DB schema와 view 정리는 `working-diary diary-notion ensure`로 분리되어 있어, view API 문제가 작업 기록 실패로 바로 이어지지 않습니다. + +각 Notion 페이지 본문은 `body_intro` 핵심 callout 1개, `결과` 체크리스트, `작업 한눈에` 표, `영향` bullet, `검증` 체크리스트, `리스크 / 다음 액션`, `부록` 순서로 생성됩니다. 코드 변경·파일·명령어·Git·원문 요청은 접힌 부록(toggle)에 기록합니다. 코드 변경은 full diff가 아니라 동작/스키마/CLI/사용자 흐름/검증 범위를 바꾼 주요 변경만 남깁니다. + +제목과 설명형 본문은 한국어로 기록하고, 파일 경로/명령어/branch/commit hash/코드 식별자 및 `Purpose`, `Status`, `Priority`, `Review Status` enum 값은 원문 또는 영어 값을 유지합니다. + +### 5분 셋업 + +1. **Notion Integration 토큰 발급** — https://www.notion.so/my-integrations → "New integration" → 토큰 복사 (`secret_...`) +2. **Notion에 루트 페이지 생성** — 이름 자유 (예: "Working Diary") +3. **그 페이지를 Integration에 공유** — 페이지 우상단 ⋯ → "Connections" → 만든 Integration 추가 +4. **셋업 명령 실행**: + ```bash + claude-diary diary-notion init + ``` + 대화형으로 token과 root page URL(또는 ID)을 입력하면 권한 검증 후 config에 저장됩니다. +5. **DB schema와 core/operating views 보장**: + ```bash + working-diary diary-notion ensure + ``` +6. **Codex에서 쓸 경우 skill 설치 또는 갱신**: + ```bash + claude-diary install --force --codex + ``` +7. **세션에서 `/diary-notion` 또는 `$diary-notion` 입력** — 작업 분리 + Notion push 자동 실행 + +> **하위항목(nesting) 1회 활성화** — Notion의 native sub-item 토글은 **UI에서만** 켤 수 있고 API로는 생성·지정할 수 없습니다. `ensure`로 DB가 만들어진 뒤 한 번: +> 1. Notion에서 그 해의 `Entries` DB 열기 +> 2. 우상단 `⋯` → **Sub-items**(하위 항목) 활성화 → 자기참조 관계 선택/생성 +> +> 그러면 push·ensure가 그 native 관계를 자동 탐지해 부모-자식을 채우고 `작업 계층` view에서 접기/펼치기로 보여줍니다. 활성화 전에는 작업 기록은 정상이지만 nesting만 빠지고, push가 활성화 안내를 출력합니다. + +### 사용법 + +```bash +# 처음 한 번 +claude-diary diary-notion init +working-diary diary-notion ensure --dry-run # 변경 없이 schema/view 상태 확인 +working-diary diary-notion ensure # schema v7, native sub-items, core/operating views 보장 +working-diary diary-notion ensure --year 2026 + +# 매 세션 +/diary-notion # Claude Code 세션 안에서 +$diary-notion # Codex 세션 안에서 + +# 수동 push가 필요한 경우 +working-diary diary-notion push --input .diary-notion-.json + +# 같은 세션 다시 push: +# 기본은 skip (Session ID + Task Index로 멱등성) +# --force 로 기존 행 archive 후 재push +working-diary diary-notion push --input .diary-notion-.json --force +``` + +다른 Codex 세션에서 최신 `$diary-notion` 지시문을 쓰려면 repo를 최신화한 뒤 `claude-diary install --force --codex`를 다시 실행하고 새 Codex 세션을 여는 것을 권장합니다. + +### Core Views + +`working-diary diary-notion ensure`는 현재 연도 또는 `--year`로 지정한 연도 `Entries` DB에 다음 5개 core view를 보장합니다. 기존 작업 row는 생성, 수정, 삭제하지 않습니다. + +| View | 용도 | 기준 | +|------|------|------| +| 작업 계층 | 메인 작업과 하위 작업 관계 확인 | native sub-item 관계 기반 접기/펼치기 nesting, native 부모 컬럼 표시, legacy `Parent Task`/`Sub-items`·`Depends On` hidden, `Work Period` 표시, `Date desc` | +| 오늘 작업 | 오늘 기록된 수행분 확인 | `Date = today`, `Date desc`, `Work Period` 표시 | +| 상태별 | 진행 단계별 작업 확인 | `Status` group_by, `Work Period` 표시 | +| 목적별 | 작업 성격별 확인 | `Purpose` group_by, `Work Period` 표시 | +| 프로젝트별 | 프로젝트별 작업 확인 | `Project` group_by, `Work Period` 표시 | + +같은 이름의 view가 이미 있고 required 설정을 만족하면 `verified`로 처리합니다. required 설정이 다르면 `working-diary diary-notion ensure`가 보장 view 기본 설정을 업데이트하고, `--dry-run`에서는 `update planned`로만 표시합니다. `작업 계층`의 sub-item nesting은 native 관계가 활성화돼 있을 때만 적용되고(없으면 ensure가 경고), `오늘 작업`의 relative today filter는 Notion API 제약에 따라 best-effort fallback을 사용합니다. + +### Operating Views + +최고모델 기준에서는 core view 5개를 유지하면서, 오늘 실행과 막힘 관리를 위한 operating view 5개도 같은 `ensure` 명령으로 보장합니다. + +| View | 용도 | 기준 | +|------|------|------| +| 오늘 우선순위 | 오늘 처리할 작업을 우선순위대로 확인 | `Date = today`, `Blocked = false`, `Priority asc`, `Date desc` | +| 전날 미완료 | 이전 기록일에서 완료되지 않은 작업 확인 | `Date before today`, `Status != Deployed`, `Priority asc` | +| Blocked | 외부 결정/권한/정보 때문에 막힌 작업 확인 | `Blocked = true`, `Block Reason` 표시 | +| 리뷰 필요 | 검토가 필요한 작업 확인 | `Review Status = Needs Review` | +| 작업 그룹별 | 여러 날/세션에 걸친 큰 작업 흐름 확인 | `Task Group` group_by | + +### 작업 row 분리 기준 + +row는 의미 있는 작업 단위로만 만듭니다. 작은 확인 항목, 긴 SQL/JS 조각, 참고 링크, 단순 메모는 별도 row가 아니라 page body 부록에 남깁니다. + +| 기준 | 처리 | +|------|------| +| 독립 상태, 검증, 코드 변경, 커밋 근거가 있는 작업 | 별도 row | +| 메인 작업을 수행하기 위한 세부 작업 | `parent_index` → native sub-item 관계(부모쪽)에 기록 → `작업 계층`에서 nesting | +| 큰 메인 작업 간 선행 관계 | `depends_on_indices` → `Depends On` | +| 전날/이전 세션에서 이어진 작업 | 새 row + 같은 `Task Group` + 필요 시 `Carryover=true` | +| 다음에 바로 할 일 | `Next Action` | +| 외부 결정/권한/정보 없이는 못 하는 일 | `Blocked=true` + `Block Reason` | + +### DB 컬럼 + +| 컬럼 | 타입 | 비고 | +|------|------|------| +| Name | title | 에이전트가 뽑은 task 제목 (명사구) | +| Date | date | | +| Work Period | date | 실제 작업 기간. 프로젝트/작업 그룹 기간 계산 재료 | +| Project | select | cwd 폴더명. group/filter용. task JSON에서 누락되거나 `unknown`이면 CLI가 명령 실행 cwd로 보정 | +| Purpose | select | Feature/Bugfix/Refactor/Docs/Test/Infra/Planning/Research/Review/Release/Support/Maintenance/General | +| Branch | select | task별 branch (group/filter용) | +| Status | select | Discussion/Design/Implementation/Testing/Deployed | +| Task Group | select | 며칠/여러 세션에 걸치는 큰 작업 묶음 | +| (native sub-item) | relation | UI에서 활성화하는 Notion native 하위항목 관계(locale 이름, 예: `상위 항목`/`하위 항목`). push가 부모쪽에 기록하고 `작업 계층` view의 nesting 토글을 구동. 코드가 이름 하드코딩 없이 자동 탐지 | +| Parent Task / Sub-items | relation | (legacy) 과거 영문 관계. native가 아니라 nesting 불가. `ensure`가 native로 이전 후 view에서 숨김 | +| Depends On | relation | 같은 DB의 선행 작업. 하위 작업이 아니라 큰 메인 작업끼리의 연결성에만 사용 | +| Priority | select | P0/P1/P2/P3. `오늘 우선순위`, `전날 미완료`, `Blocked` view 정렬 기준 | +| Next Action | rich_text | 다음에 바로 실행할 수 있는 구체적 행동 | +| Blocked | checkbox | 외부 결정/권한/정보 없이는 진행할 수 없는 작업 표시 | +| Block Reason | rich_text | 막힌 원인 | +| Carryover | checkbox | 전날 또는 이전 세션 미완료 작업을 오늘 이어서 처리한 row 표시 | +| Review Status | select | Needs Review/Reviewed/Deferred | +| Last Reviewed | date | 실제 검토일 | +| Categories | multi_select | design/refactor/bugfix/... 자유 라벨 | +| Files | number | 수정+생성 파일 수 | +| Commits | number | task별 commit 수 | +| Lines | number | 추가+삭제 합 | +| Session ID, Task Index | (hidden 권장) | 멱등성 키 | + +자세한 설계와 구현 기록: + +- [`docs/02-design/features/diary-notion-hierarchical.design.md`](docs/02-design/features/diary-notion-hierarchical.design.md) +- [`docs/02-design/features/diary-notion-views.design.md`](docs/02-design/features/diary-notion-views.design.md) +- [`docs/04-report/diary-notion-phase-2/README.md`](docs/04-report/diary-notion-phase-2/README.md) + +### 주의 + +- `config.json`은 절대 git에 커밋/공유하지 마세요 (token이 평문 저장됨) +- 사용자 프로젝트 `.gitignore`에 `.diary-notion-*.json` 추가 권장 (임시 파일 보호망) + +### 자주 겪는 문제 + +| 증상 | 원인 / 해결 | +|------|-------------| +| 하위항목 토글/nesting이 안 보임 | native sub-item 관계가 아직 없음. 그 해의 `Entries` DB에서 **⋯ → Sub-items 1회 활성화**(자기참조 관계 선택/생성). 활성화 전에는 작업 기록은 정상이고 push가 안내만 출력하며, 활성화 후 `ensure` 한 번이면 기존 `Parent Task` 데이터도 native로 이전 | +| 기존 행의 Status/Purpose/Task Group이 비어 있음 | 이 필드 로직 이전 버전으로 push된 **legacy 데이터**. 새 push부터 채워짐 — `Purpose`는 항상(기본 `General`), `Status`/`Task Group`은 에이전트 JSON에 값이 있을 때. 과거 행은 원본 JSON이 없어 자동 backfill 불가 | +| 새 연도 DB로 넘어가면 nesting이 다시 안 됨 | Notion은 해마다 새 `Entries` DB를 만들고 native sub-item은 DB마다 별도 활성화가 필요. 새 DB에서 위 ⋯ → Sub-items를 1회 더 켜면 됨 | +| 갱신한 `$diary-notion`/`$diary` 지시문이 반영 안 됨 | `claude-diary install --force --codex` 후 **새 Codex 세션**을 열어야 적용 (실행 중 세션은 로드된 스킬을 유지). `/diary-notion` 슬래시 명령을 직접 수정했다면 install이 덮어쓰기를 건너뛰므로, 최신본이 필요하면 수동 갱신 | ## 일지 예시 @@ -177,6 +349,7 @@ export CLAUDE_DIARY_TZ_OFFSET="9" ```bash claude-diary write # 현재 세션 작업일지를 즉시 기록 (`/diary` 슬래시 커맨드로도 호출) +working-diary write # 동일한 CLI의 중립 alias claude-diary search "키워드" # 키워드 검색 claude-diary filter --project my-app # 프로젝트 필터 claude-diary trace src/main.py # 파일 변경 이력 diff --git a/docs/02-design/features/diary-notion-hierarchical.design.md b/docs/02-design/features/diary-notion-hierarchical.design.md new file mode 100644 index 0000000..d5cfea1 --- /dev/null +++ b/docs/02-design/features/diary-notion-hierarchical.design.md @@ -0,0 +1,596 @@ +# /diary-notion — Hierarchical Notion Export + +> **Summary**: 슬래시 커맨드로 현재 세션을 작업 단위로 분리하여 Notion DB에 push (업무일지 자동화) +> +> **Project**: claude-code-hooks-diary +> **Date**: 2026-05-26 +> **Status**: Draft (설계 의논 중) + +> 상위 비전: [`working-diary-os.vision.md`](working-diary-os.vision.md) + +## Executive Summary + +| 관점 | 내용 | +|------|------| +| **Problem** | 기존 NotionExporter는 단순 flat DB push만 가능. 세션 1개 = 행 1개. 업무일지로 보기에 부적합 | +| **Solution** | `/diary-notion`(Claude) / `$diary-notion`(Codex) — 에이전트가 세션을 작업 단위로 분리 → 연도별 페이지/단일 DB로 push | +| **Core Value** | 별도 LLM API 키 없이 현재 에이전트 세션 컨텍스트로 업무일지 자동화 | + +--- + +## 1. Overview + +### 1.1 Design Goals + +- 한 세션의 작업을 **의미 단위로 N개 행**으로 분리 +- **연도별 페이지 → 단일 통합 DB** 구조 (단순) +- Claude Code/Codex 세션 컨텍스트만으로 동작 (별도 LLM API 키 불필요) +- Notion 무료 플랜에서도 동작 +- 기존 `exporters.notion` config 재사용 + +### 1.2 Design Principles + +- **에이전트는 의미 분석만, CLI는 기계 처리만** — 역할 분리 +- **무료 path 우선** — 외부 의존성 최소화 +- **소프트 멱등** — 실수로 두 번 눌러도 데이터 깨지지 않음 + +### 1.3 Non-Goals + +- 자동 push (Stop Hook 통합) — 별도 단순 flat 모드(`exporters.notion`)가 담당 +- Notion 페이지를 다시 markdown으로 sync — 단방향 export only +- 과거 markdown 일지 일괄 Notion 마이그레이션 — 별도 명령(`sync-notion`)으로 분리 + +--- + +## 2. Notion Structure + +``` +[루트 페이지] ← 사용자가 미리 만들고 page_id를 config에 등록 + ├─ 📄 2026 ← 자동 생성 (연도) + │ └─ 🗄️ Entries (인라인 DB) ← 자동 생성 (연도당 1개) + │ ├─ 행: 2026-05-26 / Project: claude-diary / ... + │ ├─ 행: 2026-05-26 / Project: other-project / ... + │ └─ 행: 2026-05-27 / ... + ├─ 📄 2027 ← 다음 해 첫 push 시 자동 생성 + │ └─ 🗄️ Entries + │ └─ ... +``` + +### 2.1 왜 단일 DB + Project select? + +**대안 — 프로젝트별 인라인 DB**: +- 새 프로젝트 시작할 때마다 DB 추가 생성 필요 (API 호출 ↑) +- DB가 늘어나면 캐시 키 복잡 + +**채택 — 단일 DB + Project (select)**: +- DB는 연도당 1개만 (한 번 만들면 끝) +- Notion에서 Project로 group/filter view 자유롭게 생성 가능 +- 새 프로젝트 = select 옵션만 자동 추가 (Notion API가 처리) +- "오늘 여러 프로젝트 만진 거" 한눈에 보기 자연스러움 + +--- + +## 3. DB Schema + +### 3.1 Layer 1 — Properties (DB 뷰에서 보이는 컬럼) + +| 컬럼 | 타입 | 표시 | 값 예시 | 용도 | +|------|------|------|---------|------| +| Name | title | ✅ | "DB 컬럼 스키마 의논" | 에이전트가 뽑은 task 제목 | +| Date | date | ✅ | 2026-05-26 | 정렬/필터/캘린더 뷰 | +| Work Period | date | ✅ | 2026-05-26 | 실제 작업 기간. 프로젝트/작업 그룹 기간 계산 재료 | +| Project | select | ✅ | claude-diary | group/filter. task JSON 누락/unknown 시 CLI가 cwd 폴더명으로 보정 | +| Purpose | select | ✅ | Feature | 목적별 group/filter | +| Branch | select | ✅ | feat/diary-notion | group/filter. CLI가 자동 채움 | +| Status | select | ✅ | Implementation | 5단계: Discussion/Design/Implementation/Testing/Deployed | +| Task Group | select | ✅ | diary-notion-impl | 큰 작업 단위 묶음. 에이전트가 추출 | +| Categories | multi_select | ✅ | design, notion | 작업 성격 | +| Files | number | ✅ | 7 | 수정+생성 파일 수 | +| Commits | number | ✅ | 3 | 커밋 개수 | +| Lines | number | ✅ | 142 | 추가+삭제 합 | +| Parent Task | relation (self, dual) | ✅ | → 상위 행 | 포함 관계. `Sub-items`와 양방향으로 연결 | +| Sub-items | relation (self, dual) | ✅ | → 하위 행 | Notion native 하위항목 toggle의 기준 관계 | +| Depends On | relation (self) | ✅ | → 선행 메인 작업 | 큰 메인 작업 간 선행 연결성 참조 (단방향) | +| Priority | select | ✅ | P1 | 오늘 우선순위/미완료/Blocked view 정렬 기준 | +| Next Action | rich_text | ✅ | "dry-run 재검증" | 다음에 바로 실행할 수 있는 행동 | +| Blocked | checkbox | ✅ | false | 외부 결정/권한/정보 부족으로 진행 불가 여부 | +| Block Reason | rich_text | ✅ | "API 권한 확인 필요" | 막힘 원인 | +| Carryover | checkbox | ✅ | true | 전날/이전 세션 미완료 작업 이어가기 표시 | +| Review Status | select | ✅ | Needs Review | 검토 필요/완료/보류 상태 | +| Last Reviewed | date | ✅ | 2026-06-02 | 실제 검토일 | +| Session ID | rich_text | 🔒 hidden | "abc-123-def" | 멱등성 키 | +| Task Index | number | 🔒 hidden | 0, 1, 2 | 멱등성 키 | + +→ 표시 22개 + hidden 2개 = 총 24개. 의미 요약은 컬럼이 아닌 compact body(`body_intro` + callout/checklist/toggle 부록)로 노출. + +2차 최고모델 구현에서는 이 모델을 schema v7로 확장해 `Work Period`, native `Sub-items`, 우선순위/막힘/리뷰 운영 컬럼을 함께 보장한다. `Date`는 기록일로 유지하고, `Work Period`는 프로젝트/작업 그룹의 실제 작업 기간 계산 재료로 사용한다. + +**Purpose (select)**: +- 영어 enum 사용: `Feature`, `Bugfix`, `Refactor`, `Docs`, `Test`, `Infra`, `Planning`, `Research`, `Review`, `Release`, `Support`, `Maintenance`, `General` +- Notion에서 목적별 필터/그룹을 보장하는 1차 분류. 자동 view 생성은 후속 단계로 분리. + +**Status 5단계 (select)**: +- `Discussion`: 의논만, 결정 미완 (드물게) +- `Design`: 결정/문서화 완료 +- `Implementation`: 코드 작성 (commit 있음) +- `Testing`: 테스트 작성/검증 완료 +- `Deployed`: 머지/배포까지 완료 + +한 task에 여러 단계가 섞이면 **가장 진행된 단계로**. 에이전트가 세션 컨텍스트를 보고 판단. + +**Task Group (select)**: 며칠/여러 세션에 걸치는 큰 작업 단위 묶음. 에이전트가 첫 task 시점에 새 그룹명 생성, 이전 작업의 연속이면 같은 그룹명 사용. 일관성 보장은 어렵지만 group view로 묶어 보는 편의가 핵심 가치. + +**Priority / Next Action / Carryover**: 다음날 우선순위와 오늘 실행 순서를 정하기 위한 운영 컬럼. `Priority`는 P0/P1/P2/P3만 사용하고, `Next Action`은 다음에 바로 실행 가능한 한 가지 행동을 한국어로 기록한다. 이전 날짜/세션에서 이어온 미완료 작업은 `Carryover=true`로 표시한다. + +**Blocked / Block Reason**: `Depends On`과 다르게 현재 진행 가능 여부를 나타낸다. 외부 결정, 권한, 정보가 없어 진행할 수 없을 때만 `Blocked=true`로 두고, `Block Reason`에 막힌 원인을 쓴다. + +**Review Status / Last Reviewed**: 상사 제출 전 검토, 구현 리뷰, 사후 확인이 필요한 작업을 분리하기 위한 컬럼. 검토 필요는 `Needs Review`, 검토 완료는 `Reviewed`, 뒤로 미루는 경우는 `Deferred`를 사용한다. + +**Parent Task / Sub-items (dual self-relation)**: 포함 관계. 예: `상품 목록 포커싱`의 Parent Task는 `로컬 테스트 진행`이고, 부모 row의 `Sub-items`에는 하위 작업들이 자동으로 연결된다. 같은 push 안에서는 JSON의 `parent_index`를 row ID로 변환해 `Parent Task`를 연결한다. Notion native 하위항목/sub-item toggle은 `Sub-items` relation을 기준으로 동작한다. 너무 작은 확인 항목은 별도 row가 아니라 본문 checklist로 남긴다. + +**Depends On (self-relation, 단방향)**: 같은 DB 안의 최상위 메인 작업 간 선행 연결 참조. JSON 스키마의 `depends_on_indices`가 같은 push의 top-level task index를 가리킨다. CLI가 push 순서대로 row_id 누적 → 인덱스를 실제 row ID로 변환해서 relation 채움. 하위 작업 row는 `Depends On` 연결 대상에서 제외해 sub-item 구조와 선행 관계가 섞이지 않게 한다. + +**Branch 컬럼 데이터 소스** (CLI 자동): +- task의 `commit_hashes` 있으면 → 첫 commit의 branch (`git branch --contains`) +- `commit_hashes` 없으면 → 현재 HEAD branch (`git rev-parse --abbrev-ref HEAD`) +- HEAD detached면 → fallback으로 commit hash 단편 또는 빈 값 + +### 3.2 Layer 2 — Page Body (행 클릭 시 보이는 markdown) + +```markdown +[callout] body_intro - 핵심 결과 1개. callout은 여기와 경고성 리스크에만 제한한다. + +## 결과 +- [x] 최종 결과 +- [x] 검증 완료 항목 +- [x] 커밋/푸시/배포 등 완료 상태 + +## 작업 한눈에 +| 항목 | 내용 | +| --- | --- | +| 배경 | 왜 시작했는가 | +| 범위 | 무엇을 바꿨는가 | +| 접근 | 어떻게 풀었는가 | +| 결과 | 어떤 상태가 되었는가 | + +## 영향 +- 사용자/운영/제품/개발 품질 영향 + +## 검증 +- [x] 최종 검증 결과 + +## 리스크 / 다음 액션 +[callout] 필요한 경우에만 남은 리스크 +- [ ] 후속 작업 + +## 부록 +[toggle] 개발 근거: 주요 변경, 주요 코드 변경, 파일, 명령어, Git, 이슈 +[toggle] 원문 요청: user_prompts 원문 +``` + +문제 해결형 작업은 `결과` 섹션을 다음 형태로 우선 렌더링할 수 있다. + +```markdown +## 결과 + +- 문제: 정상 생성된 view가 required property 누락 conflict로 오인됨 +- 원인: data source schema와 view retrieve 응답의 property id encoding 기준이 다름 +- 조치: property id를 decode해 비교 기준을 통일 +- 결과: core/operating view 10개 verified +``` + +**조립**: 에이전트가 만든 `body_intro`, `summary_hints`, `key_changes`, `work_context`, `work_scope`, `approach`, `outcome`, `impact`, `decisions`, `implementation_notes`, `verification`, `risks`, `next_steps`, `support_needed`, `next_action`, `block_reason` + CLI가 코드/파일/명령/Git raw 데이터를 접힌 부록(toggle)으로 조립한다. 코드 변경은 full diff가 아니라 주요 변경만 기록한다. + +**언어 정책**: `title`과 설명형 본문 필드(`body_intro`, `summary_hints`, `key_changes`, `work_context`, `work_scope`, `approach`, `outcome`, `impact`, `decisions`, `implementation_notes`, `verification`, `risks`, `next_steps`, `support_needed`, `next_action`, `block_reason`)는 한국어로 작성한다. 파일 경로, 명령어, branch, commit hash, 코드 식별자, 함수/클래스명, `Purpose`/`Status`/`Priority`/`Review Status` enum 값은 원문 또는 영어 값을 유지한다. + +**본문 보고 원칙**: +- DB relation이 구조를 담당하고, page body는 짧은 상태와 근거를 담당한다. +- `결과`, `작업 한눈에`, `영향`, `검증`, `리스크 / 다음 액션`, `부록` 순서로 배치한다. +- callout을 과하게 쓰지 않는다. 최상단 핵심 요약 1개와 경고성 리스크 정도로 제한한다. +- `작업 한눈에`는 callout 여러 개가 아니라 표로 렌더링한다. +- 검증은 최종 상태를 우선 노출하고, 중간 실행 결과는 부록으로 내린다. +- 사용자-facing 명령은 `$diary-notion` 또는 `working-diary diary-notion ...` 기준으로 노출한다. +- 과거 명령이나 내부 명령은 발생 근거가 필요할 때만 부록에 둔다. +- 주요 코드 변경과 파일/명령/Git/오류는 핵심 메시지가 아니라 근거이므로 접힌 `부록`에 둔다. +- Notion API child block 100개 제한을 넘지 않도록 렌더링 한도를 보수적으로 둔다. + +--- + +## 4. JSON Schema (Slash Command → CLI) + +```json +{ + "session_id": "abc-123-def", + "tasks": [ + { + "title": "Notion DB 컬럼 스키마 결정", + "body_intro": "DB 컬럼을 Layer 1/2로 분리. 단일 통합 DB + Project select 채택. summary 컬럼은 본문 첫 문단(body_intro)으로 통합.", + "summary_hints": ["Project/Purpose/Task Group 기준으로 필터 가능한 DB 구조를 확정"], + "key_changes": ["Project/Purpose/Task Group 기준 필터와 그룹을 컬럼으로 보장"], + "work_context": ["프로젝트/목적별로 작업을 찾기 어렵던 기존 flat DB 구조를 개선하기 위해 시작"], + "work_scope": ["Notion DB 컬럼과 본문 렌더링 정책을 함께 정리"], + "approach": ["컬럼은 필터/그룹/관계 구조를 담당하고 본문은 compact body로 읽히게 분리"], + "outcome": ["행 하나만 열어도 작업 배경, 영향, 검증, 후속 조치를 파악할 수 있게 됨"], + "impact": ["상사 보고와 개발자 회고에 모두 쓸 수 있는 단일 작업 문서가 됨"], + "code_change_highlights": ["`formatter.py`: Notion page body에 주요 변경/검증/리스크 섹션을 선택 렌더링"], + "decisions": ["view 자동화는 후속 단계로 분리"], + "implementation_notes": ["단순 파일 목록보다 개발자가 이어서 볼 수 있는 작업 기록을 우선"], + "verification": ["formatter 단위 테스트로 섹션 렌더링 검증"], + "risks": ["기존 설치된 slash command/skill은 force refresh 전까지 예전 지시문을 사용할 수 있음"], + "next_steps": ["사용자 환경에 최신 Codex skill 설치"], + "support_needed": [], + "status": "Design", + "work_period": "2026-06-02", + "priority": "P1", + "next_action": "사용자 환경에 최신 Codex skill 설치", + "blocked": false, + "block_reason": "", + "carryover": false, + "review_status": "Needs Review", + "last_reviewed": "2026-06-02", + "task_group": "diary-notion-impl", + "purpose": "Planning", + "parent_index": null, + "depends_on_indices": [], + "categories": ["design", "notion"], + "project": "claude-code-hooks-diary", + "user_prompts": ["DB 구조 의논하자", "name에는 날짜 말고..."], + "files_modified": ["src/claude_diary/exporters/notion.py"], + "files_created": [], + "commands_run": ["git log --oneline -20"], + "commit_hashes": ["abc1234"], + "errors": [] + } + ] +} +``` + +### 4.1 에이전트의 책임 (Claude slash command / Codex skill instructions) + +- transcript를 작업 단위로 분리 +- 각 task의 `title` (30~50자 명사구), `body_intro` (1~3문장 평어체, 결과 중심), `summary_hints`/`key_changes`/`code_change_highlights`/`decisions`/`implementation_notes`/`verification`/`risks`/`next_steps`, `parent_index`/`depends_on_indices` +- `categories` 추출 +- `user_prompts`, `files_modified`, `files_created`, `commands_run`, `errors` 추출 +- `commit_hashes`를 task에 매핑 + +### 4.2 CLI의 책임 + +- `commit_hashes`로 git 메타 수집 (message, lines, branch) — `git_info.py` 재사용 +- task별 Project 자동 보정 (task `project`가 없거나 `unknown`/placeholder이면 명령 실행 cwd 폴더명 사용) +- task별 Branch 자동 결정 (commit 있으면 첫 commit의 branch, 없으면 HEAD branch) +- Layer 2 body 조립 (`body_intro` + callout/checklist/toggle 부록) — `formatter.py` 확장 +- 연도 페이지/DB 자동 생성 (없으면) +- 행 추가 (멱등성 처리 포함) +- 캐시 갱신 + +### 4.3 JSON 전달 방식 — 임시 파일 via cwd + +**선택**: 에이전트가 cwd에 임시 JSON 파일을 작성 → CLI에 `--input` 으로 경로 전달. + +``` +1. 에이전트: cwd에 `.diary-notion-.json` 작성 +2. !`working-diary diary-notion push --input .diary-notion-.json` +3. CLI: 파일 read → push → try/finally로 파일 삭제 (성공/실패 무관) +4. (보험) 슬래시 커맨드 마지막에서 한 번 더 삭제 시도 +``` + +**stdin 방식을 안 쓴 이유**: PowerShell은 `<<<` here-string 미지원. heredoc 문법도 bash와 다름 (`@'...'@`). cross-platform 호환을 위해 임시 파일이 안전. + +**보안**: +- JSON에 token 등 secret 없음 (token은 CLI가 config에서 직접 read) +- transcript 데이터 자체는 `secret_scanner.py` 가 push 전에 마스킹 +- 파일명에 `session_id` 단편 박아 충돌/추측 방지 +- 사용자 프로젝트 `.gitignore`에 `.diary-notion-*.json` 패턴 추가 권장 (README에 안내) + +--- + +## 5. Flow + +``` +[사용자] + /diary-notion 입력 + │ + ▼ +[Agent (현재 세션)] ── Claude Code/Codex 세션 컨텍스트로 동작 + ├─ transcript 분석 + ├─ 작업 단위 N개 분리 + ├─ 각 task: title / body_intro / summary_hints / key_changes / work_context / work_scope / approach / outcome / impact / code_change_highlights / decisions / implementation_notes / verification / risks / next_steps / support_needed / work_period / priority / next_action / blocked / block_reason / carryover / review_status / last_reviewed / parent_index / depends_on_indices / categories / prompts / files / commands / commit_hashes + └─ JSON 생성 + │ + ▼ !`working-diary diary-notion push --input .diary-notion-.json` +[CLI: diary-notion push 명령] + ├─ JSON 파싱 + ├─ commit_hashes → git_info.py로 메타+lines 수집 + ├─ Notion API 호출: + │ ├─ 캐시 확인: 연도 페이지 / DB ID + │ ├─ 없으면 생성: + │ │ ├─ 연도 페이지: POST /pages (parent=root_page_id) + │ │ └─ DB: POST /databases + schema v7 extension PATCH + │ ├─ 각 task: + │ │ ├─ 쿼리: Session ID + Task Index 매치 행 있나? + │ │ ├─ 있으면 skip (--force면 archive 후 재생성) + │ │ └─ 없으면 POST /pages (parent=db_id, properties+body) + │ └─ 캐시 갱신 + └─ 결과 출력 +``` + +--- + +## 6. Configuration + +### 6.1 기존 config 확장 + +```json +{ + "exporters": { + "notion": { + "enabled": false, ← Stop Hook 자동 push (별도) + "api_token": "secret_xxx", + "database_id": "...", ← 기존 flat 모드용 (legacy) + "root_page_id": "abc-123", ← 신규: hierarchical용 + "mode": "hierarchical" ← 신규: "flat" | "hierarchical" + } + } +} +``` + +- `enabled` flag는 자동 hook용. **`/diary-notion`은 enabled 무관하게 동작** (api_token + root_page_id만 있으면) +- 한 사용자가 두 모드 다 쓸 일은 거의 없지만, 기존 사용자 호환성 위해 둘 다 둠 + +### 6.2 환경변수 fallback + +- `CLAUDE_DIARY_NOTION_TOKEN` +- `CLAUDE_DIARY_NOTION_ROOT_PAGE_ID` + +### 6.3 Setup Command — `claude-diary diary-notion init` + +대화형 셋업 명령. 처음 사용자가 한 번만 실행. + +**흐름**: +``` +$ claude-diary diary-notion init + +Step 1/3: Integration token + Get it from: https://www.notion.so/my-integrations + Token (secret_...): █ + +Step 2/3: Root page URL or ID + Paste full Notion URL or page ID: + > https://www.notion.so/Working-Diary-abc123def456... + ✓ Parsed page_id: abc123def456 + +Step 3/3: Verifying access... + ✓ Token valid (GET /v1/users/me) + ✓ Integration can read root page (GET /v1/blocks/{id}) + +Saved to: /config.json + exporters.notion.api_token = secret_*** + exporters.notion.root_page_id = abc123def456 + exporters.notion.mode = hierarchical +``` + +**URL 파싱**: Notion URL 끝의 32자 hex (대시 유무 모두) 정규식 추출. plain page_id 입력도 그대로 통과. + +**Write 권한 검증 정책**: 검증 안 함 (실제로 child page 생성 시도는 부작용. read 권한 OK면 write도 따라옴). 첫 push에서 실패하면 그때 안내. + +**실패 시 안내**: +- 401: "Token이 잘못되었어요. https://www.notion.so/my-integrations 에서 다시 확인하세요" +- 404: "페이지에 Integration을 공유했나요? 페이지 우상단 ⋯ → Connections → Integration 추가" + +--- + +## 7. Caching + +### 7.1 캐시 파일 + +`/notion-cache.json`: + +```json +{ + "root_page_id": "abc-123", + "years": { + "2026": "page_id_2026" + }, + "databases": { + "2026": "db_id_xxx" + }, + "rows": { + "abc-123-def:0": "row_page_id_1", + "abc-123-def:1": "row_page_id_2" + } +} +``` + +- 키 `rows`의 형식: `:` → Notion 행 page_id +- 캐시 miss 시 → Notion 검색 → 캐시 갱신 +- Notion에서 사용자가 삭제 → 다음 호출 시 API 404 → 캐시 무효화 후 재생성 + +--- + +## 8. Idempotency + +### 8.1 기본: Soft Idempotency (skip) + +- push 직전 `query DB where Session_ID=X and Task_Index=Y` +- 매치되면 skip, 없으면 새 행 추가 +- 같은 세션 두 번 push: 첫 push의 행은 그대로, 새로 추가된 task만 push + +### 8.2 `--force`: Archive & Recreate + +- 같은 `session_id`의 모든 행을 archive (Notion API의 `archived: true`) +- 그 다음 모든 task를 새로 push +- 진짜 upsert (block-level update)는 복잡해서 채택 안 함 + +--- + +## 9. Decisions & Trade-offs + +| # | 결정 | 채택 | 이유 | +|---|------|------|------| +| 1 | 계층 구조 | A: 연도 → Entries DB → 행 | 연말 회고 자료로 한 페이지에 다 보임 | +| 2 | DB 분리 | 단일 DB + Project select | 새 프로젝트마다 DB 생성 X. Notion view로 분류 | +| 3 | DB 컬럼 | 8개 표시 + 2개 hidden | 답답하지 않으면서 멱등성 키 확보 | +| 4 | 작업 분리 | 현재 에이전트 세션의 LLM | API 키 X, 의미 단위 분리 가능 | +| 5 | LLM 호출 위치 | Claude slash command 또는 Codex skill | 별도 SDK 의존성 X | +| 6 | 본문 markdown | C: 에이전트의 intro + CLI의 raw 섹션 | 의미 정리 + 일관성 동시 확보 | +| 7 | git 정보 수집 | A: CLI가 자체 수집 | 정확도 ↑, `git_info.py` 재사용 | +| 8 | 멱등성 | B + `--force`: skip 기본, force는 archive&recreate | 실수 방지 + 강제 갱신 옵션 | +| 9 | 셋업 흐름 | B: `diary-notion init` 대화형 명령 + URL 파싱 + token/read 검증 | 첫 인상 비용 ↓, page_id 헷갈림 해결, 권한 디버깅 비용 ↓ | +| 10 | 작업 분리 우선순위 | B: Semantic-first (의미 단위) | 의논 세션도 풍부, 큰 commit 안 묶임, 에이전트 정리 능력 활용 | +| 11 | Title 형식 | 명사구, 30~50자, 시제/주어/prefix/마침표 없음 | DB 뷰 한 줄에 들어감. 일관성 | +| 12 | Body intro 톤 | 평어체, 1~3문장, 결과 중심, markdown 강조 OK, 추측 금지 | 글로벌 지침과 일관. 회고 시 빠른 회상 | +| 13 | summary 컬럼 | 삭제 — 의미 요약은 compact body 섹션으로 유지 | 컬럼 중복 없이 요약/상태/검증/근거를 page body에 남김 | +| 14 | JSON 전달 방식 | 임시 파일 (cwd, `.diary-notion-.json`) | PowerShell 호환. escape 문제 회피. 디버깅 쉬움 | +| 20 | Status 컬럼 | select, 5단계 (Discussion/Design/Implementation/Testing/Deployed) | 진행도 시각화. 한 task 안에 여러 단계 섞이면 가장 진행된 단계 | +| 21 | Depends On 컬럼 | self-relation, 단방향 | 작업 순서 시각화. Notion이 reverse view 자동 제공 | +| 22 | Parent Task / Sub-items 컬럼 | self-relation, 양방향 | 포함 관계를 DB에 보존하고 native sub-item view 자동화의 기반으로 사용 | +| 22 | Task Group 컬럼 | select. 에이전트가 task별로 추출 | 며칠/여러 세션에 걸치는 큰 작업을 group view로 묶기 | +| 23 | 멱등성 + 새 컬럼 마이그레이션 | 기존 행 archive(`--force`) 후 새 스키마로 재push | Status/Depends On/Parent Task/Task Group 소급 채움 | +| 15 | Branch 컬럼 추가 + 경계 룰 | Branch select 컬럼 + "branch 다르면 task 분리"를 최우선 분리 룰로 | 한 task = 한 branch 보장. select 컬럼이 의미 있어짐. 여러 branch 섞이는 케이스 자동 해결 | +| 16 | Error 종류별 분기 | 401/403 fail fast, 400 skip, 429/5xx retry, 404 자동 재생성 | 의미 없는 retry 방지. 캐시 일관성 자동 복구 | +| 17 | Retry 정책 | 인라인 retry 3회 (exponential backoff) + JSON 파일 보존 | 수동 명령에 동기적 보고. queue 안 씀 | +| 18 | 캐시 무효화 | Lazy (404 응답 시) | 정상 path 빠름 | +| 19 | 부분 실패 | Continue + 종합 보고 (`Pushed N, skipped M, failed K`) | 행 단위 독립 | + +--- + +## 10. Slash Command Instructions (확정) + +`~/.claude/commands/diary-notion.md` 본문 초안: + +```markdown +--- +description: 현재 세션을 작업 단위로 분리해 Notion 업무일지 DB에 push +allowed-tools: + - Bash + - Read + - Write +--- + +# /diary-notion + +현재 세션의 transcript와 git 정보를 분석하여 Notion 업무일지 DB에 push. + +## 단계 + +1. **컨텍스트 수집** + - 이 세션의 user 메시지, 너의 응답, 호출한 도구 검토 + - `git log` 로 이 세션 중 만든 commit 조회 (시간 추정 OK) + +2. **작업 단위 분리 (Branch 경계 → Semantic-first)** + - **branch 경계 최우선**: 세션 중 `git switch`로 branch가 바뀌면 무조건 새 task로 분리 + - 같은 branch 안에서는 **의미 단위로 분리** (사고 흐름 = task) + - 한 commit이 여러 의미 단위에 걸치면 양쪽 task에 같은 hash 매핑 + - 큰 commit("fix: 5건 개선" 같은) 한 번에 묶지 말고 의미별로 분리 + - 짧은 follow-up("ㅇㅇ", "맞아")은 직전 task에 흡수 + - **commit이 0개인 의논 세션도 정상** — 의미 단위로 task N개 생성 + +3. **각 task별 추출** + - 언어 정책: + - `title`, `body_intro`, `summary_hints`, `key_changes`, `decisions`, `implementation_notes`, `verification`, `risks`, `next_steps`, `next_action`, `block_reason` 같은 설명형 필드는 반드시 한국어로 작성 + - `status`, `purpose`, `priority`, `review_status` enum 값은 지정된 영어 값을 그대로 사용 + - 파일 경로, 명령어, branch, commit hash, 코드 식별자, 함수/클래스명은 원문 그대로 유지 + - `user_prompts`는 사용자가 말한 원문을 증거로 보존 + - `title`: 30~50자 명사구. 시제/주어/prefix/마침표 없음 + - ✅ "Notion DB 컬럼 스키마 결정", "git_info.py 리팩토링" + - ❌ "오늘 DB 의논했다", "[설계] DB 컬럼" + - `body_intro`: 1~3문장, 200~500자, 평어체, 결과 중심 + - transcript에 없는 내용 추가 금지 (추측 X) + - markdown 강조(`**굵게**`, `` `코드` `` ) 사용 OK + - Notion 작업 DB 기록처럼 작성. 구조는 DB relation으로 남기고, 본문은 중복 없이 간결하게 쓸 것 + - `summary_hints`: 작업 결과/의미 요약 최대 4개. 단순 파일 나열이 아니라 무엇이 달라졌는지 기록 + - `key_changes`: 개발자가 이 일지만 봐도 흐름을 이해할 수 있는 주요 변경사항 최대 4개 + - `work_context`: 왜 이 작업을 시작했는지 0~1개 + - `work_scope`: 무엇을 바꿨는지 0~1개 + - `approach`: 어떻게 해결했는지 0~1개 + - `outcome`: 결과가 무엇인지 0~1개 + - `impact`: 사용자/운영/제품/개발 품질 영향 0~4개 + - `code_change_highlights`: 실제 코드 변화 중 중요한 것만 0~5개 + - 파일/함수/명령 단위 + 동작상 의미를 함께 기록 + - full diff, 단순 포맷팅, import 정리, 문구 수정, fixture 보정은 제외 + - 동작/스키마/CLI/사용자 흐름/검증 범위가 바뀐 코드는 포함 + - `decisions`: 사용자가 결정했거나 구현 중 확정한 선택지/트레이드오프 0~3개 + - `implementation_notes`: 코드 변경 요약에 넣기 애매한 제약/호환성/마이그레이션 메모 0~4개 + - `verification`: 실행한 테스트, 검증 결과, 검증하지 못한 이유 0~4개 + - `risks`: 주의사항, 남은 리스크, 운영/사용 시 헷갈릴 수 있는 점 0~3개 + - `next_steps`: 남은 작업이나 후속 단계 0~3개 + - `support_needed`: 필요한 결정/지원이 있으면 0~2개 + - `status`: `Discussion` / `Design` / `Implementation` / `Testing` / `Deployed` + - `purpose`: `Feature` / `Bugfix` / `Refactor` / `Docs` / `Test` / `Infra` / `Planning` / `Research` / `Review` / `Release` / `Support` / `Maintenance` / `General` + - `work_period`: 실제 작업 기간. 기본은 오늘 날짜, 여러 날이면 start/end range 사용 + - `priority`: `P0` / `P1` / `P2` / `P3` + - `next_action`: 다음에 바로 실행 가능한 구체적 행동 + - `blocked`: 외부 결정/권한/정보 없이는 진행할 수 없으면 `true` + - `block_reason`: `blocked`가 `true`이면 막힌 원인 + - `carryover`: 전날/이전 세션 미완료 작업을 이어서 처리한 row면 `true` + - `review_status`: `Needs Review` / `Reviewed` / `Deferred` + - `last_reviewed`: 실제 검토일 `YYYY-MM-DD` + - `task_group`: 며칠/여러 세션에 걸치는 큰 작업 단위 식별자 + - `parent_index`: 하위 작업이면 같은 push 안의 부모 task 인덱스, 최상위면 `null` + - `depends_on_indices`: 같은 push 안에서 의존하는 선행 top-level task 인덱스 배열. 하위 작업에는 사용하지 않음 + - `categories`: 1~3개. design/refactor/bugfix/test/docs/infra/discussion 같은 자유 라벨 + - `project`: 현재 cwd의 폴더명 + - `user_prompts`, `files_modified`, `files_created`, `commands_run`, `errors` + - `commit_hashes`: 이 task에 해당하는 commit (0개도 OK) + +4. **JSON 출력 및 CLI 호출** + - cwd에 `.diary-notion-<8자리>.json` 작성 (Write 도구) + - `!working-diary diary-notion push --input .diary-notion-<8자리>.json` 실행 + - 종료 후 파일 삭제 + +## JSON 형식 + +JSON Schema는 design 문서 Section 4 참고. + +## 빈 결과 처리 + +tasks 가 0개라면 (transcript에 의미 있는 작업 없음) 사용자에게 이유 설명하고 CLI 호출 없이 종료. + +## 사용자 보고 + +CLI 결과를 그대로 보여주고 push/skip된 task 요약. +``` + +--- + +## 11. Open Questions (TBD) + +모든 설계 결정 완료. 다음 단계 = 구현. + +--- + +## 11. Reuse vs New Code + +### 11.1 재사용 + +- `exporters/base.py` `BaseExporter` 인터페이스 +- `exporters/notion.py` `NotionExporter` (flat 모드는 그대로, mode 분기 추가) +- `lib/git_info.py` commit 메타 수집 +- `lib/secret_scanner.py` 시크릿 마스킹 +- `formatter.py` 본문 markdown 조립 (확장) +- `cli/setup.py` 슬래시 커맨드 install/uninstall 패턴 + +### 11.2 신규 + +- `cli/notion_push.py` — `claude-diary diary-notion push --input`, `working-diary diary-notion push --input` 명령 +- `exporters/notion.py` 안에 `_hierarchical_export()` 추가 (또는 `NotionHierarchicalExporter` 클래스 분리) +- `lib/notion_cache.py` — 캐시 read/write +- `~/.claude/commands/diary-notion.md` — 슬래시 커맨드 instructions +- `tests/test_notion_push.py` +- `tests/test_notion_cache.py` + +--- + +## 12. Compatibility & Migration + +- 기존 `exporters.notion` (flat 모드) 사용자는 영향 없음 — `mode` 키 없으면 flat 동작 +- 기존 Stop Hook 자동 push는 그대로 동작 +- `/diary-notion`은 신규 사용자가 추가 셋업해야 사용 가능 (`root_page_id` 등록) + +--- + +## 13. Security + +- `api_token`은 config.json 평문 저장 (기존과 동일) +- 셋업 가이드에 "config.json 공유/커밋 금지" 강조 필요 +- secret_scanner가 push 전에 entry_data를 마스킹 (기존 로직 재사용) diff --git a/docs/02-design/features/diary-notion-views.design.md b/docs/02-design/features/diary-notion-views.design.md new file mode 100644 index 0000000..0ab1204 --- /dev/null +++ b/docs/02-design/features/diary-notion-views.design.md @@ -0,0 +1,1141 @@ +# /diary-notion Views — Core + Operating View Automation + +> **Summary**: 1차에서 만든 Notion 작업 DB 구조를 실제 업무 관리 화면으로 탐색할 수 있도록 core views와 최고모델 운영 view를 자동 보장한다. +> +> **Project**: claude-code-hooks-diary +> **Date**: 2026-06-02 +> **Status**: Draft (설계 의논 중) + +> 상위 비전: [`working-diary-os.vision.md`](working-diary-os.vision.md) +> +> 선행 설계: [`diary-notion-hierarchical.design.md`](diary-notion-hierarchical.design.md) + +## Executive Summary + +| 관점 | 내용 | +|------|------| +| **Problem** | 1차에서 `Parent Task`, `Depends On`, `Project`, `Purpose`, `Status` 등 구조화 컬럼을 만들었지만 Notion 사용자는 여전히 직접 view를 구성해야 한다. | +| **Solution** | `working-diary diary-notion ensure` 명령으로 Notion 작업 DB schema v7, Core Views, Operating Views를 자동 생성/보장한다. | +| **Core Value** | 같은 작업 row를 계층, 오늘, 상태, 목적, 프로젝트, 우선순위, 막힘, 리뷰 관점으로 즉시 탐색할 수 있게 한다. | + +--- + +## 1. Core Views 원칙 + +Core Views는 모든 작업 row가 공통으로 가지는 DB 컬럼을 기준으로 제공하는 기본 화면이다. + +MVP 5개 view는 임시가 아니라 최종 모델에서도 유지되는 core view다. + +`작업 그룹별`은 core 5개에는 넣지 않지만 최고모델 운영 view로 함께 보장한다. + +Blocked, 전날 미완료, 오늘 우선순위, 리뷰 필요, 작업 그룹별은 최고모델 운영 view로 보장한다. 오래 방치된 작업, 자동 today-plan 생성, weekly brief는 3차 이후 지능화 단계로 분리한다. + +### 1.1 왜 Core Views인가 + +2차 View 자동화는 화면을 많이 만드는 작업이 아니다. 1차에서 만든 공통 데이터 모델을 사용자가 실제로 탐색할 수 있게 만드는 최소 화면을 자동 보장하는 작업이다. + +공통 데이터 모델: + +```text +Name +Date +Work Period +Project +Purpose +Branch +Status +Task Group +Parent Task +Depends On +Priority +Next Action +Blocked +Block Reason +Carryover +Review Status +Last Reviewed +Categories +Files +Commits +Lines +Session ID +Task Index +``` + +Core Views는 이 공통 컬럼을 다른 질문으로 재배열한다. + +```text +작업 계층 = 이 일은 어떤 큰 작업의 일부인가 +오늘 작업 = 오늘 기록된 수행분은 무엇인가 +상태별 = 어디까지 진행됐는가 +목적별 = 어떤 성격의 일인가 +프로젝트별 = 어느 프로젝트의 일인가 +오늘 우선순위 = 오늘 무엇을 먼저 처리할 것인가 +전날 미완료 = 어제 이전에 남은 일은 무엇인가 +Blocked = 어떤 일이 외부 조건 때문에 막혔는가 +리뷰 필요 = 검토가 필요한 일은 무엇인가 +작업 그룹별 = 며칠/여러 세션에 걸친 큰 흐름은 무엇인가 +``` + +`Date`와 `Work Period`는 의미가 다르다. + +```text +Date = 기록일. 오늘 작업 view의 기준 +Work Period = 실제 작업 기간. 프로젝트/작업 그룹 산출물의 기간 계산 재료 +``` + +--- + +## 2. 2차 MVP Scope + +### 2.1 명령 + +```bash +working-diary diary-notion ensure +working-diary diary-notion ensure --year 2026 +working-diary diary-notion ensure --dry-run +claude-diary diary-notion ensure +claude-diary diary-notion ensure --year 2026 +claude-diary diary-notion ensure --dry-run +``` + +역할: + +- 현재 연도 Entries DB와 schema v7를 보장한다. +- 현재 설정된 hierarchical Notion DB에 core view와 operating view가 있는지 확인한다. +- 없는 view만 생성한다. +- 같은 이름의 view가 있으면 required 설정을 검사한다. +- required 설정을 충족하면 verified로 처리한다. +- required 설정이 맞지 않으면 기존 core view를 Views API update로 보정한다. +- `--dry-run`에서는 실제 보정 없이 update planned로 보고한다. +- 기존 row는 생성/수정/삭제하지 않는다. +- 실패해도 `/diary-notion` 또는 `$diary-notion` push 기능에 영향을 주지 않는다. +- 사용자-facing 명령은 `diary-notion ensure` 하나로 둔다. +- `views ensure`는 구현 내부의 view 보장 단계 이름으로만 사용하고, 사용자에게 별도 하위 명령으로 노출하지 않는다. +- `--year`는 대상 연도 페이지/DB를 명시한다. +- `--dry-run`은 생성/수정 없이 현재 접근 가능한 상태 기준으로 변경 계획만 출력한다. + +### 2.2 MVP Required Core Views + +2차 MVP에서 자동 보장할 view는 다음 5개다. + +| View | 주 질문 | 기준 컬럼 | +|------|---------|-----------| +| 작업 계층 | 이 일은 어떤 큰 작업의 일부인가? | `Parent Task`, `Task Group` | +| 오늘 작업 | 오늘 기록된 수행분은 무엇인가? | `Date`, `Status` | +| 상태별 | 어디까지 진행됐는가? | `Status` | +| 목적별 | 어떤 성격의 일인가? | `Purpose` | +| 프로젝트별 | 어느 프로젝트의 일인가? | `Project`, `Work Period` | + +### 2.3 최고모델 Operating Views + +Core Views 5개는 최종 모델에서도 유지되는 기본 화면이다. 최고모델에서는 같은 `ensure` 명령으로 운영 view 5개를 추가 보장한다. + +| View | 주 질문 | 기준 컬럼 | +|------|---------|-----------| +| 오늘 우선순위 | 오늘 무엇을 먼저 처리할 것인가? | `Date`, `Priority`, `Blocked` | +| 전날 미완료 | 어제 이전에 남은 일은 무엇인가? | `Date`, `Status`, `Priority`, `Carryover` | +| Blocked | 어떤 일이 외부 조건 때문에 막혔는가? | `Blocked`, `Block Reason` | +| 리뷰 필요 | 검토가 필요한 일은 무엇인가? | `Review Status`, `Last Reviewed` | +| 작업 그룹별 | 며칠/여러 세션에 걸친 큰 작업 흐름은 무엇인가? | `Task Group`, `Work Period` | + +### 2.4 3차 이후로 미루는 View + +다음 view와 자동화는 schema v7의 재료를 기반으로 하지만, 이번 보장 대상은 아니다. + +| View/Automation | 단계 | 보류 이유 | +|------|------|-----------| +| 오래 방치된 작업 | Phase 3 Operations | stale 기준과 마지막 검토일 계산 정책이 더 필요하다. | +| 자동 today-plan 생성 | Phase 3 Intelligence | 전날 todo/`next_steps` 수집과 사용자 승인 흐름이 필요하다. | +| 주간 보고 | Phase 3 Intelligence | summary/review 생성 로직과 보고서 승인 흐름이 필요하다. | + +--- + +## 3. View 정의 + +### 3.1 작업 계층 + +목적: + +- `Parent Task` 기반으로 큰 작업과 하위 작업을 탐색한다. +- 1차에서 추가한 포함 관계를 사용자가 실제로 확인하게 한다. +- 메인 작업을 두고, 메인 작업을 수행하기 위한 세부 작업을 하위 항목으로 연결한다. +- `Depends On`은 하위 작업 표현 수단이 아니므로 작업 계층 view의 기본 표시에서 제외한다. + +2차 MVP는 **하위 항목 데이터 구조**를 필수로 보장한다. + +작업 계층 view는 메인 작업과 하위 작업의 `Parent Task` 관계를 반드시 노출한다. + +Notion의 접기/펼치기 sub-item UI는 최종 목표이며, 2차에서는 API 지원 여부에 따라 best-effort로 활성화한다. + +예시: + +```text +Working Diary OS + Notion 작업 계층 1차 구조 구현 + Working Diary OS 최고모델 비전 정리 + 2차 View 설계 +``` + +초기 표시 컬럼: + +- `Name` +- `Status` +- `Project` +- `Purpose` +- `Task Group` +- `Parent Task` +- `Work Period` +- `Date` + +정렬/그룹: + +- `Parent Task` 컬럼 표시는 required다. +- `Depends On` 컬럼은 작업 계층 view에서 hidden으로 둔다. +- `Work Period` 컬럼 표시는 required다. +- `subtasks` configuration 적용은 시도하되, Notion UI의 접기/펼치기 렌더링 성공은 best-effort다. +- sub-item UI 자동화가 API 제약으로 실패하면 `subtasks`를 제거한 base table view로 fallback한다. + +필수 성공 기준: + +- `작업 계층` view가 생성된다. +- `Parent Task` 컬럼이 표시된다. +- `Depends On` 컬럼이 표시되지 않는다. +- `Work Period` 컬럼이 표시된다. +- 메인 작업과 하위 작업의 포함 관계를 view에서 확인할 수 있다. + +Best-effort 기준: + +- Notion table의 접기/펼치기 sub-item UI를 활성화한다. +- sub-item UI 설정 실패 후 base table fallback이 성공하면 전체 `diary-notion ensure` 실패로 보지 않고 warning으로 보고한다. + +실패 기준: + +- fallback base table view까지 생성에 실패하면 core view 생성 실패로 보고 exit 1을 반환한다. + +### 3.2 오늘 작업 + +목적: + +- 오늘 기록된 작업을 빠르게 확인한다. +- 오늘 실제로 수행하고 `$diary-notion`으로 남긴 작업 row를 확인한다. +- 이후 `today-plan`이 제안하는 오늘 후보와 구분되는 기록용 기본 화면이다. + +초기 기준: + +```text +Date = today +Sort: Date desc +``` + +`Date = today`는 Notion relative date filter를 우선 사용한다. + +```json +{ + "filter": { + "property": "Date", + "date": { + "equals": "today" + } + } +} +``` + +Notion 공식 changelog 기준 relative date filter 값은 view filters에도 적용된다. 따라서 2차 MVP의 기본 payload는 relative today filter다. + +relative today filter 적용이 API validation에서 실패하면 CLI 실행일 기준 fixed date filter로 fallback한다. + +fixed date filter를 사용할 때의 기준일은 다음 순서로 결정한다. + +```text +1. 명시 설정 timezone +2. 로컬 환경 timezone +3. Asia/Seoul +``` + +fixed date filter fallback을 사용한 경우에는 CLI warning으로 다음 날 재실행 필요성을 안내한다. + +초기 표시 컬럼: + +- `Name` +- `Status` +- `Project` +- `Purpose` +- `Task Group` +- `Work Period` +- `Parent Task` +- `Depends On` + +주의: + +- `오늘 작업`은 “오늘 해야 할 일”이 아니라 “오늘 기록된 작업”이다. +- 어제부터 이어진 작업을 오늘도 수행했다면 오늘 수행분을 새 row로 남긴다. +- 이어진 작업은 같은 `Task Group`을 사용해 여러 날짜의 수행분을 하나의 흐름으로 묶는다. +- 오늘 수행분을 `$diary-notion`으로 새로 기록하지 않았다면 `오늘 작업` view에는 나타나지 않는다. +- `Date`는 오늘로 기록하고, `Work Period`는 오늘 수행분의 실제 작업일 또는 작업 구간을 기록한다. +- 같은 push 안에서 메인 작업과 세부 작업이 함께 생성된 경우에는 `Parent Task`로 포함 관계를 연결한다. +- `Depends On`은 하위 작업이 아니라 최상위 메인 작업끼리의 선행 연결성에만 사용한다. +- 과거 row를 찾아 cross-day `Parent Task` relation으로 자동 연결하는 것은 2차 MVP 범위가 아니며, 필요하면 후속 작업으로 분리한다. +- 2차 MVP에서는 “오늘 해야 할 작업 추천”까지 하지 않는다. +- 추천은 Phase 3 이후 자동 today-plan 단계에서 처리한다. + +예시: + +```text +어제 row +Date = 2026-06-01 +Work Period = 2026-06-01 +Task Group = diary-notion-view-design + +오늘 row +Date = 2026-06-02 +Work Period = 2026-06-02 +Task Group = diary-notion-view-design +``` + +### 3.3 상태별 + +목적: + +- 작업이 Discussion, Design, Implementation, Testing, Deployed 중 어디에 있는지 확인한다. + +그룹: + +```text +Group by Status +``` + +초기 표시 컬럼: + +- `Name` +- `Project` +- `Purpose` +- `Task Group` +- `Parent Task` +- `Work Period` +- `Date` + +상태 순서: + +```text +Discussion +Design +Implementation +Testing +Deployed +``` + +group order 세부 순서는 2차 MVP에서 강제하지 않는다. `Status` group_by 자체가 required이고, 순서 제어는 best-effort로 둔다. + +### 3.4 목적별 + +목적: + +- Feature, Bugfix, Planning, Docs 등 작업 성격을 기준으로 회고/보고 관점을 제공한다. + +그룹: + +```text +Group by Purpose +``` + +초기 표시 컬럼: + +- `Name` +- `Status` +- `Project` +- `Task Group` +- `Work Period` +- `Date` + +활용: + +- 주간 회고에서 구현/버그수정/문서/설계 비중을 확인한다. +- 상사 보고용 요약의 근거가 된다. + +빈 목적이나 분류 실패는 `General`로 남긴다. 2차 MVP는 `Purpose` group_by를 보장하지만, 빈 그룹 숨김이나 `General` 그룹 위치 조정은 best-effort로 둔다. + +### 3.5 프로젝트별 + +목적: + +- 여러 repo/프로젝트에서 생성된 row를 프로젝트 기준으로 분리해서 본다. + +그룹: + +```text +Group by Project +``` + +초기 표시 컬럼: + +- `Name` +- `Status` +- `Purpose` +- `Task Group` +- `Parent Task` +- `Work Period` +- `Date` + +활용: + +- `claude-code-hooks-diary`, `flow-chatbot`, `zelotek` 등 여러 작업이 섞여도 프로젝트별 흐름을 확인한다. +- 최종 Multi-project OS의 기본 진입점이 된다. +- 프로젝트별 기간 계산은 2차 MVP에서 하지 않고, `Work Period` 표시만 보장한다. + +### 3.6 오늘 우선순위 + +목적: + +- 오늘 기록된 작업 중 막히지 않은 작업을 우선순위 기준으로 확인한다. +- 전날 todo 자동 추천은 아니며, 사용자가 오늘 `$diary-notion`으로 남긴 row 중 실행 우선순위를 보는 운영 화면이다. + +기준: + +```text +Date = today +Blocked = false +Sort: Priority asc, Date desc +``` + +초기 표시 컬럼: + +- `Name` +- `Priority` +- `Status` +- `Project` +- `Task Group` +- `Next Action` +- `Blocked` +- `Work Period` +- `Date` + +### 3.7 전날 미완료 + +목적: + +- 오늘 이전 기록일의 row 중 완료되지 않은 일을 확인한다. +- 전날 또는 이전 세션의 미완료 작업을 다음날 우선순위 논의 재료로 남긴다. + +기준: + +```text +Date before today +Status != Deployed +Sort: Priority asc, Date desc +``` + +초기 표시 컬럼: + +- `Name` +- `Priority` +- `Status` +- `Project` +- `Task Group` +- `Next Action` +- `Carryover` +- `Work Period` +- `Date` + +### 3.8 Blocked + +목적: + +- 외부 결정, 권한, 정보 부족 때문에 진행이 막힌 작업을 별도로 확인한다. +- `Depends On`은 작업 간 선행 관계이고, `Blocked`는 현재 진행 가능 여부다. + +기준: + +```text +Blocked = true +Sort: Priority asc, Date desc +``` + +초기 표시 컬럼: + +- `Name` +- `Priority` +- `Status` +- `Project` +- `Task Group` +- `Block Reason` +- `Next Action` +- `Work Period` +- `Date` + +### 3.9 리뷰 필요 + +목적: + +- 사용자의 검토, 상사 제출 전 확인, 구현 후 리뷰가 필요한 작업을 모은다. + +기준: + +```text +Review Status = Needs Review +Sort: Date desc +``` + +초기 표시 컬럼: + +- `Name` +- `Review Status` +- `Last Reviewed` +- `Priority` +- `Project` +- `Task Group` +- `Next Action` +- `Date` + +### 3.10 작업 그룹별 + +목적: + +- 며칠 또는 여러 세션에 걸친 큰 작업 흐름을 `Task Group` 기준으로 확인한다. +- 프로젝트 산출물 기간 계산은 `Work Period`를 재료로 하지만, 이 view는 일단 탐색 화면으로 둔다. + +기준: + +```text +Group by Task Group +Sort: Date desc +``` + +초기 표시 컬럼: + +- `Name` +- `Status` +- `Priority` +- `Project` +- `Purpose` +- `Parent Task` +- `Work Period` +- `Date` + +--- + +## 4. 자동화 정책 + +### 4.1 DB/schema 보장 + +`diary-notion ensure`는 현재 연도 Entries DB와 schema v7까지 보장한다. + +```text +working-diary diary-notion ensure +→ year page 확인/생성 +→ Entries DB 확인/생성 +→ schema v7 확인/보강 +→ core views 확인/생성 +→ operating views 확인/생성 +``` + +정책: + +- DB가 없으면 현재 연도 기준으로 생성할 수 있다. +- schema가 오래됐으면 view 생성에 필요한 현재 schema v7까지 보강한다. +- schema v7은 `Work Period`, `Parent Task` ↔ `Sub-items`, `Priority`, `Next Action`, `Blocked`, `Block Reason`, `Carryover`, `Review Status`, `Last Reviewed`를 보장한다. +- 기존 row는 생성/수정/삭제하지 않는다. +- view 생성 전 root page, year, database 상태를 CLI 출력에 표시한다. +- 이 명령의 DB/schema 보장은 view 생성의 전제 조건을 맞추기 위한 것이며 작업 기록 push를 대신하지 않는다. + +예상 출력: + +```text +[working-diary diary-notion ensure] +Root page: ... +Year: 2026 +Database: Entries (created) +Schema: v7 ensured +Views: + + 작업 계층 + + 오늘 작업 + + 상태별 + + 목적별 + + 프로젝트별 + + 오늘 우선순위 + + 전날 미완료 + + Blocked + + 리뷰 필요 + + 작업 그룹별 +``` + +이미 모두 있으면: + +```text +[working-diary diary-notion ensure] +Root page: ... +Year: 2026 +Database: Entries (existing) +Schema: v7 ensured +Views: + = 작업 계층 (verified) + = 오늘 작업 (verified) + = 상태별 (verified) + = 목적별 (verified) + = 프로젝트별 (verified) + = 오늘 우선순위 (verified) + = 전날 미완료 (verified) + = Blocked (verified) + = 리뷰 필요 (verified) + = 작업 그룹별 (verified) +``` + +### 4.2 기본은 non-destructive + +View 자동화는 사용자의 수동 Notion 편집을 존중한다. + +- `diary-notion ensure`는 내부적으로 core view와 operating view를 create + verify 한다. +- 이름이 같은 view가 있으면 무조건 skip하지 않고 required 설정을 검사한다. +- required 설정을 충족하면 verified로 처리한다. +- required 설정이 맞지 않으면 기존 보장 view를 Views API update로 보정한다. +- 없는 view만 required 설정으로 create 한다. +- 기존 view의 수동 설정을 덮어쓰지 않음 +- 기존 row는 수정하지 않음 +- update가 실패해 conflict/failure가 남으면 보장 view 보장이 실패한 것이므로 exit 1을 반환한다. +- required 설정이 맞지 않아도 `오늘 작업 (Generated)` 같은 대체 view를 자동 생성하지 않고 같은 이름의 보장 view를 update한다. +- view 생성/검증 실패가 diary push 실패로 전파되지 않음 + +conflict 출력에는 view 이름, mismatch 이유, 해결 안내를 포함한다. + +```text +Views: + x 오늘 작업 -- conflict + reason: missing Date=today filter + action: check view permissions or fix the filter, then rerun + +Exit: 1 +``` + +### 4.3 Dry-run과 후속 옵션 + +2차 MVP에는 `--year`와 `--dry-run`을 포함한다. + +`--dry-run`은 실제 보장이 아니라 계획 출력이다. + +`--dry-run`에서 하는 것: + +- credential 확인 +- root/year/database 접근 가능 여부 확인 +- schema v7 보강 필요 여부 계산 +- core/operating view 생성/verify 계획 출력 +- conflict 예상 출력 +- 예상 exit code 출력 + +`--dry-run`에서 하지 않는 것: + +- year page 생성 +- database 생성 +- schema 보강 +- view 생성 +- view 수정 +- 기존 row 생성/수정/삭제 + +DB가 없을 때의 dry-run 출력 예: + +```text +[working-diary diary-notion ensure --dry-run] +Database: missing +Plan: + + create year page + + create Entries DB + + ensure schema v7 + + create 5 core views + + create 5 operating views +``` + +후속 옵션: + +```bash +working-diary diary-notion ensure --plan +working-diary diary-notion ensure --apply +working-diary diary-notion ensure --force +``` + +예상 동작: + +- `--plan`: dry-run보다 상세한 변경 계획과 drift 해결안을 출력 +- `--apply`: 사용자가 승인한 변경만 적용 +- 시스템이 관리하는 view만 재생성 또는 업데이트 +- 사용자 정의 view는 건드리지 않음 +- 적용 전 변경 계획을 출력 +- conflict 해결을 위해 대체 이름 view를 자동 생성하지 않음 + +### 4.4 Push와 분리 + +`$diary-notion`은 작업 기록에 집중한다. + +```text +$diary-notion +→ row 생성 +→ Parent Task / Depends On 연결 +→ body blocks 기록 +``` + +View 자동화는 별도 명령으로 둔다. + +```text +working-diary diary-notion ensure +→ 현재 연도 Entries DB/schema v7 보장 +→ core/operating view 존재 확인 +→ 없으면 생성 +→ 있으면 required 설정 검증 +→ required 설정 미충족 시 보장 view update +``` + +이 분리를 유지하는 이유: + +- view는 매 push마다 만들 필요가 없다. +- View API 권한/버전 문제가 작업 기록 실패로 이어지면 안 된다. +- 사용자가 원하는 시점에 화면 구성을 갱신할 수 있다. + +### 4.5 기본 설정 보장 범위 + +공식 Views API 확인 결과, table view 생성/수정 시 다음 설정은 API 모델 안에서 직접 다룰 수 있다. + +- `filter` +- `sorts` +- `configuration.properties` +- `configuration.group_by` +- `configuration.subtasks` +- `wrap_cells` +- `frozen_column_index` +- `show_vertical_lines` + +따라서 2차 MVP의 “이름 + 기본 설정 보장”은 이름만 만드는 수준이 아니다. Core view 생성 시 다음을 required 설정으로 둔다. + +Required: + +- view 이름 +- view type: `table` +- core property 표시 +- hidden property 숨김 +- view별 최소 filter/sort/group +- `Work Period` 컬럼 표시 +- `작업 계층` view의 `Parent Task` 컬럼 표시 + +Required mismatch: + +- view type이 `table`이 아님 +- `Session ID`, `Task Index`가 표시됨 +- `Work Period` 컬럼이 표시되지 않음 +- `오늘 작업`에 relative today filter 또는 fixed today filter가 없음 +- `상태별`에 `Status` group_by가 없음 +- `목적별`에 `Purpose` group_by가 없음 +- `프로젝트별`에 `Project` group_by가 없음 +- `작업 계층`에 `Parent Task` 컬럼 표시가 없음 + +Best-effort: + +- `작업 계층` view의 `Sub-items` 기반 subtask configuration payload 구성 +- Notion UI의 접기/펼치기 sub-item 렌더링이 실제 workspace에서 기대대로 활성화되는지 +- group order 세부 순서 +- column width, frozen column, wrap, vertical line 같은 presentation detail +- view tab 위치 + +Best-effort mismatch는 warning만 남기고 실패로 보지 않는다. + +`subtasks`는 API상 table configuration의 일부로 지원되므로 생성 payload에는 우선 포함한다. 다만 workspace/API 버전/권한/Notion 동작 차이로 sub-item UI 설정이 거절되거나 기대와 다르게 보일 수 있으므로, 이 실패는 2차 MVP의 전체 실패가 아니라 warning으로 처리한다. + +`subtasks` 포함 create/update가 실패하면 CLI는 `subtasks`를 제거한 base table view 생성으로 fallback한다. fallback view가 생성되면 전체 명령은 성공으로 처리하되 warning을 출력한다. base table view 생성까지 실패하면 core view 생성 실패로 보고 exit 1을 반환한다. + +Core view별 required 설정: + +| View | Required 설정 | +|------|---------------| +| 작업 계층 | `table`, 핵심 properties 표시, `Parent Task` 표시, `Work Period` 표시 | +| 오늘 작업 | `table`, relative today filter 또는 fixed today filter, `Date desc` sort, `Work Period` 표시, 핵심 properties 표시 | +| 상태별 | `table`, `Status` group_by, `Work Period` 표시, 핵심 properties 표시 | +| 목적별 | `table`, `Purpose` group_by, `Work Period` 표시, 핵심 properties 표시 | +| 프로젝트별 | `table`, `Project` group_by, `Work Period` 표시, 핵심 properties 표시 | + +Core view별 payload / verify 기준: + +| View | Create payload 기준 | Verify 기준 | +|------|----------------------|-------------| +| 작업 계층 | `type=table`, 핵심 properties visible, `Parent Task` visible, `Sub-items` hidden, `Depends On` hidden, `Work Period` visible, `Date desc` sort, `subtasks` best-effort | table view, `Parent Task` visible, `Sub-items` hidden, `Depends On` hidden, `Work Period` visible | +| 오늘 작업 | `type=table`, `Date equals today` relative filter, `Date desc` sort, 핵심 properties visible | table view, `Date = today` filter 또는 fixed date fallback filter, `Date desc` sort, `Work Period` visible | +| 상태별 | `type=table`, `Status` group_by, 핵심 properties visible | table view, `Status` group_by, `Work Period` visible | +| 목적별 | `type=table`, `Purpose` group_by, 핵심 properties visible | table view, `Purpose` group_by, `Work Period` visible | +| 프로젝트별 | `type=table`, `Project` group_by, 핵심 properties visible | table view, `Project` group_by, `Work Period` visible | + +`오늘 작업` fixed date fallback verify는 CLI가 생성한 날짜 값을 기준으로 한다. 기존 view가 fixed date filter를 가지고 있는데 날짜가 오늘이 아니면 required mismatch로 보고 conflict 처리한다. + +작업 계층 view의 best-effort 설정: + +| 설정 | 기준 | +|------|------| +| `subtasks.property_id` | `Sub-items` relation property id | +| `display_mode` | `show` | +| `filter_scope` | `parents_and_subitems` | + +모든 core view에서 기본적으로 숨긴다: + +- `Session ID` +- `Task Index` + +다음 컬럼은 view별로 표시가 필요하지 않으면 숨길 수 있다. + +- `Files` +- `Commits` +- `Lines` +- `Categories` +- `Branch` + +확인한 공식 문서: + +- Notion Developers: Working with views +- Notion Developers: Filter data source entries +- Notion Developers: Changelog - relative date filter values +- Notion Developers: Upgrading to 2025-09-03 +- Notion Developers: Upgrading to 2026-03-11 + +--- + +## 5. API 경계 + +### 5.1 API version 분리 정책 + +Notion API version은 workspace나 database를 전역 업그레이드하는 값이 아니라, 요청마다 `Notion-Version` header로 선택하는 값이다. + +2차 MVP에서는 Notion API version을 전역으로 올리지 않는다. + +결정: + +```text +기존 기록 경로 +NotionHierarchicalExporter +Notion-Version: 2022-06-28 +역할: DB 생성, schema 보강, row 생성, body blocks append, relation 연결 + +신규 view 경로 +NotionViewsClient +Notion-Version: 2026-03-11 +역할: data_source_id 확인, property id map 생성, data source schema 보정, view 조회/생성/수정 +``` + +이유: + +- `$diary-notion` push 경로는 이미 작업 기록의 핵심 경로이므로 안정성이 가장 중요하다. +- `2025-09-03`부터 Notion이 database와 data source를 더 명확히 분리했기 때문에 기존 push 경로를 통째로 올리면 DB 생성, relation, page parent, query 쪽 영향 범위가 커진다. +- `diary-notion ensure`의 view 보장 단계는 Views API와 data source schema update가 필요하므로 `2026-03-11` client로 분리한다. +- 따라서 view 자동화만 새 API version을 쓰고, 기존 기록 기능은 안정 버전에 남긴다. + +`2026-03-11`을 push 경로 전체에 적용하지는 않는다. block append의 `after` → `position`, `archived` → `in_trash`, `transcription` → `meeting_notes` 변경 영향이 있으므로 row/body push는 안정 버전으로 유지한다. + +### 5.2 기존 push 경로 + +기존 row push는 안정성이 중요하므로 현재 구조를 유지한다. + +```text +NotionHierarchicalExporter +Notion-Version: 2022-06-28 +역할: year page, database, row, schema, relation +``` + +`diary-notion ensure`는 view 생성 전 이 경로의 `ensure_database(year, force_schema=True)`를 재사용해 현재 연도 DB와 schema v7를 보장한다. + +### 5.3 view 자동화 경로 + +Views API는 별도 client로 분리한다. + +```text +NotionViewsExporter 또는 NotionViewsClient +Notion-Version: 2026-03-11 +역할: data source schema 보정, view 조회, view 생성, view 설정 update +``` + +조회 순서: + +```text +1. NotionHierarchicalExporter.ensure_database(year) + → root page 확인 + → year page 확인/생성 + → Entries DB 확인/생성 + → schema v7 보장 + → database_id 반환 + +2. NotionViewsClient + → database_id로 database/data source 정보 조회 + → data_source_id 확보 + +3. data source schema 조회 + → property name → property id map 생성 + +4. required property 검증 + → Date + → Work Period + → Status + → Project + → Purpose + → Parent Task + → Task Group + → Sub-items + → Priority + → Next Action + → Blocked + → Block Reason + → Carryover + → Review Status + → Last Reviewed + → Session ID + → Task Index + +5. core/operating view payload 생성 + → filter/group/sorts/subtasks에 property id 사용 + +6. existing views 조회 + → name 기준 매칭 + → 있으면 required 설정 verify + → 없으면 create +``` + +구현 시 고려: + +- `database_id`와 `data_source_id` 관계 확인 +- property id는 hard-code하지 않고 data source schema에서 조회 +- property name → property id map 생성 +- required property 누락 검사 +- existing view 조회 +- 같은 이름 view required 설정 검사 +- required 설정 충족 시 verified 처리 +- required 설정 미충족 시 view update 처리 +- API 버전 변경 영향 격리 + +공식 API 확인 사항: + +- Views API는 API version `2025-09-03` 이상이 필요하다. +- 현재 view/data source client는 `2026-03-11`을 사용한다. +- 2026-03-11 적용은 view/data source client로 제한하고, 기존 body append/push 경로까지 전역 적용하지 않는다. +- view 생성에는 `data_source_id`, `name`, `type`이 필요하고, top-level database view에는 `database_id`가 필요하다. +- filter/sorts는 data source query와 같은 shape를 사용한다. +- table configuration은 `properties`, `group_by`, `subtasks`를 지원한다. +- property configuration은 `visible`, `width`, `wrap`, date/time format 같은 표시 설정을 지원한다. +- subtask configuration은 self-referencing relation property를 사용해 parent-child hierarchy를 표시한다. + +경계: + +- schema v7 보장은 기존 push 경로를 재사용하고, `Parent Task` ↔ `Sub-items` data source relation 보정은 view client가 추가 방어한다. +- view payload 작성과 view 생성은 `NotionViewsClient`가 담당한다. +- property id는 절대 hard-code하지 않는다. +- 신규 컬럼이 추가되어도 data source schema에서 name → id map을 다시 만들어 view payload를 구성한다. + +### 5.4 실패 처리 + +View ensure 실패는 다음처럼 처리한다. + +```text +Auth/permission error → 명확한 안내 후 종료 +Bad request → view 이름과 요청 payload 요약 출력 +Network/rate limit → retry 또는 재실행 안내 +Partial failure → 성공/실패 view를 나눠 보고 +``` + +전제 실패: + +```text +database_id 확보 실패 → exit 1 +data_source_id 확보 실패 → exit 1 +required property 누락 → schema v7 보장 실패 또는 property map 실패, exit 1 +property id 조회 실패 → view 생성 불가, exit 1 +existing view 조회 실패 → view 보장 실패, exit 1 +``` + +작업 기록 push와 다르게, view 보장 단계는 실패해도 데이터 손실이 없다. + +### 5.5 exit code와 partial failure + +`diary-notion ensure`의 view 보장 단계는 보장 view 생성 실패와 best-effort 실패를 구분한다. + +| 상황 | exit code | rollback | 이유 | +|------|-----------|----------|------| +| core/operating view 전부 생성 | 0 | 없음 | 성공 | +| core/operating view 전부 verified | 0 | 없음 | 성공 | +| 기존 보장 view required 설정 update 성공 | 0 | 없음 | 보장 성공 | +| 기존 보장 view required 설정 update 실패 | 1 | 없음 | 보장 실패 | +| 일부 보장 view 실패 | 1 | 없음 | partial failure | +| 인증/권한 실패 | 1 | 없음 | 전제 실패 | +| DB/schema 보장 실패 | 1 | 없음 | 전제 실패 | +| relative today filter 실패 후 fixed date fallback 성공 | 0 | 없음 | best-effort warning | +| `subtasks` 설정 실패 후 base table fallback 성공 | 0 | 없음 | best-effort warning | +| `subtasks` 설정 실패 후 base table fallback 실패 | 1 | 없음 | 작업 계층 view 생성 실패 | + +정책: + +- 보장 view 생성 실패는 partial failure로 보고 exit 1을 반환한다. +- 기존 view가 required 설정을 충족하지 못하면 같은 이름의 보장 view를 update한다. update 실패 시 exit 1을 반환한다. +- 이미 생성된 view는 rollback하지 않는다. +- rollback이 기존 사용자 view나 새로 생성된 정상 view를 건드릴 수 있으므로 더 위험하다. +- relative today filter 실패 후 fixed date fallback이 성공하면 best-effort warning이며 exit code에 영향을 주지 않는다. +- `subtasks` 설정 실패 후 base table fallback이 성공하면 best-effort warning이며 exit code에 영향을 주지 않는다. +- base table fallback까지 실패하면 작업 계층 view 생성 실패이므로 exit 1을 반환한다. +- warning은 CLI 출력에 남겨 사용자가 추후 수동 설정하거나 후속 개선을 요청할 수 있게 한다. + +내부 결과 모델 후보: + +```python +{ + "created": ["작업 계층", "오늘 작업"], + "verified": ["상태별"], + "conflicts": [("목적별", "missing Purpose group_by")], + "failed": [("프로젝트별", "Notion API 400 ...")], + "warnings": [("작업 계층", "subtasks fallback: base table created")] +} +``` + +CLI 출력 예시: + +```text +[working-diary diary-notion ensure] +Database: Entries (existing) +Schema: v7 ensured +Views: + + 작업 계층 + + 오늘 작업 + ! 상태별 -- Notion API 400: ... + x 목적별 -- conflict: missing Purpose group_by + = 프로젝트별 (verified) +Warnings: + ! 작업 계층 subtasks not enabled: base table fallback created +``` + +--- + +## 6. 구현 순서 + +### Step 1. 설계 고정 + +- Core Views 5개 확정 +- 최고모델 Operating Views 5개 확정 +- 오래 방치된 작업, 자동 today-plan, weekly brief는 3차 이후로 분리 +- `diary-notion ensure`가 현재 연도 Entries DB와 schema v7를 보장한다고 명시 + +### Step 2. CLI 뼈대 + +예상 명령: + +```bash +working-diary diary-notion ensure +working-diary diary-notion ensure --year 2026 +working-diary diary-notion ensure --dry-run +claude-diary diary-notion ensure +claude-diary diary-notion ensure --year 2026 +claude-diary diary-notion ensure --dry-run +``` + +CLI 구조 후보: + +```text +claude_diary.cli.notion_ensure + cmd_notion_ensure(args) + ensure_schema() + ensure_views() + verify_views() + plan_ensure() +``` + +### Step 3. DB/schema 보장 + +기존 hierarchical exporter를 재사용한다. + +```text +NotionHierarchicalExporter.ensure_database(year) +→ year page 보장 +→ Entries DB 보장 +→ schema v7 보장 +→ database_id 반환 +``` + +이 단계에서 row는 만들지 않는다. + +### Step 4. View client 추가 + +후보 파일: + +```text +src/claude_diary/exporters/notion_views.py +``` + +역할: + +- credential resolve는 기존 diary-notion push/init과 공유 +- target database/data source 확인 +- `database_id`로 `data_source_id` 확보 +- data source schema 조회 +- property name → property id map 생성 +- required property 누락 검사 +- existing views 조회 +- existing views required 설정 검증 +- missing views 생성 +- `subtasks` 포함 작업 계층 view 생성 실패 시 base table fallback + +### Step 5. 테스트 + +테스트는 네트워크 없이 mock 기반으로 작성한다. + +필수 테스트: + +- DB가 없으면 현재 연도 DB와 schema를 보장하는 경로를 호출 +- `--year`가 대상 연도를 지정 +- `--dry-run`은 생성/수정 없이 계획만 출력 +- `--dry-run`은 year page/database/schema/view를 만들지 않음 +- DB가 없는 `--dry-run`은 생성 계획만 출력 +- `ensure_database(year)`가 `database_id`를 반환 +- `database_id`로 `data_source_id`를 조회 +- data source schema로 property name → property id map 생성 +- required property 누락 시 exit 1 +- property id를 hard-code하지 않음 +- `오늘 작업` relative today filter 생성 +- relative today filter validation 실패 시 fixed date filter fallback + warning +- fixed date fallback view가 오늘 날짜가 아니면 conflict +- 이미 있고 required 설정을 충족하는 view는 verified +- 이미 있지만 required 설정이 부족한 view는 update +- 없는 core/operating view는 create +- `Status` group order 차이는 warning 또는 ignore이며 conflict가 아님 +- `Purpose`의 빈 값/`General` 그룹 위치 차이는 conflict가 아님 +- partial failure를 report +- conflict가 있으면 exit 1 +- 일부 보장 view 실패 시 exit 1 +- `subtasks` 설정 실패 후 base table fallback 성공 시 warning만 남기고 exit 0 +- `subtasks` 설정 실패 후 base table fallback 실패 시 exit 1 +- credential missing 시 안내 +- 기존 row를 수정하지 않음 +- push 경로와 view 경로가 분리되어 있음 +- core 5개와 operating 5개가 모두 보장 대상에 포함됨 + +--- + +## 7. Non-goals + +2차 MVP에서 하지 않는다. + +- `$diary-notion` 실행마다 `diary-notion ensure` 자동 실행 +- `Progress` 계산 컬럼 추가 +- stale view 생성 +- 자동 today-plan 생성과 apply +- weekly brief 생성 +- 프로젝트/작업 그룹 전체 기간 자동 계산 +- 기존 사용자 view 강제 수정 +- 기존 row 생성/수정/삭제 +- 기존 DB 전체 마이그레이션 +- Notion을 Jira처럼 완전한 issue tracker로 만드는 것 + +--- + +## 8. 성공 기준 + +2차 MVP 성공 기준: + +- `working-diary diary-notion ensure`가 현재 연도 Entries DB와 schema v7를 보장한다. +- `working-diary diary-notion ensure --year YYYY`가 지정 연도 Entries DB와 schema v7를 보장한다. +- `working-diary diary-notion ensure --dry-run`이 생성/수정 없이 계획만 출력한다. +- `Work Period` date range 컬럼을 보장하고 core view에 표시한다. +- `Priority`, `Next Action`, `Blocked`, `Block Reason`, `Carryover`, `Review Status`, `Last Reviewed` 운영 컬럼을 보장한다. +- `Parent Task` ↔ `Sub-items` native 하위항목 relation을 보장한다. +- `working-diary diary-notion ensure`가 core view 5개와 operating view 5개를 자동 보장한다. +- 같은 이름의 view가 이미 있으면 중복 생성하지 않는다. +- 같은 이름의 view가 required 설정을 충족하면 verified로 처리한다. +- 같은 이름의 view가 required 설정을 충족하지 않으면 view update로 보정하고, update 실패 시 exit 1을 반환한다. +- 기존 row는 수정하지 않는다. +- 기존 `$diary-notion` push는 변경 없이 계속 동작한다. +- 사용자가 Notion DB에서 작업 계층, 오늘 작업, 상태별, 목적별, 프로젝트별, 오늘 우선순위, 전날 미완료, Blocked, 리뷰 필요, 작업 그룹별로 즉시 탐색할 수 있다. +- stale/자동 today-plan/weekly brief는 operating view와 혼동되지 않는다. diff --git a/docs/02-design/features/working-diary-os.vision.md b/docs/02-design/features/working-diary-os.vision.md new file mode 100644 index 0000000..fd74b10 --- /dev/null +++ b/docs/02-design/features/working-diary-os.vision.md @@ -0,0 +1,467 @@ +# Working Diary OS Vision + +> **Summary**: AI 코딩 세션, Git, Notion 작업 DB, 로컬 작업 메모를 연결해 기록, 구조화, 조회, 운영, 리뷰까지 지원하는 개인 업무 운영 시스템의 최종 방향 +> +> **Project**: claude-code-hooks-diary +> **Date**: 2026-06-01 +> **Status**: Vision Draft + +## 1. 목적 + +Working Diary OS는 단순 작업일지 생성기가 아니다. 최종 목표는 사용자가 여러 프로젝트와 여러 AI 세션에서 수행한 일을 자동으로 기록하고, 작업 구조와 근거를 잃지 않으며, 다음 행동과 우선순위를 판단할 수 있게 만드는 개인 업무 운영 시스템이다. + +핵심 질문은 다음 세 가지다. + +- 오늘 무엇을 했는가? +- 무엇이 막혀 있고 왜 막혀 있는가? +- 다음에 무엇을 해야 하는가? + +## 2. 최종 사용자 경험 + +사용자는 평소에는 세션 안에서 짧게 명령만 실행한다. + +```bash +$diary +$diary-notion +``` + +시스템은 세션의 대화, 도구 사용, 파일 변경, 명령어, Git 정보를 기반으로 작업 단위 row를 만든다. Notion에서는 다음과 같이 볼 수 있어야 한다. + +```text +프로젝트 A + 큰 작업 1 + 세부 작업 1 + 세부 작업 2 + 큰 작업 2 + +프로젝트 B + 막힌 작업 + 검증 대기 작업 +``` + +추가 명령은 필요할 때만 실행한다. + +```bash +working-diary diary-notion ensure +working-diary diary-notion ensure --dry-run +working-diary diary-notion today-plan +working-diary diary-notion review +working-diary diary-notion weekly-brief +``` + +최종 모델에서도 사용자-facing 명령은 최소화한다. Notion 기반 정비는 `working-diary diary-notion ensure` 하나를 기본 진입점으로 두고, schema/view/status/drift 관련 세부 작업은 내부 단계와 옵션으로 확장한다. + +최종적으로 사용자는 Notion DB를 열어 다음을 확인할 수 있어야 한다. + +- 작업 계층: 어떤 일이 어떤 큰 작업의 하위인지 +- 상태: 논의, 설계, 구현, 테스트, 배포 중 어디인지 +- 종속성: 무엇이 선행되어야 하는지 +- 근거: 어떤 파일, 명령어, 커밋, 테스트가 있었는지 +- 리스크: 무엇이 막혀 있고 누가 결정해야 하는지 +- 다음 액션: 다음 세션에서 무엇부터 해야 하는지 +- 오늘 계획: 전날 남긴 todo와 `next_steps`를 기준으로 무엇을 우선 처리해야 하는지 + +## 3. 핵심 원칙 + +### 3.1 기록은 자동, 판단은 보수적으로 + +세션에서 관찰된 사실은 자동으로 남긴다. 하지만 상태 변경, 우선순위, blocked 판정처럼 사용자 판단에 영향을 주는 값은 보수적으로 계산하고, 가능하면 dry-run으로 먼저 보여준다. + +### 3.2 구조는 DB, 근거는 본문 + +작업 구조는 Notion DB property로 표현한다. + +- `Project` +- `Purpose` +- `Task Group` +- `Status` +- `Parent Task` +- `Depends On` +- `Work Period` +- `Priority` +- `Next Action` +- `Blocked` +- `Block Reason` +- `Carryover` +- `Review Status` +- `Last Reviewed` + +본문은 사람이 읽는 근거를 담당한다. + +- 요약 +- 작업 한눈에 +- 검증 및 상태 +- 다음 액션 +- 접힌 부록: 코드 변경, 파일, 명령어, Git, 원문 요청 + +### 3.3 포함 관계와 선행 관계를 분리 + +`Parent Task`와 `Depends On`은 의미가 다르다. + +```text +Parent Task = 포함 관계 +예: "상품 목록 포커싱"은 "로컬 테스트 진행"의 하위 작업 + +Depends On = 큰 메인 작업끼리의 선행 관계 +예: "2차 view 자동화 구현"은 "schema v7 보장"이 끝나야 가능 +``` + +하위 작업은 `Parent Task`와 Notion sub-item으로 표현하고, 종속성으로 연결하지 않는다. 두 관계를 섞으면 view, 진행률, blocked 계산이 모두 부정확해진다. + +### 3.4 수동 수정은 자동화보다 우선 + +사용자가 Notion에서 직접 고친 값은 자동화가 함부로 덮어쓰지 않는다. 자동화가 값을 바꿀 때는 다음 중 하나를 만족해야 한다. + +- 명령에 `--apply`가 명시되어 있다. +- 값이 시스템 전용 컬럼이다. +- 사용자가 명시적으로 force/sync를 요청했다. + +### 3.5 작업 row는 의미 단위로만 만든다 + +row로 만들 기준: + +- 독립적으로 상태를 추적할 작업 +- 다른 작업의 선행 조건이 되는 작업 +- 파일/코드/테스트/커밋 근거가 남는 작업 +- 며칠 뒤 다시 찾아야 하는 작업 + +본문 checklist로 둘 기준: + +- 단순 확인 항목 +- 긴 SQL/JS/로그/메모 +- 참고 링크 +- 너무 작은 단계 + +## 4. 데이터 모델 + +### 4.1 현재 고정 모델 + +| 필드 | 역할 | +|------|------| +| `Name` | 작업 제목 | +| `Date` | 작업 기록일 | +| `Work Period` | 실제 작업 기간. 프로젝트/작업 그룹 기간 계산 재료 | +| `Project` | 프로젝트 필터/그룹 | +| `Purpose` | Feature, Bugfix, Planning 등 목적 | +| `Status` | Discussion, Design, Implementation, Testing, Deployed | +| `Task Group` | 여러 세션을 묶는 큰 작업 단위 | +| `Parent Task` | 포함 관계. Notion 하위항목/sub-item 기반 | +| `Depends On` | 큰 메인 작업끼리의 선행 관계 | +| `Priority` | P0/P1/P2/P3 우선순위 | +| `Next Action` | 다음에 바로 실행할 행동 | +| `Blocked`, `Block Reason` | 현재 진행 불가 여부와 막힘 원인 | +| `Carryover` | 전날/이전 세션 미완료 작업 이어가기 | +| `Review Status`, `Last Reviewed` | 검토 필요/완료/보류와 실제 검토일 | +| `Categories` | 보조 라벨 | +| `Files`, `Commits`, `Lines` | 변경 규모 | +| `Session ID`, `Task Index` | 멱등성 | + +### 4.2 확장 후보 모델 + +3차 이후 추가를 검토한다. + +| 필드 | 역할 | +|------|------| +| `Stale Score` | 오래 방치된 정도 | +| `Progress` | 하위 작업 기준 진행률 | +| `Review Notes` | 주간/일간 리뷰 결과 | + +확장 컬럼은 기존 핵심 모델을 대체하지 않고 보조한다. + +### 4.3 Work Period 적용 원칙 + +`Date`와 `Work Period`는 최종 모델에서도 분리한다. + +```text +Date = 기록일 +Work Period = 실제 작업 기간 +``` + +`오늘 작업` view와 daily brief는 `Date`를 기준으로 한다. 사용자가 오늘 `$diary-notion`으로 남긴 수행분을 보여주는 것이 목적이기 때문이다. + +프로젝트 산출물, 작업 그룹, 주간/월간 회고의 실제 작업 기간은 `Work Period`를 기준으로 계산한다. + +집계 규칙: + +```text +Project duration += 같은 Project row들의 min(Work Period.start) ~ max(Work Period.end) + +Task Group duration += 같은 Task Group row들의 min(Work Period.start) ~ max(Work Period.end) + +Work days += Work Period가 포함하는 날짜의 unique day count +``` + +어제 시작한 작업을 오늘 이어서 했다면 오늘 수행분은 새 row로 남기고 같은 `Task Group`으로 묶는다. 기존 row의 `Work Period`를 자동으로 늘리지 않는다. + +```text +2026-06-01 row +Date = 2026-06-01 +Work Period = 2026-06-01 +Task Group = diary-notion-view-design + +2026-06-02 row +Date = 2026-06-02 +Work Period = 2026-06-02 +Task Group = diary-notion-view-design +``` + +최종 모델에서는 이 row들을 읽어 프로젝트/작업 그룹 단위의 기간을 제안한다. 실제 요약 row, 요약 DB, `First Worked On`, `Last Worked On`, `Work Days` 같은 계산 컬럼을 만들지는 Phase 3 이후 별도 apply 단계로 둔다. + +## 5. 자동화 경계 + +### 5.1 에이전트 책임 + +- 세션을 의미 단위 작업으로 나눈다. +- 제목과 설명형 본문을 한국어로 작성한다. +- 파일, 명령어, branch, commit hash, 코드 식별자는 원문을 보존한다. +- `parent_index`와 `depends_on_indices`를 구분해 작성한다. +- 하위 작업은 `parent_index`로 연결하고, `depends_on_indices`는 최상위 메인 작업 간 선행 관계에만 사용한다. +- `Priority`, `Next Action`, `Blocked`, `Block Reason`, `Carryover`, `Review Status`, `Last Reviewed`를 보수적으로 작성한다. + +### 5.2 CLI 책임 + +- JSON을 검증하고 Notion row를 생성한다. +- Git 메타데이터를 수집한다. +- `Parent Task`와 `Depends On` relation을 row 생성 후 연결한다. +- `Depends On` 연결 시 하위 작업 row는 제외해 sub-item 구조와 선행 관계가 섞이지 않게 한다. +- `Project` 누락/unknown은 명령 실행 cwd 폴더명으로 보정한다. +- Notion schema/view 동기화는 `diary-notion ensure` 명령 단위로 분리한다. + +### 5.3 운영/리뷰 엔진 책임 + +3차 이후의 책임이다. + +- 오래 방치된 작업을 찾는다. +- 반복되는 리스크를 요약한다. +- schema/view conflict를 drift 관리 대상으로 분류하고 해결 계획을 제안한다. +- `Project` 또는 `Task Group`별 `Work Period`의 최소 시작일과 최대 종료일을 계산해 실제 작업 기간을 제안한다. +- 전날/최근 N일의 미완료 todo와 `next_steps`를 수집한다. +- `Depends On`, `Blocked`, `Status`, `Task Group` 연속성을 반영해 오늘 우선순위를 제안한다. +- 다음 액션 후보를 제안한다. +- 상사 보고용 daily/weekly brief를 생성한다. + +리뷰 엔진은 기본적으로 제안만 한다. 실제 Status/Priority/schema/view 변경은 별도 apply 단계가 필요하다. + +### 5.4 Conflict / Drift 관리 + +최종 모델에서 conflict는 단순 실패 메시지가 아니라 시스템 drift 관리 대상이다. + +기본 흐름: + +```text +Conflict 감지 +→ 원인 분류 +→ 해결 계획 제안 +→ dry-run 출력 +→ 사용자 승인 시 apply +→ 변경 내역 기록 +``` + +명령 방향: + +```bash +working-diary diary-notion ensure +working-diary diary-notion ensure --dry-run +working-diary diary-notion ensure --plan +working-diary diary-notion ensure --apply +working-diary diary-notion ensure --force +``` + +동작: + +- `diary-notion ensure`: conflict를 감지하고 이유와 수동 해결 안내를 출력한다. +- `diary-notion ensure --dry-run`: 생성/수정 없이 현재 상태 기준 계획만 출력한다. +- `diary-notion ensure --plan`: 어떤 view/schema를 어떻게 고칠지 변경 계획만 출력한다. +- `diary-notion ensure --apply`: 사용자가 승인한 변경만 적용한다. +- `diary-notion ensure --force`: 시스템이 관리하는 view만 재생성하거나 업데이트한다. + +conflict 유형: + +| 유형 | 예시 | 기본 처리 | +|------|------|-----------| +| Name conflict | 같은 이름 view가 있지만 type/filter/group이 다름 | conflict, exit 1 | +| Required setting conflict | `오늘 작업`에 today filter 없음 | conflict, exit 1 | +| Presentation drift | column width, group order, wrap 차이 | warning | +| Unsupported capability | `subtasks` API 실패 | fallback + warning | +| Schema conflict | `Work Period` 누락 | schema ensure로 보강, 실패 시 exit 1 | + +원칙: + +- 자동화는 감지와 제안까지 기본값이다. +- 수정은 `--apply` 또는 `--force`가 있어야 한다. +- 사용자 수동 view는 기본적으로 보호한다. +- conflict 해결을 위해 `오늘 작업 (Generated)` 같은 대체 view를 자동 생성하지 않는다. +- 반복 conflict는 review/weekly brief에서 내부 운영 리스크로 요약할 수 있지만, 상사 보고용 핵심 성과와는 분리한다. + +## 6. Phase Roadmap + +### Phase 1. Structure + +목표: 작업을 정확한 DB row와 relation으로 기록한다. + +완료 기준: + +- Claude `/diary-notion`과 Codex `$diary-notion`이 동일한 작업 구조를 생성한다. +- `Parent Task`와 `Depends On`이 분리된다. +- page body는 compact body와 접힌 근거로 정리된다. + +### Phase 2. Views + +목표: Notion에서 작업 관리 화면처럼 보이게 만든다. + +예상 명령: + +```bash +working-diary diary-notion ensure +``` + +Core Views: + +- 작업 계층 +- 오늘 작업: 오늘 해야 할 일이 아니라 오늘 실제로 기록된 수행분 +- 상태별 +- 목적별 +- 프로젝트별 + +Core follow-up: + +- 없음. Core Views 5개는 최종 모델에서도 기본 화면으로 유지한다. + +Operations/Intelligence views: + +- 오늘 우선순위 +- 전날 미완료 +- Blocked +- 리뷰 필요 +- 작업 그룹별 + +Phase 2에서 보장하는 schema v7 운영 컬럼: + +- `Priority` +- `Next Action` +- `Blocked` +- `Block Reason` +- `Carryover` +- `Review Status` +- `Last Reviewed` + +하위 항목 정책: + +- 메인 작업과 하위 작업의 `Parent Task` 데이터 구조는 2차에서 필수로 보장한다. +- Notion의 접기/펼치기 sub-item UI는 최종 목표이며 2차에서는 best-effort로 활성화한다. +- sub-item UI 설정이 실패하면 `Parent Task`와 `Work Period`가 표시되는 base table view로 fallback한다. + +View 자동화는 push 실패와 분리한다. view 생성/갱신 실패가 작업 기록 실패로 이어지면 안 된다. + +### Phase 3. Operations + +목표: 쌓인 DB를 읽어 상태를 점검하고 운영 정보를 계산한다. + +예상 명령: + +```bash +working-diary diary-notion ensure --dry-run +working-diary diary-notion ensure --apply +``` + +기능 후보: + +- 하위 작업 기반 진행률 계산 +- schema/view conflict 유형 분류 +- conflict dry-run plan 출력 +- 반복 conflict 추적 +- `Project`/`Task Group`별 실제 작업 기간 계산 +- `Work Period` 기반 work days 계산 +- 오래 방치된 작업 탐지 +- 검증 누락 탐지 +- 상위 작업 상태 제안 +- 전날 미완료 row와 `Next Action`을 기반으로 today-plan 후보 제안 + +### Phase 4. Intelligence + +목표: 쌓인 작업 데이터를 바탕으로 우선순위, 리스크, 다음 액션을 제안한다. + +예상 명령: + +```bash +working-diary diary-notion today-plan +working-diary diary-notion review +working-diary diary-notion weekly-brief +``` + +기능 후보: + +- 전날 남긴 todo/`next_steps` 기반 오늘 작업 우선순위 Top N 생성 +- 선행 작업이 완료된 후속 작업을 오늘 후보로 승격 +- 아직 막힌 작업은 blocker로 분리하고 우선순위 산정에서 제외하거나 낮춤 +- 프로젝트별 이번 주 요약과 실제 작업 기간 요약 +- 다음 작업 우선순위 추천 +- 반복 이슈 탐지 +- weekly review에 view/schema drift 요약 +- 상사 보고용 brief 생성 +- 다음 세션 시작용 handoff 생성 + +`today-plan`은 하루 시작 시 사용하는 명령이다. 기본 출력은 제안이며 Notion 값을 변경하지 않는다. + +```text +오늘 작업 우선순위 + +1. 결제 진행 중 키패드 차단 + 이유: 전날 next_steps에 남았고 배리어프리 로컬 테스트 완료를 막고 있음 + +2. 테스트 DB 복구 상태 확인 + 이유: 상품 목록/결제 플로우 테스트의 선행 조건 + +3. Terraform 04-modules-basic 진행 + 이유: 01~03이 완료됐고 다음 학습 순서 +``` + +### Phase 5. Multi-project OS + +목표: Notion만이 아니라 Git/GitHub/로컬 문서/AI 세션을 연결한다. + +기능 후보: + +- GitHub issue/PR 연결 +- 프로젝트별 backlog와 diary 연결 +- commit/PR 기준 작업 회고 +- 여러 프로젝트의 오늘 우선순위 통합 +- 로컬 Markdown diary와 Notion DB 양방향 참조 +- 여러 Notion DB/프로젝트의 schema/view drift 관리 +- 시스템 관리 view와 사용자 view 분리 +- 승인 기반 apply/force 운영 + +## 7. Non-goals + +현재 비목표: + +- 사용자의 모든 Notion 수동 편집을 자동으로 추적하거나 병합 +- Notion을 완전한 Jira 대체제로 만드는 것 +- 매 push마다 view/status/review 자동화를 모두 실행 +- AI가 사용자 승인 없이 우선순위나 Status를 확정 변경 +- 과거 모든 diary를 자동 마이그레이션 + +## 8. 리스크 + +| 리스크 | 설명 | 대응 | +|--------|------|------| +| 과도한 row 분리 | 체크리스트 수준 항목까지 row가 되어 DB가 지저분해짐 | row 생성 기준을 skill에 유지 | +| 자동화의 과잉 판단 | Status/Priority를 잘못 바꿈 | dry-run, 수동 우선 원칙 | +| API 버전 변화 | Notion View/Data Source API가 변경됨 | view 자동화를 push와 분리 | +| relation 오용 | Parent와 Depends On이 섞임 | 문서/skill/test에서 의미 고정 | +| 본문 장황화 | page body가 다시 보고서처럼 길어짐 | compact body와 toggle 부록 유지 | + +## 9. 성공 기준 + +최고모델의 성공 기준은 기능 개수가 아니라 사용자의 다음 행동 판단이 쉬워졌는지다. + +- 작업 하나를 열면 무엇을 했는지 30초 안에 파악된다. +- 프로젝트 하나를 보면 진행 중/막힌 일/다음 액션이 보인다. +- 프로젝트나 작업 그룹을 모아 보면 실제 작업 기간이 파악된다. +- 하루 시작 시 전날 todo와 미완료 작업을 다시 훑지 않아도 오늘 우선순위가 제안된다. +- 다음 세션을 시작할 때 이전 맥락을 다시 설명하지 않아도 된다. +- 상사 보고용 daily/weekly brief를 별도 정리 없이 만들 수 있다. +- 자동화가 사용자의 수동 판단을 방해하지 않는다. diff --git a/docs/04-report/diary-notion-phase-2/README.md b/docs/04-report/diary-notion-phase-2/README.md new file mode 100644 index 0000000..c19a0ca --- /dev/null +++ b/docs/04-report/diary-notion-phase-2/README.md @@ -0,0 +1,377 @@ +# Diary Notion Phase 2 Implementation + +> 2차 구현은 Notion 작업 DB를 단순 기록 저장소에서 작업 관리 화면으로 확장하는 단계다. 이 문서는 구현 내용을 단계별로 계속 누적하기 위한 README다. + +## 목표 + +2차의 목표는 `$diary-notion`으로 쌓인 작업 row를 Notion 안에서 바로 탐색할 수 있게 만드는 것이다. + +- schema v7로 `Work Period`, native sub-item relation, 우선순위/막힘/리뷰 운영 컬럼을 보장한다. +- `working-diary diary-notion ensure` 명령으로 DB schema, core views, operating views를 보장한다. +- 기존 push 경로는 안정성을 유지하고, view 자동화는 별도 명령으로 분리한다. +- 기존 Notion view와 row는 자동으로 덮어쓰지 않는다. +- conflict는 감지하고 보고하되, 사용자가 직접 수정하거나 후속 apply 단계에서 처리한다. + +## 현재 구현 상태 + +| 항목 | 상태 | 내용 | +| --- | --- | --- | +| Schema v7 | 완료 | `Work Period`, `Parent Task` ↔ `Sub-items`, Priority/Blocked/Review 운영 컬럼 추가 | +| Push 보강 | 완료 | 작업 row 생성 시 `Work Period` 기록 | +| Ensure CLI | 완료 | `working-diary diary-notion ensure`, `claude-diary diary-notion ensure` 지원 | +| Core Views | 완료 | 5개 core view 생성/검증 | +| Operating Views | 완료 | `오늘 우선순위`, `전날 미완료`, `Blocked`, `리뷰 필요`, `작업 그룹별` 생성/검증 | +| Dry-run | 완료 | 생성/수정 없이 계획 출력 | +| Core view update | 완료 | 기존 view required 설정 mismatch 시 같은 이름의 view를 update | +| Subtasks fallback | 완료 | `작업 계층` sub-item 설정 실패 시 base table fallback | +| Relative today fallback | 완료 | `오늘 작업` relative today filter 실패 시 fixed date fallback | +| View 자동 수정 | 완료 | 기존 보장 view required 설정 mismatch 시 같은 이름의 view를 update | + +## 단계별 구현 기록 + +### Step 1. Schema v7 보장 + +`NotionHierarchicalExporter`의 schema 버전을 `v7`로 올리고 `Work Period` date 컬럼, `Parent Task` ↔ `Sub-items` 양방향 relation, Priority/Blocked/Review 운영 컬럼을 추가했다. + +주요 내용: + +- schema 기록이 없거나 오래된 DB는 현재 extension schema 전체를 patch한다. +- `diary-notion ensure`에서는 cache가 현재 버전이어도 schema patch를 강제로 한 번 보내 보장성을 높인다. + +수정 파일: + +- `src/claude_diary/exporters/notion_hierarchical.py` +- `tests/test_notion_hierarchical.py` + +### Step 2. Work Period row 기록 + +`$diary-notion` push가 생성하는 각 작업 row에 `Work Period` 값을 넣도록 보강했다. + +입력 규칙: + +```json +{ + "work_period": "2026-06-02" +} +``` + +```json +{ + "work_period": { + "start": "2026-06-01", + "end": "2026-06-02" + } +} +``` + +지원 형태: + +- 값이 없으면 기록일 `Date`와 같은 날짜를 사용한다. +- `YYYY-MM-DD` 문자열을 지원한다. +- `YYYY-MM-DD..YYYY-MM-DD` 문자열 range를 지원한다. +- `{ "start": "...", "end": "..." }` 객체 range를 지원한다. + +수정 파일: + +- `src/claude_diary/cli/notion_push.py` +- `tests/test_notion_push.py` +- `skills/diary-notion/SKILL.md` +- `src/claude_diary/cli/setup.py` + +### Step 3. Ensure CLI 추가 + +사용자 facing 명령은 하나로 유지한다. + +```bash +working-diary diary-notion ensure +working-diary diary-notion ensure --year 2026 +working-diary diary-notion ensure --dry-run +claude-diary diary-notion ensure +``` + +동작: + +- 일반 실행은 year page, Entries DB, schema v7, core/operating views를 보장한다. +- `--year`는 대상 연도를 명시한다. +- `--dry-run`은 생성/patch 없이 접근 가능한 현재 상태 기준으로 계획만 출력한다. +- DB가 없는 dry-run은 생성 계획만 출력하고 실제 Notion에는 쓰지 않는다. + +수정 파일: + +- `src/claude_diary/cli/__init__.py` +- `src/claude_diary/cli/notion_ensure.py` +- `tests/test_cli.py` +- `tests/test_notion_ensure.py` + +### Step 4. Views API client 분리 + +기존 push 경로와 view 자동화 경로를 분리했다. + +```text +NotionHierarchicalExporter + Notion-Version: 2022-06-28 + 역할: year page, Entries DB, schema, row, relation + +NotionViewsClient + Notion-Version: 2025-09-03 + 역할: data source, property id map, view list/retrieve/create +``` + +분리 이유: + +- push 경로는 이미 안정화된 기록 경로이므로 API version 변경 영향을 최소화해야 한다. +- Views API와 data source schema update는 `2026-03-11` client에서 처리하므로 별도 client가 맞다. +- view 생성 실패가 `$diary-notion` row 기록 실패로 이어지지 않게 한다. + +수정 파일: + +- `src/claude_diary/exporters/notion_views.py` +- `tests/test_notion_views.py` + +### Step 5. Core Views 5개 생성/검증 + +2차 MVP에서 보장하는 core views: + +| View | 목적 | Required 기준 | +| --- | --- | --- | +| 작업 계층 | 상위/하위 작업 탐색 | `Parent Task`, `Work Period` 표시 | +| 오늘 작업 | 오늘 기록한 수행분 확인 | `Date = today`, `Date desc`, `Work Period` 표시 | +| 상태별 | 진행 단계 확인 | `Status` group_by | +| 목적별 | 작업 성격별 확인 | `Purpose` group_by | +| 프로젝트별 | 프로젝트별 작업 확인 | `Project` group_by | + +검증 원칙: + +- 같은 이름의 view가 없으면 생성한다. +- 같은 이름의 view가 required 설정을 만족하면 verified 처리한다. +- 같은 이름의 view가 required 설정을 만족하지 않으면 `ensure`는 Views API update로 보장 view 기본 설정을 보정한다. +- `--dry-run`에서는 실제 보정 없이 update planned로 보고한다. +- `Session ID`, `Task Index`는 hidden property로 유지한다. +- `작업 계층`은 `Sub-items` 기반 native 하위항목/sub-item 중심 view이며 `Parent Task`를 표시하고 `Depends On`은 숨긴다. +- `Depends On`은 하위 작업이 아니라 큰 메인 작업끼리의 선행 연결성에만 사용한다. + +최고모델에서 함께 보장하는 operating views: + +| View | 목적 | Required 기준 | +| --- | --- | --- | +| 오늘 우선순위 | 오늘 처리할 작업을 우선순위대로 확인 | `Date = today`, `Blocked = false`, `Priority asc` | +| 전날 미완료 | 이전 기록일에서 완료되지 않은 작업 확인 | `Date before today`, `Status != Deployed`, `Priority asc` | +| Blocked | 외부 결정/권한/정보 때문에 막힌 작업 확인 | `Blocked = true`, `Block Reason` 표시 | +| 리뷰 필요 | 검토가 필요한 작업 확인 | `Review Status = Needs Review` | +| 작업 그룹별 | 여러 날/세션에 걸친 큰 작업 흐름 확인 | `Task Group` group_by | + +검증 보정: + +- Notion data source schema는 property id를 URL-encoded 형태로 반환할 수 있다. +- Notion view retrieve 응답은 같은 property id를 decoded 형태로 반환한다. +- 따라서 property id map 생성 시 id를 decode해 view 응답과 같은 기준으로 비교한다. +- 이 보정이 없으면 실제 view가 정상 생성되어도 dry-run에서 false conflict가 발생한다. + +### Step 6. Best-effort fallback + +두 가지는 core 성공 기준이 아니라 best-effort로 처리한다. + +`작업 계층` subtasks fallback: + +- 우선 `Sub-items` self-relation 기반 `subtasks` 설정을 포함해 생성한다. +- Notion API가 거절하면 `subtasks`를 제거한 base table view로 다시 생성한다. +- base table 생성이 성공하면 warning만 출력하고 exit 0을 유지한다. + +`오늘 작업` relative today fallback: + +- 우선 `Date equals today` relative filter로 생성한다. +- Notion API validation이 실패하면 실행일 기준 fixed date filter로 다시 생성한다. +- fixed date fallback이 성공하면 warning만 출력한다. + +### Step 7. 문서와 설치 지시문 반영 + +사용자가 새 세션에서도 같은 구조를 만들 수 있도록 README와 skill 지시문을 갱신했다. + +반영 내용: + +- README에 `working-diary diary-notion ensure` 명령 추가 +- README에 `Work Period`, `Priority`, `Blocked`, `Next Action`, `Review Status` 컬럼 설명 추가 +- Codex skill JSON 예시에 `work_period`, `priority`, `next_action`, `blocked`, `block_reason`, `carryover`, `review_status`, `last_reviewed` 추가 +- 설치용 embedded Codex skill에도 동일 지시문 반영 +- CHANGELOG에 구현 항목 추가 + +수정 파일: + +- `README.md` +- `README.en.md` +- `CHANGELOG.md` +- `skills/diary-notion/SKILL.md` +- `src/claude_diary/cli/setup.py` +- `tests/test_setup.py` +- `tests/test_codex_plugin.py` + +### Step 8. 생성 본문 품질 피드백 + +실제 `$diary-notion`으로 생성된 Notion page body를 검토한 결과, 정보량은 충분하지만 읽기 UX가 아직 최종 형태에 미치지 못한다. + +확인된 문제: + +- `body_intro`, `summary_hints`, `work_context`, `work_scope`, `approach`, `outcome`, `impact`, `risks`가 대부분 callout으로 렌더링되어 `