@kmgeon/taskflow 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +374 -0
- package/bin/task-mcp.mjs +19 -0
- package/bin/task.mjs +19 -0
- package/docs/clean-code.md +29 -0
- package/docs/git.md +36 -0
- package/docs/guideline.md +25 -0
- package/docs/security.md +32 -0
- package/docs/step-by-step.md +29 -0
- package/docs/superpowers/specs/2026-03-21-cli-advisor-design.md +383 -0
- package/docs/superpowers/specs/2026-03-21-init-redesign-design.md +429 -0
- package/docs/superpowers/specs/2026-03-21-skill-architecture-design.md +362 -0
- package/docs/superpowers/specs/2026-03-23-t-create-task-run-design.md +40 -0
- package/docs/superpowers/specs/2026-03-23-task-run-design.md +44 -0
- package/docs/tdd.md +41 -0
- package/package.json +114 -0
- package/src/app/(protected)/dashboard/page.tsx +7 -0
- package/src/app/(protected)/layout.tsx +10 -0
- package/src/app/api/[[...hono]]/route.ts +13 -0
- package/src/app/example/page.tsx +11 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +168 -0
- package/src/app/layout.tsx +35 -0
- package/src/app/page.tsx +5 -0
- package/src/app/providers.tsx +57 -0
- package/src/backend/config/index.ts +36 -0
- package/src/backend/hono/app.ts +32 -0
- package/src/backend/hono/context.ts +38 -0
- package/src/backend/http/response.ts +64 -0
- package/src/backend/middleware/context.ts +23 -0
- package/src/backend/middleware/error.ts +31 -0
- package/src/backend/middleware/supabase.ts +23 -0
- package/src/backend/supabase/client.ts +17 -0
- package/src/cli/commands/__tests__/task-commands.test.ts +170 -0
- package/src/cli/commands/advisor.ts +45 -0
- package/src/cli/commands/ask.ts +50 -0
- package/src/cli/commands/board.ts +72 -0
- package/src/cli/commands/init.ts +184 -0
- package/src/cli/commands/list.ts +138 -0
- package/src/cli/commands/run.ts +143 -0
- package/src/cli/commands/set-status.ts +50 -0
- package/src/cli/commands/show.ts +28 -0
- package/src/cli/commands/tree.ts +72 -0
- package/src/cli/index.ts +38 -0
- package/src/cli/lib/__tests__/formatter.test.ts +123 -0
- package/src/cli/lib/error-boundary.test.ts +135 -0
- package/src/cli/lib/error-boundary.ts +70 -0
- package/src/cli/lib/formatter.ts +764 -0
- package/src/cli/lib/trd.ts +33 -0
- package/src/cli/lib/validate.test.ts +89 -0
- package/src/cli/lib/validate.ts +43 -0
- package/src/cli/prompts/task-run.md +25 -0
- package/src/components/layout/AppLayout.tsx +15 -0
- package/src/components/layout/Sidebar.tsx +124 -0
- package/src/components/ui/accordion.tsx +58 -0
- package/src/components/ui/avatar.tsx +50 -0
- package/src/components/ui/badge.tsx +36 -0
- package/src/components/ui/button.tsx +56 -0
- package/src/components/ui/card.tsx +79 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/dialog.tsx +122 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/file-upload.tsx +50 -0
- package/src/components/ui/form.tsx +179 -0
- package/src/components/ui/input.tsx +25 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/scroll-area.tsx +48 -0
- package/src/components/ui/select.tsx +160 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/sheet.tsx +140 -0
- package/src/components/ui/textarea.tsx +22 -0
- package/src/components/ui/toast.tsx +129 -0
- package/src/components/ui/toaster.tsx +35 -0
- package/src/core/ai/claude-client.ts +79 -0
- package/src/core/claude-runner/flag-builder.ts +57 -0
- package/src/core/claude-runner/index.ts +2 -0
- package/src/core/claude-runner/spawner.ts +86 -0
- package/src/core/prd/__tests__/auto-analyzer.test.ts +35 -0
- package/src/core/prd/__tests__/generator.test.ts +26 -0
- package/src/core/prd/__tests__/scanner.test.ts +35 -0
- package/src/core/prd/auto-analyzer.ts +9 -0
- package/src/core/prd/generator.ts +8 -0
- package/src/core/prd/scanner.ts +117 -0
- package/src/core/project/__tests__/claude-setup.test.ts +133 -0
- package/src/core/project/__tests__/config.test.ts +30 -0
- package/src/core/project/__tests__/init.test.ts +37 -0
- package/src/core/project/__tests__/skill-setup.test.ts +62 -0
- package/src/core/project/claude-setup.ts +224 -0
- package/src/core/project/config.ts +34 -0
- package/src/core/project/docs-setup.ts +26 -0
- package/src/core/project/docs-templates.ts +205 -0
- package/src/core/project/init.ts +40 -0
- package/src/core/project/skill-setup.ts +32 -0
- package/src/core/project/skill-templates.ts +277 -0
- package/src/core/task/index.ts +16 -0
- package/src/core/types.ts +58 -0
- package/src/features/example/backend/error.ts +9 -0
- package/src/features/example/backend/route.ts +52 -0
- package/src/features/example/backend/schema.ts +25 -0
- package/src/features/example/backend/service.ts +73 -0
- package/src/features/example/components/example-status.test.tsx +97 -0
- package/src/features/example/components/example-status.tsx +160 -0
- package/src/features/example/hooks/useExampleQuery.ts +23 -0
- package/src/features/example/lib/dto.test.ts +57 -0
- package/src/features/example/lib/dto.ts +5 -0
- package/src/features/kanban/backend/__tests__/sse-broadcaster.test.ts +137 -0
- package/src/features/kanban/backend/__tests__/sse-event-format.test.ts +55 -0
- package/src/features/kanban/backend/route.ts +55 -0
- package/src/features/kanban/backend/sse-broadcaster.ts +142 -0
- package/src/features/kanban/backend/sse-route.ts +43 -0
- package/src/features/kanban/components/KanbanBoard.tsx +105 -0
- package/src/features/kanban/components/KanbanColumn.tsx +51 -0
- package/src/features/kanban/components/KanbanError.tsx +29 -0
- package/src/features/kanban/components/KanbanSkeleton.tsx +46 -0
- package/src/features/kanban/components/ProgressCard.tsx +42 -0
- package/src/features/kanban/components/TaskCard.tsx +76 -0
- package/src/features/kanban/components/__tests__/kanban-components.test.tsx +86 -0
- package/src/features/kanban/hooks/useTaskSse.ts +66 -0
- package/src/features/kanban/hooks/useTasksQuery.ts +52 -0
- package/src/features/kanban/lib/__tests__/kanban-utils.test.ts +97 -0
- package/src/features/kanban/lib/kanban-utils.ts +37 -0
- package/src/features/taskflow/constants.ts +54 -0
- package/src/features/taskflow/index.ts +27 -0
- package/src/features/taskflow/lib/__tests__/filter.test.ts +89 -0
- package/src/features/taskflow/lib/__tests__/graph.test.ts +247 -0
- package/src/features/taskflow/lib/__tests__/repository.test.ts +233 -0
- package/src/features/taskflow/lib/__tests__/serializer.test.ts +98 -0
- package/src/features/taskflow/lib/advisor/__tests__/advisor-integration.test.ts +98 -0
- package/src/features/taskflow/lib/advisor/ai-advisor.test.ts +40 -0
- package/src/features/taskflow/lib/advisor/ai-advisor.ts +20 -0
- package/src/features/taskflow/lib/advisor/context-builder.test.ts +73 -0
- package/src/features/taskflow/lib/advisor/context-builder.ts +151 -0
- package/src/features/taskflow/lib/advisor/db.test.ts +106 -0
- package/src/features/taskflow/lib/advisor/db.ts +185 -0
- package/src/features/taskflow/lib/advisor/local-summary.test.ts +53 -0
- package/src/features/taskflow/lib/advisor/local-summary.ts +72 -0
- package/src/features/taskflow/lib/advisor/prompts.ts +86 -0
- package/src/features/taskflow/lib/filter.ts +54 -0
- package/src/features/taskflow/lib/fs-utils.ts +50 -0
- package/src/features/taskflow/lib/graph.ts +148 -0
- package/src/features/taskflow/lib/index-builder.ts +42 -0
- package/src/features/taskflow/lib/repository.ts +168 -0
- package/src/features/taskflow/lib/serializer.ts +62 -0
- package/src/features/taskflow/lib/watcher.ts +40 -0
- package/src/features/taskflow/types.ts +71 -0
- package/src/hooks/use-toast.ts +194 -0
- package/src/lib/remote/api-client.ts +40 -0
- package/src/lib/supabase/client.ts +8 -0
- package/src/lib/supabase/server.ts +46 -0
- package/src/lib/supabase/types.ts +3 -0
- package/src/lib/utils.ts +6 -0
- package/src/mcp/index.ts +7 -0
- package/src/mcp/server.ts +21 -0
- package/src/mcp/tools/brainstorm.ts +48 -0
- package/src/mcp/tools/prd.ts +71 -0
- package/src/mcp/tools/project.ts +39 -0
- package/src/mcp/tools/task-status.ts +40 -0
- package/src/mcp/tools/task.ts +82 -0
- package/src/mcp/util.ts +6 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# TaskFlow 스킬 아키텍처 설계
|
|
2
|
+
|
|
3
|
+
## 1. 배경 및 목적
|
|
4
|
+
|
|
5
|
+
### 현재 문제
|
|
6
|
+
- CLI 명령어가 과도하게 많고 옵션이 복잡함 (특히 `refine`은 옵션 10개)
|
|
7
|
+
- `brainstorm_prd`, `brainstorm_task` 등 MCP 도구가 내부에서 Claude API를 이중 호출
|
|
8
|
+
- Claude Code 자체가 AI인데, MCP 안에서 또 AI를 호출하는 건 토큰 낭비 + 응답 지연
|
|
9
|
+
|
|
10
|
+
### 새 방향
|
|
11
|
+
Claude Code 스킬 프롬프트가 워크플로우를 안내하고, MCP는 순수 데이터 접근만 담당한다.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
사용자 → Claude Code (스킬이 워크플로우 안내)
|
|
15
|
+
│
|
|
16
|
+
├→ MCP 데이터 도구 (읽기/쓰기)
|
|
17
|
+
└→ Claude Code 자체가 AI (대화/분석/생성)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 2. 아키텍처
|
|
21
|
+
|
|
22
|
+
### 계층 분리
|
|
23
|
+
|
|
24
|
+
| 계층 | 역할 | AI 호출 |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| **스킬 프롬프트** (`.taskflow/.claude/commands/`) | 워크플로우 오케스트레이션 | Claude Code 자체 |
|
|
27
|
+
| **MCP 도구** (`src/mcp/`) | 순수 데이터 접근 (CRUD, 파일 저장, 코드 스캔) | 없음 |
|
|
28
|
+
| **Core** (`src/core/`) | 비즈니스 로직 | 없음 (AI 클라이언트 제거) |
|
|
29
|
+
|
|
30
|
+
### 파일 위치 및 심볼릭 링크
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
.taskflow/.claude/commands/ ← 원본 (TaskFlow가 관리)
|
|
34
|
+
├── prd.md
|
|
35
|
+
├── trd.md
|
|
36
|
+
├── parse-prd.md
|
|
37
|
+
├── brainstorm.md
|
|
38
|
+
├── refine.md
|
|
39
|
+
├── next.md
|
|
40
|
+
└── task-status.md
|
|
41
|
+
|
|
42
|
+
.claude/commands/ ← task init이 심볼릭 링크 생성
|
|
43
|
+
├── prd.md → ../../.taskflow/.claude/commands/prd.md
|
|
44
|
+
├── trd.md → ../../.taskflow/.claude/commands/trd.md
|
|
45
|
+
├── parse-prd.md → ../../.taskflow/.claude/commands/parse-prd.md
|
|
46
|
+
├── brainstorm.md → ../../.taskflow/.claude/commands/brainstorm.md
|
|
47
|
+
├── refine.md → ../../.taskflow/.claude/commands/refine.md
|
|
48
|
+
├── next.md → ../../.taskflow/.claude/commands/next.md
|
|
49
|
+
└── task-status.md → ../../.taskflow/.claude/commands/task-status.md
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> **네이밍 충돌 주의:** 사용자가 `.claude/commands/`에 같은 이름의 파일을 가지고 있을 경우 `task init`은 해당 링크를 스킵한다. 필요시 `tf-` 접두사(예: `tf-prd.md`)로 변경 가능하지만, 일단 짧은 이름으로 시작한다.
|
|
53
|
+
|
|
54
|
+
- 수정/삭제는 `.taskflow/.claude/commands/`에서만 수행
|
|
55
|
+
- `.claude/commands/`의 심볼릭 링크가 자동으로 반영
|
|
56
|
+
- `task init`이 링크 생성을 담당
|
|
57
|
+
|
|
58
|
+
## 3. MCP 도구 변경
|
|
59
|
+
|
|
60
|
+
### 전체 도구 대조표
|
|
61
|
+
|
|
62
|
+
현재 17개 도구 → 정리 후 14개 도구 (제거 6, 신규 3)
|
|
63
|
+
|
|
64
|
+
| 현재 도구 | 처리 | 비고 |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `initialize_project` | **유지** | 순수 데이터 |
|
|
67
|
+
| `generate_claude_md` | **유지 + 수정** | 새 도구 목록/스킬 커맨드 반영 필요 |
|
|
68
|
+
| `generate_prd` | **제거** | `/prd` 스킬이 대체 |
|
|
69
|
+
| `brainstorm_prd` | **제거** | `/prd` 스킬이 대체 |
|
|
70
|
+
| `auto_analyze_prd` | **제거** | `scan_codebase`로 대체 (AI 호출 제거) |
|
|
71
|
+
| `generate_feature_prd` | **제거** | `/prd` 스킬에서 처리 |
|
|
72
|
+
| `parse_prd` | **제거** | `/parse-prd` 스킬이 대체 |
|
|
73
|
+
| `list_tasks` | **유지** | 순수 데이터 |
|
|
74
|
+
| `read_task` | **유지** | 순수 데이터 |
|
|
75
|
+
| `create_task` | **유지** | 순수 데이터 |
|
|
76
|
+
| `update_task` | **유지** | 순수 데이터 |
|
|
77
|
+
| `delete_task` | **유지** | 순수 데이터 |
|
|
78
|
+
| `set_task_status` | **유지** | 순수 데이터 |
|
|
79
|
+
| `get_next_task` | **유지** | 순수 데이터 |
|
|
80
|
+
| `brainstorm_task` | **제거** | `/brainstorm` 스킬이 대체 |
|
|
81
|
+
| `expand_subtasks` | **유지** | 파일 생성만 (AI 없음) |
|
|
82
|
+
| `refine_tasks` | **제거** | `/refine` 스킬이 대체 |
|
|
83
|
+
|
|
84
|
+
### 신규 도구
|
|
85
|
+
|
|
86
|
+
#### `scan_codebase`
|
|
87
|
+
코드베이스를 스캔하여 파일 목록과 시그니처를 반환한다. AI 분석 없음.
|
|
88
|
+
- 내부 구현: `auto-analyzer.ts`의 `scanFiles()` + `sampleFiles()` 호출 (순수 함수)
|
|
89
|
+
- 반환: `{ files: string[], samples: { path: string, content: string, truncated: boolean }[], projectName: string }`
|
|
90
|
+
|
|
91
|
+
#### `save_prd`
|
|
92
|
+
PRD 마크다운을 `.taskflow/prd.md`에 저장한다.
|
|
93
|
+
- 내부 구현: 기존 `savePrd()` 함수 재사용
|
|
94
|
+
- 입력: `{ markdown: string }`
|
|
95
|
+
|
|
96
|
+
#### `read_prd`
|
|
97
|
+
`.taskflow/prd.md`를 읽어서 반환한다.
|
|
98
|
+
- 반환: `{ content: string }` (파일이 없으면 에러)
|
|
99
|
+
|
|
100
|
+
### 유지 도구 (10개)
|
|
101
|
+
- `initialize_project` — 프로젝트 초기화
|
|
102
|
+
- `generate_claude_md` — CLAUDE.md 재생성 (새 도구/스킬 목록 반영하도록 수정 필요)
|
|
103
|
+
- `list_tasks` — 태스크 목록 조회
|
|
104
|
+
- `read_task` — 태스크 상세 조회
|
|
105
|
+
- `create_task` — 태스크 생성
|
|
106
|
+
- `update_task` — 태스크 수정
|
|
107
|
+
- `delete_task` — 태스크 삭제
|
|
108
|
+
- `set_task_status` — 상태 변경
|
|
109
|
+
- `get_next_task` — 다음 태스크 추천
|
|
110
|
+
- `expand_subtasks` — 서브태스크 파일 생성
|
|
111
|
+
|
|
112
|
+
### 제거 대상 코드
|
|
113
|
+
- `src/core/ai/client.ts` — `askClaude()`, `askClaudeWithRetry()`, `brainstormTask()` 전부 제거
|
|
114
|
+
- `@anthropic-ai/claude-agent-sdk` 의존성 제거
|
|
115
|
+
- `src/core/prd/generator.ts` — `startBrainstorm()`, `continueBrainstorm()`, `buildPrdMarkdown()` 제거. `savePrd()` 유지
|
|
116
|
+
- `src/mcp/tools/prd.ts` — `generate_prd`, `brainstorm_prd`, `auto_analyze_prd`, `generate_feature_prd` 제거
|
|
117
|
+
- `src/mcp/tools/brainstorm.ts` — `brainstorm_task` 제거, `expand_subtasks` 유지
|
|
118
|
+
- `src/mcp/tools/refine.ts` — `refine_tasks` 제거 (파일 자체 삭제)
|
|
119
|
+
- `src/mcp/tools/parse.ts` — `parse_prd` 제거 (파일 자체 삭제)
|
|
120
|
+
|
|
121
|
+
> **참고:** `buildPrdMarkdown()`도 제거 대상. 스킬이 Claude Code에게 직접 마크다운을 생성하게 하므로 구조화된 `PrdData` 객체를 마크다운으로 변환하는 함수는 불필요.
|
|
122
|
+
|
|
123
|
+
## 4. 스킬 설계
|
|
124
|
+
|
|
125
|
+
### 4.1 `/prd` — PRD 생성
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
사용자와 대화하며 PRD를 작성합니다.
|
|
129
|
+
|
|
130
|
+
## MCP 도구
|
|
131
|
+
- `mcp__taskflow__scan_codebase` — 코드베이스 분석
|
|
132
|
+
- `mcp__taskflow__save_prd` — PRD 저장
|
|
133
|
+
|
|
134
|
+
## 워크플로우
|
|
135
|
+
1. `scan_codebase`로 현재 프로젝트 상태 파악
|
|
136
|
+
2. 사용자에게 한 번에 하나씩 질문 (한국어):
|
|
137
|
+
- 프로젝트명, 요약, 타겟 사용자, 문제/솔루션
|
|
138
|
+
- 목표/지표, 사용 시나리오, 필수/선택 기능
|
|
139
|
+
- 비기능 요구사항, 기술 스택, 범위, 마일스톤, 리스크
|
|
140
|
+
3. 충분히 수집되면 PRD 마크다운 작성
|
|
141
|
+
4. 사용자 확인 후 `save_prd`로 저장
|
|
142
|
+
|
|
143
|
+
## PRD 형식
|
|
144
|
+
11개 섹션: 제품 개요, 타겟 사용자, 문제/솔루션, 목표/지표,
|
|
145
|
+
시나리오, 기능 요구사항(표), 비기능 요구사항, 기술 스택,
|
|
146
|
+
범위, 마일스톤, 리스크
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 4.2 `/trd` — TRD(Task Implementation Plan) 생성
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
PRD를 기반으로 TRD(구현 계획)를 작성합니다.
|
|
153
|
+
|
|
154
|
+
## MCP 도구
|
|
155
|
+
- `mcp__taskflow__read_prd` — PRD 읽기
|
|
156
|
+
- `mcp__taskflow__list_tasks` — 기존 태스크 확인
|
|
157
|
+
|
|
158
|
+
## 워크플로우
|
|
159
|
+
1. `read_prd`로 PRD 읽기
|
|
160
|
+
2. PRD를 분석하여 구현 단계별 TRD 작성
|
|
161
|
+
3. 각 단계의 기술적 결정사항, 의존성, 리스크 정리
|
|
162
|
+
4. 사용자 확인 후 Claude Code의 Write 도구로 `.taskflow/trd.md`에 저장
|
|
163
|
+
|
|
164
|
+
> TRD 저장은 MCP 도구 없이 Claude Code의 빌트인 Write 도구를 사용한다.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 4.3 `/parse-prd` — PRD → 태스크 분해
|
|
168
|
+
|
|
169
|
+
```markdown
|
|
170
|
+
PRD를 분석하여 태스크를 자동 생성합니다.
|
|
171
|
+
|
|
172
|
+
## MCP 도구
|
|
173
|
+
- `mcp__taskflow__read_prd` — PRD 읽기
|
|
174
|
+
- `mcp__taskflow__list_tasks` — 기존 태스크 확인 (중복 방지)
|
|
175
|
+
- `mcp__taskflow__create_task` — 태스크 생성
|
|
176
|
+
|
|
177
|
+
## 워크플로우
|
|
178
|
+
1. `read_prd`로 PRD 읽기
|
|
179
|
+
2. `list_tasks`로 기존 태스크 확인 (중복 방지)
|
|
180
|
+
3. PRD를 분석하여 최상위 태스크 목록 도출
|
|
181
|
+
4. 각 태스크의 제목, 설명, 우선순위, 의존성 정리
|
|
182
|
+
5. 사용자에게 목록 확인
|
|
183
|
+
6. 승인 후 `create_task`로 하나씩 생성
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 4.4 `/brainstorm` — 태스크 브레인스토밍
|
|
187
|
+
|
|
188
|
+
```markdown
|
|
189
|
+
태스크를 서브태스크로 분해합니다.
|
|
190
|
+
|
|
191
|
+
## MCP 도구
|
|
192
|
+
- `mcp__taskflow__read_task` — 태스크 읽기
|
|
193
|
+
- `mcp__taskflow__list_tasks` — 전체 태스크 맥락 파악
|
|
194
|
+
- `mcp__taskflow__expand_subtasks` — 서브태스크 파일 생성
|
|
195
|
+
|
|
196
|
+
## 워크플로우
|
|
197
|
+
1. 사용자에게 분해할 태스크 ID 확인 (또는 `list_tasks`로 선택)
|
|
198
|
+
2. `read_task`로 태스크 상세 읽기
|
|
199
|
+
3. 사용자와 대화하며 분해 방향 논의
|
|
200
|
+
4. 서브태스크 목록 제안
|
|
201
|
+
5. 사용자 확인 후 `expand_subtasks`로 생성
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 4.5 `/refine` — 요구사항 변경 분석
|
|
205
|
+
|
|
206
|
+
```markdown
|
|
207
|
+
요구사항 변경이 기존 태스크에 미치는 영향을 분석합니다.
|
|
208
|
+
|
|
209
|
+
## MCP 도구
|
|
210
|
+
- `mcp__taskflow__read_prd` — 현재 PRD 읽기
|
|
211
|
+
- `mcp__taskflow__list_tasks` — 전체 태스크 조회
|
|
212
|
+
- `mcp__taskflow__read_task` — 개별 태스크 읽기
|
|
213
|
+
- `mcp__taskflow__update_task` — 태스크 수정
|
|
214
|
+
- `mcp__taskflow__save_prd` — PRD 업데이트
|
|
215
|
+
|
|
216
|
+
## 워크플로우
|
|
217
|
+
1. 사용자에게 변경사항 확인 (대화 또는 파일 diff)
|
|
218
|
+
2. `read_prd` + `list_tasks`로 현재 상태 파악
|
|
219
|
+
3. 영향 받는 태스크 식별 및 변경 방안 제안
|
|
220
|
+
4. 사용자 확인 후 `update_task`로 수정
|
|
221
|
+
5. 필요시 PRD도 업데이트
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 4.6 `/next` — 다음 태스크 추천
|
|
225
|
+
|
|
226
|
+
```markdown
|
|
227
|
+
다음으로 작업할 태스크를 추천합니다.
|
|
228
|
+
|
|
229
|
+
## MCP 도구
|
|
230
|
+
- `mcp__taskflow__get_next_task` — 추천 태스크 조회
|
|
231
|
+
- `mcp__taskflow__read_task` — 상세 정보 읽기
|
|
232
|
+
- `mcp__taskflow__set_task_status` — 상태 변경
|
|
233
|
+
|
|
234
|
+
## 워크플로우
|
|
235
|
+
1. `get_next_task`로 추천 목록 조회
|
|
236
|
+
2. 각 태스크의 이유(의존성 해소, 우선순위)를 설명
|
|
237
|
+
3. 사용자가 선택하면 `set_task_status`로 in-progress 변경
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 4.7 `/task-status` — 진행 상황 요약
|
|
241
|
+
|
|
242
|
+
```markdown
|
|
243
|
+
현재 프로젝트 태스크 진행 상황을 요약합니다.
|
|
244
|
+
|
|
245
|
+
## MCP 도구
|
|
246
|
+
- `mcp__taskflow__list_tasks` — 전체 태스크 조회
|
|
247
|
+
|
|
248
|
+
## 워크플로우
|
|
249
|
+
1. `list_tasks`로 전체 태스크 조회
|
|
250
|
+
2. 상태별 개수, 완료율, 블로커 등 요약
|
|
251
|
+
3. 주요 이슈나 지연된 태스크 하이라이트
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## 5. task init 변경사항
|
|
255
|
+
|
|
256
|
+
기존 `task init` 플로우에 추가:
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
task init
|
|
260
|
+
├─ (기존) .taskflow/ 디렉토리 생성
|
|
261
|
+
├─ (기존) .mcp.json 생성
|
|
262
|
+
├─ (기존) PRD 생성
|
|
263
|
+
├─ (기존) .taskflow/CLAUDE.md 생성
|
|
264
|
+
├─ (기존) 루트 CLAUDE.md에 import 추가
|
|
265
|
+
├─ (신규) .taskflow/.claude/commands/ 에 스킬 파일 생성
|
|
266
|
+
└─ (신규) .claude/commands/ 에 심볼릭 링크 생성
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 심볼릭 링크 생성 로직
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
// src/core/project/skill-setup.ts
|
|
273
|
+
import fs from "node:fs/promises";
|
|
274
|
+
import path from "node:path";
|
|
275
|
+
|
|
276
|
+
const SKILLS = ["prd", "trd", "parse-prd", "brainstorm", "refine", "next", "task-status"];
|
|
277
|
+
|
|
278
|
+
export async function installSkills(projectRoot: string): Promise<void> {
|
|
279
|
+
const srcDir = path.join(projectRoot, ".taskflow", ".claude", "commands");
|
|
280
|
+
const destDir = path.join(projectRoot, ".claude", "commands");
|
|
281
|
+
|
|
282
|
+
await fs.mkdir(srcDir, { recursive: true });
|
|
283
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
284
|
+
|
|
285
|
+
for (const skill of SKILLS) {
|
|
286
|
+
const srcFile = path.join(srcDir, `${skill}.md`);
|
|
287
|
+
const destFile = path.join(destDir, `${skill}.md`);
|
|
288
|
+
|
|
289
|
+
// 원본이 존재하는지 확인
|
|
290
|
+
try { await fs.access(srcFile); } catch { continue; }
|
|
291
|
+
|
|
292
|
+
// 기존 링크/파일이 있으면 스킵
|
|
293
|
+
try { await fs.lstat(destFile); continue; } catch { /* 없으면 생성 */ }
|
|
294
|
+
|
|
295
|
+
const relativePath = path.relative(destDir, srcFile);
|
|
296
|
+
await fs.symlink(relativePath, destFile);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## 6. 점진적 전환 계획
|
|
302
|
+
|
|
303
|
+
### Phase 1: 스킬 생성 + MCP 정리
|
|
304
|
+
1. `.taskflow/.claude/commands/`에 7개 스킬 프롬프트 작성
|
|
305
|
+
2. `task init`에 스킬 설치 + 심볼릭 링크 로직 추가
|
|
306
|
+
3. MCP에서 AI 호출 도구 제거, 순수 데이터 도구로 정리
|
|
307
|
+
4. `src/core/ai/client.ts` 제거, `@anthropic-ai/claude-agent-sdk` 의존성 제거
|
|
308
|
+
|
|
309
|
+
### Phase 2: 스킬 검증
|
|
310
|
+
5. 각 스킬을 Claude Code에서 실행하며 프롬프트 다듬기
|
|
311
|
+
6. MCP 데이터 도구가 스킬과 잘 연동되는지 확인
|
|
312
|
+
|
|
313
|
+
### Phase 3: CLI 정리
|
|
314
|
+
7. AI 워크플로우 CLI 커맨드 제거 (parse-prd, brainstorm, expand, refine)
|
|
315
|
+
8. CLI는 `task init`, `task list`, `task show`, `task status` 등 유틸리티만 남김
|
|
316
|
+
|
|
317
|
+
## 7. 최종 구조
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
.taskflow/
|
|
321
|
+
├── .claude/
|
|
322
|
+
│ └── commands/ ← 스킬 원본
|
|
323
|
+
│ ├── prd.md
|
|
324
|
+
│ ├── trd.md
|
|
325
|
+
│ ├── parse-prd.md
|
|
326
|
+
│ ├── brainstorm.md
|
|
327
|
+
│ ├── refine.md
|
|
328
|
+
│ ├── next.md
|
|
329
|
+
│ └── task-status.md
|
|
330
|
+
├── config.json
|
|
331
|
+
├── prd.md
|
|
332
|
+
├── trd.md
|
|
333
|
+
├── tasks/
|
|
334
|
+
│ └── task-{NNN}.md
|
|
335
|
+
├── index/
|
|
336
|
+
├── logs/
|
|
337
|
+
└── CLAUDE.md
|
|
338
|
+
|
|
339
|
+
.claude/
|
|
340
|
+
└── commands/ ← 심볼릭 링크
|
|
341
|
+
├── prd.md → ../../.taskflow/.claude/commands/prd.md
|
|
342
|
+
├── trd.md → ...
|
|
343
|
+
├── parse-prd.md → ...
|
|
344
|
+
├── brainstorm.md → ...
|
|
345
|
+
├── refine.md → ...
|
|
346
|
+
├── next.md → ...
|
|
347
|
+
└── task-status.md → ...
|
|
348
|
+
|
|
349
|
+
src/
|
|
350
|
+
├── core/ ← 순수 비즈니스 로직 (AI 호출 없음)
|
|
351
|
+
│ ├── project/
|
|
352
|
+
│ ├── prd/ ← buildPrdMarkdown(), savePrd()만 유지
|
|
353
|
+
│ └── task/
|
|
354
|
+
├── mcp/ ← 순수 데이터 도구만
|
|
355
|
+
│ └── tools/
|
|
356
|
+
│ ├── project.ts
|
|
357
|
+
│ ├── task.ts
|
|
358
|
+
│ ├── task-status.ts
|
|
359
|
+
│ ├── prd.ts ← save_prd, read_prd, scan_codebase
|
|
360
|
+
│ └── (brainstorm.ts → expand_subtasks만 유지)
|
|
361
|
+
└── cli/ ← 유틸리티만 (init, list, show, status)
|
|
362
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# /t-create + task run — 브레인스토밍 기반 TRD 생성 및 자동 구현
|
|
2
|
+
|
|
3
|
+
## 개요
|
|
4
|
+
`/t-create` Claude Code 스킬로 브레인스토밍 기반 TRD를 생성하고,
|
|
5
|
+
`task run` CLI로 TRD를 선택하여 태스크 분해 + Ralph Loop 자동 구현하는 시스템.
|
|
6
|
+
|
|
7
|
+
## 아키텍처
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
/t-create (Claude Code 스킬)
|
|
11
|
+
├─ 요구사항 수집 (한 번에 하나, 객관식)
|
|
12
|
+
├─ 접근법 2-3개 제안 + 트레이드오프
|
|
13
|
+
├─ TRD 섹션별 작성 + 사용자 승인
|
|
14
|
+
└─ .taskflow/trd-{기능명}.md 저장
|
|
15
|
+
|
|
16
|
+
task run (CLI)
|
|
17
|
+
├─ .taskflow/trd-*.md 파일 목록 표시
|
|
18
|
+
├─ 사용자가 TRD 선택
|
|
19
|
+
├─ TRD 내용을 읽어서 프롬프트에 주입
|
|
20
|
+
└─ Ralph Loop 셋업 (.claude/ralph-loop.local.md 생성)
|
|
21
|
+
├─ Phase 1: TRD → 태스크 분해 (MCP create_task)
|
|
22
|
+
├─ Phase 2: get_next_task → 구현 → set_task_status 루프
|
|
23
|
+
└─ 모든 태스크 완료 시 종료
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 제거 항목
|
|
27
|
+
- `/create` 스킬 → `/t-create`로 대체
|
|
28
|
+
- `task create` CLI → 제거 (SDK 기반 대화 루프 불필요)
|
|
29
|
+
- `runTaskCreate()`, `TASK_CREATE_SYSTEM_PROMPT` → 제거
|
|
30
|
+
|
|
31
|
+
## 변경 파일
|
|
32
|
+
| 파일 | 변경 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `.taskflow/.claude/commands/t-create.md` | 새 파일 |
|
|
35
|
+
| `src/core/project/skill-templates.ts` | create → t-create 템플릿 교체 |
|
|
36
|
+
| `src/cli/commands/run.ts` | TRD 기반 선택 + Ralph Loop 셋업 |
|
|
37
|
+
| `src/cli/commands/create.ts` | 삭제 |
|
|
38
|
+
| `src/cli/prompts/task-create.md` | 삭제 |
|
|
39
|
+
| `src/cli/index.ts` | registerCreateCommand 제거 |
|
|
40
|
+
| `src/core/ai/claude-client.ts` | runTaskCreate 관련 제거 |
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# task run — 요구사항 단위 자동 구현
|
|
2
|
+
|
|
3
|
+
## 개요
|
|
4
|
+
`task run` CLI 커맨드: 태스크를 `group`(요구사항/기능 단위)으로 묶어 보여주고, 사용자가 선택하면 서브 에이전트(Claude CLI)가 해당 그룹의 모든 태스크를 자동으로 구현한다.
|
|
5
|
+
|
|
6
|
+
## 데이터 모델
|
|
7
|
+
`Task` 타입에 `group?: string` 필드 추가.
|
|
8
|
+
- `task create`로 생성 시 `featureName`이 `group`으로 자동 세팅
|
|
9
|
+
- MCP `create_task`에 `group` 파라미터 추가
|
|
10
|
+
- MCP `get_next_task`에 `group` 필터 추가
|
|
11
|
+
|
|
12
|
+
## CLI 흐름
|
|
13
|
+
```
|
|
14
|
+
$ task run
|
|
15
|
+
📋 요구사항 그룹 목록:
|
|
16
|
+
1. 인증 시스템 (3/5 완료)
|
|
17
|
+
2. CLI 대화 UI 개선 (0/4 완료)
|
|
18
|
+
? 구현할 그룹을 선택하세요: 2
|
|
19
|
+
🚀 서브 에이전트가 작업을 시작합니다...
|
|
20
|
+
[Claude CLI가 stdio: inherit로 실행 — 완전 자동, 태스크 연속 구현]
|
|
21
|
+
✅ 완료!
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 서브 에이전트 실행 구조
|
|
25
|
+
- `spawnClaude(flags)` — `stdio: 'inherit'`
|
|
26
|
+
- `--system-prompt-file` — 그룹 태스크 구현 전용 프롬프트
|
|
27
|
+
- `--mcp-config` — TaskFlow MCP 서버 (임시 mcp.json)
|
|
28
|
+
- CLAUDE.md 간섭은 코딩 작업에 오히려 도움
|
|
29
|
+
|
|
30
|
+
## 서브 에이전트 프롬프트 (`task-run.md`)
|
|
31
|
+
- 그룹명과 태스크 목록을 주입
|
|
32
|
+
- MCP `get_next_task(group)` → `set_task_status(in-progress)` → 구현 → `set_task_status(done)` 루프
|
|
33
|
+
- 그룹 내 모든 태스크 완료 시 종료
|
|
34
|
+
|
|
35
|
+
## 변경 파일
|
|
36
|
+
| 파일 | 변경 |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `src/features/taskflow/types.ts` | `group?: string` 추가 |
|
|
39
|
+
| `src/features/taskflow/lib/repository.ts` | createTask에서 group 처리 |
|
|
40
|
+
| `src/mcp/tools/task.ts` | create_task에 group, get_next_task에 group 필터 |
|
|
41
|
+
| `src/core/ai/claude-client.ts` | runTaskCreate에서 group 포함하여 createTask 호출 |
|
|
42
|
+
| `src/cli/commands/run.ts` | **새 파일** — 그룹 선택 UI + spawnClaude |
|
|
43
|
+
| `src/cli/prompts/task-run.md` | **새 파일** — 서브 에이전트 프롬프트 |
|
|
44
|
+
| `src/cli/index.ts` | registerRunCommand 추가 |
|
package/docs/tdd.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Test-Driven Development
|
|
2
|
+
|
|
3
|
+
## Philosophy
|
|
4
|
+
- Write tests first for new features and bug fixes
|
|
5
|
+
- Tests document behavior — they are living specifications
|
|
6
|
+
- Fast feedback: unit tests should run in <1s per file
|
|
7
|
+
|
|
8
|
+
## Test Pyramid
|
|
9
|
+
1. **Unit tests** (Vitest) — core logic, utils, schemas
|
|
10
|
+
2. **Integration tests** (Vitest) — API routes, database queries
|
|
11
|
+
3. **E2E tests** (Playwright) — critical user flows only
|
|
12
|
+
|
|
13
|
+
## Conventions
|
|
14
|
+
- Co-locate tests: `*.test.ts` next to source or in `__tests__/`
|
|
15
|
+
- Use `describe` blocks to group by function/scenario
|
|
16
|
+
- Test names: `it('should {expected behavior} when {condition}')`
|
|
17
|
+
- One assertion concept per test
|
|
18
|
+
|
|
19
|
+
## Patterns
|
|
20
|
+
```typescript
|
|
21
|
+
// Arrange
|
|
22
|
+
const input = createMockTask({ status: 'todo' });
|
|
23
|
+
|
|
24
|
+
// Act
|
|
25
|
+
const result = updateTaskStatus(input, 'in-progress');
|
|
26
|
+
|
|
27
|
+
// Assert
|
|
28
|
+
expect(result.status).toBe('in-progress');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## What to Test
|
|
32
|
+
- Business logic and transformations
|
|
33
|
+
- Edge cases and error paths
|
|
34
|
+
- Schema validation (Zod)
|
|
35
|
+
- API response shapes
|
|
36
|
+
|
|
37
|
+
## What NOT to Test
|
|
38
|
+
- Framework internals (Next.js routing, React rendering)
|
|
39
|
+
- Third-party library behavior
|
|
40
|
+
- Implementation details (private functions, internal state)
|
|
41
|
+
- Trivial getters/setters
|
package/package.json
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kmgeon/taskflow",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"task": "./bin/task.mjs",
|
|
7
|
+
"task-mcp": "./bin/task-mcp.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"src/",
|
|
12
|
+
"docs/"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"task": "tsx src/cli/index.ts",
|
|
16
|
+
"dev": "next dev --turbopack -p 4000",
|
|
17
|
+
"build": "next build",
|
|
18
|
+
"start": "next start -p 4000",
|
|
19
|
+
"lint": "next lint",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"test:ui": "vitest --ui",
|
|
23
|
+
"test:coverage": "vitest run --coverage",
|
|
24
|
+
"test:e2e": "playwright test",
|
|
25
|
+
"test:e2e:watch": "playwright test --ui",
|
|
26
|
+
"test:e2e:headed": "playwright test --headed",
|
|
27
|
+
"test:all": "run-p test test:e2e",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.81",
|
|
32
|
+
"@anthropic-ai/claude-code": "^2.1.81",
|
|
33
|
+
"@dnd-kit/core": "^6.3.1",
|
|
34
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
35
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
36
|
+
"@hookform/resolvers": "^4",
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
38
|
+
"@radix-ui/react-accordion": "^1.2.3",
|
|
39
|
+
"@radix-ui/react-avatar": "^1.1.2",
|
|
40
|
+
"@radix-ui/react-checkbox": "^1.1.1",
|
|
41
|
+
"@radix-ui/react-dialog": "^1.1.4",
|
|
42
|
+
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
|
43
|
+
"@radix-ui/react-label": "^2.1.0",
|
|
44
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
45
|
+
"@radix-ui/react-select": "^2.1.4",
|
|
46
|
+
"@radix-ui/react-separator": "^1.1.1",
|
|
47
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
48
|
+
"@radix-ui/react-toast": "^1.2.6",
|
|
49
|
+
"@supabase/ssr": "^0.5.2",
|
|
50
|
+
"@supabase/supabase-js": "^2.58.0",
|
|
51
|
+
"@tanstack/react-query": "^5",
|
|
52
|
+
"axios": "^1.7.9",
|
|
53
|
+
"boxen": "^8.0.1",
|
|
54
|
+
"chalk": "^5.6.2",
|
|
55
|
+
"chokidar": "^5.0.0",
|
|
56
|
+
"class-variance-authority": "^0.7.0",
|
|
57
|
+
"cli-table3": "^0.6.5",
|
|
58
|
+
"clsx": "^2.1.1",
|
|
59
|
+
"commander": "^14.0.3",
|
|
60
|
+
"date-fns": "^4",
|
|
61
|
+
"diff": "^8.0.3",
|
|
62
|
+
"es-toolkit": "^1",
|
|
63
|
+
"fast-glob": "^3.3.3",
|
|
64
|
+
"framer-motion": "^11",
|
|
65
|
+
"gray-matter": "^4.0.3",
|
|
66
|
+
"hono": "^4.9.9",
|
|
67
|
+
"inquirer": "^13.3.2",
|
|
68
|
+
"lucide-react": "^0.469.0",
|
|
69
|
+
"next": "15.1.0",
|
|
70
|
+
"next-themes": "^0.4.3",
|
|
71
|
+
"ora": "^9.3.0",
|
|
72
|
+
"react": "^19.0.0",
|
|
73
|
+
"react-dom": "^19.0.0",
|
|
74
|
+
"react-hook-form": "^7",
|
|
75
|
+
"react-use": "^17",
|
|
76
|
+
"remark-parse": "^11.0.0",
|
|
77
|
+
"server-only": "0.0.1",
|
|
78
|
+
"sql.js": "^1.14.1",
|
|
79
|
+
"ts-pattern": "^5",
|
|
80
|
+
"unified": "^11.0.5",
|
|
81
|
+
"tsx": "^4.20.6",
|
|
82
|
+
"zod": "^4",
|
|
83
|
+
"zustand": "^4"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@eslint/eslintrc": "^3",
|
|
87
|
+
"@playwright/test": "^1.56.0",
|
|
88
|
+
"@tailwindcss/postcss": "^4.1.13",
|
|
89
|
+
"@tailwindcss/typography": "^0.5.10",
|
|
90
|
+
"@testing-library/dom": "^10.4.1",
|
|
91
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
92
|
+
"@testing-library/react": "^16.3.0",
|
|
93
|
+
"@testing-library/user-event": "^14.6.1",
|
|
94
|
+
"@types/diff": "^8.0.0",
|
|
95
|
+
"@types/mdast": "^4.0.4",
|
|
96
|
+
"@types/node": "^20",
|
|
97
|
+
"@types/react": "^19",
|
|
98
|
+
"@types/react-dom": "^19",
|
|
99
|
+
"@vitejs/plugin-react": "^5.0.4",
|
|
100
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
101
|
+
"@vitest/ui": "^3.2.4",
|
|
102
|
+
"dotenv-cli": "^10.0.0",
|
|
103
|
+
"eslint": "^9",
|
|
104
|
+
"eslint-config-next": "15.1.0",
|
|
105
|
+
"happy-dom": "^19.0.2",
|
|
106
|
+
"npm-run-all": "^4.1.5",
|
|
107
|
+
"postcss": "^8",
|
|
108
|
+
"tailwind-merge": "^2.5.2",
|
|
109
|
+
"tailwindcss": "^4.1.13",
|
|
110
|
+
"tailwindcss-animate": "^1.0.7",
|
|
111
|
+
"typescript": "^5",
|
|
112
|
+
"vitest": "^3.2.4"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { AppLayout } from "@/components/layout/AppLayout";
|
|
3
|
+
|
|
4
|
+
type ProtectedLayoutProps = {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default function ProtectedLayout({ children }: ProtectedLayoutProps) {
|
|
9
|
+
return <AppLayout>{children}</AppLayout>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { handle } from 'hono/vercel';
|
|
2
|
+
import { createHonoApp } from '@/backend/hono/app';
|
|
3
|
+
|
|
4
|
+
const app = createHonoApp();
|
|
5
|
+
|
|
6
|
+
export const GET = handle(app);
|
|
7
|
+
export const POST = handle(app);
|
|
8
|
+
export const PUT = handle(app);
|
|
9
|
+
export const PATCH = handle(app);
|
|
10
|
+
export const DELETE = handle(app);
|
|
11
|
+
export const OPTIONS = handle(app);
|
|
12
|
+
|
|
13
|
+
export const runtime = 'nodejs';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ExampleStatus } from '@/features/example/components/example-status';
|
|
4
|
+
|
|
5
|
+
export default function ExamplePage() {
|
|
6
|
+
return (
|
|
7
|
+
<div className="min-h-screen bg-gradient-to-b from-slate-950 via-slate-900 to-slate-950 px-6 py-16 text-slate-100">
|
|
8
|
+
<ExampleStatus />
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
Binary file
|