@purpleraven/hits 0.2.0

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.
Files changed (58) hide show
  1. package/AGENTS.md +298 -0
  2. package/LICENSE +190 -0
  3. package/README.md +336 -0
  4. package/bin/hits.js +56 -0
  5. package/config/schema.json +94 -0
  6. package/config/settings.yaml +102 -0
  7. package/data/dev_handover.yaml +143 -0
  8. package/hits_core/__init__.py +9 -0
  9. package/hits_core/ai/__init__.py +11 -0
  10. package/hits_core/ai/compressor.py +86 -0
  11. package/hits_core/ai/llm_client.py +65 -0
  12. package/hits_core/ai/slm_filter.py +126 -0
  13. package/hits_core/api/__init__.py +3 -0
  14. package/hits_core/api/routes/__init__.py +8 -0
  15. package/hits_core/api/routes/auth.py +211 -0
  16. package/hits_core/api/routes/handover.py +117 -0
  17. package/hits_core/api/routes/health.py +8 -0
  18. package/hits_core/api/routes/knowledge.py +177 -0
  19. package/hits_core/api/routes/node.py +121 -0
  20. package/hits_core/api/routes/work_log.py +174 -0
  21. package/hits_core/api/server.py +181 -0
  22. package/hits_core/auth/__init__.py +21 -0
  23. package/hits_core/auth/dependencies.py +61 -0
  24. package/hits_core/auth/manager.py +368 -0
  25. package/hits_core/auth/middleware.py +69 -0
  26. package/hits_core/collector/__init__.py +18 -0
  27. package/hits_core/collector/ai_session_collector.py +118 -0
  28. package/hits_core/collector/base.py +73 -0
  29. package/hits_core/collector/daemon.py +94 -0
  30. package/hits_core/collector/git_collector.py +177 -0
  31. package/hits_core/collector/hits_action_collector.py +110 -0
  32. package/hits_core/collector/shell_collector.py +178 -0
  33. package/hits_core/main.py +36 -0
  34. package/hits_core/mcp/__init__.py +20 -0
  35. package/hits_core/mcp/server.py +429 -0
  36. package/hits_core/models/__init__.py +18 -0
  37. package/hits_core/models/node.py +56 -0
  38. package/hits_core/models/tree.py +68 -0
  39. package/hits_core/models/work_log.py +64 -0
  40. package/hits_core/models/workflow.py +92 -0
  41. package/hits_core/platform/__init__.py +5 -0
  42. package/hits_core/platform/actions.py +225 -0
  43. package/hits_core/service/__init__.py +6 -0
  44. package/hits_core/service/handover_service.py +382 -0
  45. package/hits_core/service/knowledge_service.py +172 -0
  46. package/hits_core/service/tree_service.py +105 -0
  47. package/hits_core/storage/__init__.py +11 -0
  48. package/hits_core/storage/base.py +84 -0
  49. package/hits_core/storage/file_store.py +314 -0
  50. package/hits_core/storage/redis_store.py +123 -0
  51. package/hits_web/dist/assets/index-Bgx7F6m6.css +1 -0
  52. package/hits_web/dist/assets/index-D1B5E67G.js +3 -0
  53. package/hits_web/dist/index.html +16 -0
  54. package/package.json +60 -0
  55. package/requirements-core.txt +7 -0
  56. package/requirements.txt +1 -0
  57. package/run.sh +271 -0
  58. package/server.js +234 -0
package/README.md ADDED
@@ -0,0 +1,336 @@
1
+ # HITS - Hybrid Intel Trace System
2
+
3
+ > AI를 가장 적게 쓰면서, 전임자의 뇌를 가장 완벽하게 복제하는 시스템
4
+
5
+ ## 개요
6
+
7
+ HITS는 기업의 핵심 지식과 의사결정 맥락을 보존하기 위한 하이브리드 지식 관리 시스템입니다. AI 도구 간(Claude, OpenCode, Cursor 등) 세션 전환 시 프로젝트별 인수인계를 자동화합니다.
8
+
9
+ ### 핵심 가치
10
+
11
+ - **토큰 최적화**: AI 비용 절감을 위한 시멘틱 압축과 온디맨드 분석
12
+ - **맥락 보존**: Why-How-What 계층 구조로 의사결정 과정 저장
13
+ - **실패 경험**: Negative Path로 실패한 접근법도 함께 기록
14
+ - **보안 강화**: Argon2id 해싱, JWT HttpOnly 쿠키, CSP, Rate Limiting
15
+ - **AI 세션 인수인계**: 토큰 한계로 AI 교체 시 프로젝트별 컨텍스트 자동 전달
16
+ - **중앙 집중 저장**: `~/.hits/data/`에 모든 AI 도구의 작업 기록이 통합 저장
17
+ - **프로젝트별 격리**: 프로젝트 경로 기반으로 완전히 독립된 컨텍스트 관리
18
+
19
+ ## 기술 스택
20
+
21
+ | 영역 | 기술 |
22
+ |------|------|
23
+ | **백엔드** | Python 3.10+, FastAPI, Pydantic v2 |
24
+ | **프론트엔드** | Svelte 5, Vite, TypeScript |
25
+ | **인증** | Argon2id (비밀번호), JWT HS256 (HttpOnly 쿠키) |
26
+ | **저장소** | 파일 기반 (`~/.hits/data/`), Redis (선택) |
27
+ | **보안** | CSP, CORS, Rate Limiting, Secure Headers |
28
+
29
+ ## 설치
30
+
31
+ ### 요구사항
32
+
33
+ - Python 3.10 이상
34
+ - Node.js 18+ (프론트엔드 빌드용)
35
+ - Redis (선택사항, 없으면 파일 저장소 사용)
36
+
37
+ ### 빠른 시작
38
+
39
+ ```bash
40
+ cd hits
41
+ ./run.sh # 자동 설치 + 서버 시작
42
+ ```
43
+
44
+ #### 개발 모드
45
+
46
+ ```bash
47
+ ./run.sh --dev # Vite HMR + FastAPI 백엔드
48
+ ```
49
+
50
+ #### 수동 설치
51
+
52
+ ```bash
53
+ # Python 환경
54
+ python3 -m venv venv
55
+ source venv/bin/activate
56
+ pip install -r requirements.txt
57
+
58
+ # 프론트엔드 빌드
59
+ cd hits_web
60
+ npm install
61
+ npm run build
62
+ cd ..
63
+
64
+ # 서버 실행
65
+ python -m hits_core.main --port 8765
66
+ ```
67
+
68
+ ## 보안
69
+
70
+ ### 인증 시스템
71
+
72
+ | 기능 | 구현 |
73
+ |------|------|
74
+ | **비밀번호 해싱** | Argon2id (memory=64MB, iterations=3, parallelism=1) |
75
+ | **비밀번호 최소 길이** | 8자 |
76
+ | **JWT 토큰** | HttpOnly + Secure + SameSite=Lax 쿠키 |
77
+ | **액세스 토큰** | 15분 만료 |
78
+ | **리프레시 토큰** | 7일 만료, `/api/auth/refresh` 경로에서만 전송 |
79
+ | **첫 사용자** | 자동으로 admin 역할 부여 |
80
+ | **이후 사용자** | admin만 생성 가능 |
81
+
82
+ ### 보안 헤더
83
+
84
+ ```
85
+ Content-Security-Policy: default-src 'self'; script-src 'self'; ...
86
+ X-Content-Type-Options: nosniff
87
+ X-Frame-Options: DENY
88
+ Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
89
+ Referrer-Policy: strict-origin-when-cross-origin
90
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
91
+ ```
92
+
93
+ ### Rate Limiting
94
+
95
+ - 로그인 엔드포인트: 10회/분 (IP 기준)
96
+ - 429 Too Many Requests 응답으로 제한
97
+
98
+ ### 데이터 보호
99
+
100
+ | 항목 | 권한 | 설명 |
101
+ |------|------|------|
102
+ | `~/.hits/.auth/users.json` | 600 | 사용자 데이터 (소유자만) |
103
+ | `~/.hits/.pepper` | 600 | HMAC 페퍼 (소유자만) |
104
+ | `~/.hits/.jwt_secret` | 600 | JWT 서명 키 (소유자만) |
105
+ | `~/.hits/.auth/` | 700 | 인증 디렉토리 (소유자만) |
106
+
107
+ ## 웹 UI
108
+
109
+ ### 화면 구성
110
+
111
+ ```
112
+ ┌─────────────┬───────────────────────────────────┐
113
+ │ 사이드바 │ 헤더 (탭 + 사용자 메뉴) │
114
+ │ ├───────────────────────────────────┤
115
+ │ 📂 프로젝트 │ │
116
+ │ ────────── │ 메인 컨텐츠 영역 │
117
+ │ /project-a │ │
118
+ │ /project-b │ 📋 지식 트리 | 📝 타임라인 | 🔄 인수인계 │
119
+ │ /project-c │ │
120
+ │ │ │
121
+ └─────────────┴───────────────────────────────────┘
122
+ ```
123
+
124
+ ### 주요 기능
125
+
126
+ - **지식 트리**: 카테고리별 Why-How-What 노드 관리 (CRUD)
127
+ - **타임라인**: 프로젝트별 작업 기록, 날짜별 그룹핑, 검색
128
+ - **인수인계**: 프로젝트 선택 시 자동 생성된 인수인계 요약
129
+ - **프로젝트 전환**: 사이드바에서 프로젝트 선택으로 즉시 전환
130
+ - **사용자 관리**: 비밀번호 변경, 로그아웃
131
+
132
+ ## AI 세션 인수인계
133
+
134
+ ### 작동 방식
135
+
136
+ ```
137
+ [OpenCode 세션] [Claude 세션]
138
+ │ │
139
+ 작업 수행 세션 시작
140
+ │ │
141
+ 작업 기록 ──────────────────────→ 인수인계 조회
142
+ POST /api/work-log GET /api/handover
143
+ project_path: /my-project project_path: /my-project
144
+ │ │
145
+ └──→ ~/.hits/data/ ←──┘ │
146
+ (중앙 집중) 이전 컨텍스트 파악
147
+
148
+ 작업 이어서 수행
149
+ ```
150
+
151
+ ### MCP 설정
152
+
153
+ OpenCode 또는 Claude의 MCP 설정에 추가:
154
+
155
+ ```json
156
+ {
157
+ "hits": {
158
+ "type": "local",
159
+ "command": ["python", "-m", "hits_core.mcp.server"],
160
+ "cwd": "/path/to/hits"
161
+ }
162
+ }
163
+ ```
164
+
165
+ MCP 툴:
166
+ - `hits_record_work`: 작업 기록
167
+ - `hits_get_handover`: 인수인계 요약
168
+ - `hits_search_works`: 작업 검색
169
+ - `hits_list_projects`: 프로젝트 목록
170
+ - `hits_get_recent`: 최근 작업
171
+
172
+ ## API 엔드포인트
173
+
174
+ ### 인증
175
+
176
+ | Method | Path | Description |
177
+ |--------|------|-------------|
178
+ | GET | `/api/auth/status` | 인증 상태 확인 |
179
+ | POST | `/api/auth/register` | 사용자 등록 |
180
+ | POST | `/api/auth/login` | 로그인 (HttpOnly 쿠키 설정) |
181
+ | POST | `/api/auth/logout` | 로그아웃 |
182
+ | POST | `/api/auth/refresh` | 액세스 토큰 갱신 |
183
+ | GET | `/api/auth/me` | 현재 사용자 정보 |
184
+ | PUT | `/api/auth/password` | 비밀번호 변경 |
185
+
186
+ ### 작업 기록
187
+
188
+ | Method | Path | Description |
189
+ |--------|------|-------------|
190
+ | POST | `/api/work-log` | 작업 기록 생성 |
191
+ | GET | `/api/work-logs` | 작업 목록 (`project_path` 필터) |
192
+ | GET | `/api/work-logs/search?q=...` | 작업 검색 |
193
+ | GET | `/api/work-log/{id}` | 단건 조회 |
194
+ | PUT | `/api/work-log/{id}` | 수정 |
195
+ | DELETE | `/api/work-log/{id}` | 삭제 |
196
+
197
+ ### 인수인계
198
+
199
+ | Method | Path | Description |
200
+ |--------|------|-------------|
201
+ | GET | `/api/handover?project_path=...` | 프로젝트별 인수인계 요약 |
202
+ | GET | `/api/handover/projects` | 프로젝트 목록 |
203
+ | GET | `/api/handover/project-stats?project_path=...` | 프로젝트 통계 |
204
+
205
+ ### 지식 카테고리
206
+
207
+ | Method | Path | Description |
208
+ |--------|------|-------------|
209
+ | GET | `/api/knowledge/categories` | 카테고리 목록 |
210
+ | POST | `/api/knowledge/category` | 카테고리 생성 |
211
+ | PUT | `/api/knowledge/category/{name}` | 카테고리 수정 |
212
+ | DELETE | `/api/knowledge/category/{name}` | 카테고리 삭제 |
213
+ | POST | `/api/knowledge/category/{name}/nodes` | 노드 추가 |
214
+ | PUT | `/api/knowledge/category/{name}/nodes/{idx}` | 노드 수정 |
215
+ | DELETE | `/api/knowledge/category/{name}/nodes/{idx}` | 노드 삭제 |
216
+
217
+ ### performed_by 규칙
218
+
219
+ | AI 도구 | 값 |
220
+ |---------|-----|
221
+ | OpenCode | `opencode` |
222
+ | Claude Code | `claude` |
223
+ | Cursor | `cursor` |
224
+ | 사용자 직접 | `manual` |
225
+
226
+ ## 아키텍처
227
+
228
+ ```
229
+ ┌──────────────────────────────────────────────────────────┐
230
+ │ hits_web (Svelte 5 + Vite) │
231
+ │ Material Dark 테마 · TypeScript │
232
+ │ ┌──────────┬──────────┬──────────────────────────┐ │
233
+ │ │ Sidebar │ Knowledge│ HandoverPanel │ │
234
+ │ │ Projects │ Tree │ 인수인계 요약 뷰 │ │
235
+ │ │ Filter │ Timeline │ │ │
236
+ │ └──────────┴──────────┴──────────────────────────┘ │
237
+ │ ↕ API Client (fetch + HttpOnly cookies) │
238
+ ├──────────────────────────────────────────────────────────┤
239
+ │ hits_core (Apache 2.0) │
240
+ │ ┌──────────┬──────────┬──────────┬──────────┐ │
241
+ │ │ Models │ Storage │ AI │ Auth │ │
242
+ │ │ Tree │ Redis │ Compress │ Argon2id │ │
243
+ │ │ Node │ File │ SLM/LLM │ JWT │ │
244
+ │ │ WorkLog │(~/.hits) │ Filter │ Middleware│ │
245
+ │ └──────────┴──────────┴──────────┴──────────┘ │
246
+ │ ┌──────────┬──────────┬──────────┐ │
247
+ │ │ API │ Collector│ MCP │ │
248
+ │ │ FastAPI │ Git/Shell│ Server │ │
249
+ │ │ + Static │ AI Sess. │ 5 Tools │ │
250
+ │ │ Serve │ │ │ │
251
+ │ └──────────┴──────────┴──────────┘ │
252
+ │ ┌──────────────────────────────┐ │
253
+ │ │ Service Layer │ │
254
+ │ │ TreeService HandoverService│ │
255
+ │ │ KnowledgeService │ │
256
+ │ └──────────────────────────────┘ │
257
+ └──────────────────────────────────────────────────────────┘
258
+ ```
259
+
260
+ ## 지식 트리 구조
261
+
262
+ ### Why-How-What 계층
263
+
264
+ ```
265
+ ├── WHY (의도/목적)
266
+ │ ├── "왜 이 시스템을 만들었나?"
267
+ │ └── "비즈니스 목표가 무엇인가?"
268
+
269
+ ├── HOW (논리/방법)
270
+ │ ├── "어떻게 구현했나?"
271
+ │ └── "어떤 의사결정을 내렸나?"
272
+
273
+ └── WHAT (실행/작업)
274
+ ├── "구체적으로 무엇을 하나?"
275
+ └── "실행 가능한 액션"
276
+ ```
277
+
278
+ ## 개발
279
+
280
+ ### 개발 모드
281
+
282
+ ```bash
283
+ ./run.sh --dev # Vite HMR + FastAPI
284
+ ```
285
+
286
+ ### 테스트
287
+
288
+ ```bash
289
+ ./run.sh --test # pytest 실행
290
+ ```
291
+
292
+ ### 프론트엔드 개발
293
+
294
+ ```bash
295
+ cd hits_web
296
+ npm install # 의존성 설치
297
+ npm run dev # Vite 개발 서버 (http://localhost:5173)
298
+ npm run build # 프로덕션 빌드
299
+ ```
300
+
301
+ ## 라이선스
302
+
303
+ | 패키지 | 라이선스 | 상업적 사용 |
304
+ |--------|---------|-------------|
305
+ | `hits_core` | Apache 2.0 | ✅ 자유로움 |
306
+ | `hits_web` | Apache 2.0 | ✅ 자유로움 |
307
+
308
+ ## 문제 해결
309
+
310
+ ### Node.js가 없습니다
311
+
312
+ ```bash
313
+ # Ubuntu/Debian
314
+ curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
315
+ sudo apt install -y nodejs
316
+ ```
317
+
318
+ ### Redis 연결 실패
319
+
320
+ Redis 없이도 HITS는 정상 작동합니다. 파일 기반 저장소를 자동으로 사용합니다.
321
+
322
+ ### 데이터가 어디에 저장되나요?
323
+
324
+ ```
325
+ ~/.hits/
326
+ ├── data/ ← 모든 데이터의 기본 위치
327
+ │ ├── work_logs/ ← AI 세션 작업 기록
328
+ │ ├── trees/ ← 지식 트리
329
+ │ └── workflows/ ← 워크플로우
330
+ ├── .auth/ ← 인증 데이터
331
+ │ └── users.json ← 사용자 정보 (권한 600)
332
+ ├── .pepper ← HMAC 페퍼 (권한 600)
333
+ └── .jwt_secret ← JWT 서명 키 (권한 600)
334
+
335
+ HITS_DATA_PATH 환경변수로 경로 변경 가능
336
+ ```
package/bin/hits.js ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * HITS CLI - starts the web server.
5
+ *
6
+ * Usage:
7
+ * npx hits → start production server
8
+ * npx hits --dev → start in development mode
9
+ * npx hits --setup → install Python deps + build frontend
10
+ * npx hits --port 9000 → use custom port
11
+ * npx hits --help
12
+ */
13
+
14
+ import { parseArgs } from 'node:util';
15
+ import { startServer } from '../server.js';
16
+
17
+ const { values } = parseArgs({
18
+ options: {
19
+ port: { type: 'string', short: 'p' },
20
+ dev: { type: 'boolean', short: 'd', default: false },
21
+ setup: { type: 'boolean', short: 's', default: false },
22
+ help: { type: 'boolean', short: 'h', default: false },
23
+ },
24
+ strict: true,
25
+ });
26
+
27
+ if (values.help) {
28
+ console.log(`
29
+ HITS - Hybrid Intel Trace System
30
+
31
+ Usage:
32
+ npx hits [options]
33
+
34
+ Options:
35
+ -p, --port <port> Server port (default: 8765)
36
+ -d, --dev Development mode (verbose logging)
37
+ -s, --setup Install dependencies only
38
+ -h, --help Show this help
39
+
40
+ Environment:
41
+ HITS_PORT Server port override
42
+ HITS_PYTHON Path to python executable (default: auto-detect)
43
+ `);
44
+ process.exit(0);
45
+ }
46
+
47
+ const port = parseInt(values.port || process.env.HITS_PORT || '8765', 10);
48
+
49
+ startServer({
50
+ port,
51
+ dev: values.dev,
52
+ setupOnly: values.setup,
53
+ }).catch((err) => {
54
+ console.error('Fatal:', err.message);
55
+ process.exit(1);
56
+ });
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "HITS Configuration Schema",
4
+ "description": "Configuration schema for HITS - Hybrid Intel Trace System",
5
+ "type": "object",
6
+ "properties": {
7
+ "settings": {
8
+ "type": "object",
9
+ "properties": {
10
+ "edge": {
11
+ "type": "string",
12
+ "enum": ["left", "right"],
13
+ "default": "right",
14
+ "description": "Panel edge position"
15
+ },
16
+ "width": {
17
+ "type": "integer",
18
+ "minimum": 200,
19
+ "maximum": 600,
20
+ "default": 340,
21
+ "description": "Panel width in pixels"
22
+ },
23
+ "tab_label": {
24
+ "type": "string",
25
+ "default": "🌳",
26
+ "description": "Tab button label (emoji or text)"
27
+ },
28
+ "storage": {
29
+ "type": "string",
30
+ "enum": ["auto", "redis", "file"],
31
+ "default": "auto",
32
+ "description": "Storage backend. 'auto' uses Redis if available, falls back to file"
33
+ },
34
+ "font": {
35
+ "type": "object",
36
+ "properties": {
37
+ "auto_detect": {
38
+ "type": "boolean",
39
+ "default": true,
40
+ "description": "Auto-detect best Korean font"
41
+ },
42
+ "family": {
43
+ "type": ["string", "null"],
44
+ "default": null,
45
+ "description": "Override font family name"
46
+ },
47
+ "size": {
48
+ "type": "integer",
49
+ "minimum": 8,
50
+ "maximum": 24,
51
+ "default": 10
52
+ }
53
+ }
54
+ }
55
+ }
56
+ },
57
+ "project_paths": {
58
+ "type": "array",
59
+ "items": {"type": "string"},
60
+ "description": "List of project directory paths to monitor for Git activity"
61
+ },
62
+ "categories": {
63
+ "type": "array",
64
+ "items": {
65
+ "type": "object",
66
+ "required": ["name", "icon", "items"],
67
+ "properties": {
68
+ "name": {"type": "string"},
69
+ "icon": {"type": "string"},
70
+ "items": {
71
+ "type": "array",
72
+ "items": {
73
+ "type": "object",
74
+ "required": ["name", "layer", "type", "action"],
75
+ "properties": {
76
+ "name": {"type": "string"},
77
+ "layer": {
78
+ "type": "string",
79
+ "enum": ["why", "how", "what"]
80
+ },
81
+ "type": {
82
+ "type": "string",
83
+ "enum": ["url", "shell", "app"]
84
+ },
85
+ "action": {"type": "string"},
86
+ "negative_path": {"type": "boolean", "default": false}
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,102 @@
1
+ # HITS Configuration
2
+
3
+ settings:
4
+ edge: right
5
+ width: 340
6
+ tab_label: "🌳"
7
+ storage: auto
8
+
9
+ font:
10
+ auto_detect: true
11
+ family: null
12
+ size: 10
13
+
14
+ categories:
15
+ - name: 배포 파이프라인
16
+ icon: 🚀
17
+ items:
18
+ - name: CI/CD 흐름 이해
19
+ layer: why
20
+ type: url
21
+ action: https://docs.example.com/cicd
22
+ - name: Jenkins 빌드 설정
23
+ layer: how
24
+ type: url
25
+ action: https://jenkins.example.com/configure
26
+ - name: 프로덕션 배포 실행
27
+ layer: what
28
+ type: shell
29
+ action: bash ~/scripts/deploy.sh production
30
+ - name: 롤백 절차
31
+ layer: how
32
+ type: url
33
+ action: https://docs.example.com/rollback
34
+ negative_path: true
35
+
36
+ - name: 장애 대응
37
+ icon: 🔥
38
+ items:
39
+ - name: 장애 감지 및 알림
40
+ layer: why
41
+ type: url
42
+ action: https://monitoring.example.com/alerts
43
+ - name: 로그 분석 방법
44
+ layer: how
45
+ type: shell
46
+ action: bash ~/scripts/analyze_logs.sh
47
+ - name: 서비스 재시작
48
+ layer: what
49
+ type: shell
50
+ action: bash ~/scripts/restart_service.sh
51
+ - name: 장애 보고서 작성
52
+ layer: what
53
+ type: url
54
+ action: https://docs.google.com/document/create
55
+
56
+ - name: 코드베이스 구조
57
+ icon: 📋
58
+ items:
59
+ - name: 아키텍처 개요
60
+ layer: why
61
+ type: url
62
+ action: https://wiki.example.com/architecture
63
+ - name: 모듈 의존성
64
+ layer: how
65
+ type: url
66
+ action: https://wiki.example.com/dependencies
67
+ - name: 주요 API 엔드포인트
68
+ layer: what
69
+ type: url
70
+ action: https://api.example.com/docs
71
+
72
+ - name: 테스트 가이드
73
+ icon: 🧪
74
+ items:
75
+ - name: 테스트 전략
76
+ layer: why
77
+ type: url
78
+ action: https://wiki.example.com/test-strategy
79
+ - name: 단위 테스트 작성법
80
+ layer: how
81
+ type: shell
82
+ action: pytest tests/ -v
83
+ - name: 통합 테스트 실행
84
+ layer: what
85
+ type: shell
86
+ action: pytest tests/integration/ -v
87
+
88
+ - name: 보안 & 권한
89
+ icon: 🔐
90
+ items:
91
+ - name: 보안 정책
92
+ layer: why
93
+ type: url
94
+ action: https://wiki.example.com/security
95
+ - name: SSH 키 관리
96
+ layer: how
97
+ type: shell
98
+ action: ssh-add -l
99
+ - name: 비밀번호 변경
100
+ layer: what
101
+ type: url
102
+ action: https://account.example.com/password