flurryx-code-memory 0.7.0__tar.gz → 0.7.6__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 (202) hide show
  1. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/CHANGELOG.md +57 -0
  2. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/PKG-INFO +2 -2
  3. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/README.md +7 -2
  4. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/install.ps1 +43 -19
  5. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/pyproject.toml +2 -2
  6. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/install.ps1 +142 -34
  7. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/install.sh +98 -14
  8. flurryx_code_memory-0.7.6/src/code_memory/_console.py +32 -0
  9. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/cli.py +14 -1
  10. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/treesitter.py +13 -3
  11. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/mcp_server.py +3 -0
  12. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/updater.py +146 -1
  13. flurryx_code_memory-0.7.6/tests/test_console_encoding.py +63 -0
  14. flurryx_code_memory-0.7.6/tests/test_extractor_parser_compat.py +27 -0
  15. flurryx_code_memory-0.7.6/tests/test_extras_offer.py +327 -0
  16. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/uv.lock +2 -2
  17. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/.claude-plugin/marketplace.json +0 -0
  18. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/.env.example +0 -0
  19. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/.gitignore +0 -0
  20. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docker/docker-compose.yml +0 -0
  21. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docs/BENCHMARK.md +0 -0
  22. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docs/BENCHMARK_VS_BASELINE.json +0 -0
  23. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docs/BENCHMARK_VS_BASELINE.md +0 -0
  24. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docs/architecture.png +0 -0
  25. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docs/benchmark-raw.json +0 -0
  26. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/docs/hero.png +0 -0
  27. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/install.sh +0 -0
  28. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  29. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/README.md +0 -0
  30. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/commands/code-memory.md +0 -0
  31. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/hooks/hooks.json +0 -0
  32. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/install.sh +0 -0
  33. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/lib/claim-intent.js +0 -0
  34. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/lib/claim-intent.test.js +0 -0
  35. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/lib/io.js +0 -0
  36. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/lib/memory.js +0 -0
  37. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/lib/state.js +0 -0
  38. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/on-post-tool.js +0 -0
  39. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/on-pre-tool.js +0 -0
  40. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/on-retrieve-seen.js +0 -0
  41. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/on-session-start.js +0 -0
  42. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/on-stop.js +0 -0
  43. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/on-user-prompt.js +0 -0
  44. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/scripts/resolver-debounce.js +0 -0
  45. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/claude-code/skills/code-memory/SKILL.md +0 -0
  46. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/README.md +0 -0
  47. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/hooks/hooks.json.template +0 -0
  48. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/install.sh +0 -0
  49. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/rules/code-memory.mdc +0 -0
  50. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/lib/claim-intent.js +0 -0
  51. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/lib/claim-intent.test.js +0 -0
  52. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/lib/io.js +0 -0
  53. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/lib/memory.js +0 -0
  54. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/lib/state.js +0 -0
  55. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-after-file-edit.js +0 -0
  56. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-before-mcp-execution.js +0 -0
  57. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-before-submit-prompt.js +0 -0
  58. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-post-tool-use.js +0 -0
  59. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-pre-compact.js +0 -0
  60. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-pre-tool-use.js +0 -0
  61. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-session-end.js +0 -0
  62. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-session-start.js +0 -0
  63. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/on-stop.js +0 -0
  64. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/cursor/scripts/resolver-debounce.js +0 -0
  65. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/README.md +0 -0
  66. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/install.sh +0 -0
  67. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/package-lock.json +0 -0
  68. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/package.json +0 -0
  69. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/scripts/add-mcp.py +0 -0
  70. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/scripts/install.mjs +0 -0
  71. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/scripts/uninstall.mjs +0 -0
  72. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/skills/code-memory/SKILL.md +0 -0
  73. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/src/code-memory-lib/claim-intent.test.mts +0 -0
  74. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/src/code-memory-lib/claim-intent.ts +0 -0
  75. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/src/code-memory-lib/memory-client.ts +0 -0
  76. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/src/code-memory.ts +0 -0
  77. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/opencode/tsconfig.json +0 -0
  78. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/vibe/README.md +0 -0
  79. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/vibe/install.sh +0 -0
  80. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/plugins/vibe/skills/code-memory/SKILL.md +0 -0
  81. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/benchmark.py +0 -0
  82. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/benchmark_queries.json +0 -0
  83. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/benchmark_vs_baseline.py +0 -0
  84. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/benchmark_vs_grep.sh +0 -0
  85. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/scripts/ingest.py +0 -0
  86. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/__init__.py +0 -0
  87. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/claims/__init__.py +0 -0
  88. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/claims/extractor.py +0 -0
  89. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/claims/indexer.py +0 -0
  90. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/claims/resolver.py +0 -0
  91. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/claims/store.py +0 -0
  92. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/config.py +0 -0
  93. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/embed/__init__.py +0 -0
  94. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/embed/cache.py +0 -0
  95. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/embed/m3.py +0 -0
  96. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/embed/ollama.py +0 -0
  97. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/embed/tei.py +0 -0
  98. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/episodic/__init__.py +0 -0
  99. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/episodic/sqlite_store.py +0 -0
  100. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/__init__.py +0 -0
  101. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/csproj.py +0 -0
  102. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/dll.py +0 -0
  103. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/gitignore.py +0 -0
  104. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/nuget.py +0 -0
  105. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/sanity.py +0 -0
  106. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/extractor/sln.py +0 -0
  107. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/graph/__init__.py +0 -0
  108. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/graph/falkor_store.py +0 -0
  109. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/metrics.py +0 -0
  110. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/__init__.py +0 -0
  111. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/git_delta.py +0 -0
  112. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/ingest_state.py +0 -0
  113. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/pipeline.py +0 -0
  114. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/reset.py +0 -0
  115. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/resolver.py +0 -0
  116. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/orchestrator/retrieve.py +0 -0
  117. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/resilience.py +0 -0
  118. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/__init__.py +0 -0
  119. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/autostart/__init__.py +0 -0
  120. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/autostart/base.py +0 -0
  121. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/autostart/launchd.py +0 -0
  122. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/autostart/schtasks.py +0 -0
  123. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/autostart/systemd.py +0 -0
  124. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/hooks.py +0 -0
  125. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/safety.py +0 -0
  126. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/single_flight.py +0 -0
  127. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/snapshot.py +0 -0
  128. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/store.py +0 -0
  129. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/sync.py +0 -0
  130. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/sync/watcher.py +0 -0
  131. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/vector/__init__.py +0 -0
  132. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/src/code_memory/vector/qdrant_store.py +0 -0
  133. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_autostart_adapters.py +0 -0
  134. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_chunk_text.py +0 -0
  135. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_claim_extractor.py +0 -0
  136. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_claim_indexer.py +0 -0
  137. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_claim_resolver.py +0 -0
  138. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_claim_store.py +0 -0
  139. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_config_embed_dim.py +0 -0
  140. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_config_ipv4_defaults.py +0 -0
  141. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_config_sentinel.py +0 -0
  142. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_csproj.py +0 -0
  143. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_dll_members.py +0 -0
  144. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_dll_parser.py +0 -0
  145. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_embed_backend.py +0 -0
  146. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_embed_cache.py +0 -0
  147. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_embed_m3.py +0 -0
  148. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_embed_ollama_timeout.py +0 -0
  149. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_embed_tei.py +0 -0
  150. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_ensure_fresh_no_blocking.py +0 -0
  151. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_episode_dedup.py +0 -0
  152. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_episode_head_sha.py +0 -0
  153. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_csharp.py +0 -0
  154. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_dart.py +0 -0
  155. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_filters.py +0 -0
  156. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_php.py +0 -0
  157. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_python_imports.py +0 -0
  158. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_receiver_type.py +0 -0
  159. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_references.py +0 -0
  160. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_sanity.py +0 -0
  161. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_ts_abstract.py +0 -0
  162. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_ts_inject.py +0 -0
  163. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_extractor_utf8.py +0 -0
  164. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_file_containment.py +0 -0
  165. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_git_delta.py +0 -0
  166. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_graph_queries.py +0 -0
  167. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_graph_shadow_swap.py +0 -0
  168. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_graph_temporal.py +0 -0
  169. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_graph_vacuum_at_sha.py +0 -0
  170. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_hooks_installer.py +0 -0
  171. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_ingest_safety_and_lock.py +0 -0
  172. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_ingest_state.py +0 -0
  173. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_mcp_assert_claim.py +0 -0
  174. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_mcp_server_descriptions.py +0 -0
  175. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_mcp_shutdown.py +0 -0
  176. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_mcp_strict_project.py +0 -0
  177. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_metrics.py +0 -0
  178. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_nuget_resolver.py +0 -0
  179. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_overload_resolution.py +0 -0
  180. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_partial_class.py +0 -0
  181. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_pipeline_health_check.py +0 -0
  182. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_pipeline_references.py +0 -0
  183. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_pipeline_temporal_wiring.py +0 -0
  184. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_qdrant_legacy_guard.py +0 -0
  185. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_razor_inject.py +0 -0
  186. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_resilience.py +0 -0
  187. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_resolver.py +0 -0
  188. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_resolver_assembly.py +0 -0
  189. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_retrieve_claims_surfacing.py +0 -0
  190. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_retrieve_rerank.py +0 -0
  191. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_sln.py +0 -0
  192. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_smoke.py +0 -0
  193. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_snapshot_e2e.py +0 -0
  194. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_snapshot_format.py +0 -0
  195. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_snapshot_store.py +0 -0
  196. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_sync_decision_tree.py +0 -0
  197. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_watch_safety.py +0 -0
  198. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_watcher_debouncer.py +0 -0
  199. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_watcher_exclude.py +0 -0
  200. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_watcher_ref_events.py +0 -0
  201. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_worktree_autostart_guard.py +0 -0
  202. {flurryx_code_memory-0.7.0 → flurryx_code_memory-0.7.6}/tests/test_worktree_slug.py +0 -0
@@ -8,6 +8,63 @@ when the repo grows.
8
8
  This file complements `git log`: commits explain mechanics, this file
9
9
  explains intent.
10
10
 
11
+ ## [0.7.6] — 2026-06-21
12
+
13
+ Release theme: **Correct tree-sitter pin + Windows console & extras fixes**.
14
+
15
+ ### Fixed
16
+
17
+ **tree-sitter-language-pack pinned to `==1.8.1`** (was `==1.0.0` in the broken 0.7.5).
18
+ Version 1.0.0 has no bundled language grammars (it uses a download model), so
19
+ `get_language('csharp')` raised `LanguageNotFoundError` and extraction produced
20
+ zero symbols on every platform. Version 1.9.1 is also broken (raises `'bytes'
21
+ object is not an instance of 'str'` even on macOS — a 1.9.x regression). 1.8.1
22
+ is the last known-good release with bundled grammars; the original Windows
23
+ failure was caused by the loose `>=0.7` floor letting fresh installs float to
24
+ 1.9.1.
25
+
26
+ Reason: stop floating into broken 1.9.x and restore symbol extraction everywhere.
27
+
28
+ **Windows console crash in `code-memory update`**: stdout/stderr are now forced
29
+ to UTF-8 (`errors="replace"`) at the CLI and MCP entry points, so Unicode
30
+ status glyphs (→, •, ✓) no longer raise `UnicodeEncodeError` on cp1252
31
+ PowerShell consoles.
32
+
33
+ Reason: the updater crashed before doing any work on non-UTF-8 Windows terminals.
34
+
35
+ ### Added
36
+
37
+ **Optional-extras selection prompt** in `code-memory update` and the install
38
+ one-liner (`install.sh` / `install.ps1`): users are now asked which optional
39
+ extras to enable (`dotnet` for .NET assembly indexing, `hybrid` for in-process
40
+ BGE-M3). TTY-gated with a `CODEMEMORY_EXTRAS` env override and an `--extras`
41
+ flag; non-interactive runs install nothing new. Also fixes the bash installer
42
+ gating the prompt on `[ -t 0 ]`, which was always false under `curl | bash` so
43
+ the prompt never appeared.
44
+
45
+ Reason: previously there was no way to opt into .NET indexing during update/install.
46
+
47
+ ## [0.7.5] — 2026-06-21
48
+
49
+ Release theme: **Windows ingest fix — pin tree-sitter-language-pack**.
50
+
51
+ **⚠️ Superseded by 0.7.6 — this release pinned tree-sitter-language-pack==1.0.0 which broke extraction (no bundled grammars). Do not use.**
52
+
53
+ ### Fixed
54
+
55
+ **What:** pinned `tree-sitter-language-pack` to `==1.0.0` (was `>=0.7`).
56
+ Version 1.9.1 (and other releases > 1.0.0) ship a broken Windows wheel:
57
+ `get_language()` returns a `builtins.Language` that core `tree-sitter`
58
+ rejects (`TypeError: __init__() argument 1 must be tree_sitter.Language,
59
+ not builtins.Language`), surfacing during ingest as `'bytes' object is
60
+ not an instance of 'str'`. This broke `code-memory` CLI ingest on Windows
61
+ across all install environments (uv-tool, global Python, watch daemon).
62
+
63
+ **Reason:** the loose `>=0.7` floor allowed the broken 1.9.1 wheel to
64
+ resolve on fresh Windows installs; pinning to the known-good 1.0.0
65
+ restores ingest. The pin lives in wheel metadata so every install path
66
+ resolves to the working version.
67
+
11
68
  ## [0.7.0] — 2026-06-12
12
69
 
13
70
  Release theme: **Worktree resilience, atomic graph rebuilds, and fresh
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flurryx-code-memory
3
- Version: 0.7.0
3
+ Version: 0.7.6
4
4
  Summary: Local lightweight memory layer for coding agents: FalkorDB + Qdrant + Ollama (BGE-M3) + tree-sitter
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: anyio>=4.4
@@ -10,7 +10,7 @@ Requires-Dist: mcp>=1.0
10
10
  Requires-Dist: pydantic>=2.8
11
11
  Requires-Dist: qdrant-client>=1.12
12
12
  Requires-Dist: rich>=13.7
13
- Requires-Dist: tree-sitter-language-pack>=0.7
13
+ Requires-Dist: tree-sitter-language-pack==1.8.1
14
14
  Requires-Dist: tree-sitter>=0.23
15
15
  Requires-Dist: typer>=0.12
16
16
  Requires-Dist: watchdog>=4.0
@@ -99,9 +99,14 @@ curl -fsSL https://raw.githubusercontent.com/fmflurry/code-memory/main/install.s
99
99
  **🪟 Windows**
100
100
 
101
101
  ```powershell
102
- irm https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 | iex
102
+ irm https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 -Headers @{ 'Cache-Control' = 'no-cache' } | iex
103
103
  ```
104
104
 
105
+ If PowerShell reports a parser error at `install.ps1:392` showing the old
106
+ here-string terminator piped to `Write-Host`, you are running a stale
107
+ release/checkout. Update to `main`, or delete and re-download the installer
108
+ from the `main` URL above before running it.
109
+
105
110
  The installer fetches the CLI, drops `docker-compose.yml` into `~/.code-memory/`, starts **FalkorDB** + **Qdrant**, pulls **`bge-m3`**, and wires the **Claude Code** + **OpenCode** plugins. Idempotent — safe to re-run.
106
111
 
107
112
  ### ✅ Verify
@@ -152,7 +157,7 @@ curl -fsSL https://raw.githubusercontent.com/fmflurry/code-memory/main/install.s
152
157
  **Windows** — `iex` doesn't accept args, so download then run:
153
158
 
154
159
  ```powershell
155
- iwr https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 -OutFile install.ps1
160
+ iwr https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 -Headers @{ 'Cache-Control' = 'no-cache' } -OutFile install.ps1
156
161
  ./install.ps1 -NoDocker -NoOllama -NoClaude -NoOpencode -NoMcp
157
162
  ```
158
163
 
@@ -68,6 +68,29 @@ param(
68
68
  )
69
69
 
70
70
  $ErrorActionPreference = 'Stop'
71
+ # PowerShell 7.3+ promotes native-command stderr to a terminating error when
72
+ # $ErrorActionPreference='Stop'. Docker CLI writes benign WARNINGs (e.g. the
73
+ # credential-plugin naming check) to stderr; we gate on $LASTEXITCODE instead,
74
+ # so do not let stderr alone abort the script.
75
+ $PSNativeCommandUseErrorActionPreference = $false
76
+
77
+ # Run a native command whose benign stderr (e.g. Docker CLI credential-plugin
78
+ # warnings) must NOT abort the script. Windows PowerShell 5.1 turns redirected
79
+ # native stderr into terminating NativeCommandError records under
80
+ # $ErrorActionPreference='Stop'; relaxing EAP for the call fixes it on 5.1 and
81
+ # 7+. Callers gate on $LASTEXITCODE. Returns nothing; sets $LASTEXITCODE.
82
+ function Invoke-NativeQuiet {
83
+ param([Parameter(Mandatory)][scriptblock] $Command)
84
+ $prevEAP = $ErrorActionPreference
85
+ $ErrorActionPreference = 'SilentlyContinue'
86
+ try { & $Command 2>&1 | Out-Null } finally { $ErrorActionPreference = $prevEAP }
87
+ }
88
+ function Invoke-NativeVisible {
89
+ param([Parameter(Mandatory)][scriptblock] $Command)
90
+ $prevEAP = $ErrorActionPreference
91
+ $ErrorActionPreference = 'Continue'
92
+ try { & $Command 2>&1 | ForEach-Object { Write-Host $_ } } finally { $ErrorActionPreference = $prevEAP }
93
+ }
71
94
 
72
95
  $RepoUrl = if ($env:CODEMEMORY_REPO_URL) { $env:CODEMEMORY_REPO_URL } else { 'https://github.com/fmflurry/code-memory' }
73
96
  $RawUrl = if ($env:CODEMEMORY_RAW_URL) { $env:CODEMEMORY_RAW_URL } else { 'https://raw.githubusercontent.com/fmflurry/code-memory/main' }
@@ -185,7 +208,7 @@ if ($doDocker) {
185
208
  Step "Starting FalkorDB + Qdrant"
186
209
  if (Wait-ForCmd 'docker' 'Docker Desktop' 'https://www.docker.com/products/docker-desktop') {
187
210
  # ensure daemon up
188
- & docker info *>$null
211
+ Invoke-NativeQuiet { docker info }
189
212
  if ($LASTEXITCODE -ne 0) {
190
213
  Warn "Docker CLI present but daemon not running. Start Docker Desktop."
191
214
  if (Test-Interactive) {
@@ -195,7 +218,7 @@ if ($doDocker) {
195
218
  }
196
219
  }
197
220
  if ($doDocker) {
198
- & docker compose -f (Join-Path $HomeDir 'docker/docker-compose.yml') --project-directory $HomeDir up -d
221
+ Invoke-NativeVisible { docker compose -f (Join-Path $HomeDir 'docker/docker-compose.yml') --project-directory $HomeDir up -d }
199
222
  if ($LASTEXITCODE -ne 0) {
200
223
  Warn "docker compose up failed"
201
224
  } else {
@@ -350,20 +373,21 @@ if ($doOpencode) {
350
373
 
351
374
  # ---------- done ----------
352
375
  Step "Done"
353
- @"
354
-
355
- Side files: $HomeDir\
356
- CLI: $(if ($cliPath) { $cliPath.Source } else { 'code-memory (not on PATH)' })
357
-
358
- Ingest a repo:
359
- code-memory ingest C:\path\to\repo
360
-
361
- Query:
362
- code-memory retrieve "where is the auth middleware?"
363
-
364
- Browse:
365
- FalkorDB http://localhost:3000
366
- Qdrant http://localhost:6333/dashboard
367
-
368
- Edit defaults: $HomeDir\.env
369
- "@ | Write-Host
376
+ $doneLines = @(
377
+ ''
378
+ " Side files: $HomeDir\"
379
+ " CLI: $(if ($cliPath) { $cliPath.Source } else { 'code-memory (not on PATH)' })"
380
+ ''
381
+ ' Ingest a repo:'
382
+ ' code-memory ingest C:\path\to\repo'
383
+ ''
384
+ ' Query:'
385
+ ' code-memory retrieve "where is the auth middleware?"'
386
+ ''
387
+ ' Browse:'
388
+ ' FalkorDB http://localhost:3000'
389
+ ' Qdrant http://localhost:6333/dashboard'
390
+ ''
391
+ " Edit defaults: $HomeDir\.env"
392
+ )
393
+ Write-Host ($doneLines -join [Environment]::NewLine)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "flurryx-code-memory"
7
- version = "0.7.0"
7
+ version = "0.7.6"
8
8
  description = "Local lightweight memory layer for coding agents: FalkorDB + Qdrant + Ollama (BGE-M3) + tree-sitter"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = [
@@ -12,7 +12,7 @@ dependencies = [
12
12
  "qdrant-client>=1.12",
13
13
  "falkordb>=1.0.10",
14
14
  "tree-sitter>=0.23",
15
- "tree-sitter-language-pack>=0.7",
15
+ "tree-sitter-language-pack==1.8.1",
16
16
  "pydantic>=2.8",
17
17
  "typer>=0.12",
18
18
  "rich>=13.7",
@@ -25,6 +25,15 @@
25
25
  metadata indexing (Assembly + Type graph nodes from .dll referenced
26
26
  via .csproj). Skip if no .NET source in repos you ingest.
27
27
 
28
+ .PARAMETER WithHybrid
29
+ Install the [hybrid] extra (FlagEmbedding, ~2 GB torch). Enables in-process
30
+ BGE-M3 dense+sparse hybrid reranking. Heavy — skip unless you need it.
31
+
32
+ .PARAMETER Extras
33
+ Comma list of optional extras to install (e.g. 'dotnet,hybrid'), or 'none'
34
+ to bypass the interactive prompt. Overrides -WithDotnet/-WithHybrid and the
35
+ CODEMEMORY_EXTRAS environment variable.
36
+
28
37
  .PARAMETER Plugins
29
38
  Comma-separated whitelist of harness plugins to install:
30
39
  'opencode', 'claudecode', 'cursor', 'all', or 'none'. Bypasses the
@@ -37,14 +46,22 @@
37
46
  ./.cursor.
38
47
 
39
48
  .PARAMETER ExtrasInteractive
40
- Set to `$false` to skip the interactive extras prompt. The -WithDotnet
41
- switch still applies.
49
+ Set to `$false` to skip the interactive extras prompt entirely. Overridden
50
+ by -Extras, -WithDotnet, -WithHybrid, and the CODEMEMORY_EXTRAS env var.
42
51
 
43
52
  .EXAMPLE
44
53
  ./scripts/install.ps1
45
54
  ./scripts/install.ps1 -NoOllama
46
55
  ./scripts/install.ps1 -WithDotnet -Plugins all
56
+ ./scripts/install.ps1 -WithHybrid
57
+ ./scripts/install.ps1 -Extras dotnet,hybrid
58
+ ./scripts/install.ps1 -Extras none
47
59
  ./scripts/install.ps1 -Plugins claudecode -PluginsScope project
60
+
61
+ .NOTES
62
+ Environment variables:
63
+ CODEMEMORY_EXTRAS=dotnet,hybrid same as -Extras (overrides interactive prompt)
64
+ CODEMEMORY_EXTRAS=none skip extras entirely
48
65
  #>
49
66
 
50
67
  [CmdletBinding()]
@@ -54,6 +71,8 @@ param(
54
71
  [switch]$NoTests,
55
72
  [switch]$NoMcp,
56
73
  [switch]$WithDotnet,
74
+ [switch]$WithHybrid,
75
+ [string]$Extras = '',
57
76
  [string]$Plugins = '',
58
77
  [ValidateSet('global', 'project')]
59
78
  [string]$PluginsScope = 'global',
@@ -61,6 +80,29 @@ param(
61
80
  )
62
81
 
63
82
  $ErrorActionPreference = 'Stop'
83
+ # PowerShell 7.3+ promotes native-command stderr to a terminating error when
84
+ # $ErrorActionPreference='Stop'. Docker CLI writes benign WARNINGs (e.g. the
85
+ # credential-plugin naming check) to stderr; we gate on $LASTEXITCODE instead,
86
+ # so do not let stderr alone abort the script.
87
+ $PSNativeCommandUseErrorActionPreference = $false
88
+
89
+ # Run a native command whose benign stderr (e.g. Docker CLI credential-plugin
90
+ # warnings) must NOT abort the script. Windows PowerShell 5.1 turns redirected
91
+ # native stderr into terminating NativeCommandError records under
92
+ # $ErrorActionPreference='Stop'; relaxing EAP for the call fixes it on 5.1 and
93
+ # 7+. Callers gate on $LASTEXITCODE. Returns nothing; sets $LASTEXITCODE.
94
+ function Invoke-NativeQuiet {
95
+ param([Parameter(Mandatory)][scriptblock] $Command)
96
+ $prevEAP = $ErrorActionPreference
97
+ $ErrorActionPreference = 'SilentlyContinue'
98
+ try { & $Command 2>&1 | Out-Null } finally { $ErrorActionPreference = $prevEAP }
99
+ }
100
+ function Invoke-NativeVisible {
101
+ param([Parameter(Mandatory)][scriptblock] $Command)
102
+ $prevEAP = $ErrorActionPreference
103
+ $ErrorActionPreference = 'Continue'
104
+ try { & $Command 2>&1 | ForEach-Object { Write-Host $_ } } finally { $ErrorActionPreference = $prevEAP }
105
+ }
64
106
 
65
107
  function Step($msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
66
108
  function Ok($msg) { Write-Host "[ok] $msg" -ForegroundColor Green }
@@ -105,7 +147,7 @@ if (-not $pythonBin) { Die "Python 3.11+ not found. Install from https://www.pyt
105
147
 
106
148
  if (-not $NoDocker) {
107
149
  if (-not (Test-Cmd 'docker')) { Die "Docker not found. Install Docker Desktop: https://www.docker.com/." }
108
- & docker compose version *> $null
150
+ Invoke-NativeQuiet { docker compose version }
109
151
  if ($LASTEXITCODE -ne 0) { Die "Docker Compose v2 not available (need 'docker compose')." }
110
152
  Ok "Docker present"
111
153
  }
@@ -172,24 +214,89 @@ Ok "pip upgraded"
172
214
 
173
215
  # ---------- 3. package install ----------
174
216
  # Resolve optional extras up front so we do one pip resolve.
175
- if ($ExtrasInteractive -and -not $WithDotnet) {
176
- $isTty = [Environment]::UserInteractive -and [Console]::IsInputRedirected -eq $false
177
- if ($isTty) {
178
- Step "Optional extras"
179
- Write-Host " [dotnet] .NET DLL metadata indexing (dnfile, ~200 KB)."
180
- Write-Host " Skip if no .csproj / .NET source in repos you ingest."
181
- Write-Host ""
182
- if (Prompt-YesNo "Install [dotnet] extra?" $false) { $WithDotnet = $true }
217
+ #
218
+ # Optional extras keep in sync with EXTRAS registry in updater.py.
219
+ # dotnet: .NET assembly metadata indexing (dnfile, ~200 KB).
220
+ # hybrid: in-process BGE-M3 dense+sparse via FlagEmbedding (~2 GB torch).
221
+ #
222
+ # Priority: -Extras / -WithDotnet / -WithHybrid (CLI) >
223
+ # CODEMEMORY_EXTRAS env var > interactive prompt > skip.
224
+ #
225
+ # $isTty: true when running interactively (not under irm|iex which redirects stdin).
226
+ $isTty = [Environment]::UserInteractive -and -not [Console]::IsInputRedirected
227
+
228
+ $installDotnet = [bool]$WithDotnet
229
+ $installHybrid = [bool]$WithHybrid
230
+
231
+ # Fold legacy switches into -Extras when -Extras is not already set.
232
+ if ([string]::IsNullOrWhiteSpace($Extras)) {
233
+ $legacyParts = @()
234
+ if ($WithDotnet) { $legacyParts += 'dotnet' }
235
+ if ($WithHybrid) { $legacyParts += 'hybrid' }
236
+ if ($legacyParts.Count -gt 0) { $Extras = $legacyParts -join ',' }
237
+ }
238
+
239
+ # Determine effective source.
240
+ $effectiveExtras = $Extras
241
+ if ([string]::IsNullOrWhiteSpace($effectiveExtras)) {
242
+ $envExtras = [System.Environment]::GetEnvironmentVariable('CODEMEMORY_EXTRAS')
243
+ if (-not [string]::IsNullOrWhiteSpace($envExtras)) {
244
+ $effectiveExtras = $envExtras.Trim()
183
245
  }
184
246
  }
185
247
 
186
- $extras = @('dev')
187
- if ($WithDotnet) { $extras += 'dotnet' }
188
- $extrasJoined = ($extras -join ',')
248
+ if (-not [string]::IsNullOrWhiteSpace($effectiveExtras)) {
249
+ # Flag/env path parse comma list.
250
+ if ($effectiveExtras -ieq 'none') {
251
+ $installDotnet = $false
252
+ $installHybrid = $false
253
+ } else {
254
+ foreach ($ep in $effectiveExtras.Split(',')) {
255
+ switch ($ep.Trim().ToLower()) {
256
+ 'dotnet' { $installDotnet = $true }
257
+ 'hybrid' { $installHybrid = $true }
258
+ '' { }
259
+ default { Warn "unknown extra '$($ep.Trim())' (known: dotnet, hybrid) — skipped" }
260
+ }
261
+ }
262
+ }
263
+ } elseif ($ExtrasInteractive -and $isTty) {
264
+ # Interactive TTY path.
265
+ Step "Optional extras"
266
+ # Keep descriptions in sync with updater.py EXTRAS registry.
267
+ Write-Host " [dotnet] .NET assembly metadata indexing (dnfile, ~200 KB)."
268
+ Write-Host " Skip if no .csproj / .NET source in repos you ingest."
269
+ Write-Host ""
270
+ Write-Host " [hybrid] In-process BGE-M3 dense+sparse via FlagEmbedding."
271
+ Write-Host " Heavy — pulls torch (~2 GB). Skip unless you need hybrid reranking."
272
+ Write-Host ""
273
+ if (Prompt-YesNo "Install [dotnet] extra?" $false) { $installDotnet = $true }
274
+ if (Prompt-YesNo "Install [hybrid] extra?" $false) { $installHybrid = $true }
275
+ } else {
276
+ # Non-interactive, no env override — dim hint only, no install.
277
+ Dim "hint: optional extras not installed. Re-run with -Extras dotnet,hybrid or set CODEMEMORY_EXTRAS=dotnet,hybrid."
278
+ }
279
+
280
+ $extrasBase = @('dev')
281
+ if ($installDotnet) { $extrasBase += 'dotnet' }
282
+ if ($installHybrid) { $extrasBase += 'hybrid' }
283
+ $extrasJoined = ($extrasBase -join ',')
189
284
 
190
285
  Step "Installing code-memory (editable, extras: $extrasJoined)"
191
- & pip install -e ".[$extrasJoined]"
286
+ # Base [dev] is hard-fail. Optional extras are non-fatal — a missing build
287
+ # dependency (e.g. torch wheel unavailable) must not abort the whole install.
288
+ & pip install -e ".[dev]"
192
289
  if ($LASTEXITCODE -ne 0) { Die "pip install failed" }
290
+ if ($installDotnet -or $installHybrid) {
291
+ $optionalParts = @()
292
+ if ($installDotnet) { $optionalParts += 'dotnet' }
293
+ if ($installHybrid) { $optionalParts += 'hybrid' }
294
+ $optionalJoined = $optionalParts -join ','
295
+ & pip install -e ".[dev,$optionalJoined]"
296
+ if ($LASTEXITCODE -ne 0) {
297
+ Warn "optional extras install failed (dev install succeeded; re-run: pip install -e '.[$optionalJoined]')"
298
+ }
299
+ }
193
300
  Ok "code-memory installed"
194
301
 
195
302
  # ---------- 4. .env ----------
@@ -218,7 +325,7 @@ if (-not $NoDocker) {
218
325
  & docker compose -p $CmProject -f docker/docker-compose.yml up -d --remove-orphans
219
326
  if ($LASTEXITCODE -ne 0) {
220
327
  Warn "compose up hit a container-name conflict — removing stale cm-* containers and retrying (named volumes persist)"
221
- & docker rm -f cm-falkordb cm-qdrant cm-tei *> $null
328
+ Invoke-NativeQuiet { docker rm -f cm-falkordb cm-qdrant cm-tei }
222
329
  & docker compose -p $CmProject -f docker/docker-compose.yml up -d --remove-orphans
223
330
  if ($LASTEXITCODE -ne 0) { Die "docker compose up failed" }
224
331
  }
@@ -234,7 +341,7 @@ if (-not $NoOllama) {
234
341
  Step "Pulling embedding model (bge-m3)"
235
342
 
236
343
  $daemonReady = $false
237
- & ollama list *> $null
344
+ Invoke-NativeQuiet { ollama list }
238
345
  if ($LASTEXITCODE -eq 0) { $daemonReady = $true }
239
346
 
240
347
  if (-not $daemonReady) {
@@ -246,7 +353,7 @@ if (-not $NoOllama) {
246
353
 
247
354
  for ($i = 0; $i -lt 30; $i++) {
248
355
  Start-Sleep -Seconds 1
249
- & ollama list *> $null
356
+ Invoke-NativeQuiet { ollama list }
250
357
  if ($LASTEXITCODE -eq 0) { $daemonReady = $true; break }
251
358
  }
252
359
  }
@@ -380,19 +487,20 @@ if (-not $installOpencode -and -not $installClaudecode -and -not $installCursor
380
487
 
381
488
  # ---------- done ----------
382
489
  Step "Done"
383
- @"
384
-
385
- Activate the virtualenv:
386
- . .venv\Scripts\Activate.ps1
387
-
388
- Ingest a repo:
389
- code-memory ingest C:\path\to\repo
390
-
391
- Query memory:
392
- code-memory retrieve "where is the auth middleware?"
393
-
394
- Browse:
395
- FalkorDB http://localhost:3000
396
- Qdrant http://localhost:6333/dashboard
397
-
398
- "@ | Write-Host
490
+ $doneLines = @(
491
+ ''
492
+ ' Activate the virtualenv:'
493
+ ' . .venv\Scripts\Activate.ps1'
494
+ ''
495
+ ' Ingest a repo:'
496
+ ' code-memory ingest C:\path\to\repo'
497
+ ''
498
+ ' Query memory:'
499
+ ' code-memory retrieve "where is the auth middleware?"'
500
+ ''
501
+ ' Browse:'
502
+ ' FalkorDB http://localhost:3000'
503
+ ' Qdrant http://localhost:6333/dashboard'
504
+ ''
505
+ )
506
+ Write-Host ($doneLines -join [Environment]::NewLine)
@@ -10,6 +10,9 @@
10
10
  # ./scripts/install.sh --with-claims # also pull gemma2:9b for Graphiti-style
11
11
  # # user-claim extraction (~5.4 GB)
12
12
  # ./scripts/install.sh --with-dotnet # install [dotnet] extra (dnfile, ~200 KB; .NET DLL metadata indexing)
13
+ # ./scripts/install.sh --with-hybrid # install [hybrid] extra (FlagEmbedding; ~2 GB torch)
14
+ # ./scripts/install.sh --extras=dotnet,hybrid
15
+ # # install named extras (comma list)
13
16
  # ./scripts/install.sh --extras=none # bypass interactive prompt; install only [dev]
14
17
  # ./scripts/install.sh --plugins=opencode,claudecode,cursor
15
18
  # # install named harness plugins (non-interactive)
@@ -21,6 +24,10 @@
21
24
  # # default scope is global (~/.config/opencode,
22
25
  # # ~/.claude, ~/.cursor)
23
26
  #
27
+ # Environment variables:
28
+ # CODEMEMORY_EXTRAS=dotnet,hybrid # same as --extras=... (overrides interactive prompt)
29
+ # CODEMEMORY_EXTRAS=none # skip extras entirely
30
+ #
24
31
  set -euo pipefail
25
32
 
26
33
  # ---------- helpers ----------
@@ -48,8 +55,11 @@ SKIP_OLLAMA=0
48
55
  SKIP_TESTS=0
49
56
  SKIP_MCP=0
50
57
  WITH_DOTNET=0
58
+ WITH_HYBRID=0
51
59
  WITH_CLAIMS=0
52
- EXTRAS_ARG="" # empty = interactive; "none" = skip extras prompt; other ignored
60
+ # EXTRAS_ARG: CLI value of --extras=... (overrides CODEMEMORY_EXTRAS env and interactive).
61
+ # Empty means "not set by CLI"; "none" means skip; comma list means install those extras.
62
+ EXTRAS_ARG=""
53
63
  PLUGINS_ARG="" # empty = interactive; explicit value bypasses prompt
54
64
  PLUGINS_SCOPE="global" # global | project
55
65
  for arg in "$@"; do
@@ -58,13 +68,14 @@ for arg in "$@"; do
58
68
  --no-ollama) SKIP_OLLAMA=1 ;;
59
69
  --no-tests) SKIP_TESTS=1 ;;
60
70
  --no-mcp) SKIP_MCP=1 ;;
61
- --with-dotnet) WITH_DOTNET=1 ;;
62
- --with-claims) WITH_CLAIMS=1 ;;
71
+ --with-dotnet) WITH_DOTNET=1 ;;
72
+ --with-hybrid) WITH_HYBRID=1 ;;
73
+ --with-claims) WITH_CLAIMS=1 ;;
63
74
  --extras=*) EXTRAS_ARG="${arg#--extras=}" ;;
64
75
  --plugins=*) PLUGINS_ARG="${arg#--plugins=}" ;;
65
76
  --plugins-scope=*) PLUGINS_SCOPE="${arg#--plugins-scope=}" ;;
66
77
  -h|--help)
67
- sed -n '1,22p' "$0"; exit 0 ;;
78
+ sed -n '1,29p' "$0"; exit 0 ;;
68
79
  *) die "unknown flag: $arg" ;;
69
80
  esac
70
81
  done
@@ -190,22 +201,95 @@ prompt_yes_no() {
190
201
  [ "$ans" = "y" ] || [ "$ans" = "yes" ]
191
202
  }
192
203
 
193
- if [ -z "$EXTRAS_ARG" ] && [ "$WITH_DOTNET" -eq 0 ]; then
194
- # Only interactive if stdin/stdout are a TTY.
195
- if [ -t 0 ] && [ -t 1 ]; then
196
- step "Optional extras"
197
- echo " [dotnet] .NET DLL metadata indexing (dnfile, ~200 KB)."
198
- echo " Skip if no .csproj / .NET source in repos you ingest."
199
- echo
200
- if prompt_yes_no "Install [dotnet] extra?" "n"; then WITH_DOTNET=1; fi
204
+ # ---------- extras resolution (contract mirrors updater.py / install.ps1) ----------
205
+ # Optional extras in pyproject.toml keep in sync with EXTRAS registry in updater.py.
206
+ # dotnet: .NET assembly metadata indexing (dnfile, ~200 KB).
207
+ # hybrid: in-process BGE-M3 dense+sparse via FlagEmbedding (~2 GB torch).
208
+ #
209
+ # Priority: CLI flag (--extras= / --with-dotnet / --with-hybrid) >
210
+ # CODEMEMORY_EXTRAS env var > interactive prompt > skip.
211
+ #
212
+ # TTY_OK = true when we can safely prompt:
213
+ # - Both stdin+stdout are a real TTY, OR /dev/tty is readable as a fallback
214
+ # (handles curl|bash where fd 0 is the pipe but /dev/tty is the terminal).
215
+ TTY_OK=0
216
+ if [ -t 0 ] && [ -t 1 ]; then
217
+ TTY_OK=1
218
+ elif [ -r /dev/tty ]; then
219
+ TTY_OK=1
220
+ fi
221
+
222
+ # Build the effective extras list.
223
+ # We accumulate into INSTALL_DOTNET / INSTALL_HYBRID, then build the pip string.
224
+ INSTALL_DOTNET=0
225
+ INSTALL_HYBRID=0
226
+
227
+ # Fold legacy --with-dotnet / --with-hybrid into the generic flag path.
228
+ [ "$WITH_DOTNET" -eq 1 ] && EXTRAS_ARG="${EXTRAS_ARG:-dotnet}"
229
+ [ "$WITH_HYBRID" -eq 1 ] && {
230
+ if [ -n "$EXTRAS_ARG" ] && [ "$EXTRAS_ARG" != "none" ]; then
231
+ EXTRAS_ARG="${EXTRAS_ARG},hybrid"
232
+ elif [ -z "$EXTRAS_ARG" ]; then
233
+ EXTRAS_ARG="hybrid"
234
+ fi
235
+ }
236
+
237
+ # Determine effective source of extras selection.
238
+ EFFECTIVE_EXTRAS=""
239
+ if [ -n "$EXTRAS_ARG" ]; then
240
+ EFFECTIVE_EXTRAS="$EXTRAS_ARG"
241
+ elif [ -n "${CODEMEMORY_EXTRAS:-}" ]; then
242
+ EFFECTIVE_EXTRAS="$CODEMEMORY_EXTRAS"
243
+ fi
244
+
245
+ if [ -n "$EFFECTIVE_EXTRAS" ]; then
246
+ # env/flag path — parse comma list.
247
+ if [ "$EFFECTIVE_EXTRAS" = "none" ]; then
248
+ : # install nothing extra
249
+ else
250
+ IFS=',' read -r -a _extras_parts <<< "$EFFECTIVE_EXTRAS"
251
+ for _ep in "${_extras_parts[@]}"; do
252
+ _ep="$(printf '%s' "$_ep" | tr -d '[:space:]')"
253
+ case "$_ep" in
254
+ dotnet) INSTALL_DOTNET=1 ;;
255
+ hybrid) INSTALL_HYBRID=1 ;;
256
+ "") ;;
257
+ *) warn "unknown extra '$_ep' (known: dotnet, hybrid) — skipped" ;;
258
+ esac
259
+ done
201
260
  fi
261
+ elif [ "$TTY_OK" -eq 1 ]; then
262
+ # Interactive path.
263
+ step "Optional extras"
264
+ # Keep descriptions in sync with updater.py EXTRAS registry.
265
+ echo " [dotnet] .NET assembly metadata indexing (dnfile, ~200 KB)."
266
+ echo " Skip if no .csproj / .NET source in repos you ingest."
267
+ echo
268
+ echo " [hybrid] In-process BGE-M3 dense+sparse via FlagEmbedding."
269
+ echo " Heavy — pulls torch (~2 GB). Skip unless you need hybrid reranking."
270
+ echo
271
+ if prompt_yes_no "Install [dotnet] extra?" "n"; then INSTALL_DOTNET=1; fi
272
+ if prompt_yes_no "Install [hybrid] extra?" "n"; then INSTALL_HYBRID=1; fi
273
+ else
274
+ # Non-interactive, no env override — skip silently with a dim hint.
275
+ printf "${DIM} hint: optional extras not installed. Re-run with --extras=dotnet,hybrid or set CODEMEMORY_EXTRAS=dotnet,hybrid.${RST}\n"
202
276
  fi
203
277
 
204
278
  EXTRAS="dev"
205
- [ "$WITH_DOTNET" -eq 1 ] && EXTRAS="${EXTRAS},dotnet"
279
+ [ "$INSTALL_DOTNET" -eq 1 ] && EXTRAS="${EXTRAS},dotnet"
280
+ [ "$INSTALL_HYBRID" -eq 1 ] && EXTRAS="${EXTRAS},hybrid"
206
281
 
207
282
  step "Installing code-memory (editable, extras: $EXTRAS)"
208
- pip install -e ".[${EXTRAS}]"
283
+ # The base [dev] install is hard-fail; optional extras are non-fatal so a
284
+ # missing build dependency (e.g. torch wheel not available) does not abort
285
+ # the whole install under set -e.
286
+ pip install -e ".[dev]"
287
+ if [ "$INSTALL_DOTNET" -eq 1 ] || [ "$INSTALL_HYBRID" -eq 1 ]; then
288
+ _optional_extras="${EXTRAS#dev}"
289
+ _optional_extras="${_optional_extras#,}"
290
+ pip install -e ".[dev,${_optional_extras}]" \
291
+ || warn "optional extras install failed (dev install succeeded; re-run: pip install -e '.[${_optional_extras}]')"
292
+ fi
209
293
  ok "code-memory installed"
210
294
 
211
295
  # ---------- 4. .env ----------
@@ -0,0 +1,32 @@
1
+ """Console encoding utilities.
2
+
3
+ Ensures stdout/stderr are safe on non-UTF-8 consoles (e.g. Windows cp1252).
4
+ Must be imported with zero heavy dependencies so it can be called at the
5
+ earliest point of every CLI entry point.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import sys
11
+
12
+
13
+ def _force_utf8_console() -> None:
14
+ """Reconfigure stdout and stderr to UTF-8 with errors='replace'.
15
+
16
+ On Windows the console inherits the active code page (often cp1252 / cp850).
17
+ Python's ``TextIOWrapper.reconfigure`` switches to UTF-8 while keeping the
18
+ same underlying buffer, so Unicode decoration chars (→ • ✓ —) render
19
+ correctly on a real Windows console (Python uses the Unicode console API)
20
+ and degrade to ``?`` when redirected to a cp1252 pipe — never a crash.
21
+
22
+ The ``getattr`` guard + bare ``except Exception`` make this a safe no-op
23
+ on stream types that lack ``reconfigure`` (e.g. pytest's ``CaptureFixture``
24
+ or ``io.StringIO``).
25
+ """
26
+ for stream in (sys.stdout, sys.stderr):
27
+ reconfigure = getattr(stream, "reconfigure", None)
28
+ if reconfigure is not None:
29
+ try:
30
+ reconfigure(encoding="utf-8", errors="replace")
31
+ except Exception: # noqa: BLE001
32
+ pass