Personal Operations Typed Schema
1. 목적
이 문서는 canonical ontology를 실제 구현 가능한 타입과 저장 구조로 내리기 위한 초안이다.
범위는 다음과 같다.
- canonical ontology 전체를 구현하지는 않는다
- 하지만 이후 확장이 가능한 공통 타입 구조를 먼저 고정한다
- 저장소는 우선
Postgres + JSONB + edge table을 가정한다
2. 설계 원칙
- 공통 필드는 모든 엔티티에 일관되게 적용한다
- 관계는 edge table에 저장하고 typed relation으로 구분한다
- provenance와 privacy는 선택 사항이 아니라 기본 필드다
- derived metric과 insight는 raw entity와 별도 테이블에 둔다
- 시나리오는 실 그래프를 직접 수정하지 않고 별도 state copy에 기록한다
3. 공통 Enum
entity_kind
person organization role goal objective milestone plan project task commitment decision option scenario assumption resource constraint risk calendar_event conversation document financial_event account health_signal relationship metric outcome evidence_item insight recommendation
privacy_level
public personal sensitive financial health legal
record_status
draft active paused completed dropped archived assumed invalidated
confidence_level
low medium high very_high
source_type
email calendar note document task_app bank_csv healthkit manual derived
relation_kind
owns has_role belongs_to participates_in supports blocks depends_on requires conflicts_with scheduled_for due_on communicated_in costs improves worsens affects evidenced_by derived_from chosen_for rejected_for leads_to based_on_assumption sensitive_to
4. Core Tables
4.1 entities
모든 typed entity의 공통 저장소.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | uuid | PK |
entity_kind | text | 엔티티 타입 |
title | text | 대표 이름 |
description | text | 설명 |
status | text | 공통 상태 |
privacy_level | text | 민감도 |
confidence_level | text | 신뢰도 |
canonical_key | text | dedupe용 key |
attributes | jsonb | kind-specific 속성 |
observed_at | timestamptz | 관측 시점 |
effective_from | timestamptz | 효력 시작 |
effective_to | timestamptz | 효력 종료 |
created_at | timestamptz | 생성 시점 |
updated_at | timestamptz | 수정 시점 |
핵심 아이디어는 typed table per entity 대신 공통 entity table + attributes jsonb로 시작하는 것이다. 초기엔 유연성이 더 중요하다.
4.2 edges
관계 저장소.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | uuid | PK |
relation_kind | text | 관계 타입 |
source_entity_id | uuid | source |
target_entity_id | uuid | target |
weight | numeric | 강도 또는 영향도 |
attributes | jsonb | relation-specific 속성 |
observed_at | timestamptz | 관측 시점 |
effective_from | timestamptz | 효력 시작 |
effective_to | timestamptz | 효력 종료 |
confidence_level | text | 신뢰도 |
created_at | timestamptz | 생성 시점 |
updated_at | timestamptz | 수정 시점 |
4.3 evidence_items
증거 원문 저장소.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | uuid | PK |
source_type | text | email, calendar 등 |
source_app | text | Gmail, GCal 등 |
source_id | text | 외부 시스템 ID |
content_text | text | 정규화된 텍스트 |
raw_excerpt | text | 핵심 발췌 |
metadata | jsonb | 추가 메타 |
privacy_level | text | 민감도 |
observed_at | timestamptz | 원본 발생 시점 |
created_at | timestamptz | 수집 시점 |
4.4 entity_evidence_links
엔티티와 증거 연결.
| 컬럼 | 타입 |
|---|---|
id | uuid |
entity_id | uuid |
evidence_item_id | uuid |
link_type | text |
confidence_level | text |
created_at | timestamptz |
4.5 metrics
계산된 메트릭의 시계열 저장소.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | uuid | PK |
metric_name | text | 예: runway_months |
subject_entity_id | uuid | 보통 user |
value_number | numeric | 수치 |
value_text | text | 범주형 값 허용 |
unit | text | months, hours 등 |
window_start | timestamptz | 계산 구간 시작 |
window_end | timestamptz | 계산 구간 끝 |
computed_at | timestamptz | 계산 시점 |
computation_version | text | 계산 로직 버전 |
inputs | jsonb | 사용된 source ids |
4.6 insights
파생 인사이트 저장소.
| 컬럼 | 타입 |
|---|---|
id | uuid |
insight_kind | text |
subject_entity_id | uuid |
title | text |
body | text |
confidence_level | text |
attributes | jsonb |
created_at | timestamptz |
4.7 decision_sessions
사용자의 질문 단위.
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | uuid | PK |
user_entity_id | uuid | 사용자 |
question | text | 원문 질문 |
decision_type | text | career, time, relationship 등 |
status | text | open, analyzing, completed |
baseline_snapshot_id | uuid | 분석 시작 state |
created_at | timestamptz | 생성 시점 |
updated_at | timestamptz | 수정 시점 |
4.8 decision_options
| 컬럼 | 타입 |
|---|---|
id | uuid |
decision_session_id | uuid |
label | text |
description | text |
status | text |
attributes | jsonb |
created_at | timestamptz |
4.9 scenario_runs
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | uuid | PK |
decision_session_id | uuid | 소속 결정 |
option_id | uuid | 연결된 선택지 |
scenario_name | text | 시나리오 이름 |
assumptions | jsonb | 전제 목록 |
interventions | jsonb | 적용된 개입 |
baseline_snapshot_id | uuid | 기준 상태 |
scenario_snapshot_id | uuid | 결과 상태 |
status | text | pending, completed |
created_at | timestamptz | 생성 시점 |
4.10 scenario_metric_deltas
| 컬럼 | 타입 |
|---|---|
id | uuid |
scenario_run_id | uuid |
metric_name | text |
baseline_value | numeric |
scenario_value | numeric |
delta_value | numeric |
delta_direction | text |
created_at | timestamptz |
4.11 decision_memos
| 컬럼 | 타입 |
|---|---|
id | uuid |
decision_session_id | uuid |
memo_markdown | text |
summary_json | jsonb |
confidence_level | text |
created_at | timestamptz |
4.12 state_snapshots
분석 시점 상태를 고정하기 위한 스냅샷.
| 컬럼 | 타입 |
|---|---|
id | uuid |
user_entity_id | uuid |
snapshot_kind | text |
state_json | jsonb |
created_at | timestamptz |
5. Kind-Specific Attribute Shapes
goal.attributes
{ "horizon": "quarterly", "priority": 1, "success_criteria": "decide whether to start startup prep", "area": "career" }
project.attributes
{ "project_type": "work", "owner_entity_id": "uuid", "deadline": "2026-06-30T00:00:00Z" }
commitment.attributes
{ "commitment_type": "work", "importance": "high", "hard_deadline": "2026-03-28T00:00:00Z", "repeating": true }
resource.attributes
{ "resource_type": "cash", "current_value": 42000, "unit": "usd" }
constraint.attributes
{ "constraint_type": "time", "severity": "high", "notes": "leadership meetings consume evenings" }
health_signal.attributes
{ "signal_type": "sleep_hours", "value": 6.4, "unit": "hours", "window": "daily" }
relationship.attributes
{ "relationship_type": "cofounder_candidate", "strength": 0.7, "trust_level": 0.6, "last_contact_at": "2026-03-10T12:00:00Z" }
decision.attributes
{ "decision_type": "career", "deadline": "2026-06-01T00:00:00Z", "reversibility": "medium", "stakes": "high" }
6. Derived Metrics Spec
초기 MVP에서 우선 계산할 메트릭:
| metric_name | 정의 | 입력 |
|---|---|---|
weekly_committed_hours | 이번 주 총 약속 시간 | calendar, commitments |
deep_work_hours_per_week | 연속 집중 가능 시간 | calendar, focus blocks |
free_cash_flow | 월 순현금흐름 | income, expense |
runway_months | 버틸 수 있는 개월 수 | cash, burn |
execution_load | 현재 과부하 정도 | tasks, commitments |
goal_alignment_score | 시간과 행동이 목표와 얼마나 일치하는가 | goals, activities |
context_switch_load | 시간 파편화 정도 | calendar events |
7. API Contract Draft
POST /api/decisions
입력:
{ "question": "Should I stay at my current job or start startup prep in the next 6 months?", "decision_type": "career" }
출력:
{ "decision_session_id": "uuid", "status": "open" }
POST /api/decisions/:id/run
입력:
{ "options": [ { "label": "remain_in_job", "description": "Stay focused on current job" }, { "label": "startup_prep_weekends", "description": "Use weekends for startup prep", "assumptions": ["8 deep work hours per week can be secured"] } ] }
출력:
{ "decision_session_id": "uuid", "scenario_run_ids": ["uuid", "uuid"], "status": "analyzing" }
GET /api/decisions/:id/memo
출력:
{ "decision_session_id": "uuid", "status": "completed", "memo_markdown": "...", "top_metric_deltas": [ { "metric_name": "runway_months", "delta_value": -4.0 } ] }
8. Why This Shape
이 구조를 택하는 이유는 세 가지다.
- ontology를 너무 일찍 rigid table로 박아두면 확장이 어렵다
- 그렇다고 모든 것을 문서와 embedding에만 두면 계산이 안 된다
- 그래서
entity/edge/event/metric/scenario/memo축만 먼저 고정하는 편이 좋다
9. Next Migration Path
스키마가 안정화되면 아래 순서로 더 정교하게 분리할 수 있다.
- high-volume event source는 별도 raw table로 분리
goal,decision,relationship는 dedicated typed table 생성- graph traversal이 복잡해지면 graph DB 또는 materialized path 계층 추가
- metrics 계산은 batch job에서 stream update로 이동