memory-layer-mcp 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. memory_layer_mcp-0.5.0/.claude/settings.local.json +69 -0
  2. memory_layer_mcp-0.5.0/.github/workflows/tests.yml +27 -0
  3. memory_layer_mcp-0.5.0/.gitignore +20 -0
  4. memory_layer_mcp-0.5.0/AGENTS.md +5 -0
  5. memory_layer_mcp-0.5.0/CHANGELOG.md +301 -0
  6. memory_layer_mcp-0.5.0/CLAUDE.md +46 -0
  7. memory_layer_mcp-0.5.0/HANDOFF.md +2015 -0
  8. memory_layer_mcp-0.5.0/LICENSE +21 -0
  9. memory_layer_mcp-0.5.0/PKG-INFO +773 -0
  10. memory_layer_mcp-0.5.0/README.md +716 -0
  11. memory_layer_mcp-0.5.0/benchmarks/agent_loop_loose.json +337 -0
  12. memory_layer_mcp-0.5.0/benchmarks/agent_loop_sim.py +308 -0
  13. memory_layer_mcp-0.5.0/benchmarks/agent_loop_strict.json +337 -0
  14. memory_layer_mcp-0.5.0/benchmarks/authority_poc/apply_labels.py +249 -0
  15. memory_layer_mcp-0.5.0/benchmarks/authority_poc/external_queries.json +145 -0
  16. memory_layer_mcp-0.5.0/benchmarks/authority_poc/gold_queries.json +66 -0
  17. memory_layer_mcp-0.5.0/benchmarks/authority_poc/gold_queries_v2.json +721 -0
  18. memory_layer_mcp-0.5.0/benchmarks/authority_poc/label_me.tsv +201 -0
  19. memory_layer_mcp-0.5.0/benchmarks/authority_poc/results.json +2712 -0
  20. memory_layer_mcp-0.5.0/benchmarks/authority_poc/results_v2.json +38402 -0
  21. memory_layer_mcp-0.5.0/benchmarks/authority_poc/run.py +182 -0
  22. memory_layer_mcp-0.5.0/benchmarks/authority_poc/run_v2.py +298 -0
  23. memory_layer_mcp-0.5.0/benchmarks/authority_poc/score.py +149 -0
  24. memory_layer_mcp-0.5.0/benchmarks/authority_poc/score_v2.py +303 -0
  25. memory_layer_mcp-0.5.0/benchmarks/benchmark_micro_results.json +644 -0
  26. memory_layer_mcp-0.5.0/benchmarks/compounding_pairs.json +260 -0
  27. memory_layer_mcp-0.5.0/benchmarks/compounding_report_2026-04-22.md +87 -0
  28. memory_layer_mcp-0.5.0/benchmarks/compounding_report_2026-04-23.md +87 -0
  29. memory_layer_mcp-0.5.0/benchmarks/compounding_results.json +1855 -0
  30. memory_layer_mcp-0.5.0/benchmarks/confidence_eval.py +138 -0
  31. memory_layer_mcp-0.5.0/benchmarks/memory_gold.json +49 -0
  32. memory_layer_mcp-0.5.0/benchmarks/memory_layer_v2_2026-04-28.json +527 -0
  33. memory_layer_mcp-0.5.0/benchmarks/memory_layer_v2_2026-04-28.md +43 -0
  34. memory_layer_mcp-0.5.0/benchmarks/prefetch_precision.py +188 -0
  35. memory_layer_mcp-0.5.0/benchmarks/query_set.json +217 -0
  36. memory_layer_mcp-0.5.0/benchmarks/router_calibration/valuein_gold.json +32 -0
  37. memory_layer_mcp-0.5.0/benchmarks/router_eval.py +84 -0
  38. memory_layer_mcp-0.5.0/benchmarks/router_gold.json +219 -0
  39. memory_layer_mcp-0.5.0/benchmarks/router_replay_2026-05.md +102 -0
  40. memory_layer_mcp-0.5.0/benchmarks/run_benchmark.py +373 -0
  41. memory_layer_mcp-0.5.0/benchmarks/run_benchmark_fast.py +256 -0
  42. memory_layer_mcp-0.5.0/benchmarks/run_benchmark_micro.py +200 -0
  43. memory_layer_mcp-0.5.0/benchmarks/run_benchmark_v2.py +306 -0
  44. memory_layer_mcp-0.5.0/benchmarks/run_compounding_bench.py +582 -0
  45. memory_layer_mcp-0.5.0/benchmarks/run_v040_valuein_experiment.py +508 -0
  46. memory_layer_mcp-0.5.0/benchmarks/run_valuein_bench.py +405 -0
  47. memory_layer_mcp-0.5.0/benchmarks/v040_experiment_2026-04-23.json +61 -0
  48. memory_layer_mcp-0.5.0/benchmarks/v040_experiment_2026-04-23.md +60 -0
  49. memory_layer_mcp-0.5.0/benchmarks/valuein_gold.json +281 -0
  50. memory_layer_mcp-0.5.0/benchmarks/valuein_report_2026-04-22.md +132 -0
  51. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v10_step_k_2026-04-22.md +164 -0
  52. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v2_2026-04-22.md +83 -0
  53. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v3_step_a_2026-04-22.md +58 -0
  54. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v4_step_b_2026-04-22.md +88 -0
  55. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v5_step_c_2026-04-22.md +108 -0
  56. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v6_step_d_e_2026-04-22.md +169 -0
  57. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v7_step_f_2026-04-22.md +211 -0
  58. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v8_step_g_2026-04-22.md +171 -0
  59. memory_layer_mcp-0.5.0/benchmarks/valuein_report_v9_step_j_2026-04-22.md +128 -0
  60. memory_layer_mcp-0.5.0/benchmarks/valuein_results.json +1308 -0
  61. memory_layer_mcp-0.5.0/benchmarks/wiki_bloat_audit_valuein_2026-04-23.md +101 -0
  62. memory_layer_mcp-0.5.0/docs/case-studies/2026-05-20-payssam-v2-migration.md +193 -0
  63. memory_layer_mcp-0.5.0/docs/plans/2026-04-26-memory-layer-10x-context-engineering.md +882 -0
  64. memory_layer_mcp-0.5.0/docs/plans/2026-05-12-phase4-codex-handoff.md +289 -0
  65. memory_layer_mcp-0.5.0/docs/plans/2026-05-20-distribution-artifacts.md +282 -0
  66. memory_layer_mcp-0.5.0/docs/plans/2026-05-20-phase5-in-flight-visibility.md +436 -0
  67. memory_layer_mcp-0.5.0/docs/plans/archive/2026-04-21-PLAN_q1_routing_hook.md +212 -0
  68. memory_layer_mcp-0.5.0/docs/plans/archive/2026-04-21-memory-layer-10x.md +424 -0
  69. memory_layer_mcp-0.5.0/docs/plans/completed/2026-04-14-design.md +622 -0
  70. memory_layer_mcp-0.5.0/docs/plans/completed/2026-04-16-conversation-indexing.md +288 -0
  71. memory_layer_mcp-0.5.0/docs/plans/completed/2026-04-23-v0.4.0-memory-integrity.md +225 -0
  72. memory_layer_mcp-0.5.0/docs/plans/completed/2026-04-26-codex-memory-hooks.md +556 -0
  73. memory_layer_mcp-0.5.0/docs/plans/completed/2026-05-01-router-and-quality-signals.md +397 -0
  74. memory_layer_mcp-0.5.0/docs/plans/completed/v0.3.0-deterministic-memory.md +242 -0
  75. memory_layer_mcp-0.5.0/docs/sns/2026-04-14-linkedin-hybrid-search-story.md +70 -0
  76. memory_layer_mcp-0.5.0/docs/sns/2026-05-XX-okky-velog.md +144 -0
  77. memory_layer_mcp-0.5.0/docs/sns/2026-05-XX-reddit-r-claudeai.md +114 -0
  78. memory_layer_mcp-0.5.0/docs/sns/2026-05-XX-reddit-r-localllama.md +108 -0
  79. memory_layer_mcp-0.5.0/docs/sns/2026-05-XX-show-hn.md +143 -0
  80. memory_layer_mcp-0.5.0/docs/why.ko.md +70 -0
  81. memory_layer_mcp-0.5.0/docs/why.md +70 -0
  82. memory_layer_mcp-0.5.0/pyproject.toml +70 -0
  83. memory_layer_mcp-0.5.0/scripts/poc_conv_retrieval_eval.py +185 -0
  84. memory_layer_mcp-0.5.0/scripts/poc_transcript_chunks.py +102 -0
  85. memory_layer_mcp-0.5.0/scripts/post-checkout-hook.sh +34 -0
  86. memory_layer_mcp-0.5.0/scripts/post-commit-hook.sh +24 -0
  87. memory_layer_mcp-0.5.0/scripts/wiki_bloat_audit.py +361 -0
  88. memory_layer_mcp-0.5.0/skills/bootstrap-wiki.md +150 -0
  89. memory_layer_mcp-0.5.0/skills/maintain.md +196 -0
  90. memory_layer_mcp-0.5.0/skills/rebuild-index.md +129 -0
  91. memory_layer_mcp-0.5.0/skills/save-wiki.md +65 -0
  92. memory_layer_mcp-0.5.0/skills/search.md +104 -0
  93. memory_layer_mcp-0.5.0/skills/setup-hybrid-search.md +115 -0
  94. memory_layer_mcp-0.5.0/src/hybrid_search/__init__.py +3 -0
  95. memory_layer_mcp-0.5.0/src/hybrid_search/cli.py +5231 -0
  96. memory_layer_mcp-0.5.0/src/hybrid_search/codex_hooks.py +495 -0
  97. memory_layer_mcp-0.5.0/src/hybrid_search/config.py +448 -0
  98. memory_layer_mcp-0.5.0/src/hybrid_search/hooks.py +721 -0
  99. memory_layer_mcp-0.5.0/src/hybrid_search/index/__init__.py +0 -0
  100. memory_layer_mcp-0.5.0/src/hybrid_search/index/ast_chunker.py +1248 -0
  101. memory_layer_mcp-0.5.0/src/hybrid_search/index/callgraph.py +296 -0
  102. memory_layer_mcp-0.5.0/src/hybrid_search/index/conversation_indexer.py +283 -0
  103. memory_layer_mcp-0.5.0/src/hybrid_search/index/dag.py +961 -0
  104. memory_layer_mcp-0.5.0/src/hybrid_search/index/doc_chunker.py +223 -0
  105. memory_layer_mcp-0.5.0/src/hybrid_search/index/drift.py +71 -0
  106. memory_layer_mcp-0.5.0/src/hybrid_search/index/embedder.py +220 -0
  107. memory_layer_mcp-0.5.0/src/hybrid_search/index/module_synth.py +327 -0
  108. memory_layer_mcp-0.5.0/src/hybrid_search/index/modules.py +552 -0
  109. memory_layer_mcp-0.5.0/src/hybrid_search/index/pipeline.py +580 -0
  110. memory_layer_mcp-0.5.0/src/hybrid_search/index/scanner.py +635 -0
  111. memory_layer_mcp-0.5.0/src/hybrid_search/index/synthesizer.py +611 -0
  112. memory_layer_mcp-0.5.0/src/hybrid_search/index/transcript_source.py +506 -0
  113. memory_layer_mcp-0.5.0/src/hybrid_search/memory/__init__.py +9 -0
  114. memory_layer_mcp-0.5.0/src/hybrid_search/memory/cards.py +457 -0
  115. memory_layer_mcp-0.5.0/src/hybrid_search/memory/hook_runtime.py +286 -0
  116. memory_layer_mcp-0.5.0/src/hybrid_search/memory/integrity.py +447 -0
  117. memory_layer_mcp-0.5.0/src/hybrid_search/memory/qa_log.py +538 -0
  118. memory_layer_mcp-0.5.0/src/hybrid_search/memory/quality.py +96 -0
  119. memory_layer_mcp-0.5.0/src/hybrid_search/memory/reader.py +529 -0
  120. memory_layer_mcp-0.5.0/src/hybrid_search/memory/router.py +147 -0
  121. memory_layer_mcp-0.5.0/src/hybrid_search/memory/routing_template.py +218 -0
  122. memory_layer_mcp-0.5.0/src/hybrid_search/project.py +114 -0
  123. memory_layer_mcp-0.5.0/src/hybrid_search/search/__init__.py +0 -0
  124. memory_layer_mcp-0.5.0/src/hybrid_search/search/bm25.py +158 -0
  125. memory_layer_mcp-0.5.0/src/hybrid_search/search/conv_in_flight.py +164 -0
  126. memory_layer_mcp-0.5.0/src/hybrid_search/search/fusion.py +95 -0
  127. memory_layer_mcp-0.5.0/src/hybrid_search/search/in_flight.py +304 -0
  128. memory_layer_mcp-0.5.0/src/hybrid_search/search/modules_search.py +309 -0
  129. memory_layer_mcp-0.5.0/src/hybrid_search/search/orchestrator.py +1877 -0
  130. memory_layer_mcp-0.5.0/src/hybrid_search/search/snippet.py +85 -0
  131. memory_layer_mcp-0.5.0/src/hybrid_search/search/vector.py +202 -0
  132. memory_layer_mcp-0.5.0/src/hybrid_search/security.py +150 -0
  133. memory_layer_mcp-0.5.0/src/hybrid_search/server.py +221 -0
  134. memory_layer_mcp-0.5.0/src/hybrid_search/storage/__init__.py +0 -0
  135. memory_layer_mcp-0.5.0/src/hybrid_search/storage/db.py +1108 -0
  136. memory_layer_mcp-0.5.0/src/hybrid_search/storage/indexes.py +45 -0
  137. memory_layer_mcp-0.5.0/src/hybrid_search/storage/wiki.py +645 -0
  138. memory_layer_mcp-0.5.0/src/hybrid_search/tools/__init__.py +0 -0
  139. memory_layer_mcp-0.5.0/src/hybrid_search/tools/hybrid_search.py +136 -0
  140. memory_layer_mcp-0.5.0/src/hybrid_search/tools/index.py +65 -0
  141. memory_layer_mcp-0.5.0/src/hybrid_search/tools/projects.py +50 -0
  142. memory_layer_mcp-0.5.0/src/hybrid_search/tools/semantic_search.py +158 -0
  143. memory_layer_mcp-0.5.0/src/hybrid_search/tools/symbols.py +60 -0
  144. memory_layer_mcp-0.5.0/src/hybrid_search/tools/trace.py +297 -0
  145. memory_layer_mcp-0.5.0/src/hybrid_search/tools/wiki.py +212 -0
  146. memory_layer_mcp-0.5.0/src/hybrid_search/wiki_cleanup.py +178 -0
  147. memory_layer_mcp-0.5.0/templates/CLAUDE_md_search_section.md +32 -0
  148. memory_layer_mcp-0.5.0/tests/__init__.py +0 -0
  149. memory_layer_mcp-0.5.0/tests/test_ast_chunker.py +411 -0
  150. memory_layer_mcp-0.5.0/tests/test_callgraph.py +870 -0
  151. memory_layer_mcp-0.5.0/tests/test_cli_hook_install.py +1002 -0
  152. memory_layer_mcp-0.5.0/tests/test_code_lane_guard.py +173 -0
  153. memory_layer_mcp-0.5.0/tests/test_codex_hooks.py +251 -0
  154. memory_layer_mcp-0.5.0/tests/test_config.py +187 -0
  155. memory_layer_mcp-0.5.0/tests/test_conv_in_flight.py +269 -0
  156. memory_layer_mcp-0.5.0/tests/test_conversation_hook_spawn.py +65 -0
  157. memory_layer_mcp-0.5.0/tests/test_conversation_indexer.py +261 -0
  158. memory_layer_mcp-0.5.0/tests/test_conversation_lane.py +106 -0
  159. memory_layer_mcp-0.5.0/tests/test_conversation_store.py +180 -0
  160. memory_layer_mcp-0.5.0/tests/test_cwd_boost.py +109 -0
  161. memory_layer_mcp-0.5.0/tests/test_dag.py +640 -0
  162. memory_layer_mcp-0.5.0/tests/test_doc_chunker.py +175 -0
  163. memory_layer_mcp-0.5.0/tests/test_drift.py +122 -0
  164. memory_layer_mcp-0.5.0/tests/test_embedder.py +140 -0
  165. memory_layer_mcp-0.5.0/tests/test_fusion.py +233 -0
  166. memory_layer_mcp-0.5.0/tests/test_graph_cli.py +330 -0
  167. memory_layer_mcp-0.5.0/tests/test_in_flight_overlay.py +284 -0
  168. memory_layer_mcp-0.5.0/tests/test_memory_boost.py +250 -0
  169. memory_layer_mcp-0.5.0/tests/test_memory_cards.py +116 -0
  170. memory_layer_mcp-0.5.0/tests/test_memory_hook.py +686 -0
  171. memory_layer_mcp-0.5.0/tests/test_memory_integrity.py +303 -0
  172. memory_layer_mcp-0.5.0/tests/test_memory_layer_e2e.py +184 -0
  173. memory_layer_mcp-0.5.0/tests/test_memory_quality.py +170 -0
  174. memory_layer_mcp-0.5.0/tests/test_module_injection.py +420 -0
  175. memory_layer_mcp-0.5.0/tests/test_module_synth.py +389 -0
  176. memory_layer_mcp-0.5.0/tests/test_modules.py +565 -0
  177. memory_layer_mcp-0.5.0/tests/test_modules_search.py +367 -0
  178. memory_layer_mcp-0.5.0/tests/test_orchestrator.py +499 -0
  179. memory_layer_mcp-0.5.0/tests/test_pipeline.py +93 -0
  180. memory_layer_mcp-0.5.0/tests/test_qa_log.py +346 -0
  181. memory_layer_mcp-0.5.0/tests/test_qa_reader.py +390 -0
  182. memory_layer_mcp-0.5.0/tests/test_query_classifier.py +108 -0
  183. memory_layer_mcp-0.5.0/tests/test_reranker.py +214 -0
  184. memory_layer_mcp-0.5.0/tests/test_router.py +118 -0
  185. memory_layer_mcp-0.5.0/tests/test_routing_template.py +164 -0
  186. memory_layer_mcp-0.5.0/tests/test_scanner.py +736 -0
  187. memory_layer_mcp-0.5.0/tests/test_security.py +324 -0
  188. memory_layer_mcp-0.5.0/tests/test_server_stdin_filter.py +64 -0
  189. memory_layer_mcp-0.5.0/tests/test_snippet.py +169 -0
  190. memory_layer_mcp-0.5.0/tests/test_store_db.py +280 -0
  191. memory_layer_mcp-0.5.0/tests/test_synthesizer.py +582 -0
  192. memory_layer_mcp-0.5.0/tests/test_wiki.py +336 -0
  193. memory_layer_mcp-0.5.0/tests/test_wiki_cleanup.py +97 -0
  194. memory_layer_mcp-0.5.0/tests/test_wiki_orphan_cleanup.py +113 -0
@@ -0,0 +1,69 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "Edit|Write",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "ROOT=$(git rev-parse --show-toplevel 2>/dev/null) && [ -n \"$ROOT\" ] && [ -f \"$ROOT/.hybrid-search/wiki/STALE.md\" ] && echo 'STALE wiki pages detected — update them BEFORE editing code:' && cat \"$ROOT/.hybrid-search/wiki/STALE.md\"; :"
10
+ }
11
+ ]
12
+ },
13
+ {
14
+ "matcher": "Grep|Read",
15
+ "hooks": [
16
+ {
17
+ "type": "command",
18
+ "command": "/Users/ian/project/claude_project/hybrid-search-mcp/.venv/bin/python -m hybrid_search.cli qa-hook 2>/dev/null || true",
19
+ "timeout": 5
20
+ }
21
+ ]
22
+ }
23
+ ],
24
+ "PostToolUse": [
25
+ {
26
+ "matcher": "Edit|Write",
27
+ "hooks": [
28
+ {
29
+ "type": "command",
30
+ "command": "ROOT=$(git rev-parse --show-toplevel 2>/dev/null) && [ -n \"$ROOT\" ] && [ -f \"$ROOT/.hybrid-search/wiki-gaps.txt\" ] && echo 'Wiki gaps — new modules need wiki pages:' && cat \"$ROOT/.hybrid-search/wiki-gaps.txt\"; :"
31
+ }
32
+ ]
33
+ }
34
+ ],
35
+ "SessionStart": [
36
+ {
37
+ "hooks": [
38
+ {
39
+ "type": "command",
40
+ "command": "/Users/ian/project/claude_project/hybrid-search-mcp/.venv/bin/python -m hybrid_search.cli qa-hook 2>/dev/null || true",
41
+ "timeout": 5
42
+ }
43
+ ]
44
+ }
45
+ ],
46
+ "UserPromptSubmit": [
47
+ {
48
+ "hooks": [
49
+ {
50
+ "type": "command",
51
+ "command": "/Users/ian/project/claude_project/hybrid-search-mcp/.venv/bin/python -m hybrid_search.cli qa-hook 2>/dev/null || true",
52
+ "timeout": 10
53
+ }
54
+ ]
55
+ }
56
+ ],
57
+ "Stop": [
58
+ {
59
+ "hooks": [
60
+ {
61
+ "type": "command",
62
+ "command": "/Users/ian/project/claude_project/hybrid-search-mcp/.venv/bin/python -m hybrid_search.cli qa-hook 2>/dev/null || true",
63
+ "timeout": 5
64
+ }
65
+ ]
66
+ }
67
+ ]
68
+ }
69
+ }
@@ -0,0 +1,27 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.11", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+ cache: pip
22
+
23
+ - name: Install
24
+ run: pip install -e ".[dev]"
25
+
26
+ - name: Run tests
27
+ run: python -m pytest tests/ -q
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ .env
9
+ .env.*
10
+ *.lock
11
+ .ruff_cache/
12
+ .pytest_cache/
13
+ .mypy_cache/
14
+
15
+ # Machine-local runtime state — never commit
16
+ .hybrid-search/
17
+ .codex/
18
+
19
+ # PoC embedding cache — derived from conversation content, regenerated on run
20
+ scripts/.poc_cache/
@@ -0,0 +1,5 @@
1
+ <!-- hybrid-search-mcp:codex-routing -->
2
+ ## Hybrid Search Memory
3
+
4
+ - Use `mcp__hybrid-search__hybrid_search` for project memory and code/docs search when context may already exist.
5
+ - Codex hooks inject relevant hybrid-search memory before exploratory prompts and save completed turns after answers.
@@ -0,0 +1,301 @@
1
+ # Changelog
2
+
3
+ All notable changes to hybrid-search-mcp. Format loosely follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
5
+ versions are [SemVer](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## Unreleased
8
+
9
+ ### Added
10
+
11
+ - **Codex memory hooks**. New `codex-hook` entry handles Codex
12
+ `SessionStart`, `UserPromptSubmit`, and `Stop` payloads. Codex receives
13
+ hybrid-search context before exploratory prompts and completed turns are
14
+ saved as qa logs with `trigger: codex_stop_hook` and `client: codex`.
15
+ - **Bounded answer excerpts for Stop-hook memory**. Claude and Codex completed
16
+ turns now persist a sanitized, capped `## Answer excerpt` plus
17
+ `answer_excerpt_chars`, improving memory quality without storing unbounded
18
+ transcripts.
19
+ - **`install-codex-hook` CLI**. Writes Codex hooks to `.codex/hooks.json`
20
+ or `~/.codex/hooks.json`, enables `[features].hooks = true`, and
21
+ registers the MCP server using Codex TOML `[mcp_servers.hybrid-search]`.
22
+ - Shared hook runtime for Claude Code and Codex prompt classification,
23
+ session context, prompt context, and completed-turn recording.
24
+ - Status now reports Codex hook/config presence and warns about
25
+ `AGENTS.override.md` / near-limit `AGENTS.md` project docs.
26
+ - **Memory cards**. New `memory-card create/list/show/grep` commands promote
27
+ qa logs into compact semantic memory under
28
+ `.hybrid-search/memory/cards/`, indexed as `node_type="memory_card"`.
29
+ - **Memory compaction and graph-lite facts**. New `memory compact`,
30
+ `memory procedural review`, and `memory facts export/list` commands create
31
+ cards from qa logs, write reviewed procedural candidates, and export
32
+ lightweight temporal facts to `.hybrid-search/memory/facts.jsonl`.
33
+ - **Router Phase 1 scanner noise filter**. Reindex now skips common content
34
+ binaries/media/archives and oversized Markdown under content roots by
35
+ default, with `[scanner.exclude]` overrides, `reindex --include-content`,
36
+ and a doctor excluded-paths summary.
37
+ - **Router Phase 2 — quality signals**. Hybrid search responses now include
38
+ `top_score`, `score_gap`, confidence bands, weak-result fallback hints, and
39
+ a `recalibrate` CLI for project-specific thresholds.
40
+ - **Router Phase 3 — heuristic prompt router**. User prompt hooks now surface
41
+ a bounded route suggestion for `hybrid_search`, `grep`, or `memory`, backed
42
+ by a hand-labeled router benchmark.
43
+ - **In-flight dirty worktree visibility**. `hybrid_search(..., cwd=...)` now
44
+ overlays tracked uncommitted file changes as ephemeral `[in-flight]` results,
45
+ suppresses deleted dirty paths, and avoids persisting or embedding dirty
46
+ content.
47
+ - `setup --dry-run`: preview CLAUDE.md/AGENTS.md changes without writing.
48
+ - `setup --force`: recover from a corrupted routing block.
49
+
50
+ ### Changed
51
+
52
+ - qa log frontmatter accepts an optional `client` field. Existing records
53
+ without it remain valid.
54
+ - Memory-aware ranking now boosts curated `memory_card` chunks above raw
55
+ `qa_log` chunks for explicit recall queries.
56
+ - Codex hook installation now migrates the deprecated
57
+ `[features].codex_hooks` flag to `[features].hooks`.
58
+ - CLAUDE.md and AGENTS.md routing sections now use versioned sentinel
59
+ markers (`<!-- BEGIN/END hybrid-search-mcp routing v1 -->`). Existing
60
+ installs migrate automatically on the next `setup`. Idempotent —
61
+ re-running `setup` on a current install produces no diff.
62
+ - Routing block now includes a self-justify rule (one-sentence tool
63
+ choice per call) and a weak-confidence fallback contract. G4 manual
64
+ replay (`benchmarks/router_replay_2026-05.md`) showed these rules
65
+ were already being followed via qa_log priming; the durable value is
66
+ pinning the contract in CLAUDE.md so it survives qa_log churn.
67
+
68
+ ## [0.4.0] — 2026-04-23
69
+
70
+ **Memory integrity.** v0.3.0 guaranteed every turn persists; v0.4.0 keeps
71
+ those persisted turns *useful* over time. Three deterministic passes run
72
+ at every reindex — staleness, semantic dedup, archive TTL — so qa_log
73
+ stops being an append-only dumpster and becomes actual memory that
74
+ consolidates.
75
+
76
+ ### Added
77
+
78
+ - **Staleness pruning** (`memory.integrity.detect_stale_qa`). qa_log
79
+ files whose ``## Top results`` paths are *all* absent from the store
80
+ DB are archived (not unlinked). Mirrors the v0.3.0 wiki orphan
81
+ detector.
82
+ - **Semantic dedup** (`memory.integrity.detect_semantic_duplicates`).
83
+ For every pair of qa_log chunks, compares cosine similarity from the
84
+ already-indexed vectors. Pairs at or above threshold
85
+ (default **0.90**) cluster via union-find; the newest member is kept,
86
+ older members are archived. No re-embedding, no LLM cost.
87
+ - **Archive tier**. Every prune (auto-prune, qa-prune, staleness,
88
+ dedup) moves files into ``<project>/.hybrid-search/qa-archive/
89
+ YYYY/MM/*.md`` instead of unlinking. Archive entries older than
90
+ ``archive_ttl_days`` (default **30**) are permanently removed on
91
+ subsequent reindexes — cheap insurance against regret.
92
+ - **`qa-restore` CLI**. Brings an archived entry back into qa/. Accepts
93
+ the stem, hash prefix (≥4 hex chars), or friendly id from
94
+ ``qa-list``. Path-preserving restore.
95
+ - **`integrity` CLI**. Runs the full pass on demand. `--dedup-threshold`
96
+ lets users tune sensitivity without editing config.
97
+ - **`qa-stats` v2**. Surfaces ``active`` / ``archived`` / ``recent
98
+ archive (7d)`` / ``total ever`` counters alongside the existing
99
+ by-type / by-month breakdown. New ``by trigger`` line shows how many
100
+ of the active qa files came from each save path (``mcp_tool``,
101
+ ``stop_hook``, ``user_prompt_submit``).
102
+ - **`[memory.integrity]` config block** — ``enabled`` (default true),
103
+ ``dedup_threshold`` (0.90), ``archive_ttl_days`` (30).
104
+ - **`VectorEngine.get_vector(chunk_id)`** — surfaces the stored HNSW
105
+ vector to callers that need pairwise cosine without going through
106
+ ``search()``. Used by the dedup pass.
107
+ - **Plan doc** `docs/plans/2026-04-23-v0.4.0-memory-integrity.md` with
108
+ architecture, stages, verification gates, and risk register.
109
+ - Tests: 23 new in `test_memory_integrity.py` covering archive /
110
+ staleness / dedup / purge / restore / stats. Full suite:
111
+ **845 passing**.
112
+
113
+ ### Changed
114
+
115
+ - Reindex tail order: `auto_prune` → `wiki_cleanup` → `integrity_pass`
116
+ → `archive purge`. Independent passes; each skips silently when
117
+ applicable sub-state is absent.
118
+ - `_ensure_gitignore_entries` now auto-patches ``.hybrid-search/
119
+ qa-archive/`` so archived qa files never leak into git.
120
+
121
+ ### Verification
122
+
123
+ Ran the full G-gate sweep:
124
+
125
+ - G1 (staleness): unit suite + single-file smoke → archived correctly
126
+ - G2 (dedup): live 3-identical-plants smoke → 1 kept, 2 archived
127
+ - G3 (archive TTL): 45-day-old mtime-forge → purged on next pass
128
+ - G4 (existing tests): 822 → 845 (+23, 100% pass)
129
+ - G5 (new tests): 23 in `test_memory_integrity.py` alone
130
+ - G6 (gitignore): ``.hybrid-search/qa-archive/`` auto-added on setup
131
+ - G_integrity (valuein live): no new stale or dedup pairs on clean
132
+ run — environment already healthy post-v0.3.0 cleanup
133
+
134
+ ### Non-goals (unchanged from plan)
135
+
136
+ - No LLM-based summarisation
137
+ - No cross-project qa consolidation
138
+ - Existing qa_log markdown format stays backward-compatible (additive
139
+ frontmatter only; v0.2.x files still parse cleanly)
140
+
141
+ ## [0.3.0] — 2026-04-23
142
+
143
+ **Deterministic Memory Layer.** v0.2.0 left two leaks: qa_log save only
144
+ fires when Claude chooses the MCP tool (stochastic), and wiki pages
145
+ accumulate orphans as source files disappear from the index
146
+ (gitignore drift, deletions). v0.3.0 closes both with two new hooks and
147
+ automated wiki cleanup — every user–Claude turn persists regardless of
148
+ tool choice, and every reindex purges orphan wiki pages.
149
+
150
+ ### Added
151
+
152
+ - **`Stop` hook** (`hybrid_search.hooks._handle_stop`). Fires at the end
153
+ of every Claude turn; parses the transcript JSONL to find the last
154
+ user prompt + assistant activity, writes a qa_log entry tagged
155
+ ``trigger: stop_hook``. Respects ``stop_hook_active`` to avoid
156
+ continuation loops. Dedups against recent MCP-tool saves (5-second
157
+ window + query hash match) so turns that DID call
158
+ ``hybrid_search`` aren't double-persisted.
159
+ - **`UserPromptSubmit` hook** (`_handle_user_prompt_submit`). Fires when
160
+ the user submits a prompt; classifies as exploratory via KO/EN
161
+ keyword heuristics (`어떤`/`어떻게`/`구조`/`how`/`explain`/...) plus
162
+ memory-intent markers (`지난번`/`previously`/...) that bypass the
163
+ length gate. Exploratory prompts trigger an on-the-fly
164
+ ``hybrid_search`` call; top-10 results are injected as
165
+ ``hookSpecificOutput.additionalContext`` and saved to qa_log with
166
+ ``trigger: user_prompt_submit``. Slash commands, bash pass-through,
167
+ `@file` references, and short single-token prompts short-circuit
168
+ before any search.
169
+ - **Orphan wiki auto-cleanup** (`hybrid_search.wiki_cleanup`). At the
170
+ end of every reindex, compares each wiki page's ``## Files`` refs
171
+ against the store DB's ``relative_path`` set; pages whose references
172
+ are *all* absent from the DB are deleted. Protects against gitignore
173
+ drift (files excluded from the index but still on disk) and actual
174
+ file deletion. Available as a standalone CLI via
175
+ ``hybrid-search-mcp wiki-cleanup [--dry-run] [--verbose]``.
176
+ - **qa_log format v2**: optional frontmatter fields ``trigger``,
177
+ ``tools_used``, ``answer_chars``. Backward-compatible — v0.2.x
178
+ records (without these fields) still parse cleanly.
179
+ - **Stronger `CLAUDE.md` routing section**: imperative wording
180
+ ("반드시 이 순서로", "예외 없이") plus explicit
181
+ ``mcp__hybrid-search__hybrid_search`` tool name and trigger-word
182
+ tables per question category. Replaces the descriptive v0.2.x
183
+ "의도 기반 라우팅" section on re-setup.
184
+ - **`install-memory-hook` upgrade**: now installs all four hook types
185
+ (PreToolUse, SessionStart, UserPromptSubmit, Stop). Existing
186
+ installs with stale paths are refreshed in place. Idempotent.
187
+ - **`scripts/wiki_bloat_audit.py`** gains a `--delete` flag with a
188
+ DB-based orphan detector (previously disk-only, which undercounted
189
+ gitignore-drift zombies by an order of magnitude).
190
+ - **Plan doc** at `docs/plans/v0.3.0-deterministic-memory.md` with
191
+ goals, design, stages, verification checklist, risk register.
192
+ - Tests: 32 new (`test_memory_hook.py` +TestStopHook +TestUserPromptSubmitHook
193
+ +TestExploratoryClassifier, `test_wiki_orphan_cleanup.py`).
194
+ Full suite: **822 passing**.
195
+
196
+ ### Changed
197
+
198
+ - `qa_log.record()` accepts a ``trigger`` argument (default
199
+ ``"mcp_tool"`` preserves prior behaviour). Adds ``record_turn()``
200
+ for non-MCP saves.
201
+ - `install_memory_hook()` returns ``{added, updated, path, status}``
202
+ — ``updated`` counts stale-path refreshes that were rewritten in
203
+ place. CLI output distinguishes installed vs refreshed blocks.
204
+
205
+ ### Fixed
206
+
207
+ - **valuein_homepage cleanup**: 765 orphan wiki pages removed
208
+ (2,584 → 1,819 pages, ≈30% reduction). Almost all were
209
+ ``mindvault-out/*`` or ``docs/valueinmath_docs/학습/*`` pages that
210
+ had been excluded from the index by `.gitignore` additions but were
211
+ never pruned.
212
+ - Stop hook's transcript parser skips local-command stdout,
213
+ command-message envelopes, and system-reminder blocks — only
214
+ genuine user prompts survive the filter.
215
+
216
+ ### Notes
217
+
218
+ - The bench (`benchmarks/run_compounding_bench.py`) drives the
219
+ orchestrator directly, so it does *not* exercise the v0.3.0
220
+ Stop / UserPromptSubmit guarantees (those only fire inside Claude
221
+ Code). Re-run numbers post-cleanup show Track A identity memory
222
+ surface unchanged at 80 %; Track B paraphrase dropped from 65 % to
223
+ 50 % in this environment, attributable to the 30 % fewer wiki
224
+ chunks now in the index. The guaranteed-save property is verified
225
+ by unit tests (``TestStopHook`` suite) rather than the compounding
226
+ bench.
227
+ - Non-goals preserved: no MCP tools added; existing qa_log files
228
+ remain readable; module_synth page-generation algorithm untouched.
229
+
230
+ ## [0.2.0] — 2026-04-22
231
+
232
+ **Memory Layer, evidenced.** v0.1 introduced the qa_log compounding loop
233
+ but made no measurable claim. v0.2 closes that gap with a benchmark, disk
234
+ retention, and automatic memory consultation hooks — the three pieces that
235
+ turn "it works on my machine" into a shippable product.
236
+
237
+ ### Added
238
+
239
+ - **Compounding benchmark** (`benchmarks/run_compounding_bench.py`,
240
+ `benchmarks/compounding_pairs.json`). LongMemEval / LoCoMo-inspired
241
+ session-separated Q1a → Q1b methodology with leakage split. Two tracks:
242
+ identity re-query (upper bound) and paraphrased follow-up (realistic
243
+ case). Reports memory surface rate, answer-found rate, gold recall@10
244
+ regression guard, with cold/warm deltas per category. Safe to run on
245
+ a live project — the script backs up and restores `.hybrid-search/qa/`
246
+ around the experiment.
247
+ - First run on valuein_homepage (20 pairs, 1,307 files):
248
+ - Identity: answer_found **80% → 95%** (+15pp), memory surface
249
+ **0% → 80%** (+80pp), gold recall@10 flat within noise (−1.7pp).
250
+ - Paraphrase: answer_found **75% → 95%** (+20pp), memory surface
251
+ **0% → 65%** (+65pp).
252
+ - Non-leaky subset (15 pairs): answer_found **73% → 100%**.
253
+ - **Auto-prune on reindex** (`[memory]` config section, default on).
254
+ journald-style two-ceiling retention (`retention_days=90`,
255
+ `max_files=2000`). First activation is a dry-run — the user confirms
256
+ via `qa-prune --confirm-first-run` before the policy actually deletes
257
+ anything. Opt-out via `auto_prune=false` in `config.toml`.
258
+ - New reader primitives: `reader.select_over_count`,
259
+ `reader.prune_keep_latest`, `reader.auto_prune`.
260
+ - **PreToolUse + SessionStart memory hook** (`hybrid-search qa-hook`,
261
+ `hybrid-search install-memory-hook`). Matches Graphify's pattern: a
262
+ one-time SessionStart summary + per-Grep/Read contextual nudges, both
263
+ returning the v2.1.9 `hookSpecificOutput.additionalContext` JSON so
264
+ Claude sees the hint in-context before running the tool. Hooks are
265
+ silent when they have nothing to say (noise patterns, no matches),
266
+ capped at 800 chars per injection. `install-memory-hook` merges into
267
+ `.claude/settings.local.json` non-destructively — existing hooks are
268
+ preserved, re-running is idempotent.
269
+ - **`MemoryConfig`** in `hybrid_search.config` — `auto_prune`,
270
+ `retention_days`, `max_files`, `require_first_run_confirm`.
271
+ - Default `config.toml` template now includes a `[memory]` block with
272
+ inline documentation.
273
+ - Tests: 37 new (`test_memory_hook.py`, `test_qa_reader::TestPruneKeepLatest`,
274
+ `::TestAutoPrune`). Full suite: **783 passing**.
275
+
276
+ ### Changed
277
+
278
+ - `README.md` — hero claim ("search quality compounds with usage") now
279
+ cites measured numbers instead of asserting. New sections:
280
+ "Compounding benchmark (2026-04-22)", "Retention — Memory doesn't
281
+ balloon your disk", "Automatic memory consultation — PreToolUse +
282
+ SessionStart hooks". Package description in `pyproject.toml` updated
283
+ to lead with "Memory Layer MCP for Claude Code".
284
+ - `cmd_reindex` gains a final-step call to `_run_auto_prune` (no-op when
285
+ `[memory].auto_prune = false` or the qa dir is absent).
286
+
287
+ ### Notes
288
+
289
+ - No breaking changes. Existing `.hybrid-search/qa/` directories are
290
+ untouched on first reindex (dry-run gate); users must opt in once per
291
+ project.
292
+ - Paraphrase track's non-leaky subset achieves 100% answer_found at the
293
+ cost of a modest top-1 redistribution (gold code/doc sometimes drops
294
+ one rank when a qa_log chunk surfaces). This is the expected trade-off
295
+ for memory: the user gets both signals.
296
+
297
+ ## [0.1.0] — 2026-04-21
298
+
299
+ Initial Memory Layer release. `qa_log` persistence default-on, 30-day
300
+ half-life decay, memory-intent boost (지난번에 / previously), secret
301
+ filter, per-project scoping. Details in `HANDOFF.md`.
@@ -0,0 +1,46 @@
1
+ # Hybrid Search MCP
2
+
3
+ BM25 + Vector 하이브리드 검색 MCP 서버.
4
+
5
+ ## 실행 환경
6
+
7
+ ```bash
8
+ source .venv/bin/activate
9
+ python -m pytest tests/ -x -q
10
+ ```
11
+
12
+ <!-- BEGIN hybrid-search-mcp routing v1 -->
13
+ ## 검색 전략 — 반드시 이 순서로
14
+
15
+ 이 프로젝트는 `hybrid-search-mcp` Memory Layer가 설치돼 있다. **아래 규칙을 예외 없이 지킬 것.**
16
+
17
+ | 질문 유형 | 신호 | **반드시 먼저 호출** | 보충 |
18
+ |---|---|---|---|
19
+ | **기능 탐색** | "어떤 기능", "관련 기능", "어떻게 구성", "흐름", "설명해줘", "정리해줘", "아키텍처" | `mcp__hybrid-search__hybrid_search` | Grep, Read |
20
+ | **설계/맥락** | "왜 이렇게", "배경", "이유", "결정", "히스토리", "지난번" | `mcp__hybrid-search__hybrid_search` | Wiki |
21
+ | **스키마/DB** | "테이블", "마이그레이션", "DDL", "스키마 변화" | `mcp__hybrid-search__hybrid_search` (file_pattern `*.sql`) | Grep |
22
+ | **구조/관계** | "전체 그림", "누가 호출", "의존" | Wiki (`.hybrid-search/wiki/index.md`) | `mcp__hybrid-search__hybrid_search` |
23
+ | **정밀 조회** | 정확한 심볼명 / 파일명 / 에러 문자열 | Grep | Read |
24
+
25
+ **운영 규칙**:
26
+ - **탐색형 질문에 Grep 먼저 호출 금지** — 반드시 `mcp__hybrid-search__hybrid_search` 먼저.
27
+ - **쿼리는 사용자의 자연어 문장을 그대로** 쓸 것 — 키워드 뭉치로 재작성 금지.
28
+ (예: "우리 환불 기능에 대해 알려줘" ⭕ / "환불 퇴원 refund 워크플로우 정산" ❌)
29
+ 자연어 문장이 벡터 매칭 품질이 더 좋고, 분류기가 가중치를 자동 조정한다.
30
+ - 1차에서 답이 부족해도 도구를 **바꾸지 말고 같은 레인에서 보충** (hybrid→wiki MCP 레인, grep→read 텍스트 레인).
31
+ - Wiki는 `.hybrid-search/wiki/index.md`에서 시작, `[[링크]]` 있으면 따라갈 것.
32
+
33
+ **자동 동작 (수동 개입 불필요)**:
34
+ - 질문 시작 시 관련 과거 Q&A 자동 컨텍스트 주입 (UserPromptSubmit)
35
+ - 세션 시작 시 최근 Q&A 요약 주입 (SessionStart)
36
+ - 답변 종료 시 `.hybrid-search/qa/`에 자동 저장 (Stop)
37
+ - `git commit` 후 변경 파일만 재인덱싱 + 좀비 wiki 자동 삭제
38
+
39
+ **자기 정당화 (Self-justify)**:
40
+ - 모든 검색 호출 직전, **한 문장으로 어떤 도구를 골랐고 왜인지** 말할 것.
41
+ - 예: "탐색형 질문이라 `mcp__hybrid-search__hybrid_search` 먼저 호출합니다."
42
+
43
+ **Confidence 계약 (weak → fallback)**:
44
+ - `hybrid_search` 응답의 `confidence: weak`이면 답하기 전에 `fallback_hint`에 적힌 대체 도구로 한 번 더 시도할 것.
45
+ - `strong`/`mixed`면 그대로 진행.
46
+ <!-- END hybrid-search-mcp routing v1 -->