# Devflow Python 재시작 계획 (plan.md v4 r1) ## Context TS 모노레포 전체 폐기 + Python으로 Devflow 새로 짜기. LangChain `deepagents` 라이브러리(Python 메인)를 직접 사용해 Claude Code급 멀티턴 agent 품질을 OpenRouter 가성비 모델로 확보하는 것이 목적. 직전까지의 M1~M8 (TS) 구현과 이번 세션의 OpenRouter Step 1(TS) 변경은 모두 폐기 대상이다. 원인: 1. Claude/Anthropic 직접 API 비용 부담. 2. OpenRouter 가성비 모델(DeepSeek 등)을 주 backend로. 3. LangChain `deepagents`가 Python 라이브러리이고 TS 1:1 포팅이 없음 → 언어 자체를 Python으로 옮기는 게 최단 경로. --- ## 폐기 / 보존 ### 폐기 (모두 git rm 또는 디렉토리 삭제) - `apps/{api,cli,web,worker}/` - `packages/{core,db,run-engine,session,workflows}/` - `tests/` - `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `package.json` - `biome.json`, `lefthook.yml`, `vitest.workspace.ts`, `drizzle.config.ts` - `tsconfig.base.json`, `tsconfig.json`, `tsconfig.typecheck.json` - `.nvmrc` - 이번 세션의 OpenRouter Step 1 TS 변경 (enums/config/binding) — 동일 의도를 Python에서 재구현 ### 보존 (언어 중립 자산) - `docs/plan.md` — v3 r13 도메인 명세(§2 디렉토리 빼고 §4~§17 대부분)는 그대로 살림. §0/§1/§2/§3/§20/§22만 v4 r1로 패치. - `docs/schemas/artifacts/*.json` — JSON Schema 2020-12, 언어 무관 - `docs/schemas/personas/*.yaml`, `docs/schemas/templates/*.yaml` — 도메인 자산 - `docker-compose.yml` — Postgres + Temporal 컨테이너 - `.env.example` — 일부 키 그대로 - `migrations/*.sql` — Alembic baseline으로 흡수 후 검토 - `.git`, `.github` (있다면), `.gitignore` 일부 갱신 --- ## 스택 (v4 r1) | 영역 | 선택 | 대체 후보 (참고용) | |---|---|---| | 언어/런타임 | **Python 3.12+** | 3.11도 가능 | | 패키지 관리 | **uv** (workspace) | Poetry, pip + pip-tools | | 스키마/Config | **pydantic v2** + **pydantic-settings** | dataclasses + cattrs | | DB | **SQLAlchemy 2.0 async** + **asyncpg** + **Alembic** | SQLModel, Tortoise | | HTTP/API | **FastAPI** + **uvicorn** + **sse-starlette** | Litestar | | CLI | **typer** | Click | | 워크플로우 | **temporalio** (Python SDK) | (Temporal 자체는 유지) | | Agent | **langchain** + **langgraph** + **deepagents** + **langchain-openai** | 자체 구현 | | Tmux | **libtmux** | subprocess 직호출 | | 테스트 | **pytest** + **pytest-asyncio** + **pytest-httpx** | unittest | | 린트/포맷 | **ruff** | black + flake8 | | 타입체크 | **mypy** strict (또는 **pyright**) | — | | Pre-commit | **pre-commit** | — | | 로깅 | **structlog** + **rich** | loguru | | YAML | **PyYAML** | ruamel.yaml | | JSON Schema | **jsonschema** | — | ### Web GUI **이번 plan 범위 외.** TS web app은 폐기되지만 Python 재이식은 별도 마일스톤. 후보: FastAPI SSR + HTMX, 별도 SPA(Svelte/Vue) 분리. 결정 보류. --- ## 디렉토리 구조 ```text devflow/ ├── pyproject.toml # uv workspace root ├── uv.lock ├── ruff.toml ├── mypy.ini ├── .pre-commit-config.yaml ├── docker-compose.yml # 보존 ├── .env.example ├── alembic.ini ├── docs/ │ ├── plan.md # v4 r1로 패치 │ └── schemas/ # 보존 ├── alembic/ │ ├── env.py │ └── versions/ ├── packages/ │ ├── core/src/devflow_core/ │ │ ├── config.py │ │ ├── enums.py │ │ ├── errors.py │ │ ├── hash.py │ │ ├── persona.py │ │ ├── binding.py │ │ ├── prompt_envelope.py │ │ ├── artifact_schema.py │ │ └── run_event.py │ ├── db/src/devflow_db/ │ │ ├── models/ │ │ ├── repositories/ │ │ └── client.py │ ├── session/src/devflow_session/ │ │ ├── adapter.py │ │ ├── fake.py │ │ ├── tmux.py │ │ └── openrouter_deepagents.py │ ├── run_engine/src/devflow_run_engine/ │ └── workflows/src/devflow_workflows/ ├── apps/ │ ├── api/ # FastAPI │ ├── cli/ # typer │ └── worker/ # Temporal Python worker └── tests/ ├── e2e/ └── fixtures/ ``` --- ## plan.md v4 r1 패치 항목 - §0 헤더: `v4 r1`, "Major version bump: language migration TS → Python. v3 CC counters preserved as historical; v4 CC counter starts at 1." - §1 Stack Decisions: **전면 재작성** (위 스택 표 채택). - §2 Directory Layout: 위 구조로 교체. - §3 doctor checklist: Node/pnpm 체크 → Python/uv 체크로 교체. Postgres, tmux, git, Docker, OpenRouter check 13 유지. - §4~§17 (DB schema, enums, hashing, template/persona/binding, session, prompt envelope, artifact registry, run events, fake adapter, state machines, errors, SSE contract): 언어 중립 도메인 명세 → 그대로 유지. Python 구현 시 동일 의미. - §8.5 OpenRouter Adapter: **재작성** — 단발 응답 + 마커 추출(v3 r13) → **deepagents 멀티턴 + tool use**. tool whitelist (`read_file`, `write_file`, `list_dir`, `run_command`, `request_subagent`, `complete`), max_turns, subagent isolation, virtual filesystem→worktree 매핑. - §18 Errors: `token_budget_exceeded`, `tool_quota_exceeded` 추가. - §20 Milestones: 기존 M1~M13을 Python 재이식 매핑 (M1-Py ~ M8-Py 본 plan 범위, M9~M13 후속). - §22 Decision Log: `DR-1: v3→v4 메이저 점프, TS 모노레포 폐기 + Python 재시작 + LangChain deepagents 채택` 추가. CC-39(OpenRouter TS)는 v4에서 의미 변경, deepagents 통합으로 superseded. - §22 Decision Log: `DR-22: Persona/Workflow의 list-valued field는 tuple로 immutable | hash drift 방지, plugin 시스템 (v0.2)에서 외부 mutate 차단` 추가. --- ## 구현 단계 (각 Step = 1 PR) ### Step 0 — 폐기 + 스캐폴딩 ⚠️ 위험 큼 1. 폐기 디렉토리/파일 git rm. 2. `uv init` + workspace 멤버 등록. 3. 새 디렉토리 트리 생성 (위 구조). 4. `ruff.toml`, `mypy.ini`, `.pre-commit-config.yaml`, `alembic.ini` 추가. 5. plan.md v4 r1 패치 적용 (§0/§1/§2/§3/§20/§22). 6. CHANGELOG.md `[Unreleased]`에 "BREAKING: TS codebase removed, Python rewrite begins" 기록. 7. `docker-compose.yml`, `docs/schemas/` 보존 확인. ### Step 1 — `devflow_core` (M1.4-Py) config/enums/errors/hash/persona/prompt_envelope/run_event를 pydantic v2로. plan.md §5/§6/§7 명세 그대로. ### Step 2 — `devflow_db` (M1.2-Py) SQLAlchemy 2 async 모델 + Alembic baseline. 기존 `migrations/*.sql`을 baseline으로 흡수. ### Step 3 — `apps/cli` doctor (M1.3-Py) typer 기반. 체크 1~12 + OpenRouter check 13. Node/pnpm 체크는 Python/uv로 교체. ### Step 4 — Persona/Template seeding + binding (M2-Py) YAML 로더(`docs/schemas/{personas,templates}/`) + pydantic 검증 + autoSelect/override/diversity (§7.4 그대로). ### Step 5 — Artifact schema registry (M2.3-Py) `jsonschema` 라이브러리로 2020-12 검증. `docs/schemas/artifacts/`를 그대로 로드. ### Step 6 — Fake session adapter (M3-Py) 인메모리. fixture 기반 시나리오(§12). ### Step 7 — Run engine (M4-Py) in-process. 페이즈 진행, 이벤트 append, idempotency key. ### Step 8 — Temporal integration (M5-Py) temporalio worker. 워크플로우/액티비티 §15 그대로 포팅. ### Step 9 — Tmux adapter (M6-Py) libtmux + subprocess. 기존 §8.2 상태머신 유지. ### Step 10 — TUI recovery (M7-Py) 세션 상태머신, recovery counters. ### Step 11 — FastAPI + SSE (M8-Py, GUI 제외) REST + SSE-Starlette. GUI는 별도. ### Step 12 — OpenRouter deepagents adapter (M9-Py 일부, **본 변경 핵심**) - `langchain-openai` ChatOpenAI를 OpenRouter base URL로. - `deepagents.create_deep_agent(tools, instructions, subagents)`. - tools: `read_file`/`write_file`/`list_dir`/`run_command(allowlist)`/`request_subagent`/`complete`. - subagents: review/verifier 분리 컨텍스트. - virtual filesystem → 실제 worktree 매핑. - artifact 작성은 `write_file(expectedArtifactPath, ...)` 호출로 (v3 r13 마커 폐기). - 토큰 한도/turn 한도는 페르소나 `modelConfig.maxTurns`, `modelConfig.maxTokensTotal`로. - 시드 페르소나 2개: `openrouter-deepseek-spec@1.yaml`, `openrouter-deepseek-reviewer@1.yaml` (DeepSeek 디폴트). --- ## 의존성 (Step 0에서 정확 버전 lock) ```toml [project] requires-python = ">=3.12,<3.14" dependencies = [ "pydantic>=2.9", "pydantic-settings>=2.6", "sqlalchemy[asyncio]>=2.0", "alembic>=1.14", "asyncpg>=0.30", "fastapi>=0.115", "uvicorn[standard]>=0.34", "sse-starlette>=2.1", "typer>=0.14", "temporalio>=1.10", "langchain>=0.3", "langchain-openai>=0.2", "langgraph>=0.2", "deepagents>=0.0.5", "libtmux>=0.39", "structlog>=24.4", "rich>=13.9", "pyyaml>=6.0", "jsonschema>=4.23", "httpx>=0.28", ] [dependency-groups] dev = [ "pytest>=8.3", "pytest-asyncio>=0.24", "pytest-httpx>=0.34", "ruff>=0.8", "mypy>=1.13", "pre-commit>=4.0", ] ``` --- ## 환경 셋업 (선결) ```bash # 1) Python 3.12+ (uv가 알아서 가져옴) # 2) uv 설치 curl -LsSf https://astral.sh/uv/install.sh | sh # 3) 워크스페이스 동기화 uv sync # 4) 컨테이너 (보존된 docker-compose.yml) docker compose up -d ``` 기존 pnpm 환경 문제(`pnpm not found`)는 Node 자체가 필요 없어져 자연 해결. --- ## 모델 위임 정책 (메모리 룰 유지) | 작업 | 모델 | subagent_type | |---|---|---| | Python 구현 | sonnet | `coder` / `general-purpose` | | 코드 리뷰 | opus | `feature-dev:code-reviewer` / `reviewer` | | 리뷰 지적 수정 | sonnet | `coder` | --- ## 검증 (각 Step 게이트) ```bash uv run ruff check . uv run ruff format --check . uv run mypy . uv run pytest ``` 전부 PASS → 커밋 → 다음 Step. --- ## 범위 외 - Web GUI 재이식 (TS 폐기 확정, Python 재이식은 별도 마일스톤). - 다중 모델 fallback (rate limit 시 다른 모델로). - 비용 추적/예산 게이트 (OpenRouter usage API). - 다른 HTTP provider (Anthropic 직접, OpenAI 직접). - 한국어 GUI/문서화. --- ## 주의 - **Step 0의 git rm은 비가역적 위험**: 직전에 `git tag pre-python-rewrite`를 찍어 v3 마지막 커밋을 태깅. 필요 시 `git checkout pre-python-rewrite -- ` 로 자료 추출 가능. - TS 마지막 commit `c9fed71` 이후의 미커밋 변경(M9 단계 A yaml/json + plan.md r13 + Step 1 TS) 처리: - yaml/json (M9 A): 보존 (언어 중립) - plan.md r13 패치: v4 r1 패치 안에서 일부 흡수 (CC-39는 변경 의미 변경됨) - Step 1 TS 변경: git rm 대상에 포함 (Python 재구현)