gitmem-mcp 1.0.3 → 1.0.5

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 (293) hide show
  1. package/CHANGELOG.md +14 -14
  2. package/dist/commands/check.d.ts +1 -1
  3. package/dist/commands/check.js +4 -3
  4. package/dist/diagnostics/anonymizer.d.ts +1 -1
  5. package/dist/diagnostics/anonymizer.js +1 -1
  6. package/dist/diagnostics/channels.d.ts +1 -1
  7. package/dist/diagnostics/channels.js +1 -1
  8. package/dist/diagnostics/collector.d.ts +1 -1
  9. package/dist/diagnostics/collector.js +1 -1
  10. package/dist/diagnostics/index.d.ts +1 -1
  11. package/dist/diagnostics/index.js +1 -1
  12. package/dist/hooks/quick-retrieve.js +2 -1
  13. package/dist/index.js +0 -0
  14. package/dist/schemas/active-sessions.d.ts +9 -9
  15. package/dist/schemas/active-sessions.js +1 -1
  16. package/dist/schemas/common.d.ts +2 -5
  17. package/dist/schemas/common.js +13 -7
  18. package/dist/schemas/create-learning.js +1 -1
  19. package/dist/schemas/session-close.d.ts +5 -8
  20. package/dist/schemas/session-close.js +7 -3
  21. package/dist/schemas/session-start.d.ts +4 -4
  22. package/dist/schemas/session-start.js +1 -1
  23. package/dist/schemas/thread.d.ts +1 -1
  24. package/dist/schemas/thread.js +1 -1
  25. package/dist/server.d.ts +2 -2
  26. package/dist/server.js +21 -10
  27. package/dist/services/active-sessions.js +3 -2
  28. package/dist/services/agent-briefing.d.ts +1 -1
  29. package/dist/services/agent-briefing.js +1 -1
  30. package/dist/services/agent-detection.d.ts +1 -0
  31. package/dist/services/agent-detection.js +21 -12
  32. package/dist/services/analytics.d.ts +1 -1
  33. package/dist/services/analytics.js +3 -3
  34. package/dist/services/behavioral-decay.js +2 -2
  35. package/dist/services/cache.d.ts +1 -1
  36. package/dist/services/cache.js +1 -1
  37. package/dist/services/compliance-validator.d.ts +1 -1
  38. package/dist/services/compliance-validator.js +5 -5
  39. package/dist/services/config.d.ts +1 -1
  40. package/dist/services/config.js +1 -1
  41. package/dist/services/file-lock.js +12 -0
  42. package/dist/services/gitmem-dir.d.ts +17 -4
  43. package/dist/services/gitmem-dir.js +43 -9
  44. package/dist/services/local-file-storage.d.ts +1 -1
  45. package/dist/services/local-file-storage.js +4 -3
  46. package/dist/services/local-vector-search.d.ts +1 -1
  47. package/dist/services/local-vector-search.js +2 -2
  48. package/dist/services/metrics.d.ts +6 -6
  49. package/dist/services/metrics.js +8 -8
  50. package/dist/services/session-state.d.ts +7 -7
  51. package/dist/services/session-state.js +19 -7
  52. package/dist/services/startup.d.ts +1 -1
  53. package/dist/services/startup.js +3 -2
  54. package/dist/services/supabase-client.d.ts +17 -6
  55. package/dist/services/supabase-client.js +44 -8
  56. package/dist/services/thread-manager.d.ts +1 -1
  57. package/dist/services/thread-manager.js +5 -5
  58. package/dist/services/thread-supabase.d.ts +1 -1
  59. package/dist/services/thread-supabase.js +2 -2
  60. package/dist/services/transcript-chunker.d.ts +1 -1
  61. package/dist/services/transcript-chunker.js +1 -1
  62. package/dist/services/variant-assignment.d.ts +6 -6
  63. package/dist/services/variant-assignment.js +9 -8
  64. package/dist/tools/analyze.d.ts +2 -2
  65. package/dist/tools/analyze.js +2 -2
  66. package/dist/tools/archive-learning.js +36 -22
  67. package/dist/tools/confirm-scars.js +1 -1
  68. package/dist/tools/create-decision.d.ts +1 -1
  69. package/dist/tools/create-decision.js +2 -2
  70. package/dist/tools/create-learning.d.ts +1 -1
  71. package/dist/tools/create-learning.js +4 -4
  72. package/dist/tools/create-linear-issue.d.ts +18 -0
  73. package/dist/tools/create-linear-issue.js +197 -0
  74. package/dist/tools/create-thread.d.ts +1 -1
  75. package/dist/tools/create-thread.js +2 -2
  76. package/dist/tools/definitions.js +50 -48
  77. package/dist/tools/get-transcript.d.ts +1 -1
  78. package/dist/tools/get-transcript.js +1 -1
  79. package/dist/tools/graph-traverse.d.ts +1 -1
  80. package/dist/tools/graph-traverse.js +18 -16
  81. package/dist/tools/list-threads.d.ts +2 -2
  82. package/dist/tools/list-threads.js +4 -4
  83. package/dist/tools/log.d.ts +1 -1
  84. package/dist/tools/log.js +1 -1
  85. package/dist/tools/prepare-context.d.ts +1 -1
  86. package/dist/tools/prepare-context.js +1 -1
  87. package/dist/tools/recall.d.ts +4 -4
  88. package/dist/tools/recall.js +25 -25
  89. package/dist/tools/record-scar-usage-batch.js +2 -2
  90. package/dist/tools/record-scar-usage.d.ts +1 -1
  91. package/dist/tools/record-scar-usage.js +3 -3
  92. package/dist/tools/resolve-thread.d.ts +2 -2
  93. package/dist/tools/resolve-thread.js +3 -3
  94. package/dist/tools/save-transcript.d.ts +1 -1
  95. package/dist/tools/save-transcript.js +1 -1
  96. package/dist/tools/search.d.ts +1 -1
  97. package/dist/tools/search.js +1 -1
  98. package/dist/tools/session-close.d.ts +1 -1
  99. package/dist/tools/session-close.js +31 -31
  100. package/dist/tools/session-start.d.ts +5 -5
  101. package/dist/tools/session-start.js +63 -61
  102. package/dist/types/index.d.ts +13 -13
  103. package/hooks/.claude-plugin/plugin.json +1 -1
  104. package/hooks/scripts/post-tool-use.sh +1 -1
  105. package/hooks/scripts/recall-check.sh +1 -1
  106. package/hooks/scripts/session-close-check.sh +1 -1
  107. package/hooks/scripts/session-start.sh +1 -1
  108. package/package.json +6 -3
  109. package/dist/commands/check.d.ts.map +0 -1
  110. package/dist/commands/check.js.map +0 -1
  111. package/dist/constants/closing-questions.d.ts.map +0 -1
  112. package/dist/constants/closing-questions.js.map +0 -1
  113. package/dist/diagnostics/anonymizer.d.ts.map +0 -1
  114. package/dist/diagnostics/anonymizer.js.map +0 -1
  115. package/dist/diagnostics/channels.d.ts.map +0 -1
  116. package/dist/diagnostics/channels.js.map +0 -1
  117. package/dist/diagnostics/collector.d.ts.map +0 -1
  118. package/dist/diagnostics/collector.js.map +0 -1
  119. package/dist/diagnostics/index.d.ts.map +0 -1
  120. package/dist/diagnostics/index.js.map +0 -1
  121. package/dist/hooks/format-utils.d.ts.map +0 -1
  122. package/dist/hooks/format-utils.js.map +0 -1
  123. package/dist/hooks/quick-retrieve.d.ts.map +0 -1
  124. package/dist/hooks/quick-retrieve.js.map +0 -1
  125. package/dist/index.d.ts.map +0 -1
  126. package/dist/index.js.map +0 -1
  127. package/dist/schemas/absorb-observations.d.ts.map +0 -1
  128. package/dist/schemas/absorb-observations.js.map +0 -1
  129. package/dist/schemas/active-sessions.d.ts.map +0 -1
  130. package/dist/schemas/active-sessions.js.map +0 -1
  131. package/dist/schemas/analyze.d.ts.map +0 -1
  132. package/dist/schemas/analyze.js.map +0 -1
  133. package/dist/schemas/common.d.ts.map +0 -1
  134. package/dist/schemas/common.js.map +0 -1
  135. package/dist/schemas/create-decision.d.ts.map +0 -1
  136. package/dist/schemas/create-decision.js.map +0 -1
  137. package/dist/schemas/create-learning.d.ts.map +0 -1
  138. package/dist/schemas/create-learning.js.map +0 -1
  139. package/dist/schemas/get-transcript.d.ts.map +0 -1
  140. package/dist/schemas/get-transcript.js.map +0 -1
  141. package/dist/schemas/index.d.ts.map +0 -1
  142. package/dist/schemas/index.js.map +0 -1
  143. package/dist/schemas/log.d.ts.map +0 -1
  144. package/dist/schemas/log.js.map +0 -1
  145. package/dist/schemas/prepare-context.d.ts.map +0 -1
  146. package/dist/schemas/prepare-context.js.map +0 -1
  147. package/dist/schemas/recall.d.ts.map +0 -1
  148. package/dist/schemas/recall.js.map +0 -1
  149. package/dist/schemas/record-scar-usage-batch.d.ts.map +0 -1
  150. package/dist/schemas/record-scar-usage-batch.js.map +0 -1
  151. package/dist/schemas/record-scar-usage.d.ts.map +0 -1
  152. package/dist/schemas/record-scar-usage.js.map +0 -1
  153. package/dist/schemas/registry.d.ts.map +0 -1
  154. package/dist/schemas/registry.js.map +0 -1
  155. package/dist/schemas/save-transcript.d.ts.map +0 -1
  156. package/dist/schemas/save-transcript.js.map +0 -1
  157. package/dist/schemas/search-transcripts.d.ts.map +0 -1
  158. package/dist/schemas/search-transcripts.js.map +0 -1
  159. package/dist/schemas/search.d.ts.map +0 -1
  160. package/dist/schemas/search.js.map +0 -1
  161. package/dist/schemas/session-close.d.ts.map +0 -1
  162. package/dist/schemas/session-close.js.map +0 -1
  163. package/dist/schemas/session-start.d.ts.map +0 -1
  164. package/dist/schemas/session-start.js.map +0 -1
  165. package/dist/schemas/thread.d.ts.map +0 -1
  166. package/dist/schemas/thread.js.map +0 -1
  167. package/dist/server.d.ts.map +0 -1
  168. package/dist/server.js.map +0 -1
  169. package/dist/services/active-sessions.d.ts.map +0 -1
  170. package/dist/services/active-sessions.js.map +0 -1
  171. package/dist/services/agent-briefing.d.ts.map +0 -1
  172. package/dist/services/agent-briefing.js.map +0 -1
  173. package/dist/services/agent-detection.d.ts.map +0 -1
  174. package/dist/services/agent-detection.js.map +0 -1
  175. package/dist/services/analytics.d.ts.map +0 -1
  176. package/dist/services/analytics.js.map +0 -1
  177. package/dist/services/behavioral-decay.d.ts.map +0 -1
  178. package/dist/services/behavioral-decay.js.map +0 -1
  179. package/dist/services/bm25.d.ts.map +0 -1
  180. package/dist/services/bm25.js.map +0 -1
  181. package/dist/services/cache.d.ts.map +0 -1
  182. package/dist/services/cache.js.map +0 -1
  183. package/dist/services/cache.test.d.ts +0 -8
  184. package/dist/services/cache.test.d.ts.map +0 -1
  185. package/dist/services/cache.test.js +0 -267
  186. package/dist/services/cache.test.js.map +0 -1
  187. package/dist/services/compliance-validator.d.ts.map +0 -1
  188. package/dist/services/compliance-validator.js.map +0 -1
  189. package/dist/services/config.d.ts.map +0 -1
  190. package/dist/services/config.js.map +0 -1
  191. package/dist/services/display-protocol.d.ts.map +0 -1
  192. package/dist/services/display-protocol.js.map +0 -1
  193. package/dist/services/effect-tracker.d.ts.map +0 -1
  194. package/dist/services/effect-tracker.js.map +0 -1
  195. package/dist/services/embedding.d.ts.map +0 -1
  196. package/dist/services/embedding.js.map +0 -1
  197. package/dist/services/file-lock.d.ts.map +0 -1
  198. package/dist/services/file-lock.js.map +0 -1
  199. package/dist/services/gitmem-dir.d.ts.map +0 -1
  200. package/dist/services/gitmem-dir.js.map +0 -1
  201. package/dist/services/local-file-storage.d.ts.map +0 -1
  202. package/dist/services/local-file-storage.js.map +0 -1
  203. package/dist/services/local-vector-search.d.ts.map +0 -1
  204. package/dist/services/local-vector-search.js.map +0 -1
  205. package/dist/services/metrics.d.ts.map +0 -1
  206. package/dist/services/metrics.js.map +0 -1
  207. package/dist/services/session-state.d.ts.map +0 -1
  208. package/dist/services/session-state.js.map +0 -1
  209. package/dist/services/startup.d.ts.map +0 -1
  210. package/dist/services/startup.js.map +0 -1
  211. package/dist/services/storage.d.ts.map +0 -1
  212. package/dist/services/storage.js.map +0 -1
  213. package/dist/services/supabase-client.d.ts.map +0 -1
  214. package/dist/services/supabase-client.js.map +0 -1
  215. package/dist/services/thread-dedup.d.ts.map +0 -1
  216. package/dist/services/thread-dedup.js.map +0 -1
  217. package/dist/services/thread-manager.d.ts.map +0 -1
  218. package/dist/services/thread-manager.js.map +0 -1
  219. package/dist/services/thread-suggestions.d.ts.map +0 -1
  220. package/dist/services/thread-suggestions.js.map +0 -1
  221. package/dist/services/thread-supabase.d.ts.map +0 -1
  222. package/dist/services/thread-supabase.js.map +0 -1
  223. package/dist/services/thread-vitality.d.ts.map +0 -1
  224. package/dist/services/thread-vitality.js.map +0 -1
  225. package/dist/services/tier.d.ts.map +0 -1
  226. package/dist/services/tier.js.map +0 -1
  227. package/dist/services/timezone.d.ts.map +0 -1
  228. package/dist/services/timezone.js.map +0 -1
  229. package/dist/services/transcript-chunker.d.ts.map +0 -1
  230. package/dist/services/transcript-chunker.js.map +0 -1
  231. package/dist/services/triple-writer.d.ts.map +0 -1
  232. package/dist/services/triple-writer.js.map +0 -1
  233. package/dist/services/variant-assignment.d.ts.map +0 -1
  234. package/dist/services/variant-assignment.js.map +0 -1
  235. package/dist/services/variant-generation.d.ts.map +0 -1
  236. package/dist/services/variant-generation.js.map +0 -1
  237. package/dist/tools/absorb-observations.d.ts.map +0 -1
  238. package/dist/tools/absorb-observations.js.map +0 -1
  239. package/dist/tools/analyze.d.ts.map +0 -1
  240. package/dist/tools/analyze.js.map +0 -1
  241. package/dist/tools/archive-learning.d.ts.map +0 -1
  242. package/dist/tools/archive-learning.js.map +0 -1
  243. package/dist/tools/cleanup-threads.d.ts.map +0 -1
  244. package/dist/tools/cleanup-threads.js.map +0 -1
  245. package/dist/tools/confirm-scars.d.ts.map +0 -1
  246. package/dist/tools/confirm-scars.js.map +0 -1
  247. package/dist/tools/create-decision.d.ts.map +0 -1
  248. package/dist/tools/create-decision.js.map +0 -1
  249. package/dist/tools/create-learning.d.ts.map +0 -1
  250. package/dist/tools/create-learning.js.map +0 -1
  251. package/dist/tools/create-thread.d.ts.map +0 -1
  252. package/dist/tools/create-thread.js.map +0 -1
  253. package/dist/tools/definitions.d.ts.map +0 -1
  254. package/dist/tools/definitions.js.map +0 -1
  255. package/dist/tools/dismiss-suggestion.d.ts.map +0 -1
  256. package/dist/tools/dismiss-suggestion.js.map +0 -1
  257. package/dist/tools/get-transcript.d.ts.map +0 -1
  258. package/dist/tools/get-transcript.js.map +0 -1
  259. package/dist/tools/graph-traverse.d.ts.map +0 -1
  260. package/dist/tools/graph-traverse.js.map +0 -1
  261. package/dist/tools/list-threads.d.ts.map +0 -1
  262. package/dist/tools/list-threads.js.map +0 -1
  263. package/dist/tools/log.d.ts.map +0 -1
  264. package/dist/tools/log.js.map +0 -1
  265. package/dist/tools/prepare-context.d.ts.map +0 -1
  266. package/dist/tools/prepare-context.js.map +0 -1
  267. package/dist/tools/promote-suggestion.d.ts.map +0 -1
  268. package/dist/tools/promote-suggestion.js.map +0 -1
  269. package/dist/tools/recall.d.ts.map +0 -1
  270. package/dist/tools/recall.js.map +0 -1
  271. package/dist/tools/recall.test.d.ts +0 -5
  272. package/dist/tools/recall.test.d.ts.map +0 -1
  273. package/dist/tools/recall.test.js +0 -155
  274. package/dist/tools/recall.test.js.map +0 -1
  275. package/dist/tools/record-scar-usage-batch.d.ts.map +0 -1
  276. package/dist/tools/record-scar-usage-batch.js.map +0 -1
  277. package/dist/tools/record-scar-usage.d.ts.map +0 -1
  278. package/dist/tools/record-scar-usage.js.map +0 -1
  279. package/dist/tools/resolve-thread.d.ts.map +0 -1
  280. package/dist/tools/resolve-thread.js.map +0 -1
  281. package/dist/tools/save-transcript.d.ts.map +0 -1
  282. package/dist/tools/save-transcript.js.map +0 -1
  283. package/dist/tools/search-transcripts.d.ts.map +0 -1
  284. package/dist/tools/search-transcripts.js.map +0 -1
  285. package/dist/tools/search.d.ts.map +0 -1
  286. package/dist/tools/search.js.map +0 -1
  287. package/dist/tools/session-close.d.ts.map +0 -1
  288. package/dist/tools/session-close.js.map +0 -1
  289. package/dist/tools/session-start.d.ts.map +0 -1
  290. package/dist/tools/session-start.js.map +0 -1
  291. package/dist/types/index.d.ts.map +0 -1
  292. package/dist/types/index.js.map +0 -1
  293. package/hooks/tests/test-hooks.sh +0 -577
@@ -1,577 +0,0 @@
1
- #!/bin/bash
2
- # ============================================================================
3
- # gitmem-hooks — Integration Tests
4
- # Tests all four hook scripts against real scenarios
5
- #
6
- # Updated for Phase 1 multi-session registry format (GIT-19):
7
- # - active-sessions.json (plural) with {"sessions": [...]} array
8
- # - Per-session data at .gitmem/sessions/{session_id}/session.json
9
- # ============================================================================
10
-
11
- set -e
12
-
13
- SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
14
- PASS=0
15
- FAIL=0
16
- TOTAL=0
17
-
18
- # Colors
19
- GREEN='\033[0;32m'
20
- RED='\033[0;31m'
21
- YELLOW='\033[1;33m'
22
- NC='\033[0m'
23
-
24
- pass() {
25
- PASS=$((PASS + 1))
26
- TOTAL=$((TOTAL + 1))
27
- echo -e " ${GREEN}PASS${NC}: $1"
28
- }
29
-
30
- fail() {
31
- FAIL=$((FAIL + 1))
32
- TOTAL=$((TOTAL + 1))
33
- echo -e " ${RED}FAIL${NC}: $1"
34
- echo -e " Expected: $2"
35
- echo -e " Got: $3"
36
- }
37
-
38
- # ============================================================================
39
- # Setup: create a temp workspace that simulates the project directory
40
- # ============================================================================
41
-
42
- TMPDIR=$(mktemp -d)
43
- trap "rm -rf $TMPDIR" EXIT
44
-
45
- cd "$TMPDIR"
46
-
47
- # ============================================================================
48
- # Helpers: multi-session registry format (Phase 1, GIT-19)
49
- # ============================================================================
50
-
51
- # Create multi-session registry (replaces old active-session.json singular)
52
- create_session_registry() {
53
- local sid="${1:-test-session}"
54
- mkdir -p "$TMPDIR/.gitmem"
55
- echo "{\"sessions\":[{\"session_id\":\"$sid\"}]}" > "$TMPDIR/.gitmem/active-sessions.json"
56
- }
57
-
58
- # Remove session registry and per-session data
59
- remove_session_registry() {
60
- rm -f "$TMPDIR/.gitmem/active-sessions.json"
61
- rm -rf "$TMPDIR/.gitmem/sessions"
62
- }
63
-
64
- # Create per-session data file (needed by recall-check.sh for scar/confirmation checks)
65
- create_session_data() {
66
- local sid="${1:-test-session}"
67
- local surfaced_scars="${2:-[]}"
68
- local confirmations="${3:-[]}"
69
- mkdir -p "$TMPDIR/.gitmem/sessions/$sid"
70
- echo "{\"surfaced_scars\":$surfaced_scars,\"confirmations\":$confirmations}" > "$TMPDIR/.gitmem/sessions/$sid/session.json"
71
- }
72
-
73
- # Helper: check if gitmem binary exists on disk (affects detection tests)
74
- gitmem_binary_on_disk() {
75
- for p in "/workspace/gitmem/dist/index.js"; do
76
- [ -f "$p" ] && return 0
77
- done
78
- command -v gitmem &>/dev/null && return 0
79
- return 1
80
- }
81
-
82
- # Helper: set up state dir with known values
83
- setup_state() {
84
- local tool_count="${1:-0}"
85
- local start_offset="${2:-0}" # seconds ago
86
-
87
- rm -rf /tmp/gitmem-hooks-*
88
- export CLAUDE_SESSION_ID="test-$$"
89
- local STATE_DIR="/tmp/gitmem-hooks-test-$$"
90
- mkdir -p "$STATE_DIR"
91
- echo "$tool_count" > "$STATE_DIR/tool_call_count"
92
- echo $(($(date +%s) - start_offset)) > "$STATE_DIR/start_time"
93
- rm -f "$STATE_DIR/stop_hook_active"
94
- }
95
-
96
- # ============================================================================
97
- # TEST GROUP 1: session-start.sh
98
- # ============================================================================
99
-
100
- echo ""
101
- echo -e "${YELLOW}=== SessionStart Hook ===${NC}"
102
-
103
- # Test 1.1: Gitmem detected in .mcp.json
104
- echo '{"mcpServers":{"gitmem":{"command":"node","args":["/path/to/gitmem"]}}}' > "$TMPDIR/.mcp.json"
105
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-start.sh" 2>/dev/null)
106
-
107
- if echo "$OUTPUT" | grep -q "SESSION START"; then
108
- pass "Gitmem detected → outputs session start instruction"
109
- else
110
- fail "Gitmem detected → outputs session start instruction" \
111
- "Contains 'SESSION START'" \
112
- "$OUTPUT"
113
- fi
114
-
115
- # Test 1.2: Output is plain text, not JSON
116
- if echo "$OUTPUT" | grep -q "additionalContext"; then
117
- fail "Output is plain text, not JSON" \
118
- "No JSON additionalContext" \
119
- "Found 'additionalContext' in output"
120
- else
121
- pass "Output is plain text, not JSON"
122
- fi
123
-
124
- # Test 1.3: Gitmem NOT in .mcp.json (may still detect via disk fallback)
125
- rm "$TMPDIR/.mcp.json"
126
- echo '{"mcpServers":{"other-tool":{}}}' > "$TMPDIR/.mcp.json"
127
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-start.sh" 2>/dev/null)
128
-
129
- if gitmem_binary_on_disk; then
130
- # Gitmem binary exists on disk — detection cascade finds it even without .mcp.json
131
- if echo "$OUTPUT" | grep -q "SESSION START"; then
132
- pass "Gitmem not in .mcp.json but found on disk → still detected (correct cascade)"
133
- else
134
- fail "Gitmem not in .mcp.json but found on disk → still detected" \
135
- "Contains 'SESSION START' (disk fallback)" \
136
- "$OUTPUT"
137
- fi
138
- else
139
- if echo "$OUTPUT" | grep -q "not detected"; then
140
- pass "Gitmem not in .mcp.json, no binary → outputs 'not detected' message"
141
- else
142
- fail "Gitmem not in .mcp.json, no binary → outputs 'not detected'" \
143
- "Contains 'not detected'" \
144
- "$OUTPUT"
145
- fi
146
- fi
147
-
148
- # Test 1.4: No .mcp.json at all (may still detect via disk fallback)
149
- rm "$TMPDIR/.mcp.json"
150
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-start.sh" 2>/dev/null)
151
-
152
- if gitmem_binary_on_disk; then
153
- if echo "$OUTPUT" | grep -q "SESSION START"; then
154
- pass "No .mcp.json but gitmem on disk → still detected (correct cascade)"
155
- else
156
- fail "No .mcp.json but gitmem on disk → still detected" \
157
- "Contains 'SESSION START' (disk fallback)" \
158
- "$OUTPUT"
159
- fi
160
- else
161
- if echo "$OUTPUT" | grep -q "not detected"; then
162
- pass "No .mcp.json file, no binary → outputs 'not detected' message"
163
- else
164
- fail "No .mcp.json file, no binary → outputs 'not detected'" \
165
- "Contains 'not detected'" \
166
- "$OUTPUT"
167
- fi
168
- fi
169
-
170
- # Test 1.5: gitmem-mcp alternate name detected
171
- echo '{"mcpServers":{"gitmem-mcp":{"command":"node"}}}' > "$TMPDIR/.mcp.json"
172
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-start.sh" 2>/dev/null)
173
-
174
- if echo "$OUTPUT" | grep -q "SESSION START"; then
175
- pass "gitmem-mcp alternate name → detected"
176
- else
177
- fail "gitmem-mcp alternate name → detected" \
178
- "Contains 'SESSION START'" \
179
- "$OUTPUT"
180
- fi
181
-
182
- # Test 1.6: Creates state directory
183
- if [ -d "/tmp/gitmem-hooks-$$" ] || ls /tmp/gitmem-hooks-* &>/dev/null; then
184
- pass "Creates /tmp/gitmem-hooks-{session} state directory"
185
- else
186
- fail "Creates /tmp/gitmem-hooks-{session} state directory" \
187
- "Directory exists" \
188
- "Not found"
189
- fi
190
-
191
- # Clean up state dirs created by tests
192
- rm -rf /tmp/gitmem-hooks-*
193
-
194
- # ============================================================================
195
- # TEST GROUP 2: session-close-check.sh (Stop hook)
196
- # ============================================================================
197
-
198
- echo ""
199
- echo -e "${YELLOW}=== Stop Hook (Session Close Check) ===${NC}"
200
-
201
- # Test 2.1: No session, no work → allows stop
202
- setup_state 0 0
203
- remove_session_registry
204
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
205
- EXIT_CODE=$?
206
-
207
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
208
- pass "No session, no work → allows stop (exit 0, no block)"
209
- else
210
- fail "No session, no work → allows stop" \
211
- "exit 0, no block output" \
212
- "exit=$EXIT_CODE, output=$OUTPUT"
213
- fi
214
-
215
- # Test 2.2: THE BUG FIX — session_start called, <5 calls, <5 min → allows stop
216
- setup_state 2 60 # 2 tool calls, 60 seconds ago
217
- create_session_registry "test-session"
218
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
219
- EXIT_CODE=$?
220
-
221
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
222
- pass "session_start + <5 calls + <5 min → allows stop (BUG FIX)"
223
- else
224
- fail "session_start + <5 calls + <5 min → allows stop (BUG FIX)" \
225
- "exit 0, no block" \
226
- "exit=$EXIT_CODE, output=$OUTPUT"
227
- fi
228
-
229
- # Test 2.3: session_start called, >5 tool calls → blocks
230
- setup_state 10 60 # 10 tool calls, 60 seconds ago
231
- create_session_registry "test-session"
232
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
233
-
234
- if echo "$OUTPUT" | grep -q "block"; then
235
- pass "session_start + >5 calls → blocks (requires session_close)"
236
- else
237
- fail "session_start + >5 calls → blocks" \
238
- "Output contains 'block'" \
239
- "$OUTPUT"
240
- fi
241
-
242
- # Test 2.4: session_start called, >5 min → blocks
243
- setup_state 2 600 # 2 tool calls, 600 seconds (10 min) ago
244
- create_session_registry "test-session"
245
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
246
-
247
- if echo "$OUTPUT" | grep -q "block"; then
248
- pass "session_start + >5 min → blocks (requires session_close)"
249
- else
250
- fail "session_start + >5 min → blocks" \
251
- "Output contains 'block'" \
252
- "$OUTPUT"
253
- fi
254
-
255
- # Test 2.5: Session properly closed (registry empty) → allows stop
256
- setup_state 10 600 # meaningful work
257
- remove_session_registry
258
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
259
- EXIT_CODE=$?
260
-
261
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
262
- pass "Session closed (registry removed) → allows stop"
263
- else
264
- fail "Session closed → allows stop" \
265
- "exit 0, no block" \
266
- "exit=$EXIT_CODE, output=$OUTPUT"
267
- fi
268
-
269
- # Test 2.6: Infinite loop guard — second stop attempt passes through
270
- setup_state 10 60
271
- create_session_registry "test-session"
272
- # First stop — should block
273
- echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null > /dev/null
274
- # Second stop — should pass through (guard active)
275
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
276
- EXIT_CODE=$?
277
-
278
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
279
- pass "Infinite loop guard → second stop always passes"
280
- else
281
- fail "Infinite loop guard → second stop passes" \
282
- "exit 0, no block on second attempt" \
283
- "exit=$EXIT_CODE, output=$OUTPUT"
284
- fi
285
-
286
- # Test 2.7: No state dir at all, no session → allows stop
287
- rm -rf /tmp/gitmem-hooks-*
288
- remove_session_registry
289
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
290
- EXIT_CODE=$?
291
-
292
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
293
- pass "No state dir, no session → allows stop"
294
- else
295
- fail "No state dir → allows stop" \
296
- "exit 0, no block" \
297
- "exit=$EXIT_CODE, output=$OUTPUT"
298
- fi
299
-
300
- # Test 2.8: >5 calls but NO session_start → should NOT block
301
- # (meaningful by tool count but no session to close)
302
- setup_state 10 60
303
- remove_session_registry
304
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
305
- EXIT_CODE=$?
306
-
307
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
308
- pass ">5 calls but no session_start → allows stop (nothing to close)"
309
- else
310
- fail ">5 calls but no session_start → allows stop" \
311
- "exit 0, no block" \
312
- "exit=$EXIT_CODE, output=$OUTPUT"
313
- fi
314
-
315
- # Test 2.9: THE REAL BUG — No state dir + active session registry → allows stop
316
- # (Plugin SessionStart hook didn't fire, user called session_start manually,
317
- # but no tracking data exists. Must NOT block with bogus duration calculation.)
318
- rm -rf /tmp/gitmem-hooks-*
319
- create_session_registry "test-session"
320
- OUTPUT=$(echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null)
321
- EXIT_CODE=$?
322
-
323
- if [ $EXIT_CODE -eq 0 ] && ! echo "$OUTPUT" | grep -q "block"; then
324
- pass "No state dir + active session → allows stop (no tracking data)"
325
- else
326
- fail "No state dir + active session → allows stop" \
327
- "exit 0, no block (graceful degradation)" \
328
- "exit=$EXIT_CODE, output=$OUTPUT"
329
- fi
330
-
331
- # Test 2.10: No state dir + active session → creates state dir for next time
332
- rm -rf /tmp/gitmem-hooks-*
333
- create_session_registry "test-session"
334
- echo '{}' | bash "$SCRIPT_DIR/scripts/session-close-check.sh" 2>/dev/null > /dev/null
335
- if [ -d "/tmp/gitmem-hooks-test-$$" ] && [ -f "/tmp/gitmem-hooks-test-$$/start_time" ]; then
336
- pass "No state dir + session → creates state dir for future tracking"
337
- else
338
- fail "No state dir + session → creates state dir" \
339
- "State dir exists with start_time" \
340
- "Dir or file missing"
341
- fi
342
-
343
- # ============================================================================
344
- # TEST GROUP 3: recall-check.sh (PreToolUse hook)
345
- # ============================================================================
346
-
347
- echo ""
348
- echo -e "${YELLOW}=== PreToolUse Hook (Recall Check) ===${NC}"
349
-
350
- # Test 3.1: No active session → passes silently
351
- remove_session_registry
352
- OUTPUT=$(echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
353
- bash "$SCRIPT_DIR/scripts/recall-check.sh" 2>/dev/null)
354
- EXIT_CODE=$?
355
-
356
- if [ $EXIT_CODE -eq 0 ] && [ -z "$OUTPUT" ]; then
357
- pass "No active session → passes silently"
358
- else
359
- fail "No active session → passes silently" \
360
- "exit 0, empty output" \
361
- "exit=$EXIT_CODE, output='$OUTPUT'"
362
- fi
363
-
364
- # Test 3.2: Non-consequential Bash command → passes silently
365
- setup_state 10 60
366
- create_session_registry "test-session"
367
- create_session_data "test-session" "[]" "[]"
368
- OUTPUT=$(echo '{"tool_name":"Bash","tool_input":{"command":"ls -la"}}' | \
369
- bash "$SCRIPT_DIR/scripts/recall-check.sh" 2>/dev/null)
370
- EXIT_CODE=$?
371
-
372
- if [ $EXIT_CODE -eq 0 ] && [ -z "$OUTPUT" ]; then
373
- pass "Non-consequential Bash (ls) → passes silently"
374
- else
375
- fail "Non-consequential Bash → passes silently" \
376
- "exit 0, empty output" \
377
- "exit=$EXIT_CODE, output='$OUTPUT'"
378
- fi
379
-
380
- # Test 3.3: Consequential Bash (git push) with no recall → nags after >3 calls
381
- setup_state 0 0
382
- create_session_registry "test-session"
383
- create_session_data "test-session" "[]" "[]"
384
-
385
- # Run 4 git push calls to exceed the 3-call threshold
386
- for i in 1 2 3; do
387
- echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
388
- bash "$SCRIPT_DIR/scripts/recall-check.sh" 2>/dev/null > /dev/null
389
- done
390
- # 4th call should trigger nag
391
- OUTPUT=$(echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
392
- bash "$SCRIPT_DIR/scripts/recall-check.sh" 2>/dev/null)
393
-
394
- if echo "$OUTPUT" | grep -q "RECALL REMINDER"; then
395
- pass "Consequential action + no recall + >3 calls → nags"
396
- else
397
- fail "Consequential action + >3 calls → nags" \
398
- "Contains 'RECALL REMINDER'" \
399
- "$OUTPUT"
400
- fi
401
-
402
- # Test 3.4: Write to .sql file → consequential
403
- setup_state 5 0
404
- create_session_registry "test-session"
405
- create_session_data "test-session" "[]" "[]"
406
- OUTPUT=$(echo '{"tool_name":"Write","tool_input":{"file_path":"/path/to/migration.sql"}}' | \
407
- bash "$SCRIPT_DIR/scripts/recall-check.sh" 2>/dev/null)
408
-
409
- if echo "$OUTPUT" | grep -q "RECALL REMINDER"; then
410
- pass "Write .sql file + no recall → nags"
411
- else
412
- fail "Write .sql file → nags" \
413
- "Contains 'RECALL REMINDER'" \
414
- "$OUTPUT"
415
- fi
416
-
417
- # Clean up
418
- rm -rf /tmp/gitmem-hooks-*
419
-
420
- # ============================================================================
421
- # TEST GROUP 4: post-tool-use.sh (PostToolUse hook — audit trail)
422
- # ============================================================================
423
-
424
- echo ""
425
- echo -e "${YELLOW}=== PostToolUse Hook (Audit Trail) ===${NC}"
426
-
427
- # Test 4.1: No active session → passes silently (no audit written)
428
- remove_session_registry
429
- rm -rf /tmp/gitmem-hooks-*
430
- setup_state 0 0
431
- OUTPUT=$(echo '{"tool_name":"mcp__gitmem__recall","tool_input":{"query":"test"}}' | \
432
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null)
433
- EXIT_CODE=$?
434
-
435
- if [ $EXIT_CODE -eq 0 ] && [ -z "$OUTPUT" ] && [ ! -f "/tmp/gitmem-hooks-test-$$/audit.jsonl" ]; then
436
- pass "No active session → no audit written"
437
- else
438
- fail "No active session → no audit written" \
439
- "exit 0, no output, no audit.jsonl" \
440
- "exit=$EXIT_CODE, output='$OUTPUT', audit exists=$([ -f /tmp/gitmem-hooks-test-$$/audit.jsonl ] && echo yes || echo no)"
441
- fi
442
-
443
- # Test 4.2: recall call → LOOKED event logged
444
- setup_state 0 0
445
- create_session_registry "test-session"
446
- OUTPUT=$(echo '{"tool_name":"mcp__gitmem__recall","tool_input":{"query":"deployment verification"}}' | \
447
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null)
448
- EXIT_CODE=$?
449
-
450
- AUDIT_FILE="/tmp/gitmem-hooks-test-$$/audit.jsonl"
451
- if [ $EXIT_CODE -eq 0 ] && [ -f "$AUDIT_FILE" ] && grep -q '"type":"LOOKED"' "$AUDIT_FILE"; then
452
- pass "recall call → LOOKED event in audit.jsonl"
453
- else
454
- fail "recall call → LOOKED event" \
455
- "exit 0, audit.jsonl contains LOOKED" \
456
- "exit=$EXIT_CODE, file=$([ -f $AUDIT_FILE ] && cat $AUDIT_FILE || echo 'missing')"
457
- fi
458
-
459
- # Test 4.3: Consequential Bash (git push) → ACTION event logged
460
- setup_state 0 0
461
- create_session_registry "test-session"
462
- rm -f "/tmp/gitmem-hooks-test-$$/audit.jsonl"
463
- OUTPUT=$(echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
464
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null)
465
-
466
- if [ -f "$AUDIT_FILE" ] && grep -q '"type":"ACTION"' "$AUDIT_FILE" && grep -q 'git push' "$AUDIT_FILE"; then
467
- pass "git push → ACTION event in audit.jsonl"
468
- else
469
- fail "git push → ACTION event" \
470
- "audit.jsonl contains ACTION + git push" \
471
- "$([ -f $AUDIT_FILE ] && cat $AUDIT_FILE || echo 'missing')"
472
- fi
473
-
474
- # Test 4.4: Non-consequential Bash (ls) → no audit entry
475
- setup_state 0 0
476
- create_session_registry "test-session"
477
- rm -f "/tmp/gitmem-hooks-test-$$/audit.jsonl"
478
- OUTPUT=$(echo '{"tool_name":"Bash","tool_input":{"command":"ls -la"}}' | \
479
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null)
480
- EXIT_CODE=$?
481
-
482
- if [ $EXIT_CODE -eq 0 ] && [ ! -f "$AUDIT_FILE" ]; then
483
- pass "Non-consequential Bash (ls) → no audit entry"
484
- else
485
- fail "Non-consequential Bash → no audit" \
486
- "exit 0, no audit.jsonl" \
487
- "exit=$EXIT_CODE, audit=$([ -f $AUDIT_FILE ] && cat $AUDIT_FILE || echo 'missing')"
488
- fi
489
-
490
- # Test 4.5: Write .sql file → ACTION event
491
- setup_state 0 0
492
- create_session_registry "test-session"
493
- rm -f "/tmp/gitmem-hooks-test-$$/audit.jsonl"
494
- OUTPUT=$(echo '{"tool_name":"Write","tool_input":{"file_path":"/path/to/migration.sql"}}' | \
495
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null)
496
-
497
- if [ -f "$AUDIT_FILE" ] && grep -q '"type":"ACTION"' "$AUDIT_FILE" && grep -q 'migration.sql' "$AUDIT_FILE"; then
498
- pass "Write .sql → ACTION event"
499
- else
500
- fail "Write .sql → ACTION event" \
501
- "audit.jsonl contains ACTION + migration.sql" \
502
- "$([ -f $AUDIT_FILE ] && cat $AUDIT_FILE || echo 'missing')"
503
- fi
504
-
505
- # Test 4.9: Write .ts file → no audit entry (non-sensitive)
506
- setup_state 0 0
507
- create_session_registry "test-session"
508
- rm -f "/tmp/gitmem-hooks-test-$$/audit.jsonl"
509
- OUTPUT=$(echo '{"tool_name":"Write","tool_input":{"file_path":"/path/to/component.ts"}}' | \
510
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null)
511
-
512
- if [ ! -f "$AUDIT_FILE" ]; then
513
- pass "Write .ts → no audit entry (non-sensitive)"
514
- else
515
- fail "Write .ts → no audit" \
516
- "no audit.jsonl" \
517
- "$(cat $AUDIT_FILE)"
518
- fi
519
-
520
- # Test 4.10: Multiple events → JSONL appends (multiple lines)
521
- setup_state 0 0
522
- create_session_registry "test-session"
523
- rm -f "/tmp/gitmem-hooks-test-$$/audit.jsonl"
524
- echo '{"tool_name":"mcp__gitmem__recall","tool_input":{"query":"test"}}' | \
525
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null
526
- echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
527
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null
528
- echo '{"tool_name":"mcp__gitmem__search","tool_input":{"query":"hooks"}}' | \
529
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null
530
-
531
- LINE_COUNT=$(wc -l < "$AUDIT_FILE" 2>/dev/null || echo "0")
532
- LOOKED_COUNT=$(grep -c '"type":"LOOKED"' "$AUDIT_FILE" 2>/dev/null || echo "0")
533
- ACTION_COUNT=$(grep -c '"type":"ACTION"' "$AUDIT_FILE" 2>/dev/null || echo "0")
534
-
535
- if [ "$LINE_COUNT" -eq 3 ] && [ "$LOOKED_COUNT" -eq 2 ] && [ "$ACTION_COUNT" -eq 1 ]; then
536
- pass "Multiple events → JSONL appends correctly (2 LOOKED, 1 ACTION)"
537
- else
538
- fail "Multiple events → correct JSONL" \
539
- "3 lines, 2 LOOKED, 1 ACTION" \
540
- "lines=$LINE_COUNT, looked=$LOOKED_COUNT, action=$ACTION_COUNT"
541
- fi
542
-
543
- # Test 4.11: Hook always exits 0 (never blocks)
544
- setup_state 0 0
545
- create_session_registry "test-session"
546
- rm -f "/tmp/gitmem-hooks-test-$$/audit.jsonl"
547
- echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
548
- bash "$SCRIPT_DIR/scripts/post-tool-use.sh" 2>/dev/null
549
- EXIT_CODE=$?
550
-
551
- if [ $EXIT_CODE -eq 0 ]; then
552
- pass "PostToolUse hook always exits 0 (non-blocking)"
553
- else
554
- fail "PostToolUse exits 0" \
555
- "exit 0" \
556
- "exit=$EXIT_CODE"
557
- fi
558
-
559
- # Clean up
560
- rm -rf /tmp/gitmem-hooks-*
561
-
562
- # ============================================================================
563
- # Summary
564
- # ============================================================================
565
-
566
- echo ""
567
- echo -e "${YELLOW}=== Results ===${NC}"
568
- echo -e " Total: $TOTAL | ${GREEN}Pass: $PASS${NC} | ${RED}Fail: $FAIL${NC}"
569
- echo ""
570
-
571
- if [ $FAIL -gt 0 ]; then
572
- echo -e "${RED}SOME TESTS FAILED${NC}"
573
- exit 1
574
- else
575
- echo -e "${GREEN}ALL TESTS PASSED${NC}"
576
- exit 0
577
- fi