codevira 2.1.2__tar.gz → 3.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. {codevira-2.1.2 → codevira-3.1.0}/CHANGELOG.md +821 -1
  2. codevira-3.1.0/PKG-INFO +522 -0
  3. codevira-3.1.0/README.md +473 -0
  4. codevira-3.1.0/codevira.egg-info/PKG-INFO +522 -0
  5. {codevira-2.1.2 → codevira-3.1.0}/codevira.egg-info/SOURCES.txt +58 -32
  6. {codevira-2.1.2 → codevira-3.1.0}/codevira.egg-info/requires.txt +7 -3
  7. codevira-3.1.0/docs/architecture.md +264 -0
  8. codevira-3.1.0/docs/audit-2026-05-22.md +274 -0
  9. {codevira-2.1.2 → codevira-3.1.0}/docs/foolproof-product-charter.md +3 -2
  10. {codevira-2.1.2 → codevira-3.1.0}/docs/how-i-built-persistent-memory-for-ai-agents.md +10 -0
  11. {codevira-2.1.2 → codevira-3.1.0}/docs/linkedin-article-ai-agent-memory.md +9 -0
  12. {codevira-2.1.2 → codevira-3.1.0}/docs/medium-your-ai-coding-agent-has-amnesia.md +10 -0
  13. codevira-3.1.0/docs/morning-handoff-2026-05-22.md +337 -0
  14. codevira-3.1.0/docs/plans/v2.1.3.md +361 -0
  15. codevira-3.1.0/docs/plans/v2.2.0.md +960 -0
  16. codevira-3.1.0/docs/plans/v3.0.0.md +256 -0
  17. {codevira-2.1.2 → codevira-3.1.0}/docs/qa-playbook.md +14 -0
  18. {codevira-2.1.2 → codevira-3.1.0}/docs/roadmap.md +17 -4
  19. codevira-3.1.0/docs/surface-cuts-2026-05-22.md +348 -0
  20. {codevira-2.1.2 → codevira-3.1.0}/indexer/fix_history.py +57 -19
  21. {codevira-2.1.2 → codevira-3.1.0}/indexer/graph_generator.py +95 -36
  22. {codevira-2.1.2 → codevira-3.1.0}/indexer/index_codebase.py +51 -94
  23. {codevira-2.1.2 → codevira-3.1.0}/indexer/outcome_tracker.py +115 -43
  24. {codevira-2.1.2 → codevira-3.1.0}/indexer/sqlite_graph.py +13 -204
  25. {codevira-2.1.2 → codevira-3.1.0}/indexer/treesitter_parser.py +61 -23
  26. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/__init__.py +1 -1
  27. codevira-3.1.0/mcp_server/_mcp_registry.py +145 -0
  28. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/_repair_init.py +46 -22
  29. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/_safe_crash.py +0 -1
  30. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/auto_init.py +45 -14
  31. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/cli.py +512 -851
  32. codevira-3.1.0/mcp_server/cli_consensus.py +55 -0
  33. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/cli_export.py +34 -8
  34. codevira-3.1.0/mcp_server/cli_graph.py +476 -0
  35. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/cli_hooks_admin.py +80 -7
  36. codevira-3.1.0/mcp_server/cli_induce.py +328 -0
  37. codevira-3.1.0/mcp_server/cli_init.py +296 -0
  38. codevira-3.1.0/mcp_server/cli_reflect.py +170 -0
  39. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/cli_replay.py +73 -24
  40. codevira-3.1.0/mcp_server/cli_sync.py +109 -0
  41. codevira-3.1.0/mcp_server/cli_uninstall.py +478 -0
  42. codevira-3.1.0/mcp_server/cli_working.py +89 -0
  43. codevira-3.1.0/mcp_server/data/affordances.yaml +44 -0
  44. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/hooks/post_tool_use.sh +8 -0
  45. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/hooks/pre_tool_use.sh +8 -0
  46. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/hooks/session_start.sh +8 -0
  47. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/hooks/stop.sh +8 -0
  48. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/hooks/user_prompt_submit.sh +9 -0
  49. codevira-3.1.0/mcp_server/data/prompts/reflection_v1.md +40 -0
  50. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/decision_replay.py +125 -75
  51. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/doctor.py +287 -99
  52. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/__init__.py +11 -14
  53. codevira-3.1.0/mcp_server/engine/memory_fanout.py +242 -0
  54. codevira-3.1.0/mcp_server/engine/policies/__init__.py +45 -0
  55. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policies/_signature_detect.py +0 -1
  56. codevira-3.1.0/mcp_server/engine/policies/relevance_inject.py +469 -0
  57. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/signals.py +120 -185
  58. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/wiring/mcp_dispatch.py +23 -2
  59. codevira-3.1.0/mcp_server/global_sync.py +96 -0
  60. codevira-3.1.0/mcp_server/graph/template.html +2172 -0
  61. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/http_server.py +119 -47
  62. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/ide_inject.py +241 -48
  63. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/log_retention.py +30 -9
  64. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/migrate.py +21 -5
  65. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/paths.py +65 -24
  66. codevira-3.1.0/mcp_server/prompts.py +77 -0
  67. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/roadmap_drift.py +1 -1
  68. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/server.py +925 -646
  69. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/setup_wizard.py +274 -137
  70. codevira-3.1.0/mcp_server/storage/__init__.py +43 -0
  71. codevira-3.1.0/mcp_server/storage/activity_store.py +274 -0
  72. codevira-3.1.0/mcp_server/storage/agents_md_generator.py +368 -0
  73. codevira-3.1.0/mcp_server/storage/atomic.py +268 -0
  74. codevira-3.1.0/mcp_server/storage/config.py +64 -0
  75. codevira-3.1.0/mcp_server/storage/consensus_store.py +625 -0
  76. codevira-3.1.0/mcp_server/storage/decisions_store.py +618 -0
  77. codevira-3.1.0/mcp_server/storage/digest.py +134 -0
  78. codevira-3.1.0/mcp_server/storage/fts5_index.py +620 -0
  79. codevira-3.1.0/mcp_server/storage/jsonl_store.py +574 -0
  80. codevira-3.1.0/mcp_server/storage/manifest.py +199 -0
  81. codevira-3.1.0/mcp_server/storage/origin.py +130 -0
  82. codevira-3.1.0/mcp_server/storage/outcomes_writer.py +342 -0
  83. codevira-3.1.0/mcp_server/storage/paths.py +285 -0
  84. codevira-3.1.0/mcp_server/storage/reflections_store.py +342 -0
  85. codevira-3.1.0/mcp_server/storage/sanitize.py +44 -0
  86. codevira-3.1.0/mcp_server/storage/sessions_store.py +158 -0
  87. codevira-3.1.0/mcp_server/storage/skills_store.py +747 -0
  88. codevira-3.1.0/mcp_server/storage/token_estimator.py +106 -0
  89. codevira-3.1.0/mcp_server/storage/working_store.py +434 -0
  90. codevira-3.1.0/mcp_server/tools/__init__.py +0 -0
  91. codevira-3.1.0/mcp_server/tools/changesets.py +50 -0
  92. codevira-3.1.0/mcp_server/tools/check_conflict.py +290 -0
  93. codevira-3.1.0/mcp_server/tools/consensus.py +138 -0
  94. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/tools/graph.py +9 -421
  95. codevira-3.1.0/mcp_server/tools/learning.py +751 -0
  96. codevira-3.1.0/mcp_server/tools/reflections.py +125 -0
  97. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/tools/roadmap.py +396 -347
  98. codevira-3.1.0/mcp_server/tools/search.py +296 -0
  99. codevira-3.1.0/mcp_server/tools/skills.py +411 -0
  100. codevira-3.1.0/mcp_server/tools/spatial.py +521 -0
  101. codevira-3.1.0/mcp_server/tools/working.py +349 -0
  102. {codevira-2.1.2 → codevira-3.1.0}/pyproject.toml +26 -14
  103. {codevira-2.1.2 → codevira-3.1.0}/tests/test_auto_init.py +119 -52
  104. {codevira-2.1.2 → codevira-3.1.0}/tests/test_call_edge_fk_safety.py +0 -2
  105. codevira-3.1.0/tests/test_check_conflict.py +362 -0
  106. codevira-3.1.0/tests/test_cli_consensus.py +426 -0
  107. codevira-3.1.0/tests/test_cli_graph.py +852 -0
  108. codevira-3.1.0/tests/test_cli_induce.py +859 -0
  109. {codevira-2.1.2 → codevira-3.1.0}/tests/test_cli_replay.py +136 -47
  110. codevira-3.1.0/tests/test_cli_uninstall.py +475 -0
  111. {codevira-2.1.2 → codevira-3.1.0}/tests/test_cli_version.py +0 -1
  112. codevira-3.1.0/tests/test_cli_working.py +109 -0
  113. codevira-3.1.0/tests/test_consensus_handshake.py +585 -0
  114. {codevira-2.1.2 → codevira-3.1.0}/tests/test_crash_logger.py +1 -3
  115. {codevira-2.1.2 → codevira-3.1.0}/tests/test_doctor.py +71 -34
  116. {codevira-2.1.2 → codevira-3.1.0}/tests/test_fk_safety_extended.py +0 -1
  117. {codevira-2.1.2 → codevira-3.1.0}/tests/test_fork_safety.py +0 -3
  118. {codevira-2.1.2 → codevira-3.1.0}/tests/test_gitignore.py +173 -80
  119. codevira-3.1.0/tests/test_global_sync.py +152 -0
  120. {codevira-2.1.2 → codevira-3.1.0}/tests/test_graph_generator.py +39 -36
  121. {codevira-2.1.2 → codevira-3.1.0}/tests/test_http_server.py +167 -119
  122. {codevira-2.1.2 → codevira-3.1.0}/tests/test_ide_inject.py +651 -30
  123. {codevira-2.1.2 → codevira-3.1.0}/tests/test_index_codebase.py +51 -43
  124. {codevira-2.1.2 → codevira-3.1.0}/tests/test_launchd.py +1 -2
  125. {codevira-2.1.2 → codevira-3.1.0}/tests/test_log_retention.py +0 -2
  126. {codevira-2.1.2 → codevira-3.1.0}/tests/test_migrate.py +54 -37
  127. {codevira-2.1.2 → codevira-3.1.0}/tests/test_outcome_tracker.py +1 -2
  128. {codevira-2.1.2 → codevira-3.1.0}/tests/test_paths.py +237 -28
  129. codevira-3.1.0/tests/test_prompts.py +88 -0
  130. {codevira-2.1.2 → codevira-3.1.0}/tests/test_record_decision.py +39 -34
  131. codevira-3.1.0/tests/test_reflections.py +764 -0
  132. {codevira-2.1.2 → codevira-3.1.0}/tests/test_repair_init.py +0 -2
  133. {codevira-2.1.2 → codevira-3.1.0}/tests/test_roadmap_drift.py +0 -2
  134. {codevira-2.1.2 → codevira-3.1.0}/tests/test_server.py +81 -413
  135. {codevira-2.1.2 → codevira-3.1.0}/tests/test_setup_wizard.py +298 -261
  136. {codevira-2.1.2 → codevira-3.1.0}/tests/test_sqlite_graph.py +13 -176
  137. {codevira-2.1.2 → codevira-3.1.0}/tests/test_sqlite_util.py +0 -1
  138. {codevira-2.1.2 → codevira-3.1.0}/tests/test_tools_code_reader.py +93 -26
  139. {codevira-2.1.2 → codevira-3.1.0}/tests/test_tools_graph.py +55 -496
  140. {codevira-2.1.2 → codevira-3.1.0}/tests/test_tools_learning.py +163 -477
  141. {codevira-2.1.2 → codevira-3.1.0}/tests/test_tools_playbook.py +0 -1
  142. {codevira-2.1.2 → codevira-3.1.0}/tests/test_tools_roadmap.py +0 -2
  143. codevira-3.1.0/tests/test_tools_skills.py +359 -0
  144. codevira-3.1.0/tests/test_tools_spatial.py +608 -0
  145. codevira-3.1.0/tests/test_tools_working.py +306 -0
  146. {codevira-2.1.2 → codevira-3.1.0}/tests/test_treesitter_parser.py +0 -3
  147. {codevira-2.1.2 → codevira-3.1.0}/tests/test_watcher_circuit.py +0 -1
  148. codevira-2.1.2/PKG-INFO +0 -809
  149. codevira-2.1.2/README.md +0 -762
  150. codevira-2.1.2/codevira.egg-info/PKG-INFO +0 -809
  151. codevira-2.1.2/indexer/rule_learner.py +0 -336
  152. codevira-2.1.2/mcp_server/agents_md.py +0 -442
  153. codevira-2.1.2/mcp_server/cli_agents.py +0 -232
  154. codevira-2.1.2/mcp_server/cli_budget.py +0 -213
  155. codevira-2.1.2/mcp_server/cli_calibrate.py +0 -140
  156. codevira-2.1.2/mcp_server/cli_configure.py +0 -977
  157. codevira-2.1.2/mcp_server/cli_insights.py +0 -337
  158. codevira-2.1.2/mcp_server/data/templates/agents_md.tmpl +0 -3
  159. codevira-2.1.2/mcp_server/data/templates/canonical_block.md +0 -81
  160. codevira-2.1.2/mcp_server/data/templates/claude_md.tmpl +0 -3
  161. codevira-2.1.2/mcp_server/data/templates/copilot_instructions.tmpl +0 -3
  162. codevira-2.1.2/mcp_server/data/templates/cursor_rules.mdc.tmpl +0 -8
  163. codevira-2.1.2/mcp_server/data/templates/gemini_md.tmpl +0 -3
  164. codevira-2.1.2/mcp_server/data/templates/windsurfrules.tmpl +0 -3
  165. codevira-2.1.2/mcp_server/engine/intent_classifier.py +0 -214
  166. codevira-2.1.2/mcp_server/engine/policies/__init__.py +0 -44
  167. codevira-2.1.2/mcp_server/engine/policies/ai_promotion.py +0 -337
  168. codevira-2.1.2/mcp_server/engine/policies/cross_session.py +0 -591
  169. codevira-2.1.2/mcp_server/engine/policies/intent_inference.py +0 -421
  170. codevira-2.1.2/mcp_server/engine/policies/live_style.py +0 -445
  171. codevira-2.1.2/mcp_server/engine/policies/scope_contract.py +0 -362
  172. codevira-2.1.2/mcp_server/engine/promotion_score.py +0 -208
  173. codevira-2.1.2/mcp_server/engine/scope_contract.py +0 -201
  174. codevira-2.1.2/mcp_server/global_sync.py +0 -187
  175. codevira-2.1.2/mcp_server/prompts.py +0 -145
  176. codevira-2.1.2/mcp_server/tools/_decision_embeddings.py +0 -694
  177. codevira-2.1.2/mcp_server/tools/changesets.py +0 -225
  178. codevira-2.1.2/mcp_server/tools/check_conflict.py +0 -175
  179. codevira-2.1.2/mcp_server/tools/learning.py +0 -984
  180. codevira-2.1.2/mcp_server/tools/search.py +0 -897
  181. codevira-2.1.2/tests/test_cli.py +0 -1423
  182. codevira-2.1.2/tests/test_cli_agents.py +0 -375
  183. codevira-2.1.2/tests/test_cli_configure.py +0 -1075
  184. codevira-2.1.2/tests/test_cli_insights.py +0 -159
  185. codevira-2.1.2/tests/test_decision_embeddings.py +0 -253
  186. codevira-2.1.2/tests/test_global_sync.py +0 -325
  187. codevira-2.1.2/tests/test_prompts.py +0 -101
  188. codevira-2.1.2/tests/test_retire_rule.py +0 -271
  189. codevira-2.1.2/tests/test_rule_learner.py +0 -411
  190. codevira-2.1.2/tests/test_tools_changesets.py +0 -424
  191. codevira-2.1.2/tests/test_tools_search.py +0 -489
  192. {codevira-2.1.2 → codevira-3.1.0}/LICENSE +0 -0
  193. {codevira-2.1.2 → codevira-3.1.0}/MANIFEST.in +0 -0
  194. {codevira-2.1.2 → codevira-3.1.0}/agents/builder.md +0 -0
  195. {codevira-2.1.2 → codevira-3.1.0}/agents/developer.md +0 -0
  196. {codevira-2.1.2 → codevira-3.1.0}/agents/documenter.md +0 -0
  197. {codevira-2.1.2 → codevira-3.1.0}/agents/orchestrator.md +0 -0
  198. {codevira-2.1.2 → codevira-3.1.0}/agents/planner.md +0 -0
  199. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/01-code-review.md +0 -0
  200. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/02-adversarial-fix-review.md +0 -0
  201. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/03-cross-module-impact.md +0 -0
  202. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/06-doc-drift.md +0 -0
  203. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/07-security-audit.md +0 -0
  204. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/12-llm-redteam.md +0 -0
  205. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/13-multi-ide-schema.md +0 -0
  206. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/22-competitor-benchmark.md +0 -0
  207. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/README.md +0 -0
  208. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/tier2-scripts.md +0 -0
  209. {codevira-2.1.2 → codevira-3.1.0}/agents/qa/tier3-manual.md +0 -0
  210. {codevira-2.1.2 → codevira-3.1.0}/agents/reviewer.md +0 -0
  211. {codevira-2.1.2 → codevira-3.1.0}/agents/tester.md +0 -0
  212. {codevira-2.1.2 → codevira-3.1.0}/codevira.egg-info/dependency_links.txt +0 -0
  213. {codevira-2.1.2 → codevira-3.1.0}/codevira.egg-info/entry_points.txt +0 -0
  214. {codevira-2.1.2 → codevira-3.1.0}/codevira.egg-info/top_level.txt +0 -0
  215. {codevira-2.1.2 → codevira-3.1.0}/config.example.yaml +0 -0
  216. {codevira-2.1.2 → codevira-3.1.0}/docs/alpha-tester-invites.md +0 -0
  217. {codevira-2.1.2 → codevira-3.1.0}/docs/demo/README.md +0 -0
  218. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/00-engine.md +0 -0
  219. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/01-decision-lock.md +0 -0
  220. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/02-anti-regression.md +0 -0
  221. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/03-scope-contract.md +0 -0
  222. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/04-blast-radius.md +0 -0
  223. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/05-cross-session.md +0 -0
  224. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/06-token-budget.md +0 -0
  225. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/07-live-style.md +0 -0
  226. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/08-decision-replay.md +0 -0
  227. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/09-intent-inference.md +0 -0
  228. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/10-ai-promotion.md +0 -0
  229. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/README.md +0 -0
  230. {codevira-2.1.2 → codevira-3.1.0}/docs/heroes/pillar-1-setup.md +0 -0
  231. {codevira-2.1.2 → codevira-3.1.0}/docs/hn-launch-day.md +0 -0
  232. {codevira-2.1.2 → codevira-3.1.0}/docs/internal/competitive-landscape.md +0 -0
  233. {codevira-2.1.2 → codevira-3.1.0}/docs/linkedin-post-ai-agent-memory.md +0 -0
  234. {codevira-2.1.2 → codevira-3.1.0}/docs/local-pypi-https.md +0 -0
  235. {codevira-2.1.2 → codevira-3.1.0}/docs/plans/v2.1.2.md +0 -0
  236. {codevira-2.1.2 → codevira-3.1.0}/docs/release-process.md +0 -0
  237. {codevira-2.1.2 → codevira-3.1.0}/docs/troubleshooting/antigravity.md +0 -0
  238. {codevira-2.1.2 → codevira-3.1.0}/docs/v2-completion-plan.md +0 -0
  239. {codevira-2.1.2 → codevira-3.1.0}/docs/v2-execution-log.md +0 -0
  240. {codevira-2.1.2 → codevira-3.1.0}/docs/v2-master-plan.md +0 -0
  241. {codevira-2.1.2 → codevira-3.1.0}/docs/vs-other-memory-tools.md +0 -0
  242. {codevira-2.1.2 → codevira-3.1.0}/graph/_schema.yaml +0 -0
  243. {codevira-2.1.2 → codevira-3.1.0}/indexer/__init__.py +0 -0
  244. {codevira-2.1.2 → codevira-3.1.0}/indexer/_dedupe_migration.py +0 -0
  245. {codevira-2.1.2 → codevira-3.1.0}/indexer/_fork_safety.py +0 -0
  246. {codevira-2.1.2 → codevira-3.1.0}/indexer/_sqlite_util.py +0 -0
  247. {codevira-2.1.2 → codevira-3.1.0}/indexer/chunker.py +0 -0
  248. {codevira-2.1.2 → codevira-3.1.0}/indexer/global_db.py +0 -0
  249. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/__main__.py +0 -0
  250. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/_ghost_check.py +0 -0
  251. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/_project_inventory.py +0 -0
  252. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/_prompts.py +0 -0
  253. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/cli_projects.py +0 -0
  254. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/crash_logger.py +0 -0
  255. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/__init__.py +0 -0
  256. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/builder.md +0 -0
  257. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/developer.md +0 -0
  258. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/documenter.md +0 -0
  259. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/orchestrator.md +0 -0
  260. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/planner.md +0 -0
  261. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/reviewer.md +0 -0
  262. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/agents/tester.md +0 -0
  263. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/config.example.yaml +0 -0
  264. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/coding-standards-generic.md +0 -0
  265. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/coding-standards-go.md +0 -0
  266. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/coding-standards-typescript.md +0 -0
  267. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/coding-standards.md +0 -0
  268. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/engineering-excellence.md +0 -0
  269. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/git-cicd-governance.md +0 -0
  270. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/git_commits.md +0 -0
  271. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/incremental-updates.md +0 -0
  272. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/master_rule.md +0 -0
  273. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/multi-language.md +0 -0
  274. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/persistence.md +0 -0
  275. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/resilience-observability.md +0 -0
  276. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/smoke-testing.md +0 -0
  277. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/data/rules/testing-standards.md +0 -0
  278. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/detect.py +0 -0
  279. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/demo_policy.py +0 -0
  280. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/events.py +0 -0
  281. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policies/anti_regression.py +0 -0
  282. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policies/blast_radius.py +0 -0
  283. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policies/decision_lock.py +0 -0
  284. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policies/post_edit_refresh.py +0 -0
  285. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policies/token_budget.py +0 -0
  286. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/policy.py +0 -0
  287. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/runner.py +0 -0
  288. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/token_meter.py +0 -0
  289. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/wiring/__init__.py +0 -0
  290. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/engine/wiring/claude_code_hooks.py +0 -0
  291. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/gitignore.py +0 -0
  292. {codevira-2.1.2/mcp_server/tools → codevira-3.1.0/mcp_server/graph}/__init__.py +0 -0
  293. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/launchd.py +0 -0
  294. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/tools/code_reader.py +0 -0
  295. {codevira-2.1.2 → codevira-3.1.0}/mcp_server/tools/playbook.py +0 -0
  296. {codevira-2.1.2 → codevira-3.1.0}/rules/coding-standards.md +0 -0
  297. {codevira-2.1.2 → codevira-3.1.0}/rules/engineering-excellence.md +0 -0
  298. {codevira-2.1.2 → codevira-3.1.0}/rules/git-cicd-governance.md +0 -0
  299. {codevira-2.1.2 → codevira-3.1.0}/rules/git_commits.md +0 -0
  300. {codevira-2.1.2 → codevira-3.1.0}/rules/incremental-updates.md +0 -0
  301. {codevira-2.1.2 → codevira-3.1.0}/rules/master_rule.md +0 -0
  302. {codevira-2.1.2 → codevira-3.1.0}/rules/persistence.md +0 -0
  303. {codevira-2.1.2 → codevira-3.1.0}/rules/resilience-observability.md +0 -0
  304. {codevira-2.1.2 → codevira-3.1.0}/rules/smoke-testing.md +0 -0
  305. {codevira-2.1.2 → codevira-3.1.0}/rules/testing-standards.md +0 -0
  306. {codevira-2.1.2 → codevira-3.1.0}/setup.cfg +0 -0
  307. {codevira-2.1.2 → codevira-3.1.0}/tests/test__prompts.py +0 -0
  308. {codevira-2.1.2 → codevira-3.1.0}/tests/test_chunker.py +0 -0
  309. {codevira-2.1.2 → codevira-3.1.0}/tests/test_cli_projects.py +0 -0
  310. {codevira-2.1.2 → codevira-3.1.0}/tests/test_dedupe_migration.py +0 -0
  311. {codevira-2.1.2 → codevira-3.1.0}/tests/test_detect.py +0 -0
  312. {codevira-2.1.2 → codevira-3.1.0}/tests/test_ghost_check.py +0 -0
  313. {codevira-2.1.2 → codevira-3.1.0}/tests/test_global_db.py +0 -0
  314. {codevira-2.1.2 → codevira-3.1.0}/tests/test_hook_resilience.py +0 -0
@@ -9,7 +9,827 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
9
9
 
10
10
  ---
11
11
 
12
- ## [Unreleased]
12
+ ## [3.1.0] — Five memory subsystems + cross-IDE consensus
13
+
14
+ v3.1.0 adds five memory subsystems on top of the v3.0.x decision
15
+ log, plus a cross-IDE consensus layer. Every addition is additive
16
+ to the existing schemas; v3.0.x records continue to read without
17
+ migration. The MCP surface gains 22 new tools across the new
18
+ subsystems.
19
+
20
+ ### v3.0.x storage prereq (ships first)
21
+
22
+ - **`refactor(jsonl_store)`** — extract `read_merged` / `compact` /
23
+ `read_recent` from `decisions_store._read_merged` /
24
+ `sessions_store.read_recent`. The five new memory subsystems
25
+ share this amendment-overlay primitive instead of duplicating
26
+ it. Tests cover amendment-chain-three-deep recursion semantics.
27
+ Zero behavior change for existing callers.
28
+
29
+ - **`fix(session_id)`** — `decisions_store.record` and
30
+ `sessions_store.write` now default `session_id` to
31
+ `f"ad-hoc-{secrets.token_hex(3)}"` (e.g., `ad-hoc-a1b2c3`)
32
+ instead of the literal string `"ad-hoc"`. Every concurrent IDE
33
+ that didn't pass a slug previously collided into one bucket;
34
+ the unique-per-call default fixes cross-IDE attribution.
35
+
36
+ ### M1 — Origin tagging (provenance)
37
+
38
+ Every decision and session write now carries an `origin` block:
39
+
40
+ ```json
41
+ "origin": {"ide": "claude_code", "agent_model": "...",
42
+ "host_hash": "<12 hex chars>", "ts": "..."}
43
+ ```
44
+
45
+ - `host_hash` = `sha1(uuid.getnode() bytes + username)[:12]` —
46
+ stable per machine (MAC-based, `platform.node()` fallback),
47
+ privacy-preserving (no plaintext hostname/username leaks).
48
+ - `CODEVIRA_IDE` env var read at MCP server startup; default
49
+ `"unknown"`. `ide_inject.py` now writes `CODEVIRA_IDE=<ide_key>`
50
+ into the MCP config block for all 10 supported IDE configs
51
+ (Claude Code, Claude Desktop, Cursor, Windsurf, Antigravity —
52
+ per-project + global).
53
+ - `check_conflict` response includes the candidate's `origin` so
54
+ agents can see "this conflicts with a decision Cursor wrote 3
55
+ days ago" instead of just an opaque decision_id.
56
+ - Reads tolerate `origin` absent (legacy v3.0.x records treated
57
+ as `ide="unknown"`).
58
+
59
+ ### M2 — Working memory
60
+
61
+ Bounded, decay-scored intra-session scratchpad.
62
+
63
+ - `.codevira-cache/working.jsonl` (per-machine, ephemeral,
64
+ gitignored). Auto-populated by `post_tool_use` hook on Edit /
65
+ Write / MultiEdit / NotebookEdit / update_node (importance 4),
66
+ Bash (importance 3), tool errors (importance bumped to 7).
67
+ - 4 MCP tools: `working_add`, `working_get`, `working_promote`
68
+ (to=decision|skill|playbook with check_conflict gate), and
69
+ `get_working_context` (compact markdown for ReAct loops).
70
+ - Decay score: `importance × exp(-Δt_hours / 6) + 0.5 ×
71
+ access_count`. Top-3 surfaces in `get_session_context`.
72
+ - Eviction = amendment tombstone; periodic compaction during
73
+ `codevira sync`.
74
+ - CLI: `codevira working commit <session_id>` archives a
75
+ session's live entries to
76
+ `.codevira/working_archived/<session_id>.jsonl`.
77
+
78
+ ### M3 — Skill library (procedural memory)
79
+
80
+ `.codevira/skills.jsonl` (canonical, team-shareable). FTS5
81
+ retrieval + composite ranking.
82
+
83
+ - `skill_fts` virtual table in the existing
84
+ `.codevira-cache/fts5.sqlite`. Independent staleness key
85
+ (`skill_source_mtime`) so the existing decisions tracking is
86
+ unaffected.
87
+ - Composite ranking:
88
+ `score = 0.5 × BM25_norm + 0.3 × tag_jaccard + 0.2 ×
89
+ recency_decay(τ=30d)`. Never-used skills score 0 recency —
90
+ reinforcement, not existence, drives the recency signal.
91
+ - 6 MCP tools: `record_skill`, `get_skill`, `apply_skill_outcome`,
92
+ `list_skills`, `supersede_skill`,
93
+ `promote_skill_to_playbook` (writes
94
+ `.codevira/playbooks/<task_type>/<slug>.md`).
95
+ - Lifecycle states: `active` (default), `archived` (5 consec
96
+ failures OR `unused_days ≥ 90` — configurable; do_not_revert
97
+ exempt), `superseded` (final).
98
+ - M5 wires git-derived outcomes_writer to skill reinforcement (see
99
+ below).
100
+
101
+ ### M4 — Spatial memory
102
+
103
+ Activity heatmap + folder-tree neighborhoods + affordances.
104
+
105
+ - `.codevira-cache/activity.jsonl` (per-machine). Auto-emitted on
106
+ Edit/Write via `memory_fanout` + on `decisions_store.record`
107
+ when `file_path` is set. Schema: `{id, ts, node_id, kind:
108
+ edit|decision_ref, session_id, origin, _schema_v: 1}`.
109
+ - 4 MCP tools: `spatial_nearby` (BFS ≤ 2 hops over the indexer
110
+ graph + same-neighborhood union, ranked by `(1/(1+bfs_dist)) ×
111
+ log(1+visit_count_30d)`), `spatial_heat`,
112
+ `spatial_neighborhood`, `spatial_affordances`.
113
+ - Folder-tree neighborhoods (top-2 dir components, e.g.,
114
+ `mcp_server/storage`). Project-overridable via
115
+ `.codevira/neighborhoods.yaml`.
116
+ - Bundled `mcp_server/data/affordances.yaml` mapping file globs to
117
+ task_type affordances (e.g., `mcp_server/tools/*.py` →
118
+ `{add_tool, write_test}`). Project override:
119
+ `.codevira/affordances.yaml`; bundled + project union per match.
120
+
121
+ ### M5 — Skill induction wired to outcomes_writer
122
+
123
+ Closes the reinforcement loop. Two pieces:
124
+
125
+ - **Sessions schema additions**: `task_type` (`feature` | `bug` |
126
+ `refactor` | `release` | `docs` | `other`) and `skill_ids: []`
127
+ (skills used during the session). Additive; legacy sessions
128
+ tolerate absence.
129
+ - **outcomes_writer fan-out**: when `observe_all()` classifies a
130
+ decision as `kept` or `reverted`, each skill referenced via
131
+ `skill_ids` on the same session gets `mark_used(success=…)`.
132
+ Pre-builds a `{session_id → set[skill_id]}` index so the
133
+ per-decision fan-out is O(1). Best-effort: skill errors log and
134
+ drop without blocking the decision-outcome write.
135
+ - **CLI**: `codevira induce-skills [--apply] [--yes]` —
136
+ deterministic induction (no LLM in v3.1.0). Pipeline: filter
137
+ sessions with ≥80% kept; group by task_type; cluster by
138
+ tag-Jaccard ≥ 0.5; keep clusters ≥3 sessions; render candidate
139
+ skill with `name = "<task_type>: <top-3 tags>"`,
140
+ `procedure = bullet-summary of session.task +
141
+ decision.decision` (capped 30 lines).
142
+
143
+ ### M6 — Consensus Phase B (cross-IDE conflict check, read-only)
144
+
145
+ - Per-IDE checkpoint files
146
+ `.codevira/checkpoints/<ide_key>.json` keyed on
147
+ `last_seen_decision_id` — zero-padded base-36 D-ids preserve
148
+ monotonic ordering without clock drift.
149
+ - `consensus_store.scan_and_materialize()`: walks decisions with
150
+ `id > checkpoint`, partitions by `origin.ide` into
151
+ `current_corpus` + `foreign`, runs the reused `check_conflict`
152
+ tokenize/Jaccard/overlap math on every pair, records matches as
153
+ PC-prefixed rows in `.codevira/pending_conflicts.jsonl`.
154
+ - 2 MCP tools: `consensus_check`, `consensus_status`.
155
+ `get_session_context` surfaces a top-3 panel sorted by
156
+ `(do_not_revert × recency)`.
157
+ - CLI: `codevira consensus check`. Read-only — no amendment rows
158
+ written on decisions.
159
+
160
+ ### M7 — Consensus Phase C handshake (opt-in, default off)
161
+
162
+ Opt-in belief-revision protocol gated behind
163
+ `memory.consensus.handshake_enabled` in `.codevira/config.yaml`.
164
+
165
+ - New `config.py` helper for dotted-key lookups against
166
+ `.codevira/config.yaml`.
167
+ - `propose_supersession` (cross-IDE) appends a
168
+ `proposed_supersession` row with `expires_at = ts +
169
+ handshake_timeout_days` (default 14, configurable). Same-IDE
170
+ fast-path returns `{fast_path: True}` so the caller routes to
171
+ `decisions_store.supersede` directly.
172
+ - `resolve_proposal(action: approved|rejected|withdrawn)`
173
+ appends a resolution row carrying `resolver_origin`.
174
+ - `finalize_proposal(expired_unilateral=False)` — approved
175
+ proposals turn into a real `decisions_store.supersede` call.
176
+ Expired proposals require `expired_unilateral=True` (deadlock
177
+ safety); the audit row records the force-finalize.
178
+ - 3 MCP tools: `consensus_propose_supersession`,
179
+ `consensus_resolve`, `origin_of` (provenance lookup; always
180
+ available).
181
+ - Row kind taxonomy in pending_conflicts.jsonl: `conflict` (M6),
182
+ `proposed_supersession` (M7), `resolution` (M7).
183
+
184
+ ### M8 — Reflections (durable LLM abstractions)
185
+
186
+ Generative-Agents-style abstractions over recent decisions +
187
+ sessions.
188
+
189
+ - `.codevira/reflections.jsonl` (canonical, committed) +
190
+ `.codevira/reflection_proposals.jsonl` (review staging).
191
+ - `scrub_sensitive` strips api keys, Bearer tokens, passwords,
192
+ AWS-style AKIA, long hex/base64 from source records before the
193
+ LLM sees them.
194
+ - `build_source_context` aggregates sessions + decisions in the
195
+ period window with plan caps (≤30 sessions, ≤100 decisions,
196
+ ≤6 KB envelope).
197
+ - Bundled prompt template at
198
+ `mcp_server/data/prompts/reflection_v1.md`.
199
+ - **MCP sampling integration scope**: v3.1.0 ships the storage +
200
+ sanitization + prompt rendering + the API surface. The
201
+ `sampling/createMessage` RPC that asks the host LLM for the
202
+ abstraction is the **v3.2** deliverable. v3.1.0 `reflect()`
203
+ returns `{sampling_supported: False, rendered_prompt,
204
+ source_context, deferred_to: "v3.2"}`; the CLI accepts an LLM
205
+ response via `--from-file`.
206
+ - 3 MCP tools: `reflect`, `get_reflections`, `list_reflections`.
207
+ - CLI: `codevira reflect [--period 7d] [--from-file PATH]
208
+ [--apply] [--yes]`. Render mode prints the prompt;
209
+ `--from-file` parses the LLM YAML response and writes a
210
+ proposal; `--apply --yes` commits to `reflections.jsonl`.
211
+
212
+ ### Schema versioning convention
213
+
214
+ All NEW JSONL stores (`working`, `skills`, `activity`,
215
+ `pending_conflicts`, `reflections`) carry `_schema_v: 1` on each
216
+ record. Readers tolerate absence (treats as v1). Existing
217
+ `decisions.jsonl` / `sessions.jsonl` are unchanged.
218
+
219
+ ### `get_session_context` panels
220
+
221
+ Now carries five panels in addition to the existing roadmap /
222
+ recent decisions:
223
+ - `working` — top-3 live entries (M2).
224
+ - `consensus` — top-3 pending conflicts (M6) sorted by
225
+ `(do_not_revert × recency)`.
226
+ The plan reserves panels for working, skills, spatial,
227
+ reflections in future ticks if value justifies the token cost.
228
+
229
+ ### Tests
230
+
231
+ ~450+ new tests across `tests/storage/`, `tests/test_tools_*`,
232
+ `tests/test_cli_*`, `tests/test_reflections.py`,
233
+ `tests/test_consensus_handshake.py`, etc. The full v3.1.0 suite
234
+ runs in <20s; zero regressions from the v3.0.x baseline.
235
+
236
+ ### Locked decisions honored
237
+
238
+ The v3.0.0 locks remain intact:
239
+ - D000001 (atomic writes through `mcp_server/storage/atomic.py`)
240
+ - D000012 (WRITE-path forbidden-root validation via
241
+ `ensure_dirs`)
242
+ - The v2.2.0 "no embeddings; FTS5 + Jaccard only" decision —
243
+ M3's skill retrieval and M6's conflict check both use the
244
+ existing FTS5/Jaccard infrastructure; no new embedding deps.
245
+
246
+ ---
247
+
248
+ ## [3.0.0] — 2026-05-27 — Lean, audited, opinionated
249
+
250
+ ### Hardened (RC audit — rounds 2 + 3, pre-publish)
251
+
252
+ > Three rounds of audit ran against the v3.0.0 release candidate
253
+ > before publishing. Round 1 was the surface-cut + dead-code sweep
254
+ > already recorded in the 3.0.0 entry below. Rounds 2 and 3 were
255
+ > "what could silently break in production?" — and surfaced a
256
+ > family of concurrent-write bugs in the storage layer that the
257
+ > structured unit tests didn't catch.
258
+
259
+ - **NEW `mcp_server/storage/atomic.py`** — single canonical source
260
+ for crash-safe file writes + Posix/Windows file locks. Every
261
+ storage / tool / cli module that touches the on-disk product
262
+ state now goes through this helper. Public API:
263
+ `atomic_write_text(path, content, *, mode=None)`,
264
+ `atomic_write_bytes(path, content, *, mode=None)`, and
265
+ `file_lock(path, *, exclusive=True)` (context manager — Posix
266
+ `fcntl.flock` + Windows sentinel-file fallback). Replaces 5
267
+ hand-rolled copies that had drifted (manifest, digest,
268
+ agents_md_generator, setup_wizard, jsonl_store). 11 unit tests
269
+ pin the contract (basic write, utf-8, overwrite, mkdir, mode
270
+ bits, no-leaked-tmp, 50-thread concurrency, binary, in-process
271
+ serialization, auto-anchor, exception release, Windows-sentinel
272
+ codepath via monkey-patched `sys.platform`).
273
+
274
+ - **Concurrent-write race fixes (rounds 2 + 3).** Two distinct
275
+ race shapes were caught under 50-thread stress:
276
+ - *Atomic-rename race* (round 2). `manifest.yaml`, `digest.jsonl`,
277
+ and `AGENTS.md` writers used a fixed `<path>.tmp` suffix; two
278
+ threads' `os.replace()` calls raced on the rename target,
279
+ producing `FileNotFoundError: <path>.tmp` warnings. The
280
+ decisions themselves still landed safely (`jsonl_store.append`
281
+ uses fcntl-locked I/O); only the CACHE files lost data. Fixed
282
+ by per-write unique tmp via `tempfile.mkstemp` (and now
283
+ consolidated through `storage/atomic`).
284
+ - *Lost-update race* (round 2 caught manifest; round 3 caught
285
+ roadmap). Read-modify-write paths (`manifest.incremental_add`,
286
+ `roadmap._save_roadmap`) had no lock — 50 concurrent updates
287
+ landed as ~37 because the last save() won. Fixed by
288
+ `atomic.file_lock` around the whole read-modify-write. Three
289
+ new regression tests in `tests/storage/test_concurrent_writes.py`
290
+ pin the invariants: zero rename warnings under 50-thread
291
+ record_decision, manifest counts match JSONL, roadmap phases
292
+ all land. P9 invariant test (corrupt manifest → decision
293
+ still persists in JSONL) added too.
294
+
295
+ - **Cross-process safety proved** (`tests/storage/test_cross_process_writes.py`).
296
+ Round-2 fixes were thread-safe but not yet proven process-safe —
297
+ two `codevira` MCP server processes (Claude Desktop + Cursor
298
+ running together) racing on the same project's roadmap could
299
+ still lose updates if the `fcntl.flock` contract didn't survive
300
+ process boundaries. Two new tests spawn 20 subprocesses via
301
+ `multiprocessing.spawn` and assert: 20 concurrent
302
+ `decisions_store.record` → 20 unique IDs; 20 concurrent
303
+ `roadmap.add_phase` → all 20 phases land in roadmap.yaml.
304
+
305
+ - **Engine policy storage-correctness audit.** Each of the 6 active
306
+ engine policies (`anti_regression`, `blast_radius`,
307
+ `decision_lock`, `post_edit_refresh`, `relevance_inject`,
308
+ `token_budget`) was read line-by-line to confirm it reads from
309
+ the v3.0.0 storage layer, not the legacy SQLiteGraph paths.
310
+ One drift found: `signals.graph` round-2 fix added v3.0.0
311
+ `.codevira-cache/graph.sqlite` as the priority-1 resolution
312
+ tier — pre-fix it only checked v1.5 / v1.6 paths, structurally
313
+ silencing `BlastRadiusVeto` and the `DecisionLock` no-rationale
314
+ branch on every v3.0.0 project. Similarly `signals.decisions`
315
+ was rewired to read JSONL (was reading a SQL table that no
316
+ longer exists in v3.0.0).
317
+
318
+ - **MCP tools/list inputSchema audit.** All 23 surfaced MCP tools
319
+ validated for schema consistency (every required field in
320
+ properties, every tool has a description, every schema is
321
+ `type: object`). Zero issues.
322
+
323
+ - **NEW `scripts/chaos_smoke.py`** — adversarial probe of the
324
+ storage layer with 8 attack categories / 29 sub-tests (null
325
+ bytes, 1 MB decision text, path traversal in `file_path`,
326
+ control chars, SIGKILL during fcntl.flock, manually-corrupted
327
+ JSONL/YAML/AGENTS.md, 200-thread mixed-op storm, 20-thread
328
+ lock contention, symlink traversal via
329
+ `AGENTS.md → /etc/passwd`, 7 malformed JSON-RPC payloads to
330
+ `codevira serve`, read-only `.codevira/` dir). Result on
331
+ current commit: 29 PASS / 0 FAIL. Notable findings (not bugs,
332
+ design choices worth surfacing):
333
+ - All adversarial decision inputs are accepted (no validation
334
+ today; trust-the-agent design). v3.1 candidate for sanitization.
335
+ - Symlink safety is automatic: `atomic.os.replace` replaces the
336
+ symlink itself, not the target, so an attacker who plants
337
+ `AGENTS.md → /etc/passwd` can't escape the project root.
338
+ - fcntl.flock survives SIGKILL of the holder (kernel reaps
339
+ fd-bound locks).
340
+
341
+ - **`check_conflict` asymmetric-overlap detector for contradictions
342
+ against `do_not_revert` decisions.** The original v2.2.0 implementation
343
+ used pure symmetric Jaccard similarity with a 0.60 threshold — which
344
+ misses the common contradiction shape where a terse new decision
345
+ shares 3 of its 4 content tokens with a longer protected decision
346
+ (Jaccard = 3/9 = 0.333, below threshold; overlap coefficient =
347
+ 3/min(4,8) = 0.75, above threshold). Caught by the AgentStore
348
+ system test (`scripts/system_test_agentstore.py::A9`).
349
+
350
+ Fix adds an asymmetric overlap-coefficient path that fires ONLY
351
+ for candidates with `do_not_revert=True` AND with at least 3 shared
352
+ tokens AND with symmetric Jaccard below 0.60 (the
353
+ re-affirmation filter — re-recording a protected decision verbatim
354
+ still hits the duplicate path, not the new asymmetric path).
355
+ Duplicate detection itself (against any decision) stays symmetric +
356
+ conservative (Jaccard ≥ 0.60) — the change is conflict-specific.
357
+
358
+ Response shape adds `match_shape` (`"duplicate"` |
359
+ `"asymmetric-conflict"`), `jaccard`, `overlap_coefficient`,
360
+ `shared_tokens` per match entry + a top-level `thresholds` dict.
361
+ Existing `threshold_used` field preserved for v2.x callers.
362
+ 17 new unit tests in `tests/test_check_conflict.py` pin both
363
+ regimes + the re-affirmation filter.
364
+
365
+ - **Repointed 11 more unguarded writes at `storage.atomic`** —
366
+ the round-3 write-site sweep found `auto_init` (config.yaml +
367
+ metadata.json), `cli_init` (config.yaml + enforcement.yaml +
368
+ .gitignore), `http_server` (bearer token, +0o600 mode),
369
+ `cli_uninstall` (settings.json + AGENTS.md, 3 sites),
370
+ `cli_hooks_admin` (settings.json — was fixed-suffix tmp race),
371
+ `cli.py` (legacy `cmd_configure` + git hook write), `cli_export`
372
+ (JSON + SQL exports — both had fixed-suffix tmp races),
373
+ `cli_replay`, `log_retention`, `migrate`, and
374
+ `indexer/graph_generator` (roadmap stub). All now crash-safe via
375
+ the shared helper.
376
+
377
+ - **Doctor dogfooded against a real project + a fresh init.**
378
+ Fresh `codevira init` followed by `codevira doctor` = 13 pass /
379
+ 1 warn (pre-existing ghost dirs from earlier testing) / 0 fail.
380
+
381
+ ### Added (2026-05-26 dogfood batch)
382
+
383
+ - **`codevira graph`** — render the project's decision memory as a
384
+ single self-contained, interactive HTML file (nodes = decisions,
385
+ edges = supersedes lineage) with a client-side query/filter box and
386
+ details panel. Zero runtime dependencies, no server, works offline;
387
+ reads the canonical `.codevira/decisions.jsonl`. Inlined JSON escapes
388
+ `<` so decision text can't break out of the data island. Output
389
+ defaults to `.codevira-cache/memory-graph.html`. (D000016)
390
+ - **`summary_only` on `list_decisions`** — parity with
391
+ `search_decisions`: returns the tiny `{id, summary, do_not_revert}`
392
+ shape and takes precedence over `full`. (D000015)
393
+ - **`CODEVIRA_TOOL_PROFILE=lean`** — opt-in environment variable that
394
+ trims the advertised MCP `tools/list` from 24 to 11 daily-driver
395
+ tools (~46%, ~1.9K fewer tokens per session). Default advertises all
396
+ tools; hidden tools still work when called explicitly. (D000018)
397
+
398
+ ### Fixed (2026-05-26 dogfood batch)
399
+
400
+ - **`ensure_dirs()` refuses a forbidden project root** ($HOME / system
401
+ dirs) on the v3.0.0 JSONL write path — the WRITE-side counterpart of
402
+ the guard `get_data_dir()` already applied. Closes a trap where a
403
+ *global* MCP config (e.g. Claude Desktop, no cwd, no
404
+ `CODEVIRA_PROJECT_DIR`) resolved the root to `/` and silently created
405
+ `/.codevira` or `$HOME/.codevira`. Raises a WHAT+WHY+FIX error naming
406
+ `CODEVIRA_PROJECT_DIR`; read paths stay graceful. (D000012)
407
+
408
+ ### Changed (2026-05-26 dogfood batch)
409
+
410
+ - Trimmed the longest MCP tool description (`record_decision`) to cut
411
+ per-session token cost while preserving its `do_not_revert` +
412
+ `supersede`/`set_decision_flag` guidance. (D000018)
413
+
414
+ ### Known limitations (shipping in 3.0.0; tracked for a later release)
415
+
416
+ - **Graph spec vs implementation drift.** `paths.graph_cache_path()`
417
+ documents the v3.0.0 spec location as
418
+ `<project>/.codevira-cache/graph.sqlite`, but `indexer/` and
419
+ `tools/graph.py` still write to / read from
420
+ `<data_dir>/graph/graph.db` (the legacy v1.6 centralized
421
+ location). Runtime behavior is correct — everyone agrees on the
422
+ centralized location and `signals._load_graph()` finds it via
423
+ the fallback chain. The spec-truthfulness gap should be
424
+ reconciled in v3.1 with a migration step for existing installs.
425
+
426
+ - **Decision input sanitization is deliberately absent.** Null
427
+ bytes, 1 MB text, path traversal in `file_path`, control
428
+ characters, and empty strings are accepted today. The chaos
429
+ harness surfaced this; a v3.1 hardening pass could add
430
+ per-field validation without breaking the trust-the-agent
431
+ default.
432
+
433
+ - **Cross-process flock tested on macOS only.** The
434
+ `multiprocessing.spawn` context is the same on Linux CI, but
435
+ the cross-process test has not been exercised on Windows
436
+ (where the helper uses the sentinel-file fallback instead of
437
+ fcntl).
438
+
439
+ - **`relevance_inject` can surface weakly-related decisions on
440
+ short prompts.** The current SessionStart / UserPromptSubmit
441
+ injection scores tag + file + FTS5-BM25; with the v3.0 default
442
+ `min_score=0.10`, the top FTS5 hit alone (~0.10) is enough to
443
+ clear the gate on prompts with no tag or file overlap. Tightening
444
+ the gate naively breaks the core cross-tool wedge
445
+ (`tests/e2e/test_cross_tool_universality.py`) — FTS-only recall
446
+ IS the keyword-search path for tagless / file-less queries from
447
+ Cursor / Windsurf / Antigravity. A proper fix needs a
448
+ precision/recall benchmark with a corpus of real prompts +
449
+ decisions and a multi-prompt e2e test added BEFORE the threshold
450
+ change. Deferred to v3.0.1.
451
+
452
+ ---
453
+
454
+ ### Initial 3.0.0 RC milestone (2026-05-22)
455
+
456
+ > **Major version bump.** This is the biggest API contraction since
457
+ > v2.0 shipped: 21 MCP tools deleted, 8 CLI subcommands deleted,
458
+ > per-IDE nudge file matrix collapsed to AGENTS.md only, IDE
459
+ > detection hardened from "directory exists" to "binary on PATH +
460
+ > valid config file." The cuts are subtractive — any v2.x user who
461
+ > upgrades will lose surface they MAY have been using. SemVer
462
+ > requires the major bump.
463
+ >
464
+ > The driver: a 2026-05-22 surface-cut audit (see
465
+ > `docs/audit-2026-05-22.md`) traced 5 categories of user
466
+ > complaints to overgrown surface, false-positive IDE detections,
467
+ > and "junk left behind" after uninstall. v3.0.0 fixes all five
468
+ > categories. See `docs/surface-cuts-2026-05-22.md` for the
469
+ > per-item kill list.
470
+ >
471
+ > v3.0.0 includes everything in the unreleased v2.2.0+ work plus
472
+ > two additional pieces:
473
+ > - Full dead-code sweep across the whole repo (~3,800 lines
474
+ > removed) after the surface cuts surfaced obviously-dead
475
+ > internal helpers
476
+ > - IDE auto-detection hardened: strong signals only, ``--force``
477
+ > escape hatch, no more silent-filter on `--ide` for
478
+ > undetected IDEs
479
+
480
+ ### Added
481
+
482
+ - **`codevira uninstall` command (Phase 5).** Reverses every system
483
+ write made by `codevira init` / `codevira setup`: drops the MCP
484
+ entry from `~/.claude.json`, deletes `~/.claude/hooks/codevira-*.sh`,
485
+ strips codevira-tagged registrations from `~/.claude/settings.json`,
486
+ removes per-project `.codevira/` + `.codevira-cache/` dirs, and
487
+ strips the codevira marker block from each project's `AGENTS.md`
488
+ (preserves user content outside the markers byte-for-byte). Optional
489
+ `--keep-data` skips per-user `~/.codevira/`. Closes the audit's
490
+ "uninstalling left junk" complaint — `pipx uninstall codevira` used
491
+ to leave ~15 system touch points behind.
492
+
493
+ - **`codevira setup --force`.** Escape hatch for the rare case where
494
+ codevira's IDE detector misses an install (portable binary not on
495
+ PATH, non-standard config location). Without ``--force``, passing
496
+ `--ide cursor` on a machine where Cursor isn't auto-detected raises
497
+ a clear error pointing at the flag. The v2.x silent-filter behavior
498
+ (which made ``setup --ide cursor`` exit 0 with no output and no
499
+ config on Cursor-less machines) is gone.
500
+
501
+ - **Legacy per-IDE nudge back-compat sweep** in `codevira uninstall`:
502
+ for upgraders from v2.1.x, also strips codevira marker blocks from
503
+ `CLAUDE.md`, `GEMINI.md`, `.cursor/rules/codevira.mdc`,
504
+ `.windsurfrules`, `.github/copilot-instructions.md`.
505
+
506
+ - **`record_decision` MCP tool now forwards `tags` and `force`** —
507
+ these were silently dropped by the dispatch layer in v2.x; now
508
+ agents' tag intent actually persists when loop-calling the endpoint.
509
+
510
+ ### Changed
511
+
512
+ - **IDE auto-detection hardened (mcp_server/ide_inject.py).** Each
513
+ detector now requires a STRONG signal: either the IDE's binary on
514
+ PATH, or a verified config file (not just a parent dir). v2.x had
515
+ three WEAK detectors (Claude Desktop, Antigravity, Continue.dev)
516
+ that fired on the presence of an empty directory — false positives
517
+ that caused codevira to write MCP config for IDEs the user never
518
+ installed. v3.0.0 cross-checks.
519
+
520
+ | IDE | v2.x signal | v3.0.0 signal |
521
+ |-----------------|--------------------------------|--------------------------------------------------|
522
+ | Claude Code | `.claude/ OR claude on PATH` | `claude on PATH` |
523
+ | Claude Desktop | parent dir of config exists | config FILE exists AND parses as JSON |
524
+ | Cursor | `~/.cursor/ OR cursor on PATH` | `~/.cursor/ AND (mcp.json OR cursor on PATH)` |
525
+ | Windsurf | `~/.windsurf/ OR ~/.codeium/…` | actual mcp_config.json exists in either location |
526
+ | Antigravity | `~/.gemini/ exists` | `~/.gemini/antigravity/mcp_config.json exists` |
527
+
528
+ - **`setup_wizard.detect_targets`** raises a clear ``ValueError`` on
529
+ `--ide <name>` for known IDEs that weren't auto-detected (use
530
+ `--force` to override). v2.x silently filtered the request, which
531
+ produced the worst possible UX: command exit 0 with no output.
532
+
533
+ - **Per-IDE nudge files collapsed to AGENTS.md only.** The setup
534
+ wizard now writes exactly one nudge file (`AGENTS.md` via the new
535
+ `mcp_server.storage.agents_md_generator`) regardless of which IDEs
536
+ are detected. Per-IDE duplicates (`CLAUDE.md` / `GEMINI.md` /
537
+ `.cursor/rules/codevira.mdc` / `.windsurfrules` /
538
+ `.github/copilot-instructions.md`) were pure surface bloat — every
539
+ modern AI tool reads AGENTS.md natively.
540
+
541
+ - **`codevira doctor`'s `nudge_files` check** rewritten to verify
542
+ AGENTS.md only; fix command updated to `codevira sync`.
543
+
544
+ - **`mcp_server.global_sync`** gutted from a 187-line bidirectional
545
+ preference + rule sync to a ~90-LOC project-registry helper. New
546
+ primary entry: ``register_current_project()``. v2.x
547
+ ``import_global_to_project`` kept as a back-compat alias.
548
+
549
+ - **MCP prompt library** pruned from 5 templates to 1
550
+ (``onboard_session``). The 4 deleted templates referenced MCP tools
551
+ that the audit deleted (analyze_changes, find_hotspots,
552
+ get_learned_rules, get_preferences, get_project_maturity,
553
+ list_open_changesets, export_graph, list_nodes, search_codebase).
554
+
555
+ ### Removed
556
+
557
+ **MCP tools (46 → 24, –48%):**
558
+
559
+ - Batch 1 — Changesets:
560
+ `start_changeset`, `update_changeset_progress`, `complete_changeset`,
561
+ `list_open_changesets` (entire feature; ~zero real users).
562
+ - Batch 2 — Preferences + learned rules:
563
+ `get_preferences`, `get_learned_rules`, `retire_rule` (auto-extracted
564
+ signals were noise more than signal).
565
+ - Batch 4a — Vestigial graph helpers:
566
+ `update_node`, `list_nodes`, `add_node`, `export_graph`,
567
+ `get_graph_diff`, `get_decision_confidence`, `get_project_maturity`,
568
+ `analyze_changes`, `find_hotspots`.
569
+ - Batch 6 — Redundant / FOLD candidates:
570
+ `record_decisions` (batch — loop single-record instead),
571
+ `write_session_logs` (batch — same),
572
+ `mark_decision_protected` (use
573
+ `supersede_decision(..., do_not_revert=True)` for the same flip +
574
+ audit trail),
575
+ `refresh_index` (chromadb-era; `refresh_graph` is the still-active
576
+ code-graph refresh tool),
577
+ `get_full_roadmap` (duplicate of `get_roadmap` with a flag).
578
+
579
+ **CLI subcommands (23 → 15, –35%, batch 4b):**
580
+
581
+ - `heal`, `budget`, `agents`, `hooks`, `register`, `configure`,
582
+ `report`, `calibrate`, `insights`. Folded into `init` / `setup` /
583
+ `doctor` where they had real successors; deleted outright where
584
+ they had ~zero real usage.
585
+
586
+ **Engine policies (10 → 6, –40%, batch 3):**
587
+
588
+ - `LiveStyleEnforcement`, `AIPromotionScore`, `ProactiveIntentInference`,
589
+ `ProactiveScopeContractLock`. Default policy set:
590
+ `BlastRadiusVeto`, `DecisionLock`, `RelevanceInject`,
591
+ `TokenBudgetPersist`, `AntiRegression`, `PostEditGraphRefresh`.
592
+
593
+ **Per-project nudge files (6 → 1, –83%, batch 5):**
594
+
595
+ - `mcp_server/agents_md.py` (the legacy per-IDE nudge writer) + 7
596
+ templates (`claude_md.tmpl`, `cursor_rules.mdc.tmpl`,
597
+ `windsurfrules.tmpl`, `gemini_md.tmpl`,
598
+ `copilot_instructions.tmpl`, `agents_md.tmpl`,
599
+ `canonical_block.md`). The v3.0.0 `storage/agents_md_generator.py`
600
+ generates AGENTS.md content directly from `decisions.jsonl`.
601
+
602
+ **Dead-code sweep (after audit deletions):**
603
+
604
+ - `indexer/rule_learner.py` (~250 LOC; consumed only by deleted MCP
605
+ tools).
606
+ - 7 dead functions in `mcp_server/tools/graph.py` (~408 LOC).
607
+ - 7 dead methods in `indexer/sqlite_graph.py` (preferences +
608
+ learned_rules + project_maturity tables stay in the schema for
609
+ back-compat but are never written or read).
610
+ - `mcp_server/tools/learning.py::get_project_maturity` +
611
+ `_compute_maturity_score` / `_maturity_level` / `_maturity_hint`.
612
+ - `mcp_server/engine/signals.py::SignalContext.preferences`
613
+ (was broken — imported a non-existent symbol; v2.x would have
614
+ crashed on first call from any consuming policy).
615
+ - `mcp_server/engine/signals.py::SignalContext.outcomes` +
616
+ `.learned_rules` (no-op stubs after batch 3).
617
+ - 15 dead test classes across the test suite (matched to deleted
618
+ features).
619
+
620
+ **IDE detector entries:**
621
+
622
+ - `continue.dev` and `aider` no longer in the detector output. Neither
623
+ had a codevira-configurable integration path; their entries existed
624
+ only as advisory listings (pure noise).
625
+
626
+ ### Counts (v2.1.x → v3.0.0)
627
+
628
+ | Surface | v2.1.x | v3.0.0 | Δ |
629
+ |---------------------------------|--------------|------------|--------|
630
+ | MCP tools | 46 | 24 | -48% |
631
+ | CLI subcommands | 23 | 15 | -35% |
632
+ | Engine policies | 10 | 6 | -40% |
633
+ | Per-project nudge files | 6 | 1 | -83% |
634
+ | Templates shipped in the wheel | 7 | 0 | n/a |
635
+ | MCP prompt library | 5 | 1 | -80% |
636
+ | Pipx install size | ~450 MB | ~83 MB | -82% |
637
+ | MCP server startup | 1–3 s | <100 ms | -97% |
638
+ | Tests (passing) | 2354 | 1870 + 72 | rebased |
639
+
640
+ ### Migration notes
641
+
642
+ Most deletions have a clear successor in this file's `### Removed`
643
+ sections. Two with non-obvious mappings:
644
+
645
+ - **From `mark_decision_protected(id, True)`** →
646
+ `supersede_decision(old_id=id, new_decision=<text>, reason=<why>,
647
+ do_not_revert=True)`. The supersede path gives you the audit trail
648
+ (why you flipped the flag) that the standalone tool didn't.
649
+ - **From `record_decisions(decisions=[...])`** → for d in decisions:
650
+ `record_decision(**d)`. The audit found agents called single-record
651
+ in practice anyway, so this is the actually-used pattern.
652
+
653
+ The `codevira uninstall` command picks up any legacy artifacts on
654
+ disk from earlier versions (per-IDE nudge files, etc.) so users
655
+ upgrading don't need to hand-clean.
656
+
657
+ For IDE detection changes: if you previously relied on codevira
658
+ configuring Claude Desktop / Antigravity / Cursor based on the
659
+ presence of a directory, you may now need to either:
660
+ (a) actually install the IDE so the binary is on PATH (or so the
661
+ relevant config file exists), OR
662
+ (b) re-run `codevira setup --ide <name> --force` to override the
663
+ detector and configure anyway.
664
+
665
+ The strict mode is the right default. The audit found false-positive
666
+ configurations (codevira injected into IDEs the user never installed)
667
+ were a real churn driver — silently writing config for absent apps
668
+ makes users distrust the tool.
669
+
670
+ ---
671
+
672
+ ## [2.2.0] — 2026-05-20 — Lean (in-repo, no chromadb, token-optimized)
673
+
674
+ > The biggest architectural change since v2.0. Decisions move from
675
+ > SQLite into git-tracked JSONL in your repo. ChromaDB / sentence-
676
+ > transformers / torch removed entirely; tree-sitter-language-pack
677
+ > (351 MB) replaced by 4 individual grammar packages (TS / JS / Go /
678
+ > Rust) totaling ~5 MB. Pipx install drops from ~450 MB (v2.1.2 with
679
+ > the full grammar stack) to ~85 MB; MCP server starts in <100ms;
680
+ > per-project disk drops from 40-80 MB to ~1-2 MB. See
681
+ > `docs/plans/v2.2.0.md` for the full plan.
682
+
683
+ ### Changed (architecture)
684
+
685
+ - **Decision storage moved to `<repo>/.codevira/decisions.jsonl`** —
686
+ human-readable, git-committed, team-shareable. Visible in `git diff`
687
+ as one-decision-per-line. Replaces v2.1.x's `~/.codevira/projects/
688
+ <key>/graph/graph.db` SQLite blob for decisions (the code graph
689
+ stays in SQLite cache).
690
+ - **Sessions / preferences / learned_rules / changesets / outcomes /
691
+ roadmap also move to `.codevira/*.jsonl`**. The `.codevira-cache/`
692
+ dir (gitignored) holds the FTS5 index + code-graph SQLite + hash
693
+ cache (rebuildable by `codevira sync` / `codevira index`).
694
+ - **AGENTS.md auto-generated** with hard **5 KB cap**. Marker-bounded
695
+ (`<!-- codevira:begin -->` / `<!-- codevira:end -->`) so user-edited
696
+ content outside is preserved byte-for-byte. Every `record_decision`
697
+ regenerates it synchronously. Other AI tools (Copilot, Codex,
698
+ Cursor, Gemini, Factory, Amp, Windsurf, Zed, RooCode, Jules) read
699
+ AGENTS.md natively — codevira's decisions are now portable.
700
+
701
+ ### Removed (dropped from the runtime)
702
+
703
+ - **ChromaDB + sentence-transformers + torch deleted entirely.**
704
+ ~150 MB of dependencies gone. Pipx install ≤100 MB (gated by the
705
+ cold-install smoke G2.5). MCP server startup <100ms (was 1-3s due
706
+ to torch warmup).
707
+ - **tree-sitter-language-pack (351 MB, 17 grammars) replaced** with
708
+ individual grammar packages: `tree-sitter-typescript`,
709
+ `tree-sitter-javascript`, `tree-sitter-go`, `tree-sitter-rust`
710
+ (~5 MB total). Long-tail languages (Java, C, C++, Ruby, PHP,
711
+ Kotlin, Swift, Solidity, etc.) remain available via the opt-in
712
+ extra `pip install 'codevira[all-languages]'` which re-adds the
713
+ legacy pack. This is the single biggest contributor to the v2.2.0
714
+ size cut.
715
+ - **`search_codebase` MCP tool removed.** AI agents grep + Read files
716
+ natively in 2026; semantic code search was the source of 90%+ of
717
+ v2.1.x disk usage and every major bug (issue #10 Antigravity dlopen,
718
+ 64 GB HNSW corruption, write amplification). Calling the tool now
719
+ returns a friendly explanation pointing at grep/Read.
720
+ - **`codevira calibrate` CLI command removed.** No more semantic
721
+ thresholds (FTS5 has no learnable thresholds; uses BM25 BM25 ranking).
722
+ - **`prewarm_embedding_model()` removed.** No model to warm.
723
+ - **`mcp_server/cli_calibrate.py`, `mcp_server/tools/_decision_embeddings.py`,
724
+ `mcp_server/engine/policies/cross_session.py`** — all deleted.
725
+ ~1,500 LOC of v2.1.x code gone.
726
+
727
+ ### Added
728
+
729
+ - **`mcp_server/storage/`** new package:
730
+ - `jsonl_store.py` — atomic append, file lock, monotonic IDs,
731
+ UTF-8/emoji/CJK roundtrip
732
+ - `fts5_index.py` — SQLite FTS5 BM25 keyword search, <50ms on
733
+ 1000-decision corpus
734
+ - `manifest.py` — tag/file → id index in YAML
735
+ - `digest.py` — slim per-decision records with outcome-weighted
736
+ scoring
737
+ - `token_estimator.py` — char-based proxy (4 chars/token); optional
738
+ tiktoken via `CODEVIRA_TOKEN_PRECISION=exact`
739
+ - `agents_md_generator.py` — 5 KB-capped AGENTS.md regen with
740
+ marker preservation
741
+ - `decisions_store.py`, `sessions_store.py` — high-level facades
742
+ - `paths.py` — single source of truth for `.codevira/` paths
743
+ - **`mcp_server/engine/policies/relevance_inject.py`** — replaces
744
+ `cross_session.py`. Token-bounded injection:
745
+ - **Off-topic prompt → 0 tokens** (no `additionalContext` at all)
746
+ - **On-topic prompt → ≤600 tokens, ≤3 decisions**
747
+ - Scoring: tag (0.4) + file (0.4) + FTS5 (0.2) × outcome_weight
748
+ - Cache-stable output (sorted IDs, no timestamps,
749
+ `<codevira-context cache_key="...">` wrapper)
750
+ - Config via `.codevira/config.yaml` or `CODEVIRA_INJECT_*` env vars
751
+ - **`codevira sync`** CLI command — regenerate manifest + digest +
752
+ FTS5 + AGENTS.md from `decisions.jsonl`. Manual / recovery path
753
+ (every record_decision triggers regen synchronously).
754
+
755
+ ### Backwards compatibility
756
+
757
+ - **No migration from v2.1.x.** Per the v2.2.0 plan: clean break.
758
+ Users `codevira init` on each project to scaffold `.codevira/`.
759
+ v2.1.x continues to exist on PyPI for users who don't upgrade.
760
+ Optional `codevira archive-legacy` preserves v2.1.x decisions as a
761
+ read-only reference.
762
+ - **Decision IDs change from int (`1`, `2`) to string (`D000001`,
763
+ `D000002`).** Tools that round-trip IDs as opaque values continue
764
+ to work. Code that hardcodes int IDs needs updating.
765
+ - **`check_conflict` MCP tool semantics shifted from semantic to
766
+ Jaccard text similarity** (FTS5 candidate pool + Jaccard token-set).
767
+ Threshold tuned conservatively (0.60).
768
+
769
+ ### Tests
770
+
771
+ - 141 new tests across `tests/storage/` and `tests/engine/test_relevance_inject.py`
772
+ - Existing integration suite (`tests/integration/test_mcp_roundtrip.py`)
773
+ passes 13/14 against new backend (the 14th is a chromadb-availability
774
+ test, skipped permanently now)
775
+
776
+ ### Removed — legacy v2.1.x compatibility paths (no carryover users)
777
+
778
+ Once the v2.1.x user base dropped to zero (per maintainer's
779
+ 2026-05-22 directive: "no users; go fresh"), the defensive
780
+ SQLiteGraph fallback branches added during Phase B's incremental
781
+ migration became dead weight. Removed:
782
+
783
+ - **`build_timeline(conn=...)` SQL backend** — `build_timeline()` is
784
+ now JSONL-only; the `conn` parameter is gone. Resource handler,
785
+ CLI replay, and tests all read from `.codevira/{decisions,
786
+ outcomes, sessions}.jsonl` exclusively. Public API simplified.
787
+ - **`SignalContext.search_decisions` graph.db fallback** — JSONL FTS5
788
+ is the only backend; the legacy `graph.search_decisions()` branch
789
+ is gone. Returns `[]` cleanly when `.codevira/` isn't initialised.
790
+ - **`treesitter_parser._load_parser_for` legacy pack fallback** —
791
+ unsupported languages now raise ValueError immediately with an
792
+ actionable message. The `[all-languages]` opt-in extra is gone.
793
+ v2.3.0 may re-introduce specific long-tail grammars as individual
794
+ deps if real demand emerges.
795
+ - **Ported tests** that exercised the SQL path (test_decision_replay,
796
+ test_qa_round_week10/13, test_v2_release_candidate, test_cli_replay)
797
+ to use the JSONL planter helper (`decisions_store.record` +
798
+ `jsonl_store.append(outcomes_path, ...)`). Test count unchanged at
799
+ 2,514 passes.
800
+
801
+ ### Fixed — cross-tool wedge gaps (post-Phase-G completeness)
802
+
803
+ The cross-tool universality e2e tests surfaced several read paths
804
+ that Phase B's "tool surface repointed at JSONL" pass missed. All
805
+ fixed in the same release:
806
+
807
+ - **`SignalContext.search_decisions`** now reads via
808
+ `decisions_store.search()` (FTS5 over JSONL) when `.codevira/` is
809
+ initialized. The legacy `SQLiteGraph.search_decisions()` is kept
810
+ as a fallback for v2.1.x projects.
811
+ - **`codevira replay` CLI + `codevira://decisions` MCP resource**
812
+ now read from `.codevira/decisions.jsonl` + `.codevira/outcomes.jsonl`
813
+ + `.codevira/sessions.jsonl`. Both surface decisions recorded via
814
+ `record_decision` immediately, with outcome counts aggregated from
815
+ `outcomes.jsonl` (kept/modified/reverted). SQLiteGraph fallback
816
+ preserved for v2.1.x.
817
+ - **FTS5 index now indexes `file_path`** (BM25 weight 0.8) so search
818
+ queries like `"retries"` match decisions whose only reference to
819
+ the term is in the file path. Existing FTS5 caches without the new
820
+ column are detected and auto-dropped + rebuilt on the next search.
821
+ - **FTS5 `_sanitize_fts_query` now OR-joins terms** with stopword +
822
+ short-token stripping. The previous implicit-AND turned every
823
+ multi-word prompt into an over-strict phrase query — e.g. asking
824
+ "What did we decide about bcrypt for password hashing?" missed the
825
+ decision "use bcrypt over argon2" because "password" and "hashing"
826
+ aren't in the stored text. The off-topic 0-token gate
827
+ (`relevance_min_score=0.10`) still suppresses irrelevant matches.
828
+ - **`decisions_store.record` and `record_many` now append
829
+ `digest.jsonl` incrementally**. Previously digest was only
830
+ regenerated via `codevira sync` / `rebuild_indexes()`, so the
831
+ relevance-inject policy showed `(decision summary unavailable —
832
+ try codevira sync)` for decisions recorded since the last sync.
13
833
 
14
834
  ## [2.1.2] — 2026-05-19 — Trust recovery + QoL
15
835