@tienne/gestalt 0.12.3 → 0.14.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 (249) hide show
  1. package/README.ko.md +51 -1
  2. package/README.md +51 -1
  3. package/dist/package.json +5 -1
  4. package/dist/schemas/gestalt.schema.json +41 -3
  5. package/dist/skills/interview/SKILL.md +18 -1
  6. package/dist/src/agent/passthrough-generator.d.ts.map +1 -1
  7. package/dist/src/agent/passthrough-generator.js +3 -1
  8. package/dist/src/agent/passthrough-generator.js.map +1 -1
  9. package/dist/src/agent/role-agent-registry.d.ts.map +1 -1
  10. package/dist/src/agent/role-agent-registry.js.map +1 -1
  11. package/dist/src/agent/role-match-engine.d.ts.map +1 -1
  12. package/dist/src/agent/role-match-engine.js.map +1 -1
  13. package/dist/src/cli/commands/graph-visualize.d.ts.map +1 -1
  14. package/dist/src/cli/commands/graph-visualize.js +3 -1
  15. package/dist/src/cli/commands/graph-visualize.js.map +1 -1
  16. package/dist/src/cli/commands/init.d.ts.map +1 -1
  17. package/dist/src/cli/commands/init.js.map +1 -1
  18. package/dist/src/cli/commands/interview.d.ts.map +1 -1
  19. package/dist/src/cli/commands/interview.js +2 -2
  20. package/dist/src/cli/commands/interview.js.map +1 -1
  21. package/dist/src/cli/commands/spec.d.ts.map +1 -1
  22. package/dist/src/cli/commands/spec.js +2 -2
  23. package/dist/src/cli/commands/spec.js.map +1 -1
  24. package/dist/src/cli/commands/status.d.ts.map +1 -1
  25. package/dist/src/cli/commands/status.js.map +1 -1
  26. package/dist/src/cli/index.d.ts.map +1 -1
  27. package/dist/src/cli/index.js.map +1 -1
  28. package/dist/src/code-graph/engine.d.ts.map +1 -1
  29. package/dist/src/code-graph/engine.js +16 -13
  30. package/dist/src/code-graph/engine.js.map +1 -1
  31. package/dist/src/code-graph/plugins/go.d.ts.map +1 -1
  32. package/dist/src/code-graph/plugins/go.js +28 -4
  33. package/dist/src/code-graph/plugins/go.js.map +1 -1
  34. package/dist/src/code-graph/plugins/java.d.ts.map +1 -1
  35. package/dist/src/code-graph/plugins/java.js +63 -11
  36. package/dist/src/code-graph/plugins/java.js.map +1 -1
  37. package/dist/src/code-graph/plugins/kotlin.d.ts.map +1 -1
  38. package/dist/src/code-graph/plugins/kotlin.js +50 -7
  39. package/dist/src/code-graph/plugins/kotlin.js.map +1 -1
  40. package/dist/src/code-graph/plugins/objc.d.ts.map +1 -1
  41. package/dist/src/code-graph/plugins/objc.js +70 -12
  42. package/dist/src/code-graph/plugins/objc.js.map +1 -1
  43. package/dist/src/code-graph/plugins/python.d.ts.map +1 -1
  44. package/dist/src/code-graph/plugins/python.js +28 -4
  45. package/dist/src/code-graph/plugins/python.js.map +1 -1
  46. package/dist/src/code-graph/plugins/rust.d.ts.map +1 -1
  47. package/dist/src/code-graph/plugins/rust.js +72 -12
  48. package/dist/src/code-graph/plugins/rust.js.map +1 -1
  49. package/dist/src/code-graph/plugins/swift.d.ts.map +1 -1
  50. package/dist/src/code-graph/plugins/swift.js +62 -8
  51. package/dist/src/code-graph/plugins/swift.js.map +1 -1
  52. package/dist/src/code-graph/plugins/typescript.d.ts.map +1 -1
  53. package/dist/src/code-graph/plugins/typescript.js +2 -2
  54. package/dist/src/code-graph/plugins/typescript.js.map +1 -1
  55. package/dist/src/code-graph/providers/local-embedding.js +1 -1
  56. package/dist/src/code-graph/providers/local-embedding.js.map +1 -1
  57. package/dist/src/code-graph/storage.d.ts.map +1 -1
  58. package/dist/src/code-graph/storage.js +1 -3
  59. package/dist/src/code-graph/storage.js.map +1 -1
  60. package/dist/src/core/config.d.ts +138 -1
  61. package/dist/src/core/config.d.ts.map +1 -1
  62. package/dist/src/core/config.js +36 -3
  63. package/dist/src/core/config.js.map +1 -1
  64. package/dist/src/core/constants.d.ts.map +1 -1
  65. package/dist/src/core/constants.js +6 -6
  66. package/dist/src/core/constants.js.map +1 -1
  67. package/dist/src/core/result.d.ts.map +1 -1
  68. package/dist/src/core/result.js.map +1 -1
  69. package/dist/src/core/types.d.ts.map +1 -1
  70. package/dist/src/execute/audit-engine.d.ts.map +1 -1
  71. package/dist/src/execute/audit-engine.js +1 -3
  72. package/dist/src/execute/audit-engine.js.map +1 -1
  73. package/dist/src/execute/dag-validator.d.ts.map +1 -1
  74. package/dist/src/execute/dag-validator.js.map +1 -1
  75. package/dist/src/execute/parallel-groups.d.ts.map +1 -1
  76. package/dist/src/execute/parallel-groups.js.map +1 -1
  77. package/dist/src/execute/passthrough-engine.d.ts.map +1 -1
  78. package/dist/src/execute/passthrough-engine.js +34 -14
  79. package/dist/src/execute/passthrough-engine.js.map +1 -1
  80. package/dist/src/execute/prompts.d.ts.map +1 -1
  81. package/dist/src/execute/prompts.js +2 -4
  82. package/dist/src/execute/prompts.js.map +1 -1
  83. package/dist/src/execute/repository.d.ts.map +1 -1
  84. package/dist/src/execute/repository.js.map +1 -1
  85. package/dist/src/execute/session.d.ts.map +1 -1
  86. package/dist/src/execute/session.js +2 -1
  87. package/dist/src/execute/session.js.map +1 -1
  88. package/dist/src/execute/termination-detector.d.ts.map +1 -1
  89. package/dist/src/execute/termination-detector.js +3 -2
  90. package/dist/src/execute/termination-detector.js.map +1 -1
  91. package/dist/src/gestalt/analyzer.d.ts.map +1 -1
  92. package/dist/src/gestalt/analyzer.js +1 -2
  93. package/dist/src/gestalt/analyzer.js.map +1 -1
  94. package/dist/src/gestalt/principles.d.ts.map +1 -1
  95. package/dist/src/gestalt/principles.js +1 -3
  96. package/dist/src/gestalt/principles.js.map +1 -1
  97. package/dist/src/interview/engine.d.ts.map +1 -1
  98. package/dist/src/interview/engine.js +4 -1
  99. package/dist/src/interview/engine.js.map +1 -1
  100. package/dist/src/interview/mini-interview-engine.d.ts.map +1 -1
  101. package/dist/src/interview/mini-interview-engine.js +1 -3
  102. package/dist/src/interview/mini-interview-engine.js.map +1 -1
  103. package/dist/src/interview/passthrough-engine.d.ts.map +1 -1
  104. package/dist/src/interview/passthrough-engine.js +7 -3
  105. package/dist/src/interview/passthrough-engine.js.map +1 -1
  106. package/dist/src/interview/repository.d.ts.map +1 -1
  107. package/dist/src/interview/repository.js.map +1 -1
  108. package/dist/src/interview/resolution.js +1 -3
  109. package/dist/src/interview/resolution.js.map +1 -1
  110. package/dist/src/interview/session.d.ts.map +1 -1
  111. package/dist/src/interview/session.js.map +1 -1
  112. package/dist/src/knowledge-base/embedding-index.d.ts +11 -0
  113. package/dist/src/knowledge-base/embedding-index.d.ts.map +1 -0
  114. package/dist/src/knowledge-base/embedding-index.js +31 -0
  115. package/dist/src/knowledge-base/embedding-index.js.map +1 -0
  116. package/dist/src/knowledge-base/embedding.d.ts +19 -0
  117. package/dist/src/knowledge-base/embedding.d.ts.map +1 -0
  118. package/dist/src/knowledge-base/embedding.js +39 -0
  119. package/dist/src/knowledge-base/embedding.js.map +1 -0
  120. package/dist/src/knowledge-base/generator.d.ts +11 -0
  121. package/dist/src/knowledge-base/generator.d.ts.map +1 -0
  122. package/dist/src/knowledge-base/generator.js +91 -0
  123. package/dist/src/knowledge-base/generator.js.map +1 -0
  124. package/dist/src/knowledge-base/search.d.ts +12 -0
  125. package/dist/src/knowledge-base/search.d.ts.map +1 -0
  126. package/dist/src/knowledge-base/search.js +106 -0
  127. package/dist/src/knowledge-base/search.js.map +1 -0
  128. package/dist/src/knowledge-base/templates.d.ts +6 -0
  129. package/dist/src/knowledge-base/templates.d.ts.map +1 -0
  130. package/dist/src/knowledge-base/templates.js +27 -0
  131. package/dist/src/knowledge-base/templates.js.map +1 -0
  132. package/dist/src/knowledge-base/types.d.ts +29 -0
  133. package/dist/src/knowledge-base/types.d.ts.map +1 -0
  134. package/dist/src/knowledge-base/types.js +2 -0
  135. package/dist/src/knowledge-base/types.js.map +1 -0
  136. package/dist/src/knowledge-base/writer.d.ts +7 -0
  137. package/dist/src/knowledge-base/writer.d.ts.map +1 -0
  138. package/dist/src/knowledge-base/writer.js +21 -0
  139. package/dist/src/knowledge-base/writer.js.map +1 -0
  140. package/dist/src/llm/adapter.d.ts.map +1 -1
  141. package/dist/src/llm/adapter.js.map +1 -1
  142. package/dist/src/llm/factory.d.ts +24 -0
  143. package/dist/src/llm/factory.d.ts.map +1 -0
  144. package/dist/src/llm/factory.js +75 -0
  145. package/dist/src/llm/factory.js.map +1 -0
  146. package/dist/src/llm/openai-adapter.d.ts +1 -1
  147. package/dist/src/llm/openai-adapter.d.ts.map +1 -1
  148. package/dist/src/llm/openai-adapter.js +2 -2
  149. package/dist/src/llm/openai-adapter.js.map +1 -1
  150. package/dist/src/mcp/schemas.d.ts.map +1 -1
  151. package/dist/src/mcp/schemas.js +224 -88
  152. package/dist/src/mcp/schemas.js.map +1 -1
  153. package/dist/src/mcp/server.d.ts.map +1 -1
  154. package/dist/src/mcp/server.js +322 -109
  155. package/dist/src/mcp/server.js.map +1 -1
  156. package/dist/src/mcp/tools/benchmark-passthrough.js +1 -1
  157. package/dist/src/mcp/tools/benchmark-passthrough.js.map +1 -1
  158. package/dist/src/mcp/tools/create-agent-passthrough.d.ts.map +1 -1
  159. package/dist/src/mcp/tools/create-agent-passthrough.js.map +1 -1
  160. package/dist/src/mcp/tools/execute-passthrough.d.ts.map +1 -1
  161. package/dist/src/mcp/tools/execute-passthrough.js +71 -30
  162. package/dist/src/mcp/tools/execute-passthrough.js.map +1 -1
  163. package/dist/src/mcp/tools/generate-kb.d.ts +8 -0
  164. package/dist/src/mcp/tools/generate-kb.d.ts.map +1 -0
  165. package/dist/src/mcp/tools/generate-kb.js +52 -0
  166. package/dist/src/mcp/tools/generate-kb.js.map +1 -0
  167. package/dist/src/mcp/tools/graph-visualize-passthrough.d.ts.map +1 -1
  168. package/dist/src/mcp/tools/graph-visualize-passthrough.js.map +1 -1
  169. package/dist/src/mcp/tools/interview-passthrough.d.ts.map +1 -1
  170. package/dist/src/mcp/tools/interview-passthrough.js +7 -3
  171. package/dist/src/mcp/tools/interview-passthrough.js.map +1 -1
  172. package/dist/src/mcp/tools/interview.d.ts.map +1 -1
  173. package/dist/src/mcp/tools/interview.js +4 -2
  174. package/dist/src/mcp/tools/interview.js.map +1 -1
  175. package/dist/src/mcp/tools/review-passthrough.js +1 -1
  176. package/dist/src/mcp/tools/review-passthrough.js.map +1 -1
  177. package/dist/src/mcp/tools/search-kb.d.ts +9 -0
  178. package/dist/src/mcp/tools/search-kb.d.ts.map +1 -0
  179. package/dist/src/mcp/tools/search-kb.js +26 -0
  180. package/dist/src/mcp/tools/search-kb.js.map +1 -0
  181. package/dist/src/mcp/tools/spec-passthrough.d.ts.map +1 -1
  182. package/dist/src/mcp/tools/spec-passthrough.js.map +1 -1
  183. package/dist/src/mcp/tools/spec.d.ts.map +1 -1
  184. package/dist/src/mcp/tools/spec.js.map +1 -1
  185. package/dist/src/mcp/tools/status.d.ts.map +1 -1
  186. package/dist/src/mcp/tools/status.js +1 -1
  187. package/dist/src/mcp/tools/status.js.map +1 -1
  188. package/dist/src/mcp/tools/sync-kb.d.ts +6 -0
  189. package/dist/src/mcp/tools/sync-kb.d.ts.map +1 -0
  190. package/dist/src/mcp/tools/sync-kb.js +23 -0
  191. package/dist/src/mcp/tools/sync-kb.js.map +1 -0
  192. package/dist/src/memory/memory-context-injector.d.ts.map +1 -1
  193. package/dist/src/memory/memory-context-injector.js +2 -6
  194. package/dist/src/memory/memory-context-injector.js.map +1 -1
  195. package/dist/src/memory/user-profile-store.d.ts.map +1 -1
  196. package/dist/src/memory/user-profile-store.js +1 -4
  197. package/dist/src/memory/user-profile-store.js.map +1 -1
  198. package/dist/src/recording/agg-converter.d.ts.map +1 -1
  199. package/dist/src/recording/agg-converter.js.map +1 -1
  200. package/dist/src/recording/agg-installer.d.ts.map +1 -1
  201. package/dist/src/recording/agg-installer.js.map +1 -1
  202. package/dist/src/recording/asciinema-installer.d.ts.map +1 -1
  203. package/dist/src/recording/asciinema-installer.js.map +1 -1
  204. package/dist/src/recording/asciinema-recorder.d.ts.map +1 -1
  205. package/dist/src/recording/asciinema-recorder.js.map +1 -1
  206. package/dist/src/recording/cast-generator.d.ts.map +1 -1
  207. package/dist/src/recording/cast-generator.js +38 -13
  208. package/dist/src/recording/cast-generator.js.map +1 -1
  209. package/dist/src/recording/filename-generator.d.ts.map +1 -1
  210. package/dist/src/recording/filename-generator.js +2 -2
  211. package/dist/src/recording/filename-generator.js.map +1 -1
  212. package/dist/src/recording/recording-orchestrator.d.ts.map +1 -1
  213. package/dist/src/recording/recording-orchestrator.js.map +1 -1
  214. package/dist/src/registry/base-registry.d.ts.map +1 -1
  215. package/dist/src/registry/base-registry.js.map +1 -1
  216. package/dist/src/resilience/lateral.d.ts.map +1 -1
  217. package/dist/src/resilience/lateral.js +6 -1
  218. package/dist/src/resilience/lateral.js.map +1 -1
  219. package/dist/src/resilience/prompts.d.ts.map +1 -1
  220. package/dist/src/resilience/prompts.js.map +1 -1
  221. package/dist/src/review/agent-matcher.d.ts.map +1 -1
  222. package/dist/src/review/agent-matcher.js.map +1 -1
  223. package/dist/src/review/context-collector.d.ts.map +1 -1
  224. package/dist/src/review/context-collector.js.map +1 -1
  225. package/dist/src/review/passthrough-engine.d.ts.map +1 -1
  226. package/dist/src/review/passthrough-engine.js +1 -3
  227. package/dist/src/review/passthrough-engine.js.map +1 -1
  228. package/dist/src/review/report-generator.d.ts.map +1 -1
  229. package/dist/src/review/report-generator.js.map +1 -1
  230. package/dist/src/scripts/postinstall.js +3 -1
  231. package/dist/src/scripts/postinstall.js.map +1 -1
  232. package/dist/src/spec/generator.d.ts.map +1 -1
  233. package/dist/src/spec/generator.js.map +1 -1
  234. package/dist/src/spec/passthrough-generator.d.ts.map +1 -1
  235. package/dist/src/spec/passthrough-generator.js.map +1 -1
  236. package/dist/src/spec/schema.js +1 -1
  237. package/dist/src/spec/schema.js.map +1 -1
  238. package/dist/src/spec/text-based-spec-generator.d.ts.map +1 -1
  239. package/dist/src/spec/text-based-spec-generator.js +3 -1
  240. package/dist/src/spec/text-based-spec-generator.js.map +1 -1
  241. package/dist/src/tui/hooks/event-store-reader.d.ts.map +1 -1
  242. package/dist/src/tui/hooks/event-store-reader.js +1 -3
  243. package/dist/src/tui/hooks/event-store-reader.js.map +1 -1
  244. package/dist/src/tui/hooks/useEventStorePoller.d.ts.map +1 -1
  245. package/dist/src/tui/hooks/useEventStorePoller.js +1 -3
  246. package/dist/src/tui/hooks/useEventStorePoller.js.map +1 -1
  247. package/package.json +5 -1
  248. package/schemas/gestalt.schema.json +41 -3
  249. package/skills/interview/SKILL.md +18 -1
@@ -5,7 +5,7 @@ import { loadConfig } from '../core/config.js';
5
5
  import { log } from '../core/log.js';
6
6
  import { getVersion, checkForUpdates, getCachedUpdateResult } from '../core/version.js';
7
7
  import { EventStore } from '../events/store.js';
8
- import { AnthropicAdapter } from '../llm/adapter.js';
8
+ import { createAdapter } from '../llm/factory.js';
9
9
  import { InterviewEngine } from '../interview/engine.js';
10
10
  import { PassthroughEngine } from '../interview/passthrough-engine.js';
11
11
  import { SpecGenerator } from '../spec/generator.js';
@@ -24,8 +24,11 @@ import { handleAgentPassthrough } from './tools/agent-passthrough.js';
24
24
  import { handleReviewPassthrough } from './tools/review-passthrough.js';
25
25
  import { handleCodeGraphPassthrough } from './tools/code-graph-passthrough.js';
26
26
  import { handleGraphVisualizePassthrough } from './tools/graph-visualize-passthrough.js';
27
+ import { handleGenerateKb } from './tools/generate-kb.js';
28
+ import { handleSearchKb } from './tools/search-kb.js';
29
+ import { handleSyncKb } from './tools/sync-kb.js';
27
30
  import { PassthroughReviewEngine } from '../review/passthrough-engine.js';
28
- import { interviewInputSchema, specInputSchema, executeInputSchema, agentCreateInputSchema, benchmarkInputSchema, statusInputSchema, codeGraphInputSchema, graphVisualizeInputSchema } from './schemas.js';
31
+ import { interviewInputSchema, specInputSchema, executeInputSchema, agentCreateInputSchema, benchmarkInputSchema, statusInputSchema, codeGraphInputSchema, graphVisualizeInputSchema, } from './schemas.js';
29
32
  import { PassthroughExecuteEngine } from '../execute/passthrough-engine.js';
30
33
  import { PassthroughAgentGenerator } from '../agent/passthrough-generator.js';
31
34
  import { RoleAgentRegistry } from '../agent/role-agent-registry.js';
@@ -48,37 +51,67 @@ export async function createMcpServer(configOverrides) {
48
51
  const ptEngine = new PassthroughEngine(eventStore, agentRegistry);
49
52
  const ptSpecGen = new PassthroughSpecGenerator(eventStore, agentRegistry);
50
53
  server.tool('ges_interview', 'Conduct a Gestalt-driven interview (passthrough mode — returns prompts for caller LLM to generate questions/scores). Actions: start, respond, score, complete.', {
51
- action: z.enum(['start', 'respond', 'score', 'complete']).describe('start: begin interview, respond: answer a question, score: check resolution, complete: finish interview'),
54
+ action: z
55
+ .enum(['start', 'respond', 'score', 'complete'])
56
+ .describe('start: begin interview, respond: answer a question, score: check resolution, complete: finish interview'),
52
57
  topic: z.string().optional().describe('Topic for the interview (required for start)'),
53
- sessionId: z.string().optional().describe('Session ID (required for respond/score/complete)'),
54
- response: z.string().optional().describe('User response to the current question (required for respond)'),
58
+ sessionId: z
59
+ .string()
60
+ .optional()
61
+ .describe('Session ID (required for respond/score/complete)'),
62
+ response: z
63
+ .string()
64
+ .optional()
65
+ .describe('User response to the current question (required for respond)'),
55
66
  cwd: z.string().optional().describe('Working directory for brownfield detection'),
56
- generatedQuestion: z.string().optional().describe('Question generated by the caller LLM (required for respond in passthrough mode)'),
57
- resolutionScore: z.object({
67
+ generatedQuestion: z
68
+ .string()
69
+ .optional()
70
+ .describe('Question generated by the caller LLM (required for respond in passthrough mode)'),
71
+ resolutionScore: z
72
+ .object({
58
73
  goalClarity: z.number().min(0).max(1),
59
74
  constraintClarity: z.number().min(0).max(1),
60
75
  successCriteria: z.number().min(0).max(1),
61
76
  priorityClarity: z.number().min(0).max(1),
62
77
  contextClarity: z.number().min(0).max(1).optional(),
63
78
  contradictions: z.array(z.string()).optional(),
64
- }).optional().describe('Resolution scores computed by the caller LLM'),
65
- record: z.boolean().optional().describe('Generate a GIF recording of the interview session on complete'),
79
+ })
80
+ .optional()
81
+ .describe('Resolution scores computed by the caller LLM'),
82
+ record: z
83
+ .boolean()
84
+ .optional()
85
+ .describe('Generate a GIF recording of the interview session on complete'),
66
86
  }, (params) => {
67
87
  const input = interviewInputSchema.parse(params);
68
88
  const result = handleInterviewPassthrough(ptEngine, input);
69
89
  return { content: [{ type: 'text', text: result }] };
70
90
  });
71
91
  server.tool('ges_generate_spec', 'Generate a Spec specification (passthrough mode — returns prompt or validates externally generated spec).', {
72
- sessionId: z.string().optional().describe('Interview session ID (required when not using text input)'),
73
- text: z.string().optional().describe('Plain text description to generate spec directly without interview'),
74
- force: z.boolean().optional().default(false).describe('Force generation even if resolution threshold is not met'),
75
- spec: z.object({
92
+ sessionId: z
93
+ .string()
94
+ .optional()
95
+ .describe('Interview session ID (required when not using text input)'),
96
+ text: z
97
+ .string()
98
+ .optional()
99
+ .describe('Plain text description to generate spec directly without interview'),
100
+ force: z
101
+ .boolean()
102
+ .optional()
103
+ .default(false)
104
+ .describe('Force generation even if resolution threshold is not met'),
105
+ spec: z
106
+ .object({
76
107
  goal: z.string(),
77
108
  constraints: z.array(z.string()),
78
109
  acceptanceCriteria: z.array(z.string()),
79
110
  ontologySchema: z.object({ entities: z.array(z.any()), relations: z.array(z.any()) }),
80
111
  gestaltAnalysis: z.array(z.any()),
81
- }).optional().describe('Externally generated spec JSON to validate and store'),
112
+ })
113
+ .optional()
114
+ .describe('Externally generated spec JSON to validate and store'),
82
115
  }, (params) => {
83
116
  const input = specInputSchema.parse(params);
84
117
  const result = handleSpecPassthrough(ptEngine, ptSpecGen, input, agentRegistry);
@@ -89,14 +122,31 @@ export async function createMcpServer(configOverrides) {
89
122
  const ptExecuteEngine = new PassthroughExecuteEngine(eventStore, agentRegistry, roleAgentRegistry);
90
123
  const ptReviewEngine = new PassthroughReviewEngine(eventStore);
91
124
  server.tool('ges_execute', 'Execute a Spec specification using Gestalt principles (passthrough mode). Actions: start, plan_step, plan_complete, execute_start, execute_task, evaluate, status, evolve_fix, evolve, evolve_patch, evolve_re_execute, evolve_lateral, evolve_lateral_result, review_start, review_submit, review_consensus, review_fix.', {
92
- action: z.enum([
93
- 'start', 'plan_step', 'plan_complete', 'execute_start', 'execute_task', 'evaluate', 'status',
94
- 'evolve_fix', 'evolve', 'evolve_patch', 'evolve_re_execute',
95
- 'evolve_lateral', 'evolve_lateral_result',
96
- 'role_match', 'role_consensus',
97
- 'review_start', 'review_submit', 'review_consensus', 'review_fix',
98
- ]).describe('planning: start/plan_step/plan_complete, execution: execute_start/execute_task, evaluate: check results, status: session status, evolve_*: resilience loop, review_*: code review'),
99
- spec: z.object({
125
+ action: z
126
+ .enum([
127
+ 'start',
128
+ 'plan_step',
129
+ 'plan_complete',
130
+ 'execute_start',
131
+ 'execute_task',
132
+ 'evaluate',
133
+ 'status',
134
+ 'evolve_fix',
135
+ 'evolve',
136
+ 'evolve_patch',
137
+ 'evolve_re_execute',
138
+ 'evolve_lateral',
139
+ 'evolve_lateral_result',
140
+ 'role_match',
141
+ 'role_consensus',
142
+ 'review_start',
143
+ 'review_submit',
144
+ 'review_consensus',
145
+ 'review_fix',
146
+ ])
147
+ .describe('planning: start/plan_step/plan_complete, execution: execute_start/execute_task, evaluate: check results, status: session status, evolve_*: resilience loop, review_*: code review'),
148
+ spec: z
149
+ .object({
100
150
  version: z.string(),
101
151
  goal: z.string(),
102
152
  constraints: z.array(z.string()),
@@ -109,14 +159,21 @@ export async function createMcpServer(configOverrides) {
109
159
  resolutionScore: z.number(),
110
160
  generatedAt: z.string(),
111
161
  }),
112
- }).optional().describe('Spec specification (required for start)'),
113
- sessionId: z.string().optional().describe('Execute session ID (required for plan_step/plan_complete/status)'),
114
- stepResult: z.object({
162
+ })
163
+ .optional()
164
+ .describe('Spec specification (required for start)'),
165
+ sessionId: z
166
+ .string()
167
+ .optional()
168
+ .describe('Execute session ID (required for plan_step/plan_complete/status)'),
169
+ stepResult: z
170
+ .object({
115
171
  principle: z.enum(['figure_ground', 'closure', 'proximity', 'continuity']),
116
172
  classifiedACs: z.array(z.any()).optional(),
117
173
  atomicTasks: z.array(z.any()).optional(),
118
174
  taskGroups: z.array(z.any()).optional(),
119
- dagValidation: z.object({
175
+ dagValidation: z
176
+ .object({
120
177
  isValid: z.boolean(),
121
178
  hasCycles: z.boolean(),
122
179
  cycleDetails: z.array(z.string()).optional(),
@@ -124,15 +181,22 @@ export async function createMcpServer(configOverrides) {
124
181
  conflictDetails: z.array(z.string()).optional(),
125
182
  topologicalOrder: z.array(z.string()),
126
183
  criticalPath: z.array(z.string()),
127
- }).optional(),
128
- }).optional().describe('Planning step result (required for plan_step)'),
129
- taskResult: z.object({
184
+ })
185
+ .optional(),
186
+ })
187
+ .optional()
188
+ .describe('Planning step result (required for plan_step)'),
189
+ taskResult: z
190
+ .object({
130
191
  taskId: z.string(),
131
192
  status: z.enum(['pending', 'in_progress', 'completed', 'failed', 'skipped']),
132
193
  output: z.string(),
133
194
  artifacts: z.array(z.string()),
134
- }).optional().describe('Task execution result (required for execute_task)'),
135
- evaluationResult: z.object({
195
+ })
196
+ .optional()
197
+ .describe('Task execution result (required for execute_task)'),
198
+ evaluationResult: z
199
+ .object({
136
200
  verifications: z.array(z.object({
137
201
  acIndex: z.number(),
138
202
  satisfied: z.boolean(),
@@ -142,8 +206,11 @@ export async function createMcpServer(configOverrides) {
142
206
  overallScore: z.number().min(0).max(1),
143
207
  goalAlignment: z.number().min(0).max(1).optional().default(0),
144
208
  recommendations: z.array(z.string()),
145
- }).optional().describe('Evaluation result (optional for evaluate action)'),
146
- structuralResult: z.object({
209
+ })
210
+ .optional()
211
+ .describe('Evaluation result (optional for evaluate action)'),
212
+ structuralResult: z
213
+ .object({
147
214
  commands: z.array(z.object({
148
215
  name: z.string(),
149
216
  command: z.string(),
@@ -151,53 +218,78 @@ export async function createMcpServer(configOverrides) {
151
218
  output: z.string(),
152
219
  })),
153
220
  allPassed: z.boolean(),
154
- }).optional().describe('Structural check results (required for evaluate after structural stage)'),
155
- fixTasks: z.array(z.object({
221
+ })
222
+ .optional()
223
+ .describe('Structural check results (required for evaluate after structural stage)'),
224
+ fixTasks: z
225
+ .array(z.object({
156
226
  taskId: z.string(),
157
227
  failedCommand: z.string(),
158
228
  errorOutput: z.string(),
159
229
  fixDescription: z.string(),
160
230
  artifacts: z.array(z.string()),
161
- })).optional().describe('Fix task results (for evolve_fix)'),
162
- specPatch: z.object({
231
+ }))
232
+ .optional()
233
+ .describe('Fix task results (for evolve_fix)'),
234
+ specPatch: z
235
+ .object({
163
236
  acceptanceCriteria: z.array(z.string()).optional(),
164
237
  constraints: z.array(z.string()).optional(),
165
- ontologySchema: z.object({
238
+ ontologySchema: z
239
+ .object({
166
240
  entities: z.array(z.any()).optional(),
167
241
  relations: z.array(z.any()).optional(),
168
- }).optional(),
169
- }).optional().describe('Spec patch for contextual evolution (for evolve_patch)'),
170
- reExecuteTaskResult: z.object({
242
+ })
243
+ .optional(),
244
+ })
245
+ .optional()
246
+ .describe('Spec patch for contextual evolution (for evolve_patch)'),
247
+ reExecuteTaskResult: z
248
+ .object({
171
249
  taskId: z.string(),
172
250
  status: z.enum(['pending', 'in_progress', 'completed', 'failed', 'skipped']),
173
251
  output: z.string(),
174
252
  artifacts: z.array(z.string()),
175
- }).optional().describe('Re-execution task result (for evolve_re_execute)'),
253
+ })
254
+ .optional()
255
+ .describe('Re-execution task result (for evolve_re_execute)'),
176
256
  terminateReason: z.enum(['caller']).optional().describe('Caller-initiated termination'),
177
- lateralResult: z.object({
257
+ lateralResult: z
258
+ .object({
178
259
  persona: z.enum(['multistability', 'simplicity', 'reification', 'invariance']),
179
260
  specPatch: z.object({
180
261
  acceptanceCriteria: z.array(z.string()).optional(),
181
262
  constraints: z.array(z.string()).optional(),
182
- ontologySchema: z.object({
263
+ ontologySchema: z
264
+ .object({
183
265
  entities: z.array(z.any()).optional(),
184
266
  relations: z.array(z.any()).optional(),
185
- }).optional(),
267
+ })
268
+ .optional(),
186
269
  }),
187
270
  description: z.string(),
188
- }).optional().describe('Lateral thinking result (for evolve_lateral_result)'),
189
- matchResult: z.array(z.object({
271
+ })
272
+ .optional()
273
+ .describe('Lateral thinking result (for evolve_lateral_result)'),
274
+ matchResult: z
275
+ .array(z.object({
190
276
  agentName: z.string(),
191
277
  domain: z.array(z.string()),
192
278
  relevanceScore: z.number().min(0).max(1),
193
279
  reasoning: z.string(),
194
- })).optional().describe('Role match results (for role_match action)'),
195
- perspectives: z.array(z.object({
280
+ }))
281
+ .optional()
282
+ .describe('Role match results (for role_match action)'),
283
+ perspectives: z
284
+ .array(z.object({
196
285
  agentName: z.string(),
197
286
  perspective: z.string(),
198
287
  confidence: z.number().min(0).max(1),
199
- })).optional().describe('Role perspectives (for role_consensus action)'),
200
- consensus: z.object({
288
+ }))
289
+ .optional()
290
+ .describe('Role perspectives (for role_consensus action)'),
291
+ consensus: z
292
+ .object({
201
293
  consensus: z.string(),
202
294
  conflictResolutions: z.array(z.string()),
203
295
  perspectives: z.array(z.object({
@@ -205,7 +297,9 @@ export async function createMcpServer(configOverrides) {
205
297
  perspective: z.string(),
206
298
  confidence: z.number().min(0).max(1),
207
299
  })),
208
- }).optional().describe('Synthesized consensus (for role_consensus action)'),
300
+ })
301
+ .optional()
302
+ .describe('Synthesized consensus (for role_consensus action)'),
209
303
  }, async (params) => {
210
304
  const input = executeInputSchema.parse(params);
211
305
  // Route review actions to review engine
@@ -218,18 +312,31 @@ export async function createMcpServer(configOverrides) {
218
312
  });
219
313
  const ptAgentGen = new PassthroughAgentGenerator(eventStore, roleAgentRegistry);
220
314
  server.tool('ges_create_agent', 'Create a custom Role Agent from a completed interview session (passthrough mode). Actions: start, submit.', {
221
- action: z.enum(['start', 'submit']).describe('start: get agent creation context with prompts, submit: validate and save AGENT.md'),
315
+ action: z
316
+ .enum(['start', 'submit'])
317
+ .describe('start: get agent creation context with prompts, submit: validate and save AGENT.md'),
222
318
  sessionId: z.string().describe('The interview session ID'),
223
- agentContent: z.string().optional().describe('Complete AGENT.md content (frontmatter + body) to validate and save (required for submit)'),
224
- cwd: z.string().optional().describe('Working directory where agents/{name}/AGENT.md will be created (defaults to process.cwd())'),
319
+ agentContent: z
320
+ .string()
321
+ .optional()
322
+ .describe('Complete AGENT.md content (frontmatter + body) to validate and save (required for submit)'),
323
+ cwd: z
324
+ .string()
325
+ .optional()
326
+ .describe('Working directory where agents/{name}/AGENT.md will be created (defaults to process.cwd())'),
225
327
  }, (params) => {
226
328
  const input = agentCreateInputSchema.parse(params);
227
329
  const result = handleCreateAgentPassthrough(ptEngine, ptAgentGen, input);
228
330
  return { content: [{ type: 'text', text: result }] };
229
331
  });
230
- server.tool('ges_agent', 'List available agents or retrieve a specific agent\'s system prompt for standalone use — no pipeline required. Actions: list (get all role/review agents), get (retrieve agent by name).', {
231
- action: z.enum(['list', 'get']).describe('list: get all available agents grouped by type, get: retrieve a specific agent\'s systemPrompt'),
232
- name: z.string().optional().describe('Agent name (required for action=get, e.g. "architect", "security-reviewer")'),
332
+ server.tool('ges_agent', "List available agents or retrieve a specific agent's system prompt for standalone use — no pipeline required. Actions: list (get all role/review agents), get (retrieve agent by name).", {
333
+ action: z
334
+ .enum(['list', 'get'])
335
+ .describe("list: get all available agents grouped by type, get: retrieve a specific agent's systemPrompt"),
336
+ name: z
337
+ .string()
338
+ .optional()
339
+ .describe('Agent name (required for action=get, e.g. "architect", "security-reviewer")'),
233
340
  }, (params) => {
234
341
  const result = handleAgentPassthrough(roleAgentRegistry, {
235
342
  action: params.action,
@@ -238,22 +345,42 @@ export async function createMcpServer(configOverrides) {
238
345
  return { content: [{ type: 'text', text: result }] };
239
346
  });
240
347
  server.tool('ges_benchmark', 'Run Gestalt pipeline benchmarks in passthrough mode. Actions: start (begin a scenario), respond (submit LLM response), status (check progress). No API key required — caller acts as the LLM.', {
241
- action: z.enum(['start', 'respond', 'status']).describe('start: begin benchmark scenario, respond: submit LLM response for current step, status: check benchmark progress'),
242
- scenario: z.string().optional().describe('Scenario name for start: auth-system, dashboard, api-gateway'),
243
- benchmarkSessionId: z.string().optional().describe('Benchmark session ID (required for respond/status)'),
244
- response: z.string().optional().describe('JSON response from the caller LLM (required for respond)'),
245
- usage: z.object({
348
+ action: z
349
+ .enum(['start', 'respond', 'status'])
350
+ .describe('start: begin benchmark scenario, respond: submit LLM response for current step, status: check benchmark progress'),
351
+ scenario: z
352
+ .string()
353
+ .optional()
354
+ .describe('Scenario name for start: auth-system, dashboard, api-gateway'),
355
+ benchmarkSessionId: z
356
+ .string()
357
+ .optional()
358
+ .describe('Benchmark session ID (required for respond/status)'),
359
+ response: z
360
+ .string()
361
+ .optional()
362
+ .describe('JSON response from the caller LLM (required for respond)'),
363
+ usage: z
364
+ .object({
246
365
  inputTokens: z.number(),
247
366
  outputTokens: z.number(),
248
- }).optional().describe('Token usage from the caller LLM call (optional, for metrics)'),
367
+ })
368
+ .optional()
369
+ .describe('Token usage from the caller LLM call (optional, for metrics)'),
249
370
  }, (params) => {
250
371
  const input = benchmarkInputSchema.parse(params);
251
372
  const result = handleBenchmarkPassthrough(input);
252
373
  return { content: [{ type: 'text', text: result }] };
253
374
  });
254
375
  server.tool('ges_status', 'Check the status of interview and execute sessions.', {
255
- sessionId: z.string().optional().describe('Specific session ID to check (omit for all sessions)'),
256
- sessionType: z.enum(['interview', 'execute', 'all']).optional().default('all')
376
+ sessionId: z
377
+ .string()
378
+ .optional()
379
+ .describe('Specific session ID to check (omit for all sessions)'),
380
+ sessionType: z
381
+ .enum(['interview', 'execute', 'all'])
382
+ .optional()
383
+ .default('all')
257
384
  .describe('Filter by session type (default: all)'),
258
385
  }, (params) => {
259
386
  const input = statusInputSchema.parse(params);
@@ -261,17 +388,36 @@ export async function createMcpServer(configOverrides) {
261
388
  return { content: [{ type: 'text', text: result }] };
262
389
  });
263
390
  server.tool('ges_code_graph', 'Build and query the code knowledge graph for a repository. Actions: build (index codebase), blast_radius (find impacted files from changes), query (graph traversal), stats (show DB stats), db_exists (check if graph DB exists).', {
264
- action: z.enum(['build', 'blast_radius', 'query', 'stats', 'db_exists']).describe('build: index codebase into graph DB, blast_radius: find files impacted by changes, query: traverse graph, stats: show stats, db_exists: check if DB exists'),
391
+ action: z
392
+ .enum(['build', 'blast_radius', 'query', 'stats', 'db_exists'])
393
+ .describe('build: index codebase into graph DB, blast_radius: find files impacted by changes, query: traverse graph, stats: show stats, db_exists: check if DB exists'),
265
394
  repoRoot: z.string().describe('Absolute path to the repository root'),
266
- include: z.array(z.string()).optional().describe('Glob patterns to include (default: **/*)'),
395
+ include: z
396
+ .array(z.string())
397
+ .optional()
398
+ .describe('Glob patterns to include (default: **/*)'),
267
399
  exclude: z.array(z.string()).optional().describe('Glob patterns to exclude'),
268
- mode: z.enum(['full', 'incremental']).optional().describe('Build mode: full (default) or incremental (hash-based skip)'),
269
- changedFiles: z.array(z.string()).optional().describe('Changed file paths (auto-detected from git diff HEAD~1 if omitted)'),
400
+ mode: z
401
+ .enum(['full', 'incremental'])
402
+ .optional()
403
+ .describe('Build mode: full (default) or incremental (hash-based skip)'),
404
+ changedFiles: z
405
+ .array(z.string())
406
+ .optional()
407
+ .describe('Changed file paths (auto-detected from git diff HEAD~1 if omitted)'),
270
408
  base: z.string().optional().describe('Git base ref for diff detection (default: HEAD~1)'),
271
- maxDepth: z.number().optional().describe('BFS traversal depth for blast_radius (default: 2)'),
272
- pattern: z.enum(['callers_of', 'callees_of', 'tests_for', 'imports_of']).optional()
409
+ maxDepth: z
410
+ .number()
411
+ .optional()
412
+ .describe('BFS traversal depth for blast_radius (default: 2)'),
413
+ pattern: z
414
+ .enum(['callers_of', 'callees_of', 'tests_for', 'imports_of'])
415
+ .optional()
273
416
  .describe('Query pattern (required for query action)'),
274
- target: z.string().optional().describe('Target function or file path (required for query action)'),
417
+ target: z
418
+ .string()
419
+ .optional()
420
+ .describe('Target function or file path (required for query action)'),
275
421
  }, async (params) => {
276
422
  const input = codeGraphInputSchema.parse(params);
277
423
  const result = await handleCodeGraphPassthrough(input);
@@ -279,25 +425,69 @@ export async function createMcpServer(configOverrides) {
279
425
  });
280
426
  server.tool('ges_graph_visualize', 'Start a local HTTP server that renders an interactive D3.js force-directed graph visualization of the code knowledge graph. Opens the browser automatically. Requires an existing or auto-buildable code-graph.db.', {
281
427
  repoRoot: z.string().describe('Absolute path to the repository root'),
282
- port: z.number().optional().describe('Preferred server port (default: 7891, auto-increments on conflict)'),
428
+ port: z
429
+ .number()
430
+ .optional()
431
+ .describe('Preferred server port (default: 7891, auto-increments on conflict)'),
283
432
  }, async (params) => {
284
433
  const input = graphVisualizeInputSchema.parse(params);
285
434
  const result = await handleGraphVisualizePassthrough(input);
286
435
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
287
436
  });
437
+ server.tool('ges_generate_kb', 'Gestalt 코드 그래프 분석 결과 및 도메인 내용을 MD 파일로 내보내고 임베딩을 생성합니다', {
438
+ repoRoot: z.string().optional().describe('분석할 레포 경로 (기본: cwd)'),
439
+ outputPath: z.string().optional().describe('출력 경로 (기본: .gestalt-kb/)'),
440
+ types: z
441
+ .array(z.enum(['code-graph', 'business-logic', 'api-spec', 'adr', 'policy']))
442
+ .optional()
443
+ .describe('생성할 타입 필터'),
444
+ }, async (params) => {
445
+ const result = await handleGenerateKb(params, process.cwd());
446
+ return { content: [{ type: 'text', text: result }] };
447
+ });
448
+ server.tool('ges_search', 'Knowledge Base에서 시맨틱 검색을 수행합니다', {
449
+ query: z.string().describe('검색 쿼리'),
450
+ k: z.number().optional().describe('반환할 결과 수 (기본: 5)'),
451
+ kbPath: z.string().optional().describe('Knowledge Base 경로 (기본: .gestalt-kb/)'),
452
+ types: z
453
+ .array(z.enum(['code-graph', 'business-logic', 'api-spec', 'adr', 'policy']))
454
+ .optional()
455
+ .describe('검색할 타입 필터'),
456
+ }, async (params) => {
457
+ const result = await handleSearchKb(params, process.cwd());
458
+ return { content: [{ type: 'text', text: result }] };
459
+ });
460
+ server.tool('ges_sync', 'Knowledge Base를 다른 경로로 동기화(복사)합니다', {
461
+ sourcePath: z.string().optional().describe('소스 경로 (기본: .gestalt-kb/)'),
462
+ targetPath: z.string().describe('동기화 대상 경로'),
463
+ }, async (params) => {
464
+ const result = await handleSyncKb(params, process.cwd());
465
+ return { content: [{ type: 'text', text: result }] };
466
+ });
288
467
  }
289
468
  else {
290
469
  // ─── Normal mode: direct LLM calls ──────────────────────────
291
- const llm = new AnthropicAdapter(config.llm.apiKey, config.llm.model);
470
+ const llm = createAdapter(config.llm);
292
471
  const engine = new InterviewEngine(llm, eventStore);
293
472
  const specGenerator = new SpecGenerator(llm, eventStore);
294
473
  server.tool('ges_interview', 'Conduct a Gestalt-driven interview to clarify project requirements. Actions: start, respond, score, complete.', {
295
- action: z.enum(['start', 'respond', 'score', 'complete']).describe('start: begin interview, respond: answer a question, score: check resolution, complete: finish interview'),
474
+ action: z
475
+ .enum(['start', 'respond', 'score', 'complete'])
476
+ .describe('start: begin interview, respond: answer a question, score: check resolution, complete: finish interview'),
296
477
  topic: z.string().optional().describe('Topic for the interview (required for start)'),
297
- sessionId: z.string().optional().describe('Session ID (required for respond/score/complete)'),
298
- response: z.string().optional().describe('User response to the current question (required for respond)'),
478
+ sessionId: z
479
+ .string()
480
+ .optional()
481
+ .describe('Session ID (required for respond/score/complete)'),
482
+ response: z
483
+ .string()
484
+ .optional()
485
+ .describe('User response to the current question (required for respond)'),
299
486
  cwd: z.string().optional().describe('Working directory for brownfield detection'),
300
- record: z.boolean().optional().describe('Generate a GIF recording of the interview session on complete'),
487
+ record: z
488
+ .boolean()
489
+ .optional()
490
+ .describe('Generate a GIF recording of the interview session on complete'),
301
491
  }, async (params) => {
302
492
  const input = interviewInputSchema.parse(params);
303
493
  const result = await handleInterview(engine, input);
@@ -305,15 +495,25 @@ export async function createMcpServer(configOverrides) {
305
495
  });
306
496
  server.tool('ges_generate_spec', 'Generate a Spec specification from a completed interview session.', {
307
497
  sessionId: z.string().describe('The interview session ID'),
308
- force: z.boolean().optional().default(false).describe('Force generation even if resolution threshold is not met'),
498
+ force: z
499
+ .boolean()
500
+ .optional()
501
+ .default(false)
502
+ .describe('Force generation even if resolution threshold is not met'),
309
503
  }, async (params) => {
310
504
  const input = specInputSchema.parse(params);
311
505
  const result = await handleSpec(engine, specGenerator, input);
312
506
  return { content: [{ type: 'text', text: result }] };
313
507
  });
314
508
  server.tool('ges_status', 'Check the status of interview and execute sessions.', {
315
- sessionId: z.string().optional().describe('Specific session ID to check (omit for all sessions)'),
316
- sessionType: z.enum(['interview', 'execute', 'all']).optional().default('all')
509
+ sessionId: z
510
+ .string()
511
+ .optional()
512
+ .describe('Specific session ID to check (omit for all sessions)'),
513
+ sessionType: z
514
+ .enum(['interview', 'execute', 'all'])
515
+ .optional()
516
+ .default('all')
317
517
  .describe('Filter by session type (default: all)'),
318
518
  }, (params) => {
319
519
  const input = statusInputSchema.parse(params);
@@ -369,7 +569,7 @@ function handleStatusPassthrough(engine, executeEngine, input) {
369
569
  }
370
570
  }
371
571
  // List mode
372
- const interviewSessions = (sessionType === 'interview' || sessionType === 'all')
572
+ const interviewSessions = sessionType === 'interview' || sessionType === 'all'
373
573
  ? engine.listSessions().map((s) => ({
374
574
  sessionId: s.sessionId,
375
575
  topic: s.topic,
@@ -380,7 +580,7 @@ function handleStatusPassthrough(engine, executeEngine, input) {
380
580
  createdAt: s.createdAt,
381
581
  }))
382
582
  : [];
383
- const executeSessions = (sessionType === 'execute' || sessionType === 'all')
583
+ const executeSessions = sessionType === 'execute' || sessionType === 'all'
384
584
  ? executeEngine.listSessions().map((s) => formatExecuteSessionSummary(s))
385
585
  : [];
386
586
  return JSON.stringify({
@@ -434,38 +634,49 @@ function formatExecuteSession(session) {
434
634
  currentStep: session.currentStep,
435
635
  stepsCompleted: session.planningSteps.map((s) => s.principle),
436
636
  hasPlan: !!session.executionPlan,
437
- taskProgress: { total: totalTasks, completed: completedTasks, failed: failedTasks, pending: pendingTasks },
637
+ taskProgress: {
638
+ total: totalTasks,
639
+ completed: completedTasks,
640
+ failed: failedTasks,
641
+ pending: pendingTasks,
642
+ },
438
643
  satisfiedACs: `${satisfiedACs}/${totalACs}`,
439
644
  evaluateStage: session.evaluateStage ?? null,
440
645
  hasEvaluation: !!session.evaluationResult,
441
646
  evaluationScore: session.evaluationResult?.overallScore ?? null,
442
647
  goalAlignment: session.evaluationResult?.goalAlignment ?? null,
443
648
  driftAlerts: session.driftHistory.filter((d) => d.thresholdExceeded).length,
444
- evolution: session.evolutionHistory.length > 0 ? {
445
- scoreProgression: session.evolutionHistory.map((gen) => ({
446
- generation: gen.generation,
447
- score: gen.evaluationScore,
448
- goalAlignment: gen.goalAlignment,
449
- fieldsChanged: Object.keys(gen.delta).filter((k) => {
450
- const val = gen.delta[k];
451
- return Array.isArray(val) ? val.length > 0 : val !== undefined;
452
- }),
453
- })),
454
- summary: summarizeEvolution(session),
455
- } : null,
649
+ evolution: session.evolutionHistory.length > 0
650
+ ? {
651
+ scoreProgression: session.evolutionHistory.map((gen) => ({
652
+ generation: gen.generation,
653
+ score: gen.evaluationScore,
654
+ goalAlignment: gen.goalAlignment,
655
+ fieldsChanged: Object.keys(gen.delta).filter((k) => {
656
+ const val = gen.delta[k];
657
+ return Array.isArray(val) ? val.length > 0 : val !== undefined;
658
+ }),
659
+ })),
660
+ summary: summarizeEvolution(session),
661
+ }
662
+ : null,
456
663
  evolveStage: session.evolveStage ?? null,
457
664
  currentGeneration: session.currentGeneration,
458
665
  terminationReason: session.terminationReason ?? null,
459
- lateral: session.lateralTriedPersonas.length > 0 ? {
460
- triedPersonas: session.lateralTriedPersonas,
461
- totalAttempts: session.lateralAttempts,
462
- currentPersona: session.lateralCurrentPersona ?? null,
463
- currentPattern: session.lateralCurrentPattern ?? null,
464
- } : null,
465
- roleAgent: session.roleMatches ? {
466
- matchedAgents: session.roleMatches.map((m) => m.agentName),
467
- hasConsensus: !!session.roleConsensus,
468
- } : null,
666
+ lateral: session.lateralTriedPersonas.length > 0
667
+ ? {
668
+ triedPersonas: session.lateralTriedPersonas,
669
+ totalAttempts: session.lateralAttempts,
670
+ currentPersona: session.lateralCurrentPersona ?? null,
671
+ currentPattern: session.lateralCurrentPattern ?? null,
672
+ }
673
+ : null,
674
+ roleAgent: session.roleMatches
675
+ ? {
676
+ matchedAgents: session.roleMatches.map((m) => m.agentName),
677
+ hasConsensus: !!session.roleConsensus,
678
+ }
679
+ : null,
469
680
  createdAt: session.createdAt,
470
681
  updatedAt: session.updatedAt,
471
682
  };
@@ -497,12 +708,14 @@ export async function startMcpServer(configOverrides) {
497
708
  const transport = new StdioServerTransport();
498
709
  await server.connect(transport);
499
710
  log(`MCP server started on stdio${isPassthrough ? ' (passthrough mode)' : ''}`);
500
- checkForUpdates().then((result) => {
711
+ checkForUpdates()
712
+ .then((result) => {
501
713
  if (result?.updateAvailable) {
502
714
  log(`Update available: ${result.currentVersion} → ${result.latestVersion}`);
503
715
  log(`Run: npx -y @tienne/gestalt@latest`);
504
716
  }
505
- }).catch(() => { });
717
+ })
718
+ .catch(() => { });
506
719
  process.on('SIGINT', async () => {
507
720
  await skillRegistry.stopWatching();
508
721
  await agentRegistry.stopWatching();