claude-memory-layer 1.0.11 → 1.0.12

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 (99) hide show
  1. package/AGENTS.md +60 -0
  2. package/README.md +166 -2
  3. package/bootstrap-kb/decisions/decisions.md +244 -0
  4. package/bootstrap-kb/glossary/glossary.md +46 -0
  5. package/bootstrap-kb/modules/.claude-plugin.md +22 -0
  6. package/bootstrap-kb/modules/agents.md.md +15 -0
  7. package/bootstrap-kb/modules/claude.md.md +15 -0
  8. package/bootstrap-kb/modules/context.md.md +15 -0
  9. package/bootstrap-kb/modules/docs.md +18 -0
  10. package/bootstrap-kb/modules/handoff.md.md +15 -0
  11. package/bootstrap-kb/modules/package-lock.json.md +15 -0
  12. package/bootstrap-kb/modules/package.json.md +15 -0
  13. package/bootstrap-kb/modules/plan.md.md +15 -0
  14. package/bootstrap-kb/modules/readme.md.md +15 -0
  15. package/bootstrap-kb/modules/scripts.md +26 -0
  16. package/bootstrap-kb/modules/spec.md.md +15 -0
  17. package/bootstrap-kb/modules/specs.md +20 -0
  18. package/bootstrap-kb/modules/src.md +51 -0
  19. package/bootstrap-kb/modules/tests.md +42 -0
  20. package/bootstrap-kb/modules/tsconfig.json.md +15 -0
  21. package/bootstrap-kb/modules/vitest.config.ts.md +15 -0
  22. package/bootstrap-kb/overview/overview.md +40 -0
  23. package/bootstrap-kb/sources/manifest.json +950 -0
  24. package/bootstrap-kb/sources/manifest.md +227 -0
  25. package/bootstrap-kb/timeline/timeline.md +57 -0
  26. package/d.sh +3 -0
  27. package/deploy.sh +3 -0
  28. package/dist/cli/index.js +2389 -286
  29. package/dist/cli/index.js.map +4 -4
  30. package/dist/core/index.js +1017 -132
  31. package/dist/core/index.js.map +4 -4
  32. package/dist/hooks/post-tool-use.js +1347 -202
  33. package/dist/hooks/post-tool-use.js.map +4 -4
  34. package/dist/hooks/session-end.js +1339 -194
  35. package/dist/hooks/session-end.js.map +4 -4
  36. package/dist/hooks/session-start.js +1343 -198
  37. package/dist/hooks/session-start.js.map +4 -4
  38. package/dist/hooks/stop.js +1351 -206
  39. package/dist/hooks/stop.js.map +4 -4
  40. package/dist/hooks/user-prompt-submit.js +1347 -202
  41. package/dist/hooks/user-prompt-submit.js.map +4 -4
  42. package/dist/server/api/index.js +1436 -211
  43. package/dist/server/api/index.js.map +4 -4
  44. package/dist/server/index.js +1445 -220
  45. package/dist/server/index.js.map +4 -4
  46. package/dist/services/memory-service.js +1345 -199
  47. package/dist/services/memory-service.js.map +4 -4
  48. package/dist/ui/app.js +69 -2
  49. package/dist/ui/index.html +8 -0
  50. package/docs/MCP_MEMORY_SERVICE_COMPARATIVE_REVIEW.md +271 -0
  51. package/docs/MEMU_ADOPTION.md +40 -0
  52. package/memory/.claude-plugin/commands/2026-02-25.md +263 -0
  53. package/memory/_index.md +405 -0
  54. package/memory/default/uncategorized/2026-02-25.md +4839 -0
  55. package/memory/specs/20260207-dashboard-upgrade/2026-02-25.md +142 -0
  56. package/memory/specs/citations-system/2026-02-25.md +1121 -0
  57. package/memory/specs/endless-mode/2026-02-25.md +1392 -0
  58. package/memory/specs/entity-edge-model/2026-02-25.md +1263 -0
  59. package/memory/specs/evidence-aligner-v2/2026-02-25.md +1028 -0
  60. package/memory/specs/mcp-desktop-integration/2026-02-25.md +1334 -0
  61. package/memory/specs/post-tool-use-hook/2026-02-25.md +1164 -0
  62. package/memory/specs/private-tags/2026-02-25.md +1057 -0
  63. package/memory/specs/progressive-disclosure/2026-02-25.md +1436 -0
  64. package/memory/specs/task-entity-system/2026-02-25.md +924 -0
  65. package/memory/specs/vector-outbox-v2/2026-02-25.md +1510 -0
  66. package/memory/specs/web-viewer-ui/2026-02-25.md +1709 -0
  67. package/package.json +2 -1
  68. package/scripts/build.ts +6 -0
  69. package/src/cli/index.ts +281 -2
  70. package/src/core/consolidated-store.ts +63 -1
  71. package/src/core/consolidation-worker.ts +115 -6
  72. package/src/core/event-store.ts +14 -0
  73. package/src/core/index.ts +1 -0
  74. package/src/core/ingest-interceptor.ts +80 -0
  75. package/src/core/markdown-mirror.ts +70 -0
  76. package/src/core/md-mirror.ts +92 -0
  77. package/src/core/mongo-sync-config.ts +165 -0
  78. package/src/core/mongo-sync-worker.ts +381 -0
  79. package/src/core/retriever.ts +540 -150
  80. package/src/core/sqlite-event-store.ts +350 -1
  81. package/src/core/tag-taxonomy.ts +51 -0
  82. package/src/core/types.ts +28 -0
  83. package/src/server/api/health.ts +53 -0
  84. package/src/server/api/index.ts +3 -1
  85. package/src/server/api/stats.ts +46 -1
  86. package/src/services/bootstrap-organizer.ts +443 -0
  87. package/src/services/codex-session-history-importer.ts +474 -0
  88. package/src/services/memory-service.ts +373 -68
  89. package/src/ui/app.js +69 -2
  90. package/src/ui/index.html +8 -0
  91. package/tests/bootstrap-organizer.test.ts +111 -0
  92. package/tests/consolidation-worker.test.ts +75 -0
  93. package/tests/ingest-interceptor.test.ts +38 -0
  94. package/tests/markdown-mirror.test.ts +85 -0
  95. package/tests/md-mirror.test.ts +50 -0
  96. package/tests/retriever-fallback-chain.test.ts +223 -0
  97. package/tests/retriever-strategy-scope.test.ts +97 -0
  98. package/tests/retriever.memu-adoption.test.ts +122 -0
  99. package/tests/sqlite-event-store-replication.test.ts +92 -0
package/dist/ui/app.js CHANGED
@@ -11,6 +11,7 @@ const state = {
11
11
  sharedStats: null,
12
12
  mostAccessed: null,
13
13
  helpfulness: null,
14
+ retrievalTraces: null,
14
15
  currentLevel: 'L0',
15
16
  currentSort: 'recent',
16
17
  currentView: 'overview',
@@ -235,17 +236,19 @@ async function refreshData() {
235
236
  if(btn) btn.classList.add('loading');
236
237
 
237
238
  try {
238
- const [stats, shared, mostAccessed, helpfulness] = await Promise.all([
239
+ const [stats, shared, mostAccessed, helpfulness, retrievalTraces] = await Promise.all([
239
240
  fetch(apiUrl(`${API_BASE}/stats`)).then(r => r.json()).catch(() => null),
240
241
  fetch(apiUrl(`${API_BASE}/stats/shared`)).then(r => r.json()).catch(() => null),
241
242
  fetch(apiUrl(`${API_BASE}/stats/most-accessed`, { limit: 10 })).then(r => r.json()).catch(() => null),
242
- fetch(apiUrl(`${API_BASE}/stats/helpfulness`, { limit: 5 })).then(r => r.json()).catch(() => null)
243
+ fetch(apiUrl(`${API_BASE}/stats/helpfulness`, { limit: 5 })).then(r => r.json()).catch(() => null),
244
+ fetch(apiUrl(`${API_BASE}/stats/retrieval-traces`, { limit: 20 })).then(r => r.json()).catch(() => null)
243
245
  ]);
244
246
 
245
247
  state.stats = stats;
246
248
  state.sharedStats = shared;
247
249
  state.mostAccessed = mostAccessed;
248
250
  state.helpfulness = helpfulness;
251
+ state.retrievalTraces = retrievalTraces;
249
252
 
250
253
  updateStatsUI();
251
254
  updateSharedUI();
@@ -397,6 +400,7 @@ function updateMemoryUsageUI() {
397
400
  updateGraduationBars();
398
401
  updateHelpfulnessUI();
399
402
  updateMostHelpfulList();
403
+ updateRetrievalTraceUI();
400
404
  }
401
405
 
402
406
  function updateGraduationBars() {
@@ -483,6 +487,69 @@ function updateMostHelpfulList() {
483
487
  }).join('');
484
488
  }
485
489
 
490
+
491
+ function updateRetrievalTraceUI() {
492
+ const summaryEl = document.getElementById('retrieval-trace-summary');
493
+ const listEl = document.getElementById('retrieval-trace-list');
494
+ if (!summaryEl || !listEl) return;
495
+
496
+ const payload = state.retrievalTraces;
497
+ const stats = payload?.stats;
498
+ const traces = payload?.traces || [];
499
+
500
+ if (!stats || !Number.isFinite(stats.totalQueries) || stats.totalQueries === 0) {
501
+ summaryEl.innerHTML = '<span style="color:var(--text-muted);">No retrieval traces yet.</span>';
502
+ listEl.innerHTML = '<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">No query/context trace data</div>';
503
+ return;
504
+ }
505
+
506
+ const selectionRate = ((stats.selectionRate || 0) * 100).toFixed(1);
507
+ summaryEl.innerHTML = `
508
+ <div style="display:flex; gap:14px; flex-wrap:wrap; font-size:12px;">
509
+ <span><strong>${formatNumber(stats.totalQueries)}</strong> queries</span>
510
+ <span><strong>${Number(stats.avgCandidateCount || 0).toFixed(1)}</strong> avg candidates</span>
511
+ <span><strong>${Number(stats.avgSelectedCount || 0).toFixed(1)}</strong> avg selected</span>
512
+ <span><strong>${selectionRate}%</strong> selection rate</span>
513
+ </div>
514
+ `;
515
+
516
+ listEl.innerHTML = traces.slice(0, 8).map((t) => {
517
+ const ts = t.createdAt ? new Date(t.createdAt).toLocaleString() : '-';
518
+ const confidence = t.confidence || 'n/a';
519
+ const selected = Number(t.selectedCount || 0);
520
+ const candidates = Number(t.candidateCount || 0);
521
+ const selectedDetails = (t.selectedDetails || []).slice(0, 2);
522
+ const candidateDetails = (t.candidateDetails || []).slice(0, 3);
523
+ const selectedIdsHtml = selectedDetails.length > 0
524
+ ? selectedDetails.map((d) => {
525
+ const breakdown = `score=${Number(d.score || 0).toFixed(3)} · s=${Number(d.semanticScore || 0).toFixed(3)} · l=${Number(d.lexicalScore || 0).toFixed(3)} · r=${Number(d.recencyScore || 0).toFixed(3)}`;
526
+ return `<span class="event-type-badge" style="cursor:pointer;" onclick="openDetailModal('${d.eventId}')" title="${escapeHtml(breakdown)}">${escapeHtml((d.eventId || '').slice(0, 8))}...</span>`;
527
+ }).join(' ')
528
+ : ((t.selectedEventIds || []).slice(0, 2).map((id) => `<span class="event-type-badge" style="cursor:pointer;" onclick="openDetailModal('${id}')">${escapeHtml((id || '').slice(0, 8))}...</span>`).join(' ') || '-');
529
+
530
+ const scoreBreakdownHtml = selectedDetails.length > 0
531
+ ? selectedDetails.map((d) => `<div style="font-size:10px; color:var(--text-muted);">${escapeHtml((d.eventId || '').slice(0, 8))}... → score ${Number(d.score || 0).toFixed(3)} (s ${Number(d.semanticScore || 0).toFixed(3)}, l ${Number(d.lexicalScore || 0).toFixed(3)}, r ${Number(d.recencyScore || 0).toFixed(3)})</div>`).join('')
532
+ : '';
533
+
534
+ return `
535
+ <div class="shared-item" style="align-items:flex-start;">
536
+ <div class="shared-info" style="align-items:flex-start; flex-direction:column; gap:4px;">
537
+ <span style="font-size:12px; color:var(--text-secondary);"><strong>Q:</strong> ${escapeHtml((t.queryText || '').slice(0, 120))}</span>
538
+ <span style="font-size:11px; color:var(--text-muted);">${ts} · strategy=${escapeHtml(t.strategy || 'auto')} · conf=${escapeHtml(confidence)}</span>
539
+ <span style="font-size:11px; color:var(--text-muted);">selected IDs: ${selectedIdsHtml}</span>
540
+ <span style="font-size:11px; color:var(--text-muted);">candidates: ${candidateDetails.map((d) => `<span class=\"event-type-badge\" style=\"cursor:pointer;\" onclick=\"openDetailModal('${d.eventId}')\">${escapeHtml((d.eventId || '').slice(0, 8))}...</span>`).join(' ') || '-'}</span>
541
+ ${scoreBreakdownHtml}
542
+ </div>
543
+ <div style="display:flex; flex-direction:column; align-items:flex-end; gap:2px; min-width:68px;">
544
+ <span style="font-size:13px; font-weight:600; color:var(--accent-primary);">${selected}/${candidates}</span>
545
+ <span style="font-size:10px; color:var(--text-muted);">sel/cand</span>
546
+ </div>
547
+ </div>
548
+ `;
549
+ }).join('');
550
+ }
551
+
552
+
486
553
  // --- Charts ---
487
554
 
488
555
  async function initActivityChart() {
@@ -271,6 +271,14 @@
271
271
  <div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
272
272
  </div>
273
273
  </div>
274
+
275
+ <div style="margin-top:20px;">
276
+ <div class="section-label">Retrieval Trace (1:1)</div>
277
+ <div id="retrieval-trace-summary" style="padding:8px 0; font-size:13px; color:var(--text-muted);">Loading...</div>
278
+ <div id="retrieval-trace-list" class="shared-list">
279
+ <div style="padding:12px; text-align:center; color:var(--text-muted); font-size:13px;">Loading...</div>
280
+ </div>
281
+ </div>
274
282
  </div>
275
283
 
276
284
  </div>
@@ -0,0 +1,271 @@
1
+ # mcp-memory-service 코드 리뷰 기반 개선 제안서
2
+
3
+ 작성일: 2026-02-26
4
+ 대상:
5
+ - 참고 레포: `~/workspace/mcp-memory-service` (commit `8d7e582`)
6
+ - 개선 대상: `~/workspace/claude-memory-layer`
7
+
8
+ ---
9
+
10
+ ## 0) 결론 요약
11
+
12
+ `claude-memory-layer`는 이미 구조가 매우 좋고(프로젝트 해시 격리, scoped retrieval, outbox, endless mode, shared store 실험), **핵심 기능은 충분히 경쟁력 있음**.
13
+
14
+ 다만 `mcp-memory-service`를 기준으로 봤을 때 실제 운영 관점에서 보강하면 체감이 큰 포인트는 아래 5가지:
15
+
16
+ 1. **멀티-repo 스코프 강제 정책**(기본 격리 + 명시적 cross-repo)
17
+ 2. **태그 taxonomy 표준화**(`proj:`, `agent:`, `topic:`, `q:` 등) + 자동 주입
18
+ 3. **HTTP/SSE API 레이어**(운영/관측/통합성 증가)
19
+ 4. **하이브리드 검색(BM25+Vector) 공식화** 및 점수 퓨전 표준화
20
+ 5. **운영 안정성 레이어**(헬스체크, 백업/복구, 보존정책, 인증)
21
+
22
+ 즉, 지금은 “강한 코어 엔진” 단계고, 다음 단계는 “**운영형 메모리 플랫폼**”으로 가는 게 맞음.
23
+
24
+ ---
25
+
26
+ ## 1) 조사 방식
27
+
28
+ ### 확인한 핵심 파일(참고 레포)
29
+ - `README.md`
30
+ - `docs/architecture.md`
31
+ - `docs/agents/README.md`
32
+ - `docs/mastery/configuration-guide.md`
33
+ - `src/mcp_memory_service/models/tag_taxonomy.py`
34
+ - `src/mcp_memory_service/web/api/memories.py`
35
+ - `src/mcp_memory_service/web/api/search.py`
36
+
37
+ ### 확인한 핵심 파일(현재 레포)
38
+ - `README.md`
39
+ - `package.json`
40
+ - `src/services/memory-service.ts`
41
+ - `src/core/retriever.ts`
42
+ - `src/core/event-store.ts`
43
+ - `docs/OPERATIONS.md`
44
+ - `docs/MEMU_ADOPTION.md`
45
+
46
+ ---
47
+
48
+ ## 2) 현재 `claude-memory-layer` 강점 (유지해야 할 것)
49
+
50
+ 1. **프로젝트 격리 설계가 이미 있음**
51
+ - `hashProjectPath()` + `~/.claude-code/memory/projects/{hash}`
52
+ - 세션 레지스트리로 session→project 매핑
53
+
54
+ 2. **검색 전략 설계가 좋음**
55
+ - `fast/deep/auto`, fallback chain, scope filter, rerank, graph-hop
56
+ - 실전성 높은 토큰/정확도 트레이드오프
57
+
58
+ 3. **쓰기 파이프라인 안정성 의식이 강함**
59
+ - SQLite primary, outbox, background worker
60
+ - hook 경량 모드(lightweightMode)
61
+
62
+ 4. **고급 메모리 기능이 이미 구현/실험됨**
63
+ - graduation, endless mode, shared store, markdown mirror
64
+
65
+ => 요약: 엔진 레벨은 이미 상당히 앞서 있음.
66
+
67
+ ---
68
+
69
+ ## 3) `mcp-memory-service` 대비 갭 분석
70
+
71
+ ### A. 멀티-repo 운영 규칙의 “정책 강제력”
72
+
73
+ - 현 상태: 프로젝트 해시 분리는 있으나, 교차 검색/주입 정책이 코드/문서에서 강하게 표준화되어 있지는 않음
74
+ - 참고 레포 포인트:
75
+ - `agent:` 태그 자동 주입(`X-Agent-ID`)
76
+ - 태그 namespace 체계 명시(`proj:`, `topic:`, `q:` ...)
77
+
78
+ **리스크**
79
+ - 여러 repo를 운용할수록 검색 누수(다른 repo 기억 주입) 가능성 증가
80
+
81
+ **개선안**
82
+ - 기본 policy: `same-project-only`
83
+ - cross-project는 explicit flag + 이유(required reason) 필요
84
+ - retrieval 요청 시 project_id 부재면 hard-fail(옵션)
85
+
86
+ ---
87
+
88
+ ### B. 태그 체계 표준화 부족
89
+
90
+ - 현 상태: metadata/scope가 강하지만 태그 네임스페이스 규약은 상대적으로 약함
91
+ - 참고 레포 포인트:
92
+ - `TagTaxonomy`를 별도 모델로 정의하고 namespace 유효성 관리
93
+
94
+ **개선안**
95
+ - `src/core/tag-taxonomy.ts` 신설
96
+ - 표준 namespace:
97
+ - `proj:` repository identifier
98
+ - `agent:` 실행 주체
99
+ - `topic:` 주제
100
+ - `q:` 품질/신뢰 등급
101
+ - `t:` 시간/스프린트
102
+ - `sys:` 시스템 자동 태그
103
+ - ingest 시 최소 `proj:<hash>` 자동 부착
104
+
105
+ ---
106
+
107
+ ### C. HTTP/SSE 운용 계층 부재(또는 약함)
108
+
109
+ - 현 상태: CLI/hooks 중심 구조가 강점이지만, 외부 오케스트레이터/다중 클라이언트 연동은 제한적
110
+ - 참고 레포 포인트:
111
+ - REST API + SSE + dashboard 연동
112
+
113
+ **개선안**
114
+ - 최소 API부터 시작:
115
+ - `POST /api/memories`
116
+ - `POST /api/memories/search`
117
+ - `GET /api/memories?project=...`
118
+ - `GET /api/health`
119
+ - SSE 이벤트:
120
+ - memory_stored
121
+ - memory_deleted
122
+ - search_completed
123
+
124
+ ---
125
+
126
+ ### D. Hybrid search 점수 체계 공식화 필요
127
+
128
+ - 현 상태: fast/deep + rerank는 이미 훌륭함
129
+ - 부족한 점: “BM25 + Vector + Recency + Quality”를 운영상 조정 가능한 공식으로 고정 문서화한 수준은 약함
130
+ - 참고 레포 포인트:
131
+ - hybrid 검색을 제품 기능으로 명시
132
+
133
+ **개선안**
134
+ - `score = w_semantic*S + w_lexical*L + w_recency*R + w_quality*Q`
135
+ - env/config에서 가중치 조정 가능하게
136
+ - quality 점수 부재 시 graceful fallback
137
+
138
+ ---
139
+
140
+ ### E. 운영/보안 레이어
141
+
142
+ - 현 상태: runbook/ops 스크립트 존재(좋음)
143
+ - 참고 레포 포인트:
144
+ - 인증, 헬스/환경 점검, 상세 config 가이드
145
+
146
+ **개선안**
147
+ - 최소 추가:
148
+ - `MEMORY_API_KEY` 인증(HTTP 도입 시)
149
+ - `/api/health` + 저장소 상태 + outbox backlog 노출
150
+ - 백업/복구 명령 표준화
151
+ - 보존정책(TTL, 중요도 기반 정리) 명문화
152
+
153
+ ---
154
+
155
+ ## 4) 우선순위 로드맵 (실행 순서)
156
+
157
+ ## P0 (당장 효과 큼, 1~3일)
158
+ 1. 멀티-repo 스코프 기본 정책 강제
159
+ 2. `proj:` 자동 태깅
160
+ 3. 검색 기본값 same-project-only
161
+ 4. 교차 검색은 명시적 옵션 필요
162
+
163
+ ## P1 (1~2주)
164
+ 1. tag taxonomy 모듈화
165
+ 2. hybrid scoring 공식화 + 설정화
166
+ 3. health endpoint/metrics 정리
167
+
168
+ ## P2 (2~4주)
169
+ 1. HTTP API + SSE 추가
170
+ 2. 인증(OAuth까지는 아니어도 API key)
171
+ 3. 팀/멀티클라이언트 운영 문서화
172
+
173
+ ---
174
+
175
+ ## 5) 구체 구현 제안 (코드 레벨)
176
+
177
+ ### 5.1 Retrieval 옵션 확장
178
+ `src/core/retriever.ts`에 아래 정책 필드 추가 권장:
179
+
180
+ - `projectScopeMode: 'strict' | 'prefer' | 'global'`
181
+ - `allowedProjectHashes?: string[]`
182
+ - `crossProjectReason?: string`
183
+
184
+ `strict`일 때 현재 프로젝트 hash 불일치 결과는 필터링.
185
+
186
+ ---
187
+
188
+ ### 5.2 자동 태깅 훅
189
+ `MemoryService.storeUserPrompt/storeAgentResponse/storeToolObservation`에서 metadata 병합 시:
190
+
191
+ - `scope.project.hash`
192
+ - `scope.project.path`
193
+ - `tags` 개념을 도입하면 `proj:${projectHash}` 자동 주입
194
+
195
+ ---
196
+
197
+ ### 5.3 정책 파일 도입
198
+ `claude-memory-layer/policies/memory-scope-policy.json` 예:
199
+
200
+ ```json
201
+ {
202
+ "defaultMode": "strict",
203
+ "allowCrossProject": false,
204
+ "requireReasonForCrossProject": true,
205
+ "alwaysIncludeTags": ["sys:auto", "proj:auto"]
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ### 5.4 운영 API 최소셋
212
+ 향후 `src/server`에 라우트 추가:
213
+
214
+ - `GET /api/health`
215
+ - db 연결 상태
216
+ - vector worker backlog
217
+ - failed outbox 개수
218
+ - `POST /api/memories/search`
219
+ - projectHash 필수(운영 모드에서)
220
+
221
+ ---
222
+
223
+ ## 6) 여러 repository 관리 관점 평가
224
+
225
+ 질문의 핵심(“여러 repo 관리 용이?”)에 대해:
226
+
227
+ - `claude-memory-layer` 현재 구조는 **잠재적으로 매우 유리**
228
+ - 프로젝트 해시 분리 구조가 이미 있기 때문
229
+ - 하지만 운영 안정성은 “격리 정책 강제 + 표준 태깅 + API 관측”이 있어야 완성
230
+
231
+ 즉, **아키텍처 방향은 맞고, 운영 레이어 보강이 필요**.
232
+
233
+ ---
234
+
235
+ ## 7) 추천 최종 전략
236
+
237
+ `/Users/namsangboy/workspace/claude-memory-layer`를 계속 중심으로 가져가되:
238
+
239
+ 1. P0/P1 개선 먼저 적용해서 “멀티-repo 안 섞이는 안정성” 확보
240
+ 2. 그 다음 HTTP/SSE/API key 붙여서 외부 자동화/다중 클라이언트 지원
241
+ 3. 마지막에 공유 지식(shared store) 룰을 엄격히(검증된 것만 승격)
242
+
243
+ 이 순서가 리스크/효율 밸런스가 가장 좋음.
244
+
245
+ ---
246
+
247
+ ## 8) 보너스: 바로 체크할 TODO
248
+
249
+ - [x] `projectScopeMode` 옵션 추가
250
+ - [x] 기본 검색 strict project filter 적용
251
+ - [x] `proj:<hash>` 자동 태깅
252
+ - [x] tag taxonomy 모듈 생성
253
+ - [x] health API에 outbox failed/pending 수치 노출 (`GET /api/health`)
254
+ - [ ] 문서에 cross-project 허용 조건 명시
255
+
256
+ ### P1 적용 메모 (이번 반영)
257
+
258
+ - 태그 taxonomy 파일 추가: `src/core/tag-taxonomy.ts`
259
+ - namespace 유효성 검증(`sys:, q:, proj:, topic:, t:, user:, agent:`)
260
+ - tags 정규화(`normalizeTags`)로 ingest 시 품질 보정
261
+ - rerank 가중치 설정화
262
+ - 환경변수 지원:
263
+ - `MEMORY_RERANK_WEIGHT_SEMANTIC`
264
+ - `MEMORY_RERANK_WEIGHT_LEXICAL`
265
+ - `MEMORY_RERANK_WEIGHT_RECENCY`
266
+ - 3개가 모두 유효하면 정규화해서 고정값 사용
267
+ - 없으면 기존 adaptive/기본 동작 fallback
268
+
269
+ ---
270
+
271
+ 원하면 다음 단계로 health endpoint/운영 지표(outbox backlog, failed 카운트)까지 이어서 붙일 수 있음.
@@ -0,0 +1,40 @@
1
+ # memU Adoption Notes (claude-memory-layer)
2
+
3
+ 이 프로젝트에 적용된 memU 장점 요약입니다.
4
+
5
+ ## 1) Dual Retrieval Strategy
6
+ - `strategy: "fast" | "deep" | "auto"`
7
+ - `fast`: 키워드 기반(FTS/keyword) 우선 탐색으로 저지연 검색
8
+ - `deep`: 임베딩 + 벡터 검색 + 재정렬(키워드 오버랩 가중)로 정밀 검색
9
+
10
+ ## 2) Scoped Retrieval Filters
11
+ `scope`로 검색 범위를 좁혀 정확도를 높입니다.
12
+
13
+ - `sessionId` / `sessionIdPrefix`
14
+ - `eventTypes`
15
+ - `canonicalKeyPrefix`
16
+ - `contentIncludes` (부분 문자열 OR)
17
+ - `metadata` (dot-path, 예: `scope.project.id`)
18
+
19
+ ## 3) Hybrid Rerank Behavior
20
+ `rerankWithKeyword=true`일 때 semantic score에 키워드 오버랩/최근성 점수를 가중해 재정렬합니다.
21
+
22
+ ## 4) Test Coverage
23
+ - `tests/retriever.memu-adoption.test.ts`
24
+ - metadata dot-path 스코프 필터
25
+ - fast 전략 키워드 경로
26
+ - `tests/retriever-strategy-scope.test.ts`
27
+ - fast/deep 전략 및 복합 스코프 필터
28
+
29
+ ## Quick Example
30
+ ```ts
31
+ await retriever.retrieve('브리핑', {
32
+ strategy: 'deep',
33
+ topK: 10,
34
+ scope: {
35
+ sessionIdPrefix: 'agent:main:',
36
+ canonicalKeyPrefix: 'pref/briefing',
37
+ metadata: { 'scope.project.id': 'alpha' }
38
+ }
39
+ });
40
+ ```
@@ -0,0 +1,263 @@
1
+
2
+ ## 2026-02-25T12:31:21.733Z | a551b032-ffdd-43e5-8f34-c42b12b091ce
3
+ - type: session_summary
4
+ - session: import:organized
5
+ # /memory-forget
6
+
7
+ Remove specific memories from storage.
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ /memory-forget <event-id>
13
+ /memory-forget --session <session-id>
14
+ /memory-forget --before <date>
15
+ ```
16
+
17
+ ## Arguments
18
+
19
+ - `event-id`: Specific event ID to forget
20
+ - `--session <id>`: Forget all events from a session
21
+ - `--before <date>`: Forget events before a date (YYYY-MM-DD)
22
+ - `--confirm`: Skip confirmation prompt
23
+
24
+ ## Examples
25
+
26
+ ```
27
+ /memory-forget abc123-def456
28
+ /memory-forget --session session_xyz --confirm
29
+ /memory-forget --before 2024-01-01
30
+ ```
31
+
32
+ ## Description
33
+
34
+ Removes memories from storage. This operation:
35
+
36
+ 1. Marks events as deleted in EventStore (soft delete)
37
+ 2. Removes corresponding vectors from LanceDB
38
+ 3. Updates memory level statistics
39
+
40
+ ⚠️ **Note**: Due to the append-only architecture, deleted events are marked but not physically removed from the event log. Vector embeddings are physically deleted.
41
+
42
+ ## Implementation
43
+
44
+ ```bash
45
+ node dist/cli/index.js forget $ARGUMENTS
46
+ ```
47
+
48
+ ## 2026-02-25T12:31:21.738Z | ec065482-7832-4ec6-9fbf-584ca1d05d75
49
+ - type: session_summary
50
+ - session: import:organized
51
+ # /memory-history
52
+
53
+ View conversation history from memory.
54
+
55
+ ## Usage
56
+
57
+ ```
58
+ /memory-history [options]
59
+ ```
60
+
61
+ ## Options
62
+
63
+ - `--session <id>`: Show history for a specific session
64
+ - `--limit <n>`: Limit number of events (default: 20)
65
+ - `--type <type>`: Filter by event type (user_prompt, agent_response, session_summary)
66
+
67
+ ## Examples
68
+
69
+ ```
70
+ /memory-history
71
+ /memory-history --limit 50
72
+ /memory-history --session abc123
73
+ /memory-history --type user_prompt
74
+ ```
75
+
76
+ ## Description
77
+
78
+ Displays stored conversation events from memory. By default shows the most recent events across all sessions. Use filters to narrow down to specific sessions or event types.
79
+
80
+ ## Implementation
81
+
82
+ ```bash
83
+ node dist/cli/index.js history $ARGUMENTS
84
+ ```
85
+
86
+ ## 2026-02-25T12:31:21.740Z | 5be40880-b0f7-4aa3-9844-7190b1fa06cf
87
+ - type: session_summary
88
+ - session: import:organized
89
+ # /memory-import
90
+
91
+ Import existing Claude Code conversation history into memory.
92
+
93
+ ## Usage
94
+
95
+ ```
96
+ /memory-import [options]
97
+ ```
98
+
99
+ ## Options
100
+
101
+ - `--project <path>`: Import from specific project path
102
+ - `--session <file>`: Import a specific session file (JSONL)
103
+ - `--all`: Import all sessions from all projects
104
+ - `--limit <n>`: Limit messages per session
105
+ - `--verbose`: Show detailed progress
106
+
107
+ ## Examples
108
+
109
+ ```
110
+ /memory-import
111
+ /memory-import --project /home/user/myproject
112
+ /memory-import --all
113
+ /memory-import --session ~/.claude/projects/xyz/abc123.jsonl
114
+ /memory-import --all --limit 100 --verbose
115
+ ```
116
+
117
+ ## Description
118
+
119
+ This command imports existing Claude Code conversation history from JSONL session files into the memory store. This allows the plugin to learn from your previous conversations and provide more relevant context in future sessions.
120
+
121
+ ### What gets imported:
122
+
123
+ - **User prompts**: Your questions and requests
124
+ - **Agent responses**: Claude's responses (truncated to 5000 chars)
125
+ - **Session metadata**: Timestamps and session IDs
126
+
127
+ ### Deduplication
128
+
129
+ The importer automatically skips duplicate messages based on content hash, so you can safely run import multiple times without creating duplicate memories.
130
+
131
+ ### Session Files Location
132
+
133
+ Claude Code stores session history in:
134
+ ```
135
+ ~/.claude/projects/<project-hash>/<session-id>.jsonl
136
+ ```
137
+
138
+ Use `/memory-list` to see available sessions before importing.
139
+
140
+ ## Implementation
141
+
142
+ ```bash
143
+ node dist/cli/index.js import $ARGUMENTS
144
+ ```
145
+
146
+ ## 2026-02-25T12:31:21.743Z | 3d6ec7cb-b61d-4638-b767-a2d6a1e1b7bd
147
+ - type: session_summary
148
+ - session: import:organized
149
+ # /memory-list
150
+
151
+ List available Claude Code sessions that can be imported.
152
+
153
+ ## Usage
154
+
155
+ ```
156
+ /memory-list [options]
157
+ ```
158
+
159
+ ## Options
160
+
161
+ - `--project <path>`: Filter sessions by project path
162
+
163
+ ## Examples
164
+
165
+ ```
166
+ /memory-list
167
+ /memory-list --project /home/user/myproject
168
+ ```
169
+
170
+ ## Description
171
+
172
+ Shows all available Claude Code session files that can be imported into memory. Each session displays:
173
+
174
+ - **Session ID**: Unique identifier for the session
175
+ - **Modified date**: When the session was last updated
176
+ - **File size**: Size of the session file
177
+ - **Path**: Full path to the JSONL file
178
+
179
+ Use this command to identify which sessions you want to import before running `/memory-import`.
180
+
181
+ ## Implementation
182
+
183
+ ```bash
184
+ node dist/cli/index.js list $ARGUMENTS
185
+ ```
186
+
187
+ ## 2026-02-25T12:31:21.745Z | fd04fc38-ab42-4406-aadc-9d73fdbbb079
188
+ - type: session_summary
189
+ - session: import:organized
190
+ # /memory-search
191
+
192
+ Search through stored memories using semantic search.
193
+
194
+ ## Usage
195
+
196
+ ```
197
+ /memory-search <query>
198
+ ```
199
+
200
+ ## Arguments
201
+
202
+ - `query`: The search query to find relevant memories
203
+
204
+ ## Examples
205
+
206
+ ```
207
+ /memory-search how to implement authentication
208
+ /memory-search React component patterns
209
+ /memory-search database optimization
210
+ ```
211
+
212
+ ## Description
213
+
214
+ This command searches through all stored conversation memories using semantic similarity. It returns the most relevant memories that match your query, along with their confidence scores.
215
+
216
+ The search uses AXIOMMIND weighted scoring:
217
+ - **High confidence** (≥0.92): Strong match, likely relevant
218
+ - **Suggested** (≥0.75): May be relevant, review recommended
219
+ - **None** (<0.75): No significant matches found
220
+
221
+ ## Implementation
222
+
223
+ ```bash
224
+ node dist/cli/index.js search "$ARGUMENTS"
225
+ ```
226
+
227
+ ## 2026-02-25T12:31:21.746Z | dc8f7b26-d8dd-461f-9911-54b26b23343e
228
+ - type: session_summary
229
+ - session: import:organized
230
+ # /memory-stats
231
+
232
+ View memory storage statistics.
233
+
234
+ ## Usage
235
+
236
+ ```
237
+ /memory-stats
238
+ ```
239
+
240
+ ## Description
241
+
242
+ Displays statistics about stored memories including:
243
+
244
+ - Total number of events
245
+ - Number of vector embeddings
246
+ - Memory level distribution (L0-L4)
247
+ - Storage size information
248
+
249
+ ## Memory Levels
250
+
251
+ The graduation pipeline moves memories through these levels:
252
+
253
+ - **L0**: Raw events (EventStore)
254
+ - **L1**: Structured JSON (patterns, summaries)
255
+ - **L2**: Type candidates (validated schemas)
256
+ - **L3**: Verified knowledge (cross-session validated)
257
+ - **L4**: Active/searchable (indexed, readily available)
258
+
259
+ ## Implementation
260
+
261
+ ```bash
262
+ node dist/cli/index.js stats
263
+ ```