claude-memory-layer 1.0.27 → 1.0.28
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.
- package/.env.example +7 -0
- package/AGENTS.md +11 -0
- package/README.md +184 -41
- package/benchmarks/replay/anonymized-real-sessions.json +48 -0
- package/dist/cli/index.js +10097 -6003
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +9745 -5587
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +6545 -5270
- package/dist/hooks/post-tool-use.js.map +4 -4
- package/dist/hooks/semantic-daemon.js +6646 -5354
- package/dist/hooks/semantic-daemon.js.map +4 -4
- package/dist/hooks/session-end.js +6618 -5347
- package/dist/hooks/session-end.js.map +4 -4
- package/dist/hooks/session-start.js +6619 -5354
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +6614 -5325
- package/dist/hooks/stop.js.map +4 -4
- package/dist/hooks/user-prompt-submit.js +6702 -5356
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/index.js +13537 -0
- package/dist/index.js.map +7 -0
- package/dist/mcp/index.js +20770 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/server/api/index.js +6632 -5319
- package/dist/server/api/index.js.map +4 -4
- package/dist/server/index.js +6667 -5340
- package/dist/server/index.js.map +4 -4
- package/dist/services/memory-service.js +6568 -5350
- package/dist/services/memory-service.js.map +4 -4
- package/dist/ui/assets/js/bootstrap.js +244 -0
- package/dist/ui/assets/js/chat.js +373 -0
- package/dist/ui/assets/js/disclosure.js +232 -0
- package/dist/ui/assets/js/modals.js +298 -0
- package/dist/ui/assets/js/overview.js +655 -0
- package/dist/ui/assets/js/state.js +72 -0
- package/dist/ui/assets/js/views.js +468 -0
- package/dist/ui/index.html +43 -1
- package/dist/ui/index.ts +3 -0
- package/dist/ui/style.css +222 -0
- package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +627 -0
- package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +440 -0
- package/docs/MEMORY_USEFULNESS_AUDIT.md +371 -0
- package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +80 -0
- package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +333 -0
- package/docs/PRODUCT_VALIDATION_MATRIX.md +82 -0
- package/docs/PROJECT_STRUCTURE_ANALYSIS.md +421 -0
- package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +501 -0
- package/docs/REFACTORING_PLAN_THIN_CORE.md +414 -0
- package/docs/REFERENCE_PROJECT_ANALYSES.md +25 -0
- package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +452 -0
- package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +446 -0
- package/docs/architecture/comparison-index.md +47 -0
- package/docs/reports/codex-real-data-validation-20260505T040447Z.md +46 -0
- package/package.json +9 -5
- package/scripts/build.ts +25 -8
- package/scripts/generate-session-qrels.ts +126 -0
- package/scripts/replay-retrieval-benchmark.ts +69 -0
- package/specs/thin-core-refactor/context.md +275 -0
- package/specs/thin-core-refactor/plan.md +536 -0
- package/specs/thin-core-refactor/spec.md +465 -0
- package/src/adapters/claude/capture/index.ts +3 -0
- package/src/adapters/claude/context/index.ts +3 -0
- package/src/adapters/claude/hooks/index.ts +21 -0
- package/src/adapters/claude/hooks/post-tool-use.ts +239 -0
- package/src/adapters/claude/hooks/prompt-injection-policy.ts +104 -0
- package/src/adapters/claude/hooks/semantic-daemon-client.ts +209 -0
- package/src/adapters/claude/hooks/semantic-daemon.ts +283 -0
- package/src/adapters/claude/hooks/session-end.ts +59 -0
- package/src/adapters/claude/hooks/session-start.ts +73 -0
- package/src/adapters/claude/hooks/stop.ts +128 -0
- package/src/adapters/claude/hooks/user-prompt-submit.ts +361 -0
- package/src/adapters/claude/index.ts +4 -0
- package/src/adapters/claude/transcript/index.ts +4 -0
- package/src/adapters/claude/transcript/transcript-reader.ts +57 -0
- package/src/adapters/claude/transcript/turn-reconstructor.ts +65 -0
- package/src/apps/cli/claude-settings-hooks.ts +138 -0
- package/src/apps/cli/codex-import-runner.ts +125 -0
- package/src/apps/cli/codex-validation-output.ts +95 -0
- package/src/apps/cli/hermes-import-runner.ts +130 -0
- package/src/apps/cli/hermes-validation-output.ts +91 -0
- package/src/apps/cli/index.ts +1731 -0
- package/src/apps/cli/mcp-install.ts +106 -0
- package/src/apps/cli/retrieval-disclosure-output.ts +196 -0
- package/src/apps/dashboard/assets/js/bootstrap.js +244 -0
- package/src/apps/dashboard/assets/js/chat.js +373 -0
- package/src/apps/dashboard/assets/js/disclosure.js +232 -0
- package/src/apps/dashboard/assets/js/modals.js +298 -0
- package/src/apps/dashboard/assets/js/overview.js +655 -0
- package/src/apps/dashboard/assets/js/state.js +72 -0
- package/src/apps/dashboard/assets/js/views.js +468 -0
- package/src/{ui → apps/dashboard}/index.html +43 -1
- package/src/apps/dashboard/index.ts +3 -0
- package/src/{ui → apps/dashboard}/style.css +222 -0
- package/src/apps/index.ts +5 -0
- package/src/apps/server/api/chat.ts +244 -0
- package/src/apps/server/api/citations.ts +105 -0
- package/src/apps/server/api/events.ts +137 -0
- package/src/apps/server/api/health.ts +53 -0
- package/src/apps/server/api/index.ts +26 -0
- package/src/apps/server/api/projects.ts +74 -0
- package/src/apps/server/api/search.ts +184 -0
- package/src/apps/server/api/sessions.ts +115 -0
- package/src/apps/server/api/stats.ts +723 -0
- package/src/apps/server/api/turns.ts +143 -0
- package/src/apps/server/api/utils.ts +65 -0
- package/src/apps/server/index.ts +111 -0
- package/src/cli/index.ts +2 -1311
- package/src/cli/retrieval-disclosure-output.ts +2 -0
- package/src/compat/index.ts +5 -0
- package/src/core/derive/fact-deriver.ts +170 -0
- package/src/core/derive/index.ts +2 -0
- package/src/core/derive/summary-deriver.ts +76 -0
- package/src/core/embedder.ts +4 -152
- package/src/core/engine/embedding-maintenance-service.ts +187 -0
- package/src/core/engine/endless-memory-services.ts +4 -0
- package/src/core/engine/index.ts +19 -0
- package/src/core/engine/memory-engine-services.ts +170 -0
- package/src/core/engine/memory-ingest-service.ts +317 -0
- package/src/core/engine/memory-query-service.ts +173 -0
- package/src/core/engine/memory-runtime-service.ts +162 -0
- package/src/core/engine/memory-service-composition.ts +231 -0
- package/src/core/engine/retrieval-analytics-service.ts +181 -0
- package/src/core/engine/retrieval-disclosure-service.ts +420 -0
- package/src/core/engine/retrieval-orchestrator.ts +377 -0
- package/src/core/engine/retrieval-services.ts +176 -0
- package/src/core/engine/shared-memory-services.ts +4 -0
- package/src/core/entity-repo.ts +1 -3
- package/src/core/event-store.ts +3 -3
- package/src/core/evidence-aligner.ts +2 -2
- package/src/core/external-market-context.ts +582 -0
- package/src/core/graduation.ts +2 -3
- package/src/core/index.ts +21 -0
- package/src/core/matcher.ts +2 -4
- package/src/core/model/memory-fact.ts +30 -0
- package/src/core/model/memory-rule.ts +14 -0
- package/src/core/model/memory-summary.ts +21 -0
- package/src/core/model/raw-event.ts +28 -0
- package/src/core/model/retrieval-result.ts +35 -0
- package/src/core/privacy/filter.ts +21 -10
- package/src/core/product-validation-matrix.ts +314 -0
- package/src/core/progressive-retriever.ts +1 -2
- package/src/core/registry/project-path.ts +54 -0
- package/src/core/registry/session-registry.ts +69 -0
- package/src/core/replay-evaluator.ts +625 -0
- package/src/core/retrieval-benchmark.ts +117 -0
- package/src/core/retrieval-quality.ts +109 -0
- package/src/core/retriever.ts +53 -15
- package/src/core/session-qrels.ts +360 -0
- package/src/core/shared-event-store.ts +1 -1
- package/src/core/sqlite-event-store.ts +35 -11
- package/src/core/task/blocker-resolver.ts +2 -2
- package/src/core/task/task-resolver.ts +0 -1
- package/src/core/vector-outbox.ts +1 -10
- package/src/core/vector-worker.ts +1 -1
- package/src/extensions/endless-memory/endless-memory-services.ts +350 -0
- package/src/extensions/endless-memory/index.ts +1 -0
- package/src/extensions/index.ts +5 -0
- package/src/extensions/mcp/handlers.ts +960 -0
- package/src/extensions/mcp/index.ts +48 -0
- package/src/extensions/mcp/tools.ts +252 -0
- package/src/extensions/shared-memory/index.ts +1 -0
- package/src/extensions/shared-memory/shared-memory-services.ts +211 -0
- package/src/extensions/vector/embedder.ts +197 -0
- package/src/extensions/vector/index.ts +1 -0
- package/src/hooks/post-tool-use.ts +3 -236
- package/src/hooks/semantic-daemon-client.ts +1 -208
- package/src/hooks/semantic-daemon.ts +6 -271
- package/src/hooks/session-end.ts +4 -79
- package/src/hooks/session-start.ts +4 -73
- package/src/hooks/stop.ts +3 -173
- package/src/hooks/user-prompt-submit.ts +3 -338
- package/src/index.ts +13 -0
- package/src/mcp/handlers.ts +2 -212
- package/src/mcp/index.ts +3 -46
- package/src/mcp/tools.ts +2 -78
- package/src/server/api/chat.ts +2 -244
- package/src/server/api/citations.ts +2 -105
- package/src/server/api/events.ts +2 -137
- package/src/server/api/health.ts +2 -53
- package/src/server/api/index.ts +2 -26
- package/src/server/api/projects.ts +2 -74
- package/src/server/api/search.ts +2 -102
- package/src/server/api/sessions.ts +2 -115
- package/src/server/api/stats.ts +2 -724
- package/src/server/api/turns.ts +2 -143
- package/src/server/api/utils.ts +2 -46
- package/src/server/index.ts +2 -100
- package/src/services/bootstrap-organizer.ts +46 -26
- package/src/services/codex-session-history-importer.ts +521 -29
- package/src/services/hermes-session-history-importer.ts +733 -0
- package/src/services/memory-service-config.ts +36 -0
- package/src/services/memory-service-registry.ts +150 -0
- package/src/services/memory-service.ts +211 -1325
- package/src/services/session-history-importer.ts +58 -14
- package/tests/README.md +23 -0
- package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +54 -0
- package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +98 -0
- package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +99 -0
- package/tests/apps/app-layer-boundary.test.ts +48 -0
- package/tests/apps/claude-settings-hooks.test.ts +107 -0
- package/tests/apps/cli-disclosure-output.test.ts +212 -0
- package/tests/apps/codex-import-runner.test.ts +99 -0
- package/tests/apps/codex-validation-output.test.ts +100 -0
- package/tests/apps/hermes-import-runner.test.ts +99 -0
- package/tests/apps/mcp-install-command.test.ts +59 -0
- package/tests/apps/package-build-entrypoints.test.ts +30 -0
- package/tests/apps/search-api-disclosure.test.ts +162 -0
- package/tests/apps/stats-api-lightweight.test.ts +67 -0
- package/tests/apps/ui-disclosure-output.test.ts +140 -0
- package/tests/{bootstrap-organizer.test.ts → core/bootstrap-organizer.test.ts} +1 -1
- package/tests/{canonical-key.test.ts → core/canonical-key.test.ts} +1 -1
- package/tests/core/codex-session-history-importer-validation.test.ts +185 -0
- package/tests/{consolidation-worker.test.ts → core/consolidation-worker.test.ts} +2 -2
- package/tests/core/embedding-maintenance-service.test.ts +282 -0
- package/tests/{evidence-aligner.test.ts → core/evidence-aligner.test.ts} +1 -1
- package/tests/core/external-market-context.test.ts +209 -0
- package/tests/core/fact-deriver.test.ts +79 -0
- package/tests/core/hermes-session-history-importer-validation.test.ts +609 -0
- package/tests/{ingest-interceptor.test.ts → core/ingest-interceptor.test.ts} +1 -1
- package/tests/{markdown-mirror.test.ts → core/markdown-mirror.test.ts} +2 -2
- package/tests/{matcher.test.ts → core/matcher.test.ts} +1 -1
- package/tests/{md-mirror.test.ts → core/md-mirror.test.ts} +2 -2
- package/tests/core/memory-engine-services.test.ts +240 -0
- package/tests/core/memory-ingest-service.test.ts +296 -0
- package/tests/core/memory-query-service.test.ts +129 -0
- package/tests/core/memory-runtime-service.test.ts +201 -0
- package/tests/core/memory-service-composition.test.ts +192 -0
- package/tests/core/memory-service-config.test.ts +41 -0
- package/tests/core/memory-service-facade.test.ts +30 -0
- package/tests/core/memory-service-registry.test.ts +206 -0
- package/tests/core/product-validation-matrix.test.ts +61 -0
- package/tests/core/project-registry.test.ts +78 -0
- package/tests/core/replay-evaluator.test.ts +181 -0
- package/tests/core/retrieval-analytics-service.test.ts +210 -0
- package/tests/core/retrieval-benchmark.test.ts +93 -0
- package/tests/core/retrieval-disclosure-service.test.ts +264 -0
- package/tests/core/retrieval-orchestrator.test.ts +403 -0
- package/tests/core/retrieval-quality.test.ts +31 -0
- package/tests/core/retrieval-services.test.ts +185 -0
- package/tests/{retriever-fallback-chain.test.ts → core/retriever-fallback-chain.test.ts} +3 -3
- package/tests/{retriever-strategy-scope.test.ts → core/retriever-strategy-scope.test.ts} +70 -3
- package/tests/{retriever.memu-adoption.test.ts → core/retriever.memu-adoption.test.ts} +3 -3
- package/tests/core/session-history-importer-filter.test.ts +78 -0
- package/tests/core/session-qrels.test.ts +250 -0
- package/tests/{sqlite-event-store-replication.test.ts → core/sqlite-event-store-replication.test.ts} +36 -1
- package/tests/core/summary-deriver.test.ts +66 -0
- package/tests/extensions/embedder-warning-suppression.test.ts +53 -0
- package/tests/extensions/endless-memory-extension-boundary.test.ts +17 -0
- package/tests/extensions/endless-memory-services.test.ts +325 -0
- package/tests/extensions/mcp-context-tools.test.ts +905 -0
- package/tests/extensions/mcp-extension-boundary.test.ts +21 -0
- package/tests/extensions/mcp-package-build.test.ts +22 -0
- package/tests/extensions/mcp-project-aware-tools.test.ts +102 -0
- package/tests/extensions/shared-memory-extension-boundary.test.ts +24 -0
- package/tests/extensions/shared-memory-services.test.ts +309 -0
- package/tests/extensions/vector-extension-boundary.test.ts +21 -0
- package/.claude/settings.local.json +0 -25
- package/.npm-cache/_cacache/content-v2/sha512/04/76/c098f88dfe584a2b80870bff7421b05d17d3d9ee1027f77772332a22d3f93a9a57101a2855107f6ad82077a818bba912b2bc317f2361b5ddb09ad284d9ce +0 -0
- package/.npm-cache/_cacache/content-v2/sha512/60/25/d2ecd39cfc7cab58351162814be77f935c6d6491c10c3745d456da7ddb2117ffd90c10e53fe3c0f1ed16b403307841543634504398b16ee4e6b6dd8e0c45 +0 -0
- package/.npm-cache/_cacache/index-v5/2b/9a/7f8f40206ed8a2e0a84efaa953ccaed1f5d001e14b931083f2e7a0738007 +0 -2
- package/.npm-cache/_cacache/index-v5/2e/d9/fcfa5c6a6abdc2a3644ab84a95936047298c465a2f47ee03db8f7fe1e946 +0 -3
- package/.npm-cache/_cacache/index-v5/a9/42/e519633356d12d3d2f19da66a8301016d496c8f5c3e0554124aaa62dc043 +0 -2
- package/.npm-cache/_logs/2026-02-26T12_04_52_729Z-debug-0.log +0 -256
- package/.npm-cache/_logs/2026-02-26T12_05_36_835Z-debug-0.log +0 -18
- package/.npm-cache/_logs/2026-02-26T12_05_45_982Z-debug-0.log +0 -32
- package/.npm-cache/_logs/2026-02-26T12_05_48_515Z-debug-0.log +0 -260
- package/.npm-cache/_logs/2026-02-26T12_05_53_567Z-debug-0.log +0 -69
- package/.npm-cache/_update-notifier-last-checked +0 -0
- package/bootstrap-kb/decisions/decisions.md +0 -244
- package/bootstrap-kb/glossary/glossary.md +0 -46
- package/bootstrap-kb/modules/.claude-plugin.md +0 -22
- package/bootstrap-kb/modules/agents.md.md +0 -15
- package/bootstrap-kb/modules/claude.md.md +0 -15
- package/bootstrap-kb/modules/context.md.md +0 -15
- package/bootstrap-kb/modules/docs.md +0 -18
- package/bootstrap-kb/modules/handoff.md.md +0 -15
- package/bootstrap-kb/modules/package-lock.json.md +0 -15
- package/bootstrap-kb/modules/package.json.md +0 -15
- package/bootstrap-kb/modules/plan.md.md +0 -15
- package/bootstrap-kb/modules/readme.md.md +0 -15
- package/bootstrap-kb/modules/scripts.md +0 -26
- package/bootstrap-kb/modules/spec.md.md +0 -15
- package/bootstrap-kb/modules/specs.md +0 -20
- package/bootstrap-kb/modules/src.md +0 -51
- package/bootstrap-kb/modules/tests.md +0 -42
- package/bootstrap-kb/modules/tsconfig.json.md +0 -15
- package/bootstrap-kb/modules/vitest.config.ts.md +0 -15
- package/bootstrap-kb/overview/overview.md +0 -40
- package/bootstrap-kb/sources/manifest.json +0 -950
- package/bootstrap-kb/sources/manifest.md +0 -227
- package/bootstrap-kb/timeline/timeline.md +0 -57
- package/claude-memory-layer-1.0.14.tgz +0 -0
- package/d.sh +0 -3
- package/deploy.sh +0 -3
- package/dist/ui/app.js +0 -2101
- package/memory/.claude-plugin/commands/2026-02-25.md +0 -263
- package/memory/_index.md +0 -419
- package/memory/agent_response/uncategorized/2026-02-26.md +0 -176
- package/memory/agent_response/uncategorized/2026-03-03.md +0 -14
- package/memory/agent_response/uncategorized/2026-03-04.md +0 -1421
- package/memory/agent_response/uncategorized/2026-03-05.md +0 -157
- package/memory/default/uncategorized/2026-02-25.md +0 -4839
- package/memory/session_summary/uncategorized/2026-02-26.md +0 -13
- package/memory/session_summary/uncategorized/2026-03-03.md +0 -5
- package/memory/session_summary/uncategorized/2026-03-04.md +0 -50
- package/memory/specs/20260207-dashboard-upgrade/2026-02-25.md +0 -142
- package/memory/specs/citations-system/2026-02-25.md +0 -1121
- package/memory/specs/endless-mode/2026-02-25.md +0 -1392
- package/memory/specs/entity-edge-model/2026-02-25.md +0 -1263
- package/memory/specs/evidence-aligner-v2/2026-02-25.md +0 -1028
- package/memory/specs/mcp-desktop-integration/2026-02-25.md +0 -1334
- package/memory/specs/post-tool-use-hook/2026-02-25.md +0 -1164
- package/memory/specs/private-tags/2026-02-25.md +0 -1057
- package/memory/specs/progressive-disclosure/2026-02-25.md +0 -1436
- package/memory/specs/task-entity-system/2026-02-25.md +0 -924
- package/memory/specs/vector-outbox-v2/2026-02-25.md +0 -1510
- package/memory/specs/web-viewer-ui/2026-02-25.md +0 -1709
- package/memory/tool_observation/uncategorized/2026-02-26.md +0 -209
- package/memory/tool_observation/uncategorized/2026-03-03.md +0 -21
- package/memory/tool_observation/uncategorized/2026-03-04.md +0 -1033
- package/memory/tool_observation/uncategorized/2026-03-05.md +0 -33
- package/memory/user_prompt/uncategorized/2026-02-26.md +0 -25
- package/memory/user_prompt/uncategorized/2026-03-04.md +0 -634
- package/memory/user_prompt/uncategorized/2026-03-05.md +0 -6
- package/specs/optional-duckdb/context.md +0 -77
- package/specs/optional-duckdb/plan.md +0 -142
- package/specs/optional-duckdb/spec.md +0 -35
- package/src/ui/app.js +0 -2101
|
@@ -1,4839 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
## 2026-02-25T12:31:21.747Z | b9246a1c-4968-424a-aee5-d4c62a2d1346
|
|
3
|
-
- type: session_summary
|
|
4
|
-
- session: import:organized
|
|
5
|
-
# Codex / AI Agent Instructions
|
|
6
|
-
|
|
7
|
-
이 저장소는 **Claude Code용 메모리 플러그인 + CLI + 로컬 대시보드 서버**입니다.
|
|
8
|
-
Codex(또는 다른 코딩 에이전트)가 작업할 때 아래 규칙을 우선으로 따르세요.
|
|
9
|
-
|
|
10
|
-
## Quick Commands
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm install
|
|
14
|
-
npm run build
|
|
15
|
-
|
|
16
|
-
# 웹 대시보드(로컬)
|
|
17
|
-
node dist/server/index.js
|
|
18
|
-
# 또는
|
|
19
|
-
npx claude-memory-layer dashboard
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Key Entry Points
|
|
23
|
-
|
|
24
|
-
- `scripts/build.ts`: esbuild 기반 빌드. `dist/` 생성 + `.claude-plugin/` 및 `src/ui` 복사
|
|
25
|
-
- `src/cli/index.ts`: CLI 엔트리포인트 (`bin`: `claude-memory-layer`)
|
|
26
|
-
- `src/server/index.ts`: 대시보드/REST API 서버 (기본 포트 `37777`)
|
|
27
|
-
- `src/server/api/chat.ts`: **외부 `claude` CLI**를 `spawn('claude', ...)`로 호출 (환경에 따라 미설치일 수 있음)
|
|
28
|
-
|
|
29
|
-
## Local Side-Effects (주의)
|
|
30
|
-
|
|
31
|
-
- `claude-memory-layer install` / `uninstall` 은 **사용자 머신의** `~/.claude/settings.json` 을 수정합니다.
|
|
32
|
-
- 자동 실행/테스트 목적으로 임의 실행하지 말고, 사용자가 명시적으로 요청할 때만 실행하세요.
|
|
33
|
-
- 훅/CLI/서버는 기본적으로 `~/.claude-code/memory` 아래에 데이터를 읽고/씁니다.
|
|
34
|
-
- 메모리 스토리지를 삭제/초기화하는 동작은 요청 없이는 하지 마세요.
|
|
35
|
-
|
|
36
|
-
## Common Pitfall: Self-dependency (반복 발생)
|
|
37
|
-
|
|
38
|
-
`package.json`의 `dependencies`에 **자기 자신**을 추가하면 설치가 꼬입니다.
|
|
39
|
-
|
|
40
|
-
- 금지 예: `"claude-memory-layer": "^1.0.x"`
|
|
41
|
-
- 진단: `npm list claude-memory-layer` 결과가 `(empty)` 여야 정상
|
|
42
|
-
- 복구:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
rm package-lock.json && rm -rf node_modules
|
|
46
|
-
npm install
|
|
47
|
-
npm list claude-memory-layer
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Release / Publish Workflow
|
|
51
|
-
|
|
52
|
-
1. Self-dependency 확인: `npm list claude-memory-layer` → `(empty)`
|
|
53
|
-
2. 버전 업데이트: `npm version patch` 또는 `package.json` 수정
|
|
54
|
-
3. 빌드: `npm run build`
|
|
55
|
-
4. 배포: `npm publish --otp=<code>`
|
|
56
|
-
5. 확인: `npm view claude-memory-layer versions`
|
|
57
|
-
|
|
58
|
-
## Dev Notes
|
|
59
|
-
|
|
60
|
-
- Node.js: `>=18` (ESM 프로젝트)
|
|
61
|
-
- 스토리지: **SQLite(WAL) 기반**으로 훅(쓰기) + 서버(읽기) 동시 동작을 전제로 함
|
|
62
|
-
- 테스트/정적분석 스크립트는 존재하지만, 현재 시점에서 전부 “항상 green”을 보장하지 않을 수 있으니
|
|
63
|
-
변경 전후로 실제 실행 결과를 확인하고 진행하세요.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
## 2026-02-25T12:31:21.748Z | ac708211-cc0a-4817-aa7d-372f6ec29338
|
|
67
|
-
- type: session_summary
|
|
68
|
-
- session: import:organized
|
|
69
|
-
# Code Memory - Project Instructions
|
|
70
|
-
|
|
71
|
-
## Common Mistakes to Avoid
|
|
72
|
-
|
|
73
|
-
### ⚠️ Self-dependency in package.json (반복 발생 주의!)
|
|
74
|
-
- **절대로** package.json의 dependencies에 자기 자신의 패키지를 추가하지 말 것
|
|
75
|
-
- 예: `"claude-memory-layer": "^1.0.x"` 같은 순환 의존성 금지
|
|
76
|
-
- npm list 시 이상한 중첩 구조가 보이면 self-dependency 의심할 것
|
|
77
|
-
|
|
78
|
-
#### 원인
|
|
79
|
-
- `package-lock.json`에 self-dependency가 저장되면, `npm install` 시 package.json에 복원됨
|
|
80
|
-
- 한번 잘못 들어가면 lock 파일 때문에 계속 복원되는 악순환 발생
|
|
81
|
-
|
|
82
|
-
#### 해결 방법
|
|
83
|
-
```bash
|
|
84
|
-
# 1. package.json에서 self-dependency 제거
|
|
85
|
-
# 2. lock 파일과 node_modules 삭제
|
|
86
|
-
rm package-lock.json && rm -rf node_modules
|
|
87
|
-
# 3. 새로 설치
|
|
88
|
-
npm install
|
|
89
|
-
# 4. 확인 (empty가 나와야 정상)
|
|
90
|
-
npm list claude-memory-layer
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## npm Publish Workflow
|
|
94
|
-
1. Self-dependency 확인: `npm list claude-memory-layer` → `(empty)` 확인
|
|
95
|
-
2. 버전 업데이트: package.json 직접 수정 또는 `npm version patch`
|
|
96
|
-
3. 빌드: `npm run build`
|
|
97
|
-
4. 배포: `npm publish --otp=<코드>`
|
|
98
|
-
5. 확인: `npm view claude-memory-layer versions`
|
|
99
|
-
|
|
100
|
-
## 2026-02-25T12:31:21.749Z | f509ff1e-5ec2-4749-83c7-f96eedd933e8
|
|
101
|
-
- type: session_summary
|
|
102
|
-
- session: import:organized
|
|
103
|
-
# Claude Memory Layer - 작업 핸드오프 문서
|
|
104
|
-
|
|
105
|
-
## 현재 상태
|
|
106
|
-
**날짜**: 2026-02-01
|
|
107
|
-
**상태**: SQLite WAL 마이그레이션 완료 ✅
|
|
108
|
-
|
|
109
|
-
## 문제 해결 완료
|
|
110
|
-
|
|
111
|
-
### 기존 문제
|
|
112
|
-
- DuckDB 다중 프로세스 동시 접근 충돌
|
|
113
|
-
- 웹 대시보드 (localhost:37777)에서 500 에러
|
|
114
|
-
- 훅과 서버 동시 실행 불가
|
|
115
|
-
|
|
116
|
-
### 해결책: 2-tier 스토리지 아키텍처
|
|
117
|
-
```
|
|
118
|
-
Hooks (쓰기) ──▶ SQLite (WAL) ◀── Server (읽기)
|
|
119
|
-
│
|
|
120
|
-
└── 동시 접근 가능 ✅
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## 구현된 변경사항
|
|
124
|
-
|
|
125
|
-
### 새 파일
|
|
126
|
-
1. **`src/core/sqlite-wrapper.ts`** - SQLite WAL 모드 래퍼
|
|
127
|
-
2. **`src/core/sqlite-event-store.ts`** - SQLite 기반 EventStore
|
|
128
|
-
3. **`src/core/sync-worker.ts`** - SQLite→DuckDB 동기화 워커 (미래 분석용)
|
|
129
|
-
|
|
130
|
-
### 수정된 파일
|
|
131
|
-
1. **`src/services/memory-service.ts`** - 이중 스토어 아키텍처 통합
|
|
132
|
-
- `sqliteStore`: Primary store (항상 사용)
|
|
133
|
-
- `analyticsStore`: DuckDB (옵션, 분석용)
|
|
134
|
-
- `analyticsEnabled` 옵션 추가
|
|
135
|
-
|
|
136
|
-
2. **`src/core/index.ts`** - 새 모듈 export
|
|
137
|
-
|
|
138
|
-
3. **`scripts/build.ts`** - better-sqlite3 external 추가
|
|
139
|
-
|
|
140
|
-
4. **`package.json`** - better-sqlite3 의존성 추가
|
|
141
|
-
|
|
142
|
-
## 테스트 결과
|
|
143
|
-
```bash
|
|
144
|
-
# 서버 실행 중 훅 테스트
|
|
145
|
-
$ node dist/server/index.js &
|
|
146
|
-
$ echo '{"session_id":"test","prompt":"test","cwd":"/tmp"}' | node dist/hooks/user-prompt-submit.js
|
|
147
|
-
{"context":""} # 성공!
|
|
148
|
-
|
|
149
|
-
# 동시 실행 테스트 (5개 훅 병렬)
|
|
150
|
-
All hooks completed ✅
|
|
151
|
-
eventCount: 7
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## 아키텍처 결정
|
|
155
|
-
|
|
156
|
-
### Primary Store: SQLite (WAL 모드)
|
|
157
|
-
- 훅에서 직접 쓰기
|
|
158
|
-
- 서버에서 직접 읽기
|
|
159
|
-
- WAL 모드: 다중 리더 + 단일 라이터 지원
|
|
160
|
-
- 락 충돌 없음
|
|
161
|
-
|
|
162
|
-
### Analytics Store: DuckDB (옵션, 미래용)
|
|
163
|
-
- 복잡한 분석 쿼리용
|
|
164
|
-
- 배치 동기화 (SyncWorker)
|
|
165
|
-
- 현재는 비활성화
|
|
166
|
-
|
|
167
|
-
## 빌드 및 실행
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
# 빌드
|
|
171
|
-
npm run build
|
|
172
|
-
|
|
173
|
-
# 서버 시작
|
|
174
|
-
node dist/server/index.js
|
|
175
|
-
|
|
176
|
-
# 훅 테스트 (서버 실행 중에도 가능!)
|
|
177
|
-
echo '{"session_id":"test","prompt":"test","cwd":"/tmp"}' | node dist/hooks/user-prompt-submit.js
|
|
178
|
-
|
|
179
|
-
# 대시보드
|
|
180
|
-
open http://localhost:37777
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## 향후 작업 (선택사항)
|
|
184
|
-
|
|
185
|
-
1. **DuckDB 분석 기능 활성화**
|
|
186
|
-
- SyncWorker로 SQLite→DuckDB 동기화
|
|
187
|
-
- 복잡한 통계/분석 쿼리에 DuckDB 사용
|
|
188
|
-
|
|
189
|
-
2. **Shared Store SQLite 마이그레이션**
|
|
190
|
-
- 현재: 훅에서 비활성화
|
|
191
|
-
- 향후: SQLite 기반으로 전환
|
|
192
|
-
|
|
193
|
-
3. **마이그레이션 도구**
|
|
194
|
-
- 기존 DuckDB 데이터를 SQLite로 마이그레이션
|
|
195
|
-
|
|
196
|
-
## 2026-02-25T12:31:21.750Z | 51d82e23-a7ef-4b51-92d0-1d5d33f1b606
|
|
197
|
-
- type: session_summary
|
|
198
|
-
- session: import:organized
|
|
199
|
-
# Claude Memory Layer
|
|
200
|
-
|
|
201
|
-
Claude Code 플러그인으로, 대화 내용을 기억하여 사용할수록 똑똑해지는 AI 어시스턴트를 만듭니다.
|
|
202
|
-
|
|
203
|
-
## 개요
|
|
204
|
-
|
|
205
|
-
Claude Memory Layer는 Claude Code에서 사용자와 AI 간의 모든 대화를 저장하고, 새로운 질문을 할 때 관련된 과거 대화를 자동으로 검색하여 컨텍스트로 제공합니다. 이를 통해:
|
|
206
|
-
|
|
207
|
-
- **연속성 있는 대화**: 이전 세션에서 논의한 내용을 기억
|
|
208
|
-
- **프로젝트 맥락 이해**: 프로젝트별로 축적된 지식 활용
|
|
209
|
-
- **개인화된 응답**: 사용자의 선호도와 패턴 학습
|
|
210
|
-
|
|
211
|
-
## Features
|
|
212
|
-
|
|
213
|
-
### Core Features
|
|
214
|
-
|
|
215
|
-
- **Conversation Memory**: 사용자 프롬프트와 AI 응답 저장
|
|
216
|
-
- **Semantic Search**: 벡터 임베딩을 통한 의미 기반 검색
|
|
217
|
-
- **AXIOMMIND Architecture**: 7가지 원칙 기반 안정적 메모리 관리
|
|
218
|
-
- **Memory Graduation**: L0→L4 단계별 메모리 승격
|
|
219
|
-
- **Evidence Alignment**: 응답이 실제 기억에 기반했는지 검증
|
|
220
|
-
- **History Import**: 기존 Claude Code 세션 기록 임포트
|
|
221
|
-
|
|
222
|
-
### Advanced Features
|
|
223
|
-
|
|
224
|
-
- **Citations System**: 메모리 출처 추적 (`[mem:abc123]` 형식)으로 검색 결과의 원본 확인 가능
|
|
225
|
-
- **Endless Mode**: 세션 경계 없는 연속적 메모리 스트림, Biomimetic Memory Architecture 기반
|
|
226
|
-
- **Entity-Edge Model**: entries/entities/edges 3-layer 모델로 데이터 관계 명시적 모델링
|
|
227
|
-
- **Evidence Aligner V2**: Quote 기반 3단계 정렬 (exact → normalized → fuzzy)
|
|
228
|
-
- **MCP Desktop Integration**: Claude Desktop용 MCP 서버로 CLI와 동일한 메모리 공유
|
|
229
|
-
- **PostToolUse Hook**: 도구 실행 결과 (Read, Write, Bash 등) 캡처 및 저장
|
|
230
|
-
- **Private Tags**: `<private>` 태그로 민감 정보를 명시적으로 제외
|
|
231
|
-
- **Progressive Disclosure**: 3-Layer 검색 (인덱스 → 타임라인 → 상세)으로 토큰 효율화
|
|
232
|
-
- **memU-inspired Retrieval**: fast/deep 전략 + 스코프 필터(session prefix, canonical key prefix, metadata path)
|
|
233
|
-
- **Append-only Markdown Mirror**: 저장 이벤트를 `memory/<namespace>/<category...>/YYYY-MM-DD.md`에도 동기 append (기본값: `namespace=default`, `category=uncategorized`, 경로 세그먼트 sanitize)
|
|
234
|
-
- `memory/_index.md` 인덱스를 자동 갱신
|
|
235
|
-
- **Task Entity System**: Task를 Entity로 승격하여 세션 간 상태 추적
|
|
236
|
-
- **Vector Outbox V2**: Transactional Outbox 패턴으로 DuckDB-LanceDB 정합성 보장
|
|
237
|
-
- **Web Viewer UI**: localhost:37777 대시보드로 실시간 메모리 모니터링
|
|
238
|
-
|
|
239
|
-
## 설치 방법
|
|
240
|
-
|
|
241
|
-
### 1. 의존성 설치
|
|
242
|
-
|
|
243
|
-
```bash
|
|
244
|
-
cd claude-memory-layer
|
|
245
|
-
npm install
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### 2. 빌드
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
npm run build
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### 3. Claude Code에 플러그인 등록
|
|
255
|
-
|
|
256
|
-
빌드된 플러그인을 Claude Code 설정에 추가합니다:
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
# Claude Code 설정 디렉토리에 플러그인 복사
|
|
260
|
-
cp -r dist/.claude-plugin ~/.claude/plugins/claude-memory-layer/
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
## 사용 방법
|
|
264
|
-
|
|
265
|
-
### 자동 동작 (Hooks)
|
|
266
|
-
|
|
267
|
-
플러그인은 Claude Code 세션에 자동으로 연결되어 동작합니다:
|
|
268
|
-
|
|
269
|
-
| Hook | 동작 |
|
|
270
|
-
|------|------|
|
|
271
|
-
| **SessionStart** | 세션 시작 시 프로젝트 관련 컨텍스트 로드 |
|
|
272
|
-
| **UserPromptSubmit** | 프롬프트 입력 시 관련 기억 검색 및 저장 |
|
|
273
|
-
| **Stop** | AI 응답 완료 시 응답 내용 저장 |
|
|
274
|
-
| **SessionEnd** | 세션 종료 시 요약 생성 및 저장 |
|
|
275
|
-
|
|
276
|
-
### Slash 명령어
|
|
277
|
-
|
|
278
|
-
Claude Code 내에서 사용할 수 있는 명령어:
|
|
279
|
-
|
|
280
|
-
```bash
|
|
281
|
-
# 메모리 검색 - 관련 기억 찾기
|
|
282
|
-
/memory-search "authentication 구현 방법"
|
|
283
|
-
|
|
284
|
-
# 대화 기록 보기
|
|
285
|
-
/memory-history
|
|
286
|
-
/memory-history --limit 50
|
|
287
|
-
/memory-history --session <session-id>
|
|
288
|
-
|
|
289
|
-
# 통계 확인
|
|
290
|
-
/memory-stats
|
|
291
|
-
|
|
292
|
-
# 기존 대화 기록 임포트
|
|
293
|
-
/memory-import # 현재 프로젝트
|
|
294
|
-
/memory-import --all # 모든 프로젝트
|
|
295
|
-
/memory-import --project /path/to/project # 특정 프로젝트
|
|
296
|
-
|
|
297
|
-
# 임포트 가능한 세션 목록
|
|
298
|
-
/memory-list
|
|
299
|
-
|
|
300
|
-
# 메모리 삭제
|
|
301
|
-
/memory-forget --session <id> --confirm
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
### 기존 메모리 정리 Import (구조화)
|
|
305
|
-
|
|
306
|
-
레거시 markdown 메모리를 읽어서 구조화 경로로 재저장(import)할 수 있습니다.
|
|
307
|
-
|
|
308
|
-
```bash
|
|
309
|
-
# 미리보기(실제 저장 없음)
|
|
310
|
-
claude-memory-layer organize-import /path/to/legacy-memory --dry-run
|
|
311
|
-
|
|
312
|
-
# 실제 import
|
|
313
|
-
claude-memory-layer organize-import /path/to/legacy-memory --project /path/to/project
|
|
314
|
-
|
|
315
|
-
# 일부만 import
|
|
316
|
-
claude-memory-layer organize-import /path/to/legacy-memory --limit 100
|
|
317
|
-
|
|
318
|
-
# source에 markdown이 없으면 자동 bootstrap(코드+git 분석)
|
|
319
|
-
claude-memory-layer organize-import /path/to/empty-dir --project /path/to/project
|
|
320
|
-
|
|
321
|
-
# bootstrap 강제 실행
|
|
322
|
-
claude-memory-layer organize-import /path/to/memory --force-bootstrap --repo /path/to/project
|
|
323
|
-
|
|
324
|
-
# 자동 bootstrap 비활성화
|
|
325
|
-
claude-memory-layer organize-import /path/to/empty-dir --no-bootstrap-if-empty
|
|
326
|
-
|
|
327
|
-
# markdown이 없는 초기 상태면 bootstrap 생성 + import
|
|
328
|
-
claude-memory-layer organize-import /path/to/empty-dir --bootstrap --repo /path/to/codebase
|
|
329
|
-
|
|
330
|
-
# bootstrap 강제 재생성 (기존 markdown 있어도)
|
|
331
|
-
claude-memory-layer organize-import /path/to/legacy-memory --force-bootstrap --repo /path/to/codebase --out /path/to/legacy-memory/bootstrap-kb
|
|
332
|
-
|
|
333
|
-
# 증분 bootstrap (기본값): 이전 manifest를 기준으로 변경분 중심 업데이트
|
|
334
|
-
claude-memory-layer organize-import /path/to/legacy-memory --bootstrap --repo /path/to/codebase --incremental
|
|
335
|
-
|
|
336
|
-
# 전체 재생성 bootstrap
|
|
337
|
-
claude-memory-layer organize-import /path/to/legacy-memory --bootstrap --repo /path/to/codebase --no-incremental
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### CLI 명령어
|
|
341
|
-
|
|
342
|
-
터미널에서 직접 사용:
|
|
343
|
-
|
|
344
|
-
```bash
|
|
345
|
-
# 메모리 검색
|
|
346
|
-
npx claude-memory-layer search "React 컴포넌트 패턴"
|
|
347
|
-
npx claude-memory-layer search "API 에러 처리" --top-k 10
|
|
348
|
-
|
|
349
|
-
# 대화 기록 조회
|
|
350
|
-
npx claude-memory-layer history
|
|
351
|
-
npx claude-memory-layer history --limit 50 --type user_prompt
|
|
352
|
-
|
|
353
|
-
# 통계 확인
|
|
354
|
-
npx claude-memory-layer stats
|
|
355
|
-
|
|
356
|
-
# 기존 세션 임포트
|
|
357
|
-
npx claude-memory-layer import # 현재 프로젝트
|
|
358
|
-
npx claude-memory-layer import --all # 모든 프로젝트
|
|
359
|
-
npx claude-memory-layer import --all --verbose # 상세 로그
|
|
360
|
-
|
|
361
|
-
# 임포트 가능한 세션 목록
|
|
362
|
-
npx claude-memory-layer list
|
|
363
|
-
npx claude-memory-layer list --project /path/to/project
|
|
364
|
-
|
|
365
|
-
# 임베딩 수동 처리
|
|
366
|
-
npx claude-memory-layer process
|
|
367
|
-
|
|
368
|
-
# MongoDB 동기화 (옵션, 멀티 서버 협업)
|
|
369
|
-
# - 여러 서버에서 같은 프로젝트를 개발할 때, 각 서버의 로컬 SQLite(events.sqlite) 이벤트를
|
|
370
|
-
# 하나의 MongoDB로 모아 push/pull 동기화할 수 있습니다.
|
|
371
|
-
# - 동일 프로젝트는 반드시 같은 project key로 실행해야 합니다.
|
|
372
|
-
export CLAUDE_MEMORY_MONGO_URI="mongodb://USER:PASSWORD@HOST:PORT/"
|
|
373
|
-
export CLAUDE_MEMORY_MONGO_DB="claude_memory_layer"
|
|
374
|
-
export CLAUDE_MEMORY_MONGO_PROJECT="my-project"
|
|
375
|
-
|
|
376
|
-
# 1회 동기화 (push+pull)
|
|
377
|
-
npx claude-memory-layer mongo-sync
|
|
378
|
-
|
|
379
|
-
# 지속 동기화 (주기적으로 push+pull)
|
|
380
|
-
npx claude-memory-layer mongo-sync --watch --interval 30000
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### memU-inspired Retrieval 사용 예시
|
|
384
|
-
|
|
385
|
-
아래 예시는 SDK/서비스 레벨에서 `retrieveMemories()` 호출 시 적용되는 옵션입니다.
|
|
386
|
-
|
|
387
|
-
```ts
|
|
388
|
-
import { getMemoryServiceForProject } from './src/services/memory-service.js';
|
|
389
|
-
|
|
390
|
-
const memory = getMemoryServiceForProject('/path/to/project');
|
|
391
|
-
|
|
392
|
-
// 1) Fast: 키워드 기반 빠른 검색
|
|
393
|
-
const fast = await memory.retrieveMemories('브리핑 포맷', {
|
|
394
|
-
strategy: 'fast',
|
|
395
|
-
topK: 5,
|
|
396
|
-
minScore: 0.6
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
// 2) Deep: 벡터 검색 + 키워드 오버랩 재정렬
|
|
400
|
-
const deep = await memory.retrieveMemories('브리핑 포맷', {
|
|
401
|
-
strategy: 'deep',
|
|
402
|
-
topK: 10,
|
|
403
|
-
rerankWithKeyword: true
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
// 3) Scoped filter: 세션/타입/계층형 메타데이터로 범위 제한
|
|
407
|
-
const scoped = await memory.retrieveMemories('아침 브리핑', {
|
|
408
|
-
strategy: 'deep',
|
|
409
|
-
scope: {
|
|
410
|
-
sessionIdPrefix: 'agent:main:',
|
|
411
|
-
eventTypes: ['user_prompt', 'agent_response'],
|
|
412
|
-
canonicalKeyPrefix: 'pref/briefing',
|
|
413
|
-
contentIncludes: ['아침'],
|
|
414
|
-
metadata: {
|
|
415
|
-
'scope.project.id': 'alpha'
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
팁:
|
|
422
|
-
- `strategy: 'auto'`는 기본적으로 `deep` 경로를 사용합니다.
|
|
423
|
-
- 저지연 응답이 중요하면 `fast`, 정확도 우선이면 `deep`를 권장합니다.
|
|
424
|
-
|
|
425
|
-
## Privacy 기능
|
|
426
|
-
|
|
427
|
-
### Private Tags
|
|
428
|
-
|
|
429
|
-
민감한 정보를 메모리에서 제외하려면 `<private>` 태그를 사용합니다:
|
|
430
|
-
|
|
431
|
-
```markdown
|
|
432
|
-
이 부분은 저장됩니다.
|
|
433
|
-
|
|
434
|
-
<private>
|
|
435
|
-
API_KEY=sk-xxxx
|
|
436
|
-
SECRET_TOKEN=abc123
|
|
437
|
-
이 내용은 메모리에 저장되지 않습니다.
|
|
438
|
-
</private>
|
|
439
|
-
|
|
440
|
-
이 부분도 저장됩니다.
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
저장 결과:
|
|
444
|
-
```
|
|
445
|
-
이 부분은 저장됩니다.
|
|
446
|
-
[PRIVATE]
|
|
447
|
-
이 부분도 저장됩니다.
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### 자동 필터링
|
|
451
|
-
|
|
452
|
-
다음 패턴은 자동으로 마스킹됩니다:
|
|
453
|
-
- `password`, `api_key`, `secret`, `token`
|
|
454
|
-
- Bearer 토큰
|
|
455
|
-
- Private Key 블록
|
|
456
|
-
|
|
457
|
-
## Citations (인용 시스템)
|
|
458
|
-
|
|
459
|
-
검색 결과에는 인용 ID가 포함됩니다:
|
|
460
|
-
|
|
461
|
-
```
|
|
462
|
-
🔍 Search Results:
|
|
463
|
-
|
|
464
|
-
#1 [mem:a7Bc3x] (score: 0.94)
|
|
465
|
-
"DuckDB를 사용하여 이벤트 소싱 패턴을..."
|
|
466
|
-
📅 2026-01-30 | 🔗 Session abc123
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
원본 확인:
|
|
470
|
-
```bash
|
|
471
|
-
claude-memory-layer show mem:a7Bc3x
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
## Endless Mode
|
|
475
|
-
|
|
476
|
-
세션 경계 없이 연속적인 메모리 스트림을 유지합니다:
|
|
477
|
-
|
|
478
|
-
```bash
|
|
479
|
-
# Endless Mode 활성화
|
|
480
|
-
claude-memory-layer config set mode endless
|
|
481
|
-
|
|
482
|
-
# 상태 확인
|
|
483
|
-
claude-memory-layer status
|
|
484
|
-
|
|
485
|
-
# 출력 예시:
|
|
486
|
-
# Mode: Endless
|
|
487
|
-
# Working Set: 47 events (last 18 hours)
|
|
488
|
-
# Continuity Score: 0.85 (seamless)
|
|
489
|
-
# Consolidated: 23 memories
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
### 모드 비교
|
|
493
|
-
|
|
494
|
-
| 기존 세션 모드 | Endless Mode |
|
|
495
|
-
|---------------|-------------|
|
|
496
|
-
| 명확한 시작/끝 | 연속적 스트림 |
|
|
497
|
-
| 세션별 요약 | 점진적 통합 |
|
|
498
|
-
| 재시작 시 빈 상태 | 이전 컨텍스트 유지 |
|
|
499
|
-
|
|
500
|
-
## MCP Desktop Integration
|
|
501
|
-
|
|
502
|
-
Claude Desktop에서 메모리 검색을 사용하려면:
|
|
503
|
-
|
|
504
|
-
```bash
|
|
505
|
-
# MCP 서버 설치
|
|
506
|
-
claude-memory-layer mcp install
|
|
507
|
-
|
|
508
|
-
# 또는 수동 설정: ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
509
|
-
{
|
|
510
|
-
"mcpServers": {
|
|
511
|
-
"claude-memory-layer": {
|
|
512
|
-
"command": "npx",
|
|
513
|
-
"args": ["claude-memory-layer-mcp"]
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
### 제공되는 MCP 도구
|
|
520
|
-
|
|
521
|
-
| 도구 | 설명 |
|
|
522
|
-
|------|------|
|
|
523
|
-
| `mem-search` | 메모리 검색 |
|
|
524
|
-
| `mem-timeline` | 타임라인 조회 |
|
|
525
|
-
| `mem-details` | 상세 정보 조회 |
|
|
526
|
-
| `mem-stats` | 통계 조회 |
|
|
527
|
-
|
|
528
|
-
## Web Viewer
|
|
529
|
-
|
|
530
|
-
브라우저에서 메모리 대시보드를 확인할 수 있습니다:
|
|
531
|
-
|
|
532
|
-
```bash
|
|
533
|
-
# 웹 서버 시작
|
|
534
|
-
claude-memory-layer dashboard
|
|
535
|
-
|
|
536
|
-
# 브라우저에서 접속
|
|
537
|
-
# http://localhost:37777
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
### 주요 기능
|
|
541
|
-
- 실시간 이벤트 스트림
|
|
542
|
-
- 세션/프로젝트별 탐색
|
|
543
|
-
- 벡터 검색 인터페이스
|
|
544
|
-
- 저장소 통계 대시보드
|
|
545
|
-
- Outbox 상태 모니터링
|
|
546
|
-
|
|
547
|
-
## 기존 대화 기록 임포트
|
|
548
|
-
|
|
549
|
-
이미 Claude Code를 사용해왔다면, 기존 대화 기록을 임포트하여 바로 활용할 수 있습니다:
|
|
550
|
-
|
|
551
|
-
```bash
|
|
552
|
-
# 1. 먼저 임포트 가능한 세션 확인
|
|
553
|
-
npx claude-memory-layer list
|
|
554
|
-
|
|
555
|
-
# 2. 현재 프로젝트의 모든 세션 임포트
|
|
556
|
-
npx claude-memory-layer import
|
|
557
|
-
|
|
558
|
-
# 3. 또는 모든 프로젝트의 세션 임포트
|
|
559
|
-
npx claude-memory-layer import --all --verbose
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
### 임포트 결과 예시
|
|
563
|
-
|
|
564
|
-
```
|
|
565
|
-
📥 Importing all sessions from all projects
|
|
566
|
-
|
|
567
|
-
⏳ Processing embeddings...
|
|
568
|
-
|
|
569
|
-
✅ Import Complete
|
|
570
|
-
|
|
571
|
-
Sessions processed: 15
|
|
572
|
-
Total messages: 342
|
|
573
|
-
Imported prompts: 156
|
|
574
|
-
Imported responses: 186
|
|
575
|
-
Skipped duplicates: 0
|
|
576
|
-
Embeddings processed: 342
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
### 중복 처리
|
|
580
|
-
|
|
581
|
-
임포트는 콘텐츠 해시 기반으로 중복을 자동 감지합니다. 여러 번 실행해도 같은 내용이 중복 저장되지 않습니다.
|
|
582
|
-
|
|
583
|
-
## 동작 원리
|
|
584
|
-
|
|
585
|
-
### 1. 메모리 저장
|
|
586
|
-
|
|
587
|
-
```
|
|
588
|
-
사용자 프롬프트 입력
|
|
589
|
-
↓
|
|
590
|
-
EventStore에 저장 (DuckDB, append-only)
|
|
591
|
-
↓
|
|
592
|
-
Outbox에 임베딩 요청 등록
|
|
593
|
-
↓
|
|
594
|
-
Vector Worker가 임베딩 생성
|
|
595
|
-
↓
|
|
596
|
-
VectorStore에 저장 (LanceDB)
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
### 2. 메모리 검색
|
|
600
|
-
|
|
601
|
-
```
|
|
602
|
-
새 프롬프트 입력
|
|
603
|
-
↓
|
|
604
|
-
임베딩 생성
|
|
605
|
-
↓
|
|
606
|
-
VectorStore에서 유사 벡터 검색
|
|
607
|
-
↓
|
|
608
|
-
AXIOMMIND Matcher로 신뢰도 계산
|
|
609
|
-
↓
|
|
610
|
-
컨텍스트로 Claude에 제공
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
### 3. 메모리 승격 (Graduation)
|
|
614
|
-
|
|
615
|
-
자주 참조되는 메모리는 더 높은 레벨로 승격됩니다:
|
|
616
|
-
|
|
617
|
-
| Level | 이름 | 설명 | 승격 조건 |
|
|
618
|
-
|-------|------|------|-----------|
|
|
619
|
-
| L0 | EventStore | 원본 이벤트 | 기본 저장 |
|
|
620
|
-
| L1 | Structured | 구조화된 패턴 | 3회 이상 접근 |
|
|
621
|
-
| L2 | Candidates | 검증된 스키마 | 5회 이상, 다중 세션 참조 |
|
|
622
|
-
| L3 | Verified | 교차 검증됨 | 높은 신뢰도 |
|
|
623
|
-
| L4 | Active | 활성 지식 | 10회 이상, 3개 이상 세션 |
|
|
624
|
-
|
|
625
|
-
## 매칭 신뢰도
|
|
626
|
-
|
|
627
|
-
검색 결과는 신뢰도에 따라 분류됩니다:
|
|
628
|
-
|
|
629
|
-
| 신뢰도 | 점수 | Gap | 동작 |
|
|
630
|
-
|--------|------|-----|------|
|
|
631
|
-
| **High** | ≥0.92 | ≥0.03 | 자동으로 컨텍스트에 포함 |
|
|
632
|
-
| **Suggested** | ≥0.75 | <0.03 | 대안 제시 |
|
|
633
|
-
| **None** | <0.75 | - | 매칭 없음 |
|
|
634
|
-
|
|
635
|
-
## Architecture
|
|
636
|
-
|
|
637
|
-
### System Overview
|
|
638
|
-
|
|
639
|
-
```
|
|
640
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
641
|
-
│ Claude Code Hooks │
|
|
642
|
-
│ SessionStart │ UserPromptSubmit │ Stop │ PostToolUse │ End │
|
|
643
|
-
└──────────────────────────┬──────────────────────────────────┘
|
|
644
|
-
│
|
|
645
|
-
▼
|
|
646
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
647
|
-
│ Memory Service │
|
|
648
|
-
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
649
|
-
│ │ Retriever │ │ Matcher │ │ Graduation │ │
|
|
650
|
-
│ │ Progressive│ │ Evidence │ │ L0 → L4 │ │
|
|
651
|
-
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
652
|
-
└──────────────────────────┬──────────────────────────────────┘
|
|
653
|
-
│
|
|
654
|
-
┌──────────────────┴──────────────────┐
|
|
655
|
-
▼ ▼
|
|
656
|
-
┌───────────────┐ ┌───────────────┐
|
|
657
|
-
│ EventStore │ ──── Outbox ────▶ │ VectorStore │
|
|
658
|
-
│ (DuckDB) │ (V2 Pattern) │ (LanceDB) │
|
|
659
|
-
└───────────────┘ └───────────────┘
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
### Entity-Edge Model (3-Layer)
|
|
663
|
-
|
|
664
|
-
```
|
|
665
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
666
|
-
│ edges │
|
|
667
|
-
│ ┌──────────┐ evidence_of ┌──────────┐ │
|
|
668
|
-
│ │ Entry │ ─────────────────▶│ Entity │ │
|
|
669
|
-
│ │ (Fact, │ │ (Task, │ │
|
|
670
|
-
│ │ Decision)│ │ Artifact)│ │
|
|
671
|
-
│ └──────────┘ └──────────┘ │
|
|
672
|
-
│ │ │ │
|
|
673
|
-
│ │ derived_from │ blocked_by │
|
|
674
|
-
│ ▼ ▼ │
|
|
675
|
-
│ ┌──────────┐ ┌──────────┐ │
|
|
676
|
-
│ │ Entry │ │ Entity │ │
|
|
677
|
-
│ └──────────┘ └──────────┘ │
|
|
678
|
-
└─────────────────────────────────────────────────────────────┘
|
|
679
|
-
```
|
|
680
|
-
|
|
681
|
-
### Progressive Disclosure (토큰 효율화)
|
|
682
|
-
|
|
683
|
-
```
|
|
684
|
-
Layer 1: Search Index (~50-100 tokens/result)
|
|
685
|
-
│ { id, summary, score }
|
|
686
|
-
│
|
|
687
|
-
└──▶ Layer 2: Timeline Context (~200 tokens)
|
|
688
|
-
│ 시간순 전후 맥락
|
|
689
|
-
│
|
|
690
|
-
└──▶ Layer 3: Full Details (~500-1000 tokens)
|
|
691
|
-
선택된 항목만 전체 로드
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
### MCP Integration
|
|
695
|
-
|
|
696
|
-
```
|
|
697
|
-
┌─────────────────────┐ ┌─────────────────────┐
|
|
698
|
-
│ Claude Desktop │◀────────│ claude-memory-layer │
|
|
699
|
-
│ (MCP Client) │ stdio │ (MCP Server) │
|
|
700
|
-
└─────────────────────┘ └──────────┬──────────┘
|
|
701
|
-
│
|
|
702
|
-
▼
|
|
703
|
-
┌─────────────────────┐
|
|
704
|
-
│ Shared Storage │
|
|
705
|
-
│ ~/.claude-code/ │
|
|
706
|
-
└─────────────────────┘
|
|
707
|
-
```
|
|
708
|
-
|
|
709
|
-
## AXIOMMIND 7 원칙
|
|
710
|
-
|
|
711
|
-
1. **Single Source of Truth**: DuckDB EventStore가 유일한 진실의 원천
|
|
712
|
-
2. **Append-Only**: 이벤트는 수정/삭제 없이 추가만
|
|
713
|
-
3. **Idempotency**: dedupe_key로 중복 이벤트 감지
|
|
714
|
-
4. **Evidence Alignment**: 주장이 실제 소스에 기반했는지 검증
|
|
715
|
-
5. **Entity-Based Tasks**: canonical_key로 일관된 엔티티 식별
|
|
716
|
-
6. **Vector Store Consistency**: DuckDB → LanceDB 단방향 흐름
|
|
717
|
-
7. **Standard JSON**: 모든 데이터는 이식 가능한 JSON 형식
|
|
718
|
-
|
|
719
|
-
## 저장 위치
|
|
720
|
-
|
|
721
|
-
메모리는 기본적으로 다음 위치에 저장됩니다:
|
|
722
|
-
|
|
723
|
-
```
|
|
724
|
-
~/.claude-code/memory/
|
|
725
|
-
├── events.duckdb # 이벤트 저장소
|
|
726
|
-
└── vectors/ # 벡터 임베딩
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
Claude Code 세션 기록 위치:
|
|
730
|
-
|
|
731
|
-
```
|
|
732
|
-
~/.claude/projects/<project-hash>/<session-id>.jsonl
|
|
733
|
-
```
|
|
734
|
-
|
|
735
|
-
## 개발
|
|
736
|
-
|
|
737
|
-
```bash
|
|
738
|
-
# 의존성 설치
|
|
739
|
-
npm install
|
|
740
|
-
|
|
741
|
-
# 빌드
|
|
742
|
-
npm run build
|
|
743
|
-
|
|
744
|
-
# 테스트
|
|
745
|
-
npm test
|
|
746
|
-
|
|
747
|
-
# 타입 체크
|
|
748
|
-
npm run typecheck
|
|
749
|
-
|
|
750
|
-
# 개발 모드 실행
|
|
751
|
-
npm run dev
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
## 기술 스택
|
|
755
|
-
|
|
756
|
-
- **DuckDB**: 이벤트 저장소 (append-only SQL)
|
|
757
|
-
- **LanceDB**: 벡터 저장소 (고성능 벡터 검색)
|
|
758
|
-
- **@xenova/transformers**: 로컬 임베딩 생성
|
|
759
|
-
- **Zod**: 런타임 타입 검증
|
|
760
|
-
- **Commander**: CLI 인터페이스
|
|
761
|
-
- **TypeScript**: 타입 안전한 코드
|
|
762
|
-
- **Bun**: HTTP 서버 (Web Viewer)
|
|
763
|
-
- **Hono**: 경량 라우터
|
|
764
|
-
- **MCP SDK**: Claude Desktop 통합
|
|
765
|
-
|
|
766
|
-
## Specification Documents
|
|
767
|
-
|
|
768
|
-
상세 설계 문서는 `specs/` 디렉토리에서 확인할 수 있습니다:
|
|
769
|
-
|
|
770
|
-
| 문서 | 설명 |
|
|
771
|
-
|------|------|
|
|
772
|
-
| [citations-system](specs/citations-system/spec.md) | 메모리 인용 시스템 |
|
|
773
|
-
| [endless-mode](specs/endless-mode/spec.md) | 연속 세션 모드 |
|
|
774
|
-
| [entity-edge-model](specs/entity-edge-model/spec.md) | 3-Layer 데이터 모델 |
|
|
775
|
-
| [evidence-aligner-v2](specs/evidence-aligner-v2/spec.md) | 증거 정렬 시스템 |
|
|
776
|
-
| [mcp-desktop-integration](specs/mcp-desktop-integration/spec.md) | MCP 서버 통합 |
|
|
777
|
-
| [post-tool-use-hook](specs/post-tool-use-hook/spec.md) | 도구 사용 기록 |
|
|
778
|
-
| [private-tags](specs/private-tags/spec.md) | 프라이버시 태그 |
|
|
779
|
-
| [progressive-disclosure](specs/progressive-disclosure/spec.md) | 토큰 효율화 검색 |
|
|
780
|
-
| [task-entity-system](specs/task-entity-system/spec.md) | Task Entity 관리 |
|
|
781
|
-
| [vector-outbox-v2](specs/vector-outbox-v2/spec.md) | Transactional Outbox |
|
|
782
|
-
| [web-viewer-ui](specs/web-viewer-ui/spec.md) | 웹 대시보드 |
|
|
783
|
-
|
|
784
|
-
## Roadmap
|
|
785
|
-
|
|
786
|
-
### Phase 1: Core (완료)
|
|
787
|
-
- [x] Event Store (DuckDB)
|
|
788
|
-
- [x] Vector Store (LanceDB)
|
|
789
|
-
- [x] Memory Graduation (L0→L4)
|
|
790
|
-
- [x] Evidence Alignment
|
|
791
|
-
- [x] History Import
|
|
792
|
-
|
|
793
|
-
### Phase 2: Advanced Features (진행 중)
|
|
794
|
-
- [ ] Citations System
|
|
795
|
-
- [ ] Endless Mode
|
|
796
|
-
- [ ] Entity-Edge Model
|
|
797
|
-
- [ ] Evidence Aligner V2
|
|
798
|
-
- [ ] Private Tags
|
|
799
|
-
|
|
800
|
-
### Phase 3: Integration
|
|
801
|
-
- [ ] MCP Desktop Integration
|
|
802
|
-
- [ ] Web Viewer UI
|
|
803
|
-
- [ ] PostToolUse Hook
|
|
804
|
-
- [ ] Progressive Disclosure
|
|
805
|
-
|
|
806
|
-
### Phase 4: Optimization
|
|
807
|
-
- [ ] Vector Outbox V2
|
|
808
|
-
- [ ] Task Entity System
|
|
809
|
-
- [ ] Performance Tuning
|
|
810
|
-
|
|
811
|
-
## License
|
|
812
|
-
|
|
813
|
-
MIT
|
|
814
|
-
|
|
815
|
-
## 2026-02-25T12:31:21.752Z | 4b1b77d6-27a5-4d41-8a7b-f4d6890d71ae
|
|
816
|
-
- type: session_summary
|
|
817
|
-
- session: import:organized
|
|
818
|
-
# Context: Claude Code Memory Plugin
|
|
819
|
-
|
|
820
|
-
## 1. 프로젝트 배경
|
|
821
|
-
|
|
822
|
-
이 문서는 Claude Code용 Memory Plugin 개발을 위한 배경 연구와 참조 자료를 정리합니다.
|
|
823
|
-
|
|
824
|
-
### 1.1 목표
|
|
825
|
-
|
|
826
|
-
사용자가 Claude Code를 사용할수록 더 똑똑해지는 Agent를 만들기 위한 플러그인 개발:
|
|
827
|
-
- 사용자 prompt와 agent 응답을 지속적으로 기억
|
|
828
|
-
- 새로운 prompt 입력 시 관련된 과거 기억을 검색하여 컨텍스트로 활용
|
|
829
|
-
- 시간이 지남에 따라 개인화된 경험 제공
|
|
830
|
-
|
|
831
|
-
---
|
|
832
|
-
|
|
833
|
-
## 2. Claude Code Plugin System 분석
|
|
834
|
-
|
|
835
|
-
### 2.1 플러그인 구조
|
|
836
|
-
|
|
837
|
-
```
|
|
838
|
-
plugin-name/
|
|
839
|
-
├── .claude-plugin/
|
|
840
|
-
│ └── plugin.json # 플러그인 메타데이터 (필수)
|
|
841
|
-
├── commands/ # 슬래시 명령어 (선택)
|
|
842
|
-
├── agents/ # 전문화된 에이전트 (선택)
|
|
843
|
-
├── skills/ # 에이전트 스킬 (선택)
|
|
844
|
-
├── hooks/ # 이벤트 핸들러 (선택)
|
|
845
|
-
├── .mcp.json # MCP 서버 구성 (선택)
|
|
846
|
-
└── README.md # 문서
|
|
847
|
-
```
|
|
848
|
-
|
|
849
|
-
### 2.2 사용 가능한 Hook 이벤트
|
|
850
|
-
|
|
851
|
-
| Hook Event | 용도 | Memory Plugin 활용 |
|
|
852
|
-
|------------|------|-------------------|
|
|
853
|
-
| `SessionStart` | 세션 시작 시 실행 | 이전 세션 기억 로드 |
|
|
854
|
-
| `SessionEnd` | 세션 종료 시 실행 | 현재 세션 기억 저장 |
|
|
855
|
-
| `UserPromptSubmit` | 사용자 입력 시 실행 | 관련 기억 검색 및 주입 |
|
|
856
|
-
| `PreToolUse` | 도구 실행 전 | 도구별 과거 사용 패턴 제공 |
|
|
857
|
-
| `PostToolUse` | 도구 실행 후 | 도구 결과 기억 |
|
|
858
|
-
| `Stop` | Agent 응답 완료 시 | 전체 대화 기억 저장 |
|
|
859
|
-
| `PreCompact` | 컨텍스트 압축 전 | 중요 기억 보존 |
|
|
860
|
-
|
|
861
|
-
### 2.3 Hook Input/Output 형식
|
|
862
|
-
|
|
863
|
-
```json
|
|
864
|
-
// UserPromptSubmit hook input
|
|
865
|
-
{
|
|
866
|
-
"session_id": "...",
|
|
867
|
-
"prompt": "사용자가 입력한 텍스트",
|
|
868
|
-
"timestamp": "..."
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
// Hook은 stdout으로 결과 반환
|
|
872
|
-
// - 빈 출력: 변경 없음
|
|
873
|
-
// - JSON 출력: 컨텍스트 주입 또는 수정
|
|
874
|
-
```
|
|
875
|
-
|
|
876
|
-
---
|
|
877
|
-
|
|
878
|
-
## 3. AI Memory System 연구
|
|
879
|
-
|
|
880
|
-
### 3.1 Memory의 종류
|
|
881
|
-
|
|
882
|
-
| 유형 | 설명 | 지속성 |
|
|
883
|
-
|------|------|--------|
|
|
884
|
-
| **Short-term Memory** | 현재 대화 컨텍스트 | 세션 내 |
|
|
885
|
-
| **Long-term Memory** | 사용자 선호도, 과거 인사이트 | 영구적 |
|
|
886
|
-
| **Episodic Memory** | 구체적인 대화/이벤트 기억 | 영구적 |
|
|
887
|
-
| **Semantic Memory** | 추출된 지식과 관계 | 영구적 |
|
|
888
|
-
|
|
889
|
-
### 3.2 주요 Memory 솔루션 비교
|
|
890
|
-
|
|
891
|
-
| 솔루션 | 특징 | 장점 |
|
|
892
|
-
|--------|------|------|
|
|
893
|
-
| **Mem0** | Y Combinator 투자, 그래프 기반 | 복잡한 관계 표현 |
|
|
894
|
-
| **LangChain Memory** | 프레임워크 내장 | 쉬운 통합 |
|
|
895
|
-
| **Zep/Graphiti** | 시간적 지식 그래프 | 시계열 추적 |
|
|
896
|
-
| **AWS AgentCore Memory** | 비동기 파이프라인 | 확장성 |
|
|
897
|
-
| **Google Vertex Memory Bank** | 유사도 검색 | 엔터프라이즈 |
|
|
898
|
-
|
|
899
|
-
### 3.3 Memory vs RAG
|
|
900
|
-
|
|
901
|
-
- **RAG**: 외부 문서에서 정보 검색 (stateless)
|
|
902
|
-
- **Memory**: 과거 상호작용에서 컨텍스트 검색 (stateful)
|
|
903
|
-
- **이 플러그인**: Memory 중심 + 선택적 RAG 통합
|
|
904
|
-
|
|
905
|
-
---
|
|
906
|
-
|
|
907
|
-
## 4. AXIOMMIND Memory System 참조
|
|
908
|
-
|
|
909
|
-
Gist에서 제공된 AXIOMMIND 시스템의 핵심 개념:
|
|
910
|
-
|
|
911
|
-
### 4.1 아키텍처 레이어
|
|
912
|
-
|
|
913
|
-
```
|
|
914
|
-
┌─────────────────────────────────────────────────────────┐
|
|
915
|
-
│ L0 EventStore (Single Source of Truth) │
|
|
916
|
-
│ - Append-only events table │
|
|
917
|
-
│ - Event deduplication via dedupe_key │
|
|
918
|
-
│ - Projection offset tracking │
|
|
919
|
-
└─────────────────────────────────────────────────────────┘
|
|
920
|
-
↓
|
|
921
|
-
┌─────────────────────────────────────────────────────────┐
|
|
922
|
-
│ Extraction/Sorting Layer (LLM Processing) │
|
|
923
|
-
│ - LLM extracts structured JSON from raw input │
|
|
924
|
-
│ - Evidence alignment and validation │
|
|
925
|
-
└─────────────────────────────────────────────────────────┘
|
|
926
|
-
↓
|
|
927
|
-
┌─────────────────────────────────────────────────────────┐
|
|
928
|
-
│ Derived Stores (Rebuildable from Events) │
|
|
929
|
-
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
930
|
-
│ │ DuckDB │ │ LanceDB │ │ Relational │ │
|
|
931
|
-
│ │ (FTS/SQL) │ │ (Vectors) │ │ Views │ │
|
|
932
|
-
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
933
|
-
└─────────────────────────────────────────────────────────┘
|
|
934
|
-
```
|
|
935
|
-
|
|
936
|
-
### 4.2 핵심 원칙
|
|
937
|
-
|
|
938
|
-
- **Append-only EventStore**: 모든 변경 추적, 파생 저장소에서 언제든 재구성 가능
|
|
939
|
-
- **Canonical Key 정규화**: 동일 개념의 여러 표현을 단일 키로 통합
|
|
940
|
-
- **단일 진실 공급원(SoT)**: events 테이블만 영구 저장, 나머지는 파생
|
|
941
|
-
- **멱등성 보장**: `dedupe_key`로 중복 이벤트 차단
|
|
942
|
-
|
|
943
|
-
### 4.3 Canonical Key 정규화 (핵심 알고리즘)
|
|
944
|
-
|
|
945
|
-
```python
|
|
946
|
-
# canonical_key.py - 결정론적 키 생성
|
|
947
|
-
def make_canonical_key(title: str, project: str = None) -> str:
|
|
948
|
-
"""
|
|
949
|
-
동일한 제목은 항상 동일한 키를 생성
|
|
950
|
-
|
|
951
|
-
정규화 단계:
|
|
952
|
-
1. NFKC 유니코드 정규화
|
|
953
|
-
2. 소문자 변환
|
|
954
|
-
3. 구두점 제거
|
|
955
|
-
4. 연속 공백 정리
|
|
956
|
-
5. (선택) 프로젝트/도메인 컨텍스트 추가
|
|
957
|
-
6. 긴 키는 MD5 체크섬으로 truncate
|
|
958
|
-
"""
|
|
959
|
-
import unicodedata
|
|
960
|
-
import re
|
|
961
|
-
import hashlib
|
|
962
|
-
|
|
963
|
-
# Step 1-4: 정규화
|
|
964
|
-
normalized = unicodedata.normalize('NFKC', title)
|
|
965
|
-
normalized = normalized.lower()
|
|
966
|
-
normalized = re.sub(r'[^\w\s]', '', normalized)
|
|
967
|
-
normalized = re.sub(r'\s+', ' ', normalized).strip()
|
|
968
|
-
|
|
969
|
-
# Step 5: 컨텍스트 추가
|
|
970
|
-
if project:
|
|
971
|
-
key = f"{project}::{normalized}"
|
|
972
|
-
else:
|
|
973
|
-
key = normalized
|
|
974
|
-
|
|
975
|
-
# Step 6: 긴 키 처리
|
|
976
|
-
MAX_KEY_LENGTH = 200
|
|
977
|
-
if len(key) > MAX_KEY_LENGTH:
|
|
978
|
-
hash_suffix = hashlib.md5(key.encode()).hexdigest()[:8]
|
|
979
|
-
key = key[:MAX_KEY_LENGTH - 9] + "_" + hash_suffix
|
|
980
|
-
|
|
981
|
-
return key
|
|
982
|
-
```
|
|
983
|
-
|
|
984
|
-
**Memory Plugin 적용**:
|
|
985
|
-
- 사용자 prompt의 canonical key로 중복 질문 감지
|
|
986
|
-
- 유사한 질문들을 그룹화하여 패턴 추출
|
|
987
|
-
|
|
988
|
-
### 4.4 Matching Thresholds (엄격한 매칭 기준)
|
|
989
|
-
|
|
990
|
-
```python
|
|
991
|
-
# task_matcher.py - 매칭 임계값
|
|
992
|
-
MATCH_THRESHOLDS = {
|
|
993
|
-
"min_combined_score": 0.92, # 최소 결합 점수
|
|
994
|
-
"min_gap": 0.03, # 1위와 2위 간 최소 점수 차이
|
|
995
|
-
"suggestion_threshold": 0.75, # 제안 모드 임계값
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
def calculate_weighted_score(result: SearchResult) -> float:
|
|
999
|
-
"""
|
|
1000
|
-
가중치 점수 계산 (stage, status, recency)
|
|
1001
|
-
"""
|
|
1002
|
-
weights = {
|
|
1003
|
-
"semantic_similarity": 0.4, # 벡터 유사도
|
|
1004
|
-
"fts_score": 0.25, # 전문 검색 점수
|
|
1005
|
-
"recency_bonus": 0.2, # 최신성 가산점
|
|
1006
|
-
"status_weight": 0.15, # 상태별 가중치
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
score = (
|
|
1010
|
-
result.vector_score * weights["semantic_similarity"] +
|
|
1011
|
-
result.fts_score * weights["fts_score"] +
|
|
1012
|
-
result.recency_score * weights["recency_bonus"] +
|
|
1013
|
-
result.status_score * weights["status_weight"]
|
|
1014
|
-
)
|
|
1015
|
-
return score
|
|
1016
|
-
|
|
1017
|
-
def match_with_confidence(query: str, candidates: list) -> MatchResult:
|
|
1018
|
-
"""
|
|
1019
|
-
엄격한 매칭: top-1이 확실히 우세할 때만 확정
|
|
1020
|
-
"""
|
|
1021
|
-
if len(candidates) == 0:
|
|
1022
|
-
return MatchResult(match=None, confidence="none")
|
|
1023
|
-
|
|
1024
|
-
top = candidates[0]
|
|
1025
|
-
|
|
1026
|
-
if top.score < MATCH_THRESHOLDS["suggestion_threshold"]:
|
|
1027
|
-
return MatchResult(match=None, confidence="none")
|
|
1028
|
-
|
|
1029
|
-
if top.score >= MATCH_THRESHOLDS["min_combined_score"]:
|
|
1030
|
-
if len(candidates) == 1:
|
|
1031
|
-
return MatchResult(match=top, confidence="high")
|
|
1032
|
-
|
|
1033
|
-
gap = top.score - candidates[1].score
|
|
1034
|
-
if gap >= MATCH_THRESHOLDS["min_gap"]:
|
|
1035
|
-
return MatchResult(match=top, confidence="high")
|
|
1036
|
-
|
|
1037
|
-
# 점수가 높지만 확실하지 않음 → 제안 모드
|
|
1038
|
-
return MatchResult(match=top, confidence="suggested")
|
|
1039
|
-
```
|
|
1040
|
-
|
|
1041
|
-
**Memory Plugin 적용**:
|
|
1042
|
-
- 관련 기억 검색 시 엄격한 임계값 적용
|
|
1043
|
-
- 애매한 매칭은 "suggested" 상태로 표시
|
|
1044
|
-
|
|
1045
|
-
### 4.5 Single-Writer Pattern (벡터 동시성 제어)
|
|
1046
|
-
|
|
1047
|
-
```python
|
|
1048
|
-
# vector_worker.py - Outbox 패턴으로 동시성 제어
|
|
1049
|
-
|
|
1050
|
-
"""
|
|
1051
|
-
LanceDB는 동시 쓰기에 취약하므로 Single-Writer 패턴 사용:
|
|
1052
|
-
1. 이벤트 저장 시 embedding_outbox 테이블에 작업 추가
|
|
1053
|
-
2. 별도 워커가 outbox를 순차적으로 처리
|
|
1054
|
-
3. 처리 완료 시 outbox에서 삭제
|
|
1055
|
-
"""
|
|
1056
|
-
|
|
1057
|
-
# DuckDB의 outbox 테이블
|
|
1058
|
-
CREATE TABLE embedding_outbox (
|
|
1059
|
-
id UUID PRIMARY KEY,
|
|
1060
|
-
event_id UUID NOT NULL,
|
|
1061
|
-
content TEXT NOT NULL,
|
|
1062
|
-
status VARCHAR DEFAULT 'pending', -- 'pending' | 'processing' | 'done'
|
|
1063
|
-
created_at TIMESTAMP DEFAULT NOW(),
|
|
1064
|
-
processed_at TIMESTAMP
|
|
1065
|
-
);
|
|
1066
|
-
|
|
1067
|
-
# Python 워커 (단일 프로세스)
|
|
1068
|
-
class VectorWorker:
|
|
1069
|
-
def __init__(self, db: DuckDB, lance: LanceDB, embedder: Embedder):
|
|
1070
|
-
self.db = db
|
|
1071
|
-
self.lance = lance
|
|
1072
|
-
self.embedder = embedder
|
|
1073
|
-
|
|
1074
|
-
async def process_outbox(self, batch_size: int = 32):
|
|
1075
|
-
"""
|
|
1076
|
-
Outbox에서 pending 항목을 가져와 순차 처리
|
|
1077
|
-
"""
|
|
1078
|
-
# 1. Pending 항목 가져오기 (락 획득)
|
|
1079
|
-
pending = self.db.execute("""
|
|
1080
|
-
UPDATE embedding_outbox
|
|
1081
|
-
SET status = 'processing'
|
|
1082
|
-
WHERE id IN (
|
|
1083
|
-
SELECT id FROM embedding_outbox
|
|
1084
|
-
WHERE status = 'pending'
|
|
1085
|
-
ORDER BY created_at
|
|
1086
|
-
LIMIT ?
|
|
1087
|
-
)
|
|
1088
|
-
RETURNING *
|
|
1089
|
-
""", [batch_size])
|
|
1090
|
-
|
|
1091
|
-
if not pending:
|
|
1092
|
-
return
|
|
1093
|
-
|
|
1094
|
-
# 2. 배치 임베딩 생성
|
|
1095
|
-
contents = [p.content for p in pending]
|
|
1096
|
-
vectors = await self.embedder.embed_batch(contents)
|
|
1097
|
-
|
|
1098
|
-
# 3. LanceDB에 저장 (단일 쓰기)
|
|
1099
|
-
records = [
|
|
1100
|
-
{"event_id": p.event_id, "content": p.content, "vector": v}
|
|
1101
|
-
for p, v in zip(pending, vectors)
|
|
1102
|
-
]
|
|
1103
|
-
self.lance.add(records)
|
|
1104
|
-
|
|
1105
|
-
# 4. Outbox 정리
|
|
1106
|
-
ids = [p.id for p in pending]
|
|
1107
|
-
self.db.execute("""
|
|
1108
|
-
DELETE FROM embedding_outbox WHERE id = ANY(?)
|
|
1109
|
-
""", [ids])
|
|
1110
|
-
```
|
|
1111
|
-
|
|
1112
|
-
**Memory Plugin 적용**:
|
|
1113
|
-
- 대화 저장 시 즉시 반환, 임베딩은 비동기 처리
|
|
1114
|
-
- 동시성 문제 없이 안정적인 벡터 인덱싱
|
|
1115
|
-
|
|
1116
|
-
### 4.6 Blocker/Condition 분류 전략
|
|
1117
|
-
|
|
1118
|
-
```python
|
|
1119
|
-
# task_resolver.py - 애매한 참조 처리
|
|
1120
|
-
|
|
1121
|
-
"""
|
|
1122
|
-
Blocker 분류 전략:
|
|
1123
|
-
1. Artifact: URL, Jira, GitHub 이슈 등 명확한 참조
|
|
1124
|
-
2. Task: 엄격한 매칭만 허용 (score >= 0.92)
|
|
1125
|
-
3. Condition: 애매한 참조 흡수 (나중에 해결 가능)
|
|
1126
|
-
"""
|
|
1127
|
-
|
|
1128
|
-
class BlockerType(Enum):
|
|
1129
|
-
ARTIFACT = "artifact" # 명확한 외부 참조
|
|
1130
|
-
TASK = "task" # 확정된 작업 참조
|
|
1131
|
-
CONDITION = "condition" # 애매한 조건/참조
|
|
1132
|
-
|
|
1133
|
-
def classify_blocker(reference: str, match_result: MatchResult) -> BlockerType:
|
|
1134
|
-
# URL, 이슈 번호 등은 Artifact
|
|
1135
|
-
if is_artifact_reference(reference):
|
|
1136
|
-
return BlockerType.ARTIFACT
|
|
1137
|
-
|
|
1138
|
-
# 높은 신뢰도 매칭은 Task
|
|
1139
|
-
if match_result.confidence == "high":
|
|
1140
|
-
return BlockerType.TASK
|
|
1141
|
-
|
|
1142
|
-
# 나머지는 Condition으로 흡수
|
|
1143
|
-
return BlockerType.CONDITION
|
|
1144
|
-
|
|
1145
|
-
# Condition은 나중에 실제 Task로 해결될 수 있음
|
|
1146
|
-
# resolves_to edge로 연결
|
|
1147
|
-
```
|
|
1148
|
-
|
|
1149
|
-
**Memory Plugin 적용**:
|
|
1150
|
-
- 불완전한 컨텍스트도 일단 저장
|
|
1151
|
-
- 나중에 추가 정보로 보강 가능
|
|
1152
|
-
|
|
1153
|
-
### 4.7 Query Patterns (효과적인 뷰 활용)
|
|
1154
|
-
|
|
1155
|
-
```sql
|
|
1156
|
-
-- v_task_blockers_effective: Condition 해결을 반영한 최종 blocker 뷰
|
|
1157
|
-
CREATE VIEW v_memory_context_effective AS
|
|
1158
|
-
SELECT
|
|
1159
|
-
m.id,
|
|
1160
|
-
m.session_id,
|
|
1161
|
-
m.content,
|
|
1162
|
-
m.event_type,
|
|
1163
|
-
m.timestamp,
|
|
1164
|
-
-- Condition이 해결된 경우 실제 참조로 대체
|
|
1165
|
-
COALESCE(r.resolved_content, m.content) as effective_content,
|
|
1166
|
-
COALESCE(r.resolved_id, m.id) as effective_id
|
|
1167
|
-
FROM memories m
|
|
1168
|
-
LEFT JOIN memory_resolutions r ON m.id = r.condition_id
|
|
1169
|
-
WHERE r.resolution_type IS NULL OR r.resolution_type = 'confirmed';
|
|
1170
|
-
|
|
1171
|
-
-- 4가지 주요 쿼리 패턴
|
|
1172
|
-
-- 1. 확정된 관련 기억
|
|
1173
|
-
SELECT * FROM v_memory_context_effective
|
|
1174
|
-
WHERE semantic_score >= 0.92;
|
|
1175
|
-
|
|
1176
|
-
-- 2. 제안 상태의 기억 (확인 대기)
|
|
1177
|
-
SELECT * FROM memories
|
|
1178
|
-
WHERE match_confidence = 'suggested';
|
|
1179
|
-
|
|
1180
|
-
-- 3. 자동 플레이스홀더 감지
|
|
1181
|
-
SELECT * FROM memories
|
|
1182
|
-
WHERE auto_placeholder = true;
|
|
1183
|
-
|
|
1184
|
-
-- 4. 해결된 조건 매핑
|
|
1185
|
-
SELECT condition_id, resolved_to_id
|
|
1186
|
-
FROM memory_resolutions
|
|
1187
|
-
WHERE resolution_type = 'confirmed';
|
|
1188
|
-
```
|
|
1189
|
-
|
|
1190
|
-
### 4.8 Placeholder 자동 생성
|
|
1191
|
-
|
|
1192
|
-
```python
|
|
1193
|
-
# 정보가 불완전할 때 플레이스홀더 생성
|
|
1194
|
-
def create_placeholder_if_needed(event: MemoryEvent) -> Optional[Placeholder]:
|
|
1195
|
-
"""
|
|
1196
|
-
컨텍스트가 불완전하면 자동 플레이스홀더 생성
|
|
1197
|
-
- auto_placeholder=true 플래그 설정
|
|
1198
|
-
- 나중에 추가 정보로 해결 가능
|
|
1199
|
-
"""
|
|
1200
|
-
if is_incomplete_context(event):
|
|
1201
|
-
return Placeholder(
|
|
1202
|
-
id=generate_uuid(),
|
|
1203
|
-
event_id=event.id,
|
|
1204
|
-
placeholder_type="unknown_context",
|
|
1205
|
-
auto_placeholder=True,
|
|
1206
|
-
created_at=datetime.now()
|
|
1207
|
-
)
|
|
1208
|
-
return None
|
|
1209
|
-
```
|
|
1210
|
-
|
|
1211
|
-
### 4.9 주요 모듈 요약
|
|
1212
|
-
|
|
1213
|
-
| 모듈 | 역할 | Memory Plugin 대응 |
|
|
1214
|
-
|------|------|-------------------|
|
|
1215
|
-
| `canonical_key.py` | 결정론적 키 정규화 | `normalizer.ts` |
|
|
1216
|
-
| `event_store.py` | append-only 이벤트 저장 | `event-store.ts` |
|
|
1217
|
-
| `task_matcher.py` | 가중치 기반 매칭 | `matcher.ts` |
|
|
1218
|
-
| `task_resolver.py` | 상태 전이 검증 | `resolver.ts` |
|
|
1219
|
-
| `projector_task.py` | 이벤트→엔티티 투영 | `projector.ts` |
|
|
1220
|
-
| `vector_worker.py` | 단일 쓰기 임베딩 | `vector-worker.ts` |
|
|
1221
|
-
|
|
1222
|
-
### 4.10 Memory Graduation Pipeline (L0 → L4)
|
|
1223
|
-
|
|
1224
|
-
AXIOMMIND의 핵심 개념인 **다단계 메모리 승격 파이프라인**:
|
|
1225
|
-
|
|
1226
|
-
```
|
|
1227
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
1228
|
-
│ Memory Graduation Pipeline │
|
|
1229
|
-
├─────────────────────────────────────────────────────────────────┤
|
|
1230
|
-
│ │
|
|
1231
|
-
│ L0: EventStore (Raw) │
|
|
1232
|
-
│ ├── 원본 채팅 로그, 프롬프트/응답 │
|
|
1233
|
-
│ ├── Append-only, 불변 │
|
|
1234
|
-
│ └── dedupe_key로 멱등성 보장 │
|
|
1235
|
-
│ ↓ │
|
|
1236
|
-
│ L1: Structured JSON │
|
|
1237
|
-
│ ├── LLM이 추출한 구조화된 데이터 │
|
|
1238
|
-
│ ├── 엔티티, 관계, 인사이트 │
|
|
1239
|
-
│ └── EvidenceAligner로 증거 스팬 정렬 │
|
|
1240
|
-
│ ↓ │
|
|
1241
|
-
│ L2: Idris Candidates (검증 대상) │
|
|
1242
|
-
│ ├── 타입 안전한 표현으로 변환 │
|
|
1243
|
-
│ ├── 의존적 타입으로 불변식 검증 │
|
|
1244
|
-
│ └── idris_generator.py가 생성 │
|
|
1245
|
-
│ ↓ │
|
|
1246
|
-
│ L3: Verified Knowledge │
|
|
1247
|
-
│ ├── Idris 타입체커 통과 │
|
|
1248
|
-
│ ├── 모순 없음 확인 │
|
|
1249
|
-
│ └── 신뢰도 높은 지식 │
|
|
1250
|
-
│ ↓ │
|
|
1251
|
-
│ L4: Active Memory (검색 가능) │
|
|
1252
|
-
│ ├── 벡터 인덱싱 완료 │
|
|
1253
|
-
│ ├── 실시간 검색 가능 │
|
|
1254
|
-
│ └── 컨텍스트 주입에 사용 │
|
|
1255
|
-
│ │
|
|
1256
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
1257
|
-
```
|
|
1258
|
-
|
|
1259
|
-
**Memory Plugin 적용**:
|
|
1260
|
-
- L0: 모든 대화를 `events` 테이블에 저장
|
|
1261
|
-
- L1: 주기적으로 인사이트 추출 (LLM 기반)
|
|
1262
|
-
- L2: TypeScript 강타입으로 검증 (Idris2 개념 적용)
|
|
1263
|
-
- L3: 테스트 통과한 검증된 지식
|
|
1264
|
-
- L4: LanceDB에 인덱싱되어 검색 가능한 상태
|
|
1265
|
-
|
|
1266
|
-
### 4.11 AXIOMMIND 7가지 필수 원칙
|
|
1267
|
-
|
|
1268
|
-
| # | 원칙 | 설명 | Memory Plugin 적용 |
|
|
1269
|
-
|---|------|------|-------------------|
|
|
1270
|
-
| 1 | **진실의 원천(SoT)은 이벤트 로그** | 파생 테이블은 언제든 재구성 가능 | `events` 테이블만 영구 저장 |
|
|
1271
|
-
| 2 | **추가전용 구조** | events에 UPDATE/DELETE 금지 | `append()` 메서드만 제공 |
|
|
1272
|
-
| 3 | **멱등성 보장** | `dedupe_key`로 중복 제어 | content_hash + session_id |
|
|
1273
|
-
| 4 | **증거 범위는 파이프라인이 확정** | LLM은 인용문만, aligner가 스팬 계산 | `EvidenceAligner` 모듈 |
|
|
1274
|
-
| 5 | **Task는 엔티티** | 세션마다 새 항목 아닌 기존 업데이트 | `canonical_key`로 동일성 판단 |
|
|
1275
|
-
| 6 | **벡터 저장소 정합성** | DuckDB → outbox → LanceDB 단방향 | Single-Writer Pattern |
|
|
1276
|
-
| 7 | **DuckDB JSON 사용** | JSONB 제거, 표준 JSON만 | `metadata JSON` 컬럼 |
|
|
1277
|
-
|
|
1278
|
-
```typescript
|
|
1279
|
-
// 원칙 적용 예시: EventStore 인터페이스
|
|
1280
|
-
interface EventStoreInterface {
|
|
1281
|
-
// 원칙 2: 추가전용 - append만 허용
|
|
1282
|
-
append(event: MemoryEvent): Promise<AppendResult>;
|
|
1283
|
-
|
|
1284
|
-
// 조회는 자유롭게
|
|
1285
|
-
getBySession(sessionId: string): Promise<MemoryEvent[]>;
|
|
1286
|
-
getRecent(limit: number): Promise<MemoryEvent[]>;
|
|
1287
|
-
|
|
1288
|
-
// 원칙 2 위반: UPDATE/DELETE 메서드 없음
|
|
1289
|
-
// update(): ❌ 금지
|
|
1290
|
-
// delete(): ❌ 금지
|
|
1291
|
-
}
|
|
1292
|
-
```
|
|
1293
|
-
|
|
1294
|
-
### 4.12 Evidence Aligner (증거 정렬기)
|
|
1295
|
-
|
|
1296
|
-
```python
|
|
1297
|
-
# evidence_aligner.py - LLM 인용문을 정확한 스팬으로 변환
|
|
1298
|
-
|
|
1299
|
-
class EvidenceAligner:
|
|
1300
|
-
"""
|
|
1301
|
-
원칙 4: LLM은 인용문만 제공, aligner가 정확한 스팬 계산
|
|
1302
|
-
|
|
1303
|
-
LLM이 추출한 대략적인 인용문을 원본 텍스트에서
|
|
1304
|
-
정확한 (start, end) 위치로 변환
|
|
1305
|
-
"""
|
|
1306
|
-
|
|
1307
|
-
def align(
|
|
1308
|
-
self,
|
|
1309
|
-
source_text: str,
|
|
1310
|
-
llm_quote: str,
|
|
1311
|
-
fuzzy_threshold: float = 0.85
|
|
1312
|
-
) -> Optional[EvidenceSpan]:
|
|
1313
|
-
"""
|
|
1314
|
-
1. 정확한 매칭 시도
|
|
1315
|
-
2. 실패 시 fuzzy matching (Levenshtein)
|
|
1316
|
-
3. 임계값 미달 시 None 반환
|
|
1317
|
-
"""
|
|
1318
|
-
# 정확한 매칭
|
|
1319
|
-
exact_pos = source_text.find(llm_quote)
|
|
1320
|
-
if exact_pos >= 0:
|
|
1321
|
-
return EvidenceSpan(
|
|
1322
|
-
start=exact_pos,
|
|
1323
|
-
end=exact_pos + len(llm_quote),
|
|
1324
|
-
confidence=1.0,
|
|
1325
|
-
match_type="exact"
|
|
1326
|
-
)
|
|
1327
|
-
|
|
1328
|
-
# Fuzzy 매칭
|
|
1329
|
-
best_match = self._fuzzy_search(source_text, llm_quote)
|
|
1330
|
-
if best_match and best_match.score >= fuzzy_threshold:
|
|
1331
|
-
return EvidenceSpan(
|
|
1332
|
-
start=best_match.start,
|
|
1333
|
-
end=best_match.end,
|
|
1334
|
-
confidence=best_match.score,
|
|
1335
|
-
match_type="fuzzy"
|
|
1336
|
-
)
|
|
1337
|
-
|
|
1338
|
-
return None
|
|
1339
|
-
|
|
1340
|
-
def _fuzzy_search(self, text: str, query: str) -> Optional[FuzzyMatch]:
|
|
1341
|
-
# 슬라이딩 윈도우 + Levenshtein 거리
|
|
1342
|
-
...
|
|
1343
|
-
```
|
|
1344
|
-
|
|
1345
|
-
**Memory Plugin 적용**:
|
|
1346
|
-
- 사용자가 "이전에 rate limiting 얘기했잖아"라고 하면
|
|
1347
|
-
- LLM이 대략적인 인용문 추출
|
|
1348
|
-
- EvidenceAligner가 정확한 원본 위치 찾기
|
|
1349
|
-
- 해당 컨텍스트를 정확히 주입
|
|
1350
|
-
|
|
1351
|
-
### 5.1 Vector Database: LanceDB
|
|
1352
|
-
|
|
1353
|
-
선택 이유:
|
|
1354
|
-
- **Embedded 모드**: SQLite처럼 서버 없이 로컬 실행
|
|
1355
|
-
- **Apache Arrow 기반**: 빠른 디스크 접근
|
|
1356
|
-
- **다중 모달 지원**: 텍스트, 이미지, 오디오 임베딩
|
|
1357
|
-
- **DuckDB 호환**: SQL 쿼리 가능
|
|
1358
|
-
|
|
1359
|
-
```python
|
|
1360
|
-
import lancedb
|
|
1361
|
-
|
|
1362
|
-
db = lancedb.connect("~/.claude-memory")
|
|
1363
|
-
table = db.create_table("conversations", data)
|
|
1364
|
-
results = table.search(query_embedding).limit(10).to_list()
|
|
1365
|
-
```
|
|
1366
|
-
|
|
1367
|
-
### 5.2 관계형 저장소: DuckDB
|
|
1368
|
-
|
|
1369
|
-
선택 이유:
|
|
1370
|
-
- **임베디드**: 파일 기반, 서버 불필요
|
|
1371
|
-
- **분석 최적화**: OLAP 워크로드에 적합
|
|
1372
|
-
- **SQL 지원**: 친숙한 쿼리 언어
|
|
1373
|
-
- **Lance 포맷 호환**: LanceDB와 통합
|
|
1374
|
-
|
|
1375
|
-
### 5.3 Embedding Model
|
|
1376
|
-
|
|
1377
|
-
옵션:
|
|
1378
|
-
1. **OpenAI text-embedding-3-small**: 고품질, API 비용
|
|
1379
|
-
2. **sentence-transformers**: 로컬 실행, 무료
|
|
1380
|
-
3. **Ollama embeddings**: 로컬 LLM 활용
|
|
1381
|
-
|
|
1382
|
-
권장: sentence-transformers (로컬 우선) + OpenAI fallback
|
|
1383
|
-
|
|
1384
|
-
---
|
|
1385
|
-
|
|
1386
|
-
## 6. Idris2 활용 고려사항
|
|
1387
|
-
|
|
1388
|
-
### 6.1 Idris2 개요
|
|
1389
|
-
|
|
1390
|
-
- **의존적 타입 시스템**: 타입 수준에서 프로그램 검증
|
|
1391
|
-
- **Type-Driven Development**: 타입이 프로그램 설계를 가이드
|
|
1392
|
-
- **Quantitative Type Theory (QTT)**: 선형 타입 지원
|
|
1393
|
-
|
|
1394
|
-
### 6.2 적용 가능 영역
|
|
1395
|
-
|
|
1396
|
-
1. **타입 안전한 이벤트 스키마**
|
|
1397
|
-
```idris
|
|
1398
|
-
data MemoryEvent : Type where
|
|
1399
|
-
UserPrompt : (sessionId : String) -> (content : String) -> MemoryEvent
|
|
1400
|
-
AgentResponse : (sessionId : String) -> (content : String) -> MemoryEvent
|
|
1401
|
-
```
|
|
1402
|
-
|
|
1403
|
-
2. **불변성 보장**
|
|
1404
|
-
- Append-only EventStore의 불변성을 타입 수준에서 강제
|
|
1405
|
-
|
|
1406
|
-
3. **정확성 증명**
|
|
1407
|
-
- 중복 제거 로직의 정확성 검증
|
|
1408
|
-
- 검색 알고리즘의 속성 증명
|
|
1409
|
-
|
|
1410
|
-
### 6.3 실용적 접근
|
|
1411
|
-
|
|
1412
|
-
Idris2를 직접 사용하기보다 **개념적 영감**으로 활용:
|
|
1413
|
-
- TypeScript의 강타입 시스템 적극 활용
|
|
1414
|
-
- Zod/io-ts로 런타임 타입 검증
|
|
1415
|
-
- 불변 데이터 구조 (Immutable.js 또는 순수 함수형 패턴)
|
|
1416
|
-
|
|
1417
|
-
---
|
|
1418
|
-
|
|
1419
|
-
## 7. 참조 링크
|
|
1420
|
-
|
|
1421
|
-
### Claude Code Plugin 개발
|
|
1422
|
-
- [Create plugins - Claude Code Docs](https://code.claude.com/docs/en/plugins)
|
|
1423
|
-
- [Claude Code Plugins README](https://github.com/anthropics/claude-code/blob/main/plugins/README.md)
|
|
1424
|
-
- [Hook Development SKILL](https://github.com/anthropics/claude-code/blob/main/plugins/plugin-dev/skills/hook-development/SKILL.md)
|
|
1425
|
-
- [Claude Code Plugins Complete Guide](https://jangwook.net/en/blog/en/claude-code-plugins-complete-guide/)
|
|
1426
|
-
|
|
1427
|
-
### AI Memory Systems
|
|
1428
|
-
- [Mem0: Building Production-Ready AI Agents](https://arxiv.org/pdf/2504.19413)
|
|
1429
|
-
- [AWS AgentCore Long-term Memory](https://aws.amazon.com/blogs/machine-learning/building-smarter-ai-agents-agentcore-long-term-memory-deep-dive/)
|
|
1430
|
-
- [Google Vertex AI Memory Bank](https://docs.cloud.google.com/agent-builder/agent-engine/memory-bank/overview)
|
|
1431
|
-
- [LangChain Conversational Memory](https://www.pinecone.io/learn/series/langchain/langchain-conversational-memory/)
|
|
1432
|
-
|
|
1433
|
-
### Vector Databases
|
|
1434
|
-
- [LanceDB](https://lancedb.com/)
|
|
1435
|
-
- [Lance Format on GitHub](https://github.com/lance-format/lance)
|
|
1436
|
-
|
|
1437
|
-
### Idris2
|
|
1438
|
-
- [Idris2 Official Site](https://www.idris-lang.org/)
|
|
1439
|
-
- [Idris 2: Quantitative Type Theory in Practice](https://arxiv.org/abs/2104.00480)
|
|
1440
|
-
- [Idris2 GitHub](https://github.com/idris-lang/Idris2)
|
|
1441
|
-
|
|
1442
|
-
---
|
|
1443
|
-
|
|
1444
|
-
## 8. 용어 정의
|
|
1445
|
-
|
|
1446
|
-
| 용어 | 정의 |
|
|
1447
|
-
|------|------|
|
|
1448
|
-
| **Memory** | 과거 대화에서 추출/저장된 정보 |
|
|
1449
|
-
| **Embedding** | 텍스트를 벡터로 변환한 표현 |
|
|
1450
|
-
| **Semantic Search** | 의미 기반 유사도 검색 |
|
|
1451
|
-
| **EventStore** | 모든 이벤트를 시간순으로 저장하는 append-only 저장소 |
|
|
1452
|
-
| **Hook** | 특정 이벤트 발생 시 실행되는 스크립트 |
|
|
1453
|
-
| **MCP** | Model Context Protocol - Claude와 외부 도구 연결 |
|
|
1454
|
-
|
|
1455
|
-
## 2026-02-25T12:31:21.755Z | 235651b6-564e-4b06-8fa5-48a5e946455a
|
|
1456
|
-
- type: session_summary
|
|
1457
|
-
- session: import:organized
|
|
1458
|
-
# memU Adoption Notes (claude-memory-layer)
|
|
1459
|
-
|
|
1460
|
-
이 프로젝트에 적용된 memU 장점 요약입니다.
|
|
1461
|
-
|
|
1462
|
-
## 1) Dual Retrieval Strategy
|
|
1463
|
-
- `strategy: "fast" | "deep" | "auto"`
|
|
1464
|
-
- `fast`: 키워드 기반(FTS/keyword) 우선 탐색으로 저지연 검색
|
|
1465
|
-
- `deep`: 임베딩 + 벡터 검색 + 재정렬(키워드 오버랩 가중)로 정밀 검색
|
|
1466
|
-
|
|
1467
|
-
## 2) Scoped Retrieval Filters
|
|
1468
|
-
`scope`로 검색 범위를 좁혀 정확도를 높입니다.
|
|
1469
|
-
|
|
1470
|
-
- `sessionId` / `sessionIdPrefix`
|
|
1471
|
-
- `eventTypes`
|
|
1472
|
-
- `canonicalKeyPrefix`
|
|
1473
|
-
- `contentIncludes` (부분 문자열 OR)
|
|
1474
|
-
- `metadata` (dot-path, 예: `scope.project.id`)
|
|
1475
|
-
|
|
1476
|
-
## 3) Hybrid Rerank Behavior
|
|
1477
|
-
`rerankWithKeyword=true`일 때 semantic score에 키워드 오버랩/최근성 점수를 가중해 재정렬합니다.
|
|
1478
|
-
|
|
1479
|
-
## 4) Test Coverage
|
|
1480
|
-
- `tests/retriever.memu-adoption.test.ts`
|
|
1481
|
-
- metadata dot-path 스코프 필터
|
|
1482
|
-
- fast 전략 키워드 경로
|
|
1483
|
-
- `tests/retriever-strategy-scope.test.ts`
|
|
1484
|
-
- fast/deep 전략 및 복합 스코프 필터
|
|
1485
|
-
|
|
1486
|
-
## Quick Example
|
|
1487
|
-
```ts
|
|
1488
|
-
await retriever.retrieve('브리핑', {
|
|
1489
|
-
strategy: 'deep',
|
|
1490
|
-
topK: 10,
|
|
1491
|
-
scope: {
|
|
1492
|
-
sessionIdPrefix: 'agent:main:',
|
|
1493
|
-
canonicalKeyPrefix: 'pref/briefing',
|
|
1494
|
-
metadata: { 'scope.project.id': 'alpha' }
|
|
1495
|
-
}
|
|
1496
|
-
});
|
|
1497
|
-
```
|
|
1498
|
-
|
|
1499
|
-
## 2026-02-25T12:31:21.756Z | 50c73261-3d2b-490d-ad69-3a4c68cff7c9
|
|
1500
|
-
- type: session_summary
|
|
1501
|
-
- session: import:organized
|
|
1502
|
-
# Operations Runbook
|
|
1503
|
-
|
|
1504
|
-
## Health scripts
|
|
1505
|
-
|
|
1506
|
-
- `npm run ops:sync-gap:report`
|
|
1507
|
-
- `npm run ops:sync-gap:fix`
|
|
1508
|
-
- `npm run ops:sync-gap:heal`
|
|
1509
|
-
- `npm run ops:review:resolve`
|
|
1510
|
-
- `npm run ops:heartbeat`
|
|
1511
|
-
|
|
1512
|
-
## Status policy
|
|
1513
|
-
|
|
1514
|
-
- `ok`: no failed outbox items and no un-leveled events after heal
|
|
1515
|
-
- `needs-attention`: failed outbox remains or level sync still broken
|
|
1516
|
-
|
|
1517
|
-
## Notes
|
|
1518
|
-
|
|
1519
|
-
These scripts are best-effort operational automation for Claude memory DB (`~/.claude-code/memory/events.sqlite`).
|
|
1520
|
-
|
|
1521
|
-
## 2026-02-25T12:31:26.190Z | 6813c625-f6f1-44bf-8758-088cf3ba1434
|
|
1522
|
-
- type: session_summary
|
|
1523
|
-
- session: import:organized
|
|
1524
|
-
# Implementation Plan: Claude Code Memory Plugin
|
|
1525
|
-
|
|
1526
|
-
## 1. 개발 단계 개요
|
|
1527
|
-
|
|
1528
|
-
AXIOMMIND 파이프라인 구현 단계에 맞춰 구성:
|
|
1529
|
-
|
|
1530
|
-
```
|
|
1531
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
1532
|
-
│ P0: 필수 품질 (Must Have) │
|
|
1533
|
-
│ ├── EventStore (append-only, dedupe) │
|
|
1534
|
-
│ ├── EvidenceAligner (증거 스팬 정렬) │
|
|
1535
|
-
│ ├── Task Entity System (canonical_key) │
|
|
1536
|
-
│ ├── Vector Outbox (single-writer) │
|
|
1537
|
-
│ ├── Basic Hooks (SessionStart, Stop) │
|
|
1538
|
-
│ └── CLI 기본 명령어 │
|
|
1539
|
-
├─────────────────────────────────────────────────────────────────┤
|
|
1540
|
-
│ P1: 운영 (Operations) │
|
|
1541
|
-
│ ├── build_runs 테이블 (파이프라인 실행 추적) │
|
|
1542
|
-
│ ├── conflict_ledger (충돌 기록) │
|
|
1543
|
-
│ ├── decision_ledger (의사결정 기록) │
|
|
1544
|
-
│ ├── 메트릭 스켈레톤 │
|
|
1545
|
-
│ └── 에러 복구 메커니즘 │
|
|
1546
|
-
├─────────────────────────────────────────────────────────────────┤
|
|
1547
|
-
│ P2: 검색 (Retrieval) │
|
|
1548
|
-
│ ├── 하이브리드 검색 (Vector + FTS) │
|
|
1549
|
-
│ ├── 골드셋 평가 시스템 │
|
|
1550
|
-
│ ├── 인사이트 추출 (LLM 기반) │
|
|
1551
|
-
│ └── L2→L3→L4 승격 파이프라인 │
|
|
1552
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
1553
|
-
```
|
|
1554
|
-
|
|
1555
|
-
### 구현 Phase 매핑
|
|
1556
|
-
|
|
1557
|
-
| AXIOMMIND | 플러그인 Phase | 핵심 산출물 |
|
|
1558
|
-
|-----------|---------------|-------------|
|
|
1559
|
-
| **P0** | Phase 0-1 | EventStore, VectorWorker, 기본 Hook |
|
|
1560
|
-
| **P0** | Phase 2-3 | Embedder, Retriever, Hook 통합 |
|
|
1561
|
-
| **P1** | Phase 4 | CLI, 운영 도구, 메트릭 |
|
|
1562
|
-
| **P2** | Phase 5 | 하이브리드 검색, 평가, 최적화 |
|
|
1563
|
-
|
|
1564
|
-
```
|
|
1565
|
-
Phase 0: 프로젝트 설정
|
|
1566
|
-
↓
|
|
1567
|
-
Phase 1: Core Storage Layer (P0 - EventStore, Outbox)
|
|
1568
|
-
↓
|
|
1569
|
-
Phase 2: Embedding & Retrieval (P0 - Vector, Matcher)
|
|
1570
|
-
↓
|
|
1571
|
-
Phase 3: Hook Integration (P0 - 기본 동작)
|
|
1572
|
-
↓
|
|
1573
|
-
Phase 4: Commands & CLI (P1 - 운영)
|
|
1574
|
-
↓
|
|
1575
|
-
Phase 5: Testing & Polish (P2 - 검색 최적화)
|
|
1576
|
-
```
|
|
1577
|
-
|
|
1578
|
-
---
|
|
1579
|
-
|
|
1580
|
-
## Phase 0: 프로젝트 설정
|
|
1581
|
-
|
|
1582
|
-
### 0.1 디렉토리 구조 생성
|
|
1583
|
-
|
|
1584
|
-
```
|
|
1585
|
-
code-memory/
|
|
1586
|
-
├── .claude-plugin/
|
|
1587
|
-
│ └── plugin.json # 플러그인 메타데이터
|
|
1588
|
-
├── commands/
|
|
1589
|
-
│ ├── search.md # /code-memory:search
|
|
1590
|
-
│ ├── history.md # /code-memory:history
|
|
1591
|
-
│ ├── insights.md # /code-memory:insights
|
|
1592
|
-
│ ├── forget.md # /code-memory:forget
|
|
1593
|
-
│ └── stats.md # /code-memory:stats
|
|
1594
|
-
├── hooks/
|
|
1595
|
-
│ └── hooks.json # Hook 설정
|
|
1596
|
-
├── src/
|
|
1597
|
-
│ ├── cli/
|
|
1598
|
-
│ │ ├── index.ts # CLI 엔트리포인트
|
|
1599
|
-
│ │ ├── commands/
|
|
1600
|
-
│ │ │ ├── session-start.ts
|
|
1601
|
-
│ │ │ ├── session-end.ts
|
|
1602
|
-
│ │ │ ├── search.ts
|
|
1603
|
-
│ │ │ ├── save.ts
|
|
1604
|
-
│ │ │ └── init.ts
|
|
1605
|
-
│ │ └── utils.ts
|
|
1606
|
-
│ ├── core/
|
|
1607
|
-
│ │ ├── canonical-key.ts # 정규화된 키 생성 (AXIOMMIND)
|
|
1608
|
-
│ │ ├── event-store.ts # DuckDB 이벤트 저장소
|
|
1609
|
-
│ │ ├── vector-store.ts # LanceDB 벡터 저장소
|
|
1610
|
-
│ │ ├── vector-worker.ts # Single-writer 패턴 워커 (AXIOMMIND)
|
|
1611
|
-
│ │ ├── embedder.ts # 임베딩 생성
|
|
1612
|
-
│ │ ├── matcher.ts # 가중치 기반 매칭 (AXIOMMIND)
|
|
1613
|
-
│ │ ├── evidence-aligner.ts # 증거 스팬 정렬 (AXIOMMIND 원칙4)
|
|
1614
|
-
│ │ ├── retriever.ts # 기억 검색
|
|
1615
|
-
│ │ ├── projector.ts # 이벤트→엔티티 투영 (AXIOMMIND)
|
|
1616
|
-
│ │ ├── graduation.ts # L0→L4 승격 파이프라인 (AXIOMMIND)
|
|
1617
|
-
│ │ └── types.ts # 타입 정의
|
|
1618
|
-
│ ├── hooks/
|
|
1619
|
-
│ │ ├── session-start.ts
|
|
1620
|
-
│ │ ├── user-prompt-submit.ts
|
|
1621
|
-
│ │ ├── stop.ts
|
|
1622
|
-
│ │ └── session-end.ts
|
|
1623
|
-
│ └── index.ts
|
|
1624
|
-
├── tests/
|
|
1625
|
-
│ ├── event-store.test.ts
|
|
1626
|
-
│ ├── vector-store.test.ts
|
|
1627
|
-
│ ├── retriever.test.ts
|
|
1628
|
-
│ └── integration.test.ts
|
|
1629
|
-
├── scripts/
|
|
1630
|
-
│ └── build.ts
|
|
1631
|
-
├── package.json
|
|
1632
|
-
├── tsconfig.json
|
|
1633
|
-
├── vitest.config.ts
|
|
1634
|
-
├── README.md
|
|
1635
|
-
├── spec.md
|
|
1636
|
-
├── plan.md
|
|
1637
|
-
└── context.md
|
|
1638
|
-
```
|
|
1639
|
-
|
|
1640
|
-
### 0.2 초기 설정 작업
|
|
1641
|
-
|
|
1642
|
-
```bash
|
|
1643
|
-
# 1. package.json 생성
|
|
1644
|
-
npm init -y
|
|
1645
|
-
|
|
1646
|
-
# 2. TypeScript 및 핵심 의존성 설치
|
|
1647
|
-
npm install -D typescript @types/node tsx esbuild vitest
|
|
1648
|
-
|
|
1649
|
-
# 3. 런타임 의존성
|
|
1650
|
-
npm install zod commander duckdb lancedb
|
|
1651
|
-
|
|
1652
|
-
# 4. 임베딩 (선택)
|
|
1653
|
-
npm install @xenova/transformers # 또는 Python sentence-transformers
|
|
1654
|
-
```
|
|
1655
|
-
|
|
1656
|
-
### 0.3 TypeScript 설정
|
|
1657
|
-
|
|
1658
|
-
```json
|
|
1659
|
-
// tsconfig.json
|
|
1660
|
-
{
|
|
1661
|
-
"compilerOptions": {
|
|
1662
|
-
"target": "ES2022",
|
|
1663
|
-
"module": "ESNext",
|
|
1664
|
-
"moduleResolution": "bundler",
|
|
1665
|
-
"strict": true,
|
|
1666
|
-
"esModuleInterop": true,
|
|
1667
|
-
"skipLibCheck": true,
|
|
1668
|
-
"outDir": "dist",
|
|
1669
|
-
"rootDir": "src",
|
|
1670
|
-
"declaration": true,
|
|
1671
|
-
"resolveJsonModule": true
|
|
1672
|
-
},
|
|
1673
|
-
"include": ["src/**/*"],
|
|
1674
|
-
"exclude": ["node_modules", "dist", "tests"]
|
|
1675
|
-
}
|
|
1676
|
-
```
|
|
1677
|
-
|
|
1678
|
-
---
|
|
1679
|
-
|
|
1680
|
-
## Phase 1: Core Storage Layer
|
|
1681
|
-
|
|
1682
|
-
### 1.1 타입 정의 (src/core/types.ts)
|
|
1683
|
-
|
|
1684
|
-
```typescript
|
|
1685
|
-
// Idris2 영감: 완전하고 불변한 타입 정의
|
|
1686
|
-
|
|
1687
|
-
import { z } from 'zod';
|
|
1688
|
-
|
|
1689
|
-
// 이벤트 타입 스키마
|
|
1690
|
-
export const EventTypeSchema = z.enum([
|
|
1691
|
-
'user_prompt',
|
|
1692
|
-
'agent_response',
|
|
1693
|
-
'session_summary'
|
|
1694
|
-
]);
|
|
1695
|
-
export type EventType = z.infer<typeof EventTypeSchema>;
|
|
1696
|
-
|
|
1697
|
-
// 메모리 이벤트 스키마
|
|
1698
|
-
export const MemoryEventSchema = z.object({
|
|
1699
|
-
id: z.string().uuid(),
|
|
1700
|
-
eventType: EventTypeSchema,
|
|
1701
|
-
sessionId: z.string(),
|
|
1702
|
-
timestamp: z.date(),
|
|
1703
|
-
content: z.string(),
|
|
1704
|
-
contentHash: z.string(),
|
|
1705
|
-
metadata: z.record(z.unknown()).optional()
|
|
1706
|
-
});
|
|
1707
|
-
export type MemoryEvent = z.infer<typeof MemoryEventSchema>;
|
|
1708
|
-
|
|
1709
|
-
// 세션 스키마
|
|
1710
|
-
export const SessionSchema = z.object({
|
|
1711
|
-
id: z.string(),
|
|
1712
|
-
startedAt: z.date(),
|
|
1713
|
-
endedAt: z.date().optional(),
|
|
1714
|
-
projectPath: z.string().optional(),
|
|
1715
|
-
summary: z.string().optional(),
|
|
1716
|
-
tags: z.array(z.string()).optional()
|
|
1717
|
-
});
|
|
1718
|
-
export type Session = z.infer<typeof SessionSchema>;
|
|
1719
|
-
|
|
1720
|
-
// 검색 결과
|
|
1721
|
-
export const MemoryMatchSchema = z.object({
|
|
1722
|
-
event: MemoryEventSchema,
|
|
1723
|
-
score: z.number().min(0).max(1),
|
|
1724
|
-
relevanceReason: z.string().optional()
|
|
1725
|
-
});
|
|
1726
|
-
export type MemoryMatch = z.infer<typeof MemoryMatchSchema>;
|
|
1727
|
-
|
|
1728
|
-
// 설정 스키마
|
|
1729
|
-
export const ConfigSchema = z.object({
|
|
1730
|
-
storage: z.object({
|
|
1731
|
-
path: z.string().default('~/.claude-code/memory'),
|
|
1732
|
-
maxSizeMB: z.number().default(500)
|
|
1733
|
-
}),
|
|
1734
|
-
embedding: z.object({
|
|
1735
|
-
provider: z.enum(['local', 'openai']).default('local'),
|
|
1736
|
-
model: z.string().default('all-MiniLM-L6-v2'),
|
|
1737
|
-
batchSize: z.number().default(32)
|
|
1738
|
-
}),
|
|
1739
|
-
retrieval: z.object({
|
|
1740
|
-
topK: z.number().default(5),
|
|
1741
|
-
minScore: z.number().default(0.7),
|
|
1742
|
-
maxTokens: z.number().default(2000)
|
|
1743
|
-
})
|
|
1744
|
-
});
|
|
1745
|
-
export type Config = z.infer<typeof ConfigSchema>;
|
|
1746
|
-
|
|
1747
|
-
// AXIOMMIND: Matching 결과 타입
|
|
1748
|
-
export const MatchConfidenceSchema = z.enum(['high', 'suggested', 'none']);
|
|
1749
|
-
export type MatchConfidence = z.infer<typeof MatchConfidenceSchema>;
|
|
1750
|
-
|
|
1751
|
-
export const MatchResultSchema = z.object({
|
|
1752
|
-
match: MemoryMatchSchema.nullable(),
|
|
1753
|
-
confidence: MatchConfidenceSchema,
|
|
1754
|
-
gap: z.number().optional(),
|
|
1755
|
-
alternatives: z.array(MemoryMatchSchema).optional()
|
|
1756
|
-
});
|
|
1757
|
-
export type MatchResult = z.infer<typeof MatchResultSchema>;
|
|
1758
|
-
|
|
1759
|
-
// AXIOMMIND: Matching Thresholds
|
|
1760
|
-
export const MATCH_THRESHOLDS = {
|
|
1761
|
-
minCombinedScore: 0.92,
|
|
1762
|
-
minGap: 0.03,
|
|
1763
|
-
suggestionThreshold: 0.75
|
|
1764
|
-
} as const;
|
|
1765
|
-
```
|
|
1766
|
-
|
|
1767
|
-
### 1.2 Canonical Key 구현 (src/core/canonical-key.ts) - AXIOMMIND
|
|
1768
|
-
|
|
1769
|
-
```typescript
|
|
1770
|
-
/**
|
|
1771
|
-
* AXIOMMIND canonical_key.py 포팅
|
|
1772
|
-
* 동일한 제목은 항상 동일한 키를 생성하는 결정론적 정규화
|
|
1773
|
-
*/
|
|
1774
|
-
|
|
1775
|
-
import { createHash } from 'crypto';
|
|
1776
|
-
|
|
1777
|
-
const MAX_KEY_LENGTH = 200;
|
|
1778
|
-
|
|
1779
|
-
/**
|
|
1780
|
-
* 텍스트를 정규화된 canonical key로 변환
|
|
1781
|
-
*
|
|
1782
|
-
* 정규화 단계:
|
|
1783
|
-
* 1. NFKC 유니코드 정규화
|
|
1784
|
-
* 2. 소문자 변환
|
|
1785
|
-
* 3. 구두점 제거
|
|
1786
|
-
* 4. 연속 공백 정리
|
|
1787
|
-
* 5. 컨텍스트 추가 (선택)
|
|
1788
|
-
* 6. 긴 키 truncate + MD5
|
|
1789
|
-
*/
|
|
1790
|
-
export function makeCanonicalKey(
|
|
1791
|
-
title: string,
|
|
1792
|
-
context?: { project?: string; sessionId?: string }
|
|
1793
|
-
): string {
|
|
1794
|
-
// Step 1: NFKC 정규화
|
|
1795
|
-
let normalized = title.normalize('NFKC');
|
|
1796
|
-
|
|
1797
|
-
// Step 2: 소문자 변환
|
|
1798
|
-
normalized = normalized.toLowerCase();
|
|
1799
|
-
|
|
1800
|
-
// Step 3: 구두점 제거 (유니코드 호환)
|
|
1801
|
-
normalized = normalized.replace(/[^\p{L}\p{N}\s]/gu, '');
|
|
1802
|
-
|
|
1803
|
-
// Step 4: 연속 공백 정리
|
|
1804
|
-
normalized = normalized.replace(/\s+/g, ' ').trim();
|
|
1805
|
-
|
|
1806
|
-
// Step 5: 컨텍스트 추가
|
|
1807
|
-
let key = normalized;
|
|
1808
|
-
if (context?.project) {
|
|
1809
|
-
key = `${context.project}::${key}`;
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
|
-
// Step 6: 긴 키 처리
|
|
1813
|
-
if (key.length > MAX_KEY_LENGTH) {
|
|
1814
|
-
const hashSuffix = createHash('md5').update(key).digest('hex').slice(0, 8);
|
|
1815
|
-
key = key.slice(0, MAX_KEY_LENGTH - 9) + '_' + hashSuffix;
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
return key;
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
/**
|
|
1822
|
-
* 두 텍스트가 동일한 canonical key를 가지는지 확인
|
|
1823
|
-
*/
|
|
1824
|
-
export function isSameCanonicalKey(a: string, b: string): boolean {
|
|
1825
|
-
return makeCanonicalKey(a) === makeCanonicalKey(b);
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
/**
|
|
1829
|
-
* Dedupe key 생성 (content + session으로 유일성 보장)
|
|
1830
|
-
*/
|
|
1831
|
-
export function makeDedupeKey(content: string, sessionId: string): string {
|
|
1832
|
-
const contentHash = createHash('sha256').update(content).digest('hex');
|
|
1833
|
-
return `${sessionId}:${contentHash}`;
|
|
1834
|
-
}
|
|
1835
|
-
```
|
|
1836
|
-
|
|
1837
|
-
### 1.3 Event Store 구현 (src/core/event-store.ts)
|
|
1838
|
-
|
|
1839
|
-
```typescript
|
|
1840
|
-
// AXIOMMIND 스타일: append-only, 멱등성, 단일 진실 공급원
|
|
1841
|
-
|
|
1842
|
-
import { Database } from 'duckdb';
|
|
1843
|
-
import { createHash } from 'crypto';
|
|
1844
|
-
import { MemoryEvent, EventType } from './types';
|
|
1845
|
-
|
|
1846
|
-
export class EventStore {
|
|
1847
|
-
private db: Database;
|
|
1848
|
-
|
|
1849
|
-
constructor(dbPath: string) {
|
|
1850
|
-
this.db = new Database(dbPath);
|
|
1851
|
-
this.initialize();
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
private initialize(): void {
|
|
1855
|
-
// 이벤트 테이블 (불변, append-only)
|
|
1856
|
-
this.db.run(`
|
|
1857
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
1858
|
-
id VARCHAR PRIMARY KEY,
|
|
1859
|
-
event_type VARCHAR NOT NULL,
|
|
1860
|
-
session_id VARCHAR NOT NULL,
|
|
1861
|
-
timestamp TIMESTAMP NOT NULL,
|
|
1862
|
-
content TEXT NOT NULL,
|
|
1863
|
-
metadata JSON,
|
|
1864
|
-
content_hash VARCHAR UNIQUE
|
|
1865
|
-
)
|
|
1866
|
-
`);
|
|
1867
|
-
|
|
1868
|
-
// 중복 방지 테이블
|
|
1869
|
-
this.db.run(`
|
|
1870
|
-
CREATE TABLE IF NOT EXISTS event_dedup (
|
|
1871
|
-
content_hash VARCHAR PRIMARY KEY,
|
|
1872
|
-
event_id VARCHAR NOT NULL
|
|
1873
|
-
)
|
|
1874
|
-
`);
|
|
1875
|
-
|
|
1876
|
-
// 세션 테이블
|
|
1877
|
-
this.db.run(`
|
|
1878
|
-
CREATE TABLE IF NOT EXISTS sessions (
|
|
1879
|
-
id VARCHAR PRIMARY KEY,
|
|
1880
|
-
started_at TIMESTAMP NOT NULL,
|
|
1881
|
-
ended_at TIMESTAMP,
|
|
1882
|
-
project_path VARCHAR,
|
|
1883
|
-
summary TEXT
|
|
1884
|
-
)
|
|
1885
|
-
`);
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
// 멱등성 보장 저장
|
|
1889
|
-
async append(event: Omit<MemoryEvent, 'id' | 'contentHash'>): Promise<{
|
|
1890
|
-
success: boolean;
|
|
1891
|
-
eventId?: string;
|
|
1892
|
-
isDuplicate?: boolean;
|
|
1893
|
-
}> {
|
|
1894
|
-
const contentHash = this.hashContent(event.content);
|
|
1895
|
-
|
|
1896
|
-
// 중복 확인
|
|
1897
|
-
const existing = this.db.prepare(`
|
|
1898
|
-
SELECT event_id FROM event_dedup WHERE content_hash = ?
|
|
1899
|
-
`).get(contentHash);
|
|
1900
|
-
|
|
1901
|
-
if (existing) {
|
|
1902
|
-
return { success: true, eventId: existing.event_id, isDuplicate: true };
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
const id = crypto.randomUUID();
|
|
1906
|
-
|
|
1907
|
-
this.db.run(`
|
|
1908
|
-
INSERT INTO events (id, event_type, session_id, timestamp, content, metadata, content_hash)
|
|
1909
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1910
|
-
`, [id, event.eventType, event.sessionId, event.timestamp, event.content,
|
|
1911
|
-
JSON.stringify(event.metadata), contentHash]);
|
|
1912
|
-
|
|
1913
|
-
this.db.run(`
|
|
1914
|
-
INSERT INTO event_dedup (content_hash, event_id) VALUES (?, ?)
|
|
1915
|
-
`, [contentHash, id]);
|
|
1916
|
-
|
|
1917
|
-
return { success: true, eventId: id, isDuplicate: false };
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
private hashContent(content: string): string {
|
|
1921
|
-
return createHash('sha256').update(content).digest('hex');
|
|
1922
|
-
}
|
|
1923
|
-
|
|
1924
|
-
// 세션별 이벤트 조회
|
|
1925
|
-
async getSessionEvents(sessionId: string): Promise<MemoryEvent[]> {
|
|
1926
|
-
return this.db.prepare(`
|
|
1927
|
-
SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC
|
|
1928
|
-
`).all(sessionId);
|
|
1929
|
-
}
|
|
1930
|
-
|
|
1931
|
-
// 최근 이벤트 조회
|
|
1932
|
-
async getRecentEvents(limit: number = 100): Promise<MemoryEvent[]> {
|
|
1933
|
-
return this.db.prepare(`
|
|
1934
|
-
SELECT * FROM events ORDER BY timestamp DESC LIMIT ?
|
|
1935
|
-
`).all(limit);
|
|
1936
|
-
}
|
|
1937
|
-
}
|
|
1938
|
-
```
|
|
1939
|
-
|
|
1940
|
-
### 1.3 Vector Store 구현 (src/core/vector-store.ts)
|
|
1941
|
-
|
|
1942
|
-
```typescript
|
|
1943
|
-
import * as lancedb from 'lancedb';
|
|
1944
|
-
|
|
1945
|
-
export class VectorStore {
|
|
1946
|
-
private db: lancedb.Connection;
|
|
1947
|
-
private table: lancedb.Table | null = null;
|
|
1948
|
-
|
|
1949
|
-
constructor(private dbPath: string) {}
|
|
1950
|
-
|
|
1951
|
-
async initialize(): Promise<void> {
|
|
1952
|
-
this.db = await lancedb.connect(this.dbPath);
|
|
1953
|
-
|
|
1954
|
-
// 테이블이 없으면 생성 (첫 데이터 삽입 시)
|
|
1955
|
-
try {
|
|
1956
|
-
this.table = await this.db.openTable('conversations');
|
|
1957
|
-
} catch {
|
|
1958
|
-
// 테이블이 없으면 나중에 생성
|
|
1959
|
-
this.table = null;
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
async upsert(data: {
|
|
1964
|
-
id: string;
|
|
1965
|
-
eventId: string;
|
|
1966
|
-
sessionId: string;
|
|
1967
|
-
eventType: string;
|
|
1968
|
-
content: string;
|
|
1969
|
-
vector: number[];
|
|
1970
|
-
timestamp: string;
|
|
1971
|
-
metadata?: Record<string, unknown>;
|
|
1972
|
-
}): Promise<void> {
|
|
1973
|
-
if (!this.table) {
|
|
1974
|
-
// 첫 데이터로 테이블 생성
|
|
1975
|
-
this.table = await this.db.createTable('conversations', [data]);
|
|
1976
|
-
return;
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
|
-
await this.table.add([data]);
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
async search(queryVector: number[], options: {
|
|
1983
|
-
limit?: number;
|
|
1984
|
-
minScore?: number;
|
|
1985
|
-
filter?: string;
|
|
1986
|
-
} = {}): Promise<Array<{
|
|
1987
|
-
id: string;
|
|
1988
|
-
eventId: string;
|
|
1989
|
-
content: string;
|
|
1990
|
-
score: number;
|
|
1991
|
-
}>> {
|
|
1992
|
-
if (!this.table) {
|
|
1993
|
-
return [];
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
const { limit = 5, minScore = 0.7 } = options;
|
|
1997
|
-
|
|
1998
|
-
const results = await this.table
|
|
1999
|
-
.search(queryVector)
|
|
2000
|
-
.limit(limit)
|
|
2001
|
-
.execute();
|
|
2002
|
-
|
|
2003
|
-
return results
|
|
2004
|
-
.filter(r => r._distance <= (1 - minScore)) // distance to score
|
|
2005
|
-
.map(r => ({
|
|
2006
|
-
id: r.id,
|
|
2007
|
-
eventId: r.eventId,
|
|
2008
|
-
content: r.content,
|
|
2009
|
-
score: 1 - r._distance
|
|
2010
|
-
}));
|
|
2011
|
-
}
|
|
2012
|
-
|
|
2013
|
-
async delete(eventId: string): Promise<void> {
|
|
2014
|
-
if (!this.table) return;
|
|
2015
|
-
await this.table.delete(`eventId = "${eventId}"`);
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
```
|
|
2019
|
-
|
|
2020
|
-
### 1.4 Vector Worker 구현 (src/core/vector-worker.ts) - AXIOMMIND Single-Writer
|
|
2021
|
-
|
|
2022
|
-
```typescript
|
|
2023
|
-
/**
|
|
2024
|
-
* AXIOMMIND vector_worker.py 포팅
|
|
2025
|
-
* Single-Writer 패턴으로 LanceDB 동시성 문제 해결
|
|
2026
|
-
*
|
|
2027
|
-
* 원리:
|
|
2028
|
-
* 1. 이벤트 저장 시 embedding_outbox에 작업 추가 (빠름)
|
|
2029
|
-
* 2. 별도 워커가 outbox를 순차적으로 처리 (단일 쓰기)
|
|
2030
|
-
* 3. 처리 완료 시 outbox에서 삭제
|
|
2031
|
-
*/
|
|
2032
|
-
|
|
2033
|
-
import { Database } from 'duckdb';
|
|
2034
|
-
import { VectorStore } from './vector-store';
|
|
2035
|
-
import { Embedder } from './embedder';
|
|
2036
|
-
|
|
2037
|
-
interface OutboxItem {
|
|
2038
|
-
id: string;
|
|
2039
|
-
eventId: string;
|
|
2040
|
-
content: string;
|
|
2041
|
-
status: 'pending' | 'processing' | 'done' | 'failed';
|
|
2042
|
-
retryCount: number;
|
|
2043
|
-
createdAt: Date;
|
|
2044
|
-
}
|
|
2045
|
-
|
|
2046
|
-
export class VectorWorker {
|
|
2047
|
-
private isRunning = false;
|
|
2048
|
-
private pollInterval = 1000; // 1초
|
|
2049
|
-
|
|
2050
|
-
constructor(
|
|
2051
|
-
private db: Database,
|
|
2052
|
-
private vectorStore: VectorStore,
|
|
2053
|
-
private embedder: Embedder
|
|
2054
|
-
) {}
|
|
2055
|
-
|
|
2056
|
-
/**
|
|
2057
|
-
* Outbox에 임베딩 작업 추가 (빠른 반환)
|
|
2058
|
-
*/
|
|
2059
|
-
async enqueue(eventId: string, content: string): Promise<string> {
|
|
2060
|
-
const id = crypto.randomUUID();
|
|
2061
|
-
|
|
2062
|
-
this.db.run(`
|
|
2063
|
-
INSERT INTO embedding_outbox (id, event_id, content, status, retry_count, created_at)
|
|
2064
|
-
VALUES (?, ?, ?, 'pending', 0, NOW())
|
|
2065
|
-
`, [id, eventId, content]);
|
|
2066
|
-
|
|
2067
|
-
return id;
|
|
2068
|
-
}
|
|
2069
|
-
|
|
2070
|
-
/**
|
|
2071
|
-
* 워커 시작 (백그라운드에서 실행)
|
|
2072
|
-
*/
|
|
2073
|
-
async start(): Promise<void> {
|
|
2074
|
-
if (this.isRunning) return;
|
|
2075
|
-
this.isRunning = true;
|
|
2076
|
-
|
|
2077
|
-
while (this.isRunning) {
|
|
2078
|
-
await this.processOutbox();
|
|
2079
|
-
await this.sleep(this.pollInterval);
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
|
|
2083
|
-
/**
|
|
2084
|
-
* 워커 중지
|
|
2085
|
-
*/
|
|
2086
|
-
stop(): void {
|
|
2087
|
-
this.isRunning = false;
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
/**
|
|
2091
|
-
* Outbox 처리 (핵심 로직)
|
|
2092
|
-
*/
|
|
2093
|
-
private async processOutbox(batchSize: number = 32): Promise<number> {
|
|
2094
|
-
// 1. Pending 항목 가져오기 + 락 획득 (atomic update)
|
|
2095
|
-
const pending = this.db.prepare(`
|
|
2096
|
-
UPDATE embedding_outbox
|
|
2097
|
-
SET status = 'processing'
|
|
2098
|
-
WHERE id IN (
|
|
2099
|
-
SELECT id FROM embedding_outbox
|
|
2100
|
-
WHERE status = 'pending'
|
|
2101
|
-
ORDER BY created_at
|
|
2102
|
-
LIMIT ?
|
|
2103
|
-
)
|
|
2104
|
-
RETURNING *
|
|
2105
|
-
`).all(batchSize) as OutboxItem[];
|
|
2106
|
-
|
|
2107
|
-
if (pending.length === 0) {
|
|
2108
|
-
return 0;
|
|
2109
|
-
}
|
|
2110
|
-
|
|
2111
|
-
try {
|
|
2112
|
-
// 2. 배치 임베딩 생성
|
|
2113
|
-
const contents = pending.map(p => p.content);
|
|
2114
|
-
const vectors = await this.embedder.embedBatch(contents);
|
|
2115
|
-
|
|
2116
|
-
// 3. LanceDB에 저장 (단일 쓰기 - 동시성 안전)
|
|
2117
|
-
for (let i = 0; i < pending.length; i++) {
|
|
2118
|
-
const item = pending[i];
|
|
2119
|
-
await this.vectorStore.upsert({
|
|
2120
|
-
id: crypto.randomUUID(),
|
|
2121
|
-
eventId: item.eventId,
|
|
2122
|
-
sessionId: '', // 필요시 조회
|
|
2123
|
-
eventType: '',
|
|
2124
|
-
content: item.content.slice(0, 1000), // 미리보기용
|
|
2125
|
-
vector: vectors[i],
|
|
2126
|
-
timestamp: new Date().toISOString()
|
|
2127
|
-
});
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
// 4. 성공한 항목 삭제
|
|
2131
|
-
const ids = pending.map(p => `'${p.id}'`).join(',');
|
|
2132
|
-
this.db.run(`DELETE FROM embedding_outbox WHERE id IN (${ids})`);
|
|
2133
|
-
|
|
2134
|
-
return pending.length;
|
|
2135
|
-
|
|
2136
|
-
} catch (error) {
|
|
2137
|
-
// 5. 실패 시 retry_count 증가
|
|
2138
|
-
const ids = pending.map(p => `'${p.id}'`).join(',');
|
|
2139
|
-
this.db.run(`
|
|
2140
|
-
UPDATE embedding_outbox
|
|
2141
|
-
SET status = CASE WHEN retry_count >= 3 THEN 'failed' ELSE 'pending' END,
|
|
2142
|
-
retry_count = retry_count + 1,
|
|
2143
|
-
error_message = ?
|
|
2144
|
-
WHERE id IN (${ids})
|
|
2145
|
-
`, [String(error)]);
|
|
2146
|
-
|
|
2147
|
-
return 0;
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
private sleep(ms: number): Promise<void> {
|
|
2152
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
2153
|
-
}
|
|
2154
|
-
}
|
|
2155
|
-
```
|
|
2156
|
-
|
|
2157
|
-
### 1.5 Matcher 구현 (src/core/matcher.ts) - AXIOMMIND Weighted Scoring
|
|
2158
|
-
|
|
2159
|
-
```typescript
|
|
2160
|
-
/**
|
|
2161
|
-
* AXIOMMIND task_matcher.py 포팅
|
|
2162
|
-
* 가중치 기반 스코어링 + 엄격한 매칭 임계값
|
|
2163
|
-
*/
|
|
2164
|
-
|
|
2165
|
-
import { MemoryMatch, MatchResult, MATCH_THRESHOLDS } from './types';
|
|
2166
|
-
|
|
2167
|
-
interface ScoringWeights {
|
|
2168
|
-
semanticSimilarity: number;
|
|
2169
|
-
ftsScore: number;
|
|
2170
|
-
recencyBonus: number;
|
|
2171
|
-
statusWeight: number;
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
const DEFAULT_WEIGHTS: ScoringWeights = {
|
|
2175
|
-
semanticSimilarity: 0.4,
|
|
2176
|
-
ftsScore: 0.25,
|
|
2177
|
-
recencyBonus: 0.2,
|
|
2178
|
-
statusWeight: 0.15
|
|
2179
|
-
};
|
|
2180
|
-
|
|
2181
|
-
interface RawSearchResult {
|
|
2182
|
-
id: string;
|
|
2183
|
-
eventId: string;
|
|
2184
|
-
content: string;
|
|
2185
|
-
vectorScore: number; // 벡터 유사도 (0-1)
|
|
2186
|
-
ftsScore?: number; // 전문 검색 점수 (0-1)
|
|
2187
|
-
timestamp: Date;
|
|
2188
|
-
eventType: string;
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
/**
|
|
2192
|
-
* 가중치 결합 점수 계산
|
|
2193
|
-
*/
|
|
2194
|
-
export function calculateWeightedScore(
|
|
2195
|
-
result: RawSearchResult,
|
|
2196
|
-
weights: ScoringWeights = DEFAULT_WEIGHTS
|
|
2197
|
-
): number {
|
|
2198
|
-
// 최신성 가산점 (30일 이내 = 1.0, 이후 감소)
|
|
2199
|
-
const daysSince = (Date.now() - result.timestamp.getTime()) / (1000 * 60 * 60 * 24);
|
|
2200
|
-
const recencyScore = Math.max(0, 1 - daysSince / 30);
|
|
2201
|
-
|
|
2202
|
-
// 상태별 가중치 (agent_response > user_prompt)
|
|
2203
|
-
const statusScore = result.eventType === 'agent_response' ? 1.0 : 0.8;
|
|
2204
|
-
|
|
2205
|
-
const score =
|
|
2206
|
-
result.vectorScore * weights.semanticSimilarity +
|
|
2207
|
-
(result.ftsScore ?? 0) * weights.ftsScore +
|
|
2208
|
-
recencyScore * weights.recencyBonus +
|
|
2209
|
-
statusScore * weights.statusWeight;
|
|
2210
|
-
|
|
2211
|
-
return Math.min(1, Math.max(0, score)); // 0-1 범위로 클램프
|
|
2212
|
-
}
|
|
2213
|
-
|
|
2214
|
-
/**
|
|
2215
|
-
* 엄격한 매칭: top-1이 확실히 우세할 때만 확정
|
|
2216
|
-
*
|
|
2217
|
-
* AXIOMMIND 규칙:
|
|
2218
|
-
* - combined score >= 0.92 AND gap >= 0.03 → 'high' (확정)
|
|
2219
|
-
* - 0.75 <= score < 0.92 → 'suggested' (제안)
|
|
2220
|
-
* - score < 0.75 → 'none' (매칭 없음)
|
|
2221
|
-
*/
|
|
2222
|
-
export function matchWithConfidence(
|
|
2223
|
-
candidates: MemoryMatch[]
|
|
2224
|
-
): MatchResult {
|
|
2225
|
-
if (candidates.length === 0) {
|
|
2226
|
-
return { match: null, confidence: 'none' };
|
|
2227
|
-
}
|
|
2228
|
-
|
|
2229
|
-
// 점수순 정렬
|
|
2230
|
-
const sorted = [...candidates].sort((a, b) => b.score - a.score);
|
|
2231
|
-
const top = sorted[0];
|
|
2232
|
-
|
|
2233
|
-
// 임계값 미달
|
|
2234
|
-
if (top.score < MATCH_THRESHOLDS.suggestionThreshold) {
|
|
2235
|
-
return { match: null, confidence: 'none' };
|
|
2236
|
-
}
|
|
2237
|
-
|
|
2238
|
-
// 확정 매칭 체크
|
|
2239
|
-
if (top.score >= MATCH_THRESHOLDS.minCombinedScore) {
|
|
2240
|
-
// 단일 후보
|
|
2241
|
-
if (sorted.length === 1) {
|
|
2242
|
-
return { match: top, confidence: 'high' };
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
// 2위와의 gap 체크
|
|
2246
|
-
const gap = top.score - sorted[1].score;
|
|
2247
|
-
if (gap >= MATCH_THRESHOLDS.minGap) {
|
|
2248
|
-
return { match: top, confidence: 'high', gap };
|
|
2249
|
-
}
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
// 제안 모드 (확실하지 않음)
|
|
2253
|
-
return {
|
|
2254
|
-
match: top,
|
|
2255
|
-
confidence: 'suggested',
|
|
2256
|
-
gap: sorted.length > 1 ? top.score - sorted[1].score : undefined,
|
|
2257
|
-
alternatives: sorted.slice(1, 4) // 상위 3개 대안
|
|
2258
|
-
};
|
|
2259
|
-
}
|
|
2260
|
-
|
|
2261
|
-
/**
|
|
2262
|
-
* 검색 결과를 MemoryMatch로 변환
|
|
2263
|
-
*/
|
|
2264
|
-
export function toMemoryMatch(
|
|
2265
|
-
result: RawSearchResult,
|
|
2266
|
-
weights?: ScoringWeights
|
|
2267
|
-
): MemoryMatch {
|
|
2268
|
-
const score = calculateWeightedScore(result, weights);
|
|
2269
|
-
|
|
2270
|
-
return {
|
|
2271
|
-
event: {
|
|
2272
|
-
id: result.eventId,
|
|
2273
|
-
eventType: result.eventType as any,
|
|
2274
|
-
sessionId: '',
|
|
2275
|
-
timestamp: result.timestamp,
|
|
2276
|
-
content: result.content,
|
|
2277
|
-
contentHash: ''
|
|
2278
|
-
},
|
|
2279
|
-
score,
|
|
2280
|
-
relevanceReason: `Weighted score: ${(score * 100).toFixed(1)}% ` +
|
|
2281
|
-
`(vector: ${(result.vectorScore * 100).toFixed(0)}%)`
|
|
2282
|
-
};
|
|
2283
|
-
}
|
|
2284
|
-
```
|
|
2285
|
-
|
|
2286
|
-
### 1.6 Evidence Aligner 구현 (src/core/evidence-aligner.ts) - AXIOMMIND 원칙4
|
|
2287
|
-
|
|
2288
|
-
```typescript
|
|
2289
|
-
/**
|
|
2290
|
-
* AXIOMMIND 원칙 4: 증거 범위는 파이프라인이 확정
|
|
2291
|
-
*
|
|
2292
|
-
* LLM이 추출한 대략적인 인용문을 원본 텍스트에서
|
|
2293
|
-
* 정확한 (start, end) 위치로 변환
|
|
2294
|
-
*/
|
|
2295
|
-
|
|
2296
|
-
interface EvidenceSpan {
|
|
2297
|
-
start: number;
|
|
2298
|
-
end: number;
|
|
2299
|
-
confidence: number;
|
|
2300
|
-
matchType: 'exact' | 'fuzzy' | 'none';
|
|
2301
|
-
originalQuote: string;
|
|
2302
|
-
alignedText: string;
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
interface FuzzyMatch {
|
|
2306
|
-
start: number;
|
|
2307
|
-
end: number;
|
|
2308
|
-
score: number;
|
|
2309
|
-
text: string;
|
|
2310
|
-
}
|
|
2311
|
-
|
|
2312
|
-
export class EvidenceAligner {
|
|
2313
|
-
private fuzzyThreshold: number;
|
|
2314
|
-
|
|
2315
|
-
constructor(fuzzyThreshold: number = 0.85) {
|
|
2316
|
-
this.fuzzyThreshold = fuzzyThreshold;
|
|
2317
|
-
}
|
|
2318
|
-
|
|
2319
|
-
/**
|
|
2320
|
-
* LLM 인용문을 원본 텍스트에서 정확한 스팬으로 변환
|
|
2321
|
-
*/
|
|
2322
|
-
align(sourceText: string, llmQuote: string): EvidenceSpan | null {
|
|
2323
|
-
// 1. 정확한 매칭 시도
|
|
2324
|
-
const exactPos = sourceText.indexOf(llmQuote);
|
|
2325
|
-
if (exactPos >= 0) {
|
|
2326
|
-
return {
|
|
2327
|
-
start: exactPos,
|
|
2328
|
-
end: exactPos + llmQuote.length,
|
|
2329
|
-
confidence: 1.0,
|
|
2330
|
-
matchType: 'exact',
|
|
2331
|
-
originalQuote: llmQuote,
|
|
2332
|
-
alignedText: llmQuote
|
|
2333
|
-
};
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
// 2. 정규화 후 매칭 (공백, 대소문자 무시)
|
|
2337
|
-
const normalizedMatch = this.normalizedSearch(sourceText, llmQuote);
|
|
2338
|
-
if (normalizedMatch && normalizedMatch.score >= 0.95) {
|
|
2339
|
-
return {
|
|
2340
|
-
start: normalizedMatch.start,
|
|
2341
|
-
end: normalizedMatch.end,
|
|
2342
|
-
confidence: normalizedMatch.score,
|
|
2343
|
-
matchType: 'exact',
|
|
2344
|
-
originalQuote: llmQuote,
|
|
2345
|
-
alignedText: normalizedMatch.text
|
|
2346
|
-
};
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2349
|
-
// 3. Fuzzy 매칭 (Levenshtein 거리)
|
|
2350
|
-
const fuzzyMatch = this.fuzzySearch(sourceText, llmQuote);
|
|
2351
|
-
if (fuzzyMatch && fuzzyMatch.score >= this.fuzzyThreshold) {
|
|
2352
|
-
return {
|
|
2353
|
-
start: fuzzyMatch.start,
|
|
2354
|
-
end: fuzzyMatch.end,
|
|
2355
|
-
confidence: fuzzyMatch.score,
|
|
2356
|
-
matchType: 'fuzzy',
|
|
2357
|
-
originalQuote: llmQuote,
|
|
2358
|
-
alignedText: fuzzyMatch.text
|
|
2359
|
-
};
|
|
2360
|
-
}
|
|
2361
|
-
|
|
2362
|
-
// 4. 매칭 실패
|
|
2363
|
-
return null;
|
|
2364
|
-
}
|
|
2365
|
-
|
|
2366
|
-
/**
|
|
2367
|
-
* 정규화된 검색 (공백/대소문자 무시)
|
|
2368
|
-
*/
|
|
2369
|
-
private normalizedSearch(text: string, query: string): FuzzyMatch | null {
|
|
2370
|
-
const normalize = (s: string) => s.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
2371
|
-
const normalizedText = normalize(text);
|
|
2372
|
-
const normalizedQuery = normalize(query);
|
|
2373
|
-
|
|
2374
|
-
const pos = normalizedText.indexOf(normalizedQuery);
|
|
2375
|
-
if (pos < 0) return null;
|
|
2376
|
-
|
|
2377
|
-
// 원본 텍스트에서 실제 위치 찾기
|
|
2378
|
-
let originalStart = 0;
|
|
2379
|
-
let normalizedPos = 0;
|
|
2380
|
-
for (let i = 0; i < text.length && normalizedPos < pos; i++) {
|
|
2381
|
-
if (!/\s/.test(text[i]) || (i > 0 && !/\s/.test(text[i-1]))) {
|
|
2382
|
-
normalizedPos++;
|
|
2383
|
-
}
|
|
2384
|
-
originalStart = i + 1;
|
|
2385
|
-
}
|
|
2386
|
-
|
|
2387
|
-
return {
|
|
2388
|
-
start: originalStart,
|
|
2389
|
-
end: originalStart + query.length,
|
|
2390
|
-
score: 0.98,
|
|
2391
|
-
text: text.slice(originalStart, originalStart + query.length)
|
|
2392
|
-
};
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
/**
|
|
2396
|
-
* Fuzzy 검색 (슬라이딩 윈도우 + Levenshtein)
|
|
2397
|
-
*/
|
|
2398
|
-
private fuzzySearch(text: string, query: string): FuzzyMatch | null {
|
|
2399
|
-
const windowSize = Math.min(query.length * 1.5, text.length);
|
|
2400
|
-
let bestMatch: FuzzyMatch | null = null;
|
|
2401
|
-
|
|
2402
|
-
for (let i = 0; i <= text.length - query.length; i++) {
|
|
2403
|
-
const window = text.slice(i, i + Math.ceil(windowSize));
|
|
2404
|
-
const score = this.similarity(window.slice(0, query.length), query);
|
|
2405
|
-
|
|
2406
|
-
if (!bestMatch || score > bestMatch.score) {
|
|
2407
|
-
bestMatch = {
|
|
2408
|
-
start: i,
|
|
2409
|
-
end: i + query.length,
|
|
2410
|
-
score,
|
|
2411
|
-
text: window.slice(0, query.length)
|
|
2412
|
-
};
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
|
|
2416
|
-
return bestMatch;
|
|
2417
|
-
}
|
|
2418
|
-
|
|
2419
|
-
/**
|
|
2420
|
-
* Levenshtein 기반 유사도 (0-1)
|
|
2421
|
-
*/
|
|
2422
|
-
private similarity(a: string, b: string): number {
|
|
2423
|
-
const distance = this.levenshteinDistance(a.toLowerCase(), b.toLowerCase());
|
|
2424
|
-
const maxLen = Math.max(a.length, b.length);
|
|
2425
|
-
return maxLen === 0 ? 1 : 1 - distance / maxLen;
|
|
2426
|
-
}
|
|
2427
|
-
|
|
2428
|
-
private levenshteinDistance(a: string, b: string): number {
|
|
2429
|
-
const matrix: number[][] = [];
|
|
2430
|
-
for (let i = 0; i <= b.length; i++) {
|
|
2431
|
-
matrix[i] = [i];
|
|
2432
|
-
}
|
|
2433
|
-
for (let j = 0; j <= a.length; j++) {
|
|
2434
|
-
matrix[0][j] = j;
|
|
2435
|
-
}
|
|
2436
|
-
for (let i = 1; i <= b.length; i++) {
|
|
2437
|
-
for (let j = 1; j <= a.length; j++) {
|
|
2438
|
-
const cost = a[j - 1] === b[i - 1] ? 0 : 1;
|
|
2439
|
-
matrix[i][j] = Math.min(
|
|
2440
|
-
matrix[i - 1][j] + 1,
|
|
2441
|
-
matrix[i][j - 1] + 1,
|
|
2442
|
-
matrix[i - 1][j - 1] + cost
|
|
2443
|
-
);
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
return matrix[b.length][a.length];
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
|
-
```
|
|
2450
|
-
|
|
2451
|
-
### 1.7 Graduation Pipeline 구현 (src/core/graduation.ts) - AXIOMMIND L0→L4
|
|
2452
|
-
|
|
2453
|
-
```typescript
|
|
2454
|
-
/**
|
|
2455
|
-
* AXIOMMIND Memory Graduation Pipeline
|
|
2456
|
-
* L0(Raw) → L1(Structured) → L2(Candidates) → L3(Verified) → L4(Active)
|
|
2457
|
-
*/
|
|
2458
|
-
|
|
2459
|
-
import { EventStore } from './event-store';
|
|
2460
|
-
import { VectorStore } from './vector-store';
|
|
2461
|
-
import { VectorWorker } from './vector-worker';
|
|
2462
|
-
import { MemoryEvent } from './types';
|
|
2463
|
-
|
|
2464
|
-
type MemoryLevel = 'L0' | 'L1' | 'L2' | 'L3' | 'L4';
|
|
2465
|
-
|
|
2466
|
-
interface GraduationResult {
|
|
2467
|
-
eventId: string;
|
|
2468
|
-
fromLevel: MemoryLevel;
|
|
2469
|
-
toLevel: MemoryLevel;
|
|
2470
|
-
success: boolean;
|
|
2471
|
-
reason?: string;
|
|
2472
|
-
}
|
|
2473
|
-
|
|
2474
|
-
interface LevelStatus {
|
|
2475
|
-
level: MemoryLevel;
|
|
2476
|
-
count: number;
|
|
2477
|
-
lastUpdated: Date | null;
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
|
-
export class GraduationPipeline {
|
|
2481
|
-
constructor(
|
|
2482
|
-
private eventStore: EventStore,
|
|
2483
|
-
private vectorStore: VectorStore,
|
|
2484
|
-
private vectorWorker: VectorWorker
|
|
2485
|
-
) {}
|
|
2486
|
-
|
|
2487
|
-
/**
|
|
2488
|
-
* L0 → L1: 원본 이벤트에서 구조화된 데이터 추출
|
|
2489
|
-
* (LLM 기반 추출은 별도 서비스에서 처리)
|
|
2490
|
-
*/
|
|
2491
|
-
async promoteToL1(eventId: string): Promise<GraduationResult> {
|
|
2492
|
-
// L1 승격은 LLM 추출 완료 후 마킹
|
|
2493
|
-
// 여기서는 메타데이터만 업데이트
|
|
2494
|
-
return {
|
|
2495
|
-
eventId,
|
|
2496
|
-
fromLevel: 'L0',
|
|
2497
|
-
toLevel: 'L1',
|
|
2498
|
-
success: true
|
|
2499
|
-
};
|
|
2500
|
-
}
|
|
2501
|
-
|
|
2502
|
-
/**
|
|
2503
|
-
* L1 → L2: 타입 검증 대상으로 승격
|
|
2504
|
-
* TypeScript 타입 체크 통과 여부 확인
|
|
2505
|
-
*/
|
|
2506
|
-
async promoteToL2(eventId: string, structuredData: unknown): Promise<GraduationResult> {
|
|
2507
|
-
try {
|
|
2508
|
-
// Zod 스키마로 검증
|
|
2509
|
-
// const validated = SomeSchema.parse(structuredData);
|
|
2510
|
-
|
|
2511
|
-
return {
|
|
2512
|
-
eventId,
|
|
2513
|
-
fromLevel: 'L1',
|
|
2514
|
-
toLevel: 'L2',
|
|
2515
|
-
success: true
|
|
2516
|
-
};
|
|
2517
|
-
} catch (error) {
|
|
2518
|
-
return {
|
|
2519
|
-
eventId,
|
|
2520
|
-
fromLevel: 'L1',
|
|
2521
|
-
toLevel: 'L2',
|
|
2522
|
-
success: false,
|
|
2523
|
-
reason: `Validation failed: ${error}`
|
|
2524
|
-
};
|
|
2525
|
-
}
|
|
2526
|
-
}
|
|
2527
|
-
|
|
2528
|
-
/**
|
|
2529
|
-
* L2 → L3: 검증 완료 (모순 없음 확인)
|
|
2530
|
-
*/
|
|
2531
|
-
async promoteToL3(eventId: string): Promise<GraduationResult> {
|
|
2532
|
-
// 기존 지식과의 모순 체크
|
|
2533
|
-
// 중복 체크
|
|
2534
|
-
// 신뢰도 계산
|
|
2535
|
-
|
|
2536
|
-
return {
|
|
2537
|
-
eventId,
|
|
2538
|
-
fromLevel: 'L2',
|
|
2539
|
-
toLevel: 'L3',
|
|
2540
|
-
success: true
|
|
2541
|
-
};
|
|
2542
|
-
}
|
|
2543
|
-
|
|
2544
|
-
/**
|
|
2545
|
-
* L3 → L4: 검색 가능 상태로 승격 (벡터 인덱싱)
|
|
2546
|
-
*/
|
|
2547
|
-
async promoteToL4(eventId: string, content: string): Promise<GraduationResult> {
|
|
2548
|
-
try {
|
|
2549
|
-
// VectorWorker의 outbox에 추가 (비동기 인덱싱)
|
|
2550
|
-
await this.vectorWorker.enqueue(eventId, content);
|
|
2551
|
-
|
|
2552
|
-
return {
|
|
2553
|
-
eventId,
|
|
2554
|
-
fromLevel: 'L3',
|
|
2555
|
-
toLevel: 'L4',
|
|
2556
|
-
success: true
|
|
2557
|
-
};
|
|
2558
|
-
} catch (error) {
|
|
2559
|
-
return {
|
|
2560
|
-
eventId,
|
|
2561
|
-
fromLevel: 'L3',
|
|
2562
|
-
toLevel: 'L4',
|
|
2563
|
-
success: false,
|
|
2564
|
-
reason: `Indexing failed: ${error}`
|
|
2565
|
-
};
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
|
|
2569
|
-
/**
|
|
2570
|
-
* 전체 파이프라인 실행 (L0 → L4)
|
|
2571
|
-
*/
|
|
2572
|
-
async graduateFull(event: MemoryEvent): Promise<GraduationResult[]> {
|
|
2573
|
-
const results: GraduationResult[] = [];
|
|
2574
|
-
|
|
2575
|
-
// L0 → L1 (구조화)
|
|
2576
|
-
const l1Result = await this.promoteToL1(event.id);
|
|
2577
|
-
results.push(l1Result);
|
|
2578
|
-
if (!l1Result.success) return results;
|
|
2579
|
-
|
|
2580
|
-
// L1 → L2 (타입 검증)
|
|
2581
|
-
const l2Result = await this.promoteToL2(event.id, event);
|
|
2582
|
-
results.push(l2Result);
|
|
2583
|
-
if (!l2Result.success) return results;
|
|
2584
|
-
|
|
2585
|
-
// L2 → L3 (모순 체크)
|
|
2586
|
-
const l3Result = await this.promoteToL3(event.id);
|
|
2587
|
-
results.push(l3Result);
|
|
2588
|
-
if (!l3Result.success) return results;
|
|
2589
|
-
|
|
2590
|
-
// L3 → L4 (인덱싱)
|
|
2591
|
-
const l4Result = await this.promoteToL4(event.id, event.content);
|
|
2592
|
-
results.push(l4Result);
|
|
2593
|
-
|
|
2594
|
-
return results;
|
|
2595
|
-
}
|
|
2596
|
-
|
|
2597
|
-
/**
|
|
2598
|
-
* 각 레벨별 통계 조회
|
|
2599
|
-
*/
|
|
2600
|
-
async getLevelStats(): Promise<LevelStatus[]> {
|
|
2601
|
-
// 실제 구현에서는 DB 쿼리
|
|
2602
|
-
return [
|
|
2603
|
-
{ level: 'L0', count: 0, lastUpdated: null },
|
|
2604
|
-
{ level: 'L1', count: 0, lastUpdated: null },
|
|
2605
|
-
{ level: 'L2', count: 0, lastUpdated: null },
|
|
2606
|
-
{ level: 'L3', count: 0, lastUpdated: null },
|
|
2607
|
-
{ level: 'L4', count: 0, lastUpdated: null }
|
|
2608
|
-
];
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
```
|
|
2612
|
-
|
|
2613
|
-
---
|
|
2614
|
-
|
|
2615
|
-
## Phase 2: Embedding & Retrieval
|
|
2616
|
-
|
|
2617
|
-
### 2.1 Embedder 구현 (src/core/embedder.ts)
|
|
2618
|
-
|
|
2619
|
-
```typescript
|
|
2620
|
-
import { pipeline, Pipeline } from '@xenova/transformers';
|
|
2621
|
-
|
|
2622
|
-
export class Embedder {
|
|
2623
|
-
private model: Pipeline | null = null;
|
|
2624
|
-
private modelName: string;
|
|
2625
|
-
|
|
2626
|
-
constructor(modelName: string = 'Xenova/all-MiniLM-L6-v2') {
|
|
2627
|
-
this.modelName = modelName;
|
|
2628
|
-
}
|
|
2629
|
-
|
|
2630
|
-
async initialize(): Promise<void> {
|
|
2631
|
-
this.model = await pipeline('feature-extraction', this.modelName);
|
|
2632
|
-
}
|
|
2633
|
-
|
|
2634
|
-
async embed(text: string): Promise<number[]> {
|
|
2635
|
-
if (!this.model) {
|
|
2636
|
-
await this.initialize();
|
|
2637
|
-
}
|
|
2638
|
-
|
|
2639
|
-
const result = await this.model!(text, {
|
|
2640
|
-
pooling: 'mean',
|
|
2641
|
-
normalize: true
|
|
2642
|
-
});
|
|
2643
|
-
|
|
2644
|
-
return Array.from(result.data);
|
|
2645
|
-
}
|
|
2646
|
-
|
|
2647
|
-
async embedBatch(texts: string[]): Promise<number[][]> {
|
|
2648
|
-
return Promise.all(texts.map(t => this.embed(t)));
|
|
2649
|
-
}
|
|
2650
|
-
}
|
|
2651
|
-
```
|
|
2652
|
-
|
|
2653
|
-
### 2.2 Retriever 구현 (src/core/retriever.ts)
|
|
2654
|
-
|
|
2655
|
-
```typescript
|
|
2656
|
-
import { Embedder } from './embedder';
|
|
2657
|
-
import { VectorStore } from './vector-store';
|
|
2658
|
-
import { EventStore } from './event-store';
|
|
2659
|
-
import { MemoryMatch, Config } from './types';
|
|
2660
|
-
|
|
2661
|
-
export class Retriever {
|
|
2662
|
-
constructor(
|
|
2663
|
-
private embedder: Embedder,
|
|
2664
|
-
private vectorStore: VectorStore,
|
|
2665
|
-
private eventStore: EventStore,
|
|
2666
|
-
private config: Config
|
|
2667
|
-
) {}
|
|
2668
|
-
|
|
2669
|
-
async search(query: string): Promise<MemoryMatch[]> {
|
|
2670
|
-
// 1. 쿼리 임베딩
|
|
2671
|
-
const queryVector = await this.embedder.embed(query);
|
|
2672
|
-
|
|
2673
|
-
// 2. 벡터 검색
|
|
2674
|
-
const vectorResults = await this.vectorStore.search(queryVector, {
|
|
2675
|
-
limit: this.config.retrieval.topK,
|
|
2676
|
-
minScore: this.config.retrieval.minScore
|
|
2677
|
-
});
|
|
2678
|
-
|
|
2679
|
-
// 3. 이벤트 정보 보강
|
|
2680
|
-
const matches: MemoryMatch[] = [];
|
|
2681
|
-
|
|
2682
|
-
for (const result of vectorResults) {
|
|
2683
|
-
// 원본 이벤트 조회
|
|
2684
|
-
const events = await this.eventStore.getSessionEvents(result.eventId);
|
|
2685
|
-
const event = events.find(e => e.id === result.eventId);
|
|
2686
|
-
|
|
2687
|
-
if (event) {
|
|
2688
|
-
matches.push({
|
|
2689
|
-
event,
|
|
2690
|
-
score: result.score,
|
|
2691
|
-
relevanceReason: `Semantic similarity: ${(result.score * 100).toFixed(1)}%`
|
|
2692
|
-
});
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
|
|
2696
|
-
return matches;
|
|
2697
|
-
}
|
|
2698
|
-
|
|
2699
|
-
// 컨텍스트 포맷팅
|
|
2700
|
-
formatContext(matches: MemoryMatch[]): string {
|
|
2701
|
-
if (matches.length === 0) {
|
|
2702
|
-
return '';
|
|
2703
|
-
}
|
|
2704
|
-
|
|
2705
|
-
const lines = ['## Relevant Memories\n'];
|
|
2706
|
-
|
|
2707
|
-
for (const match of matches) {
|
|
2708
|
-
const date = new Date(match.event.timestamp).toLocaleDateString();
|
|
2709
|
-
lines.push(`### ${match.event.eventType} (${date})`);
|
|
2710
|
-
lines.push(`> ${match.event.content.slice(0, 500)}...`);
|
|
2711
|
-
lines.push(`_Relevance: ${(match.score * 100).toFixed(0)}%_\n`);
|
|
2712
|
-
}
|
|
2713
|
-
|
|
2714
|
-
return lines.join('\n');
|
|
2715
|
-
}
|
|
2716
|
-
}
|
|
2717
|
-
```
|
|
2718
|
-
|
|
2719
|
-
---
|
|
2720
|
-
|
|
2721
|
-
## Phase 3: Hook Integration
|
|
2722
|
-
|
|
2723
|
-
### 3.1 hooks.json 설정
|
|
2724
|
-
|
|
2725
|
-
```json
|
|
2726
|
-
{
|
|
2727
|
-
"hooks": {
|
|
2728
|
-
"SessionStart": [
|
|
2729
|
-
{
|
|
2730
|
-
"type": "command",
|
|
2731
|
-
"command": "npx code-memory session-start",
|
|
2732
|
-
"timeout": 5000
|
|
2733
|
-
}
|
|
2734
|
-
],
|
|
2735
|
-
"UserPromptSubmit": [
|
|
2736
|
-
{
|
|
2737
|
-
"type": "command",
|
|
2738
|
-
"command": "npx code-memory search --stdin",
|
|
2739
|
-
"timeout": 3000
|
|
2740
|
-
}
|
|
2741
|
-
],
|
|
2742
|
-
"Stop": [
|
|
2743
|
-
{
|
|
2744
|
-
"type": "command",
|
|
2745
|
-
"command": "npx code-memory save --stdin",
|
|
2746
|
-
"timeout": 5000
|
|
2747
|
-
}
|
|
2748
|
-
],
|
|
2749
|
-
"SessionEnd": [
|
|
2750
|
-
{
|
|
2751
|
-
"type": "command",
|
|
2752
|
-
"command": "npx code-memory session-end --stdin",
|
|
2753
|
-
"timeout": 10000
|
|
2754
|
-
}
|
|
2755
|
-
]
|
|
2756
|
-
}
|
|
2757
|
-
}
|
|
2758
|
-
```
|
|
2759
|
-
|
|
2760
|
-
### 3.2 UserPromptSubmit Hook (src/hooks/user-prompt-submit.ts)
|
|
2761
|
-
|
|
2762
|
-
```typescript
|
|
2763
|
-
import { Retriever } from '../core/retriever';
|
|
2764
|
-
import { loadServices } from '../core/services';
|
|
2765
|
-
|
|
2766
|
-
export async function handleUserPromptSubmit(input: {
|
|
2767
|
-
session_id: string;
|
|
2768
|
-
prompt: string;
|
|
2769
|
-
}): Promise<{ context?: string }> {
|
|
2770
|
-
const { retriever } = await loadServices();
|
|
2771
|
-
|
|
2772
|
-
// 관련 기억 검색
|
|
2773
|
-
const matches = await retriever.search(input.prompt);
|
|
2774
|
-
|
|
2775
|
-
if (matches.length === 0) {
|
|
2776
|
-
return {};
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
|
-
// 컨텍스트 포맷팅
|
|
2780
|
-
const context = retriever.formatContext(matches);
|
|
2781
|
-
|
|
2782
|
-
return { context };
|
|
2783
|
-
}
|
|
2784
|
-
|
|
2785
|
-
// CLI 엔트리포인트
|
|
2786
|
-
if (process.stdin.isTTY === false) {
|
|
2787
|
-
let data = '';
|
|
2788
|
-
process.stdin.on('data', chunk => data += chunk);
|
|
2789
|
-
process.stdin.on('end', async () => {
|
|
2790
|
-
const input = JSON.parse(data);
|
|
2791
|
-
const result = await handleUserPromptSubmit(input);
|
|
2792
|
-
console.log(JSON.stringify(result));
|
|
2793
|
-
});
|
|
2794
|
-
}
|
|
2795
|
-
```
|
|
2796
|
-
|
|
2797
|
-
### 3.3 Stop Hook (src/hooks/stop.ts)
|
|
2798
|
-
|
|
2799
|
-
```typescript
|
|
2800
|
-
import { EventStore } from '../core/event-store';
|
|
2801
|
-
import { VectorStore } from '../core/vector-store';
|
|
2802
|
-
import { Embedder } from '../core/embedder';
|
|
2803
|
-
import { loadServices } from '../core/services';
|
|
2804
|
-
|
|
2805
|
-
export async function handleStop(input: {
|
|
2806
|
-
session_id: string;
|
|
2807
|
-
messages: Array<{ role: string; content: string }>;
|
|
2808
|
-
}): Promise<void> {
|
|
2809
|
-
const { eventStore, vectorStore, embedder } = await loadServices();
|
|
2810
|
-
|
|
2811
|
-
// 마지막 user-assistant 쌍 저장
|
|
2812
|
-
const messages = input.messages.slice(-2);
|
|
2813
|
-
|
|
2814
|
-
for (const msg of messages) {
|
|
2815
|
-
const eventType = msg.role === 'user' ? 'user_prompt' : 'agent_response';
|
|
2816
|
-
|
|
2817
|
-
// 1. 이벤트 저장
|
|
2818
|
-
const result = await eventStore.append({
|
|
2819
|
-
eventType,
|
|
2820
|
-
sessionId: input.session_id,
|
|
2821
|
-
timestamp: new Date(),
|
|
2822
|
-
content: msg.content,
|
|
2823
|
-
metadata: {}
|
|
2824
|
-
});
|
|
2825
|
-
|
|
2826
|
-
// 2. 임베딩 생성 및 벡터 저장 (중복 아닌 경우)
|
|
2827
|
-
if (result.success && !result.isDuplicate) {
|
|
2828
|
-
const vector = await embedder.embed(msg.content);
|
|
2829
|
-
|
|
2830
|
-
await vectorStore.upsert({
|
|
2831
|
-
id: crypto.randomUUID(),
|
|
2832
|
-
eventId: result.eventId!,
|
|
2833
|
-
sessionId: input.session_id,
|
|
2834
|
-
eventType,
|
|
2835
|
-
content: msg.content.slice(0, 1000), // 미리보기용
|
|
2836
|
-
vector,
|
|
2837
|
-
timestamp: new Date().toISOString()
|
|
2838
|
-
});
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
}
|
|
2842
|
-
```
|
|
2843
|
-
|
|
2844
|
-
---
|
|
2845
|
-
|
|
2846
|
-
## Phase 4: Commands & CLI
|
|
2847
|
-
|
|
2848
|
-
### 4.1 Search Command (commands/search.md)
|
|
2849
|
-
|
|
2850
|
-
```markdown
|
|
2851
|
-
---
|
|
2852
|
-
description: Search through your conversation memory
|
|
2853
|
-
---
|
|
2854
|
-
|
|
2855
|
-
# Memory Search
|
|
2856
|
-
|
|
2857
|
-
Search for relevant memories based on your query.
|
|
2858
|
-
|
|
2859
|
-
## Usage
|
|
2860
|
-
|
|
2861
|
-
The user wants to search their conversation memory for: "$ARGUMENTS"
|
|
2862
|
-
|
|
2863
|
-
Search the memory database and return the most relevant past conversations, code snippets, and insights related to the query.
|
|
2864
|
-
|
|
2865
|
-
Display the results in a clear format showing:
|
|
2866
|
-
1. The date of the memory
|
|
2867
|
-
2. A brief excerpt of the content
|
|
2868
|
-
3. The relevance score
|
|
2869
|
-
|
|
2870
|
-
If no relevant memories are found, inform the user and suggest they can build up their memory by having more conversations.
|
|
2871
|
-
```
|
|
2872
|
-
|
|
2873
|
-
### 4.2 CLI Entry Point (src/cli/index.ts)
|
|
2874
|
-
|
|
2875
|
-
```typescript
|
|
2876
|
-
import { Command } from 'commander';
|
|
2877
|
-
import { handleSessionStart } from './commands/session-start';
|
|
2878
|
-
import { handleSearch } from './commands/search';
|
|
2879
|
-
import { handleSave } from './commands/save';
|
|
2880
|
-
import { handleSessionEnd } from './commands/session-end';
|
|
2881
|
-
import { handleInit } from './commands/init';
|
|
2882
|
-
|
|
2883
|
-
const program = new Command();
|
|
2884
|
-
|
|
2885
|
-
program
|
|
2886
|
-
.name('code-memory')
|
|
2887
|
-
.description('Claude Code Memory Plugin CLI')
|
|
2888
|
-
.version('1.0.0');
|
|
2889
|
-
|
|
2890
|
-
program
|
|
2891
|
-
.command('init')
|
|
2892
|
-
.description('Initialize the memory database')
|
|
2893
|
-
.action(handleInit);
|
|
2894
|
-
|
|
2895
|
-
program
|
|
2896
|
-
.command('session-start')
|
|
2897
|
-
.description('Handle session start')
|
|
2898
|
-
.option('--session-id <id>', 'Session ID')
|
|
2899
|
-
.option('--cwd <path>', 'Current working directory')
|
|
2900
|
-
.action(handleSessionStart);
|
|
2901
|
-
|
|
2902
|
-
program
|
|
2903
|
-
.command('search')
|
|
2904
|
-
.description('Search memories')
|
|
2905
|
-
.option('--query <text>', 'Search query')
|
|
2906
|
-
.option('--stdin', 'Read from stdin')
|
|
2907
|
-
.option('--limit <n>', 'Max results', '5')
|
|
2908
|
-
.action(handleSearch);
|
|
2909
|
-
|
|
2910
|
-
program
|
|
2911
|
-
.command('save')
|
|
2912
|
-
.description('Save conversation')
|
|
2913
|
-
.option('--stdin', 'Read from stdin')
|
|
2914
|
-
.action(handleSave);
|
|
2915
|
-
|
|
2916
|
-
program
|
|
2917
|
-
.command('session-end')
|
|
2918
|
-
.description('Handle session end')
|
|
2919
|
-
.option('--stdin', 'Read from stdin')
|
|
2920
|
-
.action(handleSessionEnd);
|
|
2921
|
-
|
|
2922
|
-
program.parse();
|
|
2923
|
-
```
|
|
2924
|
-
|
|
2925
|
-
---
|
|
2926
|
-
|
|
2927
|
-
## Phase 5: Testing & Polish
|
|
2928
|
-
|
|
2929
|
-
### 5.1 테스트 케이스 (tests/event-store.test.ts)
|
|
2930
|
-
|
|
2931
|
-
```typescript
|
|
2932
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2933
|
-
import { EventStore } from '../src/core/event-store';
|
|
2934
|
-
import { unlink } from 'fs/promises';
|
|
2935
|
-
|
|
2936
|
-
describe('EventStore', () => {
|
|
2937
|
-
let store: EventStore;
|
|
2938
|
-
const testDbPath = './test-events.db';
|
|
2939
|
-
|
|
2940
|
-
beforeEach(() => {
|
|
2941
|
-
store = new EventStore(testDbPath);
|
|
2942
|
-
});
|
|
2943
|
-
|
|
2944
|
-
afterEach(async () => {
|
|
2945
|
-
await unlink(testDbPath).catch(() => {});
|
|
2946
|
-
});
|
|
2947
|
-
|
|
2948
|
-
it('should append events with deduplication', async () => {
|
|
2949
|
-
const event = {
|
|
2950
|
-
eventType: 'user_prompt' as const,
|
|
2951
|
-
sessionId: 'test-session',
|
|
2952
|
-
timestamp: new Date(),
|
|
2953
|
-
content: 'Hello, how are you?',
|
|
2954
|
-
metadata: {}
|
|
2955
|
-
};
|
|
2956
|
-
|
|
2957
|
-
// 첫 번째 저장
|
|
2958
|
-
const result1 = await store.append(event);
|
|
2959
|
-
expect(result1.success).toBe(true);
|
|
2960
|
-
expect(result1.isDuplicate).toBe(false);
|
|
2961
|
-
|
|
2962
|
-
// 중복 저장 시도
|
|
2963
|
-
const result2 = await store.append(event);
|
|
2964
|
-
expect(result2.success).toBe(true);
|
|
2965
|
-
expect(result2.isDuplicate).toBe(true);
|
|
2966
|
-
expect(result2.eventId).toBe(result1.eventId);
|
|
2967
|
-
});
|
|
2968
|
-
|
|
2969
|
-
it('should retrieve events by session', async () => {
|
|
2970
|
-
const sessionId = 'test-session';
|
|
2971
|
-
|
|
2972
|
-
await store.append({
|
|
2973
|
-
eventType: 'user_prompt',
|
|
2974
|
-
sessionId,
|
|
2975
|
-
timestamp: new Date(),
|
|
2976
|
-
content: 'First message',
|
|
2977
|
-
metadata: {}
|
|
2978
|
-
});
|
|
2979
|
-
|
|
2980
|
-
await store.append({
|
|
2981
|
-
eventType: 'agent_response',
|
|
2982
|
-
sessionId,
|
|
2983
|
-
timestamp: new Date(),
|
|
2984
|
-
content: 'First response',
|
|
2985
|
-
metadata: {}
|
|
2986
|
-
});
|
|
2987
|
-
|
|
2988
|
-
const events = await store.getSessionEvents(sessionId);
|
|
2989
|
-
expect(events.length).toBe(2);
|
|
2990
|
-
});
|
|
2991
|
-
});
|
|
2992
|
-
```
|
|
2993
|
-
|
|
2994
|
-
### 5.2 통합 테스트 (tests/integration.test.ts)
|
|
2995
|
-
|
|
2996
|
-
```typescript
|
|
2997
|
-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
2998
|
-
import { EventStore } from '../src/core/event-store';
|
|
2999
|
-
import { VectorStore } from '../src/core/vector-store';
|
|
3000
|
-
import { Embedder } from '../src/core/embedder';
|
|
3001
|
-
import { Retriever } from '../src/core/retriever';
|
|
3002
|
-
|
|
3003
|
-
describe('Integration: Memory Retrieval', () => {
|
|
3004
|
-
let eventStore: EventStore;
|
|
3005
|
-
let vectorStore: VectorStore;
|
|
3006
|
-
let embedder: Embedder;
|
|
3007
|
-
let retriever: Retriever;
|
|
3008
|
-
|
|
3009
|
-
beforeAll(async () => {
|
|
3010
|
-
eventStore = new EventStore('./test-integration.db');
|
|
3011
|
-
vectorStore = new VectorStore('./test-integration-vectors');
|
|
3012
|
-
embedder = new Embedder();
|
|
3013
|
-
|
|
3014
|
-
await vectorStore.initialize();
|
|
3015
|
-
await embedder.initialize();
|
|
3016
|
-
|
|
3017
|
-
retriever = new Retriever(eventStore, vectorStore, embedder, {
|
|
3018
|
-
retrieval: { topK: 5, minScore: 0.5, maxTokens: 2000 }
|
|
3019
|
-
});
|
|
3020
|
-
|
|
3021
|
-
// 테스트 데이터 삽입
|
|
3022
|
-
const testData = [
|
|
3023
|
-
{ content: 'How to implement rate limiting in Express?', type: 'user_prompt' },
|
|
3024
|
-
{ content: 'You can use express-rate-limit middleware...', type: 'agent_response' },
|
|
3025
|
-
{ content: 'How to add authentication to my API?', type: 'user_prompt' },
|
|
3026
|
-
{ content: 'Use Passport.js or JWT for authentication...', type: 'agent_response' }
|
|
3027
|
-
];
|
|
3028
|
-
|
|
3029
|
-
for (const data of testData) {
|
|
3030
|
-
const result = await eventStore.append({
|
|
3031
|
-
eventType: data.type as any,
|
|
3032
|
-
sessionId: 'test-session',
|
|
3033
|
-
timestamp: new Date(),
|
|
3034
|
-
content: data.content,
|
|
3035
|
-
metadata: {}
|
|
3036
|
-
});
|
|
3037
|
-
|
|
3038
|
-
const vector = await embedder.embed(data.content);
|
|
3039
|
-
await vectorStore.upsert({
|
|
3040
|
-
id: crypto.randomUUID(),
|
|
3041
|
-
eventId: result.eventId!,
|
|
3042
|
-
sessionId: 'test-session',
|
|
3043
|
-
eventType: data.type,
|
|
3044
|
-
content: data.content,
|
|
3045
|
-
vector,
|
|
3046
|
-
timestamp: new Date().toISOString()
|
|
3047
|
-
});
|
|
3048
|
-
}
|
|
3049
|
-
});
|
|
3050
|
-
|
|
3051
|
-
it('should find relevant memories', async () => {
|
|
3052
|
-
const matches = await retriever.search('rate limiting');
|
|
3053
|
-
|
|
3054
|
-
expect(matches.length).toBeGreaterThan(0);
|
|
3055
|
-
expect(matches[0].event.content).toContain('rate limiting');
|
|
3056
|
-
});
|
|
3057
|
-
|
|
3058
|
-
it('should format context correctly', () => {
|
|
3059
|
-
const matches = [
|
|
3060
|
-
{
|
|
3061
|
-
event: {
|
|
3062
|
-
id: '1',
|
|
3063
|
-
eventType: 'user_prompt',
|
|
3064
|
-
sessionId: 'test',
|
|
3065
|
-
timestamp: new Date(),
|
|
3066
|
-
content: 'Test content',
|
|
3067
|
-
contentHash: 'hash'
|
|
3068
|
-
},
|
|
3069
|
-
score: 0.95,
|
|
3070
|
-
relevanceReason: 'High similarity'
|
|
3071
|
-
}
|
|
3072
|
-
];
|
|
3073
|
-
|
|
3074
|
-
const context = retriever.formatContext(matches);
|
|
3075
|
-
expect(context).toContain('Relevant Memories');
|
|
3076
|
-
expect(context).toContain('Test content');
|
|
3077
|
-
});
|
|
3078
|
-
});
|
|
3079
|
-
```
|
|
3080
|
-
|
|
3081
|
-
### 5.3 빌드 스크립트 (scripts/build.ts)
|
|
3082
|
-
|
|
3083
|
-
```typescript
|
|
3084
|
-
import * as esbuild from 'esbuild';
|
|
3085
|
-
|
|
3086
|
-
async function build() {
|
|
3087
|
-
// CLI 빌드
|
|
3088
|
-
await esbuild.build({
|
|
3089
|
-
entryPoints: ['src/cli/index.ts'],
|
|
3090
|
-
bundle: true,
|
|
3091
|
-
platform: 'node',
|
|
3092
|
-
target: 'node18',
|
|
3093
|
-
outfile: 'dist/cli.js',
|
|
3094
|
-
external: ['duckdb', 'lancedb', '@xenova/transformers']
|
|
3095
|
-
});
|
|
3096
|
-
|
|
3097
|
-
console.log('Build complete!');
|
|
3098
|
-
}
|
|
3099
|
-
|
|
3100
|
-
build().catch(console.error);
|
|
3101
|
-
```
|
|
3102
|
-
|
|
3103
|
-
---
|
|
3104
|
-
|
|
3105
|
-
## 마일스톤 체크리스트
|
|
3106
|
-
|
|
3107
|
-
### Phase 0: 프로젝트 설정
|
|
3108
|
-
- [ ] 디렉토리 구조 생성
|
|
3109
|
-
- [ ] package.json 초기화
|
|
3110
|
-
- [ ] 의존성 설치
|
|
3111
|
-
- [ ] TypeScript 설정
|
|
3112
|
-
- [ ] plugin.json 생성
|
|
3113
|
-
|
|
3114
|
-
### Phase 1: Core Storage Layer
|
|
3115
|
-
- [ ] types.ts - Zod 스키마 정의
|
|
3116
|
-
- [ ] event-store.ts - DuckDB 연동
|
|
3117
|
-
- [ ] vector-store.ts - LanceDB 연동
|
|
3118
|
-
- [ ] 단위 테스트
|
|
3119
|
-
|
|
3120
|
-
### Phase 2: Embedding & Retrieval
|
|
3121
|
-
- [ ] embedder.ts - 로컬 임베딩
|
|
3122
|
-
- [ ] retriever.ts - 검색 로직
|
|
3123
|
-
- [ ] 컨텍스트 포맷터
|
|
3124
|
-
- [ ] 단위 테스트
|
|
3125
|
-
|
|
3126
|
-
### Phase 3: Hook Integration
|
|
3127
|
-
- [ ] hooks.json 설정
|
|
3128
|
-
- [ ] session-start hook
|
|
3129
|
-
- [ ] user-prompt-submit hook
|
|
3130
|
-
- [ ] stop hook
|
|
3131
|
-
- [ ] session-end hook
|
|
3132
|
-
|
|
3133
|
-
### Phase 4: Commands & CLI
|
|
3134
|
-
- [ ] CLI 엔트리포인트
|
|
3135
|
-
- [ ] search 명령어
|
|
3136
|
-
- [ ] history 명령어
|
|
3137
|
-
- [ ] forget 명령어
|
|
3138
|
-
- [ ] stats 명령어
|
|
3139
|
-
|
|
3140
|
-
### Phase 5: Testing & Polish
|
|
3141
|
-
- [ ] 통합 테스트
|
|
3142
|
-
- [ ] README.md
|
|
3143
|
-
- [ ] 에러 처리 개선
|
|
3144
|
-
- [ ] 성능 최적화
|
|
3145
|
-
- [ ] 첫 릴리스 준비
|
|
3146
|
-
|
|
3147
|
-
---
|
|
3148
|
-
|
|
3149
|
-
## 리스크 및 대응
|
|
3150
|
-
|
|
3151
|
-
| 리스크 | 영향 | 대응 |
|
|
3152
|
-
|--------|------|------|
|
|
3153
|
-
| 임베딩 모델 로드 시간 | 세션 시작 지연 | 모델 캐싱, 지연 로드 |
|
|
3154
|
-
| 대용량 대화 처리 | 메모리 부족 | 스트리밍, 배치 처리 |
|
|
3155
|
-
| DuckDB/LanceDB 호환성 | 설치 실패 | fallback 구현, 순수 JS 대안 |
|
|
3156
|
-
| Hook 타임아웃 | 기능 미작동 | 비동기 처리, 캐싱 |
|
|
3157
|
-
|
|
3158
|
-
---
|
|
3159
|
-
|
|
3160
|
-
## 다음 단계
|
|
3161
|
-
|
|
3162
|
-
1. **Phase 0 완료 후**: 기본 플러그인 구조 동작 확인
|
|
3163
|
-
2. **Phase 1-2 완료 후**: 기억 저장/검색 기능 데모
|
|
3164
|
-
3. **Phase 3-4 완료 후**: 실제 Claude Code에서 테스트
|
|
3165
|
-
4. **Phase 5 완료 후**: 커뮤니티 마켓플레이스 등록
|
|
3166
|
-
|
|
3167
|
-
## 2026-02-25T12:31:26.199Z | 5808e4d1-65b8-46d8-8745-b6208eafa711
|
|
3168
|
-
- type: session_summary
|
|
3169
|
-
- session: import:organized
|
|
3170
|
-
# Specification: Claude Code Memory Plugin
|
|
3171
|
-
|
|
3172
|
-
## 1. 개요
|
|
3173
|
-
|
|
3174
|
-
### 1.1 플러그인 정보
|
|
3175
|
-
|
|
3176
|
-
| 항목 | 값 |
|
|
3177
|
-
|------|-----|
|
|
3178
|
-
| **이름** | `code-memory` |
|
|
3179
|
-
| **버전** | `1.0.0` |
|
|
3180
|
-
| **설명** | 대화 기억을 통해 사용자 맞춤형 경험을 제공하는 Claude Code 플러그인 |
|
|
3181
|
-
| **핵심 가치** | "사용할수록 똑똑해지는 Agent" |
|
|
3182
|
-
|
|
3183
|
-
### 1.2 핵심 기능
|
|
3184
|
-
|
|
3185
|
-
1. **대화 기억 저장**: 모든 사용자 prompt와 agent 응답을 영구 저장
|
|
3186
|
-
2. **지능형 검색**: 새로운 prompt와 관련된 과거 기억을 의미 기반 검색
|
|
3187
|
-
3. **컨텍스트 주입**: 관련 기억을 현재 대화에 자동 주입
|
|
3188
|
-
4. **학습 및 진화**: 패턴 인식을 통한 개인화
|
|
3189
|
-
|
|
3190
|
-
---
|
|
3191
|
-
|
|
3192
|
-
## 2. 아키텍처
|
|
3193
|
-
|
|
3194
|
-
### 2.1 시스템 구조
|
|
3195
|
-
|
|
3196
|
-
```
|
|
3197
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
3198
|
-
│ Claude Code Session │
|
|
3199
|
-
└─────────────────────────────────────────────────────────────┘
|
|
3200
|
-
│ │ │
|
|
3201
|
-
▼ ▼ ▼
|
|
3202
|
-
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
3203
|
-
│ SessionStart│ │UserPrompt │ │ Stop/ │
|
|
3204
|
-
│ Hook │ │Submit Hook │ │ SessionEnd │
|
|
3205
|
-
└─────────────┘ └─────────────┘ └─────────────┘
|
|
3206
|
-
│ │ │
|
|
3207
|
-
▼ ▼ ▼
|
|
3208
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
3209
|
-
│ Memory Service (Core) │
|
|
3210
|
-
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
3211
|
-
│ │ Ingester │ │ Embedder │ │ Retriever│ │ Ranker │ │
|
|
3212
|
-
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|
3213
|
-
└─────────────────────────────────────────────────────────────┘
|
|
3214
|
-
│ │ │
|
|
3215
|
-
▼ ▼ ▼
|
|
3216
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
3217
|
-
│ Storage Layer │
|
|
3218
|
-
│ ┌───────────────────┐ ┌───────────────────┐ │
|
|
3219
|
-
│ │ LanceDB │ │ DuckDB │ │
|
|
3220
|
-
│ │ (Vector Store) │ │ (Event Store) │ │
|
|
3221
|
-
│ └───────────────────┘ └───────────────────┘ │
|
|
3222
|
-
└─────────────────────────────────────────────────────────────┘
|
|
3223
|
-
```
|
|
3224
|
-
|
|
3225
|
-
### 2.2 데이터 흐름
|
|
3226
|
-
|
|
3227
|
-
```
|
|
3228
|
-
1. [SessionStart]
|
|
3229
|
-
→ 이전 세션 요약 로드
|
|
3230
|
-
→ 사용자 선호도/패턴 로드
|
|
3231
|
-
|
|
3232
|
-
2. [UserPromptSubmit]
|
|
3233
|
-
→ 현재 prompt 임베딩 생성
|
|
3234
|
-
→ 관련 기억 검색 (top-k)
|
|
3235
|
-
→ 기억을 시스템 프롬프트로 주입
|
|
3236
|
-
|
|
3237
|
-
3. [Stop/AgentResponse]
|
|
3238
|
-
→ 전체 대화 쌍 (prompt + response) 저장
|
|
3239
|
-
→ 비동기 임베딩 생성 및 인덱싱
|
|
3240
|
-
|
|
3241
|
-
4. [SessionEnd]
|
|
3242
|
-
→ 세션 요약 생성 및 저장
|
|
3243
|
-
→ 장기 기억으로 통합
|
|
3244
|
-
```
|
|
3245
|
-
|
|
3246
|
-
### 2.3 Memory Graduation Pipeline (L0 → L4)
|
|
3247
|
-
|
|
3248
|
-
AXIOMMIND 기반 다단계 메모리 승격 구조:
|
|
3249
|
-
|
|
3250
|
-
| 레벨 | 이름 | 설명 | 저장소 | 상태 |
|
|
3251
|
-
|------|------|------|--------|------|
|
|
3252
|
-
| **L0** | EventStore | 원본 대화 로그 (불변) | DuckDB `events` | 즉시 저장 |
|
|
3253
|
-
| **L1** | Structured | LLM 추출 구조화 데이터 | DuckDB `insights` | 비동기 처리 |
|
|
3254
|
-
| **L2** | Candidates | 타입 검증 대상 | TypeScript 검증 | 배치 처리 |
|
|
3255
|
-
| **L3** | Verified | 검증 완료 지식 | DuckDB `verified_knowledge` | 검증 후 |
|
|
3256
|
-
| **L4** | Active | 검색 가능 메모리 | LanceDB | 인덱싱 후 |
|
|
3257
|
-
|
|
3258
|
-
```
|
|
3259
|
-
User Prompt → L0 (즉시) → L1 (비동기) → L2 (배치) → L3 (검증) → L4 (검색 가능)
|
|
3260
|
-
↑ ↓
|
|
3261
|
-
└──────────── 검색 시 L4에서 조회 ─────────────┘
|
|
3262
|
-
```
|
|
3263
|
-
|
|
3264
|
-
### 2.4 AXIOMMIND 7가지 필수 원칙
|
|
3265
|
-
|
|
3266
|
-
본 플러그인은 다음 원칙을 준수합니다:
|
|
3267
|
-
|
|
3268
|
-
| # | 원칙 | 구현 |
|
|
3269
|
-
|---|------|------|
|
|
3270
|
-
| 1 | 진실의 원천은 이벤트 로그 | `events` 테이블에서 모든 파생 데이터 재구성 가능 |
|
|
3271
|
-
| 2 | 추가전용 구조 | `EventStore.append()` 만 제공, UPDATE/DELETE 없음 |
|
|
3272
|
-
| 3 | 멱등성 보장 | `dedupe_key = session_id + content_hash` |
|
|
3273
|
-
| 4 | 증거 범위는 파이프라인이 확정 | `EvidenceAligner`가 정확한 스팬 계산 |
|
|
3274
|
-
| 5 | Task는 엔티티 | `canonical_key`로 동일 개념 통합 |
|
|
3275
|
-
| 6 | 벡터 저장소 정합성 | DuckDB → outbox → LanceDB 단방향 |
|
|
3276
|
-
| 7 | DuckDB JSON 사용 | JSONB 대신 표준 JSON |
|
|
3277
|
-
|
|
3278
|
-
---
|
|
3279
|
-
|
|
3280
|
-
## 3. 데이터 모델
|
|
3281
|
-
|
|
3282
|
-
### 3.1 Event Schema (DuckDB) - AXIOMMIND 스타일
|
|
3283
|
-
|
|
3284
|
-
```sql
|
|
3285
|
-
-- ============================================================
|
|
3286
|
-
-- L0 EventStore: Single Source of Truth (불변, append-only)
|
|
3287
|
-
-- ============================================================
|
|
3288
|
-
|
|
3289
|
-
CREATE TABLE events (
|
|
3290
|
-
id UUID PRIMARY KEY,
|
|
3291
|
-
event_type VARCHAR NOT NULL, -- 'user_prompt' | 'agent_response' | 'session_summary'
|
|
3292
|
-
session_id VARCHAR NOT NULL,
|
|
3293
|
-
timestamp TIMESTAMP NOT NULL,
|
|
3294
|
-
content TEXT NOT NULL,
|
|
3295
|
-
canonical_key VARCHAR NOT NULL, -- 정규화된 키 (NFKC, lowercase, no punctuation)
|
|
3296
|
-
metadata JSON,
|
|
3297
|
-
dedupe_key VARCHAR UNIQUE -- 멱등성 보장 (content_hash + session_id)
|
|
3298
|
-
);
|
|
3299
|
-
|
|
3300
|
-
-- 중복 방지 테이블 (event_dedup)
|
|
3301
|
-
CREATE TABLE event_dedup (
|
|
3302
|
-
dedupe_key VARCHAR PRIMARY KEY,
|
|
3303
|
-
event_id UUID NOT NULL REFERENCES events(id),
|
|
3304
|
-
created_at TIMESTAMP DEFAULT NOW()
|
|
3305
|
-
);
|
|
3306
|
-
|
|
3307
|
-
-- Projection offset 추적 (증분 처리용)
|
|
3308
|
-
CREATE TABLE projection_offsets (
|
|
3309
|
-
projection_name VARCHAR PRIMARY KEY,
|
|
3310
|
-
last_event_id UUID,
|
|
3311
|
-
last_timestamp TIMESTAMP,
|
|
3312
|
-
updated_at TIMESTAMP DEFAULT NOW()
|
|
3313
|
-
);
|
|
3314
|
-
|
|
3315
|
-
-- ============================================================
|
|
3316
|
-
-- 세션 메타데이터
|
|
3317
|
-
-- ============================================================
|
|
3318
|
-
|
|
3319
|
-
CREATE TABLE sessions (
|
|
3320
|
-
id VARCHAR PRIMARY KEY,
|
|
3321
|
-
started_at TIMESTAMP NOT NULL,
|
|
3322
|
-
ended_at TIMESTAMP,
|
|
3323
|
-
project_path VARCHAR,
|
|
3324
|
-
summary TEXT,
|
|
3325
|
-
tags JSON
|
|
3326
|
-
);
|
|
3327
|
-
|
|
3328
|
-
-- ============================================================
|
|
3329
|
-
-- 추출된 인사이트 (파생 데이터, 재구성 가능)
|
|
3330
|
-
-- ============================================================
|
|
3331
|
-
|
|
3332
|
-
CREATE TABLE insights (
|
|
3333
|
-
id UUID PRIMARY KEY,
|
|
3334
|
-
insight_type VARCHAR NOT NULL, -- 'preference' | 'pattern' | 'expertise'
|
|
3335
|
-
content TEXT NOT NULL,
|
|
3336
|
-
canonical_key VARCHAR NOT NULL, -- 정규화된 키
|
|
3337
|
-
confidence FLOAT,
|
|
3338
|
-
source_events JSON, -- 원본 이벤트 ID 목록
|
|
3339
|
-
created_at TIMESTAMP,
|
|
3340
|
-
last_updated TIMESTAMP
|
|
3341
|
-
);
|
|
3342
|
-
|
|
3343
|
-
-- ============================================================
|
|
3344
|
-
-- Embedding Outbox (Single-Writer Pattern)
|
|
3345
|
-
-- ============================================================
|
|
3346
|
-
|
|
3347
|
-
CREATE TABLE embedding_outbox (
|
|
3348
|
-
id UUID PRIMARY KEY,
|
|
3349
|
-
event_id UUID NOT NULL REFERENCES events(id),
|
|
3350
|
-
content TEXT NOT NULL,
|
|
3351
|
-
status VARCHAR DEFAULT 'pending', -- 'pending' | 'processing' | 'done' | 'failed'
|
|
3352
|
-
retry_count INT DEFAULT 0,
|
|
3353
|
-
created_at TIMESTAMP DEFAULT NOW(),
|
|
3354
|
-
processed_at TIMESTAMP,
|
|
3355
|
-
error_message TEXT
|
|
3356
|
-
);
|
|
3357
|
-
|
|
3358
|
-
-- ============================================================
|
|
3359
|
-
-- Memory Resolutions (Condition → Task 해결)
|
|
3360
|
-
-- ============================================================
|
|
3361
|
-
|
|
3362
|
-
CREATE TABLE memory_resolutions (
|
|
3363
|
-
id UUID PRIMARY KEY,
|
|
3364
|
-
condition_id UUID NOT NULL, -- 원본 조건/참조
|
|
3365
|
-
resolved_to_id UUID, -- 해결된 대상
|
|
3366
|
-
resolution_type VARCHAR, -- 'confirmed' | 'rejected' | 'pending'
|
|
3367
|
-
confidence FLOAT,
|
|
3368
|
-
resolved_at TIMESTAMP
|
|
3369
|
-
);
|
|
3370
|
-
|
|
3371
|
-
-- ============================================================
|
|
3372
|
-
-- Effective View (Condition 해결 반영)
|
|
3373
|
-
-- ============================================================
|
|
3374
|
-
|
|
3375
|
-
CREATE VIEW v_memory_context_effective AS
|
|
3376
|
-
SELECT
|
|
3377
|
-
e.id,
|
|
3378
|
-
e.session_id,
|
|
3379
|
-
e.content,
|
|
3380
|
-
e.canonical_key,
|
|
3381
|
-
e.event_type,
|
|
3382
|
-
e.timestamp,
|
|
3383
|
-
COALESCE(r.resolved_to_id, e.id) as effective_id,
|
|
3384
|
-
CASE
|
|
3385
|
-
WHEN r.resolution_type = 'confirmed' THEN 'resolved'
|
|
3386
|
-
WHEN r.resolution_type = 'pending' THEN 'pending'
|
|
3387
|
-
ELSE 'direct'
|
|
3388
|
-
END as resolution_status
|
|
3389
|
-
FROM events e
|
|
3390
|
-
LEFT JOIN memory_resolutions r ON e.id = r.condition_id;
|
|
3391
|
-
```
|
|
3392
|
-
|
|
3393
|
-
### 3.2 Vector Schema (LanceDB)
|
|
3394
|
-
|
|
3395
|
-
```python
|
|
3396
|
-
# 대화 임베딩 테이블
|
|
3397
|
-
conversations_schema = {
|
|
3398
|
-
"id": str, # UUID
|
|
3399
|
-
"event_id": str, # events 테이블 참조
|
|
3400
|
-
"session_id": str,
|
|
3401
|
-
"event_type": str, # 'user_prompt' | 'agent_response'
|
|
3402
|
-
"content": str, # 원본 텍스트 (검색 결과 표시용)
|
|
3403
|
-
"vector": list[float], # 임베딩 벡터 (384 또는 1536 차원)
|
|
3404
|
-
"timestamp": str,
|
|
3405
|
-
"metadata": dict # 추가 메타데이터
|
|
3406
|
-
}
|
|
3407
|
-
|
|
3408
|
-
# 인사이트 임베딩 테이블
|
|
3409
|
-
insights_schema = {
|
|
3410
|
-
"id": str,
|
|
3411
|
-
"insight_id": str, # insights 테이블 참조
|
|
3412
|
-
"content": str,
|
|
3413
|
-
"vector": list[float],
|
|
3414
|
-
"insight_type": str,
|
|
3415
|
-
"confidence": float
|
|
3416
|
-
}
|
|
3417
|
-
```
|
|
3418
|
-
|
|
3419
|
-
### 3.3 TypeScript 타입 정의 (Idris2 영감)
|
|
3420
|
-
|
|
3421
|
-
```typescript
|
|
3422
|
-
// 불변성과 타입 안전성을 강조한 설계
|
|
3423
|
-
|
|
3424
|
-
// 이벤트 타입 (Union Type으로 완전성 보장)
|
|
3425
|
-
type EventType = 'user_prompt' | 'agent_response' | 'session_summary';
|
|
3426
|
-
|
|
3427
|
-
// 이벤트 구조 (Readonly로 불변성 강제)
|
|
3428
|
-
interface MemoryEvent {
|
|
3429
|
-
readonly id: string;
|
|
3430
|
-
readonly eventType: EventType;
|
|
3431
|
-
readonly sessionId: string;
|
|
3432
|
-
readonly timestamp: Date;
|
|
3433
|
-
readonly content: string;
|
|
3434
|
-
readonly contentHash: string;
|
|
3435
|
-
readonly metadata: Readonly<Record<string, unknown>>;
|
|
3436
|
-
}
|
|
3437
|
-
|
|
3438
|
-
// 검색 결과 (신뢰도 점수 포함)
|
|
3439
|
-
interface MemoryMatch {
|
|
3440
|
-
readonly event: MemoryEvent;
|
|
3441
|
-
readonly score: number; // 0.0 ~ 1.0
|
|
3442
|
-
readonly relevanceReason: string;
|
|
3443
|
-
}
|
|
3444
|
-
|
|
3445
|
-
// 컨텍스트 주입 결과
|
|
3446
|
-
interface ContextInjection {
|
|
3447
|
-
readonly memories: ReadonlyArray<MemoryMatch>;
|
|
3448
|
-
readonly systemPromptAddition: string;
|
|
3449
|
-
readonly totalTokensUsed: number;
|
|
3450
|
-
}
|
|
3451
|
-
|
|
3452
|
-
// 저장 결과 (성공/실패 명시적 표현)
|
|
3453
|
-
type SaveResult =
|
|
3454
|
-
| { success: true; eventId: string }
|
|
3455
|
-
| { success: false; error: string; isDuplicate: boolean };
|
|
3456
|
-
```
|
|
3457
|
-
|
|
3458
|
-
---
|
|
3459
|
-
|
|
3460
|
-
## 4. Hook 명세
|
|
3461
|
-
|
|
3462
|
-
### 4.1 SessionStart Hook
|
|
3463
|
-
|
|
3464
|
-
**목적**: 세션 시작 시 관련 컨텍스트 로드
|
|
3465
|
-
|
|
3466
|
-
```json
|
|
3467
|
-
{
|
|
3468
|
-
"hooks": {
|
|
3469
|
-
"SessionStart": [
|
|
3470
|
-
{
|
|
3471
|
-
"type": "command",
|
|
3472
|
-
"command": "code-memory session-start",
|
|
3473
|
-
"timeout": 5000
|
|
3474
|
-
}
|
|
3475
|
-
]
|
|
3476
|
-
}
|
|
3477
|
-
}
|
|
3478
|
-
```
|
|
3479
|
-
|
|
3480
|
-
**입력**:
|
|
3481
|
-
```json
|
|
3482
|
-
{
|
|
3483
|
-
"session_id": "sess_abc123",
|
|
3484
|
-
"cwd": "/path/to/project"
|
|
3485
|
-
}
|
|
3486
|
-
```
|
|
3487
|
-
|
|
3488
|
-
**출력**:
|
|
3489
|
-
```json
|
|
3490
|
-
{
|
|
3491
|
-
"context": "## Previous Session Context\n- Last worked on: API authentication\n- User preference: Prefers TypeScript\n- Recent patterns: Uses Zod for validation"
|
|
3492
|
-
}
|
|
3493
|
-
```
|
|
3494
|
-
|
|
3495
|
-
### 4.2 UserPromptSubmit Hook
|
|
3496
|
-
|
|
3497
|
-
**목적**: 사용자 입력 시 관련 기억 검색 및 주입
|
|
3498
|
-
|
|
3499
|
-
```json
|
|
3500
|
-
{
|
|
3501
|
-
"hooks": {
|
|
3502
|
-
"UserPromptSubmit": [
|
|
3503
|
-
{
|
|
3504
|
-
"type": "command",
|
|
3505
|
-
"command": "code-memory search",
|
|
3506
|
-
"timeout": 3000
|
|
3507
|
-
}
|
|
3508
|
-
]
|
|
3509
|
-
}
|
|
3510
|
-
}
|
|
3511
|
-
```
|
|
3512
|
-
|
|
3513
|
-
**입력**:
|
|
3514
|
-
```json
|
|
3515
|
-
{
|
|
3516
|
-
"session_id": "sess_abc123",
|
|
3517
|
-
"prompt": "How do I add rate limiting to the API?"
|
|
3518
|
-
}
|
|
3519
|
-
```
|
|
3520
|
-
|
|
3521
|
-
**출력**:
|
|
3522
|
-
```json
|
|
3523
|
-
{
|
|
3524
|
-
"context": "## Relevant Memories\n\n### Previous Discussion (2 weeks ago)\nYou implemented rate limiting for the /users endpoint using express-rate-limit...\n\n### Your Preferences\n- Prefers middleware-based solutions\n- Uses Redis for distributed rate limiting"
|
|
3525
|
-
}
|
|
3526
|
-
```
|
|
3527
|
-
|
|
3528
|
-
### 4.3 Stop Hook
|
|
3529
|
-
|
|
3530
|
-
**목적**: Agent 응답 완료 시 대화 저장
|
|
3531
|
-
|
|
3532
|
-
```json
|
|
3533
|
-
{
|
|
3534
|
-
"hooks": {
|
|
3535
|
-
"Stop": [
|
|
3536
|
-
{
|
|
3537
|
-
"type": "command",
|
|
3538
|
-
"command": "code-memory save",
|
|
3539
|
-
"timeout": 5000
|
|
3540
|
-
}
|
|
3541
|
-
]
|
|
3542
|
-
}
|
|
3543
|
-
}
|
|
3544
|
-
```
|
|
3545
|
-
|
|
3546
|
-
**입력**:
|
|
3547
|
-
```json
|
|
3548
|
-
{
|
|
3549
|
-
"session_id": "sess_abc123",
|
|
3550
|
-
"stop_reason": "end_turn",
|
|
3551
|
-
"messages": [
|
|
3552
|
-
{"role": "user", "content": "..."},
|
|
3553
|
-
{"role": "assistant", "content": "..."}
|
|
3554
|
-
]
|
|
3555
|
-
}
|
|
3556
|
-
```
|
|
3557
|
-
|
|
3558
|
-
### 4.4 SessionEnd Hook
|
|
3559
|
-
|
|
3560
|
-
**목적**: 세션 종료 시 요약 저장
|
|
3561
|
-
|
|
3562
|
-
```json
|
|
3563
|
-
{
|
|
3564
|
-
"hooks": {
|
|
3565
|
-
"SessionEnd": [
|
|
3566
|
-
{
|
|
3567
|
-
"type": "command",
|
|
3568
|
-
"command": "code-memory session-end",
|
|
3569
|
-
"timeout": 10000
|
|
3570
|
-
}
|
|
3571
|
-
]
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
```
|
|
3575
|
-
|
|
3576
|
-
---
|
|
3577
|
-
|
|
3578
|
-
## 5. 명령어 인터페이스
|
|
3579
|
-
|
|
3580
|
-
### 5.1 슬래시 명령어
|
|
3581
|
-
|
|
3582
|
-
| 명령어 | 설명 | 예시 |
|
|
3583
|
-
|--------|------|------|
|
|
3584
|
-
| `/code-memory:search` | 기억 수동 검색 | `/code-memory:search rate limiting` |
|
|
3585
|
-
| `/code-memory:history` | 최근 대화 이력 | `/code-memory:history 10` |
|
|
3586
|
-
| `/code-memory:insights` | 추출된 인사이트 보기 | `/code-memory:insights` |
|
|
3587
|
-
| `/code-memory:forget` | 특정 기억 삭제 | `/code-memory:forget <id>` |
|
|
3588
|
-
| `/code-memory:export` | 기억 내보내기 | `/code-memory:export json` |
|
|
3589
|
-
| `/code-memory:stats` | 통계 보기 | `/code-memory:stats` |
|
|
3590
|
-
|
|
3591
|
-
### 5.2 CLI 명령어 (Hook에서 호출)
|
|
3592
|
-
|
|
3593
|
-
```bash
|
|
3594
|
-
# 세션 시작
|
|
3595
|
-
code-memory session-start --session-id <id> --cwd <path>
|
|
3596
|
-
|
|
3597
|
-
# 기억 검색
|
|
3598
|
-
code-memory search --query <text> --limit 5 --threshold 0.7
|
|
3599
|
-
|
|
3600
|
-
# 대화 저장
|
|
3601
|
-
code-memory save --stdin # JSON 입력 수신
|
|
3602
|
-
|
|
3603
|
-
# 세션 종료
|
|
3604
|
-
code-memory session-end --session-id <id>
|
|
3605
|
-
|
|
3606
|
-
# 데이터베이스 초기화
|
|
3607
|
-
code-memory init
|
|
3608
|
-
|
|
3609
|
-
# 임베딩 재생성
|
|
3610
|
-
code-memory reindex
|
|
3611
|
-
```
|
|
3612
|
-
|
|
3613
|
-
---
|
|
3614
|
-
|
|
3615
|
-
## 6. 설정
|
|
3616
|
-
|
|
3617
|
-
### 6.1 plugin.json
|
|
3618
|
-
|
|
3619
|
-
```json
|
|
3620
|
-
{
|
|
3621
|
-
"name": "code-memory",
|
|
3622
|
-
"description": "Learn from conversations to provide personalized assistance",
|
|
3623
|
-
"version": "1.0.0",
|
|
3624
|
-
"author": {
|
|
3625
|
-
"name": "Buzzni"
|
|
3626
|
-
},
|
|
3627
|
-
"homepage": "https://github.com/buzzni/code-memory",
|
|
3628
|
-
"repository": {
|
|
3629
|
-
"type": "git",
|
|
3630
|
-
"url": "https://github.com/buzzni/code-memory.git"
|
|
3631
|
-
},
|
|
3632
|
-
"license": "MIT",
|
|
3633
|
-
"engines": {
|
|
3634
|
-
"claude-code": ">=1.0.33"
|
|
3635
|
-
},
|
|
3636
|
-
"keywords": ["memory", "learning", "personalization", "context"]
|
|
3637
|
-
}
|
|
3638
|
-
```
|
|
3639
|
-
|
|
3640
|
-
### 6.2 사용자 설정 (config.json)
|
|
3641
|
-
|
|
3642
|
-
```json
|
|
3643
|
-
{
|
|
3644
|
-
"storage": {
|
|
3645
|
-
"path": "~/.claude-code/memory",
|
|
3646
|
-
"maxSizeMB": 500
|
|
3647
|
-
},
|
|
3648
|
-
"embedding": {
|
|
3649
|
-
"provider": "local", // "local" | "openai"
|
|
3650
|
-
"model": "all-MiniLM-L6-v2", // local 모델
|
|
3651
|
-
"openaiModel": "text-embedding-3-small",
|
|
3652
|
-
"batchSize": 32
|
|
3653
|
-
},
|
|
3654
|
-
"retrieval": {
|
|
3655
|
-
"topK": 5,
|
|
3656
|
-
"minScore": 0.7,
|
|
3657
|
-
"maxTokens": 2000 // 주입할 최대 토큰 수
|
|
3658
|
-
},
|
|
3659
|
-
"matching": {
|
|
3660
|
-
"minCombinedScore": 0.92, // 확정 매칭 최소 점수 (AXIOMMIND)
|
|
3661
|
-
"minGap": 0.03, // 1위-2위 간 최소 점수 차이
|
|
3662
|
-
"suggestionThreshold": 0.75, // 제안 모드 임계값
|
|
3663
|
-
"weights": {
|
|
3664
|
-
"semanticSimilarity": 0.4, // 벡터 유사도 가중치
|
|
3665
|
-
"ftsScore": 0.25, // 전문 검색 가중치
|
|
3666
|
-
"recencyBonus": 0.2, // 최신성 가산점
|
|
3667
|
-
"statusWeight": 0.15 // 상태별 가중치
|
|
3668
|
-
}
|
|
3669
|
-
},
|
|
3670
|
-
"privacy": {
|
|
3671
|
-
"excludePatterns": [ // 저장 제외 패턴
|
|
3672
|
-
"password",
|
|
3673
|
-
"secret",
|
|
3674
|
-
"api_key"
|
|
3675
|
-
],
|
|
3676
|
-
"anonymize": false
|
|
3677
|
-
},
|
|
3678
|
-
"features": {
|
|
3679
|
-
"autoSave": true,
|
|
3680
|
-
"sessionSummary": true,
|
|
3681
|
-
"insightExtraction": true,
|
|
3682
|
-
"crossProjectLearning": false, // 프로젝트 간 학습
|
|
3683
|
-
"singleWriterMode": true // Outbox 패턴 사용 (권장)
|
|
3684
|
-
}
|
|
3685
|
-
}
|
|
3686
|
-
```
|
|
3687
|
-
|
|
3688
|
-
### 6.3 Matching Thresholds (AXIOMMIND 기반)
|
|
3689
|
-
|
|
3690
|
-
검색 결과의 신뢰도를 3단계로 분류:
|
|
3691
|
-
|
|
3692
|
-
| 신뢰도 | 조건 | 동작 |
|
|
3693
|
-
|--------|------|------|
|
|
3694
|
-
| **high** | score ≥ 0.92 AND gap ≥ 0.03 | 확정 매칭, 자동 컨텍스트 주입 |
|
|
3695
|
-
| **suggested** | 0.75 ≤ score < 0.92 | 제안 모드, 사용자 확인 권장 |
|
|
3696
|
-
| **none** | score < 0.75 | 매칭 없음 |
|
|
3697
|
-
|
|
3698
|
-
```typescript
|
|
3699
|
-
// Matching 결과 타입
|
|
3700
|
-
interface MatchResult {
|
|
3701
|
-
readonly match: MemoryMatch | null;
|
|
3702
|
-
readonly confidence: 'high' | 'suggested' | 'none';
|
|
3703
|
-
readonly gap?: number; // top-1과 top-2 간 점수 차이
|
|
3704
|
-
readonly alternatives?: ReadonlyArray<MemoryMatch>; // suggested일 때 대안들
|
|
3705
|
-
}
|
|
3706
|
-
```
|
|
3707
|
-
|
|
3708
|
-
---
|
|
3709
|
-
|
|
3710
|
-
## 7. 보안 및 프라이버시
|
|
3711
|
-
|
|
3712
|
-
### 7.1 데이터 보호
|
|
3713
|
-
|
|
3714
|
-
1. **로컬 저장**: 모든 데이터는 사용자 로컬에만 저장
|
|
3715
|
-
2. **민감 정보 필터링**: password, secret, api_key 등 자동 제외
|
|
3716
|
-
3. **선택적 익명화**: 개인 식별 정보 마스킹 옵션
|
|
3717
|
-
|
|
3718
|
-
### 7.2 데이터 삭제
|
|
3719
|
-
|
|
3720
|
-
```bash
|
|
3721
|
-
# 특정 기억 삭제
|
|
3722
|
-
code-memory forget --id <event_id>
|
|
3723
|
-
|
|
3724
|
-
# 세션 전체 삭제
|
|
3725
|
-
code-memory forget --session <session_id>
|
|
3726
|
-
|
|
3727
|
-
# 기간별 삭제
|
|
3728
|
-
code-memory forget --before "2024-01-01"
|
|
3729
|
-
|
|
3730
|
-
# 전체 초기화
|
|
3731
|
-
code-memory reset --confirm
|
|
3732
|
-
```
|
|
3733
|
-
|
|
3734
|
-
---
|
|
3735
|
-
|
|
3736
|
-
## 8. 성능 요구사항
|
|
3737
|
-
|
|
3738
|
-
| 항목 | 목표 | 비고 |
|
|
3739
|
-
|------|------|------|
|
|
3740
|
-
| **검색 지연** | < 500ms | 10만 건 기준 |
|
|
3741
|
-
| **저장 지연** | < 100ms | 비동기 처리 |
|
|
3742
|
-
| **메모리 사용** | < 200MB | 실행 시 |
|
|
3743
|
-
| **디스크 사용** | < 500MB | 기본 제한 |
|
|
3744
|
-
| **시작 시간** | < 2s | 세션 시작 |
|
|
3745
|
-
|
|
3746
|
-
---
|
|
3747
|
-
|
|
3748
|
-
## 9. 의존성
|
|
3749
|
-
|
|
3750
|
-
### 9.1 런타임 의존성
|
|
3751
|
-
|
|
3752
|
-
| 패키지 | 버전 | 용도 |
|
|
3753
|
-
|--------|------|------|
|
|
3754
|
-
| `lancedb` | ^0.5.0 | 벡터 저장소 |
|
|
3755
|
-
| `duckdb` | ^0.10.0 | 이벤트 저장소 |
|
|
3756
|
-
| `sentence-transformers` | ^2.2.0 | 로컬 임베딩 (Python) |
|
|
3757
|
-
| `@xenova/transformers` | ^2.15.0 | 로컬 임베딩 (JS) |
|
|
3758
|
-
| `zod` | ^3.22.0 | 스키마 검증 |
|
|
3759
|
-
| `commander` | ^12.0.0 | CLI 파싱 |
|
|
3760
|
-
|
|
3761
|
-
### 9.2 개발 의존성
|
|
3762
|
-
|
|
3763
|
-
| 패키지 | 버전 | 용도 |
|
|
3764
|
-
|--------|------|------|
|
|
3765
|
-
| `typescript` | ^5.4.0 | 타입 시스템 |
|
|
3766
|
-
| `vitest` | ^1.4.0 | 테스트 |
|
|
3767
|
-
| `tsx` | ^4.7.0 | TS 실행 |
|
|
3768
|
-
| `esbuild` | ^0.20.0 | 빌드 |
|
|
3769
|
-
|
|
3770
|
-
---
|
|
3771
|
-
|
|
3772
|
-
## 10. 향후 확장
|
|
3773
|
-
|
|
3774
|
-
### Phase 2 (v1.1.0)
|
|
3775
|
-
- [ ] 그래프 기반 관계 저장 (Neo4j/Graphiti)
|
|
3776
|
-
- [ ] 멀티 프로젝트 학습
|
|
3777
|
-
- [ ] 팀 기억 공유 (암호화)
|
|
3778
|
-
|
|
3779
|
-
### Phase 3 (v2.0.0)
|
|
3780
|
-
- [ ] 자동 인사이트 추출 (LLM 기반)
|
|
3781
|
-
- [ ] 코드 스니펫 특화 기억
|
|
3782
|
-
- [ ] IDE 통합 (VSCode extension)
|
|
3783
|
-
|
|
3784
|
-
---
|
|
3785
|
-
|
|
3786
|
-
## 11. 성공 지표
|
|
3787
|
-
|
|
3788
|
-
| 지표 | 측정 방법 | 목표 |
|
|
3789
|
-
|------|----------|------|
|
|
3790
|
-
| **관련성** | 사용자 피드백 | 80%+ 유용 |
|
|
3791
|
-
| **속도** | 응답 지연 | < 500ms |
|
|
3792
|
-
| **채택률** | 활성 사용자 | 1000+ |
|
|
3793
|
-
| **재사용률** | 기억 활용 빈도 | 50%+ 세션 |
|
|
3794
|
-
|
|
3795
|
-
## 2026-02-25T12:44:49.770Z | c15348b2-9c17-4b7f-abd6-06abcf83c7fa
|
|
3796
|
-
- type: session_summary
|
|
3797
|
-
- session: import:organized
|
|
3798
|
-
# Decisions (extracted)
|
|
3799
|
-
|
|
3800
|
-
- confidence: high
|
|
3801
|
-
|
|
3802
|
-
## 2026-01-31 | feat: implement complete code-memory plugin
|
|
3803
|
-
- status: active (inferred)
|
|
3804
|
-
- source: commit:111f400e73f0568b192a5b1b37a88622fd44d648
|
|
3805
|
-
- author: Claude
|
|
3806
|
-
- changedFiles: 31
|
|
3807
|
-
- confidence: mid
|
|
3808
|
-
|
|
3809
|
-
## 2026-01-31 | feat: add session history import functionality
|
|
3810
|
-
- status: active (inferred)
|
|
3811
|
-
- source: commit:22b1c43d9b9f095cd2a210f529ca8bee5a1100c5
|
|
3812
|
-
- author: Claude
|
|
3813
|
-
- changedFiles: 5
|
|
3814
|
-
- confidence: mid
|
|
3815
|
-
|
|
3816
|
-
## 2026-02-01 | docs: Update README with comprehensive feature documentation (#3)
|
|
3817
|
-
- status: active (inferred)
|
|
3818
|
-
- source: commit:3662dfae8381fdf35923b115f58c362e091c474a
|
|
3819
|
-
- author: justinbuzzni
|
|
3820
|
-
- changedFiles: 1
|
|
3821
|
-
- confidence: mid
|
|
3822
|
-
|
|
3823
|
-
## 2026-02-01 | feat: Add cross-project shared troubleshooting store
|
|
3824
|
-
- status: active (inferred)
|
|
3825
|
-
- source: commit:d04e562b5b011e0f07cdea0664db823f0caca5d0
|
|
3826
|
-
- author: justinbuzzni
|
|
3827
|
-
- changedFiles: 9
|
|
3828
|
-
- confidence: mid
|
|
3829
|
-
|
|
3830
|
-
## 2026-02-01 | refactor: Extract DuckDB wrapper for consistent async API
|
|
3831
|
-
- status: active (inferred)
|
|
3832
|
-
- source: commit:65b0f64da3fd2c4b0b758b89f9d0f22301df23a7
|
|
3833
|
-
- author: justinbuzzni
|
|
3834
|
-
- changedFiles: 19
|
|
3835
|
-
- confidence: mid
|
|
3836
|
-
|
|
3837
|
-
## 2026-02-01 | feat: Add web dashboard for memory visualization
|
|
3838
|
-
- status: active (inferred)
|
|
3839
|
-
- source: commit:665cf11bb9a01f1bcba51ec49f53382e95cd7e32
|
|
3840
|
-
- author: justinbuzzni
|
|
3841
|
-
- changedFiles: 5
|
|
3842
|
-
- confidence: mid
|
|
3843
|
-
|
|
3844
|
-
## 2026-02-01 | refactor: Rename project from code-memory to claude-memory-layer
|
|
3845
|
-
- status: active (inferred)
|
|
3846
|
-
- source: commit:f35da2b92704d7d1b5655edac3516c64a829eeef
|
|
3847
|
-
- author: justinbuzzni
|
|
3848
|
-
- changedFiles: 7
|
|
3849
|
-
- confidence: mid
|
|
3850
|
-
|
|
3851
|
-
## 2026-02-01 | feat: Migrate primary store from DuckDB to SQLite (WAL mode)
|
|
3852
|
-
- status: active (inferred)
|
|
3853
|
-
- source: commit:be36be70f69d42d2373ac26e6c0b8e8b53ca0340
|
|
3854
|
-
- author: justinbuzzni
|
|
3855
|
-
- changedFiles: 8
|
|
3856
|
-
- confidence: mid
|
|
3857
|
-
|
|
3858
|
-
## 2026-02-01 | feat: Enhance dashboard, CLI, and memory graduation system
|
|
3859
|
-
- status: active (inferred)
|
|
3860
|
-
- source: commit:babfd15284754bc3dbb698fcc4c81efcf53fcd85
|
|
3861
|
-
- author: justinbuzzni
|
|
3862
|
-
- changedFiles: 13
|
|
3863
|
-
- confidence: mid
|
|
3864
|
-
|
|
3865
|
-
## 2026-02-07 | feat: Add memory helpfulness tracking and dashboard sort controls
|
|
3866
|
-
- status: active (inferred)
|
|
3867
|
-
- source: commit:794640023652fc38b010e1ab46ca6a9a504a09e8
|
|
3868
|
-
- author: justinbuzzni
|
|
3869
|
-
- changedFiles: 9
|
|
3870
|
-
- confidence: mid
|
|
3871
|
-
|
|
3872
|
-
## 2026-02-08 | feat: Add interactive dashboard with modals, navigation, and detail views
|
|
3873
|
-
- status: active (inferred)
|
|
3874
|
-
- source: commit:20c37b2cdffd271eaf04df9d2e87e5f23a4f853e
|
|
3875
|
-
- author: justinbuzzni
|
|
3876
|
-
- changedFiles: 5
|
|
3877
|
-
- confidence: mid
|
|
3878
|
-
|
|
3879
|
-
## 2026-02-08 | fix: Align hooks with actual Claude Code input format and use lightweight service
|
|
3880
|
-
- status: active (inferred)
|
|
3881
|
-
- source: commit:a1d93af414821eb92d74cd02abb748849366ebfb
|
|
3882
|
-
- author: justinbuzzni
|
|
3883
|
-
- changedFiles: 4
|
|
3884
|
-
- confidence: mid
|
|
3885
|
-
|
|
3886
|
-
## 2026-02-08 | feat: Add real-time progress display for import command
|
|
3887
|
-
- status: active (inferred)
|
|
3888
|
-
- source: commit:fd8f38af7cecf7d31a32a5aba9b1902178f986b1
|
|
3889
|
-
- author: justinbuzzni
|
|
3890
|
-
- changedFiles: 2
|
|
3891
|
-
- confidence: mid
|
|
3892
|
-
|
|
3893
|
-
## 2026-02-08 | feat: Add turn-based event grouping, force reimport, and session registry support
|
|
3894
|
-
- status: active (inferred)
|
|
3895
|
-
- source: commit:938ec34bdf5fe1e4c43274424497ca081d62023a
|
|
3896
|
-
- author: justinbuzzni
|
|
3897
|
-
- changedFiles: 9
|
|
3898
|
-
- confidence: mid
|
|
3899
|
-
|
|
3900
|
-
## 2026-02-08 | feat: Add per-project dashboard with project selector and turns API
|
|
3901
|
-
- status: active (inferred)
|
|
3902
|
-
- source: commit:af18cee5277324c78a9e1bca5873bc86ee5b2719
|
|
3903
|
-
- author: justinbuzzni
|
|
3904
|
-
- changedFiles: 12
|
|
3905
|
-
- confidence: mid
|
|
3906
|
-
|
|
3907
|
-
## 2026-02-08 | fix: Handle vector store table race condition and auto-create SQLite directories
|
|
3908
|
-
- status: active (inferred)
|
|
3909
|
-
- source: commit:5b7401917611b50ee49e38bdf080983d1c763d5e
|
|
3910
|
-
- author: justinbuzzni
|
|
3911
|
-
- changedFiles: 2
|
|
3912
|
-
- confidence: mid
|
|
3913
|
-
|
|
3914
|
-
## 2026-02-08 | feat: Add Ask Memory chat service to dashboard
|
|
3915
|
-
- status: active (inferred)
|
|
3916
|
-
- source: commit:a7b260f0ceeff6d768fefb675e6425f5b4717d7e
|
|
3917
|
-
- author: justinbuzzni
|
|
3918
|
-
- changedFiles: 5
|
|
3919
|
-
- confidence: mid
|
|
3920
|
-
|
|
3921
|
-
## 2026-02-08 | feat: Widen chat panel and add conversation history with localStorage
|
|
3922
|
-
- status: active (inferred)
|
|
3923
|
-
- source: commit:15547d41e952350d095dfe3c01b2afa749638532
|
|
3924
|
-
- author: justinbuzzni
|
|
3925
|
-
- changedFiles: 3
|
|
3926
|
-
- confidence: mid
|
|
3927
|
-
|
|
3928
|
-
## 2026-02-08 | fix: Knowledge Graph shows data even when no memories have been accessed
|
|
3929
|
-
- status: active (inferred)
|
|
3930
|
-
- source: commit:78b0956610eb7d22c28a821c67e10e6e9996c5be
|
|
3931
|
-
- author: justinbuzzni
|
|
3932
|
-
- changedFiles: 2
|
|
3933
|
-
- confidence: mid
|
|
3934
|
-
|
|
3935
|
-
## 2026-02-20 | feat(ops): add heartbeat orchestrator and sync-gap auto-heal scripts
|
|
3936
|
-
- status: active (inferred)
|
|
3937
|
-
- source: commit:d56d22ba3271c1d51ea8bbaddb21f5f3d0a79d49
|
|
3938
|
-
- author: namsangboy
|
|
3939
|
-
- changedFiles: 7
|
|
3940
|
-
- confidence: mid
|
|
3941
|
-
|
|
3942
|
-
## 2026-02-09 | feat: optional MongoDB sync for project events
|
|
3943
|
-
- status: active (inferred)
|
|
3944
|
-
- source: commit:11d3092e372836f784a760fc0b4269fd44e9159f
|
|
3945
|
-
- author: Justin
|
|
3946
|
-
- changedFiles: 9
|
|
3947
|
-
- confidence: mid
|
|
3948
|
-
|
|
3949
|
-
## 2026-02-22 | feat: add Codex session history importer, MongoDB sync config, and AGENTS.md
|
|
3950
|
-
- status: active (inferred)
|
|
3951
|
-
- source: commit:4855172b8f92fff0c148c106de4e10c494d2bb09
|
|
3952
|
-
- author: Justin
|
|
3953
|
-
- changedFiles: 4
|
|
3954
|
-
- confidence: mid
|
|
3955
|
-
|
|
3956
|
-
## 2026-02-24 | feat(memory): adopt memU-style scoped retrieval and staged ingest hooks
|
|
3957
|
-
- status: active (inferred)
|
|
3958
|
-
- source: commit:d278200d0f0666616a8556f2f25f9758b3ab9afd
|
|
3959
|
-
- author: justinbuzzni
|
|
3960
|
-
- changedFiles: 6
|
|
3961
|
-
- confidence: mid
|
|
3962
|
-
|
|
3963
|
-
## 2026-02-24 | feat(memory): add append-only markdown mirror for categorized event archives
|
|
3964
|
-
- status: active (inferred)
|
|
3965
|
-
- source: commit:917ad7fc97a1c2de68637dfbe4b4cdd51776ec30
|
|
3966
|
-
- author: justinbuzzni
|
|
3967
|
-
- changedFiles: 4
|
|
3968
|
-
- confidence: mid
|
|
3969
|
-
|
|
3970
|
-
## 2026-02-24 | feat: append-only markdown mirror in sqlite ingest flow
|
|
3971
|
-
- status: active (inferred)
|
|
3972
|
-
- source: commit:72250046152e851ed70476a8704ca38ca633ffab
|
|
3973
|
-
- author: justinbuzzni
|
|
3974
|
-
- changedFiles: 3
|
|
3975
|
-
- confidence: mid
|
|
3976
|
-
|
|
3977
|
-
## 2026-02-24 | feat(memory): auto-refresh markdown mirror index
|
|
3978
|
-
- status: active (inferred)
|
|
3979
|
-
- source: commit:3a34d45a594affb034d6e416e3a29b6d2dcc20a5
|
|
3980
|
-
- author: justinbuzzni
|
|
3981
|
-
- changedFiles: 3
|
|
3982
|
-
- confidence: mid
|
|
3983
|
-
|
|
3984
|
-
## 2026-02-24 | feat(cli): add organize-import command for structured markdown memory import
|
|
3985
|
-
- status: active (inferred)
|
|
3986
|
-
- source: commit:fe9ef67e5acabb81885a3c752a5b8525f80856a5
|
|
3987
|
-
- author: justinbuzzni
|
|
3988
|
-
- changedFiles: 3
|
|
3989
|
-
- confidence: mid
|
|
3990
|
-
|
|
3991
|
-
## 2026-02-24 | feat(retrieval): add auto fallback chain fast→deep→scope-expand→summary
|
|
3992
|
-
- status: active (inferred)
|
|
3993
|
-
- source: commit:0dceb2d914e67e10d140848340f30e6fd07c4f67
|
|
3994
|
-
- author: justinbuzzni
|
|
3995
|
-
- changedFiles: 2
|
|
3996
|
-
- confidence: mid
|
|
3997
|
-
|
|
3998
|
-
## 2026-02-24 | feat(ranking): add helpfulness-driven adaptive rerank weights v1
|
|
3999
|
-
- status: active (inferred)
|
|
4000
|
-
- source: commit:7de02967a1d59aea3e04ef1239585b93828c503a
|
|
4001
|
-
- author: justinbuzzni
|
|
4002
|
-
- changedFiles: 3
|
|
4003
|
-
- confidence: mid
|
|
4004
|
-
|
|
4005
|
-
## 2026-02-24 | feat(retrieval): add ttl/decay ranking policy v1
|
|
4006
|
-
- status: active (inferred)
|
|
4007
|
-
- source: commit:46f2cfa2d99f0c8fb3a48709a97f62800f01d4fe
|
|
4008
|
-
- author: justinbuzzni
|
|
4009
|
-
- changedFiles: 2
|
|
4010
|
-
- confidence: mid
|
|
4011
|
-
|
|
4012
|
-
## 2026-02-24 | feat(retrieval): add intent-rewrite deep retrieval merge flow
|
|
4013
|
-
- status: active (inferred)
|
|
4014
|
-
- source: commit:5fd950beee4d02f00b0c93be668a2e114ce9b257
|
|
4015
|
-
- author: justinbuzzni
|
|
4016
|
-
- changedFiles: 3
|
|
4017
|
-
- confidence: mid
|
|
4018
|
-
|
|
4019
|
-
## 2026-02-24 | feat(retrieval): add graph-hop expansion with hop penalty
|
|
4020
|
-
- status: active (inferred)
|
|
4021
|
-
- source: commit:d1dfe03f881d1a76ecd9a916cbf04c3ff2a4bf7e
|
|
4022
|
-
- author: justinbuzzni
|
|
4023
|
-
- changedFiles: 2
|
|
4024
|
-
- confidence: mid
|
|
4025
|
-
|
|
4026
|
-
## 2026-02-24 | feat(consolidation): add hierarchical summary→rule automation with report
|
|
4027
|
-
- status: active (inferred)
|
|
4028
|
-
- source: commit:7c84b5eacff733d8cb692eb9d47b7297a0872e43
|
|
4029
|
-
- author: justinbuzzni
|
|
4030
|
-
- changedFiles: 6
|
|
4031
|
-
- confidence: mid
|
|
4032
|
-
|
|
4033
|
-
## 2026-02-25 | Feat/organize import bootstrap kb (#10)
|
|
4034
|
-
- status: active (inferred)
|
|
4035
|
-
- source: commit:db38c7e606a59478c03bac7e5bb5951954ca0813
|
|
4036
|
-
- author: justinbuzzni
|
|
4037
|
-
- changedFiles: 4
|
|
4038
|
-
- confidence: mid
|
|
4039
|
-
|
|
4040
|
-
## Sources
|
|
4041
|
-
- source: git-log:since=180 days ago;max=1000
|
|
4042
|
-
|
|
4043
|
-
## 2026-02-25T12:44:49.793Z | ad99702b-0e3a-4054-ab3c-27d4d1c83850
|
|
4044
|
-
- type: session_summary
|
|
4045
|
-
- session: import:organized
|
|
4046
|
-
# Glossary (auto-extracted)
|
|
4047
|
-
|
|
4048
|
-
- confidence: mid
|
|
4049
|
-
|
|
4050
|
-
- context
|
|
4051
|
-
- spec
|
|
4052
|
-
- plan
|
|
4053
|
-
- memory
|
|
4054
|
-
- store
|
|
4055
|
-
- sync
|
|
4056
|
-
- worker
|
|
4057
|
-
- retriever
|
|
4058
|
-
- event
|
|
4059
|
-
- mirror
|
|
4060
|
-
- session
|
|
4061
|
-
- shared
|
|
4062
|
-
- vector
|
|
4063
|
-
- gap
|
|
4064
|
-
- history
|
|
4065
|
-
- matcher
|
|
4066
|
-
- sqlite
|
|
4067
|
-
- task
|
|
4068
|
-
- aligner
|
|
4069
|
-
- auto
|
|
4070
|
-
- bootstrap
|
|
4071
|
-
- canonical
|
|
4072
|
-
- config
|
|
4073
|
-
- consolidation
|
|
4074
|
-
- evidence
|
|
4075
|
-
- graduation
|
|
4076
|
-
- importer
|
|
4077
|
-
- ingest
|
|
4078
|
-
- interceptor
|
|
4079
|
-
- key
|
|
4080
|
-
- markdown
|
|
4081
|
-
- mongo
|
|
4082
|
-
- organizer
|
|
4083
|
-
- package
|
|
4084
|
-
- repo
|
|
4085
|
-
- resolver
|
|
4086
|
-
- search
|
|
4087
|
-
- stats
|
|
4088
|
-
- wrapper
|
|
4089
|
-
|
|
4090
|
-
## Sources
|
|
4091
|
-
- source: repo-scan:/home/walter/workspace/opensource/claude-memory-layer
|
|
4092
|
-
|
|
4093
|
-
## 2026-02-25T12:44:49.802Z | df87a07f-4efe-4925-829a-2dd51fb27014
|
|
4094
|
-
- type: session_summary
|
|
4095
|
-
- session: import:organized
|
|
4096
|
-
# Module: .claude-plugin
|
|
4097
|
-
|
|
4098
|
-
- responsibility: inferred from top-level path `.claude-plugin/`
|
|
4099
|
-
- files: 8
|
|
4100
|
-
- languages: Markdown, JSON
|
|
4101
|
-
- confidence: high
|
|
4102
|
-
|
|
4103
|
-
## Entry Candidates
|
|
4104
|
-
- none detected
|
|
4105
|
-
|
|
4106
|
-
## Related Commits (recent sample)
|
|
4107
|
-
- 2026-01-31 111f400e feat: implement complete code-memory plugin
|
|
4108
|
-
- 2026-01-31 22b1c43d feat: add session history import functionality
|
|
4109
|
-
- 2026-02-01 504ec3dd docs: Add citations and endless mode specification documents (#2)
|
|
4110
|
-
- 2026-02-01 f35da2b9 refactor: Rename project from code-memory to claude-memory-layer
|
|
4111
|
-
|
|
4112
|
-
## Sources
|
|
4113
|
-
- source: repo-path:.claude-plugin/**
|
|
4114
|
-
- source: commit:111f400e73f0568b192a5b1b37a88622fd44d648
|
|
4115
|
-
- source: commit:22b1c43d9b9f095cd2a210f529ca8bee5a1100c5
|
|
4116
|
-
- source: commit:504ec3ddd7f451fabf2cf01e073fc96e65ae124e
|
|
4117
|
-
- source: commit:f35da2b92704d7d1b5655edac3516c64a829eeef
|
|
4118
|
-
|
|
4119
|
-
## 2026-02-25T12:44:49.817Z | 7a188e68-aab0-4d23-ae8c-b904d850224f
|
|
4120
|
-
- type: session_summary
|
|
4121
|
-
- session: import:organized
|
|
4122
|
-
# Module: AGENTS.md
|
|
4123
|
-
|
|
4124
|
-
- responsibility: inferred from top-level path `AGENTS.md/`
|
|
4125
|
-
- files: 1
|
|
4126
|
-
- languages: Markdown
|
|
4127
|
-
- confidence: low
|
|
4128
|
-
|
|
4129
|
-
## Entry Candidates
|
|
4130
|
-
- none detected
|
|
4131
|
-
|
|
4132
|
-
## Related Commits (recent sample)
|
|
4133
|
-
- none in selected range
|
|
4134
|
-
|
|
4135
|
-
## Sources
|
|
4136
|
-
- source: repo-path:AGENTS.md/**
|
|
4137
|
-
|
|
4138
|
-
## 2026-02-25T12:44:49.826Z | 9f2abb09-0094-4864-b1d1-8481675491bd
|
|
4139
|
-
- type: session_summary
|
|
4140
|
-
- session: import:organized
|
|
4141
|
-
# Module: CLAUDE.md
|
|
4142
|
-
|
|
4143
|
-
- responsibility: inferred from top-level path `CLAUDE.md/`
|
|
4144
|
-
- files: 1
|
|
4145
|
-
- languages: Markdown
|
|
4146
|
-
- confidence: low
|
|
4147
|
-
|
|
4148
|
-
## Entry Candidates
|
|
4149
|
-
- none detected
|
|
4150
|
-
|
|
4151
|
-
## Related Commits (recent sample)
|
|
4152
|
-
- none in selected range
|
|
4153
|
-
|
|
4154
|
-
## Sources
|
|
4155
|
-
- source: repo-path:CLAUDE.md/**
|
|
4156
|
-
|
|
4157
|
-
## 2026-02-25T12:44:49.834Z | a410152a-449c-4f76-b5e9-5bbecacd4370
|
|
4158
|
-
- type: session_summary
|
|
4159
|
-
- session: import:organized
|
|
4160
|
-
# Module: context.md
|
|
4161
|
-
|
|
4162
|
-
- responsibility: inferred from top-level path `context.md/`
|
|
4163
|
-
- files: 1
|
|
4164
|
-
- languages: Markdown
|
|
4165
|
-
- confidence: low
|
|
4166
|
-
|
|
4167
|
-
## Entry Candidates
|
|
4168
|
-
- none detected
|
|
4169
|
-
|
|
4170
|
-
## Related Commits (recent sample)
|
|
4171
|
-
- none in selected range
|
|
4172
|
-
|
|
4173
|
-
## Sources
|
|
4174
|
-
- source: repo-path:context.md/**
|
|
4175
|
-
|
|
4176
|
-
## 2026-02-25T12:44:49.841Z | 7b9b955f-89a4-4b90-a75f-35a50e59b14d
|
|
4177
|
-
- type: session_summary
|
|
4178
|
-
- session: import:organized
|
|
4179
|
-
# Module: docs
|
|
4180
|
-
|
|
4181
|
-
- responsibility: inferred from top-level path `docs/`
|
|
4182
|
-
- files: 2
|
|
4183
|
-
- languages: Markdown
|
|
4184
|
-
- confidence: mid
|
|
4185
|
-
|
|
4186
|
-
## Entry Candidates
|
|
4187
|
-
- none detected
|
|
4188
|
-
|
|
4189
|
-
## Related Commits (recent sample)
|
|
4190
|
-
- 2026-02-20 d56d22ba feat(ops): add heartbeat orchestrator and sync-gap auto-heal scripts
|
|
4191
|
-
- 2026-02-24 4447e64f docs(memory): document memU-inspired retrieval strategies and scoped filters
|
|
4192
|
-
|
|
4193
|
-
## Sources
|
|
4194
|
-
- source: repo-path:docs/**
|
|
4195
|
-
- source: commit:d56d22ba3271c1d51ea8bbaddb21f5f3d0a79d49
|
|
4196
|
-
- source: commit:4447e64fa00065bfb364d38c597ad87484770891
|
|
4197
|
-
|
|
4198
|
-
## 2026-02-25T12:44:49.849Z | 39062a82-1fd5-47ba-850c-36adb9aaad2a
|
|
4199
|
-
- type: session_summary
|
|
4200
|
-
- session: import:organized
|
|
4201
|
-
# Module: HANDOFF.md
|
|
4202
|
-
|
|
4203
|
-
- responsibility: inferred from top-level path `HANDOFF.md/`
|
|
4204
|
-
- files: 1
|
|
4205
|
-
- languages: Markdown
|
|
4206
|
-
- confidence: low
|
|
4207
|
-
|
|
4208
|
-
## Entry Candidates
|
|
4209
|
-
- none detected
|
|
4210
|
-
|
|
4211
|
-
## Related Commits (recent sample)
|
|
4212
|
-
- none in selected range
|
|
4213
|
-
|
|
4214
|
-
## Sources
|
|
4215
|
-
- source: repo-path:HANDOFF.md/**
|
|
4216
|
-
|
|
4217
|
-
## 2026-02-25T12:44:49.856Z | ede06b47-7e54-4a2b-8e59-0d87fec83fa5
|
|
4218
|
-
- type: session_summary
|
|
4219
|
-
- session: import:organized
|
|
4220
|
-
# Module: package-lock.json
|
|
4221
|
-
|
|
4222
|
-
- responsibility: inferred from top-level path `package-lock.json/`
|
|
4223
|
-
- files: 1
|
|
4224
|
-
- languages: JSON
|
|
4225
|
-
- confidence: low
|
|
4226
|
-
|
|
4227
|
-
## Entry Candidates
|
|
4228
|
-
- none detected
|
|
4229
|
-
|
|
4230
|
-
## Related Commits (recent sample)
|
|
4231
|
-
- none in selected range
|
|
4232
|
-
|
|
4233
|
-
## Sources
|
|
4234
|
-
- source: repo-path:package-lock.json/**
|
|
4235
|
-
|
|
4236
|
-
## 2026-02-25T12:44:49.863Z | ccfcd6c5-95fb-4a1c-9708-d518cad72a84
|
|
4237
|
-
- type: session_summary
|
|
4238
|
-
- session: import:organized
|
|
4239
|
-
# Module: package.json
|
|
4240
|
-
|
|
4241
|
-
- responsibility: inferred from top-level path `package.json/`
|
|
4242
|
-
- files: 1
|
|
4243
|
-
- languages: JSON
|
|
4244
|
-
- confidence: low
|
|
4245
|
-
|
|
4246
|
-
## Entry Candidates
|
|
4247
|
-
- none detected
|
|
4248
|
-
|
|
4249
|
-
## Related Commits (recent sample)
|
|
4250
|
-
- none in selected range
|
|
4251
|
-
|
|
4252
|
-
## Sources
|
|
4253
|
-
- source: repo-path:package.json/**
|
|
4254
|
-
|
|
4255
|
-
## 2026-02-25T12:44:49.869Z | 698bcbda-e8a5-47c8-8b97-4cffebd4c1d6
|
|
4256
|
-
- type: session_summary
|
|
4257
|
-
- session: import:organized
|
|
4258
|
-
# Module: plan.md
|
|
4259
|
-
|
|
4260
|
-
- responsibility: inferred from top-level path `plan.md/`
|
|
4261
|
-
- files: 1
|
|
4262
|
-
- languages: Markdown
|
|
4263
|
-
- confidence: low
|
|
4264
|
-
|
|
4265
|
-
## Entry Candidates
|
|
4266
|
-
- none detected
|
|
4267
|
-
|
|
4268
|
-
## Related Commits (recent sample)
|
|
4269
|
-
- none in selected range
|
|
4270
|
-
|
|
4271
|
-
## Sources
|
|
4272
|
-
- source: repo-path:plan.md/**
|
|
4273
|
-
|
|
4274
|
-
## 2026-02-25T12:44:49.876Z | 3c641407-4507-4025-a30a-1ba8bc3ba6a9
|
|
4275
|
-
- type: session_summary
|
|
4276
|
-
- session: import:organized
|
|
4277
|
-
# Module: README.md
|
|
4278
|
-
|
|
4279
|
-
- responsibility: inferred from top-level path `README.md/`
|
|
4280
|
-
- files: 1
|
|
4281
|
-
- languages: Markdown
|
|
4282
|
-
- confidence: low
|
|
4283
|
-
|
|
4284
|
-
## Entry Candidates
|
|
4285
|
-
- none detected
|
|
4286
|
-
|
|
4287
|
-
## Related Commits (recent sample)
|
|
4288
|
-
- none in selected range
|
|
4289
|
-
|
|
4290
|
-
## Sources
|
|
4291
|
-
- source: repo-path:README.md/**
|
|
4292
|
-
|
|
4293
|
-
## 2026-02-25T12:44:49.883Z | f948c223-8747-48a2-aacb-eb3c0f4d7ef1
|
|
4294
|
-
- type: session_summary
|
|
4295
|
-
- session: import:organized
|
|
4296
|
-
# Module: scripts
|
|
4297
|
-
|
|
4298
|
-
- responsibility: inferred from top-level path `scripts/`
|
|
4299
|
-
- files: 6
|
|
4300
|
-
- languages: JavaScript, Shell, TypeScript
|
|
4301
|
-
- confidence: high
|
|
4302
|
-
|
|
4303
|
-
## Entry Candidates
|
|
4304
|
-
- none detected
|
|
4305
|
-
|
|
4306
|
-
## Related Commits (recent sample)
|
|
4307
|
-
- 2026-01-31 111f400e feat: implement complete code-memory plugin
|
|
4308
|
-
- 2026-02-01 665cf11b feat: Add web dashboard for memory visualization
|
|
4309
|
-
- 2026-02-01 f35da2b9 refactor: Rename project from code-memory to claude-memory-layer
|
|
4310
|
-
- 2026-02-01 be36be70 feat: Migrate primary store from DuckDB to SQLite (WAL mode)
|
|
4311
|
-
- 2026-02-20 d56d22ba feat(ops): add heartbeat orchestrator and sync-gap auto-heal scripts
|
|
4312
|
-
- 2026-02-09 11d3092e feat: optional MongoDB sync for project events
|
|
4313
|
-
|
|
4314
|
-
## Sources
|
|
4315
|
-
- source: repo-path:scripts/**
|
|
4316
|
-
- source: commit:111f400e73f0568b192a5b1b37a88622fd44d648
|
|
4317
|
-
- source: commit:665cf11bb9a01f1bcba51ec49f53382e95cd7e32
|
|
4318
|
-
- source: commit:f35da2b92704d7d1b5655edac3516c64a829eeef
|
|
4319
|
-
- source: commit:be36be70f69d42d2373ac26e6c0b8e8b53ca0340
|
|
4320
|
-
- source: commit:d56d22ba3271c1d51ea8bbaddb21f5f3d0a79d49
|
|
4321
|
-
- source: commit:11d3092e372836f784a760fc0b4269fd44e9159f
|
|
4322
|
-
|
|
4323
|
-
## 2026-02-25T12:44:49.889Z | 2da127d3-7fff-44bb-85aa-3858635b10e1
|
|
4324
|
-
- type: session_summary
|
|
4325
|
-
- session: import:organized
|
|
4326
|
-
# Module: spec.md
|
|
4327
|
-
|
|
4328
|
-
- responsibility: inferred from top-level path `spec.md/`
|
|
4329
|
-
- files: 1
|
|
4330
|
-
- languages: Markdown
|
|
4331
|
-
- confidence: low
|
|
4332
|
-
|
|
4333
|
-
## Entry Candidates
|
|
4334
|
-
- none detected
|
|
4335
|
-
|
|
4336
|
-
## Related Commits (recent sample)
|
|
4337
|
-
- none in selected range
|
|
4338
|
-
|
|
4339
|
-
## Sources
|
|
4340
|
-
- source: repo-path:spec.md/**
|
|
4341
|
-
|
|
4342
|
-
## 2026-02-25T12:44:49.896Z | c7f1b00c-61ee-4621-a012-4cb83d80fd99
|
|
4343
|
-
- type: session_summary
|
|
4344
|
-
- session: import:organized
|
|
4345
|
-
# Module: specs
|
|
4346
|
-
|
|
4347
|
-
- responsibility: inferred from top-level path `specs/`
|
|
4348
|
-
- files: 35
|
|
4349
|
-
- languages: Markdown
|
|
4350
|
-
- confidence: high
|
|
4351
|
-
|
|
4352
|
-
## Entry Candidates
|
|
4353
|
-
- none detected
|
|
4354
|
-
|
|
4355
|
-
## Related Commits (recent sample)
|
|
4356
|
-
- 2026-02-01 4bbbc717 Merge pull request #1 from buzzni/claude/idris2-memory-storage-JLk7J
|
|
4357
|
-
- 2026-02-01 504ec3dd docs: Add citations and endless mode specification documents (#2)
|
|
4358
|
-
- 2026-02-08 20c37b2c feat: Add interactive dashboard with modals, navigation, and detail views
|
|
4359
|
-
|
|
4360
|
-
## Sources
|
|
4361
|
-
- source: repo-path:specs/**
|
|
4362
|
-
- source: commit:4bbbc7174f920434cfc67ee02746a9b9824ec101
|
|
4363
|
-
- source: commit:504ec3ddd7f451fabf2cf01e073fc96e65ae124e
|
|
4364
|
-
- source: commit:20c37b2cdffd271eaf04df9d2e87e5f23a4f853e
|
|
4365
|
-
|
|
4366
|
-
## 2026-02-25T12:44:49.902Z | 8315c023-3a7a-451d-82de-1629672658c6
|
|
4367
|
-
- type: session_summary
|
|
4368
|
-
- session: import:organized
|
|
4369
|
-
# Module: src
|
|
4370
|
-
|
|
4371
|
-
- responsibility: inferred from top-level path `src/`
|
|
4372
|
-
- files: 70
|
|
4373
|
-
- languages: TypeScript, JavaScript
|
|
4374
|
-
- confidence: high
|
|
4375
|
-
|
|
4376
|
-
## Entry Candidates
|
|
4377
|
-
- src/cli/index.ts
|
|
4378
|
-
- src/core/index.ts
|
|
4379
|
-
- src/core/privacy/index.ts
|
|
4380
|
-
- src/core/task/index.ts
|
|
4381
|
-
- src/mcp/index.ts
|
|
4382
|
-
- src/server/api/index.ts
|
|
4383
|
-
- src/server/index.ts
|
|
4384
|
-
- src/ui/app.js
|
|
4385
|
-
|
|
4386
|
-
## Related Commits (recent sample)
|
|
4387
|
-
- 2026-01-31 111f400e feat: implement complete code-memory plugin
|
|
4388
|
-
- 2026-01-31 22b1c43d feat: add session history import functionality
|
|
4389
|
-
- 2026-02-01 4bbbc717 Merge pull request #1 from buzzni/claude/idris2-memory-storage-JLk7J
|
|
4390
|
-
- 2026-02-01 504ec3dd docs: Add citations and endless mode specification documents (#2)
|
|
4391
|
-
- 2026-02-01 d04e562b feat: Add cross-project shared troubleshooting store
|
|
4392
|
-
- 2026-02-01 65b0f64d refactor: Extract DuckDB wrapper for consistent async API
|
|
4393
|
-
- 2026-02-01 665cf11b feat: Add web dashboard for memory visualization
|
|
4394
|
-
- 2026-02-01 f35da2b9 refactor: Rename project from code-memory to claude-memory-layer
|
|
4395
|
-
- 2026-02-01 be36be70 feat: Migrate primary store from DuckDB to SQLite (WAL mode)
|
|
4396
|
-
- 2026-02-01 babfd152 feat: Enhance dashboard, CLI, and memory graduation system
|
|
4397
|
-
- 2026-02-02 543643e7 perf: Add fast keyword search and optimize hook performance
|
|
4398
|
-
- 2026-02-07 79464002 feat: Add memory helpfulness tracking and dashboard sort controls
|
|
4399
|
-
- 2026-02-08 20c37b2c feat: Add interactive dashboard with modals, navigation, and detail views
|
|
4400
|
-
- 2026-02-08 a1d93af4 fix: Align hooks with actual Claude Code input format and use lightweight service
|
|
4401
|
-
- 2026-02-08 fd8f38af feat: Add real-time progress display for import command
|
|
4402
|
-
|
|
4403
|
-
## Sources
|
|
4404
|
-
- source: repo-path:src/**
|
|
4405
|
-
- source: commit:111f400e73f0568b192a5b1b37a88622fd44d648
|
|
4406
|
-
- source: commit:22b1c43d9b9f095cd2a210f529ca8bee5a1100c5
|
|
4407
|
-
- source: commit:4bbbc7174f920434cfc67ee02746a9b9824ec101
|
|
4408
|
-
- source: commit:504ec3ddd7f451fabf2cf01e073fc96e65ae124e
|
|
4409
|
-
- source: commit:d04e562b5b011e0f07cdea0664db823f0caca5d0
|
|
4410
|
-
- source: commit:65b0f64da3fd2c4b0b758b89f9d0f22301df23a7
|
|
4411
|
-
- source: commit:665cf11bb9a01f1bcba51ec49f53382e95cd7e32
|
|
4412
|
-
- source: commit:f35da2b92704d7d1b5655edac3516c64a829eeef
|
|
4413
|
-
- source: commit:be36be70f69d42d2373ac26e6c0b8e8b53ca0340
|
|
4414
|
-
- source: commit:babfd15284754bc3dbb698fcc4c81efcf53fcd85
|
|
4415
|
-
- source: commit:543643e7a9f1d4a94f3216c2369d0212a51ff32d
|
|
4416
|
-
- source: commit:794640023652fc38b010e1ab46ca6a9a504a09e8
|
|
4417
|
-
- source: commit:20c37b2cdffd271eaf04df9d2e87e5f23a4f853e
|
|
4418
|
-
- source: commit:a1d93af414821eb92d74cd02abb748849366ebfb
|
|
4419
|
-
- source: commit:fd8f38af7cecf7d31a32a5aba9b1902178f986b1
|
|
4420
|
-
|
|
4421
|
-
## 2026-02-25T12:44:49.909Z | c2836359-ecb1-4c15-86ab-42163c79b489
|
|
4422
|
-
- type: session_summary
|
|
4423
|
-
- session: import:organized
|
|
4424
|
-
# Module: tests
|
|
4425
|
-
|
|
4426
|
-
- responsibility: inferred from top-level path `tests/`
|
|
4427
|
-
- files: 12
|
|
4428
|
-
- languages: TypeScript
|
|
4429
|
-
- confidence: high
|
|
4430
|
-
|
|
4431
|
-
## Entry Candidates
|
|
4432
|
-
- none detected
|
|
4433
|
-
|
|
4434
|
-
## Related Commits (recent sample)
|
|
4435
|
-
- 2026-01-31 111f400e feat: implement complete code-memory plugin
|
|
4436
|
-
- 2026-02-09 11d3092e feat: optional MongoDB sync for project events
|
|
4437
|
-
- 2026-02-24 d278200d feat(memory): adopt memU-style scoped retrieval and staged ingest hooks
|
|
4438
|
-
- 2026-02-24 917ad7fc feat(memory): add append-only markdown mirror for categorized event archives
|
|
4439
|
-
- 2026-02-24 72250046 feat: append-only markdown mirror in sqlite ingest flow
|
|
4440
|
-
- 2026-02-24 3a34d45a feat(memory): auto-refresh markdown mirror index
|
|
4441
|
-
- 2026-02-24 df15146c chore(memory): normalize markdown mirror default category to uncategorized
|
|
4442
|
-
- 2026-02-24 0dceb2d9 feat(retrieval): add auto fallback chain fast→deep→scope-expand→summary
|
|
4443
|
-
- 2026-02-24 7de02967 feat(ranking): add helpfulness-driven adaptive rerank weights v1
|
|
4444
|
-
- 2026-02-24 46f2cfa2 feat(retrieval): add ttl/decay ranking policy v1
|
|
4445
|
-
- 2026-02-24 5fd950be feat(retrieval): add intent-rewrite deep retrieval merge flow
|
|
4446
|
-
- 2026-02-24 d1dfe03f feat(retrieval): add graph-hop expansion with hop penalty
|
|
4447
|
-
- 2026-02-24 7c84b5ea feat(consolidation): add hierarchical summary→rule automation with report
|
|
4448
|
-
- 2026-02-25 db38c7e6 Feat/organize import bootstrap kb (#10)
|
|
4449
|
-
|
|
4450
|
-
## Sources
|
|
4451
|
-
- source: repo-path:tests/**
|
|
4452
|
-
- source: commit:111f400e73f0568b192a5b1b37a88622fd44d648
|
|
4453
|
-
- source: commit:11d3092e372836f784a760fc0b4269fd44e9159f
|
|
4454
|
-
- source: commit:d278200d0f0666616a8556f2f25f9758b3ab9afd
|
|
4455
|
-
- source: commit:917ad7fc97a1c2de68637dfbe4b4cdd51776ec30
|
|
4456
|
-
- source: commit:72250046152e851ed70476a8704ca38ca633ffab
|
|
4457
|
-
- source: commit:3a34d45a594affb034d6e416e3a29b6d2dcc20a5
|
|
4458
|
-
- source: commit:df15146c2a8c3e389c1a2b8d6fcfb4a33f7a772d
|
|
4459
|
-
- source: commit:0dceb2d914e67e10d140848340f30e6fd07c4f67
|
|
4460
|
-
- source: commit:7de02967a1d59aea3e04ef1239585b93828c503a
|
|
4461
|
-
- source: commit:46f2cfa2d99f0c8fb3a48709a97f62800f01d4fe
|
|
4462
|
-
- source: commit:5fd950beee4d02f00b0c93be668a2e114ce9b257
|
|
4463
|
-
- source: commit:d1dfe03f881d1a76ecd9a916cbf04c3ff2a4bf7e
|
|
4464
|
-
- source: commit:7c84b5eacff733d8cb692eb9d47b7297a0872e43
|
|
4465
|
-
- source: commit:db38c7e606a59478c03bac7e5bb5951954ca0813
|
|
4466
|
-
|
|
4467
|
-
## 2026-02-25T12:44:49.916Z | 5b4e83de-4ba2-4475-9b94-47f66c4571d4
|
|
4468
|
-
- type: session_summary
|
|
4469
|
-
- session: import:organized
|
|
4470
|
-
# Module: tsconfig.json
|
|
4471
|
-
|
|
4472
|
-
- responsibility: inferred from top-level path `tsconfig.json/`
|
|
4473
|
-
- files: 1
|
|
4474
|
-
- languages: JSON
|
|
4475
|
-
- confidence: low
|
|
4476
|
-
|
|
4477
|
-
## Entry Candidates
|
|
4478
|
-
- none detected
|
|
4479
|
-
|
|
4480
|
-
## Related Commits (recent sample)
|
|
4481
|
-
- none in selected range
|
|
4482
|
-
|
|
4483
|
-
## Sources
|
|
4484
|
-
- source: repo-path:tsconfig.json/**
|
|
4485
|
-
|
|
4486
|
-
## 2026-02-25T12:44:49.923Z | baf71944-cc8e-411f-96d2-a861944fe5c4
|
|
4487
|
-
- type: session_summary
|
|
4488
|
-
- session: import:organized
|
|
4489
|
-
# Module: vitest.config.ts
|
|
4490
|
-
|
|
4491
|
-
- responsibility: inferred from top-level path `vitest.config.ts/`
|
|
4492
|
-
- files: 1
|
|
4493
|
-
- languages: TypeScript
|
|
4494
|
-
- confidence: low
|
|
4495
|
-
|
|
4496
|
-
## Entry Candidates
|
|
4497
|
-
- none detected
|
|
4498
|
-
|
|
4499
|
-
## Related Commits (recent sample)
|
|
4500
|
-
- none in selected range
|
|
4501
|
-
|
|
4502
|
-
## Sources
|
|
4503
|
-
- source: repo-path:vitest.config.ts/**
|
|
4504
|
-
|
|
4505
|
-
## 2026-02-25T12:44:49.931Z | b68be7e7-e001-42ca-be4e-d5c07a37bf0d
|
|
4506
|
-
- type: session_summary
|
|
4507
|
-
- session: import:organized
|
|
4508
|
-
# Codebase Overview
|
|
4509
|
-
|
|
4510
|
-
- generatedAt: 2026-02-25T12:44:49.677Z
|
|
4511
|
-
- deterministicPipeline: true
|
|
4512
|
-
- repo: /home/walter/workspace/opensource/claude-memory-layer
|
|
4513
|
-
- filesAnalyzed: 150
|
|
4514
|
-
- commitsAnalyzed: 47
|
|
4515
|
-
- confidence: high
|
|
4516
|
-
|
|
4517
|
-
## Directory / Module Map
|
|
4518
|
-
- src: 70 files (TypeScript, JavaScript)
|
|
4519
|
-
- specs: 35 files (Markdown)
|
|
4520
|
-
- tests: 12 files (TypeScript)
|
|
4521
|
-
- .claude-plugin: 8 files (Markdown, JSON)
|
|
4522
|
-
- scripts: 6 files (JavaScript, Shell, TypeScript)
|
|
4523
|
-
- .omc: 4 files (JSON)
|
|
4524
|
-
- docs: 2 files (Markdown)
|
|
4525
|
-
- AGENTS.md: 1 files (Markdown)
|
|
4526
|
-
- CLAUDE.md: 1 files (Markdown)
|
|
4527
|
-
- context.md: 1 files (Markdown)
|
|
4528
|
-
- d.sh: 1 files (Shell)
|
|
4529
|
-
- deploy.sh: 1 files (Shell)
|
|
4530
|
-
- HANDOFF.md: 1 files (Markdown)
|
|
4531
|
-
- package-lock.json: 1 files (JSON)
|
|
4532
|
-
- package.json: 1 files (JSON)
|
|
4533
|
-
- plan.md: 1 files (Markdown)
|
|
4534
|
-
- README.md: 1 files (Markdown)
|
|
4535
|
-
- spec.md: 1 files (Markdown)
|
|
4536
|
-
- tsconfig.json: 1 files (JSON)
|
|
4537
|
-
- vitest.config.ts: 1 files (TypeScript)
|
|
4538
|
-
|
|
4539
|
-
## Fact
|
|
4540
|
-
- Generated from deterministic file scan and git history parsing.
|
|
4541
|
-
|
|
4542
|
-
## Inference
|
|
4543
|
-
- Module responsibilities should be reviewed by maintainers for nuanced boundaries.
|
|
4544
|
-
|
|
4545
|
-
## Sources
|
|
4546
|
-
- source: repo-scan:/home/walter/workspace/opensource/claude-memory-layer
|
|
4547
|
-
- source: git-log:since=180 days ago;max=1000
|
|
4548
|
-
|
|
4549
|
-
## 2026-02-25T12:44:49.939Z | a238e1a3-f03a-415a-b90c-ed2c563c2db2
|
|
4550
|
-
- type: session_summary
|
|
4551
|
-
- session: import:organized
|
|
4552
|
-
# Sources Manifest
|
|
4553
|
-
|
|
4554
|
-
- deterministicPipeline: true
|
|
4555
|
-
- mode: incremental
|
|
4556
|
-
- sourceCount: 197
|
|
4557
|
-
|
|
4558
|
-
## Outputs
|
|
4559
|
-
- decisions/decisions.md
|
|
4560
|
-
- glossary/glossary.md
|
|
4561
|
-
- modules/.claude-plugin.md
|
|
4562
|
-
- modules/agents.md.md
|
|
4563
|
-
- modules/claude.md.md
|
|
4564
|
-
- modules/context.md.md
|
|
4565
|
-
- modules/docs.md
|
|
4566
|
-
- modules/handoff.md.md
|
|
4567
|
-
- modules/package-lock.json.md
|
|
4568
|
-
- modules/package.json.md
|
|
4569
|
-
- modules/plan.md.md
|
|
4570
|
-
- modules/readme.md.md
|
|
4571
|
-
- modules/scripts.md
|
|
4572
|
-
- modules/spec.md.md
|
|
4573
|
-
- modules/specs.md
|
|
4574
|
-
- modules/src.md
|
|
4575
|
-
- modules/tests.md
|
|
4576
|
-
- modules/tsconfig.json.md
|
|
4577
|
-
- modules/vitest.config.ts.md
|
|
4578
|
-
- overview/overview.md
|
|
4579
|
-
- timeline/timeline.md
|
|
4580
|
-
|
|
4581
|
-
## Sources (sample)
|
|
4582
|
-
- file:.claude-plugin/commands/memory-forget.md
|
|
4583
|
-
- file:.claude-plugin/commands/memory-history.md
|
|
4584
|
-
- file:.claude-plugin/commands/memory-import.md
|
|
4585
|
-
- file:.claude-plugin/commands/memory-list.md
|
|
4586
|
-
- file:.claude-plugin/commands/memory-search.md
|
|
4587
|
-
- file:.claude-plugin/commands/memory-stats.md
|
|
4588
|
-
- file:.claude-plugin/hooks.json
|
|
4589
|
-
- file:.claude-plugin/plugin.json
|
|
4590
|
-
- file:.omc/project-memory.json
|
|
4591
|
-
- file:.omc/sessions/9d7106b0-883c-4ad7-b7be-39de88a483e5.json
|
|
4592
|
-
- file:.omc/sessions/dccdf47f-f9ef-4621-a49d-f333667baf0a.json
|
|
4593
|
-
- file:.omc/state/subagent-tracking.json
|
|
4594
|
-
- file:AGENTS.md
|
|
4595
|
-
- file:CLAUDE.md
|
|
4596
|
-
- file:HANDOFF.md
|
|
4597
|
-
- file:README.md
|
|
4598
|
-
- file:context.md
|
|
4599
|
-
- file:d.sh
|
|
4600
|
-
- file:deploy.sh
|
|
4601
|
-
- file:docs/MEMU_ADOPTION.md
|
|
4602
|
-
- file:docs/OPERATIONS.md
|
|
4603
|
-
- file:package-lock.json
|
|
4604
|
-
- file:package.json
|
|
4605
|
-
- file:plan.md
|
|
4606
|
-
- file:scripts/build.ts
|
|
4607
|
-
- file:scripts/fix-sync-gap.js
|
|
4608
|
-
- file:scripts/heartbeat-memory-orchestrator.sh
|
|
4609
|
-
- file:scripts/report-sync-gap.js
|
|
4610
|
-
- file:scripts/review-queue-auto-resolve.js
|
|
4611
|
-
- file:scripts/sync-gap-auto-heal.sh
|
|
4612
|
-
- file:spec.md
|
|
4613
|
-
- file:specs/20260207-dashboard-upgrade/context.md
|
|
4614
|
-
- file:specs/20260207-dashboard-upgrade/spec.md
|
|
4615
|
-
- file:specs/citations-system/context.md
|
|
4616
|
-
- file:specs/citations-system/plan.md
|
|
4617
|
-
- file:specs/citations-system/spec.md
|
|
4618
|
-
- file:specs/endless-mode/context.md
|
|
4619
|
-
- file:specs/endless-mode/plan.md
|
|
4620
|
-
- file:specs/endless-mode/spec.md
|
|
4621
|
-
- file:specs/entity-edge-model/context.md
|
|
4622
|
-
- file:specs/entity-edge-model/plan.md
|
|
4623
|
-
- file:specs/entity-edge-model/spec.md
|
|
4624
|
-
- file:specs/evidence-aligner-v2/context.md
|
|
4625
|
-
- file:specs/evidence-aligner-v2/plan.md
|
|
4626
|
-
- file:specs/evidence-aligner-v2/spec.md
|
|
4627
|
-
- file:specs/mcp-desktop-integration/context.md
|
|
4628
|
-
- file:specs/mcp-desktop-integration/plan.md
|
|
4629
|
-
- file:specs/mcp-desktop-integration/spec.md
|
|
4630
|
-
- file:specs/post-tool-use-hook/context.md
|
|
4631
|
-
- file:specs/post-tool-use-hook/plan.md
|
|
4632
|
-
- file:specs/post-tool-use-hook/spec.md
|
|
4633
|
-
- file:specs/private-tags/context.md
|
|
4634
|
-
- file:specs/private-tags/plan.md
|
|
4635
|
-
- file:specs/private-tags/spec.md
|
|
4636
|
-
- file:specs/progressive-disclosure/context.md
|
|
4637
|
-
- file:specs/progressive-disclosure/plan.md
|
|
4638
|
-
- file:specs/progressive-disclosure/spec.md
|
|
4639
|
-
- file:specs/task-entity-system/context.md
|
|
4640
|
-
- file:specs/task-entity-system/plan.md
|
|
4641
|
-
- file:specs/task-entity-system/spec.md
|
|
4642
|
-
- file:specs/vector-outbox-v2/context.md
|
|
4643
|
-
- file:specs/vector-outbox-v2/plan.md
|
|
4644
|
-
- file:specs/vector-outbox-v2/spec.md
|
|
4645
|
-
- file:specs/web-viewer-ui/context.md
|
|
4646
|
-
- file:specs/web-viewer-ui/plan.md
|
|
4647
|
-
- file:specs/web-viewer-ui/spec.md
|
|
4648
|
-
- file:src/cli/index.ts
|
|
4649
|
-
- file:src/core/canonical-key.ts
|
|
4650
|
-
- file:src/core/citation-generator.ts
|
|
4651
|
-
- file:src/core/consolidated-store.ts
|
|
4652
|
-
- file:src/core/consolidation-worker.ts
|
|
4653
|
-
- file:src/core/context-formatter.ts
|
|
4654
|
-
- file:src/core/continuity-manager.ts
|
|
4655
|
-
- file:src/core/db-wrapper.ts
|
|
4656
|
-
- file:src/core/edge-repo.ts
|
|
4657
|
-
- file:src/core/embedder.ts
|
|
4658
|
-
- file:src/core/entity-repo.ts
|
|
4659
|
-
- file:src/core/event-store.ts
|
|
4660
|
-
- file:src/core/evidence-aligner.ts
|
|
4661
|
-
- file:src/core/graduation-worker.ts
|
|
4662
|
-
- file:src/core/graduation.ts
|
|
4663
|
-
- file:src/core/index.ts
|
|
4664
|
-
- file:src/core/ingest-interceptor.ts
|
|
4665
|
-
- file:src/core/markdown-mirror.ts
|
|
4666
|
-
- file:src/core/matcher.ts
|
|
4667
|
-
- file:src/core/md-mirror.ts
|
|
4668
|
-
- file:src/core/metadata-extractor.ts
|
|
4669
|
-
- file:src/core/mongo-sync-config.ts
|
|
4670
|
-
- file:src/core/mongo-sync-worker.ts
|
|
4671
|
-
- file:src/core/privacy/filter.ts
|
|
4672
|
-
- file:src/core/privacy/index.ts
|
|
4673
|
-
- file:src/core/privacy/tag-parser.ts
|
|
4674
|
-
- file:src/core/progressive-retriever.ts
|
|
4675
|
-
- file:src/core/retriever.ts
|
|
4676
|
-
- file:src/core/shared-event-store.ts
|
|
4677
|
-
- file:src/core/shared-promoter.ts
|
|
4678
|
-
- file:src/core/shared-store.ts
|
|
4679
|
-
- file:src/core/shared-vector-store.ts
|
|
4680
|
-
- file:src/core/sqlite-event-store.ts
|
|
4681
|
-
- file:src/core/sqlite-wrapper.ts
|
|
4682
|
-
- file:src/core/sync-worker.ts
|
|
4683
|
-
- file:src/core/task/blocker-resolver.ts
|
|
4684
|
-
- file:src/core/task/index.ts
|
|
4685
|
-
- file:src/core/task/task-matcher.ts
|
|
4686
|
-
- file:src/core/task/task-projector.ts
|
|
4687
|
-
- file:src/core/task/task-resolver.ts
|
|
4688
|
-
- file:src/core/turn-state.ts
|
|
4689
|
-
- file:src/core/types.ts
|
|
4690
|
-
- file:src/core/vector-outbox.ts
|
|
4691
|
-
- file:src/core/vector-store.ts
|
|
4692
|
-
- file:src/core/vector-worker.ts
|
|
4693
|
-
- file:src/core/working-set-store.ts
|
|
4694
|
-
- file:src/hooks/post-tool-use.ts
|
|
4695
|
-
- file:src/hooks/session-end.ts
|
|
4696
|
-
- file:src/hooks/session-start.ts
|
|
4697
|
-
- file:src/hooks/stop.ts
|
|
4698
|
-
- file:src/hooks/user-prompt-submit.ts
|
|
4699
|
-
- file:src/mcp/handlers.ts
|
|
4700
|
-
- file:src/mcp/index.ts
|
|
4701
|
-
- file:src/mcp/tools.ts
|
|
4702
|
-
- file:src/server/api/chat.ts
|
|
4703
|
-
- file:src/server/api/citations.ts
|
|
4704
|
-
- file:src/server/api/events.ts
|
|
4705
|
-
- file:src/server/api/index.ts
|
|
4706
|
-
- file:src/server/api/projects.ts
|
|
4707
|
-
- file:src/server/api/search.ts
|
|
4708
|
-
- file:src/server/api/sessions.ts
|
|
4709
|
-
- file:src/server/api/stats.ts
|
|
4710
|
-
- file:src/server/api/turns.ts
|
|
4711
|
-
- file:src/server/api/utils.ts
|
|
4712
|
-
- file:src/server/index.ts
|
|
4713
|
-
- file:src/services/bootstrap-organizer.ts
|
|
4714
|
-
- file:src/services/codex-session-history-importer.ts
|
|
4715
|
-
- file:src/services/memory-service.ts
|
|
4716
|
-
- file:src/services/session-history-importer.ts
|
|
4717
|
-
- file:src/ui/app.js
|
|
4718
|
-
- file:tests/bootstrap-organizer.test.ts
|
|
4719
|
-
- file:tests/canonical-key.test.ts
|
|
4720
|
-
- file:tests/consolidation-worker.test.ts
|
|
4721
|
-
- file:tests/evidence-aligner.test.ts
|
|
4722
|
-
- file:tests/ingest-interceptor.test.ts
|
|
4723
|
-
- file:tests/markdown-mirror.test.ts
|
|
4724
|
-
- file:tests/matcher.test.ts
|
|
4725
|
-
- file:tests/md-mirror.test.ts
|
|
4726
|
-
- file:tests/retriever-fallback-chain.test.ts
|
|
4727
|
-
- file:tests/retriever-strategy-scope.test.ts
|
|
4728
|
-
- file:tests/retriever.memu-adoption.test.ts
|
|
4729
|
-
- file:tests/sqlite-event-store-replication.test.ts
|
|
4730
|
-
- file:tsconfig.json
|
|
4731
|
-
- file:vitest.config.ts
|
|
4732
|
-
- commit:09a27030ac03dc003fc725ce1fd360a53ca3159f
|
|
4733
|
-
- commit:e0fb3078d786dd6f6a4cd8fac87e547668c04466
|
|
4734
|
-
- commit:83614efe2baf9ca3223508daecfff2e55fbf092e
|
|
4735
|
-
- commit:111f400e73f0568b192a5b1b37a88622fd44d648
|
|
4736
|
-
- commit:22b1c43d9b9f095cd2a210f529ca8bee5a1100c5
|
|
4737
|
-
- commit:ead5da9868336e6bb0696fd5ee236bc32c327079
|
|
4738
|
-
- commit:03ce3f8393e52df24f86ffc10756d3974204c373
|
|
4739
|
-
- commit:4bbbc7174f920434cfc67ee02746a9b9824ec101
|
|
4740
|
-
- commit:504ec3ddd7f451fabf2cf01e073fc96e65ae124e
|
|
4741
|
-
- commit:3662dfae8381fdf35923b115f58c362e091c474a
|
|
4742
|
-
- commit:d04e562b5b011e0f07cdea0664db823f0caca5d0
|
|
4743
|
-
- commit:65b0f64da3fd2c4b0b758b89f9d0f22301df23a7
|
|
4744
|
-
- commit:665cf11bb9a01f1bcba51ec49f53382e95cd7e32
|
|
4745
|
-
- commit:f35da2b92704d7d1b5655edac3516c64a829eeef
|
|
4746
|
-
- commit:d4f1f16858e2bf2436f12e4141fedbecf3a75851
|
|
4747
|
-
- commit:be36be70f69d42d2373ac26e6c0b8e8b53ca0340
|
|
4748
|
-
- commit:babfd15284754bc3dbb698fcc4c81efcf53fcd85
|
|
4749
|
-
- commit:543643e7a9f1d4a94f3216c2369d0212a51ff32d
|
|
4750
|
-
- commit:a8a8b4edb28a04c1d07abd6e67625f6b68b67b55
|
|
4751
|
-
- commit:794640023652fc38b010e1ab46ca6a9a504a09e8
|
|
4752
|
-
- commit:20c37b2cdffd271eaf04df9d2e87e5f23a4f853e
|
|
4753
|
-
- commit:a1d93af414821eb92d74cd02abb748849366ebfb
|
|
4754
|
-
- commit:fd8f38af7cecf7d31a32a5aba9b1902178f986b1
|
|
4755
|
-
- commit:938ec34bdf5fe1e4c43274424497ca081d62023a
|
|
4756
|
-
- commit:af18cee5277324c78a9e1bca5873bc86ee5b2719
|
|
4757
|
-
- commit:5b7401917611b50ee49e38bdf080983d1c763d5e
|
|
4758
|
-
- commit:a7b260f0ceeff6d768fefb675e6425f5b4717d7e
|
|
4759
|
-
- commit:15547d41e952350d095dfe3c01b2afa749638532
|
|
4760
|
-
- commit:78b0956610eb7d22c28a821c67e10e6e9996c5be
|
|
4761
|
-
- commit:d56d22ba3271c1d51ea8bbaddb21f5f3d0a79d49
|
|
4762
|
-
- commit:11d3092e372836f784a760fc0b4269fd44e9159f
|
|
4763
|
-
- commit:4855172b8f92fff0c148c106de4e10c494d2bb09
|
|
4764
|
-
- commit:d278200d0f0666616a8556f2f25f9758b3ab9afd
|
|
4765
|
-
- commit:4447e64fa00065bfb364d38c597ad87484770891
|
|
4766
|
-
- commit:e25f03a7680d82532d10620d3495ac6dc2b67a46
|
|
4767
|
-
- commit:917ad7fc97a1c2de68637dfbe4b4cdd51776ec30
|
|
4768
|
-
- commit:72250046152e851ed70476a8704ca38ca633ffab
|
|
4769
|
-
- commit:3a34d45a594affb034d6e416e3a29b6d2dcc20a5
|
|
4770
|
-
- commit:df15146c2a8c3e389c1a2b8d6fcfb4a33f7a772d
|
|
4771
|
-
- commit:fe9ef67e5acabb81885a3c752a5b8525f80856a5
|
|
4772
|
-
- commit:0dceb2d914e67e10d140848340f30e6fd07c4f67
|
|
4773
|
-
- commit:7de02967a1d59aea3e04ef1239585b93828c503a
|
|
4774
|
-
- commit:46f2cfa2d99f0c8fb3a48709a97f62800f01d4fe
|
|
4775
|
-
- commit:5fd950beee4d02f00b0c93be668a2e114ce9b257
|
|
4776
|
-
- commit:d1dfe03f881d1a76ecd9a916cbf04c3ff2a4bf7e
|
|
4777
|
-
- commit:7c84b5eacff733d8cb692eb9d47b7297a0872e43
|
|
4778
|
-
- commit:db38c7e606a59478c03bac7e5bb5951954ca0813
|
|
4779
|
-
|
|
4780
|
-
## 2026-02-25T12:44:49.946Z | 244d330a-f728-4c93-bcfc-93c4096cd3b5
|
|
4781
|
-
- type: session_summary
|
|
4782
|
-
- session: import:organized
|
|
4783
|
-
# Timeline
|
|
4784
|
-
|
|
4785
|
-
- confidence: mid
|
|
4786
|
-
|
|
4787
|
-
## 2026-01
|
|
4788
|
-
- 2026-01-31 09a27030 docs: add specification documents for code-memory plugin
|
|
4789
|
-
- 2026-01-31 e0fb3078 docs: enhance AXIOMMIND integration in specification documents
|
|
4790
|
-
- 2026-01-31 83614efe docs: add Memory Graduation Pipeline and 7 AXIOMMIND principles
|
|
4791
|
-
- 2026-01-31 111f400e feat: implement complete code-memory plugin
|
|
4792
|
-
- 2026-01-31 22b1c43d feat: add session history import functionality
|
|
4793
|
-
- 2026-01-31 ead5da98 docs: update README with detailed Korean documentation
|
|
4794
|
-
- 2026-01-31 03ce3f83 Add implementation guide for AxiomMind Memory Pipeline
|
|
4795
|
-
|
|
4796
|
-
## 2026-02
|
|
4797
|
-
- 2026-02-01 4bbbc717 Merge pull request #1 from buzzni/claude/idris2-memory-storage-JLk7J
|
|
4798
|
-
- 2026-02-01 504ec3dd docs: Add citations and endless mode specification documents (#2)
|
|
4799
|
-
- 2026-02-01 3662dfae docs: Update README with comprehensive feature documentation (#3)
|
|
4800
|
-
- 2026-02-01 d04e562b feat: Add cross-project shared troubleshooting store
|
|
4801
|
-
- 2026-02-01 65b0f64d refactor: Extract DuckDB wrapper for consistent async API
|
|
4802
|
-
- 2026-02-01 665cf11b feat: Add web dashboard for memory visualization
|
|
4803
|
-
- 2026-02-01 f35da2b9 refactor: Rename project from code-memory to claude-memory-layer
|
|
4804
|
-
- 2026-02-01 d4f1f168 docs: Update README for claude-memory-layer rename
|
|
4805
|
-
- 2026-02-01 be36be70 feat: Migrate primary store from DuckDB to SQLite (WAL mode)
|
|
4806
|
-
- 2026-02-01 babfd152 feat: Enhance dashboard, CLI, and memory graduation system
|
|
4807
|
-
- 2026-02-02 543643e7 perf: Add fast keyword search and optimize hook performance
|
|
4808
|
-
- 2026-02-06 a8a8b4ed chore: Bump version to 1.0.10 and add project configuration
|
|
4809
|
-
- 2026-02-07 79464002 feat: Add memory helpfulness tracking and dashboard sort controls
|
|
4810
|
-
- 2026-02-08 20c37b2c feat: Add interactive dashboard with modals, navigation, and detail views
|
|
4811
|
-
- 2026-02-08 a1d93af4 fix: Align hooks with actual Claude Code input format and use lightweight service
|
|
4812
|
-
- 2026-02-08 fd8f38af feat: Add real-time progress display for import command
|
|
4813
|
-
- 2026-02-08 938ec34b feat: Add turn-based event grouping, force reimport, and session registry support
|
|
4814
|
-
- 2026-02-08 af18cee5 feat: Add per-project dashboard with project selector and turns API
|
|
4815
|
-
- 2026-02-08 5b740191 fix: Handle vector store table race condition and auto-create SQLite directories
|
|
4816
|
-
- 2026-02-08 a7b260f0 feat: Add Ask Memory chat service to dashboard
|
|
4817
|
-
- 2026-02-08 15547d41 feat: Widen chat panel and add conversation history with localStorage
|
|
4818
|
-
- 2026-02-08 78b09566 fix: Knowledge Graph shows data even when no memories have been accessed
|
|
4819
|
-
- 2026-02-20 d56d22ba feat(ops): add heartbeat orchestrator and sync-gap auto-heal scripts
|
|
4820
|
-
- 2026-02-09 11d3092e feat: optional MongoDB sync for project events
|
|
4821
|
-
- 2026-02-22 4855172b feat: add Codex session history importer, MongoDB sync config, and AGENTS.md
|
|
4822
|
-
- 2026-02-24 d278200d feat(memory): adopt memU-style scoped retrieval and staged ingest hooks
|
|
4823
|
-
- 2026-02-24 4447e64f docs(memory): document memU-inspired retrieval strategies and scoped filters
|
|
4824
|
-
- 2026-02-24 e25f03a7 docs(readme): add practical examples for memU-inspired retrieval options
|
|
4825
|
-
- 2026-02-24 917ad7fc feat(memory): add append-only markdown mirror for categorized event archives
|
|
4826
|
-
- 2026-02-24 72250046 feat: append-only markdown mirror in sqlite ingest flow
|
|
4827
|
-
- 2026-02-24 3a34d45a feat(memory): auto-refresh markdown mirror index
|
|
4828
|
-
- 2026-02-24 df15146c chore(memory): normalize markdown mirror default category to uncategorized
|
|
4829
|
-
- 2026-02-24 fe9ef67e feat(cli): add organize-import command for structured markdown memory import
|
|
4830
|
-
- 2026-02-24 0dceb2d9 feat(retrieval): add auto fallback chain fast→deep→scope-expand→summary
|
|
4831
|
-
- 2026-02-24 7de02967 feat(ranking): add helpfulness-driven adaptive rerank weights v1
|
|
4832
|
-
- 2026-02-24 46f2cfa2 feat(retrieval): add ttl/decay ranking policy v1
|
|
4833
|
-
- 2026-02-24 5fd950be feat(retrieval): add intent-rewrite deep retrieval merge flow
|
|
4834
|
-
- 2026-02-24 d1dfe03f feat(retrieval): add graph-hop expansion with hop penalty
|
|
4835
|
-
- 2026-02-24 7c84b5ea feat(consolidation): add hierarchical summary→rule automation with report
|
|
4836
|
-
- 2026-02-25 db38c7e6 Feat/organize import bootstrap kb (#10)
|
|
4837
|
-
|
|
4838
|
-
## Sources
|
|
4839
|
-
- source: git-log:since=180 days ago;max=1000
|