claude-code-workflow 6.1.4 → 6.2.2

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 (437) hide show
  1. package/.claude/CLAUDE.md +10 -0
  2. package/.claude/agents/action-planning-agent.md +857 -778
  3. package/.claude/agents/cli-execution-agent.md +266 -269
  4. package/.claude/agents/cli-explore-agent.md +2 -2
  5. package/.claude/agents/cli-lite-planning-agent.md +142 -92
  6. package/.claude/agents/cli-planning-agent.md +4 -4
  7. package/.claude/agents/code-developer.md +7 -6
  8. package/.claude/agents/conceptual-planning-agent.md +2 -2
  9. package/.claude/agents/context-search-agent.md +31 -32
  10. package/.claude/agents/doc-generator.md +4 -4
  11. package/.claude/agents/memory-bridge.md +93 -93
  12. package/.claude/agents/test-context-search-agent.md +8 -7
  13. package/.claude/agents/test-fix-agent.md +7 -6
  14. package/.claude/commands/clean.md +516 -0
  15. package/.claude/commands/memory/compact.md +383 -0
  16. package/.claude/commands/memory/docs-full-cli.md +471 -471
  17. package/.claude/commands/memory/docs-related-cli.md +386 -386
  18. package/.claude/commands/memory/docs.md +615 -615
  19. package/.claude/commands/memory/load.md +5 -5
  20. package/.claude/commands/memory/tech-research-rules.md +310 -0
  21. package/.claude/commands/memory/update-full.md +332 -332
  22. package/.claude/commands/memory/workflow-skill-memory.md +4 -4
  23. package/.claude/commands/task/create.md +151 -151
  24. package/.claude/commands/version.md +254 -254
  25. package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
  26. package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
  27. package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
  28. package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
  29. package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
  30. package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
  31. package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
  32. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  33. package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
  34. package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
  35. package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
  36. package/.claude/commands/workflow/debug.md +321 -0
  37. package/.claude/commands/workflow/execute.md +13 -0
  38. package/.claude/commands/workflow/init.md +165 -164
  39. package/.claude/commands/workflow/lite-execute.md +119 -13
  40. package/.claude/commands/workflow/lite-fix.md +623 -621
  41. package/.claude/commands/workflow/lite-plan.md +610 -592
  42. package/.claude/commands/workflow/plan.md +5 -5
  43. package/.claude/commands/workflow/review-module-cycle.md +2 -0
  44. package/.claude/commands/workflow/review-session-cycle.md +2 -0
  45. package/.claude/commands/workflow/review.md +297 -291
  46. package/.claude/commands/workflow/session/complete.md +153 -500
  47. package/.claude/commands/workflow/session/list.md +95 -95
  48. package/.claude/commands/workflow/session/resume.md +60 -60
  49. package/.claude/commands/workflow/session/start.md +199 -199
  50. package/.claude/commands/workflow/tdd-plan.md +3 -3
  51. package/.claude/commands/workflow/tdd-verify.md +23 -9
  52. package/.claude/commands/workflow/test-cycle-execute.md +2 -0
  53. package/.claude/commands/workflow/test-fix-gen.md +699 -699
  54. package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
  55. package/.claude/commands/workflow/tools/context-gather.md +436 -434
  56. package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
  57. package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
  58. package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
  59. package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
  60. package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
  61. package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
  62. package/.claude/skills/command-guide/SKILL.md +5 -5
  63. package/.claude/skills/command-guide/index/all-commands.json +1 -1
  64. package/.claude/skills/command-guide/index/by-category.json +1 -1
  65. package/.claude/skills/command-guide/index/by-use-case.json +1 -1
  66. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
  67. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
  68. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
  69. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
  70. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
  71. package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
  72. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
  73. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
  74. package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
  75. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
  76. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
  77. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
  78. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
  79. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
  80. package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
  81. package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
  82. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
  83. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
  84. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
  85. package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
  86. package/.claude/skills/command-guide/reference/commands/version.md +254 -254
  87. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
  88. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
  89. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
  90. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
  91. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
  92. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
  93. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  94. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
  95. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
  96. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
  97. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
  98. package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
  99. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
  100. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
  101. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
  102. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
  103. package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
  104. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
  105. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
  106. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
  107. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
  108. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
  109. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
  110. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
  111. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
  112. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
  113. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
  114. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
  115. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
  116. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
  117. package/.claude/workflows/chinese-response.md +38 -0
  118. package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
  119. package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
  120. package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
  121. package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
  122. package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
  123. package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
  124. package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
  125. package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
  126. package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
  127. package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
  128. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
  129. package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
  130. package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
  131. package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
  132. package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
  133. package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
  134. package/.claude/workflows/cli-tools-usage.md +526 -0
  135. package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
  136. package/.claude/workflows/context-tools.md +84 -0
  137. package/.claude/workflows/file-modification.md +64 -0
  138. package/.claude/workflows/tool-strategy.md +216 -79
  139. package/.claude/workflows/windows-platform.md +16 -0
  140. package/.claude/workflows/workflow-architecture.md +942 -942
  141. package/.codex/AGENTS.md +63 -330
  142. package/.codex/prompts/debug.md +318 -0
  143. package/.codex/prompts/execute.md +273 -0
  144. package/.codex/prompts/lite-execute.md +164 -0
  145. package/.codex/prompts/lite-plan.md +469 -0
  146. package/.codex/prompts.zip +0 -0
  147. package/.gemini/GEMINI.md +25 -164
  148. package/.qwen/QWEN.md +0 -139
  149. package/README.md +29 -9
  150. package/ccw/README.md +30 -6
  151. package/ccw/bin/ccw-mcp.js +7 -0
  152. package/ccw/bin/ccw.js +9 -9
  153. package/ccw/package.json +65 -47
  154. package/ccw/src/.workflow/.cli-history/history.db +0 -0
  155. package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
  156. package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
  157. package/ccw/src/cli.ts +244 -0
  158. package/ccw/src/commands/cli.ts +740 -0
  159. package/ccw/src/commands/core-memory.ts +770 -0
  160. package/ccw/src/commands/hook.ts +315 -0
  161. package/ccw/src/commands/install.ts +519 -0
  162. package/ccw/src/commands/{list.js → list.ts} +1 -1
  163. package/ccw/src/commands/memory.ts +1090 -0
  164. package/ccw/src/commands/{serve.js → serve.ts} +14 -5
  165. package/ccw/src/commands/session-path-resolver.ts +372 -0
  166. package/ccw/src/commands/session.ts +1141 -0
  167. package/ccw/src/commands/{stop.js → stop.ts} +16 -6
  168. package/ccw/src/commands/tool.ts +201 -0
  169. package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
  170. package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
  171. package/ccw/src/commands/{view.js → view.ts} +22 -8
  172. package/ccw/src/config/storage-paths.ts +670 -0
  173. package/ccw/src/core/cache-manager.ts +294 -0
  174. package/ccw/src/core/claude-freshness.ts +319 -0
  175. package/ccw/src/core/core-memory-store.ts +1528 -0
  176. package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
  177. package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
  178. package/ccw/src/core/data-aggregator.ts +584 -0
  179. package/ccw/src/core/history-importer.ts +625 -0
  180. package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
  181. package/ccw/src/core/lite-scanner.ts +469 -0
  182. package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
  183. package/ccw/src/core/memory-embedder-bridge.ts +262 -0
  184. package/ccw/src/core/memory-store.ts +978 -0
  185. package/ccw/src/core/routes/ccw-routes.ts +96 -0
  186. package/ccw/src/core/routes/claude-routes.ts +1183 -0
  187. package/ccw/src/core/routes/cli-routes.ts +561 -0
  188. package/ccw/src/core/routes/codexlens-routes.ts +806 -0
  189. package/ccw/src/core/routes/core-memory-routes.ts +605 -0
  190. package/ccw/src/core/routes/files-routes.ts +428 -0
  191. package/ccw/src/core/routes/graph-routes.md +164 -0
  192. package/ccw/src/core/routes/graph-routes.ts +626 -0
  193. package/ccw/src/core/routes/help-routes.ts +308 -0
  194. package/ccw/src/core/routes/hooks-routes.ts +405 -0
  195. package/ccw/src/core/routes/mcp-routes.ts +1271 -0
  196. package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
  197. package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
  198. package/ccw/src/core/routes/memory-routes.ts +1206 -0
  199. package/ccw/src/core/routes/rules-routes.ts +526 -0
  200. package/ccw/src/core/routes/session-routes.ts +467 -0
  201. package/ccw/src/core/routes/skills-routes.ts +599 -0
  202. package/ccw/src/core/routes/status-routes.ts +57 -0
  203. package/ccw/src/core/routes/system-routes.ts +427 -0
  204. package/ccw/src/core/server.ts +431 -0
  205. package/ccw/src/core/session-clustering-service.ts +1258 -0
  206. package/ccw/src/core/session-scanner.ts +283 -0
  207. package/ccw/src/core/websocket.ts +190 -0
  208. package/ccw/src/{index.js → index.ts} +1 -0
  209. package/ccw/src/mcp-server/index.ts +186 -0
  210. package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
  211. package/ccw/src/templates/assets/css/github.min.css +10 -0
  212. package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
  213. package/ccw/src/templates/assets/js/d3.min.js +2 -0
  214. package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
  215. package/ccw/src/templates/assets/js/lucide.min.js +12 -0
  216. package/ccw/src/templates/assets/js/marked.min.js +69 -0
  217. package/ccw/src/templates/assets/js/tailwind.js +83 -0
  218. package/ccw/src/templates/dashboard-css/01-base.css +11 -0
  219. package/ccw/src/templates/dashboard-css/02-session.css +22 -0
  220. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
  221. package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
  222. package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
  223. package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
  224. package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
  225. package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
  226. package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
  227. package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
  228. package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
  229. package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
  230. package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
  231. package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
  232. package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
  233. package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
  234. package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
  235. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
  236. package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
  237. package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
  238. package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
  239. package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
  240. package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
  241. package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
  242. package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
  243. package/ccw/src/templates/dashboard-css/29-help.css +264 -0
  244. package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
  245. package/ccw/src/templates/dashboard-js/api.js +162 -142
  246. package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
  247. package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
  248. package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
  249. package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
  250. package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
  251. package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
  252. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
  253. package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
  254. package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
  255. package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
  256. package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
  257. package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
  258. package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
  259. package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
  260. package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
  261. package/ccw/src/templates/dashboard-js/main.js +15 -0
  262. package/ccw/src/templates/dashboard-js/state.js +243 -42
  263. package/ccw/src/templates/dashboard-js/utils.js +47 -1
  264. package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
  265. package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
  266. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
  267. package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
  268. package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
  269. package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
  270. package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
  271. package/ccw/src/templates/dashboard-js/views/help.js +856 -0
  272. package/ccw/src/templates/dashboard-js/views/history.js +337 -0
  273. package/ccw/src/templates/dashboard-js/views/home.js +61 -15
  274. package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
  275. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
  276. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
  277. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
  278. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
  279. package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
  280. package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
  281. package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
  282. package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
  283. package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
  284. package/ccw/src/templates/dashboard.html +185 -85
  285. package/ccw/src/templates/hooks-config-example.json +60 -0
  286. package/ccw/src/tools/classify-folders.ts +245 -0
  287. package/ccw/src/tools/cli-config-manager.ts +268 -0
  288. package/ccw/src/tools/cli-executor.ts +2014 -0
  289. package/ccw/src/tools/cli-history-store.ts +1195 -0
  290. package/ccw/src/tools/codex-lens.ts +1141 -0
  291. package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
  292. package/ccw/src/tools/core-memory.ts +444 -0
  293. package/ccw/src/tools/detect-changed-modules.ts +325 -0
  294. package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
  295. package/ccw/src/tools/edit-file.ts +568 -0
  296. package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
  297. package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
  298. package/ccw/src/tools/index.ts +370 -0
  299. package/ccw/src/tools/native-session-discovery.ts +795 -0
  300. package/ccw/src/tools/notifier.ts +129 -0
  301. package/ccw/src/tools/read-file.ts +410 -0
  302. package/ccw/src/tools/resume-strategy.ts +345 -0
  303. package/ccw/src/tools/session-content-parser.ts +619 -0
  304. package/ccw/src/tools/session-manager.ts +1026 -0
  305. package/ccw/src/tools/smart-context.ts +228 -0
  306. package/ccw/src/tools/smart-search.ts +2065 -0
  307. package/ccw/src/tools/smart-search.ts.backup +1233 -0
  308. package/ccw/src/tools/storage-manager.ts +455 -0
  309. package/ccw/src/tools/write-file.ts +222 -0
  310. package/ccw/src/types/config.ts +11 -0
  311. package/ccw/src/types/index.ts +3 -0
  312. package/ccw/src/types/session.ts +25 -0
  313. package/ccw/src/types/tool.ts +41 -0
  314. package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
  315. package/ccw/src/utils/file-utils.ts +48 -0
  316. package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
  317. package/ccw/src/utils/path-validator.ts +153 -0
  318. package/ccw/src/utils/{ui.js → ui.ts} +32 -25
  319. package/codex-lens/pyproject.toml +48 -0
  320. package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
  321. package/codex-lens/src/codexlens/__init__.py +28 -0
  322. package/codex-lens/src/codexlens/__main__.py +14 -0
  323. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
  324. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
  325. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  326. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  327. package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
  328. package/codex-lens/src/codexlens/cli/__init__.py +27 -0
  329. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  330. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  331. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  332. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  333. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  334. package/codex-lens/src/codexlens/cli/commands.py +1931 -0
  335. package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
  336. package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
  337. package/codex-lens/src/codexlens/cli/output.py +124 -0
  338. package/codex-lens/src/codexlens/config.py +201 -0
  339. package/codex-lens/src/codexlens/entities.py +121 -0
  340. package/codex-lens/src/codexlens/errors.py +55 -0
  341. package/codex-lens/src/codexlens/indexing/README.md +77 -0
  342. package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
  343. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  344. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  345. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
  346. package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
  347. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
  348. package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
  349. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  350. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
  351. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  352. package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
  353. package/codex-lens/src/codexlens/parsers/factory.py +256 -0
  354. package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
  355. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
  356. package/codex-lens/src/codexlens/search/__init__.py +15 -0
  357. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
  358. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  359. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  360. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  361. package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
  362. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  363. package/codex-lens/src/codexlens/search/chain_search.py +647 -0
  364. package/codex-lens/src/codexlens/search/enrichment.py +150 -0
  365. package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
  366. package/codex-lens/src/codexlens/search/query_parser.py +242 -0
  367. package/codex-lens/src/codexlens/search/ranking.py +274 -0
  368. package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
  369. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  370. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  371. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  372. package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
  373. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  374. package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
  375. package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
  376. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  377. package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
  378. package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
  379. package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
  380. package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
  381. package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
  382. package/codex-lens/src/codexlens/storage/__init__.py +29 -0
  383. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  384. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  385. package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
  386. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  387. package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
  388. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  389. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
  390. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  391. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
  392. package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
  393. package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
  394. package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
  395. package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
  396. package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
  397. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  398. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
  399. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
  400. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
  401. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  402. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
  403. package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
  404. package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
  405. package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
  406. package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
  407. package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
  408. package/codex-lens/src/codexlens/storage/registry.py +670 -0
  409. package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
  410. package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
  411. package/package.json +4 -1
  412. package/.claude/commands/memory/tech-research.md +0 -477
  413. package/.claude/scripts/classify-folders.sh +0 -39
  414. package/.claude/scripts/convert_tokens_to_css.sh +0 -229
  415. package/.claude/scripts/detect_changed_modules.sh +0 -161
  416. package/.claude/scripts/discover-design-files.sh +0 -87
  417. package/.claude/scripts/extract-animations.js +0 -243
  418. package/.claude/scripts/extract-computed-styles.js +0 -118
  419. package/.claude/scripts/extract-layout-structure.js +0 -411
  420. package/.claude/scripts/generate_module_docs.sh +0 -717
  421. package/.claude/scripts/get_modules_by_depth.sh +0 -170
  422. package/.claude/scripts/ui-generate-preview.sh +0 -395
  423. package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
  424. package/.claude/scripts/update_module_claude.sh +0 -337
  425. package/.claude/workflows/context-search-strategy.md +0 -77
  426. package/.claude/workflows/intelligent-tools-strategy.md +0 -662
  427. package/ccw/src/cli.js +0 -119
  428. package/ccw/src/commands/install.js +0 -324
  429. package/ccw/src/commands/tool.js +0 -138
  430. package/ccw/src/core/data-aggregator.js +0 -409
  431. package/ccw/src/core/server.js +0 -2063
  432. package/ccw/src/core/session-scanner.js +0 -235
  433. package/ccw/src/tools/classify-folders.js +0 -204
  434. package/ccw/src/tools/detect-changed-modules.js +0 -288
  435. package/ccw/src/tools/edit-file.js +0 -266
  436. package/ccw/src/tools/index.js +0 -176
  437. package/ccw/src/utils/file-utils.js +0 -48
@@ -0,0 +1,154 @@
1
+ """
2
+ Manages database schema migrations.
3
+
4
+ This module provides a framework for applying versioned migrations to the SQLite
5
+ database. Migrations are discovered from the `codexlens.storage.migrations`
6
+ package and applied sequentially. The database schema version is tracked using
7
+ the `user_version` pragma.
8
+ """
9
+
10
+ import importlib
11
+ import logging
12
+ import pkgutil
13
+ from pathlib import Path
14
+ from sqlite3 import Connection
15
+ from typing import List, NamedTuple
16
+
17
+ log = logging.getLogger(__name__)
18
+
19
+
20
+ class Migration(NamedTuple):
21
+ """Represents a single database migration."""
22
+
23
+ version: int
24
+ name: str
25
+ upgrade: callable
26
+
27
+
28
+ def discover_migrations() -> List[Migration]:
29
+ """
30
+ Discovers and returns a sorted list of database migrations.
31
+
32
+ Migrations are expected to be in the `codexlens.storage.migrations` package,
33
+ with filenames in the format `migration_XXX_description.py`, where XXX is
34
+ the version number. Each migration module must contain an `upgrade` function
35
+ that takes a `sqlite3.Connection` object as its argument.
36
+
37
+ Returns:
38
+ A list of Migration objects, sorted by version.
39
+ """
40
+ import codexlens.storage.migrations
41
+
42
+ migrations = []
43
+ package_path = Path(codexlens.storage.migrations.__file__).parent
44
+
45
+ for _, name, _ in pkgutil.iter_modules([str(package_path)]):
46
+ if name.startswith("migration_"):
47
+ try:
48
+ version = int(name.split("_")[1])
49
+ module = importlib.import_module(f"codexlens.storage.migrations.{name}")
50
+ if hasattr(module, "upgrade"):
51
+ migrations.append(
52
+ Migration(version=version, name=name, upgrade=module.upgrade)
53
+ )
54
+ else:
55
+ log.warning(f"Migration {name} is missing 'upgrade' function.")
56
+ except (ValueError, IndexError) as e:
57
+ log.warning(f"Could not parse migration name {name}: {e}")
58
+ except ImportError as e:
59
+ log.warning(f"Could not import migration {name}: {e}")
60
+
61
+ migrations.sort(key=lambda m: m.version)
62
+ return migrations
63
+
64
+
65
+ class MigrationManager:
66
+ """
67
+ Manages the application of migrations to a database.
68
+ """
69
+
70
+ def __init__(self, db_conn: Connection):
71
+ """
72
+ Initializes the MigrationManager.
73
+
74
+ Args:
75
+ db_conn: The SQLite database connection.
76
+ """
77
+ self.db_conn = db_conn
78
+ self.migrations = discover_migrations()
79
+
80
+ def get_current_version(self) -> int:
81
+ """
82
+ Gets the current version of the database schema.
83
+
84
+ Returns:
85
+ The current schema version number.
86
+ """
87
+ return self.db_conn.execute("PRAGMA user_version").fetchone()[0]
88
+
89
+ def set_version(self, version: int):
90
+ """
91
+ Sets the database schema version.
92
+
93
+ Args:
94
+ version: The version number to set.
95
+ """
96
+ self.db_conn.execute(f"PRAGMA user_version = {version}")
97
+ log.info(f"Database schema version set to {version}")
98
+
99
+ def apply_migrations(self):
100
+ """
101
+ Applies all pending migrations to the database.
102
+
103
+ This method checks the current database version and applies all
104
+ subsequent migrations in order. Each migration is applied within
105
+ a transaction, unless the migration manages its own transactions.
106
+ """
107
+ current_version = self.get_current_version()
108
+ log.info(f"Current database schema version: {current_version}")
109
+
110
+ for migration in self.migrations:
111
+ if migration.version > current_version:
112
+ log.info(f"Applying migration {migration.version}: {migration.name}...")
113
+ try:
114
+ # Check if a transaction is already in progress
115
+ in_transaction = self.db_conn.in_transaction
116
+
117
+ # Only start transaction if not already in one
118
+ if not in_transaction:
119
+ self.db_conn.execute("BEGIN")
120
+
121
+ migration.upgrade(self.db_conn)
122
+ self.set_version(migration.version)
123
+
124
+ # Only commit if we started the transaction and it's still active
125
+ if not in_transaction and self.db_conn.in_transaction:
126
+ self.db_conn.execute("COMMIT")
127
+
128
+ log.info(
129
+ f"Successfully applied migration {migration.version}: {migration.name}"
130
+ )
131
+ except Exception as e:
132
+ log.error(
133
+ f"Failed to apply migration {migration.version}: {migration.name}. Error: {e}",
134
+ exc_info=True,
135
+ )
136
+ # Try to rollback if transaction is active
137
+ try:
138
+ if self.db_conn.in_transaction:
139
+ self.db_conn.execute("ROLLBACK")
140
+ except Exception:
141
+ pass # Ignore rollback errors
142
+ raise
143
+
144
+ latest_migration_version = self.migrations[-1].version if self.migrations else 0
145
+ if current_version < latest_migration_version:
146
+ # This case can be hit if migrations were applied but the loop was exited
147
+ # and set_version was not called for the last one for some reason.
148
+ # To be safe, we explicitly set the version to the latest known migration.
149
+ final_version = self.get_current_version()
150
+ if final_version != latest_migration_version:
151
+ log.warning(f"Database version ({final_version}) is not the latest migration version ({latest_migration_version}). This may indicate a problem.")
152
+
153
+ log.info("All pending migrations applied successfully.")
154
+
@@ -0,0 +1 @@
1
+ # This file makes the 'migrations' directory a Python package.
@@ -0,0 +1,123 @@
1
+ """
2
+ Migration 001: Normalize keywords into separate tables.
3
+
4
+ This migration introduces two new tables, `keywords` and `file_keywords`, to
5
+ store semantic keywords in a normalized fashion. It then migrates the existing
6
+ keywords from the `semantic_data` JSON blob in the `files` table into these
7
+ new tables. This is intended to speed up keyword-based searches significantly.
8
+ """
9
+
10
+ import json
11
+ import logging
12
+ from sqlite3 import Connection
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ def upgrade(db_conn: Connection):
18
+ """
19
+ Applies the migration to normalize keywords.
20
+
21
+ - Creates `keywords` and `file_keywords` tables.
22
+ - Creates indexes for efficient querying.
23
+ - Migrates data from `files.semantic_data` to the new tables.
24
+
25
+ Args:
26
+ db_conn: The SQLite database connection.
27
+ """
28
+ cursor = db_conn.cursor()
29
+
30
+ log.info("Creating 'keywords' and 'file_keywords' tables...")
31
+ # Create a table to store unique keywords
32
+ cursor.execute(
33
+ """
34
+ CREATE TABLE IF NOT EXISTS keywords (
35
+ id INTEGER PRIMARY KEY,
36
+ keyword TEXT NOT NULL UNIQUE
37
+ )
38
+ """
39
+ )
40
+
41
+ # Create a join table to link files and keywords (many-to-many)
42
+ cursor.execute(
43
+ """
44
+ CREATE TABLE IF NOT EXISTS file_keywords (
45
+ file_id INTEGER NOT NULL,
46
+ keyword_id INTEGER NOT NULL,
47
+ PRIMARY KEY (file_id, keyword_id),
48
+ FOREIGN KEY (file_id) REFERENCES files (id) ON DELETE CASCADE,
49
+ FOREIGN KEY (keyword_id) REFERENCES keywords (id) ON DELETE CASCADE
50
+ )
51
+ """
52
+ )
53
+
54
+ log.info("Creating indexes for new keyword tables...")
55
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords (keyword)")
56
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_file_keywords_file_id ON file_keywords (file_id)")
57
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_file_keywords_keyword_id ON file_keywords (keyword_id)")
58
+
59
+ log.info("Migrating existing keywords from 'semantic_metadata' table...")
60
+
61
+ # Check if semantic_metadata table exists before querying
62
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='semantic_metadata'")
63
+ if not cursor.fetchone():
64
+ log.info("No 'semantic_metadata' table found, skipping data migration.")
65
+ return
66
+
67
+ # Check if 'keywords' column exists in semantic_metadata table
68
+ # (current schema may already use normalized tables without this column)
69
+ cursor.execute("PRAGMA table_info(semantic_metadata)")
70
+ columns = {row[1] for row in cursor.fetchall()}
71
+ if "keywords" not in columns:
72
+ log.info("No 'keywords' column in semantic_metadata table, skipping data migration.")
73
+ return
74
+
75
+ cursor.execute("SELECT file_id, keywords FROM semantic_metadata WHERE keywords IS NOT NULL AND keywords != ''")
76
+
77
+ files_to_migrate = cursor.fetchall()
78
+ if not files_to_migrate:
79
+ log.info("No existing files with semantic metadata to migrate.")
80
+ return
81
+
82
+ log.info(f"Found {len(files_to_migrate)} files with semantic metadata to migrate.")
83
+
84
+ for file_id, keywords_json in files_to_migrate:
85
+ if not keywords_json:
86
+ continue
87
+ try:
88
+ keywords = json.loads(keywords_json)
89
+
90
+ if not isinstance(keywords, list):
91
+ log.warning(f"Keywords for file_id {file_id} is not a list, skipping.")
92
+ continue
93
+
94
+ for keyword in keywords:
95
+ if not isinstance(keyword, str):
96
+ log.warning(f"Non-string keyword '{keyword}' found for file_id {file_id}, skipping.")
97
+ continue
98
+
99
+ keyword = keyword.strip()
100
+ if not keyword:
101
+ continue
102
+
103
+ # Get or create keyword_id
104
+ cursor.execute("INSERT OR IGNORE INTO keywords (keyword) VALUES (?)", (keyword,))
105
+ cursor.execute("SELECT id FROM keywords WHERE keyword = ?", (keyword,))
106
+ keyword_id_result = cursor.fetchone()
107
+
108
+ if keyword_id_result:
109
+ keyword_id = keyword_id_result[0]
110
+ # Link file to keyword
111
+ cursor.execute(
112
+ "INSERT OR IGNORE INTO file_keywords (file_id, keyword_id) VALUES (?, ?)",
113
+ (file_id, keyword_id),
114
+ )
115
+ else:
116
+ log.error(f"Failed to retrieve or create keyword_id for keyword: {keyword}")
117
+
118
+ except json.JSONDecodeError as e:
119
+ log.warning(f"Could not parse keywords for file_id {file_id}: {e}")
120
+ except Exception as e:
121
+ log.error(f"An unexpected error occurred during migration for file_id {file_id}: {e}", exc_info=True)
122
+
123
+ log.info("Finished migrating keywords.")
@@ -0,0 +1,48 @@
1
+ """
2
+ Migration 002: Add token_count and symbol_type to symbols table.
3
+
4
+ This migration adds token counting metadata to symbols for accurate chunk
5
+ splitting and performance optimization. It also adds symbol_type for better
6
+ filtering in searches.
7
+ """
8
+
9
+ import logging
10
+ from sqlite3 import Connection
11
+
12
+ log = logging.getLogger(__name__)
13
+
14
+
15
+ def upgrade(db_conn: Connection):
16
+ """
17
+ Applies the migration to add token metadata to symbols.
18
+
19
+ - Adds token_count column to symbols table
20
+ - Adds symbol_type column to symbols table (for future use)
21
+ - Creates index on symbol_type for efficient filtering
22
+ - Backfills existing symbols with NULL token_count (to be calculated lazily)
23
+
24
+ Args:
25
+ db_conn: The SQLite database connection.
26
+ """
27
+ cursor = db_conn.cursor()
28
+
29
+ log.info("Adding token_count column to symbols table...")
30
+ try:
31
+ cursor.execute("ALTER TABLE symbols ADD COLUMN token_count INTEGER")
32
+ log.info("Successfully added token_count column.")
33
+ except Exception as e:
34
+ # Column might already exist
35
+ log.warning(f"Could not add token_count column (might already exist): {e}")
36
+
37
+ log.info("Adding symbol_type column to symbols table...")
38
+ try:
39
+ cursor.execute("ALTER TABLE symbols ADD COLUMN symbol_type TEXT")
40
+ log.info("Successfully added symbol_type column.")
41
+ except Exception as e:
42
+ # Column might already exist
43
+ log.warning(f"Could not add symbol_type column (might already exist): {e}")
44
+
45
+ log.info("Creating index on symbol_type for efficient filtering...")
46
+ cursor.execute("CREATE INDEX IF NOT EXISTS idx_symbols_type ON symbols(symbol_type)")
47
+
48
+ log.info("Migration 002 completed successfully.")
@@ -0,0 +1,232 @@
1
+ """
2
+ Migration 004: Add dual FTS tables for exact and fuzzy matching.
3
+
4
+ This migration introduces two FTS5 tables:
5
+ - files_fts_exact: Uses unicode61 tokenizer for exact token matching
6
+ - files_fts_fuzzy: Uses trigram tokenizer (or extended unicode61) for substring/fuzzy matching
7
+
8
+ Both tables are synchronized with the files table via triggers for automatic updates.
9
+ """
10
+
11
+ import logging
12
+ from sqlite3 import Connection
13
+
14
+ from codexlens.storage.sqlite_utils import check_trigram_support, get_sqlite_version
15
+
16
+ log = logging.getLogger(__name__)
17
+
18
+
19
+ def upgrade(db_conn: Connection):
20
+ """
21
+ Applies the migration to add dual FTS tables.
22
+
23
+ - Drops old files_fts table and triggers
24
+ - Creates files_fts_exact with unicode61 tokenizer
25
+ - Creates files_fts_fuzzy with trigram or extended unicode61 tokenizer
26
+ - Creates synchronized triggers for both tables
27
+ - Rebuilds FTS indexes from files table
28
+
29
+ Args:
30
+ db_conn: The SQLite database connection.
31
+ """
32
+ cursor = db_conn.cursor()
33
+
34
+ try:
35
+ # Check trigram support
36
+ has_trigram = check_trigram_support(db_conn)
37
+ version = get_sqlite_version(db_conn)
38
+ log.info(f"SQLite version: {'.'.join(map(str, version))}")
39
+
40
+ if has_trigram:
41
+ log.info("Trigram tokenizer available, using for fuzzy FTS table")
42
+ fuzzy_tokenizer = "trigram"
43
+ else:
44
+ log.warning(
45
+ f"Trigram tokenizer not available (requires SQLite >= 3.34), "
46
+ f"using extended unicode61 tokenizer for fuzzy matching"
47
+ )
48
+ fuzzy_tokenizer = "unicode61 tokenchars '_-.'"
49
+
50
+ # Start transaction
51
+ cursor.execute("BEGIN TRANSACTION")
52
+
53
+ # Check if files table has 'name' column (v2 schema doesn't have it)
54
+ cursor.execute("PRAGMA table_info(files)")
55
+ columns = {row[1] for row in cursor.fetchall()}
56
+
57
+ if 'name' not in columns:
58
+ log.info("Adding 'name' column to files table (v2 schema upgrade)...")
59
+ # Add name column
60
+ cursor.execute("ALTER TABLE files ADD COLUMN name TEXT")
61
+ # Populate name from path (extract filename from last '/')
62
+ # Use Python to do the extraction since SQLite doesn't have reverse()
63
+ cursor.execute("SELECT rowid, path FROM files")
64
+ rows = cursor.fetchall()
65
+ for rowid, path in rows:
66
+ # Extract filename from path
67
+ name = path.split('/')[-1] if '/' in path else path
68
+ cursor.execute("UPDATE files SET name = ? WHERE rowid = ?", (name, rowid))
69
+
70
+ # Rename 'path' column to 'full_path' if needed
71
+ if 'path' in columns and 'full_path' not in columns:
72
+ log.info("Renaming 'path' to 'full_path' (v2 schema upgrade)...")
73
+ # Check if indexed_at column exists in v2 schema
74
+ has_indexed_at = 'indexed_at' in columns
75
+ has_mtime = 'mtime' in columns
76
+
77
+ # SQLite doesn't support RENAME COLUMN before 3.25, so use table recreation
78
+ cursor.execute("""
79
+ CREATE TABLE files_new (
80
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
81
+ name TEXT NOT NULL,
82
+ full_path TEXT NOT NULL UNIQUE,
83
+ content TEXT,
84
+ language TEXT,
85
+ mtime REAL,
86
+ indexed_at TEXT
87
+ )
88
+ """)
89
+
90
+ # Build INSERT statement based on available columns
91
+ # Note: v2 schema has no rowid (path is PRIMARY KEY), so use NULL for AUTOINCREMENT
92
+ if has_indexed_at and has_mtime:
93
+ cursor.execute("""
94
+ INSERT INTO files_new (name, full_path, content, language, mtime, indexed_at)
95
+ SELECT name, path, content, language, mtime, indexed_at FROM files
96
+ """)
97
+ elif has_indexed_at:
98
+ cursor.execute("""
99
+ INSERT INTO files_new (name, full_path, content, language, indexed_at)
100
+ SELECT name, path, content, language, indexed_at FROM files
101
+ """)
102
+ elif has_mtime:
103
+ cursor.execute("""
104
+ INSERT INTO files_new (name, full_path, content, language, mtime)
105
+ SELECT name, path, content, language, mtime FROM files
106
+ """)
107
+ else:
108
+ cursor.execute("""
109
+ INSERT INTO files_new (name, full_path, content, language)
110
+ SELECT name, path, content, language FROM files
111
+ """)
112
+
113
+ cursor.execute("DROP TABLE files")
114
+ cursor.execute("ALTER TABLE files_new RENAME TO files")
115
+
116
+ log.info("Dropping old FTS triggers and table...")
117
+ # Drop old triggers
118
+ cursor.execute("DROP TRIGGER IF EXISTS files_ai")
119
+ cursor.execute("DROP TRIGGER IF EXISTS files_ad")
120
+ cursor.execute("DROP TRIGGER IF EXISTS files_au")
121
+
122
+ # Drop old FTS table
123
+ cursor.execute("DROP TABLE IF EXISTS files_fts")
124
+
125
+ # Create exact FTS table (unicode61 with underscores/hyphens/dots as token chars)
126
+ # Note: tokenchars includes '.' to properly tokenize qualified names like PortRole.FLOW
127
+ log.info("Creating files_fts_exact table with unicode61 tokenizer...")
128
+ cursor.execute(
129
+ """
130
+ CREATE VIRTUAL TABLE files_fts_exact USING fts5(
131
+ name, full_path UNINDEXED, content,
132
+ content='files',
133
+ content_rowid='id',
134
+ tokenize="unicode61 tokenchars '_-.'"
135
+ )
136
+ """
137
+ )
138
+
139
+ # Create fuzzy FTS table (trigram or extended unicode61)
140
+ log.info(f"Creating files_fts_fuzzy table with {fuzzy_tokenizer} tokenizer...")
141
+ cursor.execute(
142
+ f"""
143
+ CREATE VIRTUAL TABLE files_fts_fuzzy USING fts5(
144
+ name, full_path UNINDEXED, content,
145
+ content='files',
146
+ content_rowid='id',
147
+ tokenize="{fuzzy_tokenizer}"
148
+ )
149
+ """
150
+ )
151
+
152
+ # Create synchronized triggers for files_fts_exact
153
+ log.info("Creating triggers for files_fts_exact...")
154
+ cursor.execute(
155
+ """
156
+ CREATE TRIGGER files_exact_ai AFTER INSERT ON files BEGIN
157
+ INSERT INTO files_fts_exact(rowid, name, full_path, content)
158
+ VALUES(new.id, new.name, new.full_path, new.content);
159
+ END
160
+ """
161
+ )
162
+ cursor.execute(
163
+ """
164
+ CREATE TRIGGER files_exact_ad AFTER DELETE ON files BEGIN
165
+ INSERT INTO files_fts_exact(files_fts_exact, rowid, name, full_path, content)
166
+ VALUES('delete', old.id, old.name, old.full_path, old.content);
167
+ END
168
+ """
169
+ )
170
+ cursor.execute(
171
+ """
172
+ CREATE TRIGGER files_exact_au AFTER UPDATE ON files BEGIN
173
+ INSERT INTO files_fts_exact(files_fts_exact, rowid, name, full_path, content)
174
+ VALUES('delete', old.id, old.name, old.full_path, old.content);
175
+ INSERT INTO files_fts_exact(rowid, name, full_path, content)
176
+ VALUES(new.id, new.name, new.full_path, new.content);
177
+ END
178
+ """
179
+ )
180
+
181
+ # Create synchronized triggers for files_fts_fuzzy
182
+ log.info("Creating triggers for files_fts_fuzzy...")
183
+ cursor.execute(
184
+ """
185
+ CREATE TRIGGER files_fuzzy_ai AFTER INSERT ON files BEGIN
186
+ INSERT INTO files_fts_fuzzy(rowid, name, full_path, content)
187
+ VALUES(new.id, new.name, new.full_path, new.content);
188
+ END
189
+ """
190
+ )
191
+ cursor.execute(
192
+ """
193
+ CREATE TRIGGER files_fuzzy_ad AFTER DELETE ON files BEGIN
194
+ INSERT INTO files_fts_fuzzy(files_fts_fuzzy, rowid, name, full_path, content)
195
+ VALUES('delete', old.id, old.name, old.full_path, old.content);
196
+ END
197
+ """
198
+ )
199
+ cursor.execute(
200
+ """
201
+ CREATE TRIGGER files_fuzzy_au AFTER UPDATE ON files BEGIN
202
+ INSERT INTO files_fts_fuzzy(files_fts_fuzzy, rowid, name, full_path, content)
203
+ VALUES('delete', old.id, old.name, old.full_path, old.content);
204
+ INSERT INTO files_fts_fuzzy(rowid, name, full_path, content)
205
+ VALUES(new.id, new.name, new.full_path, new.content);
206
+ END
207
+ """
208
+ )
209
+
210
+ # Rebuild FTS indexes from files table
211
+ log.info("Rebuilding FTS indexes from files table...")
212
+ cursor.execute("INSERT INTO files_fts_exact(files_fts_exact) VALUES('rebuild')")
213
+ cursor.execute("INSERT INTO files_fts_fuzzy(files_fts_fuzzy) VALUES('rebuild')")
214
+
215
+ # Commit transaction
216
+ cursor.execute("COMMIT")
217
+ log.info("Migration 004 completed successfully")
218
+
219
+ # Vacuum to reclaim space (outside transaction)
220
+ try:
221
+ log.info("Running VACUUM to reclaim space...")
222
+ cursor.execute("VACUUM")
223
+ except Exception as e:
224
+ log.warning(f"VACUUM failed (non-critical): {e}")
225
+
226
+ except Exception as e:
227
+ log.error(f"Migration 004 failed: {e}")
228
+ try:
229
+ cursor.execute("ROLLBACK")
230
+ except Exception:
231
+ pass
232
+ raise