claude-memory-layer 1.0.31 → 1.0.33

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 (343) hide show
  1. package/README.md +9 -2
  2. package/dist/cli/index.js +1110 -72
  3. package/dist/cli/index.js.map +4 -4
  4. package/dist/core/index.js +414 -25
  5. package/dist/core/index.js.map +2 -2
  6. package/dist/hooks/post-tool-use.js +416 -27
  7. package/dist/hooks/post-tool-use.js.map +2 -2
  8. package/dist/hooks/semantic-daemon.js +416 -27
  9. package/dist/hooks/semantic-daemon.js.map +2 -2
  10. package/dist/hooks/session-end.js +416 -27
  11. package/dist/hooks/session-end.js.map +2 -2
  12. package/dist/hooks/session-start.js +416 -27
  13. package/dist/hooks/session-start.js.map +2 -2
  14. package/dist/hooks/stop.js +416 -27
  15. package/dist/hooks/stop.js.map +2 -2
  16. package/dist/hooks/user-prompt-submit.js +504 -34
  17. package/dist/hooks/user-prompt-submit.js.map +2 -2
  18. package/dist/index.js +416 -27
  19. package/dist/index.js.map +2 -2
  20. package/dist/mcp/index.js +407 -32
  21. package/dist/mcp/index.js.map +2 -2
  22. package/dist/server/api/index.js +850 -44
  23. package/dist/server/api/index.js.map +3 -3
  24. package/dist/server/index.js +1073 -64
  25. package/dist/server/index.js.map +3 -3
  26. package/dist/services/memory-service.js +416 -27
  27. package/dist/services/memory-service.js.map +2 -2
  28. package/dist/ui/assets/js/bootstrap.js +2 -0
  29. package/dist/ui/assets/js/overview.js +166 -3
  30. package/dist/ui/assets/js/state.js +3 -0
  31. package/dist/ui/index.html +20 -0
  32. package/dist/ui/style.css +193 -0
  33. package/package.json +15 -2
  34. package/scripts/postinstall-embedding-backend.cjs +16 -12
  35. package/AGENTS.md +0 -71
  36. package/CLAUDE.md +0 -30
  37. package/HANDOFF.md +0 -92
  38. package/Memo.txt +0 -558
  39. package/benchmarks/replay/anonymized-real-sessions.json +0 -48
  40. package/config/kpi-thresholds.json +0 -7
  41. package/context.md +0 -636
  42. package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +0 -627
  43. package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +0 -440
  44. package/docs/MCP_MEMORY_SERVICE_COMPARATIVE_REVIEW.md +0 -271
  45. package/docs/MEMORY_USEFULNESS_AUDIT.md +0 -371
  46. package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +0 -80
  47. package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +0 -333
  48. package/docs/MEMU_ADOPTION.md +0 -40
  49. package/docs/OPERATIONS.md +0 -18
  50. package/docs/PRODUCT_VALIDATION_MATRIX.md +0 -82
  51. package/docs/PROJECT_STRUCTURE_ANALYSIS.md +0 -421
  52. package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +0 -501
  53. package/docs/REFACTORING_PLAN_THIN_CORE.md +0 -414
  54. package/docs/REFERENCE_PROJECT_ANALYSES.md +0 -25
  55. package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +0 -452
  56. package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +0 -446
  57. package/docs/architecture/comparison-index.md +0 -47
  58. package/docs/reports/codex-real-data-validation-20260505T040447Z.md +0 -46
  59. package/plan.md +0 -1642
  60. package/scripts/build.ts +0 -159
  61. package/scripts/bump-patch-version.sh +0 -18
  62. package/scripts/delete-unknown-projects.js +0 -154
  63. package/scripts/fix-sync-gap.js +0 -32
  64. package/scripts/generate-session-qrels.ts +0 -126
  65. package/scripts/heartbeat-memory-orchestrator.sh +0 -28
  66. package/scripts/replay-retrieval-benchmark.ts +0 -69
  67. package/scripts/report-sync-gap.js +0 -26
  68. package/scripts/review-queue-auto-resolve.js +0 -21
  69. package/scripts/sync-gap-auto-heal.sh +0 -17
  70. package/spec.md +0 -624
  71. package/specs/20260207-dashboard-upgrade/context.md +0 -38
  72. package/specs/20260207-dashboard-upgrade/spec.md +0 -96
  73. package/specs/citations-system/context.md +0 -243
  74. package/specs/citations-system/plan.md +0 -495
  75. package/specs/citations-system/spec.md +0 -371
  76. package/specs/endless-mode/context.md +0 -305
  77. package/specs/endless-mode/plan.md +0 -620
  78. package/specs/endless-mode/spec.md +0 -455
  79. package/specs/entity-edge-model/context.md +0 -401
  80. package/specs/entity-edge-model/plan.md +0 -459
  81. package/specs/entity-edge-model/spec.md +0 -391
  82. package/specs/evidence-aligner-v2/context.md +0 -401
  83. package/specs/evidence-aligner-v2/plan.md +0 -303
  84. package/specs/evidence-aligner-v2/spec.md +0 -312
  85. package/specs/mcp-desktop-integration/context.md +0 -278
  86. package/specs/mcp-desktop-integration/plan.md +0 -550
  87. package/specs/mcp-desktop-integration/spec.md +0 -494
  88. package/specs/memory-utilization-improvements/context.md +0 -145
  89. package/specs/memory-utilization-improvements/plan.md +0 -361
  90. package/specs/memory-utilization-improvements/spec.md +0 -361
  91. package/specs/post-tool-use-hook/context.md +0 -319
  92. package/specs/post-tool-use-hook/plan.md +0 -469
  93. package/specs/post-tool-use-hook/spec.md +0 -364
  94. package/specs/private-tags/context.md +0 -288
  95. package/specs/private-tags/plan.md +0 -412
  96. package/specs/private-tags/spec.md +0 -345
  97. package/specs/progressive-disclosure/context.md +0 -346
  98. package/specs/progressive-disclosure/plan.md +0 -663
  99. package/specs/progressive-disclosure/spec.md +0 -415
  100. package/specs/selective-tool-observation/context.md +0 -100
  101. package/specs/selective-tool-observation/plan.md +0 -158
  102. package/specs/selective-tool-observation/spec.md +0 -127
  103. package/specs/task-entity-system/context.md +0 -297
  104. package/specs/task-entity-system/plan.md +0 -301
  105. package/specs/task-entity-system/spec.md +0 -314
  106. package/specs/thin-core-refactor/context.md +0 -275
  107. package/specs/thin-core-refactor/plan.md +0 -536
  108. package/specs/thin-core-refactor/spec.md +0 -465
  109. package/specs/vector-outbox-v2/context.md +0 -470
  110. package/specs/vector-outbox-v2/plan.md +0 -562
  111. package/specs/vector-outbox-v2/spec.md +0 -466
  112. package/specs/web-viewer-ui/context.md +0 -384
  113. package/specs/web-viewer-ui/plan.md +0 -797
  114. package/specs/web-viewer-ui/spec.md +0 -516
  115. package/src/adapters/claude/capture/index.ts +0 -3
  116. package/src/adapters/claude/context/index.ts +0 -3
  117. package/src/adapters/claude/hooks/index.ts +0 -21
  118. package/src/adapters/claude/hooks/post-tool-use.ts +0 -239
  119. package/src/adapters/claude/hooks/prompt-injection-policy.ts +0 -104
  120. package/src/adapters/claude/hooks/semantic-daemon-client.ts +0 -209
  121. package/src/adapters/claude/hooks/semantic-daemon.ts +0 -283
  122. package/src/adapters/claude/hooks/session-end.ts +0 -59
  123. package/src/adapters/claude/hooks/session-start.ts +0 -73
  124. package/src/adapters/claude/hooks/stop.ts +0 -128
  125. package/src/adapters/claude/hooks/user-prompt-submit.ts +0 -361
  126. package/src/adapters/claude/index.ts +0 -4
  127. package/src/adapters/claude/transcript/index.ts +0 -4
  128. package/src/adapters/claude/transcript/transcript-reader.ts +0 -57
  129. package/src/adapters/claude/transcript/turn-reconstructor.ts +0 -65
  130. package/src/apps/cli/claude-settings-hooks.ts +0 -138
  131. package/src/apps/cli/codex-import-runner.ts +0 -125
  132. package/src/apps/cli/codex-validation-output.ts +0 -95
  133. package/src/apps/cli/hermes-import-runner.ts +0 -130
  134. package/src/apps/cli/hermes-validation-output.ts +0 -91
  135. package/src/apps/cli/index.ts +0 -1735
  136. package/src/apps/cli/mcp-install.ts +0 -106
  137. package/src/apps/cli/retrieval-disclosure-output.ts +0 -196
  138. package/src/apps/dashboard/assets/js/bootstrap.js +0 -244
  139. package/src/apps/dashboard/assets/js/chat.js +0 -373
  140. package/src/apps/dashboard/assets/js/disclosure.js +0 -232
  141. package/src/apps/dashboard/assets/js/modals.js +0 -298
  142. package/src/apps/dashboard/assets/js/overview.js +0 -655
  143. package/src/apps/dashboard/assets/js/state.js +0 -72
  144. package/src/apps/dashboard/assets/js/views.js +0 -468
  145. package/src/apps/dashboard/index.html +0 -543
  146. package/src/apps/dashboard/index.ts +0 -3
  147. package/src/apps/dashboard/style.css +0 -1750
  148. package/src/apps/index.ts +0 -5
  149. package/src/apps/server/api/chat.ts +0 -244
  150. package/src/apps/server/api/citations.ts +0 -105
  151. package/src/apps/server/api/events.ts +0 -137
  152. package/src/apps/server/api/health.ts +0 -53
  153. package/src/apps/server/api/index.ts +0 -26
  154. package/src/apps/server/api/projects.ts +0 -74
  155. package/src/apps/server/api/search.ts +0 -184
  156. package/src/apps/server/api/sessions.ts +0 -115
  157. package/src/apps/server/api/stats.ts +0 -723
  158. package/src/apps/server/api/turns.ts +0 -143
  159. package/src/apps/server/api/utils.ts +0 -65
  160. package/src/apps/server/index.ts +0 -111
  161. package/src/cli/index.ts +0 -3
  162. package/src/cli/retrieval-disclosure-output.ts +0 -2
  163. package/src/compat/index.ts +0 -5
  164. package/src/core/canonical-key.ts +0 -186
  165. package/src/core/citation-generator.ts +0 -63
  166. package/src/core/consolidated-store.ts +0 -356
  167. package/src/core/consolidation-worker.ts +0 -493
  168. package/src/core/context-formatter.ts +0 -276
  169. package/src/core/continuity-manager.ts +0 -341
  170. package/src/core/db-wrapper.ts +0 -64
  171. package/src/core/derive/fact-deriver.ts +0 -170
  172. package/src/core/derive/index.ts +0 -2
  173. package/src/core/derive/summary-deriver.ts +0 -76
  174. package/src/core/edge-repo.ts +0 -333
  175. package/src/core/embedder.ts +0 -4
  176. package/src/core/engine/embedding-maintenance-service.ts +0 -187
  177. package/src/core/engine/endless-memory-services.ts +0 -4
  178. package/src/core/engine/index.ts +0 -19
  179. package/src/core/engine/memory-engine-services.ts +0 -170
  180. package/src/core/engine/memory-ingest-service.ts +0 -317
  181. package/src/core/engine/memory-query-service.ts +0 -173
  182. package/src/core/engine/memory-runtime-service.ts +0 -162
  183. package/src/core/engine/memory-service-composition.ts +0 -231
  184. package/src/core/engine/retrieval-analytics-service.ts +0 -181
  185. package/src/core/engine/retrieval-disclosure-service.ts +0 -420
  186. package/src/core/engine/retrieval-orchestrator.ts +0 -377
  187. package/src/core/engine/retrieval-services.ts +0 -176
  188. package/src/core/engine/shared-memory-services.ts +0 -4
  189. package/src/core/entity-repo.ts +0 -349
  190. package/src/core/event-store.ts +0 -779
  191. package/src/core/evidence-aligner.ts +0 -635
  192. package/src/core/external-market-context.ts +0 -582
  193. package/src/core/graduation-worker.ts +0 -171
  194. package/src/core/graduation.ts +0 -377
  195. package/src/core/index.ts +0 -64
  196. package/src/core/ingest-interceptor.ts +0 -80
  197. package/src/core/markdown-mirror.ts +0 -70
  198. package/src/core/matcher.ts +0 -208
  199. package/src/core/md-mirror.ts +0 -92
  200. package/src/core/metadata-extractor.ts +0 -203
  201. package/src/core/model/memory-fact.ts +0 -30
  202. package/src/core/model/memory-rule.ts +0 -14
  203. package/src/core/model/memory-summary.ts +0 -21
  204. package/src/core/model/raw-event.ts +0 -28
  205. package/src/core/model/retrieval-result.ts +0 -35
  206. package/src/core/mongo-sync-config.ts +0 -165
  207. package/src/core/mongo-sync-worker.ts +0 -381
  208. package/src/core/privacy/filter.ts +0 -190
  209. package/src/core/privacy/index.ts +0 -20
  210. package/src/core/privacy/tag-parser.ts +0 -145
  211. package/src/core/product-validation-matrix.ts +0 -314
  212. package/src/core/progressive-retriever.ts +0 -414
  213. package/src/core/registry/project-path.ts +0 -54
  214. package/src/core/registry/session-registry.ts +0 -69
  215. package/src/core/replay-evaluator.ts +0 -625
  216. package/src/core/retrieval-benchmark.ts +0 -117
  217. package/src/core/retrieval-quality.ts +0 -109
  218. package/src/core/retriever.ts +0 -800
  219. package/src/core/session-qrels.ts +0 -360
  220. package/src/core/shared-event-store.ts +0 -114
  221. package/src/core/shared-promoter.ts +0 -249
  222. package/src/core/shared-store.ts +0 -289
  223. package/src/core/shared-vector-store.ts +0 -203
  224. package/src/core/sqlite-event-store.ts +0 -1846
  225. package/src/core/sqlite-wrapper.ts +0 -116
  226. package/src/core/sync-worker.ts +0 -228
  227. package/src/core/tag-taxonomy.ts +0 -51
  228. package/src/core/task/blocker-resolver.ts +0 -333
  229. package/src/core/task/index.ts +0 -9
  230. package/src/core/task/task-matcher.ts +0 -240
  231. package/src/core/task/task-projector.ts +0 -358
  232. package/src/core/task/task-resolver.ts +0 -421
  233. package/src/core/turn-state.ts +0 -207
  234. package/src/core/types.ts +0 -952
  235. package/src/core/vector-outbox.ts +0 -299
  236. package/src/core/vector-store.ts +0 -231
  237. package/src/core/vector-worker.ts +0 -521
  238. package/src/core/working-set-store.ts +0 -257
  239. package/src/extensions/endless-memory/endless-memory-services.ts +0 -350
  240. package/src/extensions/endless-memory/index.ts +0 -1
  241. package/src/extensions/index.ts +0 -5
  242. package/src/extensions/mcp/handlers.ts +0 -960
  243. package/src/extensions/mcp/index.ts +0 -48
  244. package/src/extensions/mcp/tools.ts +0 -252
  245. package/src/extensions/shared-memory/index.ts +0 -1
  246. package/src/extensions/shared-memory/shared-memory-services.ts +0 -211
  247. package/src/extensions/vector/embedder.ts +0 -234
  248. package/src/extensions/vector/index.ts +0 -1
  249. package/src/hooks/post-tool-use.ts +0 -9
  250. package/src/hooks/semantic-daemon-client.ts +0 -1
  251. package/src/hooks/semantic-daemon.ts +0 -11
  252. package/src/hooks/session-end.ts +0 -9
  253. package/src/hooks/session-start.ts +0 -9
  254. package/src/hooks/stop.ts +0 -9
  255. package/src/hooks/user-prompt-submit.ts +0 -9
  256. package/src/index.ts +0 -13
  257. package/src/mcp/handlers.ts +0 -2
  258. package/src/mcp/index.ts +0 -4
  259. package/src/mcp/tools.ts +0 -2
  260. package/src/server/api/chat.ts +0 -2
  261. package/src/server/api/citations.ts +0 -2
  262. package/src/server/api/events.ts +0 -2
  263. package/src/server/api/health.ts +0 -2
  264. package/src/server/api/index.ts +0 -2
  265. package/src/server/api/projects.ts +0 -2
  266. package/src/server/api/search.ts +0 -2
  267. package/src/server/api/sessions.ts +0 -2
  268. package/src/server/api/stats.ts +0 -2
  269. package/src/server/api/turns.ts +0 -2
  270. package/src/server/api/utils.ts +0 -2
  271. package/src/server/index.ts +0 -2
  272. package/src/services/bootstrap-organizer.ts +0 -463
  273. package/src/services/codex-session-history-importer.ts +0 -966
  274. package/src/services/hermes-session-history-importer.ts +0 -733
  275. package/src/services/memory-service-config.ts +0 -36
  276. package/src/services/memory-service-registry.ts +0 -150
  277. package/src/services/memory-service.ts +0 -688
  278. package/src/services/session-history-importer.ts +0 -629
  279. package/tests/README.md +0 -23
  280. package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +0 -54
  281. package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +0 -98
  282. package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +0 -99
  283. package/tests/apps/app-layer-boundary.test.ts +0 -48
  284. package/tests/apps/claude-settings-hooks.test.ts +0 -107
  285. package/tests/apps/cli-disclosure-output.test.ts +0 -212
  286. package/tests/apps/codex-import-runner.test.ts +0 -99
  287. package/tests/apps/codex-validation-output.test.ts +0 -100
  288. package/tests/apps/hermes-import-runner.test.ts +0 -99
  289. package/tests/apps/mcp-install-command.test.ts +0 -59
  290. package/tests/apps/package-build-entrypoints.test.ts +0 -30
  291. package/tests/apps/postinstall-embedding-backend.test.ts +0 -185
  292. package/tests/apps/search-api-disclosure.test.ts +0 -162
  293. package/tests/apps/stats-api-lightweight.test.ts +0 -67
  294. package/tests/apps/ui-disclosure-output.test.ts +0 -140
  295. package/tests/core/bootstrap-organizer.test.ts +0 -111
  296. package/tests/core/canonical-key.test.ts +0 -101
  297. package/tests/core/codex-session-history-importer-validation.test.ts +0 -185
  298. package/tests/core/consolidation-worker.test.ts +0 -75
  299. package/tests/core/embedding-maintenance-service.test.ts +0 -282
  300. package/tests/core/evidence-aligner.test.ts +0 -152
  301. package/tests/core/external-market-context.test.ts +0 -209
  302. package/tests/core/fact-deriver.test.ts +0 -79
  303. package/tests/core/hermes-session-history-importer-validation.test.ts +0 -609
  304. package/tests/core/ingest-interceptor.test.ts +0 -38
  305. package/tests/core/markdown-mirror.test.ts +0 -85
  306. package/tests/core/matcher.test.ts +0 -112
  307. package/tests/core/md-mirror.test.ts +0 -50
  308. package/tests/core/memory-engine-services.test.ts +0 -240
  309. package/tests/core/memory-ingest-service.test.ts +0 -296
  310. package/tests/core/memory-query-service.test.ts +0 -129
  311. package/tests/core/memory-runtime-service.test.ts +0 -201
  312. package/tests/core/memory-service-composition.test.ts +0 -192
  313. package/tests/core/memory-service-config.test.ts +0 -41
  314. package/tests/core/memory-service-facade.test.ts +0 -30
  315. package/tests/core/memory-service-registry.test.ts +0 -206
  316. package/tests/core/product-validation-matrix.test.ts +0 -61
  317. package/tests/core/project-registry.test.ts +0 -78
  318. package/tests/core/replay-evaluator.test.ts +0 -181
  319. package/tests/core/retrieval-analytics-service.test.ts +0 -210
  320. package/tests/core/retrieval-benchmark.test.ts +0 -93
  321. package/tests/core/retrieval-disclosure-service.test.ts +0 -264
  322. package/tests/core/retrieval-orchestrator.test.ts +0 -403
  323. package/tests/core/retrieval-quality.test.ts +0 -31
  324. package/tests/core/retrieval-services.test.ts +0 -185
  325. package/tests/core/retriever-fallback-chain.test.ts +0 -223
  326. package/tests/core/retriever-strategy-scope.test.ts +0 -164
  327. package/tests/core/retriever.memu-adoption.test.ts +0 -122
  328. package/tests/core/session-history-importer-filter.test.ts +0 -78
  329. package/tests/core/session-qrels.test.ts +0 -250
  330. package/tests/core/sqlite-event-store-replication.test.ts +0 -127
  331. package/tests/core/summary-deriver.test.ts +0 -66
  332. package/tests/extensions/embedder-warning-suppression.test.ts +0 -84
  333. package/tests/extensions/endless-memory-extension-boundary.test.ts +0 -17
  334. package/tests/extensions/endless-memory-services.test.ts +0 -325
  335. package/tests/extensions/mcp-context-tools.test.ts +0 -905
  336. package/tests/extensions/mcp-extension-boundary.test.ts +0 -21
  337. package/tests/extensions/mcp-package-build.test.ts +0 -22
  338. package/tests/extensions/mcp-project-aware-tools.test.ts +0 -102
  339. package/tests/extensions/shared-memory-extension-boundary.test.ts +0 -24
  340. package/tests/extensions/shared-memory-services.test.ts +0 -309
  341. package/tests/extensions/vector-extension-boundary.test.ts +0 -21
  342. package/tsconfig.json +0 -24
  343. package/vitest.config.ts +0 -15
package/dist/index.js CHANGED
@@ -1965,10 +1965,15 @@ function sqliteTransaction(db, fn) {
1965
1965
  function toDateFromSQLite(value) {
1966
1966
  if (value instanceof Date)
1967
1967
  return value;
1968
- if (typeof value === "string")
1969
- return new Date(value);
1970
1968
  if (typeof value === "number")
1971
1969
  return new Date(value);
1970
+ if (typeof value === "string") {
1971
+ const trimmed = value.trim();
1972
+ if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(trimmed)) {
1973
+ return /* @__PURE__ */ new Date(trimmed.replace(" ", "T") + "Z");
1974
+ }
1975
+ return new Date(trimmed);
1976
+ }
1972
1977
  return new Date(String(value));
1973
1978
  }
1974
1979
  function toSQLiteTimestamp(date) {
@@ -2034,6 +2039,13 @@ var MarkdownMirror2 = class {
2034
2039
  };
2035
2040
 
2036
2041
  // src/core/sqlite-event-store.ts
2042
+ function normalizeQueryRewriteKind(value) {
2043
+ const normalized = (value || "").trim().toLowerCase();
2044
+ if (normalized === "follow-up-context" || normalized === "intent-rewrite")
2045
+ return normalized;
2046
+ return "none";
2047
+ }
2048
+ var REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;
2037
2049
  var SQLiteEventStore = class {
2038
2050
  db;
2039
2051
  initialized = false;
@@ -2294,6 +2306,8 @@ var SQLiteEventStore = class {
2294
2306
  session_id TEXT,
2295
2307
  project_hash TEXT,
2296
2308
  query_text TEXT NOT NULL,
2309
+ raw_query_text TEXT,
2310
+ query_rewrite_kind TEXT,
2297
2311
  strategy TEXT,
2298
2312
  candidate_event_ids TEXT,
2299
2313
  selected_event_ids TEXT,
@@ -2335,6 +2349,8 @@ var SQLiteEventStore = class {
2335
2349
  CREATE INDEX IF NOT EXISTS idx_helpfulness_event ON memory_helpfulness(event_id);
2336
2350
  CREATE INDEX IF NOT EXISTS idx_helpfulness_session ON memory_helpfulness(session_id);
2337
2351
  CREATE INDEX IF NOT EXISTS idx_helpfulness_score ON memory_helpfulness(helpfulness_score DESC);
2352
+ CREATE INDEX IF NOT EXISTS idx_helpfulness_created_at ON memory_helpfulness(created_at);
2353
+ CREATE INDEX IF NOT EXISTS idx_helpfulness_measured_at ON memory_helpfulness(measured_at);
2338
2354
  CREATE INDEX IF NOT EXISTS idx_retrieval_traces_created_at ON retrieval_traces(created_at DESC);
2339
2355
  CREATE INDEX IF NOT EXISTS idx_retrieval_traces_project_hash ON retrieval_traces(project_hash);
2340
2356
  CREATE INDEX IF NOT EXISTS idx_retrieval_traces_session_id ON retrieval_traces(session_id);
@@ -2368,6 +2384,18 @@ var SQLiteEventStore = class {
2368
2384
  sqliteExec(this.db, `ALTER TABLE retrieval_traces ADD COLUMN candidate_details_json TEXT;`);
2369
2385
  } catch {
2370
2386
  }
2387
+ try {
2388
+ sqliteExec(this.db, `ALTER TABLE retrieval_traces ADD COLUMN raw_query_text TEXT;`);
2389
+ } catch {
2390
+ }
2391
+ try {
2392
+ sqliteExec(this.db, `ALTER TABLE retrieval_traces ADD COLUMN query_rewrite_kind TEXT;`);
2393
+ } catch {
2394
+ }
2395
+ try {
2396
+ sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_retrieval_traces_query_rewrite_kind ON retrieval_traces(query_rewrite_kind);`);
2397
+ } catch {
2398
+ }
2371
2399
  const tableInfo = sqliteAll(this.db, "PRAGMA table_info(events)", []);
2372
2400
  const columnNames = tableInfo.map((col) => col.name);
2373
2401
  if (!columnNames.includes("access_count")) {
@@ -3153,8 +3181,11 @@ var SQLiteEventStore = class {
3153
3181
  /**
3154
3182
  * Get helpfulness statistics for dashboard
3155
3183
  */
3156
- async getHelpfulnessStats() {
3184
+ async getHelpfulnessStats(since) {
3157
3185
  await this.initialize();
3186
+ const sinceIso = since?.toISOString();
3187
+ const evaluatedWhere = sinceIso ? `WHERE measured_at IS NOT NULL AND datetime(created_at) >= datetime(?)` : `WHERE measured_at IS NOT NULL`;
3188
+ const totalWhere = sinceIso ? `WHERE datetime(created_at) >= datetime(?)` : ``;
3158
3189
  const stats = sqliteGet(
3159
3190
  this.db,
3160
3191
  `SELECT
@@ -3164,11 +3195,13 @@ var SQLiteEventStore = class {
3164
3195
  SUM(CASE WHEN helpfulness_score >= 0.4 AND helpfulness_score < 0.7 THEN 1 ELSE 0 END) as neutral,
3165
3196
  SUM(CASE WHEN helpfulness_score < 0.4 THEN 1 ELSE 0 END) as unhelpful
3166
3197
  FROM memory_helpfulness
3167
- WHERE measured_at IS NOT NULL`
3198
+ ${evaluatedWhere}`,
3199
+ sinceIso ? [sinceIso] : []
3168
3200
  );
3169
3201
  const totalRow = sqliteGet(
3170
3202
  this.db,
3171
- `SELECT COUNT(*) as total FROM memory_helpfulness`
3203
+ `SELECT COUNT(*) as total FROM memory_helpfulness ${totalWhere}`,
3204
+ sinceIso ? [sinceIso] : []
3172
3205
  );
3173
3206
  return {
3174
3207
  avgScore: Math.round((stats?.avg_score || 0) * 100) / 100,
@@ -3267,18 +3300,21 @@ var SQLiteEventStore = class {
3267
3300
  async recordRetrievalTrace(input) {
3268
3301
  await this.initialize();
3269
3302
  const traceId = randomUUID();
3303
+ const queryRewriteKind = normalizeQueryRewriteKind(input.queryRewriteKind);
3270
3304
  sqliteRun(
3271
3305
  this.db,
3272
3306
  `INSERT INTO retrieval_traces (
3273
- trace_id, session_id, project_hash, query_text, strategy,
3307
+ trace_id, session_id, project_hash, query_text, raw_query_text, query_rewrite_kind, strategy,
3274
3308
  candidate_event_ids, selected_event_ids, candidate_details_json, selected_details_json,
3275
3309
  candidate_count, selected_count, confidence, fallback_trace
3276
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3310
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3277
3311
  [
3278
3312
  traceId,
3279
3313
  input.sessionId || null,
3280
3314
  input.projectHash || null,
3281
3315
  input.queryText,
3316
+ input.rawQueryText || null,
3317
+ queryRewriteKind,
3282
3318
  input.strategy || null,
3283
3319
  JSON.stringify(input.candidateEventIds || []),
3284
3320
  JSON.stringify(input.selectedEventIds || []),
@@ -3304,6 +3340,8 @@ var SQLiteEventStore = class {
3304
3340
  sessionId: row.session_id || void 0,
3305
3341
  projectHash: row.project_hash || void 0,
3306
3342
  queryText: row.query_text,
3343
+ rawQueryText: row.raw_query_text || void 0,
3344
+ queryRewriteKind: normalizeQueryRewriteKind(row.query_rewrite_kind),
3307
3345
  strategy: row.strategy || void 0,
3308
3346
  candidateEventIds: row.candidate_event_ids ? JSON.parse(row.candidate_event_ids) : [],
3309
3347
  selectedEventIds: row.selected_event_ids ? JSON.parse(row.selected_event_ids) : [],
@@ -3330,6 +3368,11 @@ var SQLiteEventStore = class {
3330
3368
  COUNT(*) as total_queries,
3331
3369
  AVG(candidate_count) as avg_candidate_count,
3332
3370
  AVG(selected_count) as avg_selected_count,
3371
+ SUM(CASE WHEN ${REWRITTEN_QUERY_REWRITE_KIND_SQL} THEN 1 ELSE 0 END) as rewritten_queries,
3372
+ SUM(CASE WHEN ${REWRITTEN_QUERY_REWRITE_KIND_SQL} AND selected_count > 0 THEN 1 ELSE 0 END) as rewritten_queries_with_selection,
3373
+ SUM(CASE WHEN NOT (${REWRITTEN_QUERY_REWRITE_KIND_SQL}) AND selected_count > 0 THEN 1 ELSE 0 END) as raw_queries_with_selection,
3374
+ AVG(CASE WHEN ${REWRITTEN_QUERY_REWRITE_KIND_SQL} THEN selected_count END) as avg_selected_count_for_rewritten_queries,
3375
+ AVG(CASE WHEN NOT (${REWRITTEN_QUERY_REWRITE_KIND_SQL}) THEN selected_count END) as avg_selected_count_for_raw_queries,
3333
3376
  CASE
3334
3377
  WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))
3335
3378
  ELSE 0
@@ -3337,15 +3380,41 @@ var SQLiteEventStore = class {
3337
3380
  FROM retrieval_traces`,
3338
3381
  []
3339
3382
  );
3383
+ const totalQueries = Number(row?.total_queries || 0);
3384
+ const rewrittenQueries = Number(row?.rewritten_queries || 0);
3385
+ const rawQueries = Math.max(0, totalQueries - rewrittenQueries);
3386
+ const rewrittenQueriesWithSelection = Number(row?.rewritten_queries_with_selection || 0);
3387
+ const rawQueriesWithSelection = Number(row?.raw_queries_with_selection || 0);
3340
3388
  return {
3341
- totalQueries: Number(row?.total_queries || 0),
3389
+ totalQueries,
3342
3390
  avgCandidateCount: Number(row?.avg_candidate_count || 0),
3343
3391
  avgSelectedCount: Number(row?.avg_selected_count || 0),
3344
- selectionRate: Number(row?.selection_rate || 0)
3392
+ selectionRate: Number(row?.selection_rate || 0),
3393
+ rewrittenQueries,
3394
+ rewriteRate: totalQueries > 0 ? rewrittenQueries / totalQueries : 0,
3395
+ rewrittenQueriesWithSelection,
3396
+ rawQueriesWithSelection,
3397
+ rewrittenSelectionRate: rewrittenQueries > 0 ? rewrittenQueriesWithSelection / rewrittenQueries : 0,
3398
+ rawSelectionRate: rawQueries > 0 ? rawQueriesWithSelection / rawQueries : 0,
3399
+ avgSelectedCountForRewrittenQueries: Number(row?.avg_selected_count_for_rewritten_queries || 0),
3400
+ avgSelectedCountForRawQueries: Number(row?.avg_selected_count_for_raw_queries || 0)
3345
3401
  };
3346
3402
  } catch (err) {
3347
3403
  if (err?.message?.includes("no such table")) {
3348
- return { totalQueries: 0, avgCandidateCount: 0, avgSelectedCount: 0, selectionRate: 0 };
3404
+ return {
3405
+ totalQueries: 0,
3406
+ avgCandidateCount: 0,
3407
+ avgSelectedCount: 0,
3408
+ selectionRate: 0,
3409
+ rewrittenQueries: 0,
3410
+ rewriteRate: 0,
3411
+ rewrittenQueriesWithSelection: 0,
3412
+ rawQueriesWithSelection: 0,
3413
+ rewrittenSelectionRate: 0,
3414
+ rawSelectionRate: 0,
3415
+ avgSelectedCountForRewrittenQueries: 0,
3416
+ avgSelectedCountForRawQueries: 0
3417
+ };
3349
3418
  }
3350
3419
  throw err;
3351
3420
  }
@@ -3697,6 +3766,57 @@ var COMMAND_ARTIFACT_PATTERNS = [
3697
3766
  /<local-command-stdout>[\s\S]*?<\/local-command-stdout>/i,
3698
3767
  /<local-command-stderr>[\s\S]*?<\/local-command-stderr>/i
3699
3768
  ];
3769
+ var CONTINUATION_QUERY_PATTERNS = [
3770
+ /^\s*(?:continue|resume|next|what(?:'s| is)? next|next\s+(?:step|task|action)|recommended\s+(?:next\s+)?(?:step|task|action)|what should (?:we|i) do next)\??\s*$/i,
3771
+ /^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
3772
+ ];
3773
+ var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
3774
+ /^\s*(?:fix\s+(?:it|that)|repair\s+(?:it|that)|resolve\s+(?:it|that)|that\s+bug|same\s+issue)\s*$/i,
3775
+ /^\s*(?:그거|그것|이거|이것)?\s*(?:고쳐줘|수정해줘|해결해줘|처리해줘)\s*$/i
3776
+ ];
3777
+ var CURRENT_STATE_QUERY_PATTERNS = [
3778
+ /\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
3779
+ /\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
3780
+ /\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|state|status)\b/i,
3781
+ /(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
3782
+ ];
3783
+ var STALE_CONTENT_PATTERNS = [
3784
+ /\b(?:obsolete|superseded|outdated)\b/i,
3785
+ /\bstale\s+(?:operational\s+)?state\b/i,
3786
+ /\bstale\s+after\b/i,
3787
+ /\bno\s+longer\s+(?:valid|current|applies?)\b/i,
3788
+ /\bearlier\s+(?:pull request|pr)\b[\s\S]{0,160}\b(?:open|not completed|had not completed)\b/i,
3789
+ /\bshould\s+not\s+be\s+injected\s+as\s+current\s+context\b/i,
3790
+ /(?:오래된|더 이상 유효하지|현재 상태가 아님)/i
3791
+ ];
3792
+ var CONTINUATION_EXPANSION = "current next step plan roadmap status validation replay rerank memory usefulness continuation";
3793
+ var REPAIR_FOLLOW_UP_EXPANSION = "review blocker fix pattern dashboard error state metrics bucket validation sanitize rerun unresolved";
3794
+ var RETRIEVAL_PRIVACY_DECISION_EXPANSION = "retrieval telemetry privacy public api dashboard dashboards rawQueryText queryText raw query text expose safe trace metadata trace id reason strategy rewrite kind aggregate count counts candidate selected public panel";
3795
+ var DECISION_RECALL_TERMS = /* @__PURE__ */ new Set([
3796
+ "decide",
3797
+ "decided",
3798
+ "decision",
3799
+ "agreed",
3800
+ "policy",
3801
+ "constraint"
3802
+ ]);
3803
+ var RETRIEVAL_PRIVACY_SURFACE_TERMS = /* @__PURE__ */ new Set([
3804
+ "retrieval",
3805
+ "dashboard",
3806
+ "telemetry",
3807
+ "trace"
3808
+ ]);
3809
+ var DECISION_TOPIC_WEAK_TERMS = /* @__PURE__ */ new Set([
3810
+ "api",
3811
+ "dashboard",
3812
+ "retrieval",
3813
+ "trace",
3814
+ "telemetry",
3815
+ "query",
3816
+ "raw",
3817
+ "count",
3818
+ "counts"
3819
+ ]);
3700
3820
  var GENERIC_TECHNICAL_TERMS = /* @__PURE__ */ new Set([
3701
3821
  "api",
3702
3822
  "cli",
@@ -3714,6 +3834,87 @@ var GENERIC_TECHNICAL_TERMS = /* @__PURE__ */ new Set([
3714
3834
  "db",
3715
3835
  "sql"
3716
3836
  ]);
3837
+ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
3838
+ "the",
3839
+ "and",
3840
+ "or",
3841
+ "for",
3842
+ "from",
3843
+ "with",
3844
+ "without",
3845
+ "about",
3846
+ "what",
3847
+ "when",
3848
+ "where",
3849
+ "which",
3850
+ "who",
3851
+ "why",
3852
+ "how",
3853
+ "did",
3854
+ "does",
3855
+ "do",
3856
+ "we",
3857
+ "i",
3858
+ "in",
3859
+ "to",
3860
+ "of",
3861
+ "on",
3862
+ "as",
3863
+ "be",
3864
+ "was",
3865
+ "were",
3866
+ "decide",
3867
+ "decided",
3868
+ "decision",
3869
+ "agreed",
3870
+ "policy",
3871
+ "constraint",
3872
+ "showing",
3873
+ "can",
3874
+ "you",
3875
+ "me",
3876
+ "show",
3877
+ "tell",
3878
+ "please",
3879
+ "should",
3880
+ "would",
3881
+ "could",
3882
+ "this",
3883
+ "that",
3884
+ "these",
3885
+ "those",
3886
+ "use",
3887
+ "using",
3888
+ "treat",
3889
+ "continue",
3890
+ "resume",
3891
+ "next",
3892
+ "step",
3893
+ "task",
3894
+ "action",
3895
+ "current",
3896
+ "state",
3897
+ "status",
3898
+ "old",
3899
+ "already",
3900
+ "still",
3901
+ "near",
3902
+ "today",
3903
+ "\uC751",
3904
+ "\uADF8\uAC70",
3905
+ "\uADF8\uAC83",
3906
+ "\uC774\uAC70",
3907
+ "\uC774\uAC83",
3908
+ "\uB2E4\uC74C",
3909
+ "\uB2E8\uACC4",
3910
+ "\uC9C4\uD589",
3911
+ "\uC9C4\uD589\uD574\uC918",
3912
+ "\uACC4\uC18D",
3913
+ "\uC774\uC5B4\uC11C",
3914
+ "\uACE0\uCCD0\uC918",
3915
+ "\uC218\uC815\uD574\uC918",
3916
+ "\uD574\uACB0\uD574\uC918"
3917
+ ]);
3717
3918
  function isCommandArtifactQuery(query) {
3718
3919
  const trimmed = query.trim();
3719
3920
  if (!trimmed)
@@ -3725,6 +3926,73 @@ function isCommandArtifactQuery(query) {
3725
3926
  return true;
3726
3927
  return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
3727
3928
  }
3929
+ function isGenericContinuationQuery(query) {
3930
+ const trimmed = query.trim();
3931
+ if (!trimmed)
3932
+ return false;
3933
+ if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed)))
3934
+ return false;
3935
+ if (extractTechnicalQueryTerms(trimmed).length > 0)
3936
+ return false;
3937
+ const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
3938
+ if (tokens.length > 10)
3939
+ return false;
3940
+ return !/[A-Za-z0-9_-]+\.[A-Za-z0-9]+/.test(trimmed) && !/(?:^|\s)(?:feat|fix|chore|refactor|docs)\/[A-Za-z0-9._-]+/.test(trimmed) && !/[A-Za-z]:?[\\/]|\/Users\/|\.\/|\.\.\//.test(trimmed);
3941
+ }
3942
+ function isShortRepairFollowUpQuery(query) {
3943
+ const trimmed = query.trim();
3944
+ if (!trimmed)
3945
+ return false;
3946
+ if (extractTechnicalQueryTerms(trimmed).length > 0)
3947
+ return false;
3948
+ const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
3949
+ if (tokens.length > 8)
3950
+ return false;
3951
+ return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
3952
+ }
3953
+ function isCurrentStateQuery(query) {
3954
+ const trimmed = query.trim();
3955
+ if (!trimmed)
3956
+ return false;
3957
+ return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
3958
+ }
3959
+ function isStaleOrSupersededContent(content) {
3960
+ const trimmed = content.trim();
3961
+ if (!trimmed)
3962
+ return false;
3963
+ return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
3964
+ }
3965
+ function buildRetrievalQualityQuery(query) {
3966
+ const trimmed = query.trim();
3967
+ if (!trimmed)
3968
+ return query;
3969
+ if (isRetrievalPrivacyDecisionQuery(trimmed)) {
3970
+ return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
3971
+ }
3972
+ if (isGenericContinuationQuery(trimmed)) {
3973
+ return `${trimmed} ${CONTINUATION_EXPANSION}`;
3974
+ }
3975
+ if (isShortRepairFollowUpQuery(trimmed)) {
3976
+ return `${trimmed} ${REPAIR_FOLLOW_UP_EXPANSION}`;
3977
+ }
3978
+ return query;
3979
+ }
3980
+ function isRetrievalPrivacyDecisionQuery(query) {
3981
+ const trimmed = query.trim();
3982
+ if (!trimmed)
3983
+ return false;
3984
+ const terms = new Set(tokenizeQualityText(trimmed));
3985
+ const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
3986
+ if (!hasDecisionSignal)
3987
+ return false;
3988
+ const hasRawQuerySignal = terms.has("raw") && terms.has("query");
3989
+ const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
3990
+ const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
3991
+ const hasQuerySurface = terms.has("query") && (terms.has("dashboard") || terms.has("trace") || terms.has("telemetry") || terms.has("api"));
3992
+ const hasKoreanRetrievalSurface = /(?:검색|리트리벌|retrieval|대시보드|트레이스|텔레메트리|telemetry)/i.test(trimmed);
3993
+ const hasKoreanPrivacySurface = /(?:원문|쿼리|프라이버시|개인정보|노출|트레이스|메타데이터)/i.test(trimmed);
3994
+ return (hasRetrievalSurface || hasKoreanRetrievalSurface && hasKoreanPrivacySurface) && (hasRawQuerySignal || hasPrivacySignal || hasQuerySurface || hasKoreanPrivacySurface);
3995
+ }
3728
3996
  function extractTechnicalQueryTerms(query) {
3729
3997
  const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
3730
3998
  const terms = matches.filter((term) => {
@@ -3742,9 +4010,87 @@ function hasTechnicalTermOverlap(query, content) {
3742
4010
  const normalizedContent = content.toLowerCase();
3743
4011
  return terms.some((term) => normalizedContent.includes(term));
3744
4012
  }
4013
+ function hasDiscriminativeTermOverlap(query, content) {
4014
+ const queryTerms = extractDiscriminativeQueryTerms(query);
4015
+ const contentTerms = new Set(tokenizeQualityText(content));
4016
+ if (isRetrievalPrivacyDecisionQuery(query) && hasRetrievalPrivacyDecisionContent(contentTerms)) {
4017
+ return true;
4018
+ }
4019
+ if (shouldRequireDecisionTopicOverlap(query)) {
4020
+ const topicTerms = queryTerms.filter((term) => !DECISION_TOPIC_WEAK_TERMS.has(term));
4021
+ if (topicTerms.length > 0) {
4022
+ return topicTerms.some((term) => contentTerms.has(term));
4023
+ }
4024
+ }
4025
+ if (queryTerms.length < 3)
4026
+ return true;
4027
+ const requiredHits = queryTerms.length >= 3 ? 2 : 1;
4028
+ let hits = 0;
4029
+ for (const term of queryTerms) {
4030
+ if (contentTerms.has(term))
4031
+ hits += 1;
4032
+ if (hits >= requiredHits)
4033
+ return true;
4034
+ }
4035
+ return false;
4036
+ }
3745
4037
  function shouldApplyTechnicalGuard(query) {
3746
4038
  return extractTechnicalQueryTerms(query).length > 0;
3747
4039
  }
4040
+ function hasAnyTerm(terms, expectedTerms) {
4041
+ let found = false;
4042
+ expectedTerms.forEach((term) => {
4043
+ if (terms.has(term))
4044
+ found = true;
4045
+ });
4046
+ return found;
4047
+ }
4048
+ function shouldRequireDecisionTopicOverlap(query) {
4049
+ if (isRetrievalPrivacyDecisionQuery(query))
4050
+ return false;
4051
+ const trimmed = query.trim();
4052
+ if (!trimmed)
4053
+ return false;
4054
+ const terms = new Set(tokenizeQualityText(trimmed));
4055
+ return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
4056
+ }
4057
+ function extractDiscriminativeQueryTerms(query) {
4058
+ const seen = /* @__PURE__ */ new Set();
4059
+ const terms = [];
4060
+ for (const token of tokenizeQualityText(query)) {
4061
+ if (LOW_INFORMATION_QUERY_TERMS.has(token))
4062
+ continue;
4063
+ if (GENERIC_TECHNICAL_TERMS.has(token))
4064
+ continue;
4065
+ if (seen.has(token))
4066
+ continue;
4067
+ seen.add(token);
4068
+ terms.push(token);
4069
+ }
4070
+ return terms;
4071
+ }
4072
+ function hasRetrievalPrivacyDecisionContent(contentTerms) {
4073
+ const hasDashboardTraceMetadata = contentTerms.has("dashboard") && (contentTerms.has("trace") || contentTerms.has("metadata")) && (contentTerms.has("safe") || contentTerms.has("strategy") || contentTerms.has("rewrite") || contentTerms.has("candidate") || contentTerms.has("selected") || contentTerms.has("count") || contentTerms.has("reason"));
4074
+ const hasRawQueryPrivacyPolicy = contentTerms.has("retrieval") && (contentTerms.has("privacy") || contentTerms.has("expose") || contentTerms.has("raw") && contentTerms.has("query") && (contentTerms.has("dashboard") || contentTerms.has("telemetry") || contentTerms.has("api") || contentTerms.has("public")));
4075
+ return hasDashboardTraceMetadata || hasRawQueryPrivacyPolicy;
4076
+ }
4077
+ function tokenizeQualityText(text) {
4078
+ return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^A-Za-z0-9가-힣\s_.:-]/g, " ").split(/\s+/).flatMap((token) => token.split(/(?=[._:-])|(?<=[._:-])/g)).map((token) => normalizeQualityToken(token.replace(/^[._:-]+|[._:-]+$/g, ""))).filter((token) => token.length >= 2);
4079
+ }
4080
+ function normalizeQualityToken(token) {
4081
+ if (token === "apis")
4082
+ return "api";
4083
+ if (token === "ids")
4084
+ return "id";
4085
+ if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
4086
+ return token;
4087
+ if (token.length > 4 && token.endsWith("ies"))
4088
+ return `${token.slice(0, -3)}y`;
4089
+ if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
4090
+ return token.slice(0, -1);
4091
+ }
4092
+ return token;
4093
+ }
3748
4094
 
3749
4095
  // src/core/retriever.ts
3750
4096
  var DEFAULT_OPTIONS = {
@@ -3797,6 +4143,7 @@ var Retriever = class {
3797
4143
  const opts = { ...DEFAULT_OPTIONS, ...options };
3798
4144
  const sessionFilter = opts.scope?.sessionId ?? opts.sessionId;
3799
4145
  const fallbackTrace = [];
4146
+ const qualityQuery = buildRetrievalQualityQuery(query);
3800
4147
  if (isCommandArtifactQuery(query)) {
3801
4148
  fallbackTrace.push("guard:command-artifact-query");
3802
4149
  const emptyMatch = this.matcher.matchSearchResults([], () => 0);
@@ -3813,6 +4160,7 @@ var Retriever = class {
3813
4160
  const fallbackEnabled = (opts.strategy ?? "auto") === "auto";
3814
4161
  const primaryStrategy = opts.strategy === "auto" ? "fast" : opts.strategy || "fast";
3815
4162
  let current = await this.runStage(query, {
4163
+ qualityQuery,
3816
4164
  strategy: primaryStrategy,
3817
4165
  topK: opts.topK,
3818
4166
  minScore: opts.minScore,
@@ -3830,6 +4178,7 @@ var Retriever = class {
3830
4178
  fallbackTrace.push(`stage:primary:${primaryStrategy}`);
3831
4179
  if (fallbackEnabled && this.shouldFallback(current.matchResult, current.results) && primaryStrategy !== "deep") {
3832
4180
  current = await this.runStage(query, {
4181
+ qualityQuery,
3833
4182
  strategy: "deep",
3834
4183
  topK: opts.topK,
3835
4184
  minScore: opts.minScore,
@@ -3847,6 +4196,7 @@ var Retriever = class {
3847
4196
  }
3848
4197
  if (fallbackEnabled && this.shouldFallback(current.matchResult, current.results)) {
3849
4198
  current = await this.runStage(query, {
4199
+ qualityQuery,
3850
4200
  strategy: "deep",
3851
4201
  topK: opts.topK,
3852
4202
  minScore: Math.max(0.5, opts.minScore - 0.15),
@@ -3863,11 +4213,21 @@ var Retriever = class {
3863
4213
  fallbackTrace.push("fallback:scope-expanded");
3864
4214
  }
3865
4215
  if (fallbackEnabled && this.shouldFallback(current.matchResult, current.results)) {
3866
- const summary = await this.buildSummaryFallback(query, opts.topK);
4216
+ const summary = await this.buildSummaryFallback(qualityQuery, opts.topK);
4217
+ const scopedSummary = await this.applyScopeFilters(summary, {
4218
+ scope: opts.scope,
4219
+ projectScopeMode: opts.projectScopeMode,
4220
+ projectHash: opts.projectHash,
4221
+ allowedProjectHashes: opts.allowedProjectHashes
4222
+ });
4223
+ const filteredSummary = this.applyQualityFilters(scopedSummary, {
4224
+ query,
4225
+ minScore: opts.minScore
4226
+ });
3867
4227
  current = {
3868
- results: summary,
3869
- candidateResults: summary,
3870
- matchResult: this.matcher.matchSearchResults(summary, () => 0)
4228
+ results: filteredSummary,
4229
+ candidateResults: filteredSummary,
4230
+ matchResult: this.matcher.matchSearchResults(filteredSummary, () => 0)
3871
4231
  };
3872
4232
  fallbackTrace.push("fallback:summary");
3873
4233
  }
@@ -3892,7 +4252,10 @@ var Retriever = class {
3892
4252
  semanticScore: r.semanticScore,
3893
4253
  lexicalScore: r.lexicalScore,
3894
4254
  recencyScore: r.recencyScore
3895
- }))
4255
+ })),
4256
+ rawQueryText: current.queryRewriteKind ? query : void 0,
4257
+ effectiveQueryText: current.effectiveQueryText,
4258
+ queryRewriteKind: current.queryRewriteKind
3896
4259
  };
3897
4260
  }
3898
4261
  async retrieveUnified(query, options = {}) {
@@ -3930,8 +4293,11 @@ var Retriever = class {
3930
4293
  }
3931
4294
  }
3932
4295
  async runStage(query, input) {
3933
- let rerankQuery = query;
3934
- let initialResults = await this.searchByStrategy(query, {
4296
+ const searchQuery = input.qualityQuery ?? query;
4297
+ let rerankQuery = searchQuery;
4298
+ let effectiveQueryText;
4299
+ let queryRewriteKind;
4300
+ let initialResults = await this.searchByStrategy(searchQuery, {
3935
4301
  strategy: input.strategy,
3936
4302
  topK: input.topK,
3937
4303
  minScore: input.minScore,
@@ -3939,9 +4305,12 @@ var Retriever = class {
3939
4305
  });
3940
4306
  if (input.intentRewrite && input.strategy === "deep" && this.queryRewriter) {
3941
4307
  const rewritten = (await this.queryRewriter(query))?.trim();
3942
- if (rewritten && rewritten !== query) {
3943
- rerankQuery = `${query} ${rewritten}`;
3944
- const rewrittenResults = await this.searchByStrategy(rewritten, {
4308
+ const normalizedQuery = query.trim();
4309
+ if (rewritten && rewritten !== normalizedQuery) {
4310
+ effectiveQueryText = `${normalizedQuery} ${rewritten}`.trim();
4311
+ queryRewriteKind = "intent-rewrite";
4312
+ rerankQuery = buildRetrievalQualityQuery(effectiveQueryText);
4313
+ const rewrittenResults = await this.searchByStrategy(buildRetrievalQualityQuery(rewritten), {
3945
4314
  strategy: "deep",
3946
4315
  topK: input.topK,
3947
4316
  minScore: Math.max(0.5, input.minScore - 0.1),
@@ -3968,10 +4337,14 @@ var Retriever = class {
3968
4337
  });
3969
4338
  const top = qualityFiltered.slice(0, input.topK);
3970
4339
  const matchResult = this.matcher.matchSearchResults(top, () => 0);
3971
- return { results: top, candidateResults: qualityFiltered, matchResult };
4340
+ return { results: top, candidateResults: qualityFiltered, matchResult, effectiveQueryText, queryRewriteKind };
3972
4341
  }
3973
4342
  applyQualityFilters(results, options) {
3974
4343
  let filtered = [...results];
4344
+ if (isCurrentStateQuery(options.query)) {
4345
+ filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
4346
+ }
4347
+ filtered = filtered.filter((result) => hasDiscriminativeTermOverlap(options.query, result.content));
3975
4348
  if (shouldApplyTechnicalGuard(options.query)) {
3976
4349
  filtered = filtered.filter((result) => hasTechnicalTermOverlap(options.query, result.content));
3977
4350
  }
@@ -4279,7 +4652,21 @@ _Context:_ ${sessionContext}`;
4279
4652
  });
4280
4653
  }
4281
4654
  tokenize(text) {
4282
- return text.toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).filter((t) => t.length >= 2).slice(0, 64);
4655
+ return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).map((token) => this.normalizeToken(token)).filter((t) => t.length >= 2).slice(0, 64);
4656
+ }
4657
+ normalizeToken(token) {
4658
+ if (token === "apis")
4659
+ return "api";
4660
+ if (token === "ids")
4661
+ return "id";
4662
+ if (token === "does")
4663
+ return token;
4664
+ if (token.length > 4 && token.endsWith("ies"))
4665
+ return `${token.slice(0, -3)}y`;
4666
+ if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
4667
+ return token.slice(0, -1);
4668
+ }
4669
+ return token;
4283
4670
  }
4284
4671
  keywordOverlap(a, b) {
4285
4672
  if (a.length === 0 || b.length === 0)
@@ -4342,9 +4729,9 @@ var RetrievalAnalyticsService = class {
4342
4729
  await this.deps.initialize();
4343
4730
  return this.deps.retrievalStore.getHelpfulMemories(limit);
4344
4731
  }
4345
- async getHelpfulnessStats() {
4732
+ async getHelpfulnessStats(since) {
4346
4733
  await this.deps.initialize();
4347
- return this.deps.retrievalStore.getHelpfulnessStats();
4734
+ return this.deps.retrievalStore.getHelpfulnessStats(since);
4348
4735
  }
4349
4736
  /**
4350
4737
  * Extract topic keywords from event content (markdown headings and key terms).
@@ -4769,7 +5156,9 @@ var RetrievalOrchestrator = class {
4769
5156
  await this.deps.traceStore.recordRetrievalTrace({
4770
5157
  sessionId: options?.sessionId,
4771
5158
  projectHash: projectHash || void 0,
4772
- queryText: query,
5159
+ queryText: result.effectiveQueryText || query,
5160
+ rawQueryText: result.rawQueryText || (result.queryRewriteKind ? query : void 0),
5161
+ queryRewriteKind: result.queryRewriteKind || "none",
4773
5162
  strategy: options?.strategy || "auto",
4774
5163
  candidateEventIds,
4775
5164
  selectedEventIds,
@@ -12536,8 +12925,8 @@ var MemoryService = class {
12536
12925
  /**
12537
12926
  * Get helpfulness statistics for dashboard
12538
12927
  */
12539
- async getHelpfulnessStats() {
12540
- return this.retrievalAnalyticsService.getHelpfulnessStats();
12928
+ async getHelpfulnessStats(since) {
12929
+ return this.retrievalAnalyticsService.getHelpfulnessStats(since);
12541
12930
  }
12542
12931
  /**
12543
12932
  * Mark a consolidated memory as accessed