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,670 @@
1
+ /**
2
+ * Centralized Storage Paths Configuration
3
+ * Single source of truth for all CCW storage locations
4
+ *
5
+ * All data is stored under ~/.ccw/ with project isolation via SHA256 hash
6
+ */
7
+
8
+ import { homedir } from 'os';
9
+ import { join, resolve, dirname, relative, sep } from 'path';
10
+ import { createHash } from 'crypto';
11
+ import { existsSync, mkdirSync, renameSync, rmSync, readdirSync } from 'fs';
12
+ import { readdir } from 'fs/promises';
13
+
14
+ // Environment variable override for custom storage location
15
+ // Made dynamic to support testing environments
16
+ export function getCCWHome(): string {
17
+ return process.env.CCW_DATA_DIR || join(homedir(), '.ccw');
18
+ }
19
+
20
+ // Base CCW home directory (deprecated - use getCCWHome() for dynamic access)
21
+ // Kept for backward compatibility but will use dynamic value in tests
22
+ export const CCW_HOME = getCCWHome();
23
+
24
+ /**
25
+ * Convert project path to a human-readable folder name
26
+ * Examples:
27
+ * D:\Claude_dms3 → D--Claude_dms3
28
+ * /home/user/project → home-user-project
29
+ * /mnt/d/Claude_dms3 → D--Claude_dms3 (WSL mapping)
30
+ *
31
+ * @param absolutePath - Absolute project path
32
+ * @returns Safe folder name for filesystem
33
+ */
34
+ function pathToFolderName(absolutePath: string): string {
35
+ let normalized = absolutePath;
36
+
37
+ // Handle WSL path: /mnt/c/path → C:/path
38
+ const wslMatch = normalized.match(/^\/mnt\/([a-z])\/(.*)/i);
39
+ if (wslMatch) {
40
+ normalized = `${wslMatch[1].toUpperCase()}:/${wslMatch[2]}`;
41
+ }
42
+
43
+ // Normalize separators to forward slash
44
+ normalized = normalized.replace(/\\/g, '/');
45
+
46
+ // Lowercase for case-insensitive filesystems (Windows, macOS)
47
+ if (process.platform === 'win32' || process.platform === 'darwin') {
48
+ normalized = normalized.toLowerCase();
49
+ }
50
+
51
+ // Convert to folder-safe name:
52
+ // - Drive letter: C:/ → C--
53
+ // - Path separators: / → -
54
+ // - Remove leading/trailing dashes
55
+ let folderName = normalized
56
+ .replace(/^([a-z]):\/*/i, '$1--') // C:/ → C--
57
+ .replace(/^\/+/, '') // Remove leading slashes
58
+ .replace(/\/+/g, '-') // / → -
59
+ .replace(/[<>:"|?*]/g, '_') // Invalid chars → _
60
+ .replace(/(?<!^[a-z])-+/gi, '-') // Collapse dashes (except after drive letter)
61
+ .replace(/-$/g, ''); // Trim trailing dash only
62
+
63
+ // Limit length to avoid filesystem issues (max 100 chars)
64
+ if (folderName.length > 100) {
65
+ const hash = createHash('sha256').update(normalized).digest('hex').substring(0, 8);
66
+ folderName = folderName.substring(0, 90) + '_' + hash;
67
+ }
68
+
69
+ return folderName || 'unknown';
70
+ }
71
+
72
+ /**
73
+ * Calculate project identifier from project path
74
+ * Returns a human-readable folder name based on the path
75
+ * @param projectPath - Absolute or relative project path
76
+ * @returns Folder-safe project identifier
77
+ */
78
+ export function getProjectId(projectPath: string): string {
79
+ const absolutePath = resolve(projectPath);
80
+ return pathToFolderName(absolutePath);
81
+ }
82
+
83
+ /**
84
+ * Hierarchy information for a project path
85
+ */
86
+ export interface HierarchyInfo {
87
+ /** Current path's ID (flat form) */
88
+ currentId: string;
89
+ /** Parent directory's ID (if exists) */
90
+ parentId: string | null;
91
+ /** Relative path from parent */
92
+ relativePath: string;
93
+ }
94
+
95
+ // Path detection result cache
96
+ const hierarchyCache = new Map<string, HierarchyInfo>();
97
+
98
+ /**
99
+ * Detect path hierarchy relationship
100
+ * @param projectPath - Current working directory path
101
+ * @returns Hierarchy information
102
+ */
103
+ export function detectHierarchy(projectPath: string): HierarchyInfo {
104
+ const absolutePath = resolve(projectPath);
105
+
106
+ // Check cache
107
+ if (hierarchyCache.has(absolutePath)) {
108
+ return hierarchyCache.get(absolutePath)!;
109
+ }
110
+
111
+ // Execute detection
112
+ const result = detectHierarchyImpl(absolutePath);
113
+
114
+ // Cache result
115
+ hierarchyCache.set(absolutePath, result);
116
+
117
+ return result;
118
+ }
119
+
120
+ /**
121
+ * Internal hierarchy detection implementation
122
+ */
123
+ function detectHierarchyImpl(absolutePath: string): HierarchyInfo {
124
+ const currentId = pathToFolderName(absolutePath);
125
+
126
+ // Get all existing project directories
127
+ const projectsDir = join(getCCWHome(), 'projects');
128
+ if (!existsSync(projectsDir)) {
129
+ return { currentId, parentId: null, relativePath: '' };
130
+ }
131
+
132
+ // Check if there's a parent path with storage
133
+ let checkPath = absolutePath;
134
+ while (true) {
135
+ const parentPath = dirname(checkPath);
136
+ if (parentPath === checkPath) break; // Reached root directory
137
+
138
+ const parentId = pathToFolderName(parentPath);
139
+ const parentStorageDir = join(projectsDir, parentId);
140
+
141
+ // If parent path has storage directory, we found the parent
142
+ if (existsSync(parentStorageDir)) {
143
+ const relativePath = relative(parentPath, absolutePath).replace(/\\/g, '/');
144
+ return { currentId, parentId, relativePath };
145
+ }
146
+
147
+ checkPath = parentPath;
148
+ }
149
+
150
+ return { currentId, parentId: null, relativePath: '' };
151
+ }
152
+
153
+ /**
154
+ * Clear hierarchy cache
155
+ * Call this after migration completes
156
+ */
157
+ export function clearHierarchyCache(): void {
158
+ hierarchyCache.clear();
159
+ }
160
+
161
+ /**
162
+ * Verify migration integrity
163
+ */
164
+ function verifyMigration(targetDir: string, expectedSubDirs: string[]): boolean {
165
+ try {
166
+ for (const subDir of expectedSubDirs) {
167
+ const path = join(targetDir, subDir);
168
+ // Only verify directories that should exist
169
+ // In a real implementation, we'd check file counts, database integrity, etc.
170
+ }
171
+ return true;
172
+ } catch {
173
+ return false;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Rollback migration (on error)
179
+ */
180
+ function rollbackMigration(legacyDir: string, targetDir: string): void {
181
+ try {
182
+ // If target directory exists, try to move back
183
+ if (existsSync(targetDir)) {
184
+ console.error('⚠️ 尝试回滚迁移...');
185
+ // Implement rollback logic if needed
186
+ // For now, we'll just warn the user
187
+ }
188
+ } catch {
189
+ console.error('❌ 回滚失败,请手动检查数据完整性');
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Migrate from flat structure to hierarchical structure
195
+ * @param legacyDir - Old flat directory
196
+ * @param targetDir - New hierarchical directory
197
+ */
198
+ function migrateToHierarchical(legacyDir: string, targetDir: string): void {
199
+ console.log(`\n🔄 检测到旧存储结构,开始迁移...`);
200
+ console.log(` 从: ${legacyDir}`);
201
+ console.log(` 到: ${targetDir}`);
202
+
203
+ try {
204
+ // 1. Create target directory
205
+ mkdirSync(targetDir, { recursive: true });
206
+
207
+ // 2. Migrate each subdirectory
208
+ const subDirs = ['cli-history', 'memory', 'cache', 'config'];
209
+ for (const subDir of subDirs) {
210
+ const source = join(legacyDir, subDir);
211
+ const target = join(targetDir, subDir);
212
+
213
+ if (existsSync(source)) {
214
+ // Use atomic rename (same filesystem)
215
+ try {
216
+ renameSync(source, target);
217
+ console.log(` ✓ 迁移 ${subDir}`);
218
+ } catch (error: any) {
219
+ // If rename fails (cross-filesystem), fallback to copy-delete
220
+ // For now, we'll just throw the error
221
+ throw new Error(`无法迁移 ${subDir}: ${error.message}`);
222
+ }
223
+ }
224
+ }
225
+
226
+ // 3. Verify migration integrity
227
+ const verified = verifyMigration(targetDir, subDirs);
228
+ if (!verified) {
229
+ throw new Error('迁移验证失败');
230
+ }
231
+
232
+ // 4. Delete old directory
233
+ rmSync(legacyDir, { recursive: true, force: true });
234
+ console.log(`✅ 迁移完成并清理旧数据\n`);
235
+
236
+ } catch (error: any) {
237
+ console.error(`❌ 迁移失败: ${error.message}`);
238
+ // Try to rollback if possible
239
+ rollbackMigration(legacyDir, targetDir);
240
+ // Re-throw to prevent continued execution
241
+ throw error;
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Check and migrate child projects
247
+ * @param parentId - Parent project ID
248
+ * @param parentPath - Parent project path
249
+ */
250
+ function migrateChildProjects(parentId: string, parentPath: string): void {
251
+ const projectsDir = join(getCCWHome(), 'projects');
252
+ if (!existsSync(projectsDir)) return;
253
+
254
+ const absoluteParentPath = resolve(parentPath);
255
+ const entries = readdirSync(projectsDir);
256
+
257
+ for (const entry of entries) {
258
+ if (entry === parentId) continue; // Skip self
259
+
260
+ // Check if this is a child directory of the current project
261
+ // We need to reverse-engineer the original path from the folder ID
262
+ // This is challenging without storing metadata
263
+ // For now, we'll use a heuristic: if the entry starts with the parentId
264
+ // and has additional path segments, it might be a child
265
+
266
+ // Simple heuristic: check if entry is longer and starts with parentId
267
+ if (entry.startsWith(parentId + '-')) {
268
+ const legacyDir = join(projectsDir, entry);
269
+
270
+ // Try to determine the relative path
271
+ // This is an approximation - in a real implementation,
272
+ // we'd need to store original paths in a metadata file
273
+ // For now, let's extract the suffix after parentId-
274
+ const suffix = entry.substring(parentId.length + 1);
275
+
276
+ // Convert back to path segments (- → /)
277
+ const potentialRelPath = suffix.replace(/-/g, sep);
278
+
279
+ // Build target directory
280
+ const segments = potentialRelPath.split(sep).filter(Boolean);
281
+ let targetDir = join(projectsDir, parentId);
282
+ for (const segment of segments) {
283
+ targetDir = join(targetDir, segment);
284
+ }
285
+
286
+ // Only migrate if the legacy directory exists and contains data
287
+ if (existsSync(legacyDir)) {
288
+ const hasData = ['cli-history', 'memory', 'cache', 'config'].some(subDir =>
289
+ existsSync(join(legacyDir, subDir))
290
+ );
291
+
292
+ if (hasData) {
293
+ try {
294
+ migrateToHierarchical(legacyDir, targetDir);
295
+ } catch (error: any) {
296
+ console.error(`⚠️ 跳过 ${entry} 的迁移: ${error.message}`);
297
+ // Continue with other migrations
298
+ }
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Ensure a directory exists, creating it if necessary
307
+ * @param dirPath - Directory path to ensure
308
+ */
309
+ export function ensureStorageDir(dirPath: string): void {
310
+ if (!existsSync(dirPath)) {
311
+ mkdirSync(dirPath, { recursive: true });
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Global storage paths (not project-specific)
317
+ */
318
+ export const GlobalPaths = {
319
+ /** Root CCW home directory */
320
+ root: () => getCCWHome(),
321
+
322
+ /** Config directory */
323
+ config: () => join(getCCWHome(), 'config'),
324
+
325
+ /** Global settings file */
326
+ settings: () => join(getCCWHome(), 'config', 'settings.json'),
327
+
328
+ /** Recent project paths file */
329
+ recentPaths: () => join(getCCWHome(), 'config', 'recent-paths.json'),
330
+
331
+ /** Databases directory */
332
+ databases: () => join(getCCWHome(), 'db'),
333
+
334
+ /** MCP templates database */
335
+ mcpTemplates: () => join(getCCWHome(), 'db', 'mcp-templates.db'),
336
+
337
+ /** Logs directory */
338
+ logs: () => join(getCCWHome(), 'logs'),
339
+ };
340
+
341
+ /**
342
+ * Project-specific storage paths
343
+ */
344
+ export interface ProjectPaths {
345
+ /** Project root in CCW storage */
346
+ root: string;
347
+ /** CLI history directory */
348
+ cliHistory: string;
349
+ /** CLI history database file */
350
+ historyDb: string;
351
+ /** Memory store directory */
352
+ memory: string;
353
+ /** Memory store database file */
354
+ memoryDb: string;
355
+ /** Cache directory */
356
+ cache: string;
357
+ /** Dashboard cache file */
358
+ dashboardCache: string;
359
+ /** Config directory */
360
+ config: string;
361
+ /** CLI config file */
362
+ cliConfig: string;
363
+ }
364
+
365
+ /**
366
+ * Get storage paths for a specific project
367
+ * Supports hierarchical storage structure with automatic migration
368
+ * @param projectPath - Project root path
369
+ * @returns Object with all project-specific paths
370
+ */
371
+ export function getProjectPaths(projectPath: string): ProjectPaths {
372
+ const hierarchy = detectHierarchy(projectPath);
373
+
374
+ let projectDir: string;
375
+
376
+ if (hierarchy.parentId) {
377
+ // Has parent, use hierarchical structure
378
+ projectDir = join(getCCWHome(), 'projects', hierarchy.parentId);
379
+
380
+ // Build subdirectory path from relative path
381
+ const segments = hierarchy.relativePath.split('/').filter(Boolean);
382
+ for (const segment of segments) {
383
+ projectDir = join(projectDir, segment);
384
+ }
385
+
386
+ // Check if we need to migrate old flat data
387
+ const legacyDir = join(getCCWHome(), 'projects', hierarchy.currentId);
388
+ if (existsSync(legacyDir)) {
389
+ try {
390
+ migrateToHierarchical(legacyDir, projectDir);
391
+ // Clear cache after successful migration
392
+ clearHierarchyCache();
393
+ } catch (error: any) {
394
+ // If migration fails, fall back to legacy directory
395
+ console.warn(`迁移失败,使用旧存储位置: ${error.message}`);
396
+ projectDir = legacyDir;
397
+ }
398
+ }
399
+ } else {
400
+ // No parent, use root-level storage
401
+ projectDir = join(getCCWHome(), 'projects', hierarchy.currentId);
402
+
403
+ // Check if there are child projects that need migration
404
+ try {
405
+ migrateChildProjects(hierarchy.currentId, projectPath);
406
+ } catch (error: any) {
407
+ console.warn(`子项目迁移失败: ${error.message}`);
408
+ // Continue anyway - this is not critical
409
+ }
410
+ }
411
+
412
+ return {
413
+ root: projectDir,
414
+ cliHistory: join(projectDir, 'cli-history'),
415
+ historyDb: join(projectDir, 'cli-history', 'history.db'),
416
+ memory: join(projectDir, 'memory'),
417
+ memoryDb: join(projectDir, 'memory', 'memory.db'),
418
+ cache: join(projectDir, 'cache'),
419
+ dashboardCache: join(projectDir, 'cache', 'dashboard-data.json'),
420
+ config: join(projectDir, 'config'),
421
+ cliConfig: join(projectDir, 'config', 'cli-config.json'),
422
+ };
423
+ }
424
+
425
+ /**
426
+ * Get storage paths for a project by its ID (hash)
427
+ * Use when iterating centralized storage without original project path
428
+ * @param projectId - 16-character project ID hash
429
+ * @returns Object with all project-specific paths
430
+ */
431
+ export function getProjectPathsById(projectId: string): ProjectPaths {
432
+ const projectDir = join(getCCWHome(), 'projects', projectId);
433
+
434
+ return {
435
+ root: projectDir,
436
+ cliHistory: join(projectDir, 'cli-history'),
437
+ historyDb: join(projectDir, 'cli-history', 'history.db'),
438
+ memory: join(projectDir, 'memory'),
439
+ memoryDb: join(projectDir, 'memory', 'memory.db'),
440
+ cache: join(projectDir, 'cache'),
441
+ dashboardCache: join(projectDir, 'cache', 'dashboard-data.json'),
442
+ config: join(projectDir, 'config'),
443
+ cliConfig: join(projectDir, 'config', 'cli-config.json'),
444
+ };
445
+ }
446
+
447
+ /**
448
+ * Unified StoragePaths object combining global and project paths
449
+ */
450
+ export const StoragePaths = {
451
+ global: GlobalPaths,
452
+ project: getProjectPaths,
453
+ projectById: getProjectPathsById,
454
+ };
455
+
456
+ /**
457
+ * Information about a child project in hierarchical structure
458
+ */
459
+ export interface ChildProjectInfo {
460
+ /** Absolute path to the child project */
461
+ projectPath: string;
462
+ /** Relative path from parent project */
463
+ relativePath: string;
464
+ /** Project ID */
465
+ projectId: string;
466
+ /** Storage paths for this child project */
467
+ paths: ProjectPaths;
468
+ }
469
+
470
+ /**
471
+ * Recursively scan for child projects in hierarchical storage structure
472
+ * @param projectPath - Parent project path
473
+ * @returns Array of child project information
474
+ */
475
+ export function scanChildProjects(projectPath: string): ChildProjectInfo[] {
476
+ const absolutePath = resolve(projectPath);
477
+ const parentId = getProjectId(absolutePath);
478
+ const parentStorageDir = join(getCCWHome(), 'projects', parentId);
479
+
480
+ // If parent storage doesn't exist, no children
481
+ if (!existsSync(parentStorageDir)) {
482
+ return [];
483
+ }
484
+
485
+ const children: ChildProjectInfo[] = [];
486
+
487
+ /**
488
+ * Recursively scan directory for project data directories
489
+ */
490
+ function scanDirectory(dir: string, relativePath: string): void {
491
+ if (!existsSync(dir)) return;
492
+
493
+ try {
494
+ const entries = readdirSync(dir, { withFileTypes: true });
495
+
496
+ for (const entry of entries) {
497
+ if (!entry.isDirectory()) continue;
498
+
499
+ const fullPath = join(dir, entry.name);
500
+ const currentRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
501
+
502
+ // Check if this directory contains project data
503
+ const dataMarkers = ['cli-history', 'memory', 'cache', 'config'];
504
+ const hasData = dataMarkers.some(marker => existsSync(join(fullPath, marker)));
505
+
506
+ if (hasData) {
507
+ // This is a child project
508
+ const childProjectPath = join(absolutePath, currentRelPath.replace(/\//g, sep));
509
+ const childId = getProjectId(childProjectPath);
510
+
511
+ children.push({
512
+ projectPath: childProjectPath,
513
+ relativePath: currentRelPath,
514
+ projectId: childId,
515
+ paths: getProjectPaths(childProjectPath)
516
+ });
517
+ }
518
+
519
+ // Continue scanning subdirectories (skip data directories)
520
+ if (!dataMarkers.includes(entry.name)) {
521
+ scanDirectory(fullPath, currentRelPath);
522
+ }
523
+ }
524
+ } catch (error) {
525
+ // Ignore read errors
526
+ if (process.env.DEBUG) {
527
+ console.error(`[scanChildProjects] Failed to scan ${dir}:`, error);
528
+ }
529
+ }
530
+ }
531
+
532
+ scanDirectory(parentStorageDir, '');
533
+
534
+ return children;
535
+ }
536
+
537
+ /**
538
+ * Asynchronously scan for child projects in hierarchical storage structure
539
+ * Non-blocking version using fs.promises for better performance
540
+ * @param projectPath - Parent project path
541
+ * @returns Promise resolving to array of child project information
542
+ */
543
+ export async function scanChildProjectsAsync(projectPath: string): Promise<ChildProjectInfo[]> {
544
+ const absolutePath = resolve(projectPath);
545
+ const parentId = getProjectId(absolutePath);
546
+ const parentStorageDir = join(getCCWHome(), 'projects', parentId);
547
+
548
+ // If parent storage doesn't exist, no children
549
+ if (!existsSync(parentStorageDir)) {
550
+ return [];
551
+ }
552
+
553
+ const children: ChildProjectInfo[] = [];
554
+
555
+ /**
556
+ * Recursively scan directory for project data directories (async)
557
+ */
558
+ async function scanDirectoryAsync(dir: string, relativePath: string): Promise<void> {
559
+ if (!existsSync(dir)) return;
560
+
561
+ try {
562
+ const entries = await readdir(dir, { withFileTypes: true });
563
+
564
+ // Process directories in parallel for better performance
565
+ const promises = entries
566
+ .filter(entry => entry.isDirectory())
567
+ .map(async (entry) => {
568
+ const fullPath = join(dir, entry.name);
569
+ const currentRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
570
+
571
+ // Check if this directory contains project data
572
+ const dataMarkers = ['cli-history', 'memory', 'cache', 'config'];
573
+ const hasData = dataMarkers.some(marker => existsSync(join(fullPath, marker)));
574
+
575
+ if (hasData) {
576
+ // This is a child project
577
+ const childProjectPath = join(absolutePath, currentRelPath.replace(/\//g, sep));
578
+ const childId = getProjectId(childProjectPath);
579
+
580
+ children.push({
581
+ projectPath: childProjectPath,
582
+ relativePath: currentRelPath,
583
+ projectId: childId,
584
+ paths: getProjectPaths(childProjectPath)
585
+ });
586
+ }
587
+
588
+ // Continue scanning subdirectories (skip data directories)
589
+ if (!dataMarkers.includes(entry.name)) {
590
+ await scanDirectoryAsync(fullPath, currentRelPath);
591
+ }
592
+ });
593
+
594
+ await Promise.all(promises);
595
+ } catch (error) {
596
+ // Ignore read errors
597
+ if (process.env.DEBUG) {
598
+ console.error(`[scanChildProjectsAsync] Failed to scan ${dir}:`, error);
599
+ }
600
+ }
601
+ }
602
+
603
+ await scanDirectoryAsync(parentStorageDir, '');
604
+
605
+ return children;
606
+ }
607
+
608
+ /**
609
+ * Legacy storage paths (for backward compatibility detection)
610
+ */
611
+ export const LegacyPaths = {
612
+ /** Old recent paths file location */
613
+ recentPaths: () => join(homedir(), '.ccw-recent-paths.json'),
614
+
615
+ /** Old project-local CLI history */
616
+ cliHistory: (projectPath: string) => join(projectPath, '.workflow', '.cli-history'),
617
+
618
+ /** Old project-local memory store */
619
+ memory: (projectPath: string) => join(projectPath, '.workflow', '.memory'),
620
+
621
+ /** Old project-local cache */
622
+ cache: (projectPath: string) => join(projectPath, '.workflow', '.ccw-cache'),
623
+
624
+ /** Old project-local CLI config */
625
+ cliConfig: (projectPath: string) => join(projectPath, '.workflow', 'cli-config.json'),
626
+ };
627
+
628
+ /**
629
+ * Check if legacy storage exists for a project
630
+ * Useful for migration warnings or detection
631
+ * @param projectPath - Project root path
632
+ * @returns true if any legacy storage is present
633
+ */
634
+ export function isLegacyStoragePresent(projectPath: string): boolean {
635
+ return (
636
+ existsSync(LegacyPaths.cliHistory(projectPath)) ||
637
+ existsSync(LegacyPaths.memory(projectPath)) ||
638
+ existsSync(LegacyPaths.cache(projectPath)) ||
639
+ existsSync(LegacyPaths.cliConfig(projectPath))
640
+ );
641
+ }
642
+
643
+ /**
644
+ * Get CCW home directory (for external use)
645
+ */
646
+ export function getCcwHome(): string {
647
+ return getCCWHome();
648
+ }
649
+
650
+ /**
651
+ * Initialize global storage directories
652
+ * Creates the base directory structure if not present
653
+ */
654
+ export function initializeGlobalStorage(): void {
655
+ ensureStorageDir(GlobalPaths.config());
656
+ ensureStorageDir(GlobalPaths.databases());
657
+ ensureStorageDir(GlobalPaths.logs());
658
+ }
659
+
660
+ /**
661
+ * Initialize project storage directories
662
+ * @param projectPath - Project root path
663
+ */
664
+ export function initializeProjectStorage(projectPath: string): void {
665
+ const paths = getProjectPaths(projectPath);
666
+ ensureStorageDir(paths.cliHistory);
667
+ ensureStorageDir(paths.memory);
668
+ ensureStorageDir(paths.cache);
669
+ ensureStorageDir(paths.config);
670
+ }