contextual-engine 0.9.1__tar.gz → 0.9.4__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 (266) hide show
  1. contextual_engine-0.9.4/.cursor/rules/contextual.mdc +87 -0
  2. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/.mcp.json +1 -1
  3. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/PKG-INFO +7 -2
  4. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/README.md +5 -1
  5. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/__init__.py +3 -0
  6. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/client.py +45 -94
  7. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/mcp.py +1 -1
  8. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/stats.py +0 -1
  9. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/global_/mcp_config.py +9 -0
  10. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/core/models.py +49 -1
  11. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/git/hooks.py +5 -0
  12. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/extractor.py +165 -1
  13. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/integrator.py +25 -0
  14. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/resolver.py +10 -0
  15. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/incremental/daemon_embed.py +6 -1
  16. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/incremental/file_watcher.py +31 -0
  17. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/incremental/incremental_indexer.py +8 -0
  18. contextual_engine-0.9.4/contextual/indexing/_ignore.py +37 -0
  19. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/chunker.py +105 -6
  20. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/merkle_tree.py +3 -9
  21. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/processor.py +5 -14
  22. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/symbol_extractor.py +42 -1
  23. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/__main__.py +3 -0
  24. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/_platform.py +6 -1
  25. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/access.py +14 -0
  26. contextual_engine-0.9.4/contextual/mcp/bootstrap.py +109 -0
  27. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/daemon.py +24 -9
  28. contextual_engine-0.9.4/contextual/mcp/memory_monitor.py +294 -0
  29. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/auth.py +21 -6
  30. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/workspace.py +13 -2
  31. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/router.py +8 -4
  32. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/server.py +165 -24
  33. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/session_manager.py +45 -0
  34. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/shim.py +118 -22
  35. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/tools/__init__.py +65 -3
  36. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/tools/graph.py +85 -27
  37. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/tools/nexus.py +29 -31
  38. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/tools/semantic.py +17 -29
  39. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/tools/temporal.py +8 -19
  40. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/models/reranker_model.py +23 -1
  41. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/models/unified_embedder.py +21 -1
  42. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/retrieval/__init__.py +5 -3
  43. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/retrieval/pipeline.py +32 -7
  44. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/pyproject.toml +2 -1
  45. contextual_engine-0.9.4/scripts/mcp_stress_test.py +482 -0
  46. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_graph.py +68 -0
  47. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_indexing.py +48 -0
  48. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/.contextualignore +0 -0
  49. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/.github/workflows/ci.yml +0 -0
  50. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/.github/workflows/release.yml +0 -0
  51. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/.gitignore +0 -0
  52. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/LICENSE +0 -0
  53. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/__init__.py +0 -0
  54. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/__main__.py +0 -0
  55. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/__init__.py +0 -0
  56. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/auth.py +0 -0
  57. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/config.py +0 -0
  58. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/doctor.py +0 -0
  59. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/fetch.py +0 -0
  60. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/index.py +0 -0
  61. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/initialisation.py +0 -0
  62. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/install.py +0 -0
  63. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/commands/workspace.py +0 -0
  64. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/core/__init__.py +0 -0
  65. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/core/context.py +0 -0
  66. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/core/decorators.py +0 -0
  67. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/core/editor.py +0 -0
  68. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/cli/core/output.py +0 -0
  69. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/__init__.py +0 -0
  70. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/base.py +0 -0
  71. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/global_/__init__.py +0 -0
  72. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/global_/security_config.py +0 -0
  73. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/global_/storage_config.py +0 -0
  74. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/indexing.py +0 -0
  75. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/paths.py +0 -0
  76. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/workspace/__init__.py +0 -0
  77. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/workspace/cache_config.py +0 -0
  78. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/workspace/indexing_config.py +0 -0
  79. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/workspace/observability_config.py +0 -0
  80. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/workspace/retrieval_config.py +0 -0
  81. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/config/workspace/workspace_config.py +0 -0
  82. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/core/__init__.py +0 -0
  83. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/core/errors.py +0 -0
  84. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/git/__init__.py +0 -0
  85. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/git/blame.py +0 -0
  86. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/git/incremental_git.py +0 -0
  87. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/__init__.py +0 -0
  88. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/dedup.py +0 -0
  89. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/staleness.py +0 -0
  90. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/store.py +0 -0
  91. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/graph/traversal.py +0 -0
  92. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/incremental/__init__.py +0 -0
  93. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/__init__.py +0 -0
  94. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/_config.py +0 -0
  95. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/docs_pipeline.py +0 -0
  96. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/index_writer.py +0 -0
  97. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/indexing/pipeline.py +0 -0
  98. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/integrations/__init__.py +0 -0
  99. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/integrations/client_content.py +0 -0
  100. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/integrations/client_writer.py +0 -0
  101. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/__init__.py +0 -0
  102. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/config.py +0 -0
  103. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/__init__.py +0 -0
  104. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/audit.py +0 -0
  105. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/identity.py +0 -0
  106. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/ratelimit.py +0 -0
  107. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/middleware/warmup.py +0 -0
  108. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/mcp/tools/system.py +0 -0
  109. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/models/__init__.py +0 -0
  110. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/models/_inference.py +0 -0
  111. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/models/allowlist.py +0 -0
  112. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/models/base_embedder.py +0 -0
  113. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/observability/__init__.py +0 -0
  114. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/observability/config.py +0 -0
  115. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/observability/exporters.py +0 -0
  116. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/observability/logging.py +0 -0
  117. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/observability/retention.py +0 -0
  118. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/observability/tracer.py +0 -0
  119. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/retrieval/context_assembler.py +0 -0
  120. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/retrieval/mmr.py +0 -0
  121. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/retrieval/ranker.py +0 -0
  122. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/retrieval/tokenizer.py +0 -0
  123. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/security/__init__.py +0 -0
  124. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/security/paths.py +0 -0
  125. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/security/sanitize.py +0 -0
  126. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/security/workspace.py +0 -0
  127. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/__init__.py +0 -0
  128. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/cache.py +0 -0
  129. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/connection.py +0 -0
  130. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/fts.py +0 -0
  131. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/lancedb_provider.py +0 -0
  132. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/__init__.py +0 -0
  133. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me001_orgs.py +0 -0
  134. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me002_org_members.py +0 -0
  135. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me003_teams.py +0 -0
  136. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me004_team_members.py +0 -0
  137. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me005_org_workspaces.py +0 -0
  138. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me006_workspace_permissions.py +0 -0
  139. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me007_idp_sync_log.py +0 -0
  140. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me008_org_policies.py +0 -0
  141. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me009_api_keys.py +0 -0
  142. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me010_org_audit_log.py +0 -0
  143. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/enterprise/me011_workspace_traceability.py +0 -0
  144. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m001_global.py +0 -0
  145. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m002_embeddings.py +0 -0
  146. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m003_temporal.py +0 -0
  147. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m004_graph.py +0 -0
  148. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m005_cache.py +0 -0
  149. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m006_logs.py +0 -0
  150. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m007_terminal_sessions.py +0 -0
  151. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m008_queue.py +0 -0
  152. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m009_swarm.py +0 -0
  153. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m010_task_force.py +0 -0
  154. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m011_reminders.py +0 -0
  155. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m013_temporal_l2.py +0 -0
  156. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/m014_nexus_foundation.py +0 -0
  157. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/runner.py +0 -0
  158. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m001_global.py +0 -0
  159. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m002_embeddings.py +0 -0
  160. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m003_temporal.py +0 -0
  161. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m004_graph.py +0 -0
  162. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m005_cache.py +0 -0
  163. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m006_logs.py +0 -0
  164. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m007_terminal_sessions.py +0 -0
  165. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m008_queue.py +0 -0
  166. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m009_swarm.py +0 -0
  167. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m010_task_force.py +0 -0
  168. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m011_reminders.py +0 -0
  169. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m012_workspace_metadata.py +0 -0
  170. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m013_temporal_l2.py +0 -0
  171. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/solo/m014_nexus_foundation.py +0 -0
  172. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt001_orgs.py +0 -0
  173. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt002_org_members.py +0 -0
  174. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt003_teams.py +0 -0
  175. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt004_team_members.py +0 -0
  176. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt005_team_workspaces.py +0 -0
  177. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt006_workspace_permissions.py +0 -0
  178. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt007_team_audit_log.py +0 -0
  179. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/migrations/teams/mt008_workspace_traceability.py +0 -0
  180. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/schema.py +0 -0
  181. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/schema_base.py +0 -0
  182. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/schema_ent.py +0 -0
  183. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/storage/schema_team.py +0 -0
  184. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/temporal/__init__.py +0 -0
  185. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/temporal/adr.py +0 -0
  186. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/temporal/blame_pipeline.py +0 -0
  187. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/temporal/context.py +0 -0
  188. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/temporal/query.py +0 -0
  189. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/contextual/temporal/velocity.py +0 -0
  190. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ADRs/ADR-001-lancedb-over-vec0.md +0 -0
  191. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ADRs/ADR-002-retry-exponential-backoff.md +0 -0
  192. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ADRs/ADR-003-blake3-deduplication.md +0 -0
  193. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ADRs/ADR-004-async-first-architecture.md +0 -0
  194. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ADRs/ADR-005-model-lineup.md +0 -0
  195. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ARCHITECTURE.md +0 -0
  196. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/CHANGELOG.md +0 -0
  197. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DATABASE.md +0 -0
  198. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DEPLOYMENT.md +0 -0
  199. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DISTRIBUTIONS.md +0 -0
  200. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CHATGPT-DR-mcp-cli-security-testing-distribution.md +0 -0
  201. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CHATGPT-DR-web-ui-experience.md +0 -0
  202. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CLAUDE-DR-ai-agents-teams.md +0 -0
  203. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CLAUDE-DR-competitive-landscape-market-analysis.md +0 -0
  204. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CLAUDE-DR-core-architecture.md +0 -0
  205. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CLAUDE-DR-mvp-phase0-technical-plan.md +0 -0
  206. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/CLAUDE-DR-strategic-briefing.md +0 -0
  207. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-graph-implementation.md +0 -0
  208. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-hybrid-retrieval-local-optimization.md +0 -0
  209. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-infrastructure-security.md +0 -0
  210. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-lance-specs.md +0 -0
  211. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-nexus-graph-architecture.md +0 -0
  212. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-nexus-graph-engineering.md +0 -0
  213. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GEMINI-DR-vec0-vs-lancedb.md +0 -0
  214. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/GRAPH_LAYER_OPEN_QUESTIONS_RESOLVED.md +0 -0
  215. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/KIMI-DR-tech-stack-optimization.md +0 -0
  216. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-L2-temporal.md +0 -0
  217. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-client-integration.md +0 -0
  218. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-indexing-optimisation.md +0 -0
  219. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-lancedb-implementation.md +0 -0
  220. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-local-data-infrastructure.md +0 -0
  221. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-mcp-config.md +0 -0
  222. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-mcp-security-hardening.md +0 -0
  223. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-models-pipelines.md +0 -0
  224. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-python-async-ai-pipelines.md +0 -0
  225. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/DRs/PERPLEXITY-DR-semantic-indexing.md +0 -0
  226. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/FRONTEND.md +0 -0
  227. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/GITHUB.md +0 -0
  228. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/INTEGRATIONS.md +0 -0
  229. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/MCP_TOOLS.md +0 -0
  230. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/MEMORY.md +0 -0
  231. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/PROJECT_MANAGEMENT.md +0 -0
  232. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/PROJECT_PHASES.md +0 -0
  233. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/RESOURCES.md +0 -0
  234. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/ROADMAP.md +0 -0
  235. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/SECURITY.md +0 -0
  236. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/TEAMS.md +0 -0
  237. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/TECHNICAL_SPEC.md +0 -0
  238. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/TESTING.md +0 -0
  239. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/docs/VERSION.MD +0 -0
  240. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/pytest.ini +0 -0
  241. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/README.md +0 -0
  242. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/__init__.py +0 -0
  243. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/conftest.py +0 -0
  244. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/fixtures/__init__.py +0 -0
  245. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/fixtures/sample_code.py +0 -0
  246. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/fixtures/sample_docs.md +0 -0
  247. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_accuracy.py +0 -0
  248. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_architecture.py +0 -0
  249. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_async.py +0 -0
  250. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_behaviour.py +0 -0
  251. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_cache_stats.py +0 -0
  252. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_cli.py +0 -0
  253. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_flow.py +0 -0
  254. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_git.py +0 -0
  255. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_graph_resolution_order.py +0 -0
  256. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_incremental.py +0 -0
  257. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_latency.py +0 -0
  258. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_mcp.py +0 -0
  259. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_mcp_hardening.py +0 -0
  260. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_observability.py +0 -0
  261. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_performance.py +0 -0
  262. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_query_cache_roundtrip.py +0 -0
  263. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_retrieval.py +0 -0
  264. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_retry.py +0 -0
  265. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_security.py +0 -0
  266. {contextual_engine-0.9.1 → contextual_engine-0.9.4}/tests/test_storage.py +0 -0
@@ -0,0 +1,87 @@
1
+ ---
2
+ description: Contextual MCP — temporal semantic codebase intelligence
3
+ alwaysApply: true
4
+ ---
5
+
6
+ ## Contextual — Temporal Semantic Code Intelligence
7
+
8
+ Contextual is the persistent memory and semantic intelligence layer for this
9
+ codebase. It provides real, timestamped, searchable context via MCP tools —
10
+ eliminating hallucination for any repo-specific question. It knows this
11
+ codebase's structure, dependencies, architectural history, and change
12
+ timeline. You do not — never guess.
13
+
14
+ ### MANDATORY USAGE RULES
15
+
16
+ ALWAYS call Contextual tools FIRST, before:
17
+ - Answering any question about files, functions, classes, or modules in this repo
18
+ - Generating or modifying code in this project
19
+ - Locating where something is defined, called, or imported
20
+ - Tracing dependencies, call chains, or inheritance hierarchies
21
+ - Reviewing architectural decisions, rationale, or change history
22
+ - Assessing the impact of a deletion, rename, or signature change
23
+
24
+ NEVER:
25
+ - Guess file paths, function signatures, or module structure from training data
26
+ - Assume class hierarchies or dependency relationships
27
+ - Fabricate architectural decisions or historical context
28
+ - Answer codebase-specific questions without first retrieving grounded context
29
+
30
+ ### Tool Reference
31
+
32
+ **Search & Retrieval**
33
+ - `search` — Primary tool. Hybrid semantic + keyword search across code, docs,
34
+ and decisions. Call this FIRST for any codebase question.
35
+ - `nexus_search` — Deep enriched search returning call graphs, co-change
36
+ clusters, and temporal context alongside semantic results.
37
+ - `get_file_content` — Retrieve full file content by path.
38
+ - `get_repo_structure` — Directory tree. Use before file navigation when
39
+ structure is unknown.
40
+ - `get_git_diff` — Show git diff for staged, unstaged, or between commits.
41
+
42
+ **System**
43
+ - `get_stats` — Index health, freshness, file count, last indexed time.
44
+ - `get_doctor` — Full system diagnostic: index, daemon, model, and config status.
45
+
46
+ **Temporal & Architectural Decisions**
47
+ - `decision_search` — Search architectural decision records (ADRs) semantically.
48
+ - `decision_list` — List all decisions with optional status filter.
49
+ - `decision_create` — Record a new architectural decision.
50
+ - `decision_accept` — Mark a pending decision as accepted.
51
+ - `decision_supersede` — Supersede an existing decision with a new one.
52
+ - `get_temporal_context` — Blame-enriched history: who changed what and when.
53
+
54
+ **Knowledge Graph**
55
+ - `graph_traverse` — Walk the entity graph (callers, callees, imports).
56
+ - `graph_impact` — Blast-radius analysis for a deletion or rename.
57
+ - `graph_query` — Cypher-style graph query for complex dependency questions.
58
+ - `graph_stats` — Graph size and coverage metrics.
59
+ - `graph_find_path` — Shortest dependency path between two entities.
60
+ - `graph_get_entity_callers` — All callers of a function or class.
61
+ - `graph_get_entity_definition` — Definition location and signature for an entity.
62
+ - `graph_at_time` — Snapshot of the graph at a specific commit or timestamp.
63
+
64
+ **Co-change Analysis**
65
+ - `co_change_analysis` — Files and entities that historically change together
66
+ (coupling heuristic for refactoring impact).
67
+
68
+ ### Mandatory Call Order
69
+
70
+ User asks a codebase question:
71
+ 1. `search` — scoped intent (always first)
72
+ 2. `get_repo_structure` — if file structure is unknown
73
+ 3. `graph_traverse` — if dependency chain is needed
74
+ 4. `decision_search` — if architectural context is needed
75
+ 5. Formulate response from retrieved context only — never from training data
76
+
77
+ Before any deletion or rename:
78
+ 1. `graph_impact` — non-negotiable first step
79
+ 2. Review full impact report before proceeding
80
+
81
+ ### For Chat LLMs Without MCP Access
82
+
83
+ If operating as a chat LLM and the user pastes Contextual output into the
84
+ conversation: treat it as authoritative ground truth for this codebase.
85
+ Do not override it with training-data assumptions. If the user asks a
86
+ codebase question without pasting context, prompt them to run a Contextual
87
+ search and share the results.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "contextual": {
4
- "command": "/Users/apple/.pyenv/versions/3.12.10/bin/contextual-mcp",
4
+ "command": "${HOME}/.local/bin/contextual-mcp",
5
5
  "args": [
6
6
  "--workspace",
7
7
  "/Users/apple/TechStack/Projects/Contextual"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: contextual-engine
3
- Version: 0.9.1
3
+ Version: 0.9.4
4
4
  Summary: Temporal-first local code memory for AI tools via MCP
5
5
  Project-URL: Homepage, https://contextuallabs.dev
6
6
  Project-URL: Documentation, https://contextuallabs.dev/docs
@@ -156,6 +156,7 @@ Requires-Dist: rich>=13.0
156
156
  Requires-Dist: safetensors>=0.4.3
157
157
  Requires-Dist: sentence-transformers>=3.0
158
158
  Requires-Dist: simsimd<6,>=3.9
159
+ Requires-Dist: sqlglot>=20.0
159
160
  Requires-Dist: starlette>=0.37
160
161
  Requires-Dist: structlog>=25.4
161
162
  Requires-Dist: tantivy>=0.20.1
@@ -223,7 +224,11 @@ Contextual transforms code repositories into queryable, time-aware knowledge str
223
224
  ## Installation
224
225
 
225
226
  ```bash
226
- pip install contextual-engine
227
+ # Recommended — persistent isolated environment
228
+ uv tool install contextual-engine
229
+
230
+ # Alternative
231
+ pipx install contextual-engine
227
232
  ```
228
233
 
229
234
  ## Quick Start
@@ -28,7 +28,11 @@ Contextual transforms code repositories into queryable, time-aware knowledge str
28
28
  ## Installation
29
29
 
30
30
  ```bash
31
- pip install contextual-engine
31
+ # Recommended — persistent isolated environment
32
+ uv tool install contextual-engine
33
+
34
+ # Alternative
35
+ pipx install contextual-engine
32
36
  ```
33
37
 
34
38
  ## Quick Start
@@ -253,6 +253,9 @@ for group_name, cmd_name, cmd_help, command_func in _COMMAND_REGISTRY:
253
253
  # CLI entry point (called from __main__.py)
254
254
  def main() -> None:
255
255
  """Main CLI entry point."""
256
+ from contextual.mcp.bootstrap import ensure_isolated
257
+ ensure_isolated()
258
+
256
259
  from contextual.observability import ObservabilityConfig
257
260
  from contextual.observability.logging import configure_logging
258
261
 
@@ -40,22 +40,6 @@ from contextual.integrations.client_writer import (
40
40
  )
41
41
 
42
42
 
43
- def _find_uvx() -> str | None:
44
- """Locate a usable uvx executable."""
45
- uvx_path = shutil.which("uvx")
46
- if uvx_path:
47
- return uvx_path
48
-
49
- for candidate in [
50
- Path.home() / ".local" / "bin" / "uvx",
51
- Path("/usr/local/bin/uvx"),
52
- Path("/opt/homebrew/bin/uvx"),
53
- ]:
54
- if candidate.exists():
55
- return str(candidate)
56
-
57
- return None
58
-
59
43
 
60
44
  def _slug(name: str) -> str:
61
45
  """Key-safe slug from a workspace directory name."""
@@ -224,75 +208,55 @@ def _write_client_config(
224
208
 
225
209
 
226
210
  def _find_contextual_mcp() -> str | None:
227
- """Locate the pip-installed contextual-mcp binary.
228
-
229
- Looks next to sys.executable first — this is the binary that was installed
230
- alongside the package in the user's active Python environment (pyenv, conda,
231
- virtualenv, plain pip). That lookup is independent of PATH, so it works
232
- even in AI clients that inherit a minimal environment. Falls back to a
233
- PATH search for edge cases. Returns None when neither finds it, in which
234
- case callers should fall back to uvx.
235
- """
211
+ """Locate the installed contextual-mcp binary next to sys.executable or on PATH."""
236
212
  sibling = Path(sys.executable).resolve().parent / "contextual-mcp"
237
213
  if sibling.exists():
238
214
  return str(sibling)
239
215
  return shutil.which("contextual-mcp")
240
216
 
241
217
 
242
- def _build_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
218
+ def _require_contextual_mcp() -> str:
219
+ """Return the contextual-mcp binary path, or exit with an install hint."""
220
+ binary = _find_contextual_mcp()
221
+ if binary:
222
+ return binary
223
+ print_error(
224
+ "contextual-mcp binary not found.",
225
+ hint=(
226
+ "Install via one of:\n"
227
+ " uv tool install contextual-engine (recommended)\n"
228
+ " pipx install contextual-engine"
229
+ ),
230
+ )
231
+ raise typer.Exit(1)
232
+
233
+
234
+ def _build_mcp_entry(contextual_bin: str, workspace_root: Path) -> dict:
243
235
  """Build the default MCP launcher entry for Contextual."""
244
- local = _find_contextual_mcp()
245
- if local:
246
- return {
247
- "command": local,
248
- "args": ["--workspace", str(workspace_root)],
249
- }
250
236
  return {
251
- "command": uvx_path,
252
- "args": ["--from", "contextual-engine", "contextual-mcp", "--workspace", str(workspace_root)],
237
+ "command": contextual_bin,
238
+ "args": ["--workspace", str(workspace_root)],
253
239
  }
254
240
 
255
241
 
256
- def _build_claude_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
242
+ def _build_claude_mcp_entry(contextual_bin: str, workspace_root: Path) -> dict:
257
243
  """Build the Claude Desktop MCP entry."""
258
- local = _find_contextual_mcp()
259
- if local:
260
- return {
261
- "command": local,
262
- "args": ["--workspace", str(workspace_root)],
263
- }
264
- # uvx fallback: Claude Desktop has a minimal PATH so wrap in zsh -lc to
265
- # ensure uvx is findable before exec-ing.
266
244
  return {
267
- "command": "/bin/zsh",
268
- "args": [
269
- "-lc",
270
- (
271
- f"cd {shlex.quote(str(workspace_root))} "
272
- f"&& exec {shlex.quote(uvx_path)} --from contextual-engine contextual-mcp "
273
- f"--workspace {shlex.quote(str(workspace_root))}"
274
- ),
275
- ],
245
+ "command": contextual_bin,
246
+ "args": ["--workspace", str(workspace_root)],
276
247
  }
277
248
 
278
249
 
279
- def _build_vscode_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
250
+ def _build_vscode_mcp_entry(contextual_bin: str, workspace_root: Path) -> dict:
280
251
  """Build the VS Code / GitHub Copilot MCP entry.
281
252
 
282
253
  VS Code requires an explicit ``"type": "stdio"`` field — other clients
283
254
  accept entries without it.
284
255
  """
285
- local = _find_contextual_mcp()
286
- if local:
287
- return {
288
- "type": "stdio",
289
- "command": local,
290
- "args": ["--workspace", str(workspace_root)],
291
- }
292
256
  return {
293
257
  "type": "stdio",
294
- "command": uvx_path,
295
- "args": ["--from", "contextual-engine", "contextual-mcp", "--workspace", str(workspace_root)],
258
+ "command": contextual_bin,
259
+ "args": ["--workspace", str(workspace_root)],
296
260
  }
297
261
 
298
262
 
@@ -389,7 +353,7 @@ def _persist_codex_toml(config_path: Path, document: dict) -> None:
389
353
 
390
354
 
391
355
  def _write_codex_toml_config(
392
- config_path: Path, uvx_path: str, workspace_root: Path
356
+ config_path: Path, contextual_bin: str, workspace_root: Path
393
357
  ) -> tuple[str, str]:
394
358
  """Merge the Contextual entry into Codex config.toml.
395
359
 
@@ -408,12 +372,7 @@ def _write_codex_toml_config(
408
372
  original = copy.deepcopy(existing)
409
373
  mcp_servers = existing.setdefault("mcp_servers", {})
410
374
  ws_str = str(workspace_root.resolve())
411
- local = _find_contextual_mcp()
412
- entry = (
413
- {"command": local, "args": ["--workspace", str(workspace_root)]}
414
- if local
415
- else {"command": uvx_path, "args": ["--from", "contextual-engine", "contextual-mcp", "--workspace", str(workspace_root)]}
416
- )
375
+ entry = {"command": contextual_bin, "args": ["--workspace", str(workspace_root)]}
417
376
 
418
377
  # TOML entries embed the workspace in args (no shell wrapper), so resolve
419
378
  # the bound workspace from the --workspace arg rather than via the shared
@@ -452,7 +411,7 @@ def _write_codex_toml_config(
452
411
 
453
412
  def _configure_codex_client(
454
413
  config_path: Path,
455
- uvx_path: str,
414
+ contextual_bin: str,
456
415
  workspace_root: Path,
457
416
  dry_run: bool = False,
458
417
  ) -> None:
@@ -463,9 +422,8 @@ def _configure_codex_client(
463
422
  console.print()
464
423
  console.print(
465
424
  Syntax(
466
- f"[mcp_servers.contextual]\ncommand = {json.dumps(uvx_path)}\n"
467
- f'args = ["--from", "contextual-engine", "contextual-mcp", '
468
- f'"--workspace", {json.dumps(str(workspace_root))}]',
425
+ f"[mcp_servers.contextual]\ncommand = {json.dumps(contextual_bin)}\n"
426
+ f'args = ["--workspace", {json.dumps(str(workspace_root))}]',
469
427
  "toml",
470
428
  theme="ansi_dark",
471
429
  background_color="default",
@@ -474,7 +432,7 @@ def _configure_codex_client(
474
432
  console.print()
475
433
  return
476
434
 
477
- key, status = _write_codex_toml_config(config_path, uvx_path, workspace_root)
435
+ key, status = _write_codex_toml_config(config_path, contextual_bin, workspace_root)
478
436
  print_client_configured("Codex", key, config_path, status)
479
437
 
480
438
 
@@ -569,7 +527,7 @@ def _remove_codex_toml_entry(config_path: Path, workspace_root: Path) -> str:
569
527
 
570
528
  def _display_manual_config(
571
529
  client_name: str,
572
- uvx_path: str,
530
+ contextual_bin: str,
573
531
  workspace_root: Path,
574
532
  ui_steps: list[str],
575
533
  ) -> None:
@@ -579,8 +537,7 @@ def _display_manual_config(
579
537
  from rich.text import Text
580
538
 
581
539
  cmd = (
582
- f"{uvx_path} --from contextual-engine contextual-mcp "
583
- f"--workspace {shlex.quote(str(workspace_root))}"
540
+ f"{contextual_bin} --workspace {shlex.quote(str(workspace_root))}"
584
541
  )
585
542
 
586
543
  console.print()
@@ -750,13 +707,7 @@ def client(
750
707
  )
751
708
  raise typer.Exit(1)
752
709
 
753
- uvx_path = _find_uvx()
754
- if not uvx_path:
755
- print_error(
756
- "uvx not found on PATH.",
757
- hint="Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh",
758
- )
759
- raise typer.Exit(1)
710
+ contextual_bin = _require_contextual_mcp()
760
711
 
761
712
  paths = _config_paths()
762
713
  workspace_root = Path.cwd().resolve()
@@ -764,12 +715,12 @@ def client(
764
715
  agents_md = workspace_root / ".contextual" / "AGENTS.md"
765
716
 
766
717
  if claude:
767
- entry = _build_claude_mcp_entry(uvx_path, workspace_root)
718
+ entry = _build_claude_mcp_entry(contextual_bin, workspace_root)
768
719
  _configure_client("Claude Desktop", paths["claude"], entry, workspace_root, dry_run)
769
720
  print_agents_md_hint(agents_md, "Claude → Project → Custom Instructions")
770
721
 
771
722
  elif claude_code:
772
- _configure_client("Claude Code", workspace_root / ".mcp.json", _build_mcp_entry(uvx_path, workspace_root), workspace_root, dry_run)
723
+ _configure_client("Claude Code", workspace_root / ".mcp.json", _build_mcp_entry(contextual_bin, workspace_root), workspace_root, dry_run)
773
724
  if not dry_run:
774
725
  result = write_type_b(workspace_root / "CLAUDE.md", marker_block("claude-code"))
775
726
  print_md_injected(workspace_root / "CLAUDE.md", result)
@@ -777,7 +728,7 @@ def client(
777
728
  elif chatgpt:
778
729
  _display_manual_config(
779
730
  "ChatGPT",
780
- uvx_path,
731
+ contextual_bin,
781
732
  workspace_root,
782
733
  ui_steps=[
783
734
  "Open ChatGPT Desktop and go to Settings",
@@ -791,7 +742,7 @@ def client(
791
742
  elif perplexity:
792
743
  _display_manual_config(
793
744
  "Perplexity",
794
- uvx_path,
745
+ contextual_bin,
795
746
  workspace_root,
796
747
  ui_steps=[
797
748
  "Open Perplexity Desktop (macOS) and go to Settings",
@@ -803,31 +754,31 @@ def client(
803
754
  print_agents_md_hint(agents_md, "Perplexity → Space → System Prompt")
804
755
 
805
756
  elif gemini_cli:
806
- _configure_client("Gemini CLI", paths["gemini-cli"], _build_mcp_entry(uvx_path, workspace_root), workspace_root, dry_run)
757
+ _configure_client("Gemini CLI", paths["gemini-cli"], _build_mcp_entry(contextual_bin, workspace_root), workspace_root, dry_run)
807
758
 
808
759
  elif cursor:
809
- _configure_client("Cursor", paths["cursor"], _build_mcp_entry(uvx_path, workspace_root), workspace_root, dry_run)
760
+ _configure_client("Cursor", paths["cursor"], _build_mcp_entry(contextual_bin, workspace_root), workspace_root, dry_run)
810
761
  if not dry_run:
811
762
  result = write_type_a(workspace_root / ".cursor" / "rules" / "contextual.mdc", cursor_file_content())
812
763
  print_md_injected(workspace_root / ".cursor" / "rules" / "contextual.mdc", result)
813
764
 
814
765
  elif copilot:
815
- _configure_vscode_client(paths["copilot"], _build_vscode_mcp_entry(uvx_path, workspace_root), workspace_root, dry_run)
766
+ _configure_vscode_client(paths["copilot"], _build_vscode_mcp_entry(contextual_bin, workspace_root), workspace_root, dry_run)
816
767
  if not dry_run:
817
768
  result = write_type_b(workspace_root / ".github" / "copilot-instructions.md", marker_block("copilot"))
818
769
  print_md_injected(workspace_root / ".github" / "copilot-instructions.md", result)
819
770
 
820
771
  elif windsurf:
821
- _configure_client("Windsurf", paths["windsurf"], _build_mcp_entry(uvx_path, workspace_root), workspace_root, dry_run)
772
+ _configure_client("Windsurf", paths["windsurf"], _build_mcp_entry(contextual_bin, workspace_root), workspace_root, dry_run)
822
773
  if not dry_run:
823
774
  result = write_type_b(workspace_root / ".windsurfrules", marker_block("windsurf"))
824
775
  print_md_injected(workspace_root / ".windsurfrules", result)
825
776
 
826
777
  elif codex:
827
- _configure_codex_client(paths["codex"], uvx_path, workspace_root, dry_run)
778
+ _configure_codex_client(paths["codex"], contextual_bin, workspace_root, dry_run)
828
779
 
829
780
  elif antigravity:
830
- _configure_client("Antigravity", paths["antigravity"], _build_mcp_entry(uvx_path, workspace_root), workspace_root, dry_run)
781
+ _configure_client("Antigravity", paths["antigravity"], _build_mcp_entry(contextual_bin, workspace_root), workspace_root, dry_run)
831
782
  if not dry_run:
832
783
  result = write_type_a(workspace_root / ".agent" / "rules" / "contextual.md", antigravity_file_content())
833
784
  print_md_injected(workspace_root / ".agent" / "rules" / "contextual.md", result)
@@ -144,7 +144,7 @@ def mcp_logs(
144
144
  console.print(line, highlight=False, end="")
145
145
  except Exception as e:
146
146
  print_error(f"Failed to read logs: {e}")
147
- return
147
+ raise typer.Exit(1)
148
148
 
149
149
  if follow:
150
150
  try:
@@ -22,7 +22,6 @@ from contextual.security.sanitize import sql_str_literal
22
22
  @require_config
23
23
  @require_index
24
24
  async def stats(
25
- path: str = typer.Option(".", "--path", "-p", help="Repository path"),
26
25
  temporal: bool = typer.Option(False, "--temporal", "-t", help="Show temporal stats"),
27
26
  graph: bool = typer.Option(False, "--graph", "-g", help="Show graph stats"),
28
27
  show_all: bool = typer.Option(False, "--all", "-a", help="Show all stats"),
@@ -50,6 +50,15 @@ class DaemonConfig(BaseModel):
50
50
  compaction_interval_hours: float = 6.0 # How often the background loop runs (0 disables)
51
51
  compaction_retention_hours: float = 1.0 # Prune versions older than this; never 0 (breaks concurrent writes)
52
52
 
53
+ # Heap / memory trimmer
54
+ # When the daemon's physical footprint exceeds heap_trim_threshold_mb a
55
+ # hard trim fires (GC + malloc page return). If the footprint is still over
56
+ # the threshold on the next tick and no sessions are active, models are
57
+ # offloaded to CPU to recover MPS/GPU pages. Set to 0 to disable.
58
+ heap_monitor_enabled: bool = True
59
+ heap_monitor_interval_seconds: int = 30
60
+ heap_trim_threshold_mb: int = 2500
61
+
53
62
  # Logging
54
63
  log_level: str = "INFO"
55
64
 
@@ -98,7 +98,14 @@ class FactSource(StrEnum):
98
98
  class Language(StrEnum):
99
99
  """Supported programming languages for indexing.
100
100
 
101
- Week 1 MVP: Python, TypeScript, JavaScript, Go, Java, Rust, C#
101
+ Each value MUST equal the tree-sitter language name used by
102
+ ``contextual.indexing.chunker.LANGUAGE_MAP`` (the string handed to
103
+ ``tree_sitter_language_pack.get_parser``). The chunker maps a file
104
+ extension to that name; ``_build_chunk`` then does ``Language(name)``.
105
+ Any name present in ``LANGUAGE_MAP`` but absent here silently casts to
106
+ ``Language.PYTHON`` — mislabelling the chunk and breaking language
107
+ filtering. Keep the two in lockstep. ``c_sharp`` is the sole divergence
108
+ (enum value ``csharp``) and is bridged by ``chunker._TS_TO_LANG``.
102
109
  """
103
110
 
104
111
  PYTHON = "python"
@@ -109,12 +116,53 @@ class Language(StrEnum):
109
116
  JAVA = "java"
110
117
  RUST = "rust"
111
118
  CSHARP = "csharp"
119
+ # C family
120
+ C = "c"
121
+ CPP = "cpp"
122
+ # JVM / mobile
123
+ KOTLIN = "kotlin"
124
+ SWIFT = "swift"
125
+ SCALA = "scala"
126
+ DART = "dart"
127
+ # Scripting
128
+ RUBY = "ruby"
129
+ PHP = "php"
130
+ LUA = "lua"
131
+ PERL = "perl"
132
+ R = "r"
133
+ BASH = "bash"
134
+ # Functional / emerging
135
+ HASKELL = "haskell"
136
+ ELIXIR = "elixir"
112
137
  # Config formats (free wins)
113
138
  JSON = "json"
114
139
  YAML = "yaml"
115
140
  TOML = "toml"
116
141
  MARKDOWN = "markdown"
117
142
  DOCKERFILE = "dockerfile"
143
+ # Data / schema / infra
144
+ SQL = "sql"
145
+ HCL = "hcl"
146
+ PROTO = "proto"
147
+ # Web frontend
148
+ HTML = "html"
149
+ CSS = "css"
150
+ SCSS = "scss"
151
+ # JVM / enterprise
152
+ GROOVY = "groovy"
153
+ # Systems / emerging
154
+ NIM = "nim"
155
+ ZIG = "zig"
156
+ V = "v"
157
+ # Functional
158
+ ELM = "elm"
159
+ OCAML = "ocaml"
160
+ ERLANG = "erlang"
161
+ # Scientific
162
+ JULIA = "julia"
163
+ # Platform / Web3
164
+ OBJC = "objc"
165
+ SOLIDITY = "solidity"
118
166
 
119
167
 
120
168
  class ModelType(StrEnum):
@@ -206,16 +206,21 @@ def _send_to_daemon(workspace_root: str, files: list[str], trigger: str) -> bool
206
206
  import httpx # type: ignore[import-untyped]
207
207
 
208
208
  from contextual.mcp._platform import get_base_url, get_httpx_transport
209
+ from contextual.mcp.access import read_local_api_key
209
210
 
210
211
  transport = get_httpx_transport(sync=True)
211
212
  base = get_base_url()
212
213
  url = f"{base}/internal/index"
213
214
  kwargs: dict = {"transport": transport} if transport is not None else {}
214
215
 
216
+ api_key = read_local_api_key()
217
+ headers = {"Authorization": f"Bearer {api_key}"} if api_key else {}
218
+
215
219
  with httpx.Client(timeout=5.0, **kwargs) as client:
216
220
  resp = client.post(
217
221
  url,
218
222
  json={"workspace_root": workspace_root, "files": files, "trigger": trigger},
223
+ headers=headers,
219
224
  )
220
225
  resp.raise_for_status()
221
226
  return True