# 아리(Ari) — 포스트-MVP 개발 로드맵 & 횡단 아키텍처 > 한 줄 요약: MVP 3페이지(작업·인박스·대시보드) 위에 **나머지 10개 페이지 + 횡단 자율성 레이어**(자동화 엔진·승인 큐·커넥터·에이전트·RAG·멀티모달·이벤트 버스·스케줄러·인증)를 얹어, "적을 때는 분류하지 않는다 — 분류·배치·자동화는 아리가"라는 철학을 **실연동·능동 에이전트**까지 끌어올리는 포스트-MVP 진입 문서. > **이 문서는 포스트-MVP 세트의 일부 — 먼저 `dev/overview.md`(MVP 정본)와 이 `dev/post-mvp-overview.md`를 읽으세요.** 이후 `phase-7-approvals-automation.md` → `phase-8-calendar-meetings.md` → `phase-9-mail-notifications.md` → `phase-10-research-travel.md` → `phase-11-life-care.md` → `phase-12-daily-narrative.md` → `phase-13-integrations.md` → `phase-14-proactive-agent.md` → `phase-15-production.md` 순서로 진행합니다. 이 문서의 모든 값(색 HEX, px, 클래스명, 한국어 UI 문구, 데이터 필드/시드 값)은 아래 원본에서 **그대로 인용**했습니다. 스택·토큰·데이터모델·API·환경변수·시드·명명 규약은 `dev/overview.md`와 `dev/phase-2-backend.md`를 **상속**하며 임의 변경하지 않습니다. ``` REF = /Users/kim1634/mycloud/personal/workspace/ari_assistant/workspace/design-reference REF/PROJECT-README.md (제품·연합 가치 §5) REF/결재함.html · REF/자동화.html · REF/일정.html · REF/메일.html · REF/알림.html REF/리서치.html · REF/여행.html · REF/라이프.html · REF/여정.html · REF/하루 마감.html REF/assets/approve-data.js (결재함: savedToday/autoCountNight/items[risk,cta,alt,undoLabel]/log) REF/assets/auto-data.js (자동화: stats/examples/rules/suggests/log) REF/assets/cal-data.js (일정: cals/events/focusBlocks/meets, today=8) REF/assets/mail-data.js (메일: accounts/folders/people/emails[ai{...}]/sent/drafts) REF/assets/notify-data.js (알림: stats/buckets{now,later,held}/guard/digests/senders) REF/assets/research-data.js (리서치: collections/sources/report/qa/chart) REF/assets/trip-data.js (여행: trip/route/stay/prep/days/check/expense/saved/planner) REF/assets/life-data.js (라이프: sources/health/finance/knowledge) REF/assets/journey-clean-data.js (여정: stages/cards/links/rows) REF/assets/wrap-data.js (하루 마감: stats/highlights/rollover/tomorrow/prep/sleepNote) REF/assets/shell.jsx (MAIN 13항목, Icon P 맵, Topbar/SubRail) REF/assets/dash.css (디자인 토큰 :root — 상속) ``` --- ## 0. 목차 1. [개요 & 목표](#1-개요--목표) 2. [선행 조건 / 산출물](#2-선행-조건--산출물) 3. [포스트-MVP 비전 — 3페이지 → 13페이지 + 연합 + 실연동 + 능동](#3-포스트-mvp-비전--3페이지--13페이지--연합--실연동--능동) 4. [무엇이 추가되나 — 10개 페이지 + 횡단 레이어](#4-무엇이-추가되나--10개-페이지--횡단-레이어) 5. [횡단 아키텍처 다이어그램](#5-횡단-아키텍처-다이어그램) 6. [연합(federation) 시나리오](#6-연합federation-시나리오) 7. [phase 7~15 로드맵 & 의존 그래프](#7-phase-715-로드맵--의존-그래프) 8. [신규 데이터 테이블 개요 (MVP 모델 확장)](#8-신규-데이터-테이블-개요-mvp-모델-확장) 9. [event_bus 이벤트 타입 & 연합 이벤트(발행/구독)](#9-event_bus-이벤트-타입--연합-이벤트발행구독) 10. [가정/결정 (assumptions) — 사용자가 조정 가능한 지점](#10-가정결정-assumptions--사용자가-조정-가능한-지점) 11. [비기능 목표(성능/접근성/관측성)의 포스트-MVP 상향선](#11-비기능-목표성능접근성관측성의-포스트-mvp-상향선) 12. [상태 처리 & 엣지 케이스 (포스트-MVP 전역)](#12-상태-처리--엣지-케이스-포스트-mvp-전역) 13. [테스팅 & 검증](#13-테스팅--검증) 14. [완료 기준 (Definition of Done)](#14-완료-기준-definition-of-done) 15. [이 문서 세트 사용법 + MVP 문서와의 관계](#15-이-문서-세트-사용법--mvp-문서와의-관계) > (위 §번호는 본 진입 문서 내부의 절 번호입니다. CONTRACT 아웃라인 1~11 항목과 1:1 대응하며 일부 절은 통합되어 있습니다.) --- ## 1. 개요 & 목표 이 문서는 **아리 포스트-MVP**의 진입 문서이자 단일 출처(single source of truth)입니다. `dev/overview.md`가 MVP(작업·인박스·대시보드 3페이지)의 정본이라면, 이 문서는 그 **후속**으로서 나머지 10개 페이지와 **횡단 자율성 아키텍처**(automation/connectors/agents/rag/worker), **연합(event_bus)**, **실연동(mock→real 커넥터)**, **능동 에이전트/멀티모달**, **프로덕션 하드닝**까지 총괄합니다. **이 문서가 끝나면 무엇이 동작하는가**: 직접 코드가 동작하지는 않습니다 — 이 문서는 *지도*입니다. 그러나 읽고 나면 개발자는 (1) MVP 위에 무엇을 더 만드는지, (2) 어떤 횡단 레이어(고정 명명)로, (3) 어떤 순서(phase 7→15)로, (4) 어떤 신규 테이블/이벤트/계약으로 만드는지를 완전히 이해하고 `phase-7-approvals-automation.md`로 바로 진입할 수 있습니다. **포스트-MVP의 한 줄 정의**: 지우(PM)의 한 주(6/7~6/13, 오늘 6/8)에서, 아리가 **밤사이 자동으로 처리한 일**을 결재함에서 승인·되돌리고(`risk: low|high`), 자연어 한 문장이 자동화 규칙이 되며, 메일·회의의 액션이 작업으로 흐르고, 리서치·여행은 멀티스텝 **에이전트**가 종합하고, 라이프(건강·금융·지식)는 **커넥터**가 끌어오며, 여정·하루 마감이 전 페이지를 **집계**하고, 외부 제공자(Gmail/Calendar/Health/금융/Notion)는 **같은 인터페이스로 mock→real 교체**되는 — **연합으로 하나의 흐름을 이루는 Life OS**. --- ## 2. 선행 조건 / 산출물 ### 2.1 선행 조건 (의존 문서) | 의존 | 내용 | |---|---| | `dev/overview.md` | 스택·페르소나·데이터모델·API·디자인 토큰·연합 흐름의 MVP 정본. **상속**. | | `dev/phase-2-backend.md` | 신규 테이블/엔드포인트가 따라야 할 패턴(SQLModel `models.py`, Pydantic `schemas.py`, 라우터 내부 prefix 없음 + `main.py` `include_router(prefix="/api", tags=...)`, `run_seed(session=None, reset=True)`, `LLMProvider`/`get_provider()`). **상속**. | | `dev/phase-1-design-system.md` | 디자인 토큰(`tokens.css`)·`Icon`/`Topbar`(MAIN 13항목)/`SubRail`·라이트/다크·glass. 포스트-MVP 페이지가 셸을 **재사용**. | | `dev/phase-3-tasks.md` | 트리/칸반 패턴·`useTasks`/`useTree` — 메일→작업, 회의→작업, 인박스→작업 federation 도착지. | | MVP phase 0~6 완료 | phase 7은 MVP 직후 **최우선**(철학 실현). 나머지는 mock-first로 병렬화 가능하나 빌드 순서는 §7 권장. | ### 2.2 산출물 (Deliverables) | 산출물 | 내용 | 절 | |---|---|---| | 포스트-MVP 비전 | 3→13페이지 + 연합 + 실연동 + 능동 | §3 | | 추가물 카탈로그 | 10 페이지 + 9개 횡단 레이어(명명 고정) | §4 | | 횡단 아키텍처 다이어그램 | FastAPI+SQLite+Ollama 위 automation/connectors/agents/rag/worker + event_bus | §5 | | 연합 시나리오 표 | PROJECT-README §5 6대 흐름 → 이벤트/엔드포인트 매핑 | §6 | | phase 7~15 로드맵 표 | 목표/산출물/의존성/주요 레이어/규모 + 의존 그래프 | §7 | | 신규 테이블 개요 | 페이지별 테이블(원본 필드 이식) + autonomy/approval/automation 코어 | §8 | | event_bus 타입 목록 | 발행/구독 매트릭스 | §9 | | 가정/결정 | mock-first·모델 비종속·단일→멀티유저 + 조정 포인트 | §10 | | 비기능 상향선 | 성능/접근성/관측성 목표치 | §11 | | 테스팅 계약 | 실행 명령·케이스·수동 QA·통과 기준 | §13 | | 문서 세트 사용법 | 읽는 순서 + MVP 관계 | §15 | --- ## 3. 포스트-MVP 비전 — 3페이지 → 13페이지 + 연합 + 실연동 + 능동 MVP는 **"적으면 분류된다"**(인박스→작업/일정/아이디어)와 **"작업이 위험을 알린다"**(리스크 레이더)를 증명했습니다. 포스트-MVP는 같은 철학을 **세 축**으로 확장합니다. ### 3.1 13페이지 완성 — "Life OS"의 표면 `shell.jsx`의 `MAIN` 13항목이 전부 *실제 페이지*가 됩니다. MVP에서 `/(placeholder)` "준비 중"이던 10개가 모두 동작합니다. | MVP(3) | 포스트-MVP에서 추가되는 10 | |---|---| | 작업·인박스·대시보드 | 결재함 · 자동화 · 여정 · 일정 · 메일 · 알림 · 리서치 · 여행 · 라이프 · 하루 마감 | ### 3.2 연합(federation) — "끊김 없는 하나의 흐름" MVP의 연합은 `인박스 capture→confirm→작업 등장` 한 줄기였습니다. 포스트-MVP는 **내부 이벤트 버스(`event_bus`)** 로 *모든* 페이지를 잇습니다(§6, §9). 예: `meeting.ended → action items → task.created`, `mail.received → extract → task/event`, `automation.matched → approval enqueue`, `approval.executed → wrap 집계`. ### 3.3 실연동(real integration) — "가정이 아니라 데이터" MVP는 시드 목업입니다. 포스트-MVP는 **커넥터 추상화**(`backend/app/connectors/`)로 mail/calendar/chat/finance/health/knowledge 도메인을 추상화하고, phase 13에서 `CONNECTOR_=mock|real` 토글로 **같은 인터페이스에 실제 제공자**(Gmail/Workspace/HEY, Google Calendar, Apple Health, 금융 아그리게이터, Notion/Readwise)를 끼웁니다. 페이지는 phase 7~12에서 **mock-first**로 완성됩니다. ### 3.4 능동(proactive) — "할까요?가 아니라 이미 해뒀어요" MVP의 분류는 *요청-응답*이었습니다. 포스트-MVP는 **백그라운드 스케줄러(`backend/app/worker/`)** 가 사용자가 묻기 전에 움직입니다: 자동화 평가·다이제스트/브리핑 생성·반복 패턴 탐지·심부름 에이전트 실행. 결과는 **결재함**에 쌓여 *읽고 탭 한 번*(승인/되돌리기)으로 끝납니다. > 비전의 정수는 `approve-data.js` 주석 그대로입니다: *"아리는 '할까요?'라고 묻지 않고 미리 해둔다. risk: low → 자율성 '혼합' 이상에서 자동 실행(되돌리기 가능), risk: high → 보내기/결제/타인에게 전달 등은 승인 대기."* --- ## 4. 무엇이 추가되나 — 10개 페이지 + 횡단 레이어 ### 4.1 10개 페이지 (담당 phase 문서) | # | 라우트 | 라벨 | 원본 HTML / data | 핵심 | phase | |---|---|---|---|---|---| | 1 | `/approvals` | 결재함 | `결재함.html` / `approve-data.js` | 승인 큐(low=되돌리기, high=확인 실행), 자율성 설정 | phase-7 | | 2 | `/automation` | 자동화 | `자동화.html` / `auto-data.js` | 자연어 한 문장→규칙, 아리 제안, 실행 기록 | phase-7 | | 3 | `/calendar` | 일정 | `일정.html` / `cal-data.js` | 주/월/일 캘린더 + 회의 도우미(done/live/upcoming/1:1) | phase-8 | | 4 | `/mail` | 메일 | `메일.html` / `mail-data.js` | 3계정 통합 + AI 요약·작업/일정 추출·회신 초안 | phase-9 | | 5 | `/notifications` | 알림 | `알림.html` / `notify-data.js` | 트리아지(지금/나중에/아리가 처리) + 집중 보호 + 발신자 규칙 | phase-9 | | 6 | `/research` | 리서치 | `리서치.html` / `research-data.js` | 멀티소스 종합 리포트 · 지식 Q&A · 시각화/예측 | phase-10 | | 7 | `/trip` | 여행 | `여행.html` / `trip-data.js` | 출장 개요·이동·체크리스트·경비 + AI 여행 플래너 | phase-10 | | 8 | `/life` | 라이프 | `라이프.html` / `life-data.js` | 건강·금융·지식(커넥터) | phase-11 | | 9 | `/journey` | 여정 | `여정.html` / `journey-clean-data.js` | 4단계 흐름 + 협업 맵(베지어 링크) | phase-12 | | 10 | `/wrap` | 하루 마감 | `하루 마감.html` / `wrap-data.js` | 이브닝 브리핑(집계, 풀스크린·상단메뉴 없음) | phase-12 | > 라우트 슬러그는 영문 키(`approvals`/`automation`/`calendar`/`mail`/`notifications`/`research`/`trip`/`life`/`journey`/`wrap`)를 사용합니다. 상단 내비 `MAIN`의 id(`appr/auto/cal/mail/noti/research/trip/life/journey/wrap`)는 그대로 active 판정에 씁니다. `하루 마감`은 풀스크린(상단 메뉴 없음, `wrap-data.js` 컨셉) — 셸을 *적용하지 않는* 유일한 페이지. ### 4.2 9개 횡단 레이어 (명명 **고정** — 전 문서가 동일 참조) | 레이어 | 디렉터리 | 역할 | 도입 phase | |---|---|---|---| | 자동화 엔진 | `backend/app/automation/` | `rule` 모델, `event_bus`, `evaluator`(이벤트→규칙 매칭→동작/승인 enqueue), `nl_parser`(자연어→규칙, LLM provider), `suggester`(반복 패턴→규칙 제안) | phase-7 | | 승인 큐 | (모델 `approval`/`autonomy_setting`/`approval_log` + `/api/approvals`) | low+mixed이상=자동 실행(되돌리기), high=승인 대기. activity log | phase-7 | | 커넥터 추상화 | `backend/app/connectors/` | 도메인 base 인터페이스 + `MockConnector`(시드) + `RealConnector`(phase-13). 도메인: mail/calendar/chat/finance/health/knowledge | phase-8~11(mock), phase-13(real) | | 에이전트 오케스트레이션 | `backend/app/agents/` | LLM provider 위 멀티스텝 루프(plan→act(tool)→observe→reflect). 툴: web_search/rag_query/http_fetch/calendar_write/task_create/form_fill(stub) | phase-10 | | RAG/지식베이스 | `backend/app/rag/` | ingest(pdf/web/note)→chunk→embed(Ollama embeddings 추상화)→vector store(SQLite + sqlite-vec 또는 코사인) | phase-10 | | 멀티모달 캡처 | (`STTProvider`·`VisionProvider` 추상화, LLM Provider 패턴) | 음성→텍스트, 이미지→캡션/OCR. 인박스 voice/image 실구현 | phase-14 | | 연합 이벤트 모델 | (`event_bus` 이벤트 타입) | capture.classified, task.created, meeting.ended, mail.received, automation.matched, approval.executed, notification.triaged … | phase-7~12 누적 | | 능동 레이어/스케줄러 | `backend/app/worker/` | APScheduler류 백그라운드. 자동화 평가·다이제스트/브리핑·패턴 탐지·심부름 에이전트. 프로토타입은 수동 트리거 엔드포인트도 제공 | phase-14 | | 인증/멀티유저 | (세션 인증 + per-user 스코프) | MVP는 단일 데모 사용자(지우). per-user 데이터 스코프 도입 | phase-15 | --- ## 5. 횡단 아키텍처 다이어그램 기존 `브라우저 ↔ FastAPI ↔ SQLite ↔ Ollama`(MVP, `overview.md` §6) 위에 **자율성 레이어**와 **event_bus**가 얹힙니다. 회색 박스는 MVP 상속, 굵은 박스는 포스트-MVP 신규. ``` ┌──────────────────────────────────────────────────────────────────────────────────┐ │ 브라우저 · Next.js (App Router, React, TS) · Topbar(MAIN 13 전부 라이브) │ │ /dashboard /inbox /tasks ←MVP │ │ /approvals /automation /calendar /mail /notifications │ │ /research /trip /life /journey /wrap ←포스트-MVP (mock-first → real) │ │ │ lib/api.ts (/api) · lib/types.ts (schemas.py 1:1) · lib/hooks/ │ └────────┼───────────────────────────────────────────────────────────────────────────┘ │ HTTP/JSON (prefix /api) ▼ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ FastAPI · app/main.py (CORS, include_router(prefix="/api", tags=...)) │ │ ┌──────────────────────────── routers/ (MVP) ───────────────────────────────┐ │ │ │ tree · tasks · inbox · dashboard · people · llm │ │ │ ├──────────────────────────── routers/ (포스트-MVP) ─────────────────────────┤ │ │ │ approvals · automation · calendar · meetings · mail · notifications │ │ │ │ research · trip · life · journey · wrap · connectors · agents · worker │ │ │ └────────────────────────────────────┬──────────────────────────────────────┘ │ │ │ │ │ ┌────────────────────────────── 횡단 자율성 레이어 (신규) ─────────────────────┐ │ │ │ │ │ │ │ ┌───────────────────────── event_bus ─────────────────────────────┐ │ │ │ │ │ publish/subscribe: capture.classified · task.created · │ │ │ │ │ │ meeting.ended · mail.received · automation.matched · │ │ │ │ │ │ approval.enqueued · approval.executed · notification.triaged ... │ │ │ │ │ └───────┬─────────────┬─────────────┬───────────────┬──────────────┘ │ │ │ │ ▼ ▼ ▼ ▼ │ │ │ │ ┌─────────────┐ ┌────────────┐ ┌───────────┐ ┌──────────────────────┐ │ │ │ │ │ automation/ │ │ agents/ │ │ rag/ │ │ worker/ (스케줄러) │ │ │ │ │ │ rule │ │ plan→act→ │ │ ingest→ │ │ APScheduler류: │ │ │ │ │ │ evaluator │ │ observe→ │ │ chunk→ │ │ 자동화 평가·다이제스트│ │ │ │ │ │ nl_parser │ │ reflect │ │ embed→ │ │ ·패턴 탐지·심부름 │ │ │ │ │ │ suggester │ │ (tools) │ │ vec store │ │ (+수동 트리거 EP) │ │ │ │ │ └──────┬──────┘ └─────┬──────┘ └─────┬─────┘ └──────────┬───────────┘ │ │ │ │ │ │ │ │ │ │ │ │ approval 큐 tool calls: embed/query 주기 실행 │ │ │ │ (low 자동/ web_search, (knowledge) │ │ │ │ high 대기) rag_query, │ │ │ │ http_fetch, │ │ │ │ calendar_write, │ │ │ │ task_create, │ │ │ │ form_fill(stub) │ │ │ └─────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌──────────────── connectors/ (도메인 추상화) ───────────────┐ │ │ │ base IF + MockConnector(시드) ──phase13──▶ RealConnector │ │ │ │ mail · calendar · chat · finance · health · knowledge │ │ │ │ env: CONNECTOR_=mock|real (기본 mock) │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ models.py (SQLModel) · schemas.py (Pydantic) · seed.py (run_seed) │ │ llm/ provider.py(LLMProvider) · ollama.py · heuristic.py + STTProvider/Vision │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ SQLite ari.db│ │ Ollama (LLM) │ │ Ollama embed │ │ 외부 제공자(real)│ │ │ │ +sqlite-vec? │ │ OLLAMA_MODEL 주입│ │ (embeddings) │ │ Gmail/Cal/Health │ │ │ │ (vector) │ │ 폴백:heuristic │ │ 폴백:코사인 │ │ 금융/Notion ... │ │ │ └──────────────┘ └──────────────────┘ └──────────────┘ └──────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────────┘ ``` **설계 원칙(상속/고정)**: - `event_bus`는 **내부 인메모리 pub/sub**(프로토타입). 핸들러가 동기 또는 worker 큐로 동작. 영속 이벤트가 필요하면 `automation_run_log`/`approval_log`에 기록. - **event_bus 정본(단일 고정)**: 정본 모듈은 `backend/app/automation/event_bus.py` 하나뿐이다. `class EventBus { publish(event_type: str, payload: dict); subscribe(event_type: str, handler) }` + 전역 인스턴스 `bus = EventBus()`. 모듈 레벨 편의 export 로 `publish = bus.publish`, `subscribe = bus.subscribe`, `emit = bus.publish`(`emit` 은 `publish` 별칭)을 함께 제공한다. 따라서 `from app.automation.event_bus import bus`(`bus.publish('x', {...})`)와 `from app.automation.event_bus import publish`(`publish('x', {...})`, `emit` 동일) 둘 다 정상이다. `backend/app/events.py`·`backend/app/event_bus.py` 같은 다른 경로/심볼은 정본이 아니며 사용 금지. - 모든 신규 라우터는 **내부 prefix 없음** → `main.py`에서 `include_router(prefix="/api", tags=...)`로만 `/api` 부착(phase-2 규약). - 모든 모델/임베딩/STT/Vision은 **env 주입 + 폴백**(모델 비종속). Ollama 미가용·오프라인·CI에서도 `heuristic`/`scripted`/`코사인` 폴백으로 데모 결정성 보장. --- ## 6. 연합(federation) 시나리오 PROJECT-README §5의 6대 흐름을 포스트-MVP의 **이벤트/엔드포인트/도착지**로 매핑합니다. (`→`는 event_bus 발행, 굵은 한국어는 원본 UI 문구.) | # | 흐름 | 트리거 → 처리 → 도착지 | 핵심 이벤트 | 관련 phase | |---|---|---|---|---| | F1 | 캡처 → 분류 → 실행 | 인박스 한 줄 → `POST /api/inbox/capture`(동기 분류) → confirm → 작업/일정/아이디어 | `capture.classified` → `task.created`/`calendar.updated` | MVP + phase-8 | | F2 | 메일 → 작업/일정 | 메일 본문 `ai.tasks[]`/`ai.events[]` 추출 → "작업으로"/"캘린더로" → 작업 보드·캘린더 등장 | `mail.received` → `task.created`/`calendar.updated` | phase-9 | | F3 | 회의 → 작업 | 끝난 회의(`meets.e3.phase="done"`) 액션 아이템 추출 → **"작업으로" 한 번에 전송** → 담당자 작업 | `meeting.ended` → `task.created` | phase-8 | | F4 | 일정 ↔ 작업 ↔ 집중 모드 | 캘린더 빈 블록 읽어 `focusBlocks` 자동 배치 → 마감/쏠림은 리스크 레이더가 감시 | `calendar.updated` → `calendar.focus_scheduled` | phase-8 (+ MVP 리스크) | | F5 | 위임 루프 | 일정 과부하 감지 → **"민서님께 '데이터 전처리' 위임 요청"**(결재함 high) → 1:1 도우미가 위임 과제 진행 추적(`meets.e7.promises`/`signals`) | `proactive.detected` → `approval.enqueued`(high) → `approval.executed` | phase-7 + phase-8 | | F6 | 자동 처리 → 결재함 → 하루 마감 | 밤사이 자동 처리(`autoCountNight: 7`) → 결재함 승인/되돌리기 → 하루 마감 **"아리 자동 처리 12건 · 47분 아낌"** 합산 | `automation.matched` → `approval.enqueued` → `approval.executed` → `wrap.reflected` | phase-7 + phase-12 | | F7 | 알림 트리아지 → 자동화 제안 | 알림 분류(`buckets.now/later/held`) → 반복 패턴(`suggests`) → 자동화 규칙 제안(레일 dot) | `notification.triaged` → `automation.suggested` | phase-9 + phase-7 | | F8 | 공통 인물·프로젝트 | 지우·현우·민서·재호·수아 + 온보딩/분기 리포트가 전 페이지에 일관 등장(`person`/`project` 공유) | (정적 일관성) | 전 phase | **대표 federation 데이터 경로 — F3 회의→작업 (cal-data.js `meets.e3`)** ``` 회의 끝남(done) — actions: [{ text:"온보딩 와이어프레임 피드백 정리", who:"나", when:"오늘", added:true }, { text:"푸시 알림 QA 결과 공유", who:"수아", when:"내일", added:true }, { text:"매출 데이터 전달", who:"현우", when:"오늘", added:false }] │ POST /api/meetings/{id}/actions/to-tasks (added=false 항목을 task로 전송) ▼ event_bus.publish("meeting.ended", { event_id:"e3", actions:[...] }) ▼ evaluator/handler task 생성 (assignee=현우, title="매출 데이터 전달", project="경영 전략 · 분기 리포트") ▼ GET /api/tasks 에 즉시 등장 (작업 보드, phase-3 패턴) · 여정/하루마감 집계 갱신 ``` **대표 federation 데이터 경로 — F6 자동 처리→결재함→하루 마감** ``` worker(스케줄러) 야간 실행 → automation.evaluator 가 rule 매칭 ▼ approval enqueue: risk=low → 자동 실행 + undo_label; risk=high → status=pending approve-data.js 시드 예: a1 "치과 예약을 16:00로 옮겼어요"(low, undoLabel:"원래 시간으로") a4 "현우님께 회신 초안이 준비됐어요"(high, cta:"보내기", alt:"수정") ▼ 사용자: POST /api/approvals/{id}/approve | /undo event_bus.publish("approval.executed", { id:"a4", saved_minutes:... }) ▼ wrap.aggregator 하루 마감 stats: { n:"12", label:"아리 자동 처리", sub:"47분 아낌" } (wrap-data.js) ``` --- ## 7. phase 7~15 로드맵 & 의존 그래프 ### 7.1 로드맵 표 | Phase | 문서 | 목표(끝나면 동작) | 핵심 산출물 | 의존성 | 주요 신규 레이어 | 규모 | |---|---|---|---|---|---|---| | 7 | `phase-7-approvals-automation.md` | **자율성 코어**. 결재함(승인/되돌리기, 자율성 설정) + 자동화 엔진(자연어→규칙, 아리 제안, 실행 기록). low 자동/high 대기. | `approval`/`autonomy_setting`/`approval_log`, `automation_rule`/`automation_suggestion`/`automation_run_log`/`automation_stats`, `automation/`(event_bus·evaluator·nl_parser·suggester), `/api/approvals`·`/api/automation` | MVP(0~6) | automation, event_bus, 승인 큐 | L | | 8 | `phase-8-calendar-meetings.md` | 일정(주/월/일) + 회의 도우미(done/live/upcoming/1:1). 액션→작업 연합, 집중 블록 자동 배치. | `calendar`/`event`/`focus_block`/`meeting`, `/api/calendar`·`/api/meetings`, calendar 커넥터(mock) | 7 | connectors(calendar mock), event_bus | L | | 9 | `phase-9-mail-notifications.md` | 3계정 메일 + AI 요약/작업·일정 추출/회신 초안. 알림 트리아지(지금/나중에/아리가 처리) + 집중 보호 + 발신자 규칙. | `mail_account`/`email`/`mail_folder`/`sent`/`draft`, `notification`/`notification_guard`/`digest`/`sender_rule`/`notify_stats`, `/api/mail`·`/api/notifications`, mail/chat 커넥터(mock) | 7,8 | connectors(mail/chat mock) | L | | 10 | `phase-10-research-travel.md` | 리서치(멀티소스 종합·지식 Q&A·시각화/예측) + 여행(출장·AI 플래너). 에이전트 오케스트레이션 + RAG + 웹검색. | `research_collection`/`research_source`/`research_report`/`knowledge_qa`/`research_chart`, `trip`/`trip_route`/`trip_stay`/`trip_prep`/`trip_day`/`trip_checklist`/`trip_expense`/`saved_trip`/`trip_plan`, `agents/`, `rag/`, `/api/research`·`/api/trip`·`/api/agents` | 7,9 | agents, rag, web_search | L | | 11 | `phase-11-life-care.md` | 라이프 케어(건강·금융·지식). 커넥터(health/finance/knowledge mock). knowledge_item은 리서치와 공유. | `connector_source`, `health`, `finance`, `knowledge_item`, `/api/life`, health/finance/knowledge 커넥터(mock) | 7,10 | connectors(health/finance/knowledge mock) | M | | 12 | `phase-12-daily-narrative.md` | 여정(4단계 + 협업 맵) + 하루 마감(이브닝 브리핑). 전 페이지 집계 narrative. | `journey_link`(최소), wrap 집계 서비스, `/api/journey`·`/api/wrap` | 7,8,9,10,11 | event_bus(집계 구독) | M | | 13 | `phase-13-integrations.md` | 외부 연동 & 커넥터(mock→real). 같은 인터페이스로 실제 제공자 교체. | `RealConnector`(Gmail/Workspace/HEY, Google Calendar, Apple Health, 금융 아그리게이터, Notion/Readwise), OAuth/토큰 저장, `CONNECTOR_=real` | 8~11 | connectors(real) | L | | 14 | `phase-14-proactive-agent.md` | 능동형 에이전트 + 멀티모달 캡처. 심부름 대행·능동 알림·음성/이미지. | `worker/`(APScheduler류 + 수동 트리거 EP), `STTProvider`/`VisionProvider`, 인박스 voice/image 실구현, 능동 다이제스트/브리핑 | 7~12 | worker, 멀티모달 | L | | 15 | `phase-15-production.md` | 프로덕션 하드닝. 인증/멀티유저/배포/관측성/성능/보안. | 세션 인증 + per-user 스코프, 배포(Docker/compose), 로깅/메트릭/트레이싱, 성능·보안 점검 | 7~14 | 인증/멀티유저 | L | > 규모 표기: M(보통)/L(큼) — 상대 추정. phase 7~10·13~15는 L, 11~12는 M. ### 7.2 빌드 순서 & 의존 그래프 ``` 빌드 순서: 7 → 8 → 9 → 10 → 11 → 12 → 13 → 14 → 15 (7은 MVP 직후 최우선 — 철학 실현, MVP에만 의존) 의존 그래프 (→ = 선행): MVP(0~6) ──▶ 7(결재함·자동화) ──┬─▶ 8(일정·회의) ──┬─▶ 9(메일·알림) ──┐ │ │ │ │ └──────────────────┤ │ ▼ └────────────────────────────────▶ 10(리서치·여행) │ 11(라이프) ◀──────────────────────────────────────────────────────┘ │ ▼ 12(여정·하루마감) ◀── (7,8,9,10,11 집계) │ ▼ 13(실연동 mock→real) ── 8~11 의 커넥터 인터페이스에 끼움 │ ▼ 14(능동·멀티모달) ── 7~12 위에 worker/STT/Vision │ ▼ 15(프로덕션·인증/멀티유저) ``` - **페이지는 mock-first**: phase 7~12는 커넥터의 `MockConnector`(시드)로 완성. phase 13이 동일 인터페이스에 `RealConnector`를 끼워 *페이지 재작성 없이* 실연동 전환. - **7이 최우선**: 결재함·자동화는 철학("이미 해뒀어요")의 실현이며 MVP에만 의존 → 가장 먼저. - **12는 마지막 집계**: 여정·하루 마감은 작업·일정·결재·자동화·메일 등에서 계산되므로 페이지 phase 이후. --- ## 8. 신규 데이터 테이블 개요 (MVP 모델 확장) > 규약(상속): 모든 PK는 **TEXT(str)**. `tone` enum 집합 `blue|violet|coral|green|amber|ink|faint`(+ 원본 일부 데이터에 `muted` 존재 — 알림/수면 stages — 는 시드 문자열 그대로 저장하되 표시 시 `--faint`로 매핑). 날짜/문구/금액 등 한국어 UI는 **원본 *-data.js 문구를 그대로** 사용. 신규 테이블/필드는 각 phase 문서가 원본에서 정밀 이식하며, 아래는 **개요**입니다. ### 8.1 횡단 코어 (phase-7) — autonomy / approval / automation ```python # backend/app/models.py (발췌 — phase-7 가 확정) class Approval(SQLModel, table=True): # approve-data.js: items[] id: str = Field(primary_key=True) # 예 "a1".."a6" icon: str # cal|mail|users|wallet (Icon P 맵 키) tone: str # coral|blue|violet|green|amber risk: str # "low" | "high" status: str = "pending" # pending|approved|undone|executed source: str = "automation" # 허용값: automation|agent|mail|calendar|finance|inbox|life|system time: str # "07:42" | "보내기 대기" | "확인 필요" title: str # "치과 예약을 16:00로 옮겼어요" detail: str | None = None cta: str | None = None # high: "보내기" | "전달" | "일시정지" alt: str | None = None # high: "수정" | "내가 할게" | "유지" undo_label: str | None = None # low: "원래 시간으로" | "되돌리기" | "블록 해제" created_at: datetime class AutonomySetting(SQLModel, table=True): id: str = Field(default="default", primary_key=True) # PK=TEXT(str), 단일 row id="default" level: str = "mixed" # approval_first | mixed | full_auto # AutonomySetting 정본: PK 는 TEXT(str), 단일 row id="default". # 조회 session.get(AutonomySetting, "default"); 시드 AutonomySetting(id="default", level=...). # (briefing/automation_stats/notify_stats/guard 등 기존 단일 row 집계 테이블의 int id=1 은 MVP 상속 예외로 유지.) class ApprovalLog(SQLModel, table=True): # approve-data.js: log[] id: str = Field(primary_key=True) time: str # "08:55" | "어제 23:10" text: str # "스탠드업 직전 — 어제 진행 요약 노트 생성" created_at: datetime class AutomationRule(SQLModel, table=True): # auto-data.js: rules[] id: str = Field(primary_key=True) # "r1".."r7" on: bool = True # enabled cat: str # mail|focus|cal|life name: str # "수아님 메일은 바로" trigger: str # "수아님 발신 메일" cond: str | None = None # "긴급 표시가 아니면" action: str # "즉시 알림 + 3줄 요약" last: str | None = None # "오늘 09:12" | "어제 18:30" runs: int = 0 class AutomationSuggestion(SQLModel, table=True): # auto-data.js: suggests[] id: str = Field(primary_key=True) # 시드 id 규칙: asug-s1, asug-s2 (원본 s1/s2 에 asug- prefix) pattern: str # "월요일 아침마다 주간 리포트 초안을 ..." offer_name: str; offer_cat: str offer_trigger: str; offer_cond: str | None; offer_action: str class AutomationRunLog(SQLModel, table=True): # auto-data.js: log[] id: str = Field(primary_key=True) time: str; rule: str; text: str # "12:48" / "영수증 자동 정리" / "점심 결제 13,500원 → 식비로 분류" ``` > `automation_stats`(`auto-data.js: stats { active:7, runsWeek:31, saved:"1시간 40분" }`)와 결재함 헤더(`savedToday:"47분"`, `autoCountNight:7`)는 **집계 응답**(`GET /api/automation/stats`, `GET /api/approvals`)으로 계산 — 별도 테이블 대신 카운트/뷰 권장. ### 8.2 페이지별 신규 테이블 (개요 — 원본 *-data.js 기준) | 페이지 | 테이블 (개요) | 원본 필드(인용) | 원본 | |---|---|---|---| | 결재함 | `approval`, `autonomy_setting`(PK str, 단일 row id="default"), `approval_log` | `risk`,`status`,`source`(automation\|agent\|mail\|calendar\|finance\|inbox\|life\|system),`cta`/`alt`/`undo_label`,`savedToday:"47분"`,`autoCountNight:7` | approve-data.js | | 자동화 | `automation_rule`, `automation_suggestion`, `automation_run_log`, (`automation_stats`=뷰) | `trigger`/`cond`/`action`/`cat`/`on`/`last`/`runs`, `pattern`/`offer` | auto-data.js | | 일정 | `calendar`(=cals), `event`, `focus_block`, `meeting` | `day`/`start`/`end`/`title`/`cal`/`loc`/`people`/`note`/`soon`/`actions`; meeting `phase: done|live|upcoming`, `summary`/`decisions`/`actions`/`agenda`/`lastMeeting`/`lastActions`/`insights`/`signals`/`talkingPoints`/`oneOnOne` | cal-data.js (today=8) | | 메일 | `mail_account`(3), `email`, `mail_folder`, `sent`, `draft` | `account`/`from`/`to`/`subject`/`body`/`labels`/`read`/`starred`/`attachments` + `ai{summary,priority,category,tasks[],events[],replies[],file}` | mail-data.js | | 알림 | `notification`, `notification_guard`, `digest`, `sender_rule`, (`notify_stats`=뷰) | `bucket: now|later|held`, `src`/`app`/`title`/`sum`/`time`/`why`/`tone`/`act`; guard `on`/`until`/`held`/`quiet` | notify-data.js | | 리서치 | `research_collection`, `research_source`, `research_report`, `knowledge_qa`, `research_chart` | source `kind: pdf|web|note`, `learned`; report `synthesis`/`cross[]`/`counts`/`note`; qa `q`/`a`/`refs`; chart `bars`(+`forecast`)/`insight`/`caution` | research-data.js | | 여행 | `trip`, `trip_route`(out/back), `trip_stay`, `trip_prep`, `trip_day`(items), `trip_checklist`, `trip_expense`, `saved_trip`(spark), `trip_plan` | `dday:"D-4"`, route `mode`/`seat`, prep `state: done\|doing`, expense `budget`/`planned`/`rows[state: paid\|hold\|est]`, planner `results[transport/stay/days/budget/checklist/sources]` | trip-data.js | | 라이프 | `connector_source`, `health`, `finance`, `knowledge_item` | source `on`/`last`; health `rings`/`vitals`/`sleep`/`coach`/`habits`; finance `budget`/`cats`/`subs`/`coach`/`insights`; knowledge_item `type: article\|note\|idea\|highlight` + `ai` | life-data.js | | 여정 | (집계 뷰 중심) `journey_link`(최소, 필요시) | `stages`(4) + `cards` + `links`(베지어, from/to/c/dash) + `rows` | journey-clean-data.js | | 하루 마감 | (집계 중심, 상태 저장만) | `stats`/`highlights`/`rollover`/`tomorrow`/`prep`/`sleepNote`; 회고 한 줄·수면 모드는 상태 저장 | wrap-data.js | > `knowledge_item`은 **리서치(research)와 라이프(life)가 공유** 가능(life-data.js `knowledge.items[]`의 `type: article|note|idea|highlight` ≈ research 컬렉션 소스). phase-11이 정본 테이블을 두고 phase-10이 참조. > 라우터 등록(상속): 신규 라우터도 내부 prefix 없이 정의하고 `main.py`에서 `app.include_router(approvals.router, prefix="/api", tags=["approvals"])` 형태로만 `/api` 부착. 시드는 `run_seed(session=None, reset=True)` 안에서 `_seed_approvals(session)`·`_seed_automation(session)` 등 **내부 헬퍼**로 호출(공개 진입점 아님 — phase-2 `_seed_dashboard` 패턴). ### 8.3 신규 환경변수 (상속 + 추가) 상속(overview.md): `DATABASE_URL`, `OLLAMA_HOST`, `OLLAMA_MODEL`, `LLM_PROVIDER(auto|ollama|heuristic)`, `FRONTEND_ORIGIN`, `NEXT_PUBLIC_API_BASE`. 추가(포스트-MVP, 모두 폴백 기본값 보유): | 변수 | 기본값 | 용도 | 도입 | |---|---|---|---| | `CONNECTOR_MAIL` | `mock` | 메일 커넥터 mock\|real | 9/13 | | `CONNECTOR_CALENDAR` | `mock` | 캘린더 커넥터 | 8/13 | | `CONNECTOR_CHAT` | `mock` | 메신저 커넥터 | 9/13 | | `CONNECTOR_FINANCE` | `mock` | 금융 아그리게이터 | 11/13 | | `CONNECTOR_HEALTH` | `mock` | Apple Health/Watch | 11/13 | | `CONNECTOR_KNOWLEDGE` | `mock` | Notion/Readwise/웹클리퍼 | 11/13 | | `EMBED_PROVIDER` | `ollama` | RAG 임베딩 ollama\|heuristic | 10 | | `EMBED_MODEL` | (주입) | 임베딩 모델명(기본 예시만, 비종속) — `EMBED_PROVIDER` 와 반드시 함께 사용 | 10 | | `WEB_SEARCH_PROVIDER` | `mock` | 웹검색 mock\|real … | 10 | | `AGENT_PROVIDER` | (`LLM_PROVIDER` 따름) | 에이전트 루프 제공자(기본은 `LLM_PROVIDER` 상속) | 10 | | `STT_PROVIDER` / `STT_MODEL` | `auto` / (주입) | 음성→텍스트(whisper류) | 14 | | `VISION_PROVIDER` / `VISION_MODEL` | `auto` / (주입) | 이미지→캡션/OCR | 14 | | `WORKER_ENABLED` | `false` | 스케줄러 on/off(프로토타입은 수동 트리거 EP) | 14 | | `AUTH_ENABLED` | `false` | 세션 인증(단일 데모 사용자 기본) | 15 | --- ## 9. event_bus 이벤트 타입 & 연합 이벤트(발행/구독) ### 9.1 이벤트 타입 목록 (명명 고정 — 정본) > 이벤트 이름은 아래가 정본이며 **이 이름만 사용**한다(발행/구독 짝 일치). 금지/교정: `approval.created`→`approval.enqueued`, `automation.suggestion_candidate`→`automation.suggested`. 발행은 정본 모듈 `backend/app/automation/event_bus.py` 의 `publish(event_type, payload)`(별칭 `emit`) 로만 한다. | 이벤트 타입 | 페이로드(개요) | 첫 발행 phase | |---|---|---| | `capture.classified` | `{ item_id, type, sphere, project_id?, reason }` | MVP/7 | | `task.created` | `{ task_id, assignee_id, project_id, source }` | MVP/8 | | `meeting.ended` | `{ event_id, actions:[{text,who,when,added}] }` | 8 | | `calendar.updated` | `{ event_id, day, start, end, cal, source }` | 8 | | `calendar.focus_scheduled` | `{ id, day, start, end, type: light\|deep }` | 8 | | `mail.received` | `{ email_id, account, ai:{tasks,events,replies} }` | 9 | | `notification.triaged` | `{ id, bucket: now\|later\|held, why }` | 9 | | `automation.matched` | `{ rule_id, event, action }` (규칙 매칭) | 7 | | `automation.suggested` | `{ suggestion_id, pattern, offer }` (제안; `automation.suggestion_candidate` 금지) | 7/9 | | `approval.enqueued` | `{ id, risk, source }` (결재 enqueue; `approval.created` 금지) | 7 | | `approval.executed` | `{ id, risk, saved_minutes? }` (실행) | 7 | | `approval.undone` | `{ id, risk }` (되돌리기) | 7 | | `research.completed` | `{ collection_id, report_id }` | 10 | | `knowledge.ingested` | `{ item_id, kind: pdf\|web\|note }` | 10/11 | | `trip.plan.saved` | `{ plan_id, query }` | 10 | | `price.target.hit` | `{ target_id, symbol, price }` | 11 | | `errand.started` | `{ errand_id, kind }` | 14 | | `errand.updated` | `{ errand_id, progress }` | 14 | | `errand.completed` | `{ errand_id, result }` | 14 | | `proactive.detected` | `{ pattern_id, kind, suggest }` | 14 | | `weekly.reviewed` | `{ week, stats }` | 12 | | `wrap.reflected` | `{ date, note }` | 12 | | `finance.transaction` | `{ txn_id, amount, category }` | 11 | | `health.sample` | `{ sample_id, metric, value }` | 11 | > 체인: `notification.triaged` → (phase-7 suggester 구독) → `automation.suggested`. phase-7 suggester 는 `notification.triaged` 구독 + 수동 scan 둘 다 지원하며 `automation.suggested` 를 발행한다. ### 9.2 발행/구독 매트릭스 (페이지/레이어별) | 발행자 → 이벤트 | 구독자(처리) | |---|---| | 인박스 `capture.classified` | 자동화 evaluator(규칙 매칭) · 대시보드 집계 | | 일정 `meeting.ended` | 작업(`task.created`) · 여정/하루 마감 집계 | | 일정 `calendar.updated` | worker → `calendar.focus_scheduled`(집중 블록 자동 배치) · 여정/하루 마감 집계 | | 메일 `mail.received` | 작업/일정(추출, `task.created`/`calendar.updated`) · 알림 트리아지 · suggester | | 알림 `notification.triaged` | suggester → `automation.suggested`(레일 dot) | | 자동화 `automation.matched` | 승인 큐(`approval.enqueued`) · 실행 기록 | | 승인 큐 `approval.enqueued` | low+mixed이상=자동 실행→`approval.executed` · high=대기(승인 시 `approval.executed`) | | 승인 큐 `approval.executed` / `approval.undone` | 하루 마감(`wrap.reflected`/주간 `weekly.reviewed`) · 결재함 로그 · 대시보드 `saved_today` | | 리서치/지식 `research.completed` / `knowledge.ingested` | 리서치 리포트 · RAG 인덱스 · 라이프 지식 | | 라이프 `finance.transaction` / `health.sample` / `price.target.hit` | 금융/건강 집계 · 결재함(목표 도달 제안) | | worker `proactive.detected` / `errand.started`/`errand.updated`/`errand.completed` | 결재함(능동 제안) · 알림(능동 브리핑) · 심부름 추적 | > 각 페이지 phase 문서는 자신이 **발행/구독하는 이벤트를 §연합 이벤트 섹션에 명시**합니다(스타일 가이드 ⑦ 필수). 본 문서의 매트릭스가 전 phase의 참조 기준입니다. --- ## 10. 가정/결정 (assumptions) — 사용자가 조정 가능한 지점 | # | 가정/결정 | 기본값 | 조정 포인트 | |---|---|---|---| | A1 | **외부 연동은 mock-first + 커넥터 추상화** | `CONNECTOR_=mock` | phase-13에서 도메인별 `real`로 토글. 실제 제공자(Gmail/Workspace/HEY, Google Calendar, Apple Health export, 금융 아그리게이터, Notion/Readwise)는 **목표 예시이며 교체 가능**. | | A2 | **에이전트/멀티모달/임베딩은 모델 비종속** | `*_PROVIDER`/`*_MODEL` env 주입(기본값은 §8.3 표 — `EMBED_PROVIDER=ollama`, `WEB_SEARCH_PROVIDER=mock`, `AGENT_PROVIDER`는 `LLM_PROVIDER` 상속, STT/Vision=`auto`) | tool-capable·STT·vision·embedding 모델은 env로 주입. 미가용 시 **scripted/heuristic/코사인 폴백**으로 데모 동작 보장(결정성). | | A3 | **단일 데모 사용자(지우) 유지** | `AUTH_ENABLED=false` | 인증/멀티유저는 phase-15에서 세션 인증 + per-user 데이터 스코프 도입. | | A4 | **능동 레이어는 프로토타입 수동 트리거 우선** | `WORKER_ENABLED=false` | phase-14에서 APScheduler류 백그라운드 활성. 프로토타입은 수동 트리거 엔드포인트(`POST /api/worker/run/{job}`) 제공. | | A5 | **벡터 스토어는 단순 우선** | SQLite + 코사인 | sqlite-vec 가용 시 전환(같은 `rag/` 인터페이스). | | A6 | **자율성 기본 레벨 = 혼합(mixed)** | `autonomy_setting.level="mixed"` | `approval_first`(전건 승인)·`full_auto`(저위험 자동). low+mixed이상=자동 실행(되돌리기), high=항상 승인 대기. | | A7 | **데이터는 전부 목업/시드** | 지우 6/7~6/13, 오늘=6/8 | 원본 *-data.js 값을 그대로 이식. 날짜/문구/금액 변경 금지(픽셀 충실). | > 모든 가정은 본 문서에 명시되어 **사용자가 조정 가능**합니다. 조정 시에는 이 문서를 먼저 갱신하고 영향 phase에 전파합니다(overview.md §19.2 작업 방식 상속). --- ## 11. 비기능 목표(성능/접근성/관측성)의 포스트-MVP 상향선 | 영역 | MVP 기준(상속) | 포스트-MVP 상향선 | |---|---|---| | **성능 — 동기 API** | `/api/*` 단건 응답 빠름 | 목록/집계 API p95 < 300ms(로컬 SQLite). 메일/알림 목록은 페이지네이션/지연 로드. | | **성능 — 에이전트/RAG** | 해당 없음 | 에이전트 멀티스텝·RAG ingest는 **비동기/스트리밍**(진행 단계 애니메이션, trip planner `research[]` 단계 표시). 폴백 scripted는 즉시. | | **성능 — 능동** | 해당 없음 | worker 잡은 백그라운드(메인 요청 비차단). 다이제스트 생성은 예약 시각(`digests`: 09:00/13:00/18:30) 기준. | | **접근성(a11y)** | axe 위반 0(serious↑), 키보드/포커스 | 동일 + 드로어(회의 도우미)·탭·레일 ARIA(원본 `aria-current="page"`/`aria-label` 상속), 라이브 영역(능동 알림 `aria-live`), 차트 대체 텍스트(리서치 `chart.insight`/`caution`를 텍스트로 제공). | | **접근성 — 한국어** | `word-break: keep-all`, `letter-spacing:-0.011em` | 전 페이지 상속. 긴 한국어 문구(메일 본문·회의 요약)도 어절 단위 줄바꿈. | | **관측성(observability)** | (MVP 최소) | 구조적 로깅(요청 id·event_bus 이벤트·자동화 매칭·approval 전이), 메트릭(자동화 runs/주, approval 처리율, 절약 시간), phase-15에서 트레이싱. | | **결정성(데모)** | heuristic 폴백 | 에이전트 scripted 파이프라인(trip planner 예시 2개 제주/도쿄 결과 고정, 자유 입력은 0번 폴백), RAG 코사인 폴백 — **오프라인/CI에서도 동일 결과**. | | **보안/프라이버시** | 로컬 처리(Ollama) | 커넥터 토큰 저장 암호화(phase-13), per-user 스코프(phase-15), high-risk 동작은 항상 사용자 승인. | --- ## 12. 상태 처리 & 엣지 케이스 (포스트-MVP 전역) overview.md §15 전역 원칙을 상속하며, 포스트-MVP 특화 케이스를 추가합니다. | 상태/케이스 | 전역 처리 | |---|---| | **로딩** | 글래스 스켈레톤(카드 형태 유지). 에이전트/플래너는 **단계별 진행 애니메이션**(trip `research[]`, 원본 단계 표시). | | **빈(empty)** | 결재함 빈: *"오늘은 아리가 처리한 게 없어요"* 류. 알림 빈 버킷: 버킷 라벨 유지 + placeholder. | | **에러** | `lib/api.ts` 비2xx throw → 카드 단위 에러 + 재시도. 셸/테마 유지. 커넥터 real 실패 시 mock 폴백 또는 "연결 안 됨"(life `Google Fit: "연결 안 됨"` 패턴). | | **오프라인/LLM 미가용** | 분류·에이전트·임베딩 폴백 동작, `model="heuristic"`/`"scripted"`/`"cosine"` 표기. UI는 "규칙 기반으로 처리했어요" 미세 힌트(선택). | | **커넥터 mock↔real 전환** | 같은 인터페이스 → 페이지 무변경. real 미인증 시 mock 시드로 graceful degrade. | | **승인 되돌리기(undo)** | low는 즉시 실행 후 `undo_label`로 되돌리기. `status: pending→approved→executed→undone` 전이를 `approval_log`에 기록. | | **자율성 레벨 변경** | `approval_first`로 낮추면 자동 실행 중단·전건 대기. `full_auto`로 올리면 low 자동(되돌리기만). 변경은 즉시 반영. | | **멀티모달 스텁→실구현** | MVP는 voice/image 스텁. phase-14에서 STT/Vision 실구현, 미가용 시 "텍스트로 적어주세요" 폴백. | | **HTML 시드(notes/coach/insight/summary)** | 신뢰된 시드(`` 등 포함, life `coach`·research `synthesis` 등). 사용자 입력 경로는 새니타이즈 후 렌더. | --- ## 13. 테스팅 & 검증 > 본 문서는 *지도*이므로 "검증" = **문서 정확성 + 각 phase 정합성 + 횡단 명명 일관성** 점검입니다. 동시에 포스트-MVP 전 phase가 공통으로 쓸 테스트 도구·실행 명령·통과 기준을 정의합니다(각 phase 문서가 재사용). ### 13.1 실행 명령 (포스트-MVP 공통 — overview.md §16.1 상속 + 추가) ```bash # 백엔드 (backend/) uv run pytest # 전건 uv run pytest -k "automation or approval" # phase-7 자율성 코어 uv run pytest -k "connector" # 커넥터 mock 인터페이스 uv run pytest -k "agent or rag" # 에이전트/RAG(폴백 결정성) uv run pytest -k "event_bus" # 연합 이벤트 발행/구독 uv run uvicorn app.main:app --reload # 개발 서버 (:8000) uv run alembic upgrade head # 신규 테이블 마이그레이션 uv run python -m app.seed # run_seed() — 지우 한 주 + 포스트-MVP 시드 curl -s localhost:8000/api/approvals | jq . # 결재함 응답 수동 확인 curl -s -X POST localhost:8000/api/worker/run/digest | jq . # 능동 수동 트리거(phase-14) # 프론트엔드 (frontend/) pnpm dev # Next dev (:3000, /api → :8000) pnpm test # Vitest + RTL (컴포넌트) pnpm playwright test # E2E (연합 흐름) pnpm playwright test --grep @a11y # axe 접근성 pnpm build && pnpm start # 프로덕션 빌드 검증 ``` ### 13.2 이 문서(post-mvp-overview)의 검증 케이스 | # | 검증 항목 | 통과 기준 | |---|---|---| | PM-1 | 10페이지 매핑 | §4.1 라우트/라벨/원본/phase가 `MAIN`(shell.jsx)·로드맵과 일치 | | PM-2 | 횡단 레이어 명명 | §4.2 디렉터리·모델명(automation/connectors/agents/rag/worker, approval/autonomy_setting/automation_rule …)이 CONTRACT 고정 명명과 1:1 | | PM-3 | 시드 값 인용 | §8 `savedToday:"47분"`·`autoCountNight:7`·`stats{active:7,runsWeek:31,saved:"1시간 40분"}`·`risk low/high`·`cta/alt/undo_label`이 원본 *-data.js와 일치 | | PM-4 | event_bus 타입 | §9.1 이벤트 타입이 CONTRACT 예시(capture.classified/task.created/meeting.ended/mail.received/automation.matched/approval.executed/notification.triaged)를 빠짐없이 포함 | | PM-5 | 로드맵·의존 | §7 빌드 순서 `7→8→9→10→11→12→13→14→15`, 7 최우선, 페이지 mock-first/13 real 전환 명시 | | PM-6 | 연합 시나리오 | §6이 PROJECT-README §5 6대 흐름(캡처→분류→실행/메일·회의→작업/일정↔작업↔집중/위임 루프/자동처리→결재함→하루마감/공통 인물·프로젝트)을 모두 포함 | | PM-7 | 가정 명시 | §10 A1~A7이 mock-first·모델 비종속·단일→멀티유저·조정 포인트를 명시 | | PM-8 | 환경변수 규약 | §8.3이 상속 6개 + 추가(CONNECTOR_*/EMBED_PROVIDER/EMBED_MODEL/WEB_SEARCH_PROVIDER/AGENT_PROVIDER/STT_*/VISION_*/WORKER_*/AUTH_*) 일관, `EMBEDDING_MODEL` 표기 없음, 기본 CONNECTOR_*=mock·EMBED_PROVIDER=ollama·WEB_SEARCH_PROVIDER=mock·AGENT_PROVIDER=LLM_PROVIDER 상속·WORKER/AUTH=false | | PM-9 | 라우터/시드 패턴 | §8 신규 라우터 내부 prefix 없음 + `include_router(prefix="/api")`, `run_seed(session=None, reset=True)` + 내부 `_seed_*` 헬퍼(phase-2 상속) | | PM-10 | 상호 참조 | 모든 phase 문서를 정확한 파일명(`phase-7-approvals-automation.md` … `phase-15-production.md`, MVP `phase-0~6`)으로 링크 | ### 13.3 전 phase 공통 통과 기준(요약, 상세는 각 문서) - **백엔드**: `pytest` 전건 통과. 자동화 evaluator가 이벤트→규칙→approval enqueue를 정확히 수행(low 자동/high 대기). 커넥터 `MockConnector`가 base 인터페이스를 충족(real로 교체해도 동일 시그니처). 에이전트/RAG는 **폴백(scripted/cosine)으로도 결정적** 통과. - **프론트**: `pnpm test` 컴포넌트 통과. `pnpm playwright test` 연합 E2E(F3 회의→작업, F6 자동처리→결재함→하루마감) 통과. axe 위반 0(serious↑). - **디자인 충실도**: 라이트/다크 토큰 적용, 상단바 13항목 전부 라이브, 회의 도우미 드로어/레일/탭 동작, glass/라운드/그림자가 토큰과 일치, 한국어 문구가 원본 *-data.js와 동일. ### 13.4 수동 QA 체크리스트 (포스트-MVP 전체) - [ ] 상단 내비 13항목 전부 **실제 페이지**로 이동(준비 중 없음). `하루 마감`은 풀스크린(상단 메뉴 없음). - [ ] 결재함: low 항목 *되돌리기*만, high 항목 *cta/alt*(보내기/수정 등) 노출. `savedToday:"47분"`·자동 처리 건수 표시. - [ ] 자율성 설정 변경(approval_first/mixed/full_auto) → 자동 실행 동작 변화. - [ ] 자동화: 자연어 한 문장(예 *"출장 전날엔 저녁 일정 비워줘"*) → trigger/cond/action 미리보기 → 생성 → 토스트 후 목록 복귀. 아리 제안 레일 dot. - [ ] 일정: 일(日) 뷰 회의 도우미 — done(요약·결정·**액션→작업**), live(기록 중), upcoming(브리핑·지난 액션 체크), 1:1(signals/talkingPoints). - [ ] 메일: 3계정(회사/개인/사이드) 통합, AI 요약·우선순위·라벨, 본문에서 작업/일정 추출 → 작업 보드/캘린더 등장. - [ ] 알림: 지금/나중에/아리가 처리 3버킷 + 이유 칩(why) + 되돌리기. 집중 보호(`guard.until:"16:00"`). - [ ] 리서치: 멀티소스 종합 표(cross[]), 지식 Q&A(근거 refs), 시각화 + 예측(점선 forecast bar). - [ ] 여행: 출장 D-4 개요·이동·체크리스트·경비, AI 플래너(제주/도쿄 결과 + 자유 입력 폴백, 체크 localStorage). - [ ] 라이프: 건강(rings/sleep/habits)·금융(budget/subs/insights)·지식(items) + 커넥터 on/last·"연결 안 됨". - [ ] 여정: 4단계 흐름 + 베지어 협업 링크 + 하단 작업 테이블. - [ ] 하루 마감: stats(완료/딥워크/미팅/자동 처리 47분 아낌)·하이라이트·이월·내일 미리보기·수면 모드. - [ ] 연합: 회의 액션 "작업으로" → 작업 등장 / 자동 처리 → 결재함 → 하루 마감 합산. - [ ] 라이트/다크 토글 + 새로고침 유지. 한국어 `word-break: keep-all`. --- ## 14. 완료 기준 (Definition of Done) 이 진입 문서의 DoD: - [x] 포스트-MVP 비전(3→13페이지 + 연합 + 실연동 + 능동) 서술(§3). - [x] 추가물 카탈로그: 10페이지(라우트/원본/phase) + 9개 횡단 레이어(명명 고정)(§4). - [x] 횡단 아키텍처 텍스트 다이어그램(FastAPI+SQLite+Ollama 위 automation/connectors/agents/rag/worker + event_bus)(§5). - [x] 연합 시나리오 표(PROJECT-README §5 6대 흐름 → 이벤트/엔드포인트 매핑) + 대표 데이터 경로(§6). - [x] phase 7~15 로드맵 표(목표/산출물/의존성/주요 레이어/규모) + 빌드 순서·의존 그래프(§7). - [x] 신규 데이터 테이블 개요(횡단 코어 + 페이지별, 원본 필드 인용) + 환경변수(§8). - [x] event_bus 이벤트 타입 목록 + 발행/구독 매트릭스(§9). - [x] 가정/결정 A1~A7(mock-first·모델 비종속·단일→멀티유저·조정 포인트)(§10). - [x] 비기능 목표 상향선(성능/접근성/관측성/결정성/보안)(§11). - [x] 테스팅 & 검증(실행 명령·검증 케이스 PM-1~10·통과 기준·수동 QA)(§13). - [x] 모든 phase 문서를 정확한 파일명으로 상호 참조(MVP phase-0~6 + 포스트-MVP phase-7~15). - [x] 상속 규약(스택/토큰/데이터모델/API/환경변수/시드/명명) 준수, 임의 변경 없음. --- ## 15. 이 문서 세트 사용법 + MVP 문서와의 관계 ### 15.1 MVP 문서와의 관계 (상속) ``` dev/overview.md (MVP 정본) └─ phase-0-foundation.md → phase-1-design-system.md → phase-2-backend.md → phase-3-tasks.md → phase-4-inbox.md → phase-5-dashboard.md → phase-6-integration.md ▼ 상속(스택·토큰·데이터모델·API·환경변수·시드·명명) dev/post-mvp-overview.md (이 문서 · 포스트-MVP 정본) └─ phase-7 … phase-15 ``` - 스택(Next.js+React+TS / FastAPI+SQLite(SQLModel+Alembic) / Ollama Provider 추상화), 디자인 토큰(dash.css), 데이터모델 규약(PK=TEXT, tone enum), API 규약(prefix /api, 라우터 내부 prefix 없음), 환경변수, 시드(`run_seed`)는 **MVP에서 그대로 상속** — 변경 금지. - 포스트-MVP 신규 테이블/엔드포인트는 **phase-2-backend.md 패턴**을 따릅니다(SQLModel 모델 + Pydantic 스키마 + 라우터 + `_seed_*` 헬퍼). ### 15.2 읽는 순서 1. **`dev/overview.md`** — MVP 전체 그림·계약·로드맵(선행 필독). 2. **`dev/post-mvp-overview.md`(이 문서)** — 포스트-MVP 비전·횡단 아키텍처·phase 7~15 로드맵·의존성·가정. 3. **`phase-7-approvals-automation.md`** — 자율성 코어(결재함 + 자동화 엔진). MVP 직후 최우선. 4. **`phase-8-calendar-meetings.md`** — 일정 + 회의 도우미(액션→작업 연합). 5. **`phase-9-mail-notifications.md`** — 메일 + 알림 트리아지. 6. **`phase-10-research-travel.md`** — 리서치 + 여행(에이전트 + RAG + 웹검색). 7. **`phase-11-life-care.md`** — 라이프 케어(건강·금융·지식, 커넥터). 8. **`phase-12-daily-narrative.md`** — 여정 + 하루 마감(전 페이지 집계). 9. **`phase-13-integrations.md`** — 외부 연동 & 커넥터(mock→real). 10. **`phase-14-proactive-agent.md`** — 능동형 에이전트 + 멀티모달. 11. **`phase-15-production.md`** — 프로덕션 하드닝(인증/멀티유저/배포/관측성). ### 15.3 작업 방식 (overview.md §19.2 상속) - 각 포스트-MVP phase 문서는 **10개 필수 섹션**을 가집니다: ①개요·목표 ②선행조건·산출물 ③상세 구현 ④데이터/타입/API 계약 ⑤디자인 충실도 노트 ⑥상태 처리·엣지케이스 ⑦연합 이벤트(발행/구독) ⑧테스팅 & 검증 ⑨완료 기준 ⑩다음 단계. - 항상 **빌드 순서(§7.2)** 를 지키세요: `7→8→9→10→11→12→13→14→15`(7 최우선, 페이지 mock-first, 13에서 real 전환). - 값(색·필드·문구)은 항상 **`REF/assets`의 원본 *-data.js를 단일 출처**로 삼고, 의심되면 이 문서의 표(§8)와 대조하세요. - 계약(데이터 모델·API·토큰·스택·환경변수·명명)은 **변경 금지** — 변경이 필요하면 먼저 `overview.md`(MVP) 또는 이 `post-mvp-overview.md`(포스트-MVP)를 갱신하고 영향 phase에 전파합니다. --- *끝. 다음 문서: `phase-7-approvals-automation.md`*