gitmem-mcp 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/CLAUDE.md.template +65 -0
  3. package/LICENSE +21 -0
  4. package/README.md +221 -0
  5. package/bin/gitmem.js +383 -0
  6. package/dist/commands/check.d.ts +33 -0
  7. package/dist/commands/check.d.ts.map +1 -0
  8. package/dist/commands/check.js +492 -0
  9. package/dist/commands/check.js.map +1 -0
  10. package/dist/constants/closing-questions.d.ts +40 -0
  11. package/dist/constants/closing-questions.d.ts.map +1 -0
  12. package/dist/constants/closing-questions.js +107 -0
  13. package/dist/constants/closing-questions.js.map +1 -0
  14. package/dist/diagnostics/anonymizer.d.ts +55 -0
  15. package/dist/diagnostics/anonymizer.d.ts.map +1 -0
  16. package/dist/diagnostics/anonymizer.js +191 -0
  17. package/dist/diagnostics/anonymizer.js.map +1 -0
  18. package/dist/diagnostics/channels.d.ts +132 -0
  19. package/dist/diagnostics/channels.d.ts.map +1 -0
  20. package/dist/diagnostics/channels.js +150 -0
  21. package/dist/diagnostics/channels.js.map +1 -0
  22. package/dist/diagnostics/collector.d.ts +183 -0
  23. package/dist/diagnostics/collector.d.ts.map +1 -0
  24. package/dist/diagnostics/collector.js +227 -0
  25. package/dist/diagnostics/collector.js.map +1 -0
  26. package/dist/diagnostics/index.d.ts +28 -0
  27. package/dist/diagnostics/index.d.ts.map +1 -0
  28. package/dist/diagnostics/index.js +31 -0
  29. package/dist/diagnostics/index.js.map +1 -0
  30. package/dist/index.d.ts +13 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +18 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/schemas/absorb-observations.d.ts +63 -0
  35. package/dist/schemas/absorb-observations.d.ts.map +1 -0
  36. package/dist/schemas/absorb-observations.js +25 -0
  37. package/dist/schemas/absorb-observations.js.map +1 -0
  38. package/dist/schemas/active-sessions.d.ts +71 -0
  39. package/dist/schemas/active-sessions.d.ts.map +1 -0
  40. package/dist/schemas/active-sessions.js +19 -0
  41. package/dist/schemas/active-sessions.js.map +1 -0
  42. package/dist/schemas/analyze.d.ts +38 -0
  43. package/dist/schemas/analyze.d.ts.map +1 -0
  44. package/dist/schemas/analyze.js +30 -0
  45. package/dist/schemas/analyze.js.map +1 -0
  46. package/dist/schemas/common.d.ts +55 -0
  47. package/dist/schemas/common.d.ts.map +1 -0
  48. package/dist/schemas/common.js +65 -0
  49. package/dist/schemas/common.js.map +1 -0
  50. package/dist/schemas/create-decision.d.ts +48 -0
  51. package/dist/schemas/create-decision.d.ts.map +1 -0
  52. package/dist/schemas/create-decision.js +31 -0
  53. package/dist/schemas/create-decision.js.map +1 -0
  54. package/dist/schemas/create-learning.d.ts +107 -0
  55. package/dist/schemas/create-learning.d.ts.map +1 -0
  56. package/dist/schemas/create-learning.js +64 -0
  57. package/dist/schemas/create-learning.js.map +1 -0
  58. package/dist/schemas/get-transcript.d.ts +24 -0
  59. package/dist/schemas/get-transcript.d.ts.map +1 -0
  60. package/dist/schemas/get-transcript.js +22 -0
  61. package/dist/schemas/get-transcript.js.map +1 -0
  62. package/dist/schemas/index.d.ts +23 -0
  63. package/dist/schemas/index.d.ts.map +1 -0
  64. package/dist/schemas/index.js +23 -0
  65. package/dist/schemas/index.js.map +1 -0
  66. package/dist/schemas/log.d.ts +36 -0
  67. package/dist/schemas/log.d.ts.map +1 -0
  68. package/dist/schemas/log.js +27 -0
  69. package/dist/schemas/log.js.map +1 -0
  70. package/dist/schemas/prepare-context.d.ts +41 -0
  71. package/dist/schemas/prepare-context.d.ts.map +1 -0
  72. package/dist/schemas/prepare-context.js +31 -0
  73. package/dist/schemas/prepare-context.js.map +1 -0
  74. package/dist/schemas/recall.d.ts +41 -0
  75. package/dist/schemas/recall.d.ts.map +1 -0
  76. package/dist/schemas/recall.js +47 -0
  77. package/dist/schemas/recall.js.map +1 -0
  78. package/dist/schemas/record-scar-usage-batch.d.ts +82 -0
  79. package/dist/schemas/record-scar-usage-batch.d.ts.map +1 -0
  80. package/dist/schemas/record-scar-usage-batch.js +25 -0
  81. package/dist/schemas/record-scar-usage-batch.js.map +1 -0
  82. package/dist/schemas/record-scar-usage.d.ts +51 -0
  83. package/dist/schemas/record-scar-usage.d.ts.map +1 -0
  84. package/dist/schemas/record-scar-usage.js +32 -0
  85. package/dist/schemas/record-scar-usage.js.map +1 -0
  86. package/dist/schemas/save-transcript.d.ts +38 -0
  87. package/dist/schemas/save-transcript.d.ts.map +1 -0
  88. package/dist/schemas/save-transcript.js +30 -0
  89. package/dist/schemas/save-transcript.js.map +1 -0
  90. package/dist/schemas/search.d.ts +36 -0
  91. package/dist/schemas/search.d.ts.map +1 -0
  92. package/dist/schemas/search.js +27 -0
  93. package/dist/schemas/search.js.map +1 -0
  94. package/dist/schemas/session-close.d.ts +371 -0
  95. package/dist/schemas/session-close.d.ts.map +1 -0
  96. package/dist/schemas/session-close.js +95 -0
  97. package/dist/schemas/session-close.js.map +1 -0
  98. package/dist/schemas/session-start.d.ts +46 -0
  99. package/dist/schemas/session-start.d.ts.map +1 -0
  100. package/dist/schemas/session-start.js +33 -0
  101. package/dist/schemas/session-start.js.map +1 -0
  102. package/dist/schemas/thread.d.ts +72 -0
  103. package/dist/schemas/thread.d.ts.map +1 -0
  104. package/dist/schemas/thread.js +39 -0
  105. package/dist/schemas/thread.js.map +1 -0
  106. package/dist/server.d.ts +22 -0
  107. package/dist/server.d.ts.map +1 -0
  108. package/dist/server.js +313 -0
  109. package/dist/server.js.map +1 -0
  110. package/dist/services/active-sessions.d.ts +66 -0
  111. package/dist/services/active-sessions.d.ts.map +1 -0
  112. package/dist/services/active-sessions.js +311 -0
  113. package/dist/services/active-sessions.js.map +1 -0
  114. package/dist/services/agent-detection.d.ts +25 -0
  115. package/dist/services/agent-detection.d.ts.map +1 -0
  116. package/dist/services/agent-detection.js +93 -0
  117. package/dist/services/agent-detection.js.map +1 -0
  118. package/dist/services/analytics.d.ts +201 -0
  119. package/dist/services/analytics.d.ts.map +1 -0
  120. package/dist/services/analytics.js +483 -0
  121. package/dist/services/analytics.js.map +1 -0
  122. package/dist/services/cache.d.ts +148 -0
  123. package/dist/services/cache.d.ts.map +1 -0
  124. package/dist/services/cache.js +384 -0
  125. package/dist/services/cache.js.map +1 -0
  126. package/dist/services/cache.test.d.ts +8 -0
  127. package/dist/services/cache.test.d.ts.map +1 -0
  128. package/dist/services/cache.test.js +267 -0
  129. package/dist/services/cache.test.js.map +1 -0
  130. package/dist/services/compliance-validator.d.ts +30 -0
  131. package/dist/services/compliance-validator.d.ts.map +1 -0
  132. package/dist/services/compliance-validator.js +257 -0
  133. package/dist/services/compliance-validator.js.map +1 -0
  134. package/dist/services/config.d.ts +48 -0
  135. package/dist/services/config.d.ts.map +1 -0
  136. package/dist/services/config.js +128 -0
  137. package/dist/services/config.js.map +1 -0
  138. package/dist/services/embedding.d.ts +58 -0
  139. package/dist/services/embedding.d.ts.map +1 -0
  140. package/dist/services/embedding.js +243 -0
  141. package/dist/services/embedding.js.map +1 -0
  142. package/dist/services/gitmem-dir.d.ts +38 -0
  143. package/dist/services/gitmem-dir.d.ts.map +1 -0
  144. package/dist/services/gitmem-dir.js +84 -0
  145. package/dist/services/gitmem-dir.js.map +1 -0
  146. package/dist/services/local-file-storage.d.ts +56 -0
  147. package/dist/services/local-file-storage.d.ts.map +1 -0
  148. package/dist/services/local-file-storage.js +213 -0
  149. package/dist/services/local-file-storage.js.map +1 -0
  150. package/dist/services/local-vector-search.d.ts +137 -0
  151. package/dist/services/local-vector-search.d.ts.map +1 -0
  152. package/dist/services/local-vector-search.js +311 -0
  153. package/dist/services/local-vector-search.js.map +1 -0
  154. package/dist/services/metrics.d.ts +104 -0
  155. package/dist/services/metrics.d.ts.map +1 -0
  156. package/dist/services/metrics.js +264 -0
  157. package/dist/services/metrics.js.map +1 -0
  158. package/dist/services/session-state.d.ts +113 -0
  159. package/dist/services/session-state.d.ts.map +1 -0
  160. package/dist/services/session-state.js +203 -0
  161. package/dist/services/session-state.js.map +1 -0
  162. package/dist/services/startup.d.ts +112 -0
  163. package/dist/services/startup.d.ts.map +1 -0
  164. package/dist/services/startup.js +436 -0
  165. package/dist/services/startup.js.map +1 -0
  166. package/dist/services/storage.d.ts +43 -0
  167. package/dist/services/storage.d.ts.map +1 -0
  168. package/dist/services/storage.js +92 -0
  169. package/dist/services/storage.js.map +1 -0
  170. package/dist/services/supabase-client.d.ts +163 -0
  171. package/dist/services/supabase-client.d.ts.map +1 -0
  172. package/dist/services/supabase-client.js +510 -0
  173. package/dist/services/supabase-client.js.map +1 -0
  174. package/dist/services/thread-dedup.d.ts +44 -0
  175. package/dist/services/thread-dedup.d.ts.map +1 -0
  176. package/dist/services/thread-dedup.js +113 -0
  177. package/dist/services/thread-dedup.js.map +1 -0
  178. package/dist/services/thread-manager.d.ts +77 -0
  179. package/dist/services/thread-manager.d.ts.map +1 -0
  180. package/dist/services/thread-manager.js +250 -0
  181. package/dist/services/thread-manager.js.map +1 -0
  182. package/dist/services/thread-suggestions.d.ts +66 -0
  183. package/dist/services/thread-suggestions.d.ts.map +1 -0
  184. package/dist/services/thread-suggestions.js +243 -0
  185. package/dist/services/thread-suggestions.js.map +1 -0
  186. package/dist/services/thread-supabase.d.ts +111 -0
  187. package/dist/services/thread-supabase.d.ts.map +1 -0
  188. package/dist/services/thread-supabase.js +459 -0
  189. package/dist/services/thread-supabase.js.map +1 -0
  190. package/dist/services/thread-vitality.d.ts +65 -0
  191. package/dist/services/thread-vitality.d.ts.map +1 -0
  192. package/dist/services/thread-vitality.js +143 -0
  193. package/dist/services/thread-vitality.js.map +1 -0
  194. package/dist/services/tier.d.ts +52 -0
  195. package/dist/services/tier.d.ts.map +1 -0
  196. package/dist/services/tier.js +109 -0
  197. package/dist/services/tier.js.map +1 -0
  198. package/dist/services/timezone.d.ts +37 -0
  199. package/dist/services/timezone.d.ts.map +1 -0
  200. package/dist/services/timezone.js +147 -0
  201. package/dist/services/timezone.js.map +1 -0
  202. package/dist/services/transcript-chunker.d.ts +18 -0
  203. package/dist/services/transcript-chunker.d.ts.map +1 -0
  204. package/dist/services/transcript-chunker.js +237 -0
  205. package/dist/services/transcript-chunker.js.map +1 -0
  206. package/dist/services/triple-writer.d.ts +128 -0
  207. package/dist/services/triple-writer.d.ts.map +1 -0
  208. package/dist/services/triple-writer.js +338 -0
  209. package/dist/services/triple-writer.js.map +1 -0
  210. package/dist/services/variant-assignment.d.ts +92 -0
  211. package/dist/services/variant-assignment.d.ts.map +1 -0
  212. package/dist/services/variant-assignment.js +196 -0
  213. package/dist/services/variant-assignment.js.map +1 -0
  214. package/dist/tools/absorb-observations.d.ts +16 -0
  215. package/dist/tools/absorb-observations.d.ts.map +1 -0
  216. package/dist/tools/absorb-observations.js +82 -0
  217. package/dist/tools/absorb-observations.js.map +1 -0
  218. package/dist/tools/analyze.d.ts +55 -0
  219. package/dist/tools/analyze.d.ts.map +1 -0
  220. package/dist/tools/analyze.js +139 -0
  221. package/dist/tools/analyze.js.map +1 -0
  222. package/dist/tools/cleanup-threads.d.ts +47 -0
  223. package/dist/tools/cleanup-threads.d.ts.map +1 -0
  224. package/dist/tools/cleanup-threads.js +127 -0
  225. package/dist/tools/cleanup-threads.js.map +1 -0
  226. package/dist/tools/confirm-scars.d.ts +23 -0
  227. package/dist/tools/confirm-scars.d.ts.map +1 -0
  228. package/dist/tools/confirm-scars.js +209 -0
  229. package/dist/tools/confirm-scars.js.map +1 -0
  230. package/dist/tools/create-decision.d.ts +15 -0
  231. package/dist/tools/create-decision.d.ts.map +1 -0
  232. package/dist/tools/create-decision.js +138 -0
  233. package/dist/tools/create-decision.js.map +1 -0
  234. package/dist/tools/create-learning.d.ts +15 -0
  235. package/dist/tools/create-learning.d.ts.map +1 -0
  236. package/dist/tools/create-learning.js +226 -0
  237. package/dist/tools/create-learning.js.map +1 -0
  238. package/dist/tools/create-thread.d.ts +42 -0
  239. package/dist/tools/create-thread.d.ts.map +1 -0
  240. package/dist/tools/create-thread.js +180 -0
  241. package/dist/tools/create-thread.js.map +1 -0
  242. package/dist/tools/definitions.d.ts +5013 -0
  243. package/dist/tools/definitions.d.ts.map +1 -0
  244. package/dist/tools/definitions.js +2017 -0
  245. package/dist/tools/definitions.js.map +1 -0
  246. package/dist/tools/dismiss-suggestion.d.ts +20 -0
  247. package/dist/tools/dismiss-suggestion.d.ts.map +1 -0
  248. package/dist/tools/dismiss-suggestion.js +40 -0
  249. package/dist/tools/dismiss-suggestion.js.map +1 -0
  250. package/dist/tools/get-transcript.d.ts +24 -0
  251. package/dist/tools/get-transcript.d.ts.map +1 -0
  252. package/dist/tools/get-transcript.js +52 -0
  253. package/dist/tools/get-transcript.js.map +1 -0
  254. package/dist/tools/graph-traverse.d.ts +83 -0
  255. package/dist/tools/graph-traverse.d.ts.map +1 -0
  256. package/dist/tools/graph-traverse.js +394 -0
  257. package/dist/tools/graph-traverse.js.map +1 -0
  258. package/dist/tools/list-threads.d.ts +15 -0
  259. package/dist/tools/list-threads.d.ts.map +1 -0
  260. package/dist/tools/list-threads.js +114 -0
  261. package/dist/tools/list-threads.js.map +1 -0
  262. package/dist/tools/log.d.ts +43 -0
  263. package/dist/tools/log.d.ts.map +1 -0
  264. package/dist/tools/log.js +157 -0
  265. package/dist/tools/log.js.map +1 -0
  266. package/dist/tools/prepare-context.d.ts +36 -0
  267. package/dist/tools/prepare-context.d.ts.map +1 -0
  268. package/dist/tools/prepare-context.js +353 -0
  269. package/dist/tools/prepare-context.js.map +1 -0
  270. package/dist/tools/promote-suggestion.d.ts +25 -0
  271. package/dist/tools/promote-suggestion.d.ts.map +1 -0
  272. package/dist/tools/promote-suggestion.js +60 -0
  273. package/dist/tools/promote-suggestion.js.map +1 -0
  274. package/dist/tools/recall.d.ts +77 -0
  275. package/dist/tools/recall.d.ts.map +1 -0
  276. package/dist/tools/recall.js +423 -0
  277. package/dist/tools/recall.js.map +1 -0
  278. package/dist/tools/recall.test.d.ts +5 -0
  279. package/dist/tools/recall.test.d.ts.map +1 -0
  280. package/dist/tools/recall.test.js +155 -0
  281. package/dist/tools/recall.test.js.map +1 -0
  282. package/dist/tools/record-scar-usage-batch.d.ts +10 -0
  283. package/dist/tools/record-scar-usage-batch.d.ts.map +1 -0
  284. package/dist/tools/record-scar-usage-batch.js +153 -0
  285. package/dist/tools/record-scar-usage-batch.js.map +1 -0
  286. package/dist/tools/record-scar-usage.d.ts +14 -0
  287. package/dist/tools/record-scar-usage.d.ts.map +1 -0
  288. package/dist/tools/record-scar-usage.js +94 -0
  289. package/dist/tools/record-scar-usage.js.map +1 -0
  290. package/dist/tools/resolve-thread.d.ts +16 -0
  291. package/dist/tools/resolve-thread.d.ts.map +1 -0
  292. package/dist/tools/resolve-thread.js +102 -0
  293. package/dist/tools/resolve-thread.js.map +1 -0
  294. package/dist/tools/save-transcript.d.ts +29 -0
  295. package/dist/tools/save-transcript.d.ts.map +1 -0
  296. package/dist/tools/save-transcript.js +97 -0
  297. package/dist/tools/save-transcript.js.map +1 -0
  298. package/dist/tools/search.d.ts +46 -0
  299. package/dist/tools/search.d.ts.map +1 -0
  300. package/dist/tools/search.js +186 -0
  301. package/dist/tools/search.js.map +1 -0
  302. package/dist/tools/session-close.d.ts +14 -0
  303. package/dist/tools/session-close.d.ts.map +1 -0
  304. package/dist/tools/session-close.js +881 -0
  305. package/dist/tools/session-close.js.map +1 -0
  306. package/dist/tools/session-start.d.ts +38 -0
  307. package/dist/tools/session-start.d.ts.map +1 -0
  308. package/dist/tools/session-start.js +1104 -0
  309. package/dist/tools/session-start.js.map +1 -0
  310. package/dist/types/index.d.ts +456 -0
  311. package/dist/types/index.d.ts.map +1 -0
  312. package/dist/types/index.js +5 -0
  313. package/dist/types/index.js.map +1 -0
  314. package/package.json +76 -0
  315. package/schema/setup.sql +193 -0
  316. package/schema/starter-scars.json +206 -0
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Active Sessions Registry (GIT-19)
3
+ *
4
+ * CRUD operations for .gitmem/active-sessions.json — the multi-session
5
+ * registry that tracks all running MCP server sessions.
6
+ *
7
+ * Key design decisions:
8
+ * - Atomic writes (write-temp-rename) because multiple processes may
9
+ * register/unregister concurrently.
10
+ * - Sync I/O to match codebase convention (fs.writeFileSync etc).
11
+ * - Graceful degradation: corrupted registry = start fresh.
12
+ */
13
+ import * as fs from "fs";
14
+ import * as path from "path";
15
+ import * as os from "os";
16
+ import { getGitmemDir, getSessionPath } from "./gitmem-dir.js";
17
+ import { ActiveSessionsRegistrySchema } from "../schemas/active-sessions.js";
18
+ const REGISTRY_FILENAME = "active-sessions.json";
19
+ const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24 hours
20
+ // --- Atomic write utility ---
21
+ /**
22
+ * Atomic write: write to a temp file in the same directory, then rename.
23
+ * rename() on the same filesystem is atomic on POSIX.
24
+ * Falls back to direct write on rename failure.
25
+ */
26
+ function atomicWriteFileSync(filePath, data) {
27
+ const dir = path.dirname(filePath);
28
+ const tmpPath = path.join(dir, `.active-sessions.${process.pid}.tmp`);
29
+ try {
30
+ fs.writeFileSync(tmpPath, data, "utf-8");
31
+ fs.renameSync(tmpPath, filePath);
32
+ }
33
+ catch (renameErr) {
34
+ try {
35
+ fs.unlinkSync(tmpPath);
36
+ }
37
+ catch {
38
+ /* ignore cleanup failure */
39
+ }
40
+ console.warn("[active-sessions] Atomic rename failed, falling back to direct write:", renameErr);
41
+ fs.writeFileSync(filePath, data, "utf-8");
42
+ }
43
+ }
44
+ // --- Internal helpers ---
45
+ function getRegistryPath() {
46
+ return path.join(getGitmemDir(), REGISTRY_FILENAME);
47
+ }
48
+ /**
49
+ * Read the registry from disk. Returns empty registry if file
50
+ * doesn't exist, is corrupted, or fails Zod validation.
51
+ */
52
+ function readRegistry() {
53
+ try {
54
+ const filePath = getRegistryPath();
55
+ if (!fs.existsSync(filePath)) {
56
+ return { sessions: [] };
57
+ }
58
+ const raw = fs.readFileSync(filePath, "utf-8");
59
+ const parsed = JSON.parse(raw);
60
+ const result = ActiveSessionsRegistrySchema.safeParse(parsed);
61
+ if (result.success) {
62
+ return result.data;
63
+ }
64
+ console.warn("[active-sessions] Registry failed validation, starting fresh:", result.error.message);
65
+ return { sessions: [] };
66
+ }
67
+ catch (error) {
68
+ console.warn("[active-sessions] Failed to read registry:", error);
69
+ return { sessions: [] };
70
+ }
71
+ }
72
+ /**
73
+ * Write the registry to disk using atomic write.
74
+ */
75
+ function writeRegistry(registry) {
76
+ const filePath = getRegistryPath();
77
+ const dir = path.dirname(filePath);
78
+ if (!fs.existsSync(dir)) {
79
+ fs.mkdirSync(dir, { recursive: true });
80
+ }
81
+ atomicWriteFileSync(filePath, JSON.stringify(registry, null, 2));
82
+ }
83
+ // --- CRUD operations ---
84
+ /**
85
+ * Register a new session in the active-sessions registry.
86
+ * Idempotent: re-registering the same session_id replaces the entry.
87
+ */
88
+ export function registerSession(entry) {
89
+ const registry = readRegistry();
90
+ registry.sessions = registry.sessions.filter((s) => s.session_id !== entry.session_id);
91
+ registry.sessions.push(entry);
92
+ writeRegistry(registry);
93
+ console.error(`[active-sessions] Registered session ${entry.session_id.slice(0, 8)} (agent: ${entry.agent}, pid: ${entry.pid})`);
94
+ }
95
+ /**
96
+ * Unregister a session from the active-sessions registry.
97
+ * Returns true if the session was found and removed.
98
+ */
99
+ export function unregisterSession(sessionId) {
100
+ const registry = readRegistry();
101
+ const before = registry.sessions.length;
102
+ registry.sessions = registry.sessions.filter((s) => s.session_id !== sessionId);
103
+ const removed = registry.sessions.length < before;
104
+ if (removed) {
105
+ writeRegistry(registry);
106
+ console.error(`[active-sessions] Unregistered session ${sessionId.slice(0, 8)}`);
107
+ }
108
+ else {
109
+ console.warn(`[active-sessions] Session ${sessionId.slice(0, 8)} not found in registry`);
110
+ }
111
+ return removed;
112
+ }
113
+ /**
114
+ * List all active sessions from the registry.
115
+ */
116
+ export function listActiveSessions() {
117
+ return readRegistry().sessions;
118
+ }
119
+ /**
120
+ * Find a session by hostname and PID.
121
+ * Used by session_start to detect if this process already has a registered session.
122
+ */
123
+ export function findSessionByHostPid(hostname, pid) {
124
+ const registry = readRegistry();
125
+ return registry.sessions.find((s) => s.hostname === hostname && s.pid === pid) || null;
126
+ }
127
+ /**
128
+ * Find a session by session_id.
129
+ */
130
+ export function findSessionById(sessionId) {
131
+ const registry = readRegistry();
132
+ return registry.sessions.find((s) => s.session_id === sessionId) || null;
133
+ }
134
+ /**
135
+ * Prune stale sessions from the registry (GIT-22 enhanced).
136
+ *
137
+ * A session is stale if:
138
+ * 1. Its started_at is older than 24 hours, OR
139
+ * 2. Its PID no longer exists on this hostname (process died without cleanup), OR
140
+ * 3. Its per-session directory/session.json is missing (orphaned registry entry)
141
+ *
142
+ * Also cleans up per-session directories for pruned sessions,
143
+ * and removes orphaned session directories with no registry entry.
144
+ * Returns the number of sessions pruned.
145
+ */
146
+ export function pruneStale() {
147
+ const registry = readRegistry();
148
+ const now = Date.now();
149
+ const currentHostname = os.hostname();
150
+ const before = registry.sessions.length;
151
+ const gitmemDir = getGitmemDir();
152
+ registry.sessions = registry.sessions.filter((entry) => {
153
+ // GIT-22: Check for orphaned registry entry (session file missing)
154
+ const sessionFile = path.join(gitmemDir, "sessions", entry.session_id, "session.json");
155
+ if (!fs.existsSync(sessionFile)) {
156
+ // Only prune if session is old enough that session_start should have written the file.
157
+ // Brand-new sessions may not have the file yet (race window during session_start).
158
+ const age = now - new Date(entry.started_at).getTime();
159
+ if (age > 60_000) { // 1 minute grace period
160
+ console.error(`[active-sessions] Pruning orphaned registry entry ${entry.session_id.slice(0, 8)} (session file missing)`);
161
+ cleanupSessionDir(gitmemDir, entry.session_id);
162
+ return false;
163
+ }
164
+ }
165
+ // Check age
166
+ const age = now - new Date(entry.started_at).getTime();
167
+ if (age > STALE_THRESHOLD_MS) {
168
+ console.error(`[active-sessions] Pruning stale session ${entry.session_id.slice(0, 8)} (age: ${Math.round(age / 3600000)}h)`);
169
+ cleanupSessionDir(gitmemDir, entry.session_id);
170
+ return false;
171
+ }
172
+ // Check if PID is alive (only for sessions on the same host)
173
+ if (entry.hostname === currentHostname) {
174
+ try {
175
+ process.kill(entry.pid, 0); // Signal 0 = check existence only
176
+ }
177
+ catch {
178
+ console.error(`[active-sessions] Pruning dead session ${entry.session_id.slice(0, 8)} (pid ${entry.pid} no longer running)`);
179
+ cleanupSessionDir(gitmemDir, entry.session_id);
180
+ return false;
181
+ }
182
+ }
183
+ return true;
184
+ });
185
+ const pruned = before - registry.sessions.length;
186
+ if (pruned > 0) {
187
+ writeRegistry(registry);
188
+ console.error(`[active-sessions] Pruned ${pruned} stale session(s)`);
189
+ }
190
+ // GIT-22: Clean up orphaned session directories (dir exists but no registry entry)
191
+ pruneOrphanedDirs(gitmemDir, registry);
192
+ return pruned;
193
+ }
194
+ /**
195
+ * GIT-22: Remove session directories that have no corresponding registry entry.
196
+ * These can occur when a process crashes after creating the directory but before
197
+ * registering, or when the registry is rebuilt after corruption.
198
+ */
199
+ function pruneOrphanedDirs(gitmemDir, registry) {
200
+ try {
201
+ const sessionsDir = path.join(gitmemDir, "sessions");
202
+ if (!fs.existsSync(sessionsDir))
203
+ return;
204
+ const registeredIds = new Set(registry.sessions.map((s) => s.session_id));
205
+ const dirs = fs.readdirSync(sessionsDir);
206
+ for (const dirName of dirs) {
207
+ if (registeredIds.has(dirName))
208
+ continue;
209
+ const dirPath = path.join(sessionsDir, dirName);
210
+ try {
211
+ const stat = fs.statSync(dirPath);
212
+ if (!stat.isDirectory())
213
+ continue;
214
+ // Only prune directories older than 1 hour to avoid race conditions
215
+ const ageMs = Date.now() - stat.mtimeMs;
216
+ if (ageMs > 60 * 60 * 1000) {
217
+ fs.rmSync(dirPath, { recursive: true, force: true });
218
+ console.error(`[active-sessions] Cleaned up orphaned session directory: ${dirName.slice(0, 8)}`);
219
+ }
220
+ }
221
+ catch {
222
+ // Ignore errors on individual directories
223
+ }
224
+ }
225
+ }
226
+ catch {
227
+ // sessionsDir doesn't exist or can't be read — nothing to prune
228
+ }
229
+ }
230
+ /**
231
+ * Clean up the per-session directory for a pruned/closed session.
232
+ */
233
+ function cleanupSessionDir(gitmemDir, sessionId) {
234
+ try {
235
+ const sessionDir = path.join(gitmemDir, "sessions", sessionId);
236
+ if (fs.existsSync(sessionDir)) {
237
+ fs.rmSync(sessionDir, { recursive: true, force: true });
238
+ console.error(`[active-sessions] Cleaned up session directory: ${sessionDir}`);
239
+ }
240
+ }
241
+ catch (error) {
242
+ console.warn(`[active-sessions] Failed to clean up session directory for ${sessionId.slice(0, 8)}:`, error);
243
+ }
244
+ }
245
+ // --- GIT-23: Migration from old format ---
246
+ let migrationRan = false;
247
+ /**
248
+ * GIT-23: Migrate from old active-session.json (singular) to new multi-session format.
249
+ *
250
+ * Runs once per process. If old file exists and new registry does not:
251
+ * 1. Read old file
252
+ * 2. Create per-session directory with session.json
253
+ * 3. Create active-sessions.json registry with single entry
254
+ * 4. Rename old file to active-session.json.migrated (backup)
255
+ *
256
+ * Idempotent: skips if new registry already exists or old file is absent.
257
+ */
258
+ export function migrateFromLegacy() {
259
+ if (migrationRan)
260
+ return false;
261
+ migrationRan = true;
262
+ try {
263
+ const gitmemDir = getGitmemDir();
264
+ const oldPath = path.join(gitmemDir, "active-session.json");
265
+ const newPath = path.join(gitmemDir, REGISTRY_FILENAME);
266
+ // Skip if new registry already exists or old file is absent
267
+ if (fs.existsSync(newPath) || !fs.existsSync(oldPath)) {
268
+ return false;
269
+ }
270
+ const raw = fs.readFileSync(oldPath, "utf-8");
271
+ const old = JSON.parse(raw);
272
+ if (!old.session_id) {
273
+ console.warn("[active-sessions] Legacy file has no session_id, skipping migration");
274
+ return false;
275
+ }
276
+ // 1. Create per-session directory with session.json
277
+ const sessionFilePath = getSessionPath(old.session_id, "session.json");
278
+ fs.writeFileSync(sessionFilePath, JSON.stringify({
279
+ ...old,
280
+ hostname: old.hostname || os.hostname(),
281
+ pid: old.pid || process.pid,
282
+ }, null, 2));
283
+ // 2. Create registry with single entry
284
+ const entry = {
285
+ session_id: old.session_id,
286
+ agent: old.agent || "CLI",
287
+ started_at: old.started_at || new Date().toISOString(),
288
+ hostname: old.hostname || os.hostname(),
289
+ pid: old.pid || process.pid,
290
+ project: old.project || "orchestra_dev",
291
+ };
292
+ writeRegistry({ sessions: [entry] });
293
+ // 3. Rename old file to backup
294
+ const backupPath = path.join(gitmemDir, "active-session.json.migrated");
295
+ fs.renameSync(oldPath, backupPath);
296
+ console.error(`[active-sessions] Migrated legacy active-session.json → ` +
297
+ `sessions/${old.session_id.slice(0, 8)}/ + active-sessions.json (backup: active-session.json.migrated)`);
298
+ return true;
299
+ }
300
+ catch (error) {
301
+ console.warn("[active-sessions] Legacy migration failed (non-fatal):", error);
302
+ return false;
303
+ }
304
+ }
305
+ /**
306
+ * Reset migration flag (for testing only).
307
+ */
308
+ export function resetMigrationFlag() {
309
+ migrationRan = false;
310
+ }
311
+ //# sourceMappingURL=active-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-sessions.js","sourceRoot":"","sources":["../../src/services/active-sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Agent Detection Service
3
+ *
4
+ * Detects which Claude agent is running based on environment variables,
5
+ * Docker presence, and hostname.
6
+ *
7
+ * Detection matrix (from CLAUDE.md):
8
+ * | ENTRYPOINT | Docker | Hostname | Identity |
9
+ * |------------|--------|----------|----------|
10
+ * | cli | YES | (any) | CLI |
11
+ * | cli | NO | orchestra.nteg.com | CODA-1 |
12
+ * | claude-desktop | NO | (any) | DAC |
13
+ * | (empty) | NO | (local) | Brain_Local |
14
+ * | (empty) | NO | (no fs) | Brain_Cloud |
15
+ */
16
+ import type { AgentIdentity, DetectedEnvironment } from "../types/index.js";
17
+ /**
18
+ * Detect the current agent identity based on environment
19
+ */
20
+ export declare function detectAgent(): DetectedEnvironment;
21
+ /**
22
+ * Get just the agent identity (convenience function)
23
+ */
24
+ export declare function getAgentIdentity(): AgentIdentity;
25
+ //# sourceMappingURL=agent-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detection.d.ts","sourceRoot":"","sources":["../../src/services/agent-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAyB5E;;GAEG;AACH,wBAAgB,WAAW,IAAI,mBAAmB,CAuCjD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Agent Detection Service
3
+ *
4
+ * Detects which Claude agent is running based on environment variables,
5
+ * Docker presence, and hostname.
6
+ *
7
+ * Detection matrix (from CLAUDE.md):
8
+ * | ENTRYPOINT | Docker | Hostname | Identity |
9
+ * |------------|--------|----------|----------|
10
+ * | cli | YES | (any) | CLI |
11
+ * | cli | NO | orchestra.nteg.com | CODA-1 |
12
+ * | claude-desktop | NO | (any) | DAC |
13
+ * | (empty) | NO | (local) | Brain_Local |
14
+ * | (empty) | NO | (no fs) | Brain_Cloud |
15
+ */
16
+ import * as fs from "node:fs";
17
+ import * as os from "node:os";
18
+ /**
19
+ * Check if running in Docker container
20
+ */
21
+ function isDocker() {
22
+ try {
23
+ return fs.existsSync("/.dockerenv");
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ /**
30
+ * Check if filesystem is accessible (Brain Local vs Brain Cloud)
31
+ */
32
+ function hasFilesystemAccess() {
33
+ try {
34
+ fs.accessSync("/tmp", fs.constants.R_OK);
35
+ return true;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * Detect the current agent identity based on environment
43
+ */
44
+ export function detectAgent() {
45
+ const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT || null;
46
+ const docker = isDocker();
47
+ const hostname = os.hostname();
48
+ let agent;
49
+ if (entrypoint === "cli") {
50
+ if (docker) {
51
+ // CLI in Docker container
52
+ agent = "CLI";
53
+ }
54
+ else if (hostname === "orchestra.nteg.com" || hostname === "cyrus") {
55
+ // CLI on orchestra server = CODA-1
56
+ agent = "CODA-1";
57
+ }
58
+ else {
59
+ // CLI elsewhere (fallback)
60
+ agent = "CLI";
61
+ }
62
+ }
63
+ else if (entrypoint === "claude-desktop") {
64
+ // Desktop app code tab
65
+ agent = "DAC";
66
+ }
67
+ else if (!entrypoint) {
68
+ // No entrypoint - could be Brain Local or Brain Cloud
69
+ if (hasFilesystemAccess()) {
70
+ agent = "Brain_Local";
71
+ }
72
+ else {
73
+ agent = "Brain_Cloud";
74
+ }
75
+ }
76
+ else {
77
+ // Unknown entrypoint
78
+ agent = "Unknown";
79
+ }
80
+ return {
81
+ entrypoint,
82
+ docker,
83
+ hostname,
84
+ agent,
85
+ };
86
+ }
87
+ /**
88
+ * Get just the agent identity (convenience function)
89
+ */
90
+ export function getAgentIdentity() {
91
+ return detectAgent().agent;
92
+ }
93
+ //# sourceMappingURL=agent-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detection.js","sourceRoot":"","sources":["../../src/services/agent-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9B;;GAEG;AACH,SAAS,QAAQ;IACf,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB;IAC1B,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,IAAI,CAAC;IAC9D,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAE/B,IAAI,KAAoB,CAAC;IAEzB,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,IAAI,MAAM,EAAE,CAAC;YACX,0BAA0B;YAC1B,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC;aAAM,IAAI,QAAQ,KAAK,oBAAoB,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACrE,mCAAmC;YACnC,KAAK,GAAG,QAAQ,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,2BAA2B;YAC3B,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC;IACH,CAAC;SAAM,IAAI,UAAU,KAAK,gBAAgB,EAAE,CAAC;QAC3C,uBAAuB;QACvB,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;SAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACvB,sDAAsD;QACtD,IAAI,mBAAmB,EAAE,EAAE,CAAC;YAC1B,KAAK,GAAG,aAAa,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,aAAa,CAAC;QACxB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,qBAAqB;QACrB,KAAK,GAAG,SAAS,CAAC;IACpB,CAAC;IAED,OAAO;QACL,UAAU;QACV,MAAM;QACN,QAAQ;QACR,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,WAAW,EAAE,CAAC,KAAK,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Analytics Service (OD-567)
3
+ *
4
+ * Shared analytics engine for session insights. Powers both the
5
+ * gitmem-analyze MCP tool (CLI) and the GitMem Console dashboard.
6
+ *
7
+ * Uses directQuery for raw Supabase REST access (no ww-mcp dependency).
8
+ */
9
+ import type { Project } from "../types/index.js";
10
+ export interface SessionRecord {
11
+ id: string;
12
+ session_title: string | null;
13
+ session_date: string;
14
+ agent: string;
15
+ linear_issue: string | null;
16
+ decisions: unknown[];
17
+ open_threads: string[];
18
+ closing_reflection: ClosingReflection | null;
19
+ close_compliance: CloseCompliance | null;
20
+ created_at: string;
21
+ project: string;
22
+ }
23
+ interface ClosingReflection {
24
+ what_broke?: string;
25
+ what_took_longer?: string;
26
+ do_differently?: string;
27
+ what_worked?: string;
28
+ wrong_assumption?: string;
29
+ scars_applied?: string | string[];
30
+ human_additions?: string;
31
+ }
32
+ interface CloseCompliance {
33
+ agent?: string;
34
+ close_type?: string;
35
+ scars_applied?: number;
36
+ learnings_stored?: number;
37
+ checklist_displayed?: boolean;
38
+ human_asked_for_corrections?: boolean;
39
+ questions_answered_by_agent?: boolean;
40
+ }
41
+ export interface AgentBreakdown {
42
+ agent: string;
43
+ session_count: number;
44
+ decisions_total: number;
45
+ threads_total: number;
46
+ close_types: Record<string, number>;
47
+ }
48
+ export interface SummaryAnalytics {
49
+ period: {
50
+ start: string;
51
+ end: string;
52
+ days: number;
53
+ };
54
+ total_sessions: number;
55
+ sessions_with_reflections: number;
56
+ sessions_with_issues: number;
57
+ total_decisions: number;
58
+ total_open_threads: number;
59
+ agents: AgentBreakdown[];
60
+ close_type_distribution: Record<string, number>;
61
+ top_issues: Array<{
62
+ issue: string;
63
+ session_count: number;
64
+ }>;
65
+ }
66
+ /**
67
+ * Fetch sessions within a date range.
68
+ * Selects only the fields needed for analytics (no embedding column).
69
+ */
70
+ export declare function querySessionsByDateRange(startDate: string, endDate: string, project: Project, agentFilter?: string): Promise<SessionRecord[]>;
71
+ export interface ScarUsageRecord {
72
+ scar_id: string;
73
+ scar_title: string | null;
74
+ scar_severity: string | null;
75
+ agent: string | null;
76
+ reference_type: string;
77
+ execution_successful: boolean | null;
78
+ surfaced_at: string;
79
+ }
80
+ export interface RepeatMistakeRecord {
81
+ id: string;
82
+ title: string;
83
+ related_scar_id: string | null;
84
+ repeat_mistake_details: {
85
+ reason?: string;
86
+ } | null;
87
+ created_at: string;
88
+ }
89
+ export interface BlindspotsData {
90
+ period: {
91
+ start: string;
92
+ end: string;
93
+ days: number;
94
+ };
95
+ total_scars_surfaced: number;
96
+ total_scar_usages: number;
97
+ ignored_scars: Array<{
98
+ scar_id: string;
99
+ title: string;
100
+ severity: string;
101
+ times_surfaced: number;
102
+ times_ignored: number;
103
+ ignore_rate: number;
104
+ agents: string[];
105
+ }>;
106
+ failed_applications: Array<{
107
+ scar_id: string;
108
+ title: string;
109
+ times_applied: number;
110
+ times_failed: number;
111
+ failure_rate: number;
112
+ }>;
113
+ repeat_mistakes: Array<{
114
+ id: string;
115
+ title: string;
116
+ original_scar_title: string;
117
+ reason: string;
118
+ created_at: string;
119
+ }>;
120
+ agent_effectiveness: Array<{
121
+ agent: string;
122
+ scars_surfaced: number;
123
+ scars_applied: number;
124
+ application_rate: number;
125
+ success_rate: number;
126
+ }>;
127
+ severity_breakdown: Array<{
128
+ severity: string;
129
+ surfaced: number;
130
+ applied: number;
131
+ ignored: number;
132
+ application_rate: number;
133
+ }>;
134
+ }
135
+ /**
136
+ * Fetch scar_usage records within a date range.
137
+ */
138
+ export declare function queryScarUsageByDateRange(startDate: string, _endDate: string, _project: Project, agentFilter?: string): Promise<ScarUsageRecord[]>;
139
+ /**
140
+ * Fetch repeat mistakes from orchestra_learnings within a date range.
141
+ */
142
+ export declare function queryRepeatMistakes(startDate: string, _endDate: string, project: Project): Promise<RepeatMistakeRecord[]>;
143
+ /**
144
+ * Resolve scar titles and severities from orchestra_learnings for scar_usage
145
+ * records that have null/missing title data.
146
+ */
147
+ export declare function enrichScarUsageTitles(usages: ScarUsageRecord[]): Promise<ScarUsageRecord[]>;
148
+ /**
149
+ * Compute blindspots analytics from scar usage and repeat mistake data.
150
+ */
151
+ export declare function computeBlindspots(usages: ScarUsageRecord[], repeatMistakes: RepeatMistakeRecord[], days: number): BlindspotsData;
152
+ /**
153
+ * Compute basic summary statistics from a set of sessions.
154
+ */
155
+ export declare function computeSummary(sessions: SessionRecord[], days: number): SummaryAnalytics;
156
+ /**
157
+ * Extract and aggregate closing reflections from sessions.
158
+ * Returns arrays of each reflection field for further analysis.
159
+ */
160
+ type ReflectionEntry = {
161
+ text: string;
162
+ session_id: string;
163
+ agent: string;
164
+ date: string;
165
+ };
166
+ type ReflectionCategory = {
167
+ entries: ReflectionEntry[];
168
+ total_count: number;
169
+ };
170
+ export declare function aggregateClosingReflections(sessions: SessionRecord[], maxPerCategory?: number, maxTextLength?: number): {
171
+ what_broke: ReflectionCategory;
172
+ what_worked: ReflectionCategory;
173
+ wrong_assumptions: ReflectionCategory;
174
+ do_differently: ReflectionCategory;
175
+ };
176
+ /**
177
+ * Format summary analytics as compact markdown.
178
+ */
179
+ export declare function formatSummary(data: SummaryAnalytics): string;
180
+ /**
181
+ * Format reflections as compact markdown (top N per category).
182
+ */
183
+ export declare function formatReflections(data: {
184
+ period: {
185
+ start: string;
186
+ end: string;
187
+ days: number;
188
+ };
189
+ total_sessions_scanned: number;
190
+ sessions_with_reflections: number;
191
+ what_broke: ReflectionCategory;
192
+ what_worked: ReflectionCategory;
193
+ wrong_assumptions: ReflectionCategory;
194
+ do_differently: ReflectionCategory;
195
+ }, topN?: number): string;
196
+ /**
197
+ * Format blindspots as compact markdown.
198
+ */
199
+ export declare function formatBlindspots(data: BlindspotsData): string;
200
+ export {};
201
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/services/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIjD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kBAAkB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC7C,gBAAgB,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,iBAAiB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,yBAAyB,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D;AAID;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,EAAE,CAAC,CA6B1B;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,OAAO,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sBAAsB,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,KAAK,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC,CAAC;IAEH,mBAAmB,EAAE,KAAK,CAAC;QACzB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IAEH,eAAe,EAAE,KAAK,CAAC;QACrB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,mBAAmB,EAAE,MAAM,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IAEH,mBAAmB,EAAE,KAAK,CAAC;QACzB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IAEH,kBAAkB,EAAE,KAAK,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;CACJ;AAID;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,EAAE,CAAC,CA2B5B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAgBhC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,eAAe,EAAE,GACxB,OAAO,CAAC,eAAe,EAAE,CAAC,CAuC5B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,EAAE,EACzB,cAAc,EAAE,mBAAmB,EAAE,EACrC,IAAI,EAAE,MAAM,GACX,cAAc,CA+HhB;AAID;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CA0ExF;AAED;;;GAGG;AACH,KAAK,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACzF,KAAK,kBAAkB,GAAG;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,aAAa,EAAE,EACzB,cAAc,GAAE,MAAW,EAC3B,aAAa,GAAE,MAAY,GAC1B;IACD,UAAU,EAAE,kBAAkB,CAAC;IAC/B,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,cAAc,EAAE,kBAAkB,CAAC;CACpC,CAgDA;AAID;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAmC5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE;IACJ,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,yBAAyB,EAAE,MAAM,CAAC;IAClC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,cAAc,EAAE,kBAAkB,CAAC;CACpC,EACD,IAAI,GAAE,MAAW,GAChB,MAAM,CA+BR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CA2D7D"}