@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.
Files changed (129) hide show
  1. package/CLAUDE.md +13 -2
  2. package/README.ko.md +136 -3
  3. package/README.md +163 -11
  4. package/dist/package.json +2 -1
  5. package/dist/src/cli/commands/interview.d.ts +1 -0
  6. package/dist/src/cli/commands/interview.d.ts.map +1 -1
  7. package/dist/src/cli/commands/interview.js +12 -53
  8. package/dist/src/cli/commands/interview.js.map +1 -1
  9. package/dist/src/cli/index.d.ts.map +1 -1
  10. package/dist/src/cli/index.js +2 -1
  11. package/dist/src/cli/index.js.map +1 -1
  12. package/dist/src/core/types.d.ts +85 -0
  13. package/dist/src/core/types.d.ts.map +1 -1
  14. package/dist/src/execute/audit-engine.d.ts +20 -0
  15. package/dist/src/execute/audit-engine.d.ts.map +1 -0
  16. package/dist/src/execute/audit-engine.js +49 -0
  17. package/dist/src/execute/audit-engine.js.map +1 -0
  18. package/dist/src/execute/parallel-groups.d.ts +9 -0
  19. package/dist/src/execute/parallel-groups.d.ts.map +1 -0
  20. package/dist/src/execute/parallel-groups.js +39 -0
  21. package/dist/src/execute/parallel-groups.js.map +1 -0
  22. package/dist/src/execute/passthrough-engine.d.ts +2 -0
  23. package/dist/src/execute/passthrough-engine.d.ts.map +1 -1
  24. package/dist/src/execute/passthrough-engine.js +6 -0
  25. package/dist/src/execute/passthrough-engine.js.map +1 -1
  26. package/dist/src/execute/repository.d.ts.map +1 -1
  27. package/dist/src/execute/repository.js +3 -0
  28. package/dist/src/execute/repository.js.map +1 -1
  29. package/dist/src/execute/session.d.ts +3 -1
  30. package/dist/src/execute/session.d.ts.map +1 -1
  31. package/dist/src/execute/session.js +31 -0
  32. package/dist/src/execute/session.js.map +1 -1
  33. package/dist/src/interview/context-compressor.d.ts +17 -0
  34. package/dist/src/interview/context-compressor.d.ts.map +1 -0
  35. package/dist/src/interview/context-compressor.js +40 -0
  36. package/dist/src/interview/context-compressor.js.map +1 -0
  37. package/dist/src/interview/mini-interview-engine.d.ts +33 -0
  38. package/dist/src/interview/mini-interview-engine.d.ts.map +1 -0
  39. package/dist/src/interview/mini-interview-engine.js +103 -0
  40. package/dist/src/interview/mini-interview-engine.js.map +1 -0
  41. package/dist/src/interview/passthrough-engine.d.ts +7 -0
  42. package/dist/src/interview/passthrough-engine.d.ts.map +1 -1
  43. package/dist/src/interview/passthrough-engine.js +15 -1
  44. package/dist/src/interview/passthrough-engine.js.map +1 -1
  45. package/dist/src/interview/session.d.ts +2 -1
  46. package/dist/src/interview/session.d.ts.map +1 -1
  47. package/dist/src/interview/session.js +5 -0
  48. package/dist/src/interview/session.js.map +1 -1
  49. package/dist/src/mcp/schemas.d.ts +78 -9
  50. package/dist/src/mcp/schemas.d.ts.map +1 -1
  51. package/dist/src/mcp/schemas.js +26 -2
  52. package/dist/src/mcp/schemas.js.map +1 -1
  53. package/dist/src/mcp/server.d.ts.map +1 -1
  54. package/dist/src/mcp/server.js +5 -2
  55. package/dist/src/mcp/server.js.map +1 -1
  56. package/dist/src/mcp/tools/execute-passthrough.d.ts.map +1 -1
  57. package/dist/src/mcp/tools/execute-passthrough.js +174 -1
  58. package/dist/src/mcp/tools/execute-passthrough.js.map +1 -1
  59. package/dist/src/mcp/tools/interview-passthrough.d.ts.map +1 -1
  60. package/dist/src/mcp/tools/interview-passthrough.js +71 -3
  61. package/dist/src/mcp/tools/interview-passthrough.js.map +1 -1
  62. package/dist/src/mcp/tools/interview.d.ts.map +1 -1
  63. package/dist/src/mcp/tools/interview.js +34 -1
  64. package/dist/src/mcp/tools/interview.js.map +1 -1
  65. package/dist/src/mcp/tools/spec-passthrough.d.ts +2 -1
  66. package/dist/src/mcp/tools/spec-passthrough.d.ts.map +1 -1
  67. package/dist/src/mcp/tools/spec-passthrough.js +54 -3
  68. package/dist/src/mcp/tools/spec-passthrough.js.map +1 -1
  69. package/dist/src/mcp/tools/spec.d.ts.map +1 -1
  70. package/dist/src/mcp/tools/spec.js +2 -0
  71. package/dist/src/mcp/tools/spec.js.map +1 -1
  72. package/dist/src/memory/memory-context-injector.d.ts +26 -0
  73. package/dist/src/memory/memory-context-injector.d.ts.map +1 -0
  74. package/dist/src/memory/memory-context-injector.js +67 -0
  75. package/dist/src/memory/memory-context-injector.js.map +1 -0
  76. package/dist/src/memory/project-memory-store.d.ts +14 -0
  77. package/dist/src/memory/project-memory-store.d.ts.map +1 -0
  78. package/dist/src/memory/project-memory-store.js +105 -0
  79. package/dist/src/memory/project-memory-store.js.map +1 -0
  80. package/dist/src/memory/user-profile-store.d.ts +13 -0
  81. package/dist/src/memory/user-profile-store.d.ts.map +1 -0
  82. package/dist/src/memory/user-profile-store.js +89 -0
  83. package/dist/src/memory/user-profile-store.js.map +1 -0
  84. package/dist/src/recording/agg-converter.d.ts +25 -0
  85. package/dist/src/recording/agg-converter.d.ts.map +1 -0
  86. package/dist/src/recording/agg-converter.js +80 -0
  87. package/dist/src/recording/agg-converter.js.map +1 -0
  88. package/dist/src/recording/agg-installer.d.ts +6 -0
  89. package/dist/src/recording/agg-installer.d.ts.map +1 -0
  90. package/dist/src/recording/agg-installer.js +50 -0
  91. package/dist/src/recording/agg-installer.js.map +1 -0
  92. package/dist/src/recording/asciinema-installer.d.ts +6 -0
  93. package/dist/src/recording/asciinema-installer.d.ts.map +1 -0
  94. package/dist/src/recording/asciinema-installer.js +50 -0
  95. package/dist/src/recording/asciinema-installer.js.map +1 -0
  96. package/dist/src/recording/asciinema-recorder.d.ts +26 -0
  97. package/dist/src/recording/asciinema-recorder.d.ts.map +1 -0
  98. package/dist/src/recording/asciinema-recorder.js +52 -0
  99. package/dist/src/recording/asciinema-recorder.js.map +1 -0
  100. package/dist/src/recording/cast-generator.d.ts +7 -0
  101. package/dist/src/recording/cast-generator.d.ts.map +1 -0
  102. package/dist/src/recording/cast-generator.js +72 -0
  103. package/dist/src/recording/cast-generator.js.map +1 -0
  104. package/dist/src/recording/filename-generator.d.ts +1 -0
  105. package/dist/src/recording/filename-generator.d.ts.map +1 -1
  106. package/dist/src/recording/filename-generator.js +7 -0
  107. package/dist/src/recording/filename-generator.js.map +1 -1
  108. package/dist/src/recording/recording-orchestrator.d.ts +50 -0
  109. package/dist/src/recording/recording-orchestrator.d.ts.map +1 -0
  110. package/dist/src/recording/recording-orchestrator.js +98 -0
  111. package/dist/src/recording/recording-orchestrator.js.map +1 -0
  112. package/dist/src/scripts/postinstall.d.ts +2 -0
  113. package/dist/src/scripts/postinstall.d.ts.map +1 -0
  114. package/dist/src/scripts/postinstall.js +27 -0
  115. package/dist/src/scripts/postinstall.js.map +1 -0
  116. package/dist/src/spec/passthrough-generator.d.ts +2 -0
  117. package/dist/src/spec/passthrough-generator.d.ts.map +1 -1
  118. package/dist/src/spec/passthrough-generator.js +34 -0
  119. package/dist/src/spec/passthrough-generator.js.map +1 -1
  120. package/dist/src/spec/templates.d.ts +12 -0
  121. package/dist/src/spec/templates.d.ts.map +1 -0
  122. package/dist/src/spec/templates.js +103 -0
  123. package/dist/src/spec/templates.js.map +1 -0
  124. package/dist/src/spec/text-based-spec-generator.d.ts +15 -0
  125. package/dist/src/spec/text-based-spec-generator.d.ts.map +1 -0
  126. package/dist/src/spec/text-based-spec-generator.js +63 -0
  127. package/dist/src/spec/text-based-spec-generator.js.map +1 -0
  128. package/package.json +2 -1
  129. 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
- // 6a: specContext 요청
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
- 모호성 점수가 0.2에 도달하면 실행하세요:
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
- └─ SessionManager │
566
+ ├─ SessionManager │
567
+ │ └─ ContextCompressor │
438
568
  │ │
439
569
  │ Spec Generator │
440
- └─ PassthroughSpecGenerator │
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
- ## See it in action
30
+ ## Quick Start
31
31
 
32
- > **30 seconds to a structured execution plan** — no API key needed.
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
- # Start a Gestalt-driven requirements interview
36
- /interview "user authentication system"
49
+ # Step 1: Add to marketplace (one-time setup)
50
+ /plugin marketplace add tienne/gestalt
37
51
 
38
- # Once the interview is done, generate a structured Spec
39
- /spec
52
+ # Step 2: Install the plugin
53
+ /plugin install gestalt@gestalt
54
+ ```
55
+
56
+ Then in any Claude Code session:
40
57
 
41
- # Transform the Spec into a validated execution plan and run it
58
+ ```bash
59
+ /interview "user authentication system"
60
+ /spec
42
61
  /execute
43
62
  ```
44
63
 
45
- _(Demo coming soon.)_
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
- When the ambiguity score reaches 0.2, run:
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
- └─ SessionManager │
578
+ ├─ SessionManager │
579
+ │ └─ ContextCompressor │
431
580
  │ │
432
581
  │ Spec Generator │
433
- └─ PassthroughSpecGenerator │
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.6.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,5 +1,6 @@
1
1
  export interface InterviewCommandOptions {
2
2
  record?: boolean;
3
+ mp4?: boolean;
3
4
  }
4
5
  export declare function interviewCommand(topic: string, options?: InterviewCommandOptions): Promise<void>;
5
6
  //# sourceMappingURL=interview.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interview.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interview.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,IAAI,CAAC,CAqGf"}
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 { TerminalRecorder } from '../../recording/terminal-recorder.js';
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 (recorder && recorder.recording) {
84
- recorder.stop();
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":"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"}
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,CAqDnC"}
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"}
@@ -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('-r, --record', 'Record terminal output as GIF')
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,cAAc,EAAE,+BAA+B,CAAC;SACvD,MAAM,CAAC,KAAK,EAAE,KAAyB,EAAE,OAA6B,EAAE,EAAE;QACzE,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"}
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"}