gitmem-mcp 1.0.2 → 1.0.4

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 (299) hide show
  1. package/CHANGELOG.md +20 -6
  2. package/README.md +30 -9
  3. package/dist/commands/check.d.ts +1 -1
  4. package/dist/commands/check.js +4 -3
  5. package/dist/diagnostics/anonymizer.d.ts +1 -1
  6. package/dist/diagnostics/anonymizer.js +1 -1
  7. package/dist/diagnostics/channels.d.ts +1 -1
  8. package/dist/diagnostics/channels.js +1 -1
  9. package/dist/diagnostics/collector.d.ts +1 -1
  10. package/dist/diagnostics/collector.js +1 -1
  11. package/dist/diagnostics/index.d.ts +1 -1
  12. package/dist/diagnostics/index.js +1 -1
  13. package/dist/hooks/quick-retrieve.js +2 -1
  14. package/dist/index.js +0 -0
  15. package/dist/schemas/active-sessions.d.ts +9 -9
  16. package/dist/schemas/active-sessions.js +1 -1
  17. package/dist/schemas/common.d.ts +2 -5
  18. package/dist/schemas/common.js +13 -7
  19. package/dist/schemas/create-learning.d.ts +4 -4
  20. package/dist/schemas/create-learning.js +1 -1
  21. package/dist/schemas/session-close.d.ts +5 -8
  22. package/dist/schemas/session-close.js +7 -3
  23. package/dist/schemas/session-start.d.ts +4 -4
  24. package/dist/schemas/session-start.js +1 -1
  25. package/dist/schemas/thread.d.ts +1 -1
  26. package/dist/schemas/thread.js +1 -1
  27. package/dist/server.d.ts +2 -2
  28. package/dist/server.js +21 -10
  29. package/dist/services/active-sessions.js +3 -2
  30. package/dist/services/agent-briefing.d.ts +12 -0
  31. package/dist/services/agent-briefing.js +81 -0
  32. package/dist/services/agent-detection.d.ts +2 -1
  33. package/dist/services/agent-detection.js +23 -14
  34. package/dist/services/analytics.d.ts +1 -1
  35. package/dist/services/analytics.js +3 -3
  36. package/dist/services/behavioral-decay.js +2 -2
  37. package/dist/services/cache.d.ts +1 -1
  38. package/dist/services/cache.js +1 -1
  39. package/dist/services/compliance-validator.d.ts +1 -1
  40. package/dist/services/compliance-validator.js +5 -5
  41. package/dist/services/config.d.ts +1 -1
  42. package/dist/services/config.js +1 -1
  43. package/dist/services/file-lock.js +12 -0
  44. package/dist/services/gitmem-dir.d.ts +17 -4
  45. package/dist/services/gitmem-dir.js +43 -9
  46. package/dist/services/local-file-storage.d.ts +1 -1
  47. package/dist/services/local-file-storage.js +16 -10
  48. package/dist/services/local-vector-search.d.ts +1 -1
  49. package/dist/services/local-vector-search.js +2 -2
  50. package/dist/services/metrics.d.ts +6 -6
  51. package/dist/services/metrics.js +8 -8
  52. package/dist/services/session-state.d.ts +7 -7
  53. package/dist/services/session-state.js +19 -7
  54. package/dist/services/startup.d.ts +1 -1
  55. package/dist/services/startup.js +3 -2
  56. package/dist/services/supabase-client.d.ts +17 -6
  57. package/dist/services/supabase-client.js +44 -8
  58. package/dist/services/thread-manager.d.ts +1 -1
  59. package/dist/services/thread-manager.js +5 -5
  60. package/dist/services/thread-supabase.d.ts +1 -1
  61. package/dist/services/thread-supabase.js +2 -2
  62. package/dist/services/tier.d.ts +2 -0
  63. package/dist/services/tier.js +4 -0
  64. package/dist/services/transcript-chunker.d.ts +1 -1
  65. package/dist/services/transcript-chunker.js +1 -1
  66. package/dist/services/triple-writer.d.ts +4 -4
  67. package/dist/services/triple-writer.js +11 -20
  68. package/dist/services/variant-assignment.d.ts +6 -6
  69. package/dist/services/variant-assignment.js +9 -8
  70. package/dist/tools/analyze.d.ts +2 -2
  71. package/dist/tools/analyze.js +2 -2
  72. package/dist/tools/archive-learning.js +36 -22
  73. package/dist/tools/confirm-scars.js +4 -0
  74. package/dist/tools/create-decision.d.ts +1 -1
  75. package/dist/tools/create-decision.js +2 -2
  76. package/dist/tools/create-learning.d.ts +1 -1
  77. package/dist/tools/create-learning.js +4 -4
  78. package/dist/tools/create-linear-issue.d.ts +18 -0
  79. package/dist/tools/create-linear-issue.js +197 -0
  80. package/dist/tools/create-thread.d.ts +1 -1
  81. package/dist/tools/create-thread.js +2 -2
  82. package/dist/tools/definitions.d.ts +280 -58
  83. package/dist/tools/definitions.js +127 -87
  84. package/dist/tools/get-transcript.d.ts +1 -1
  85. package/dist/tools/get-transcript.js +1 -1
  86. package/dist/tools/graph-traverse.d.ts +1 -1
  87. package/dist/tools/graph-traverse.js +20 -17
  88. package/dist/tools/list-threads.d.ts +2 -2
  89. package/dist/tools/list-threads.js +4 -4
  90. package/dist/tools/log.d.ts +1 -1
  91. package/dist/tools/log.js +1 -1
  92. package/dist/tools/prepare-context.d.ts +1 -1
  93. package/dist/tools/prepare-context.js +2 -2
  94. package/dist/tools/recall.d.ts +5 -4
  95. package/dist/tools/recall.js +37 -28
  96. package/dist/tools/record-scar-usage-batch.js +2 -2
  97. package/dist/tools/record-scar-usage.d.ts +1 -1
  98. package/dist/tools/record-scar-usage.js +3 -3
  99. package/dist/tools/resolve-thread.d.ts +2 -2
  100. package/dist/tools/resolve-thread.js +3 -3
  101. package/dist/tools/save-transcript.d.ts +1 -1
  102. package/dist/tools/save-transcript.js +1 -1
  103. package/dist/tools/search.d.ts +1 -1
  104. package/dist/tools/search.js +1 -1
  105. package/dist/tools/session-close.d.ts +1 -1
  106. package/dist/tools/session-close.js +58 -57
  107. package/dist/tools/session-start.d.ts +5 -5
  108. package/dist/tools/session-start.js +63 -61
  109. package/dist/types/index.d.ts +17 -13
  110. package/hooks/.claude-plugin/plugin.json +1 -1
  111. package/hooks/scripts/post-tool-use.sh +1 -1
  112. package/hooks/scripts/recall-check.sh +1 -1
  113. package/hooks/scripts/session-close-check.sh +1 -1
  114. package/hooks/scripts/session-start.sh +1 -1
  115. package/package.json +6 -3
  116. package/schema/starter-scars.json +3 -153
  117. package/dist/commands/check.d.ts.map +0 -1
  118. package/dist/commands/check.js.map +0 -1
  119. package/dist/constants/closing-questions.d.ts.map +0 -1
  120. package/dist/constants/closing-questions.js.map +0 -1
  121. package/dist/diagnostics/anonymizer.d.ts.map +0 -1
  122. package/dist/diagnostics/anonymizer.js.map +0 -1
  123. package/dist/diagnostics/channels.d.ts.map +0 -1
  124. package/dist/diagnostics/channels.js.map +0 -1
  125. package/dist/diagnostics/collector.d.ts.map +0 -1
  126. package/dist/diagnostics/collector.js.map +0 -1
  127. package/dist/diagnostics/index.d.ts.map +0 -1
  128. package/dist/diagnostics/index.js.map +0 -1
  129. package/dist/hooks/format-utils.d.ts.map +0 -1
  130. package/dist/hooks/format-utils.js.map +0 -1
  131. package/dist/hooks/quick-retrieve.d.ts.map +0 -1
  132. package/dist/hooks/quick-retrieve.js.map +0 -1
  133. package/dist/index.d.ts.map +0 -1
  134. package/dist/index.js.map +0 -1
  135. package/dist/schemas/absorb-observations.d.ts.map +0 -1
  136. package/dist/schemas/absorb-observations.js.map +0 -1
  137. package/dist/schemas/active-sessions.d.ts.map +0 -1
  138. package/dist/schemas/active-sessions.js.map +0 -1
  139. package/dist/schemas/analyze.d.ts.map +0 -1
  140. package/dist/schemas/analyze.js.map +0 -1
  141. package/dist/schemas/common.d.ts.map +0 -1
  142. package/dist/schemas/common.js.map +0 -1
  143. package/dist/schemas/create-decision.d.ts.map +0 -1
  144. package/dist/schemas/create-decision.js.map +0 -1
  145. package/dist/schemas/create-learning.d.ts.map +0 -1
  146. package/dist/schemas/create-learning.js.map +0 -1
  147. package/dist/schemas/get-transcript.d.ts.map +0 -1
  148. package/dist/schemas/get-transcript.js.map +0 -1
  149. package/dist/schemas/index.d.ts.map +0 -1
  150. package/dist/schemas/index.js.map +0 -1
  151. package/dist/schemas/log.d.ts.map +0 -1
  152. package/dist/schemas/log.js.map +0 -1
  153. package/dist/schemas/prepare-context.d.ts.map +0 -1
  154. package/dist/schemas/prepare-context.js.map +0 -1
  155. package/dist/schemas/recall.d.ts.map +0 -1
  156. package/dist/schemas/recall.js.map +0 -1
  157. package/dist/schemas/record-scar-usage-batch.d.ts.map +0 -1
  158. package/dist/schemas/record-scar-usage-batch.js.map +0 -1
  159. package/dist/schemas/record-scar-usage.d.ts.map +0 -1
  160. package/dist/schemas/record-scar-usage.js.map +0 -1
  161. package/dist/schemas/registry.d.ts.map +0 -1
  162. package/dist/schemas/registry.js.map +0 -1
  163. package/dist/schemas/save-transcript.d.ts.map +0 -1
  164. package/dist/schemas/save-transcript.js.map +0 -1
  165. package/dist/schemas/search-transcripts.d.ts.map +0 -1
  166. package/dist/schemas/search-transcripts.js.map +0 -1
  167. package/dist/schemas/search.d.ts.map +0 -1
  168. package/dist/schemas/search.js.map +0 -1
  169. package/dist/schemas/session-close.d.ts.map +0 -1
  170. package/dist/schemas/session-close.js.map +0 -1
  171. package/dist/schemas/session-start.d.ts.map +0 -1
  172. package/dist/schemas/session-start.js.map +0 -1
  173. package/dist/schemas/thread.d.ts.map +0 -1
  174. package/dist/schemas/thread.js.map +0 -1
  175. package/dist/server.d.ts.map +0 -1
  176. package/dist/server.js.map +0 -1
  177. package/dist/services/active-sessions.d.ts.map +0 -1
  178. package/dist/services/active-sessions.js.map +0 -1
  179. package/dist/services/agent-detection.d.ts.map +0 -1
  180. package/dist/services/agent-detection.js.map +0 -1
  181. package/dist/services/analytics.d.ts.map +0 -1
  182. package/dist/services/analytics.js.map +0 -1
  183. package/dist/services/behavioral-decay.d.ts.map +0 -1
  184. package/dist/services/behavioral-decay.js.map +0 -1
  185. package/dist/services/bm25.d.ts.map +0 -1
  186. package/dist/services/bm25.js.map +0 -1
  187. package/dist/services/cache.d.ts.map +0 -1
  188. package/dist/services/cache.js.map +0 -1
  189. package/dist/services/cache.test.d.ts +0 -8
  190. package/dist/services/cache.test.d.ts.map +0 -1
  191. package/dist/services/cache.test.js +0 -267
  192. package/dist/services/cache.test.js.map +0 -1
  193. package/dist/services/compliance-validator.d.ts.map +0 -1
  194. package/dist/services/compliance-validator.js.map +0 -1
  195. package/dist/services/config.d.ts.map +0 -1
  196. package/dist/services/config.js.map +0 -1
  197. package/dist/services/display-protocol.d.ts.map +0 -1
  198. package/dist/services/display-protocol.js.map +0 -1
  199. package/dist/services/effect-tracker.d.ts.map +0 -1
  200. package/dist/services/effect-tracker.js.map +0 -1
  201. package/dist/services/embedding.d.ts.map +0 -1
  202. package/dist/services/embedding.js.map +0 -1
  203. package/dist/services/file-lock.d.ts.map +0 -1
  204. package/dist/services/file-lock.js.map +0 -1
  205. package/dist/services/gitmem-dir.d.ts.map +0 -1
  206. package/dist/services/gitmem-dir.js.map +0 -1
  207. package/dist/services/local-file-storage.d.ts.map +0 -1
  208. package/dist/services/local-file-storage.js.map +0 -1
  209. package/dist/services/local-vector-search.d.ts.map +0 -1
  210. package/dist/services/local-vector-search.js.map +0 -1
  211. package/dist/services/metrics.d.ts.map +0 -1
  212. package/dist/services/metrics.js.map +0 -1
  213. package/dist/services/session-state.d.ts.map +0 -1
  214. package/dist/services/session-state.js.map +0 -1
  215. package/dist/services/startup.d.ts.map +0 -1
  216. package/dist/services/startup.js.map +0 -1
  217. package/dist/services/storage.d.ts.map +0 -1
  218. package/dist/services/storage.js.map +0 -1
  219. package/dist/services/supabase-client.d.ts.map +0 -1
  220. package/dist/services/supabase-client.js.map +0 -1
  221. package/dist/services/thread-dedup.d.ts.map +0 -1
  222. package/dist/services/thread-dedup.js.map +0 -1
  223. package/dist/services/thread-manager.d.ts.map +0 -1
  224. package/dist/services/thread-manager.js.map +0 -1
  225. package/dist/services/thread-suggestions.d.ts.map +0 -1
  226. package/dist/services/thread-suggestions.js.map +0 -1
  227. package/dist/services/thread-supabase.d.ts.map +0 -1
  228. package/dist/services/thread-supabase.js.map +0 -1
  229. package/dist/services/thread-vitality.d.ts.map +0 -1
  230. package/dist/services/thread-vitality.js.map +0 -1
  231. package/dist/services/tier.d.ts.map +0 -1
  232. package/dist/services/tier.js.map +0 -1
  233. package/dist/services/timezone.d.ts.map +0 -1
  234. package/dist/services/timezone.js.map +0 -1
  235. package/dist/services/transcript-chunker.d.ts.map +0 -1
  236. package/dist/services/transcript-chunker.js.map +0 -1
  237. package/dist/services/triple-writer.d.ts.map +0 -1
  238. package/dist/services/triple-writer.js.map +0 -1
  239. package/dist/services/variant-assignment.d.ts.map +0 -1
  240. package/dist/services/variant-assignment.js.map +0 -1
  241. package/dist/services/variant-generation.d.ts.map +0 -1
  242. package/dist/services/variant-generation.js.map +0 -1
  243. package/dist/tools/absorb-observations.d.ts.map +0 -1
  244. package/dist/tools/absorb-observations.js.map +0 -1
  245. package/dist/tools/analyze.d.ts.map +0 -1
  246. package/dist/tools/analyze.js.map +0 -1
  247. package/dist/tools/archive-learning.d.ts.map +0 -1
  248. package/dist/tools/archive-learning.js.map +0 -1
  249. package/dist/tools/cleanup-threads.d.ts.map +0 -1
  250. package/dist/tools/cleanup-threads.js.map +0 -1
  251. package/dist/tools/confirm-scars.d.ts.map +0 -1
  252. package/dist/tools/confirm-scars.js.map +0 -1
  253. package/dist/tools/create-decision.d.ts.map +0 -1
  254. package/dist/tools/create-decision.js.map +0 -1
  255. package/dist/tools/create-learning.d.ts.map +0 -1
  256. package/dist/tools/create-learning.js.map +0 -1
  257. package/dist/tools/create-thread.d.ts.map +0 -1
  258. package/dist/tools/create-thread.js.map +0 -1
  259. package/dist/tools/definitions.d.ts.map +0 -1
  260. package/dist/tools/definitions.js.map +0 -1
  261. package/dist/tools/dismiss-suggestion.d.ts.map +0 -1
  262. package/dist/tools/dismiss-suggestion.js.map +0 -1
  263. package/dist/tools/get-transcript.d.ts.map +0 -1
  264. package/dist/tools/get-transcript.js.map +0 -1
  265. package/dist/tools/graph-traverse.d.ts.map +0 -1
  266. package/dist/tools/graph-traverse.js.map +0 -1
  267. package/dist/tools/list-threads.d.ts.map +0 -1
  268. package/dist/tools/list-threads.js.map +0 -1
  269. package/dist/tools/log.d.ts.map +0 -1
  270. package/dist/tools/log.js.map +0 -1
  271. package/dist/tools/prepare-context.d.ts.map +0 -1
  272. package/dist/tools/prepare-context.js.map +0 -1
  273. package/dist/tools/promote-suggestion.d.ts.map +0 -1
  274. package/dist/tools/promote-suggestion.js.map +0 -1
  275. package/dist/tools/recall.d.ts.map +0 -1
  276. package/dist/tools/recall.js.map +0 -1
  277. package/dist/tools/recall.test.d.ts +0 -5
  278. package/dist/tools/recall.test.d.ts.map +0 -1
  279. package/dist/tools/recall.test.js +0 -155
  280. package/dist/tools/recall.test.js.map +0 -1
  281. package/dist/tools/record-scar-usage-batch.d.ts.map +0 -1
  282. package/dist/tools/record-scar-usage-batch.js.map +0 -1
  283. package/dist/tools/record-scar-usage.d.ts.map +0 -1
  284. package/dist/tools/record-scar-usage.js.map +0 -1
  285. package/dist/tools/resolve-thread.d.ts.map +0 -1
  286. package/dist/tools/resolve-thread.js.map +0 -1
  287. package/dist/tools/save-transcript.d.ts.map +0 -1
  288. package/dist/tools/save-transcript.js.map +0 -1
  289. package/dist/tools/search-transcripts.d.ts.map +0 -1
  290. package/dist/tools/search-transcripts.js.map +0 -1
  291. package/dist/tools/search.d.ts.map +0 -1
  292. package/dist/tools/search.js.map +0 -1
  293. package/dist/tools/session-close.d.ts.map +0 -1
  294. package/dist/tools/session-close.js.map +0 -1
  295. package/dist/tools/session-start.d.ts.map +0 -1
  296. package/dist/tools/session-start.js.map +0 -1
  297. package/dist/types/index.d.ts.map +0 -1
  298. package/dist/types/index.js.map +0 -1
  299. package/hooks/tests/test-hooks.sh +0 -577
@@ -20,30 +20,21 @@ const HALF_LIFE_PROCESS = 9999;
20
20
  * Canonical persona name map.
21
21
  * Raw personas_involved values may contain full names or contextual suffixes.
22
22
  * This ensures consistent node identity in the knowledge graph.
23
+ *
24
+ * Users can populate this with their own team/persona names.
25
+ * Keys are lowercase, values are canonical display names.
23
26
  */
24
- const CANONICAL_PERSONA_NAMES = {
25
- "elena vos": "Elena",
26
- "elena": "Elena",
27
- "marcus thorne": "Marcus",
28
- "marcus": "Marcus",
29
- "reiko tanaka": "Reiko",
30
- "reiko": "Reiko",
31
- "jax": "Jax",
32
- "jax dimitri": "Jax",
33
- "jax reed": "Jax",
34
- "chris crawford": "Chris Crawford",
35
- "chris": "Chris Crawford",
36
- };
27
+ const CANONICAL_PERSONA_NAMES = {};
37
28
  /**
38
29
  * Normalize a persona label to its canonical form.
39
30
  * Strips contextual suffixes like " - UX navigation clarity" or ": Prefers non-invasive..."
40
31
  * Then maps to canonical short name if known.
41
32
  *
42
33
  * Examples:
43
- * "Elena Vos" → "Elena"
44
- * "Marcus - Architectural pattern" → "Marcus"
45
- * "Elena: Prefers non-invasive instrumentation" → "Elena"
46
- * "Chris Crawford - Process decision" → "Chris Crawford"
34
+ * "Alice Smith" → "Alice" (if mapped)
35
+ * "Bob - Architectural pattern" → "Bob" (if mapped)
36
+ * "Alice: Prefers non-invasive instrumentation" → "Alice" (if mapped)
37
+ * "Unknown Developer - Process decision" → "Unknown Developer" (passthrough)
47
38
  */
48
39
  export function normalizePersonaLabel(raw) {
49
40
  // Strip contextual suffix after " - " or ": "
@@ -54,11 +45,11 @@ export function normalizePersonaLabel(raw) {
54
45
  const canonical = CANONICAL_PERSONA_NAMES[name.toLowerCase()];
55
46
  return canonical || name;
56
47
  }
57
- /** Set of canonical persona names (Orchestra team members + human). */
48
+ /** Set of canonical persona names (team members). */
58
49
  const KNOWN_PERSONAS = new Set(Object.values(CANONICAL_PERSONA_NAMES));
59
50
  /**
60
- * Determine if a name refers to an Orchestra persona vs an agent.
61
- * Returns true for Elena, Marcus, Reiko, Jax, Chris Crawford.
51
+ * Determine if a name refers to a known persona vs an agent.
52
+ * Returns true for names in the CANONICAL_PERSONA_NAMES map.
62
53
  */
63
54
  function isPersonaName(name) {
64
55
  return KNOWN_PERSONAS.has(normalizePersonaLabel(name));
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Scar Variant Assignment Service
3
- * OD-525: Integrates variant assignment into enforcement engine
4
- * OD-547: Switched from issue-keyed to agent-keyed assignment
3
+ * Integrates variant assignment into enforcement engine
4
+ * Switched from issue-keyed to agent-keyed assignment
5
5
  *
6
6
  * Handles:
7
7
  * - Random variant assignment for scars with variants
@@ -29,7 +29,7 @@ export interface ScarVariant {
29
29
  }
30
30
  /**
31
31
  * Assignment record
32
- * OD-547: Primary key is (agent_id, scar_id), issue_id/session_id are metadata
32
+ * Primary key is (agent_id, scar_id), issue_id/session_id are metadata
33
33
  */
34
34
  export interface VariantAssignment {
35
35
  id: string;
@@ -55,12 +55,12 @@ export interface ScarWithVariant {
55
55
  export declare function getActiveVariants(scarId: string): Promise<ScarVariant[]>;
56
56
  /**
57
57
  * Get existing assignment for an agent + scar pair
58
- * OD-547: Changed from issue-keyed to agent-keyed lookup
58
+ * Changed from issue-keyed to agent-keyed lookup
59
59
  */
60
60
  export declare function getExistingAssignment(agentId: string, scarId: string): Promise<VariantAssignment | null>;
61
61
  /**
62
62
  * Create random variant assignment
63
- * OD-547: Agent-keyed with optional issue/session metadata
63
+ * Agent-keyed with optional issue/session metadata
64
64
  */
65
65
  export declare function createVariantAssignment(agentId: string, scarId: string, variants: ScarVariant[], metadata?: {
66
66
  issueId?: string;
@@ -70,7 +70,7 @@ export declare function createVariantAssignment(agentId: string, scarId: string,
70
70
  * Get or create variant assignment for a scar
71
71
  * This is the main entry point for enforcement integration
72
72
  *
73
- * OD-547: Changed from issue-keyed to agent-keyed assignment.
73
+ * Changed from issue-keyed to agent-keyed assignment.
74
74
  * Agent identity is always available, so variants are always assigned.
75
75
  *
76
76
  * @param agentId - Agent identity (e.g., 'CLI', 'DAC', 'CODA-1')
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Scar Variant Assignment Service
3
- * OD-525: Integrates variant assignment into enforcement engine
4
- * OD-547: Switched from issue-keyed to agent-keyed assignment
3
+ * Integrates variant assignment into enforcement engine
4
+ * Switched from issue-keyed to agent-keyed assignment
5
5
  *
6
6
  * Handles:
7
7
  * - Random variant assignment for scars with variants
@@ -9,6 +9,7 @@
9
9
  * - Legacy scar fallback (scars without variants use original description)
10
10
  * - Blind testing (agent doesn't know which variant they received)
11
11
  */
12
+ import { randomInt } from "crypto";
12
13
  import * as supabase from "./supabase-client.js";
13
14
  /**
14
15
  * Get active variants for a scar
@@ -35,7 +36,7 @@ export async function getActiveVariants(scarId) {
35
36
  }
36
37
  /**
37
38
  * Get existing assignment for an agent + scar pair
38
- * OD-547: Changed from issue-keyed to agent-keyed lookup
39
+ * Changed from issue-keyed to agent-keyed lookup
39
40
  */
40
41
  export async function getExistingAssignment(agentId, scarId) {
41
42
  if (!supabase.isConfigured()) {
@@ -60,15 +61,15 @@ export async function getExistingAssignment(agentId, scarId) {
60
61
  }
61
62
  /**
62
63
  * Create random variant assignment
63
- * OD-547: Agent-keyed with optional issue/session metadata
64
+ * Agent-keyed with optional issue/session metadata
64
65
  */
65
66
  export async function createVariantAssignment(agentId, scarId, variants, metadata) {
66
67
  if (!supabase.isConfigured() || variants.length === 0) {
67
68
  return null;
68
69
  }
69
70
  try {
70
- // Random selection from active variants
71
- const randomIndex = Math.floor(Math.random() * variants.length);
71
+ // Cryptographically secure random selection for blind A/B testing integrity
72
+ const randomIndex = randomInt(0, variants.length);
72
73
  const selectedVariant = variants[randomIndex];
73
74
  const result = await supabase.directUpsert("variant_assignments", {
74
75
  agent_id: agentId,
@@ -86,7 +87,7 @@ export async function createVariantAssignment(agentId, scarId, variants, metadat
86
87
  console.error(`[variant-assignment] Assignment already exists (race condition), fetching...`);
87
88
  return await getExistingAssignment(agentId, scarId);
88
89
  }
89
- console.error(`[variant-assignment] Exception creating assignment:`, error);
90
+ console.error(`[variant-assignment] Failed to create assignment for scar ${scarId}`);
90
91
  return null;
91
92
  }
92
93
  }
@@ -94,7 +95,7 @@ export async function createVariantAssignment(agentId, scarId, variants, metadat
94
95
  * Get or create variant assignment for a scar
95
96
  * This is the main entry point for enforcement integration
96
97
  *
97
- * OD-547: Changed from issue-keyed to agent-keyed assignment.
98
+ * Changed from issue-keyed to agent-keyed assignment.
98
99
  * Agent identity is always available, so variants are always assigned.
99
100
  *
100
101
  * @param agentId - Agent identity (e.g., 'CLI', 'DAC', 'CODA-1')
@@ -1,11 +1,11 @@
1
1
  /**
2
- * analyze Tool (OD-567)
2
+ * analyze Tool
3
3
  *
4
4
  * Session analytics and insights engine. Provides structured analysis
5
5
  * of session history, closing reflections, agent patterns, and more.
6
6
  *
7
7
  * Starts with "summary" lens; expanded with additional lenses in
8
- * OD-568 (Tier 1), OD-569 (Tier 2), OD-570 (Tier 3), OD-572 (Tier 4).
8
+ * (Tier 1).
9
9
  *
10
10
  * Performance target: 3000ms
11
11
  */
@@ -1,11 +1,11 @@
1
1
  /**
2
- * analyze Tool (OD-567)
2
+ * analyze Tool
3
3
  *
4
4
  * Session analytics and insights engine. Provides structured analysis
5
5
  * of session history, closing reflections, agent patterns, and more.
6
6
  *
7
7
  * Starts with "summary" lens; expanded with additional lenses in
8
- * OD-568 (Tier 1), OD-569 (Tier 2), OD-570 (Tier 3), OD-572 (Tier 4).
8
+ * (Tier 1).
9
9
  *
10
10
  * Performance target: 3000ms
11
11
  */
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { directPatch, isConfigured } from "../services/supabase-client.js";
12
12
  import { hasSupabase } from "../services/tier.js";
13
+ import { getStorage } from "../services/storage.js";
13
14
  import { flushCache } from "../services/startup.js";
14
15
  import { Timer } from "../services/metrics.js";
15
16
  import { wrapDisplay } from "../services/display-protocol.js";
@@ -26,35 +27,48 @@ export async function archiveLearning(params) {
26
27
  performance_ms: timer.stop(),
27
28
  };
28
29
  }
29
- if (!hasSupabase() || !isConfigured()) {
30
- const msg = "archive_learning requires Supabase (pro/dev tier)";
31
- return {
32
- success: false,
33
- id: params.id,
34
- cache_flushed: false,
35
- display: wrapDisplay(msg),
36
- error: msg,
37
- performance_ms: timer.stop(),
38
- };
39
- }
40
30
  try {
41
31
  const archivedAt = new Date().toISOString();
42
- await directPatch("orchestra_learnings", { id: `eq.${params.id}` }, {
43
- is_active: false,
44
- archived_at: archivedAt,
45
- });
46
- // Flush local cache so archived scar is immediately excluded
47
32
  let cacheFlushed = false;
48
- try {
49
- await flushCache();
50
- cacheFlushed = true;
33
+ if (hasSupabase() && isConfigured()) {
34
+ // Pro/dev: patch in Supabase
35
+ await directPatch("orchestra_learnings", { id: `eq.${params.id}` }, {
36
+ is_active: false,
37
+ archived_at: archivedAt,
38
+ });
39
+ try {
40
+ await flushCache();
41
+ cacheFlushed = true;
42
+ }
43
+ catch {
44
+ console.error("[archive-learning] Cache flush failed (non-fatal)");
45
+ }
51
46
  }
52
- catch {
53
- console.error("[archive-learning] Cache flush failed (non-fatal)");
47
+ else {
48
+ // Free tier: update in local JSON
49
+ const storage = getStorage();
50
+ const existing = await storage.get("learnings", params.id);
51
+ if (!existing) {
52
+ const msg = `Learning ${params.id} not found in local storage`;
53
+ return {
54
+ success: false,
55
+ id: params.id,
56
+ cache_flushed: false,
57
+ display: wrapDisplay(msg),
58
+ error: msg,
59
+ performance_ms: timer.stop(),
60
+ };
61
+ }
62
+ await storage.upsert("learnings", {
63
+ ...existing,
64
+ id: params.id,
65
+ is_active: false,
66
+ archived_at: archivedAt,
67
+ });
54
68
  }
55
69
  const latencyMs = timer.stop();
56
70
  const reasonText = params.reason ? ` Reason: ${params.reason}` : "";
57
- const display = `Archived learning ${params.id}.${reasonText}\nCache ${cacheFlushed ? "flushed" : "flush failed"} (${latencyMs}ms)`;
71
+ const display = `Archived learning ${params.id}.${reasonText}\n(${latencyMs}ms)`;
58
72
  return {
59
73
  success: true,
60
74
  id: params.id,
@@ -176,12 +176,16 @@ export async function confirmScars(params) {
176
176
  errors.push(error);
177
177
  }
178
178
  else {
179
+ // Derive default relevance from decision if not provided
180
+ const relevance = conf.relevance ??
181
+ (conf.decision === "APPLYING" ? "high" : conf.decision === "N_A" ? "low" : "low");
179
182
  validConfirmations.push({
180
183
  scar_id: conf.scar_id,
181
184
  scar_title: scar.scar_title,
182
185
  decision: conf.decision,
183
186
  evidence: conf.evidence.trim(),
184
187
  confirmed_at: new Date().toISOString(),
188
+ relevance,
185
189
  });
186
190
  confirmedIds.add(conf.scar_id);
187
191
  }
@@ -5,7 +5,7 @@
5
5
  * Generates embeddings client-side and writes directly to Supabase REST API,
6
6
  * eliminating the ww-mcp Edge Function dependency.
7
7
  *
8
- * Performance target: <3000ms (OD-429)
8
+ * Performance target: <3000ms
9
9
  */
10
10
  import type { CreateDecisionParams, CreateDecisionResult } from "../types/index.js";
11
11
  /**
@@ -5,7 +5,7 @@
5
5
  * Generates embeddings client-side and writes directly to Supabase REST API,
6
6
  * eliminating the ww-mcp Edge Function dependency.
7
7
  *
8
- * Performance target: <3000ms (OD-429)
8
+ * Performance target: <3000ms
9
9
  */
10
10
  import { v4 as uuidv4 } from "uuid";
11
11
  import * as supabase from "../services/supabase-client.js";
@@ -74,7 +74,7 @@ export async function createDecision(params) {
74
74
  cache_status: "not_applicable",
75
75
  network_call: true,
76
76
  };
77
- // OD-466: Auto-create knowledge triples (tracked fire-and-forget)
77
+ // Auto-create knowledge triples (tracked fire-and-forget)
78
78
  getEffectTracker().track("triple_write", "decision", () => writeTriplesForDecision({
79
79
  id: decisionId,
80
80
  title: params.title,
@@ -5,7 +5,7 @@
5
5
  * Generates embeddings client-side and writes directly to Supabase REST API,
6
6
  * eliminating the ww-mcp Edge Function dependency.
7
7
  *
8
- * Performance target: <3000ms (OD-429)
8
+ * Performance target: <3000ms
9
9
  */
10
10
  import type { CreateLearningParams, CreateLearningResult } from "../types/index.js";
11
11
  /**
@@ -5,7 +5,7 @@
5
5
  * Generates embeddings client-side and writes directly to Supabase REST API,
6
6
  * eliminating the ww-mcp Edge Function dependency.
7
7
  *
8
- * Performance target: <3000ms (OD-429)
8
+ * Performance target: <3000ms
9
9
  */
10
10
  import { v4 as uuidv4 } from "uuid";
11
11
  import * as supabase from "../services/supabase-client.js";
@@ -87,7 +87,7 @@ export async function createLearning(params) {
87
87
  created_at: new Date().toISOString(),
88
88
  persona_name: agentIdentity,
89
89
  source_date: new Date().toISOString().split("T")[0],
90
- // OD-508: LLM-cooperative enforcement fields (optional)
90
+ // LLM-cooperative enforcement fields (optional)
91
91
  ...(params.why_this_matters && { why_this_matters: params.why_this_matters }),
92
92
  ...(params.action_protocol && { action_protocol: params.action_protocol }),
93
93
  ...(params.self_check_criteria && { self_check_criteria: params.self_check_criteria }),
@@ -151,14 +151,14 @@ export async function createLearning(params) {
151
151
  cache_status: "not_applicable",
152
152
  network_call: true,
153
153
  };
154
- // OD-539: Defense in depth - verify write succeeded
154
+ // Defense in depth - verify write succeeded
155
155
  // directUpsert now throws on empty result, but explicit check documents expectation
156
156
  if (!writeResult || !writeResult.id) {
157
157
  throw new Error(`Write verification failed: directUpsert returned ${writeResult ? 'record without id' : 'null/undefined'}. ` +
158
158
  `Expected record with id field.`);
159
159
  }
160
160
  console.error(`[create_learning] directUpsert succeeded, verified ID: ${writeResult.id}`);
161
- // OD-466: Auto-create knowledge triples (tracked fire-and-forget)
161
+ // Auto-create knowledge triples (tracked fire-and-forget)
162
162
  getEffectTracker().track("triple_write", "learning", () => writeTriplesForLearning({
163
163
  id: learningId,
164
164
  learning_type: params.learning_type,
@@ -0,0 +1,18 @@
1
+ /**
2
+ * create_linear_issue Tool (OD-611)
3
+ *
4
+ * Proxy Linear issue creation via GraphQL API.
5
+ * Returns slim response (~50 tokens) instead of Linear MCP's ~1400 tokens.
6
+ *
7
+ * Pattern: File-based payload handoff (same as session_close).
8
+ * Agent writes description to .gitmem/issue-payload.json, then calls this
9
+ * tool with title + teamId inline. Tool reads, merges, calls Linear, deletes file.
10
+ *
11
+ * Performance target: <2000ms (one network call)
12
+ */
13
+ import type { CreateLinearIssueParams, CreateLinearIssueResult } from "../types/index.js";
14
+ /**
15
+ * Create a Linear issue via GraphQL API with slim response.
16
+ */
17
+ export declare function createLinearIssue(params: CreateLinearIssueParams): Promise<CreateLinearIssueResult>;
18
+ //# sourceMappingURL=create-linear-issue.d.ts.map
@@ -0,0 +1,197 @@
1
+ /**
2
+ * create_linear_issue Tool (OD-611)
3
+ *
4
+ * Proxy Linear issue creation via GraphQL API.
5
+ * Returns slim response (~50 tokens) instead of Linear MCP's ~1400 tokens.
6
+ *
7
+ * Pattern: File-based payload handoff (same as session_close).
8
+ * Agent writes description to .gitmem/issue-payload.json, then calls this
9
+ * tool with title + teamId inline. Tool reads, merges, calls Linear, deletes file.
10
+ *
11
+ * Performance target: <2000ms (one network call)
12
+ */
13
+ import * as fs from "fs";
14
+ import { v4 as uuidv4 } from "uuid";
15
+ import { getGitmemPath } from "../services/gitmem-dir.js";
16
+ import { Timer, buildPerformanceData, recordMetrics, } from "../services/metrics.js";
17
+ import { getEffectTracker } from "../services/effect-tracker.js";
18
+ const LINEAR_API_URL = "https://api.linear.app/graphql";
19
+ /** GraphQL mutation — request only the fields needed for the slim response */
20
+ const ISSUE_CREATE_MUTATION = `
21
+ mutation IssueCreate($input: IssueCreateInput!) {
22
+ issueCreate(input: $input) {
23
+ success
24
+ issue {
25
+ id
26
+ identifier
27
+ url
28
+ state {
29
+ name
30
+ }
31
+ }
32
+ }
33
+ }
34
+ `;
35
+ /**
36
+ * Create a Linear issue via GraphQL API with slim response.
37
+ */
38
+ export async function createLinearIssue(params) {
39
+ const timer = new Timer();
40
+ const metricsId = uuidv4();
41
+ // 1. Check LINEAR_API_KEY
42
+ const apiKey = process.env.LINEAR_API_KEY;
43
+ if (!apiKey) {
44
+ const latencyMs = timer.stop();
45
+ return {
46
+ success: false,
47
+ error: "LINEAR_API_KEY environment variable is not set. Add it to your MCP server configuration.",
48
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
49
+ };
50
+ }
51
+ // 2. Load file-based payload (same pattern as session_close)
52
+ const payloadPath = params.payload_path || getGitmemPath("issue-payload.json");
53
+ let filePayload = {};
54
+ try {
55
+ if (fs.existsSync(payloadPath)) {
56
+ filePayload = JSON.parse(fs.readFileSync(payloadPath, "utf-8"));
57
+ console.error(`[create_linear_issue] Loaded payload from ${payloadPath}`);
58
+ // Clean up payload file after reading
59
+ try {
60
+ fs.unlinkSync(payloadPath);
61
+ }
62
+ catch {
63
+ /* ignore cleanup errors */
64
+ }
65
+ }
66
+ }
67
+ catch (error) {
68
+ console.error("[create_linear_issue] Failed to read issue-payload.json:", error);
69
+ }
70
+ // 3. Merge: inline params override file payload
71
+ const teamId = params.teamId || filePayload.teamId;
72
+ const title = params.title || filePayload.title;
73
+ if (!teamId || !title) {
74
+ const latencyMs = timer.stop();
75
+ return {
76
+ success: false,
77
+ error: "teamId and title are required. Provide inline or in .gitmem/issue-payload.json.",
78
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
79
+ };
80
+ }
81
+ // 4. Build IssueCreateInput for GraphQL
82
+ const input = {
83
+ teamId,
84
+ title,
85
+ };
86
+ // Description only comes from file payload (the large field)
87
+ if (filePayload.description) {
88
+ input.description = filePayload.description;
89
+ }
90
+ // Merge optional fields — inline overrides file
91
+ if (params.priority !== undefined || filePayload.priority !== undefined) {
92
+ input.priority = params.priority ?? filePayload.priority;
93
+ }
94
+ if (params.labelIds?.length || filePayload.labelIds?.length) {
95
+ input.labelIds = params.labelIds || filePayload.labelIds;
96
+ }
97
+ if (params.projectId || filePayload.projectId) {
98
+ input.projectId = params.projectId || filePayload.projectId;
99
+ }
100
+ if (params.assigneeId || filePayload.assigneeId) {
101
+ input.assigneeId = params.assigneeId || filePayload.assigneeId;
102
+ }
103
+ if (params.parentId || filePayload.parentId) {
104
+ input.parentId = params.parentId || filePayload.parentId;
105
+ }
106
+ if (params.stateId || filePayload.stateId) {
107
+ input.stateId = params.stateId || filePayload.stateId;
108
+ }
109
+ if (params.estimate !== undefined || filePayload.estimate !== undefined) {
110
+ input.estimate = params.estimate ?? filePayload.estimate;
111
+ }
112
+ // 5. Call Linear GraphQL API
113
+ try {
114
+ const response = await fetch(LINEAR_API_URL, {
115
+ method: "POST",
116
+ headers: {
117
+ "Content-Type": "application/json",
118
+ Authorization: apiKey,
119
+ },
120
+ body: JSON.stringify({
121
+ query: ISSUE_CREATE_MUTATION,
122
+ variables: { input },
123
+ }),
124
+ });
125
+ if (!response.ok) {
126
+ const text = await response.text();
127
+ const latencyMs = timer.stop();
128
+ return {
129
+ success: false,
130
+ error: `Linear API HTTP ${response.status}: ${text.slice(0, 200)}`,
131
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
132
+ };
133
+ }
134
+ const data = (await response.json());
135
+ // Handle GraphQL errors
136
+ if (data.errors?.length) {
137
+ const latencyMs = timer.stop();
138
+ return {
139
+ success: false,
140
+ error: `Linear GraphQL error: ${data.errors.map((e) => e.message).join("; ")}`,
141
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
142
+ };
143
+ }
144
+ const issueCreate = data.data?.issueCreate;
145
+ if (!issueCreate?.success || !issueCreate.issue) {
146
+ const latencyMs = timer.stop();
147
+ return {
148
+ success: false,
149
+ error: "Linear API returned unsuccessful issueCreate",
150
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
151
+ };
152
+ }
153
+ const issue = issueCreate.issue;
154
+ const latencyMs = timer.stop();
155
+ // 6. Fire-and-forget metrics recording
156
+ getEffectTracker().track("metrics", "create_linear_issue", () => recordMetrics({
157
+ id: metricsId,
158
+ tool_name: "create_linear_issue",
159
+ latency_ms: latencyMs,
160
+ result_count: 1,
161
+ metadata: {
162
+ identifier: issue.identifier,
163
+ teamId,
164
+ has_description: !!filePayload.description,
165
+ },
166
+ }));
167
+ // 7. Return slim response (~50 tokens vs ~1400)
168
+ return {
169
+ success: true,
170
+ identifier: issue.identifier,
171
+ url: issue.url,
172
+ id: issue.id,
173
+ state: issue.state?.name,
174
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 1, {
175
+ breakdown: {
176
+ upsert: {
177
+ latency_ms: latencyMs,
178
+ source: "supabase",
179
+ cache_status: "not_applicable",
180
+ network_call: true,
181
+ },
182
+ },
183
+ }),
184
+ };
185
+ }
186
+ catch (error) {
187
+ const errorMessage = error instanceof Error ? error.message : String(error);
188
+ console.error("[create_linear_issue] Failed:", error);
189
+ const latencyMs = timer.stop();
190
+ return {
191
+ success: false,
192
+ error: `Linear API call failed: ${errorMessage}`,
193
+ performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
194
+ };
195
+ }
196
+ }
197
+ //# sourceMappingURL=create-linear-issue.js.map
@@ -4,7 +4,7 @@
4
4
  * Create an open thread outside of session close. Threads track
5
5
  * unresolved work items that carry across sessions.
6
6
  *
7
- * OD-620: Writes to Supabase (source of truth) + local file (cache).
7
+ * Writes to Supabase (source of truth) + local file (cache).
8
8
  * Falls back to local-only if Supabase is unavailable.
9
9
  *
10
10
  * Phase 3: Semantic dedup gate — before creating, checks existing open
@@ -4,7 +4,7 @@
4
4
  * Create an open thread outside of session close. Threads track
5
5
  * unresolved work items that carry across sessions.
6
6
  *
7
- * OD-620: Writes to Supabase (source of truth) + local file (cache).
7
+ * Writes to Supabase (source of truth) + local file (cache).
8
8
  * Falls back to local-only if Supabase is unavailable.
9
9
  *
10
10
  * Phase 3: Semantic dedup gate — before creating, checks existing open
@@ -123,7 +123,7 @@ export async function createThread(params) {
123
123
  created_at: new Date().toISOString(),
124
124
  ...(sessionId && { source_session: sessionId }),
125
125
  };
126
- // OD-620: Write to Supabase (source of truth) with embedding — non-blocking on failure
126
+ // Write to Supabase (source of truth) with embedding — non-blocking on failure
127
127
  let supabaseSynced = false;
128
128
  const embeddingJson = newEmbedding ? JSON.stringify(newEmbedding) : null;
129
129
  const supabaseResult = await createThreadInSupabase(thread, project, embeddingJson);