@tienne/gestalt 0.6.0 → 0.8.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.
- package/CLAUDE.md +13 -2
- package/README.ko.md +136 -3
- package/README.md +163 -11
- package/dist/package.json +2 -1
- package/dist/src/cli/commands/interview.d.ts +1 -0
- package/dist/src/cli/commands/interview.d.ts.map +1 -1
- package/dist/src/cli/commands/interview.js +12 -53
- package/dist/src/cli/commands/interview.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +2 -1
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/types.d.ts +85 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/execute/audit-engine.d.ts +20 -0
- package/dist/src/execute/audit-engine.d.ts.map +1 -0
- package/dist/src/execute/audit-engine.js +49 -0
- package/dist/src/execute/audit-engine.js.map +1 -0
- package/dist/src/execute/parallel-groups.d.ts +9 -0
- package/dist/src/execute/parallel-groups.d.ts.map +1 -0
- package/dist/src/execute/parallel-groups.js +39 -0
- package/dist/src/execute/parallel-groups.js.map +1 -0
- package/dist/src/execute/passthrough-engine.d.ts +2 -0
- package/dist/src/execute/passthrough-engine.d.ts.map +1 -1
- package/dist/src/execute/passthrough-engine.js +6 -0
- package/dist/src/execute/passthrough-engine.js.map +1 -1
- package/dist/src/execute/repository.d.ts.map +1 -1
- package/dist/src/execute/repository.js +3 -0
- package/dist/src/execute/repository.js.map +1 -1
- package/dist/src/execute/session.d.ts +3 -1
- package/dist/src/execute/session.d.ts.map +1 -1
- package/dist/src/execute/session.js +31 -0
- package/dist/src/execute/session.js.map +1 -1
- package/dist/src/interview/context-compressor.d.ts +17 -0
- package/dist/src/interview/context-compressor.d.ts.map +1 -0
- package/dist/src/interview/context-compressor.js +40 -0
- package/dist/src/interview/context-compressor.js.map +1 -0
- package/dist/src/interview/mini-interview-engine.d.ts +33 -0
- package/dist/src/interview/mini-interview-engine.d.ts.map +1 -0
- package/dist/src/interview/mini-interview-engine.js +103 -0
- package/dist/src/interview/mini-interview-engine.js.map +1 -0
- package/dist/src/interview/passthrough-engine.d.ts +7 -0
- package/dist/src/interview/passthrough-engine.d.ts.map +1 -1
- package/dist/src/interview/passthrough-engine.js +15 -1
- package/dist/src/interview/passthrough-engine.js.map +1 -1
- package/dist/src/interview/session.d.ts +2 -1
- package/dist/src/interview/session.d.ts.map +1 -1
- package/dist/src/interview/session.js +5 -0
- package/dist/src/interview/session.js.map +1 -1
- package/dist/src/mcp/schemas.d.ts +78 -9
- package/dist/src/mcp/schemas.d.ts.map +1 -1
- package/dist/src/mcp/schemas.js +26 -2
- package/dist/src/mcp/schemas.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +5 -2
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/execute-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/execute-passthrough.js +174 -1
- package/dist/src/mcp/tools/execute-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/interview-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/interview-passthrough.js +71 -3
- package/dist/src/mcp/tools/interview-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/interview.d.ts.map +1 -1
- package/dist/src/mcp/tools/interview.js +34 -1
- package/dist/src/mcp/tools/interview.js.map +1 -1
- package/dist/src/mcp/tools/spec-passthrough.d.ts +2 -1
- package/dist/src/mcp/tools/spec-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/spec-passthrough.js +54 -3
- package/dist/src/mcp/tools/spec-passthrough.js.map +1 -1
- package/dist/src/mcp/tools/spec.d.ts.map +1 -1
- package/dist/src/mcp/tools/spec.js +2 -0
- package/dist/src/mcp/tools/spec.js.map +1 -1
- package/dist/src/memory/memory-context-injector.d.ts +26 -0
- package/dist/src/memory/memory-context-injector.d.ts.map +1 -0
- package/dist/src/memory/memory-context-injector.js +67 -0
- package/dist/src/memory/memory-context-injector.js.map +1 -0
- package/dist/src/memory/project-memory-store.d.ts +14 -0
- package/dist/src/memory/project-memory-store.d.ts.map +1 -0
- package/dist/src/memory/project-memory-store.js +105 -0
- package/dist/src/memory/project-memory-store.js.map +1 -0
- package/dist/src/memory/user-profile-store.d.ts +13 -0
- package/dist/src/memory/user-profile-store.d.ts.map +1 -0
- package/dist/src/memory/user-profile-store.js +89 -0
- package/dist/src/memory/user-profile-store.js.map +1 -0
- package/dist/src/recording/agg-converter.d.ts +25 -0
- package/dist/src/recording/agg-converter.d.ts.map +1 -0
- package/dist/src/recording/agg-converter.js +80 -0
- package/dist/src/recording/agg-converter.js.map +1 -0
- package/dist/src/recording/agg-installer.d.ts +6 -0
- package/dist/src/recording/agg-installer.d.ts.map +1 -0
- package/dist/src/recording/agg-installer.js +50 -0
- package/dist/src/recording/agg-installer.js.map +1 -0
- package/dist/src/recording/asciinema-installer.d.ts +6 -0
- package/dist/src/recording/asciinema-installer.d.ts.map +1 -0
- package/dist/src/recording/asciinema-installer.js +50 -0
- package/dist/src/recording/asciinema-installer.js.map +1 -0
- package/dist/src/recording/asciinema-recorder.d.ts +26 -0
- package/dist/src/recording/asciinema-recorder.d.ts.map +1 -0
- package/dist/src/recording/asciinema-recorder.js +52 -0
- package/dist/src/recording/asciinema-recorder.js.map +1 -0
- package/dist/src/recording/cast-generator.d.ts +7 -0
- package/dist/src/recording/cast-generator.d.ts.map +1 -0
- package/dist/src/recording/cast-generator.js +72 -0
- package/dist/src/recording/cast-generator.js.map +1 -0
- package/dist/src/recording/filename-generator.d.ts +1 -0
- package/dist/src/recording/filename-generator.d.ts.map +1 -1
- package/dist/src/recording/filename-generator.js +7 -0
- package/dist/src/recording/filename-generator.js.map +1 -1
- package/dist/src/recording/recording-orchestrator.d.ts +50 -0
- package/dist/src/recording/recording-orchestrator.d.ts.map +1 -0
- package/dist/src/recording/recording-orchestrator.js +98 -0
- package/dist/src/recording/recording-orchestrator.js.map +1 -0
- package/dist/src/scripts/postinstall.d.ts +2 -0
- package/dist/src/scripts/postinstall.d.ts.map +1 -0
- package/dist/src/scripts/postinstall.js +27 -0
- package/dist/src/scripts/postinstall.js.map +1 -0
- package/dist/src/spec/passthrough-generator.d.ts +2 -0
- package/dist/src/spec/passthrough-generator.d.ts.map +1 -1
- package/dist/src/spec/passthrough-generator.js +34 -0
- package/dist/src/spec/passthrough-generator.js.map +1 -1
- package/dist/src/spec/templates.d.ts +12 -0
- package/dist/src/spec/templates.d.ts.map +1 -0
- package/dist/src/spec/templates.js +103 -0
- package/dist/src/spec/templates.js.map +1 -0
- package/dist/src/spec/text-based-spec-generator.d.ts +15 -0
- package/dist/src/spec/text-based-spec-generator.d.ts.map +1 -0
- package/dist/src/spec/text-based-spec-generator.js +63 -0
- package/dist/src/spec/text-based-spec-generator.js.map +1 -0
- package/package.json +2 -1
- package/README.backup.md +0 -442
package/CLAUDE.md
CHANGED
|
@@ -84,7 +84,7 @@ interface GestaltConfig {
|
|
|
84
84
|
|
|
85
85
|
## MCP Tools
|
|
86
86
|
- `ges_interview`: action=[start|respond|score|complete]
|
|
87
|
-
- `ges_generate_spec`: sessionId, force?
|
|
87
|
+
- `ges_generate_spec`: sessionId? (optional), text? (optional), force?, spec? (passthrough)
|
|
88
88
|
- `ges_execute`: action=[start|plan_step|plan_complete|execute_start|execute_task|evaluate|status|evolve_fix|evolve|evolve_patch|evolve_re_execute|evolve_lateral|evolve_lateral_result|role_match|role_consensus]
|
|
89
89
|
- `ges_create_agent`: action=[start|submit] — 인터뷰 기반 커스텀 Role Agent 생성
|
|
90
90
|
- `ges_status`: sessionId?
|
|
@@ -159,8 +159,18 @@ ges_interview({ action: "complete", sessionId: "<id>" })
|
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
**Step 6: Spec 생성 (2단계)**
|
|
162
|
+
|
|
163
|
+
두 가지 입력 경로 중 하나를 선택한다.
|
|
164
|
+
|
|
162
165
|
```
|
|
163
|
-
//
|
|
166
|
+
// Text-based 경로 (인터뷰 불필요)
|
|
167
|
+
ges_generate_spec({ text: "..." })
|
|
168
|
+
→ specContext (systemPrompt, specPrompt) 반환
|
|
169
|
+
|
|
170
|
+
ges_generate_spec({ text: "...", spec: {...} })
|
|
171
|
+
→ Zod 검증 후 최종 Spec 반환 + .gestalt/memory.json 자동 업데이트
|
|
172
|
+
|
|
173
|
+
// Interview 기반 경로 (6a: specContext 요청)
|
|
164
174
|
ges_generate_spec({ sessionId: "<id>" })
|
|
165
175
|
→ specContext (systemPrompt, specPrompt, allRounds) 반환
|
|
166
176
|
|
|
@@ -346,6 +356,7 @@ ges_execute({ action: "role_consensus", sessionId: "<id>", consensus: {...} })
|
|
|
346
356
|
- Spec의 `gestaltAnalysis[].principle`은 enum: `closure | proximity | similarity | figure_ground | continuity`
|
|
347
357
|
- `ontologySchema.entities[]`: `{ name, description, attributes[] }`
|
|
348
358
|
- `ontologySchema.relations[]`: `{ from, to, type }`
|
|
359
|
+
- text-based 경로: `sessionId` 불필요, 생성된 spec의 `interviewSessionId`는 `"text-input"`으로 설정
|
|
349
360
|
|
|
350
361
|
## Project Structure
|
|
351
362
|
- `src/core/` — types, errors, Result monad, config, constants
|
package/README.ko.md
CHANGED
|
@@ -94,6 +94,26 @@ Claude Code
|
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
97
|
+
## Project Memory
|
|
98
|
+
|
|
99
|
+
Spec과 실행 결과는 레포 루트의 `.gestalt/memory.json`에 자동으로 기록돼요.
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"specHistory": [
|
|
104
|
+
{ "specId": "...", "goal": "Build a user auth system", "sourceType": "text" }
|
|
105
|
+
],
|
|
106
|
+
"executionHistory": [],
|
|
107
|
+
"architectureDecisions": []
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **커밋하세요** — `.gestalt/memory.json`은 일반 JSON 파일이에요. 커밋하면 팀원도 `git pull` 후 이전 결정 사항을 그대로 이어받을 수 있어요.
|
|
112
|
+
- **컨텍스트 주입** — 다음 Spec을 생성할 때 이전 목표와 아키텍처 결정 사항이 프롬프트에 자동으로 주입돼요.
|
|
113
|
+
- **User Profile** — 개인 설정은 `~/.gestalt/profile.json`에 저장되며 커밋 대상에 포함되지 않아요.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
97
117
|
## 설치
|
|
98
118
|
|
|
99
119
|
### 옵션 1: Claude Code 플러그인 (권장)
|
|
@@ -188,11 +208,43 @@ claude mcp add gestalt -- npx -y @tienne/gestalt
|
|
|
188
208
|
8라운드 → 모호성: 0.19 ✓ Spec 생성 준비 완료
|
|
189
209
|
```
|
|
190
210
|
|
|
211
|
+
#### 인터뷰가 길어질 때 (Context Compression)
|
|
212
|
+
|
|
213
|
+
라운드가 5개를 초과하면 Gestalt가 자동으로 압축을 제안해요. `compress` action을 사용하면 이전 대화를 요약해 컨텍스트를 줄일 수 있어요:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
1. respond 응답에 needsCompression: true + compressionContext 포함
|
|
217
|
+
2. ges_interview({ action: "compress", sessionId }) → compressionContext 반환
|
|
218
|
+
3. caller가 요약 생성 후 제출 → 세션에 저장
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
이후 라운드에서는 압축된 요약이 자동으로 주입돼요.
|
|
222
|
+
|
|
191
223
|
---
|
|
192
224
|
|
|
193
225
|
### 2단계 — Spec 생성
|
|
194
226
|
|
|
195
|
-
|
|
227
|
+
**옵션 A — 텍스트로 바로 생성 (인터뷰 불필요):**
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
ges_generate_spec({ text: "Stripe로 결제 플로우 구현" })
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**옵션 A-2 — 내장 템플릿 사용:**
|
|
234
|
+
|
|
235
|
+
3가지 내장 템플릿으로 빠르게 시작할 수 있어요:
|
|
236
|
+
|
|
237
|
+
| 템플릿 ID | 설명 |
|
|
238
|
+
|-----------|------|
|
|
239
|
+
| `rest-api` | REST API 서버 (인증, CRUD, OpenAPI) |
|
|
240
|
+
| `react-dashboard` | React 대시보드 앱 (차트, 필터, 반응형) |
|
|
241
|
+
| `cli-tool` | CLI 도구 (서브커맨드, 설정, 배포) |
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
ges_generate_spec({ text: "JWT 인증이 포함된 API", template: "rest-api" })
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**옵션 B — 완료된 인터뷰에서 생성:**
|
|
196
248
|
|
|
197
249
|
```bash
|
|
198
250
|
/spec
|
|
@@ -233,6 +285,62 @@ Spec을 의존성 기반 실행 계획으로 변환하고 실행해요:
|
|
|
233
285
|
- Jaccard 유사도 기반 측정
|
|
234
286
|
- Threshold를 초과하면 소급 검토가 자동으로 시작돼요
|
|
235
287
|
|
|
288
|
+
#### 병렬 실행 (Parallel Groups)
|
|
289
|
+
|
|
290
|
+
`plan_complete` 응답에 `parallelGroups: string[][]`이 포함돼요. 의존성이 없는 태스크는 같은 그룹에 배치되어 동시 실행할 수 있어요:
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
"parallelGroups": [
|
|
294
|
+
["setup-db", "setup-env"], // 동시 실행 가능
|
|
295
|
+
["create-schema"], // 위 그룹 완료 후 실행
|
|
296
|
+
["seed-data", "run-tests"] // 동시 실행 가능
|
|
297
|
+
]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
#### 실행 이어하기 (Resume)
|
|
301
|
+
|
|
302
|
+
실행 중 세션이 중단되어도 이어서 계속할 수 있어요:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
ges_execute({ action: "resume", sessionId: "<id>" })
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`ResumeContext`를 반환해요: 완료된 태스크 목록, 다음 태스크, 진행률(%). `ges_status` 응답에도 `resumeContext`가 자동으로 포함돼요.
|
|
309
|
+
|
|
310
|
+
#### Brownfield 감사 (Audit)
|
|
311
|
+
|
|
312
|
+
기존 코드베이스가 있을 때 Spec 대비 구현 현황을 분석할 수 있어요:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# 1단계: 감사 컨텍스트 요청
|
|
316
|
+
ges_execute({ action: "audit", sessionId: "<id>" })
|
|
317
|
+
→ auditContext (systemPrompt, auditPrompt) 반환
|
|
318
|
+
|
|
319
|
+
# 2단계: 코드베이스 스냅샷 + 감사 결과 제출
|
|
320
|
+
ges_execute({
|
|
321
|
+
action: "audit",
|
|
322
|
+
sessionId: "<id>",
|
|
323
|
+
codebaseSnapshot: "...",
|
|
324
|
+
auditResult: { implementedACs: [0,2], partialACs: [1], missingACs: [3], gapAnalysis: "..." }
|
|
325
|
+
})
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### Sub-agent 스포닝 (Spawn)
|
|
329
|
+
|
|
330
|
+
복잡한 태스크를 동적으로 하위 태스크로 분해할 수 있어요:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
ges_execute({
|
|
334
|
+
action: "spawn",
|
|
335
|
+
sessionId: "<id>",
|
|
336
|
+
parentTaskId: "task-3",
|
|
337
|
+
subTasks: [
|
|
338
|
+
{ title: "DB 스키마 작성", description: "..." },
|
|
339
|
+
{ title: "마이그레이션 실행", description: "...", dependsOn: ["spawned-<id>"] }
|
|
340
|
+
]
|
|
341
|
+
})
|
|
342
|
+
```
|
|
343
|
+
|
|
236
344
|
---
|
|
237
345
|
|
|
238
346
|
### 4단계 — Evaluate (평가)
|
|
@@ -356,6 +464,9 @@ ges_create_agent → action: "submit", sessionId: "<id>", agentContent: "..."
|
|
|
356
464
|
# 인터랙티브 인터뷰 시작
|
|
357
465
|
npx @tienne/gestalt interview "주제"
|
|
358
466
|
|
|
467
|
+
# 터미널 세션을 GIF로 녹화
|
|
468
|
+
npx @tienne/gestalt interview "주제" --record
|
|
469
|
+
|
|
359
470
|
# 완료된 세션에서 Spec 생성
|
|
360
471
|
npx @tienne/gestalt spec <session-id>
|
|
361
472
|
|
|
@@ -369,6 +480,24 @@ npx @tienne/gestalt setup
|
|
|
369
480
|
npx @tienne/gestalt serve
|
|
370
481
|
```
|
|
371
482
|
|
|
483
|
+
#### 인터뷰 세션 녹화
|
|
484
|
+
|
|
485
|
+
`--record` (또는 `-r`) 플래그를 추가하면 터미널 세션을 GIF로 녹화할 수 있어요:
|
|
486
|
+
|
|
487
|
+
```bash
|
|
488
|
+
npx @tienne/gestalt interview "주제" --record
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
인터뷰가 완료되면 현재 디렉토리에 GIF 파일이 생성돼요:
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
user-auth-interview-20260327.gif
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
파일명은 LLM이 인터뷰 주제를 기반으로 kebab-case로 생성하고, `YYYYMMDD` 날짜를 붙여요. 외부 바이너리는 필요하지 않아요 — `gifencoder`와 `jimp` npm 패키지만 사용해요.
|
|
498
|
+
|
|
499
|
+
**중단된 세션 이어 녹화:** 녹화 중 세션이 중단되더라도 걱정하지 않아도 돼요. 동일 세션을 다시 실행하면 `.frames` 파일을 자동으로 감지해 이어서 녹화해요. 임시 프레임 데이터는 `.gestalt/recordings/{sessionId}.frames`에 저장되고, GIF 생성이 완료되면 자동으로 삭제돼요.
|
|
500
|
+
|
|
372
501
|
---
|
|
373
502
|
|
|
374
503
|
## 설정
|
|
@@ -434,15 +563,19 @@ Claude Code
|
|
|
434
563
|
│ Interview Engine │
|
|
435
564
|
│ ├─ GestaltPrincipleSelector │
|
|
436
565
|
│ ├─ AmbiguityScorer │
|
|
437
|
-
│
|
|
566
|
+
│ ├─ SessionManager │
|
|
567
|
+
│ └─ ContextCompressor │
|
|
438
568
|
│ │
|
|
439
569
|
│ Spec Generator │
|
|
440
|
-
│
|
|
570
|
+
│ ├─ PassthroughSpecGenerator │
|
|
571
|
+
│ └─ SpecTemplateRegistry │
|
|
441
572
|
│ │
|
|
442
573
|
│ Execute Engine │
|
|
443
574
|
│ ├─ DAG Validator │
|
|
575
|
+
│ ├─ ParallelGroupsCalculator │
|
|
444
576
|
│ ├─ DriftDetector │
|
|
445
577
|
│ ├─ EvaluationEngine │
|
|
578
|
+
│ ├─ AuditEngine │
|
|
446
579
|
│ └─ ExecuteSessionManager │
|
|
447
580
|
│ │
|
|
448
581
|
│ Resilience Engine │
|
package/README.md
CHANGED
|
@@ -27,22 +27,41 @@ Gestalt is an MCP (Model Context Protocol) server that runs inside Claude Code.
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Quick Start
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
**Choose your path:**
|
|
33
|
+
|
|
34
|
+
### For Non-Developers (Claude Desktop)
|
|
35
|
+
|
|
36
|
+
No terminal. No API key. Just Claude Desktop.
|
|
37
|
+
|
|
38
|
+
→ **[5-minute Getting Started Guide](./docs/getting-started.md)**
|
|
39
|
+
|
|
40
|
+
1. Open Claude Desktop
|
|
41
|
+
2. Install the Gestalt plugin
|
|
42
|
+
3. Type `/interview "your idea"` — Gestalt guides you through the rest
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### For Developers (MCP Integration)
|
|
33
47
|
|
|
34
48
|
```bash
|
|
35
|
-
#
|
|
36
|
-
/
|
|
49
|
+
# Step 1: Add to marketplace (one-time setup)
|
|
50
|
+
/plugin marketplace add tienne/gestalt
|
|
37
51
|
|
|
38
|
-
#
|
|
39
|
-
/
|
|
52
|
+
# Step 2: Install the plugin
|
|
53
|
+
/plugin install gestalt@gestalt
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then in any Claude Code session:
|
|
40
57
|
|
|
41
|
-
|
|
58
|
+
```bash
|
|
59
|
+
/interview "user authentication system"
|
|
60
|
+
/spec
|
|
42
61
|
/execute
|
|
43
62
|
```
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
→ **[Full MCP Reference](./docs/mcp-reference.md)** — all tools, parameters, and examples
|
|
46
65
|
|
|
47
66
|
---
|
|
48
67
|
|
|
@@ -89,6 +108,26 @@ You (in Claude Code)
|
|
|
89
108
|
|
|
90
109
|
---
|
|
91
110
|
|
|
111
|
+
## Project Memory
|
|
112
|
+
|
|
113
|
+
Every spec and execution result is automatically recorded in `.gestalt/memory.json` at your repo root.
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"specHistory": [
|
|
118
|
+
{ "specId": "...", "goal": "Build a user auth system", "sourceType": "text" }
|
|
119
|
+
],
|
|
120
|
+
"executionHistory": [],
|
|
121
|
+
"architectureDecisions": []
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- **Commit it** — `.gestalt/memory.json` is plain JSON. Commit it and teammates inherit all prior decisions on `git pull`.
|
|
126
|
+
- **Context injection** — When generating the next spec, prior goals and architecture decisions are automatically injected into the prompt.
|
|
127
|
+
- **User profile** — Personal preferences are stored in `~/.gestalt/profile.json` and are never committed.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
92
131
|
## Installation
|
|
93
132
|
|
|
94
133
|
### Option 1: Claude Code Plugin (Recommended)
|
|
@@ -183,11 +222,43 @@ Round 4 → ambiguity: 0.45 (getting clearer)
|
|
|
183
222
|
Round 8 → ambiguity: 0.19 ✓ ready for Spec
|
|
184
223
|
```
|
|
185
224
|
|
|
225
|
+
#### Long interviews: Context Compression
|
|
226
|
+
|
|
227
|
+
When rounds exceed 5, Gestalt automatically signals that compression is available. Use the `compress` action to summarize earlier rounds and keep the context window lean:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
1. respond returns needsCompression: true + compressionContext
|
|
231
|
+
2. ges_interview({ action: "compress", sessionId }) → compressionContext
|
|
232
|
+
3. Caller generates summary → submits it → stored in session
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The compressed summary is automatically injected into all subsequent rounds.
|
|
236
|
+
|
|
186
237
|
---
|
|
187
238
|
|
|
188
239
|
### Step 2 — Spec Generation
|
|
189
240
|
|
|
190
|
-
|
|
241
|
+
**Option A — From text (no interview required):**
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
ges_generate_spec({ text: "Build a checkout flow with Stripe" })
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Option A-2 — With a built-in template:**
|
|
248
|
+
|
|
249
|
+
Three starter templates pre-fill common constraints and acceptance criteria:
|
|
250
|
+
|
|
251
|
+
| Template ID | Description |
|
|
252
|
+
|-------------|-------------|
|
|
253
|
+
| `rest-api` | REST API server with auth, CRUD, and OpenAPI |
|
|
254
|
+
| `react-dashboard` | React dashboard with charts, filters, and responsive layout |
|
|
255
|
+
| `cli-tool` | CLI tool with subcommands, config, and distribution |
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
ges_generate_spec({ text: "API with JWT authentication", template: "rest-api" })
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Option B — From a completed interview:**
|
|
191
262
|
|
|
192
263
|
```bash
|
|
193
264
|
/spec
|
|
@@ -228,6 +299,62 @@ Transforms the Spec into a dependency-aware execution plan and runs it:
|
|
|
228
299
|
- Jaccard similarity-based measurement
|
|
229
300
|
- Auto-triggers a retrospective when drift exceeds threshold
|
|
230
301
|
|
|
302
|
+
#### Parallel execution groups
|
|
303
|
+
|
|
304
|
+
The `plan_complete` response includes `parallelGroups: string[][]`. Tasks with no mutual dependencies land in the same group and can be executed concurrently:
|
|
305
|
+
|
|
306
|
+
```json
|
|
307
|
+
"parallelGroups": [
|
|
308
|
+
["setup-db", "setup-env"], // run in parallel
|
|
309
|
+
["create-schema"], // after group above
|
|
310
|
+
["seed-data", "run-tests"] // run in parallel
|
|
311
|
+
]
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### Resuming an interrupted execution
|
|
315
|
+
|
|
316
|
+
Pick up where you left off when a session is interrupted:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
ges_execute({ action: "resume", sessionId: "<id>" })
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Returns `ResumeContext`: completed task IDs, next task, and `progressPercent`. The `ges_status` response also includes `resumeContext` automatically for any executing session.
|
|
323
|
+
|
|
324
|
+
#### Brownfield audit
|
|
325
|
+
|
|
326
|
+
When a codebase already exists, audit it against the Spec before executing new tasks:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
# Step 1: request audit context
|
|
330
|
+
ges_execute({ action: "audit", sessionId: "<id>" })
|
|
331
|
+
→ auditContext (systemPrompt, auditPrompt)
|
|
332
|
+
|
|
333
|
+
# Step 2: submit codebase snapshot + audit result
|
|
334
|
+
ges_execute({
|
|
335
|
+
action: "audit",
|
|
336
|
+
sessionId: "<id>",
|
|
337
|
+
codebaseSnapshot: "...",
|
|
338
|
+
auditResult: { implementedACs: [0,2], partialACs: [1], missingACs: [3], gapAnalysis: "..." }
|
|
339
|
+
})
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Sub-agent spawning
|
|
343
|
+
|
|
344
|
+
Decompose a complex task into sub-tasks dynamically during execution:
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
ges_execute({
|
|
348
|
+
action: "spawn",
|
|
349
|
+
sessionId: "<id>",
|
|
350
|
+
parentTaskId: "task-3",
|
|
351
|
+
subTasks: [
|
|
352
|
+
{ title: "Write DB schema", description: "..." },
|
|
353
|
+
{ title: "Run migration", description: "...", dependsOn: ["spawned-<id>"] }
|
|
354
|
+
]
|
|
355
|
+
})
|
|
356
|
+
```
|
|
357
|
+
|
|
231
358
|
---
|
|
232
359
|
|
|
233
360
|
### Step 4 — Evaluate
|
|
@@ -349,6 +476,9 @@ Requires `ANTHROPIC_API_KEY`. Runs Gestalt directly from the terminal without Cl
|
|
|
349
476
|
# Start an interactive interview
|
|
350
477
|
npx @tienne/gestalt interview "my topic"
|
|
351
478
|
|
|
479
|
+
# Record the session as a GIF
|
|
480
|
+
npx @tienne/gestalt interview "my topic" --record
|
|
481
|
+
|
|
352
482
|
# Generate Spec from a completed session
|
|
353
483
|
npx @tienne/gestalt spec <session-id>
|
|
354
484
|
|
|
@@ -362,6 +492,24 @@ npx @tienne/gestalt setup
|
|
|
362
492
|
npx @tienne/gestalt serve
|
|
363
493
|
```
|
|
364
494
|
|
|
495
|
+
#### Recording an interview session
|
|
496
|
+
|
|
497
|
+
Add `--record` (or `-r`) to capture the terminal session as a GIF:
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
npx @tienne/gestalt interview "my topic" --record
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
When the interview completes, a GIF is written to the current directory:
|
|
504
|
+
|
|
505
|
+
```
|
|
506
|
+
user-auth-interview-20260327.gif
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
The filename is generated by the LLM from the interview topic (kebab-case) plus a `YYYYMMDD` date stamp. No external binaries are required — recording uses `gifencoder` and `jimp` only.
|
|
510
|
+
|
|
511
|
+
**Resuming an interrupted session:** If a session is interrupted mid-recording, restarting the same session automatically detects the `.frames` file and continues where it left off. Temporary frame data is stored at `.gestalt/recordings/{sessionId}.frames` and deleted once the GIF is written.
|
|
512
|
+
|
|
365
513
|
---
|
|
366
514
|
|
|
367
515
|
## Configuration
|
|
@@ -427,15 +575,19 @@ Claude Code (you)
|
|
|
427
575
|
│ Interview Engine │
|
|
428
576
|
│ ├─ GestaltPrincipleSelector │
|
|
429
577
|
│ ├─ AmbiguityScorer │
|
|
430
|
-
│
|
|
578
|
+
│ ├─ SessionManager │
|
|
579
|
+
│ └─ ContextCompressor │
|
|
431
580
|
│ │
|
|
432
581
|
│ Spec Generator │
|
|
433
|
-
│
|
|
582
|
+
│ ├─ PassthroughSpecGenerator │
|
|
583
|
+
│ └─ SpecTemplateRegistry │
|
|
434
584
|
│ │
|
|
435
585
|
│ Execute Engine │
|
|
436
586
|
│ ├─ DAG Validator │
|
|
587
|
+
│ ├─ ParallelGroupsCalculator │
|
|
437
588
|
│ ├─ DriftDetector │
|
|
438
589
|
│ ├─ EvaluationEngine │
|
|
590
|
+
│ ├─ AuditEngine │
|
|
439
591
|
│ └─ ExecuteSessionManager │
|
|
440
592
|
│ │
|
|
441
593
|
│ Resilience Engine │
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tienne/gestalt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "TypeScript AI Development Harness - Gestalt psychology-driven requirement clarification",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"dev": "tsx bin/gestalt.ts",
|
|
25
25
|
"build": "tsc",
|
|
26
26
|
"postbuild": "cp -r agents dist/ && cp -r role-agents dist/ && cp -r review-agents dist/ && cp -r skills dist/ && cp -r schemas dist/ && cp package.json dist/ && chmod +x dist/bin/gestalt.js",
|
|
27
|
+
"postinstall": "node ./dist/src/scripts/postinstall.js || true",
|
|
27
28
|
"prepublishOnly": "pnpm build",
|
|
28
29
|
"test": "vitest run",
|
|
29
30
|
"test:watch": "vitest",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interview.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interview.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"interview.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interview.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,IAAI,CAAC,CA0Ff"}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { createInterface } from 'node:readline';
|
|
2
|
-
import { unlinkSync } from 'node:fs';
|
|
3
2
|
import { loadConfig } from '../../core/config.js';
|
|
4
3
|
import { EventStore } from '../../events/store.js';
|
|
5
4
|
import { AnthropicAdapter } from '../../llm/adapter.js';
|
|
6
5
|
import { InterviewEngine } from '../../interview/engine.js';
|
|
7
|
-
import {
|
|
8
|
-
import { detectResume } from '../../recording/resume-detector.js';
|
|
9
|
-
import { SegmentMerger } from '../../recording/segment-merger.js';
|
|
10
|
-
import { GifGenerator } from '../../recording/gif-generator.js';
|
|
11
|
-
import { FilenameGenerator } from '../../recording/filename-generator.js';
|
|
12
|
-
import { getFramesPath } from '../../recording/recording-dir.js';
|
|
6
|
+
import { RecordingOrchestrator } from '../../recording/recording-orchestrator.js';
|
|
13
7
|
export async function interviewCommand(topic, options = {}) {
|
|
14
8
|
const config = loadConfig();
|
|
15
9
|
if (!config.llm.apiKey) {
|
|
16
10
|
console.error('Error: ANTHROPIC_API_KEY is required for CLI mode. Set it in .env or as environment variable.');
|
|
17
11
|
process.exit(1);
|
|
18
12
|
}
|
|
19
|
-
const eventStore = new EventStore(config.dbPath);
|
|
20
13
|
const llm = new AnthropicAdapter(config.llm.apiKey, config.llm.model);
|
|
14
|
+
const orchestrator = new RecordingOrchestrator(llm);
|
|
15
|
+
// --record 플래그가 있고 아직 asciinema로 감싸지지 않았으면 respawn.
|
|
16
|
+
// respawn 시 process.exit()이 호출되므로 이후 코드는 실행되지 않음.
|
|
17
|
+
await orchestrator.startIfNeeded(options);
|
|
18
|
+
const eventStore = new EventStore(config.dbPath);
|
|
21
19
|
const engine = new InterviewEngine(llm, eventStore);
|
|
22
20
|
const rl = createInterface({
|
|
23
21
|
input: process.stdin,
|
|
24
22
|
output: process.stdout,
|
|
25
23
|
});
|
|
26
24
|
const prompt = (question) => new Promise((resolve) => rl.question(question, resolve));
|
|
27
|
-
let recorder = null;
|
|
28
25
|
try {
|
|
29
26
|
console.log(`\n🔍 Starting Gestalt interview for: "${topic}"\n`);
|
|
27
|
+
if (orchestrator.isRecording()) {
|
|
28
|
+
console.log('📹 Recording in progress (asciinema)...\n');
|
|
29
|
+
}
|
|
30
30
|
const startResult = await engine.start(topic);
|
|
31
31
|
if (!startResult.ok) {
|
|
32
32
|
console.error(`Error: ${startResult.error.message}`);
|
|
@@ -34,19 +34,6 @@ export async function interviewCommand(topic, options = {}) {
|
|
|
34
34
|
}
|
|
35
35
|
const { session, firstQuestion, projectType, detectedFiles } = startResult.value;
|
|
36
36
|
const sessionId = session.sessionId;
|
|
37
|
-
// --record 플래그 또는 기존 .frames 파일이 있으면 녹화 시작 (resume 자동 감지)
|
|
38
|
-
const { isResuming } = detectResume(sessionId);
|
|
39
|
-
const shouldRecord = options.record === true || isResuming;
|
|
40
|
-
if (shouldRecord) {
|
|
41
|
-
recorder = new TerminalRecorder(sessionId);
|
|
42
|
-
recorder.start();
|
|
43
|
-
if (isResuming) {
|
|
44
|
-
console.log('📹 Resuming recording from previous session...\n');
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
console.log('📹 Recording started...\n');
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
37
|
console.log(`Project type: ${projectType}`);
|
|
51
38
|
if (detectedFiles.length > 0) {
|
|
52
39
|
console.log(`Detected: ${detectedFiles.join(', ')}`);
|
|
@@ -79,42 +66,14 @@ export async function interviewCommand(topic, options = {}) {
|
|
|
79
66
|
console.log(`\n✅ Interview completed. Session ID: ${sessionId}`);
|
|
80
67
|
console.log('Run `gestalt spec ' + sessionId + '` to generate a spec.\n');
|
|
81
68
|
}
|
|
82
|
-
// 녹화 중이었다면 GIF
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
await generateGif(sessionId, topic, llm);
|
|
69
|
+
// asciinema 녹화 중이었다면 백그라운드 GIF 변환 트리거
|
|
70
|
+
if (orchestrator.isRecording()) {
|
|
71
|
+
await orchestrator.stopAndConvert(topic, sessionId, options);
|
|
86
72
|
}
|
|
87
73
|
}
|
|
88
74
|
finally {
|
|
89
|
-
// 프로세스 종료 시 recorder가 아직 녹화 중이면 pause
|
|
90
|
-
if (recorder?.recording) {
|
|
91
|
-
recorder.pause();
|
|
92
|
-
}
|
|
93
75
|
rl.close();
|
|
94
76
|
eventStore.close();
|
|
95
77
|
}
|
|
96
78
|
}
|
|
97
|
-
async function generateGif(sessionId, topic, llm) {
|
|
98
|
-
const framesPath = getFramesPath(sessionId);
|
|
99
|
-
try {
|
|
100
|
-
console.log('🎬 Generating GIF recording...');
|
|
101
|
-
const merger = new SegmentMerger();
|
|
102
|
-
const frames = await merger.readSingleFile(framesPath);
|
|
103
|
-
if (frames.length === 0) {
|
|
104
|
-
console.log('⚠️ No frames captured, skipping GIF generation.');
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
const filenameGen = new FilenameGenerator(llm);
|
|
108
|
-
const outputPath = await filenameGen.generate(topic, sessionId);
|
|
109
|
-
const gifGen = new GifGenerator({ repeat: 0, quality: 10, frameDelay: 150 });
|
|
110
|
-
const result = await gifGen.generateFromFrames(frames, outputPath);
|
|
111
|
-
// 임시 .frames 파일 정리
|
|
112
|
-
unlinkSync(framesPath);
|
|
113
|
-
console.log(`✅ GIF saved: ${result.filePath} (${(result.sizeBytes / 1024).toFixed(1)} KB, ${result.frameCount} frames)\n`);
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
117
|
-
console.error(`⚠️ GIF generation failed: ${message}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
79
|
//# sourceMappingURL=interview.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interview.js","sourceRoot":"","sources":["../../../../src/cli/commands/interview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"interview.js","sourceRoot":"","sources":["../../../../src/cli/commands/interview.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,SAAS,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,SAAS,IAAI,OAAO,CAsDnC"}
|
package/dist/src/cli/index.js
CHANGED
|
@@ -21,7 +21,8 @@ export function createCli() {
|
|
|
21
21
|
program
|
|
22
22
|
.command('interview [topic]')
|
|
23
23
|
.description('Start an interactive Gestalt interview')
|
|
24
|
-
.option('-
|
|
24
|
+
.option('--no-record', 'Disable automatic terminal session recording')
|
|
25
|
+
.option('--mp4', 'Also generate an MP4 alongside the GIF')
|
|
25
26
|
.action(async (topic, options) => {
|
|
26
27
|
await interviewCommand(topic ?? 'Untitled project', options);
|
|
27
28
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,SAAS,CAAC;SACf,WAAW,CAAC,2FAA2F,CAAC;SACxG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAEzB,OAAO;SACJ,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;SACrC,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,wCAAwC,CAAC;SACrD,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,SAAS,CAAC;SACf,WAAW,CAAC,2FAA2F,CAAC;SACxG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAEzB,OAAO;SACJ,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;SACrC,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,wCAAwC,CAAC;SACrD,MAAM,CAAC,aAAa,EAAE,8CAA8C,CAAC;SACrE,MAAM,CAAC,OAAO,EAAE,wCAAwC,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,KAAyB,EAAE,OAA4C,EAAE,EAAE;QACxF,MAAM,gBAAgB,CAAC,KAAK,IAAI,kBAAkB,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,aAAa,EAAE,yDAAyD,CAAC;SAChF,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAA4B,EAAE,EAAE;QAChE,MAAM,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,qBAAqB,CAAC;SAC9B,WAAW,CAAC,gCAAgC,CAAC;SAC7C,MAAM,CAAC,CAAC,SAAkB,EAAE,EAAE;QAC7B,aAAa,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,GAAG,EAAE;QACX,YAAY,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,sBAAsB,CAAC;SAC/B,WAAW,CAAC,wDAAwD,CAAC;SACrE,MAAM,CAAC,KAAK,EAAE,SAAkB,EAAE,EAAE;QACnC,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC"}
|