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,264 @@
1
+ /**
2
+ * GitMem Performance Metrics Service
3
+ *
4
+ * Tracks latency, result counts, and relevance signals for all GitMem tools.
5
+ * Implements OD-429 instrumentation layer.
6
+ */
7
+ import { v4 as uuidv4 } from "uuid";
8
+ import * as supabase from "./supabase-client.js";
9
+ /**
10
+ * Performance targets from OD-429
11
+ */
12
+ export const PERFORMANCE_TARGETS = {
13
+ recall: 2000,
14
+ search: 500,
15
+ log: 500,
16
+ session_start: 1500,
17
+ session_refresh: 1500, // Same pipeline as session_start minus session creation
18
+ session_close: 3000,
19
+ create_learning: 3000,
20
+ create_decision: 3000,
21
+ record_scar_usage: 1000,
22
+ record_scar_usage_batch: 2000,
23
+ save_transcript: 5000, // Large payload upload
24
+ get_transcript: 3000, // Retrieval
25
+ analyze: 3000, // Session analytics queries
26
+ graph_traverse: 3000, // Knowledge graph traversal
27
+ prepare_context: 500, // Same pipeline as search, different formatter
28
+ absorb_observations: 500, // In-memory + optional upsert
29
+ list_threads: 100, // In-memory read
30
+ resolve_thread: 100, // In-memory mutation + file write
31
+ create_thread: 100, // In-memory mutation + file write
32
+ confirm_scars: 500, // In-memory validation + file write
33
+ cleanup_threads: 2000, // Fetch all threads + lifecycle computation
34
+ };
35
+ /**
36
+ * Timer utility for tracking operation duration
37
+ */
38
+ export class Timer {
39
+ startTime;
40
+ endTime;
41
+ constructor() {
42
+ this.startTime = performance.now();
43
+ }
44
+ stop() {
45
+ this.endTime = performance.now();
46
+ return this.elapsed();
47
+ }
48
+ elapsed() {
49
+ const end = this.endTime ?? performance.now();
50
+ return Math.round(end - this.startTime);
51
+ }
52
+ }
53
+ /**
54
+ * Track a query and record metrics
55
+ */
56
+ export async function recordMetrics(metrics) {
57
+ try {
58
+ const record = {
59
+ id: metrics.id,
60
+ session_id: metrics.session_id || null,
61
+ agent: metrics.agent || null,
62
+ tool_name: metrics.tool_name,
63
+ query_text: metrics.query_text || null,
64
+ tables_searched: metrics.tables_searched || null,
65
+ latency_ms: metrics.latency_ms,
66
+ result_count: metrics.result_count,
67
+ similarity_scores: metrics.similarity_scores || null,
68
+ context_bytes: metrics.context_bytes || null,
69
+ phase_tag: metrics.phase_tag || null,
70
+ linear_issue: metrics.linear_issue || null,
71
+ memories_surfaced: metrics.memories_surfaced || null,
72
+ metadata: metrics.metadata || {},
73
+ created_at: new Date().toISOString(),
74
+ };
75
+ await supabase.directUpsert("gitmem_query_metrics", record);
76
+ }
77
+ catch (error) {
78
+ // Log but don't fail the operation - metrics are secondary
79
+ console.error("[metrics] Failed to record:", error);
80
+ }
81
+ }
82
+ /**
83
+ * Build component performance data (OD-489)
84
+ */
85
+ export function buildComponentPerformance(latencyMs, source, networkCall, cacheStatus = networkCall ? "miss" : "hit") {
86
+ return {
87
+ latency_ms: latencyMs,
88
+ source,
89
+ cache_status: cacheStatus,
90
+ network_call: networkCall,
91
+ };
92
+ }
93
+ /**
94
+ * Count network calls from breakdown (OD-489)
95
+ */
96
+ export function countNetworkCalls(breakdown) {
97
+ if (!breakdown)
98
+ return 0;
99
+ let count = 0;
100
+ // Read operations
101
+ if (breakdown.last_session?.network_call)
102
+ count++;
103
+ if (breakdown.scar_search?.network_call)
104
+ count++;
105
+ if (breakdown.decisions?.network_call)
106
+ count++;
107
+ if (breakdown.wins?.network_call)
108
+ count++;
109
+ if (breakdown.session_create?.network_call)
110
+ count++;
111
+ // Write operations
112
+ if (breakdown.embedding?.network_call)
113
+ count++;
114
+ if (breakdown.upsert?.network_call)
115
+ count++;
116
+ if (breakdown.storage_write?.network_call)
117
+ count++;
118
+ return count;
119
+ }
120
+ export function buildPerformanceData(toolName, latencyMs, resultCount, options) {
121
+ const targetMs = PERFORMANCE_TARGETS[toolName];
122
+ const networkCallsMade = countNetworkCalls(options?.breakdown);
123
+ const fullyLocal = networkCallsMade === 0;
124
+ return {
125
+ // Legacy fields
126
+ latency_ms: latencyMs,
127
+ target_ms: targetMs,
128
+ meets_target: latencyMs <= targetMs,
129
+ result_count: resultCount,
130
+ memories_surfaced: options?.memoriesSurfaced,
131
+ similarity_scores: options?.similarityScores,
132
+ cache_hit: options?.cache_hit ?? fullyLocal,
133
+ cache_age_ms: options?.cache_age_ms,
134
+ search_mode: options?.search_mode,
135
+ // OD-489: Detailed instrumentation for test harness
136
+ total_latency_ms: latencyMs,
137
+ network_calls_made: networkCallsMade,
138
+ fully_local: fullyLocal,
139
+ breakdown: options?.breakdown,
140
+ };
141
+ }
142
+ /**
143
+ * Calculate response size in bytes (approximate)
144
+ */
145
+ export function calculateContextBytes(data) {
146
+ return new TextEncoder().encode(JSON.stringify(data)).length;
147
+ }
148
+ /**
149
+ * Wrap an async operation with timing and metrics
150
+ */
151
+ export async function withMetrics(toolName, operation, options) {
152
+ const timer = new Timer();
153
+ const metricsId = uuidv4();
154
+ const result = await operation();
155
+ const latencyMs = timer.stop();
156
+ // Extract result count and memories from result if available
157
+ let resultCount = 0;
158
+ let memoriesSurfaced;
159
+ let similarityScores;
160
+ if (result && typeof result === "object") {
161
+ const r = result;
162
+ // Handle different result shapes
163
+ if (Array.isArray(r.scars)) {
164
+ resultCount = r.scars.length;
165
+ memoriesSurfaced = r.scars.map((s) => s.id);
166
+ similarityScores = r.scars
167
+ .map((s) => s.similarity)
168
+ .filter((s) => s !== undefined);
169
+ }
170
+ else if (Array.isArray(r.relevant_scars)) {
171
+ resultCount = r.relevant_scars.length;
172
+ memoriesSurfaced = r.relevant_scars.map((s) => s.id);
173
+ similarityScores = r.relevant_scars
174
+ .map((s) => s.similarity)
175
+ .filter((s) => s !== undefined);
176
+ }
177
+ else if (r.learning_id) {
178
+ resultCount = 1;
179
+ }
180
+ else if (r.decision_id) {
181
+ resultCount = 1;
182
+ }
183
+ else if (r.usage_id) {
184
+ resultCount = 1;
185
+ }
186
+ else if (r.session_id) {
187
+ resultCount = 1;
188
+ }
189
+ }
190
+ const metrics = {
191
+ id: metricsId,
192
+ session_id: options?.sessionId,
193
+ agent: options?.agent,
194
+ tool_name: toolName,
195
+ query_text: options?.queryText,
196
+ tables_searched: options?.tablesSearched,
197
+ latency_ms: latencyMs,
198
+ result_count: resultCount,
199
+ similarity_scores: similarityScores,
200
+ context_bytes: calculateContextBytes(result),
201
+ phase_tag: options?.phaseTag,
202
+ linear_issue: options?.linearIssue,
203
+ memories_surfaced: memoriesSurfaced,
204
+ };
205
+ // Record metrics asynchronously (don't await)
206
+ recordMetrics(metrics).catch(() => { });
207
+ return { result, metrics };
208
+ }
209
+ /**
210
+ * Update metrics with relevance data (called at session close)
211
+ */
212
+ export async function updateRelevanceData(sessionId, memoriesApplied) {
213
+ try {
214
+ // Get all metrics for this session that surfaced memories
215
+ const metrics = await supabase.listRecords({
216
+ table: "gitmem_query_metrics",
217
+ filters: { session_id: sessionId },
218
+ });
219
+ if (!metrics || !Array.isArray(metrics))
220
+ return;
221
+ // Update each metric with applied memories
222
+ for (const metric of metrics) {
223
+ if (metric.memories_surfaced && Array.isArray(metric.memories_surfaced)) {
224
+ const applied = metric.memories_surfaced.filter((id) => memoriesApplied.includes(id));
225
+ if (applied.length > 0) {
226
+ await supabase.directUpsert("gitmem_query_metrics", {
227
+ id: metric.id,
228
+ memories_applied: applied,
229
+ });
230
+ }
231
+ }
232
+ }
233
+ }
234
+ catch (error) {
235
+ console.error("[metrics] Failed to update relevance:", error);
236
+ }
237
+ }
238
+ /**
239
+ * Detect re-query pattern (similar query with different terms)
240
+ */
241
+ export async function detectRequery(sessionId, currentQuery, toolName) {
242
+ try {
243
+ // Get recent queries from same session
244
+ const recentMetrics = await supabase.listRecords({
245
+ table: "gitmem_query_metrics",
246
+ filters: { session_id: sessionId, tool_name: toolName },
247
+ limit: 5,
248
+ });
249
+ if (!recentMetrics || !Array.isArray(recentMetrics))
250
+ return false;
251
+ // Simple heuristic: if we have multiple queries in short succession, it's a re-query
252
+ const recentCount = recentMetrics.filter((m) => {
253
+ const created = new Date(m.created_at);
254
+ const now = new Date();
255
+ const diffMs = now.getTime() - created.getTime();
256
+ return diffMs < 60000; // Within last minute
257
+ }).length;
258
+ return recentCount >= 2;
259
+ }
260
+ catch (error) {
261
+ return false;
262
+ }
263
+ }
264
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/services/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Session State Management
3
+ * OD-547: Track current session context for auto-injecting into recall calls
4
+ * OD-552: Track surfaced scars for auto-bridging Q6 answers to scar_usage records
5
+ *
6
+ * Maintains in-memory state of the current active session including:
7
+ * - session_id from session_start
8
+ * - linear_issue if working on a Linear issue
9
+ * - agent identity
10
+ * - surfaced scars (accumulated from session_start + recall calls)
11
+ *
12
+ * This allows recall() to always assign variants even without explicit parameters.
13
+ */
14
+ import type { SurfacedScar, ScarConfirmation, Observation, SessionChild, ThreadObject } from "../types/index.js";
15
+ interface SessionContext {
16
+ sessionId: string;
17
+ linearIssue?: string;
18
+ agent?: string;
19
+ startedAt: Date;
20
+ surfacedScars: SurfacedScar[];
21
+ confirmations: ScarConfirmation[];
22
+ observations: Observation[];
23
+ children: SessionChild[];
24
+ threads: ThreadObject[];
25
+ }
26
+ /**
27
+ * Set the current active session
28
+ * Called by session_start
29
+ */
30
+ export declare function setCurrentSession(context: Omit<SessionContext, 'surfacedScars' | 'confirmations' | 'observations' | 'children' | 'threads'> & {
31
+ surfacedScars?: SurfacedScar[];
32
+ threads?: ThreadObject[];
33
+ }): void;
34
+ /**
35
+ * Get the current active session
36
+ * Returns null if no session active
37
+ */
38
+ export declare function getCurrentSession(): SessionContext | null;
39
+ /**
40
+ * Clear the current session
41
+ * Called by session_close
42
+ */
43
+ export declare function clearCurrentSession(): void;
44
+ /**
45
+ * Check if currently working on a Linear issue
46
+ */
47
+ export declare function hasActiveIssue(): boolean;
48
+ /**
49
+ * OD-552: Add surfaced scars to tracking (deduplicates by scar_id)
50
+ * Called by session_start and recall when scars are surfaced.
51
+ */
52
+ export declare function addSurfacedScars(scars: SurfacedScar[]): void;
53
+ /**
54
+ * OD-552: Get all surfaced scars for the current session
55
+ */
56
+ export declare function getSurfacedScars(): SurfacedScar[];
57
+ /**
58
+ * Add scar confirmations (refute-or-obey) to the current session.
59
+ * Called by confirm_scars tool after validation.
60
+ */
61
+ export declare function addConfirmations(confirmations: ScarConfirmation[]): void;
62
+ /**
63
+ * Get all scar confirmations for the current session.
64
+ */
65
+ export declare function getConfirmations(): ScarConfirmation[];
66
+ /**
67
+ * Check if there are recall-surfaced scars that haven't been confirmed.
68
+ * Only checks scars with source "recall" — session_start scars don't require confirmation.
69
+ */
70
+ export declare function hasUnconfirmedScars(): boolean;
71
+ /**
72
+ * v2 Phase 2: Add observations from sub-agents/teammates
73
+ */
74
+ export declare function addObservations(newObs: Observation[]): number;
75
+ /**
76
+ * v2 Phase 2: Get all observations for the current session
77
+ */
78
+ export declare function getObservations(): Observation[];
79
+ /**
80
+ * v2 Phase 2: Register a child agent in the current session
81
+ */
82
+ export declare function addChild(child: SessionChild): void;
83
+ /**
84
+ * v2 Phase 2: Get all children for the current session
85
+ */
86
+ export declare function getChildren(): SessionChild[];
87
+ /**
88
+ * Compute session activity signals for close type validation.
89
+ * Returns null if no active session (e.g., recovered from registry).
90
+ */
91
+ export interface SessionActivity {
92
+ duration_min: number;
93
+ recall_count: number;
94
+ observation_count: number;
95
+ children_count: number;
96
+ thread_count: number;
97
+ }
98
+ export declare function getSessionActivity(): SessionActivity | null;
99
+ /**
100
+ * OD-thread-lifecycle: Set threads for the current session
101
+ */
102
+ export declare function setThreads(threads: ThreadObject[]): void;
103
+ /**
104
+ * OD-thread-lifecycle: Get threads for the current session
105
+ */
106
+ export declare function getThreads(): ThreadObject[];
107
+ /**
108
+ * OD-thread-lifecycle: Resolve a thread in session state by ID.
109
+ * Returns the resolved thread or null if not found.
110
+ */
111
+ export declare function resolveThreadInState(threadId: string, resolutionNote?: string): ThreadObject | null;
112
+ export {};
113
+ //# sourceMappingURL=session-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/services/session-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjH,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAKD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,eAAe,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,CAAC,GAAG;IAAE,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;CAAE,GAAG,IAAI,CAUjN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAEzD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAc5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CAEjD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAiBxE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,gBAAgB,EAAE,CAErD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAQ7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAY7D;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,WAAW,EAAE,CAE/C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAOlD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,YAAY,EAAE,CAE5C;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,IAAI,CAY3D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAOxD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,YAAY,EAAE,CAE3C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAYnG"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Session State Management
3
+ * OD-547: Track current session context for auto-injecting into recall calls
4
+ * OD-552: Track surfaced scars for auto-bridging Q6 answers to scar_usage records
5
+ *
6
+ * Maintains in-memory state of the current active session including:
7
+ * - session_id from session_start
8
+ * - linear_issue if working on a Linear issue
9
+ * - agent identity
10
+ * - surfaced scars (accumulated from session_start + recall calls)
11
+ *
12
+ * This allows recall() to always assign variants even without explicit parameters.
13
+ */
14
+ // Global session state (single active session per MCP server instance)
15
+ let currentSession = null;
16
+ /**
17
+ * Set the current active session
18
+ * Called by session_start
19
+ */
20
+ export function setCurrentSession(context) {
21
+ currentSession = {
22
+ ...context,
23
+ surfacedScars: context.surfacedScars || [],
24
+ confirmations: [],
25
+ observations: [],
26
+ children: [],
27
+ threads: context.threads || [],
28
+ };
29
+ console.error(`[session-state] Active session set: ${context.sessionId}${context.linearIssue ? ` (issue: ${context.linearIssue})` : ''}`);
30
+ }
31
+ /**
32
+ * Get the current active session
33
+ * Returns null if no session active
34
+ */
35
+ export function getCurrentSession() {
36
+ return currentSession;
37
+ }
38
+ /**
39
+ * Clear the current session
40
+ * Called by session_close
41
+ */
42
+ export function clearCurrentSession() {
43
+ if (currentSession) {
44
+ console.error(`[session-state] Clearing session: ${currentSession.sessionId}`);
45
+ }
46
+ currentSession = null;
47
+ }
48
+ /**
49
+ * Check if currently working on a Linear issue
50
+ */
51
+ export function hasActiveIssue() {
52
+ return !!(currentSession?.linearIssue);
53
+ }
54
+ /**
55
+ * OD-552: Add surfaced scars to tracking (deduplicates by scar_id)
56
+ * Called by session_start and recall when scars are surfaced.
57
+ */
58
+ export function addSurfacedScars(scars) {
59
+ if (!currentSession) {
60
+ console.warn("[session-state] Cannot add surfaced scars: no active session");
61
+ return;
62
+ }
63
+ for (const scar of scars) {
64
+ const exists = currentSession.surfacedScars.some(s => s.scar_id === scar.scar_id);
65
+ if (!exists) {
66
+ currentSession.surfacedScars.push(scar);
67
+ }
68
+ }
69
+ console.error(`[session-state] Surfaced scars tracked: ${currentSession.surfacedScars.length} total`);
70
+ }
71
+ /**
72
+ * OD-552: Get all surfaced scars for the current session
73
+ */
74
+ export function getSurfacedScars() {
75
+ return currentSession?.surfacedScars || [];
76
+ }
77
+ /**
78
+ * Add scar confirmations (refute-or-obey) to the current session.
79
+ * Called by confirm_scars tool after validation.
80
+ */
81
+ export function addConfirmations(confirmations) {
82
+ if (!currentSession) {
83
+ console.warn("[session-state] Cannot add confirmations: no active session");
84
+ return;
85
+ }
86
+ for (const conf of confirmations) {
87
+ // Replace existing confirmation for same scar_id (allow re-confirmation)
88
+ const idx = currentSession.confirmations.findIndex(c => c.scar_id === conf.scar_id);
89
+ if (idx >= 0) {
90
+ currentSession.confirmations[idx] = conf;
91
+ }
92
+ else {
93
+ currentSession.confirmations.push(conf);
94
+ }
95
+ }
96
+ console.error(`[session-state] Confirmations tracked: ${currentSession.confirmations.length} total`);
97
+ }
98
+ /**
99
+ * Get all scar confirmations for the current session.
100
+ */
101
+ export function getConfirmations() {
102
+ return currentSession?.confirmations || [];
103
+ }
104
+ /**
105
+ * Check if there are recall-surfaced scars that haven't been confirmed.
106
+ * Only checks scars with source "recall" — session_start scars don't require confirmation.
107
+ */
108
+ export function hasUnconfirmedScars() {
109
+ if (!currentSession)
110
+ return false;
111
+ const recallScars = currentSession.surfacedScars.filter(s => s.source === "recall");
112
+ if (recallScars.length === 0)
113
+ return false;
114
+ const confirmedIds = new Set(currentSession.confirmations.map(c => c.scar_id));
115
+ return recallScars.some(s => !confirmedIds.has(s.scar_id));
116
+ }
117
+ /**
118
+ * v2 Phase 2: Add observations from sub-agents/teammates
119
+ */
120
+ export function addObservations(newObs) {
121
+ if (!currentSession) {
122
+ console.warn("[session-state] Cannot add observations: no active session");
123
+ return 0;
124
+ }
125
+ const timestamped = newObs.map(o => ({
126
+ ...o,
127
+ absorbed_at: o.absorbed_at || new Date().toISOString(),
128
+ }));
129
+ currentSession.observations.push(...timestamped);
130
+ console.error(`[session-state] Observations tracked: ${currentSession.observations.length} total`);
131
+ return timestamped.length;
132
+ }
133
+ /**
134
+ * v2 Phase 2: Get all observations for the current session
135
+ */
136
+ export function getObservations() {
137
+ return currentSession?.observations || [];
138
+ }
139
+ /**
140
+ * v2 Phase 2: Register a child agent in the current session
141
+ */
142
+ export function addChild(child) {
143
+ if (!currentSession) {
144
+ console.warn("[session-state] Cannot add child: no active session");
145
+ return;
146
+ }
147
+ currentSession.children.push(child);
148
+ console.error(`[session-state] Child registered: ${child.role} (${child.type}), total: ${currentSession.children.length}`);
149
+ }
150
+ /**
151
+ * v2 Phase 2: Get all children for the current session
152
+ */
153
+ export function getChildren() {
154
+ return currentSession?.children || [];
155
+ }
156
+ export function getSessionActivity() {
157
+ if (!currentSession)
158
+ return null;
159
+ const durationMs = Date.now() - currentSession.startedAt.getTime();
160
+ return {
161
+ duration_min: durationMs / (1000 * 60),
162
+ recall_count: currentSession.surfacedScars.filter(s => s.source === "recall").length,
163
+ observation_count: currentSession.observations.length,
164
+ children_count: currentSession.children.length,
165
+ thread_count: currentSession.threads.filter(t => t.status === "open").length,
166
+ };
167
+ }
168
+ /**
169
+ * OD-thread-lifecycle: Set threads for the current session
170
+ */
171
+ export function setThreads(threads) {
172
+ if (!currentSession) {
173
+ console.warn("[session-state] Cannot set threads: no active session");
174
+ return;
175
+ }
176
+ currentSession.threads = threads;
177
+ console.error(`[session-state] Threads set: ${threads.length} total`);
178
+ }
179
+ /**
180
+ * OD-thread-lifecycle: Get threads for the current session
181
+ */
182
+ export function getThreads() {
183
+ return currentSession?.threads || [];
184
+ }
185
+ /**
186
+ * OD-thread-lifecycle: Resolve a thread in session state by ID.
187
+ * Returns the resolved thread or null if not found.
188
+ */
189
+ export function resolveThreadInState(threadId, resolutionNote) {
190
+ if (!currentSession)
191
+ return null;
192
+ const thread = currentSession.threads.find((t) => t.id === threadId);
193
+ if (!thread || thread.status === "resolved")
194
+ return thread || null;
195
+ thread.status = "resolved";
196
+ thread.resolved_at = new Date().toISOString();
197
+ thread.resolved_by_session = currentSession.sessionId;
198
+ if (resolutionNote)
199
+ thread.resolution_note = resolutionNote;
200
+ console.error(`[session-state] Thread resolved: ${threadId}`);
201
+ return thread;
202
+ }
203
+ //# sourceMappingURL=session-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-state.js","sourceRoot":"","sources":["../../src/services/session-state.ts"],"names":[],"mappings":"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"}