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,294 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { StoragePaths, ensureStorageDir } from '../config/storage-paths.js';
4
+
5
+ interface CacheEntry<T> {
6
+ data: T;
7
+ timestamp: number;
8
+ fileHashes: Map<string, number>; // file path -> mtime
9
+ ttl?: number;
10
+ }
11
+
12
+ interface CacheOptions {
13
+ ttl?: number; // Time-to-live in milliseconds (default: 5 minutes)
14
+ cacheDir?: string; // Cache directory (default: .ccw-cache)
15
+ }
16
+
17
+ /**
18
+ * CacheManager class for storing and retrieving dashboard data
19
+ * Tracks file modification times to detect changes and invalidate cache
20
+ */
21
+ export class CacheManager<T> {
22
+ private cacheFile: string;
23
+ private ttl: number;
24
+ private cacheDir: string;
25
+
26
+ /**
27
+ * Create a new CacheManager instance
28
+ * @param cacheKey - Unique identifier for this cache (e.g., 'dashboard-data')
29
+ * @param options - Cache configuration options
30
+ */
31
+ constructor(cacheKey: string, options: CacheOptions = {}) {
32
+ if (!options.cacheDir) {
33
+ throw new Error('CacheManager requires cacheDir option. Use StoragePaths.project(path).cache');
34
+ }
35
+ this.ttl = options.ttl || 5 * 60 * 1000; // Default: 5 minutes
36
+ this.cacheDir = options.cacheDir;
37
+ this.cacheFile = join(this.cacheDir, `${cacheKey}.json`);
38
+ }
39
+
40
+ /**
41
+ * Get cached data if valid, otherwise return null
42
+ * @param watchPaths - Array of file/directory paths to check for modifications
43
+ * @returns Cached data or null if invalid/expired
44
+ */
45
+ get(watchPaths: string[] = []): T | null {
46
+ if (!existsSync(this.cacheFile)) {
47
+ return null;
48
+ }
49
+
50
+ try {
51
+ const content = readFileSync(this.cacheFile, 'utf8');
52
+ const entry: CacheEntry<T> = JSON.parse(content, (key, value) => {
53
+ // Revive Map objects from JSON
54
+ if (key === 'fileHashes' && value && typeof value === 'object') {
55
+ return new Map(Object.entries(value));
56
+ }
57
+ return value;
58
+ });
59
+
60
+ // Check TTL expiration
61
+ if (this.ttl > 0) {
62
+ const age = Date.now() - entry.timestamp;
63
+ if (age > this.ttl) {
64
+ return null;
65
+ }
66
+ }
67
+
68
+ // Check if any watched files have changed
69
+ if (watchPaths.length > 0) {
70
+ const currentHashes = this.computeFileHashes(watchPaths);
71
+ if (!this.hashesMatch(entry.fileHashes, currentHashes)) {
72
+ return null;
73
+ }
74
+ }
75
+
76
+ return entry.data;
77
+ } catch (err) {
78
+ // If cache file is corrupted or unreadable, treat as invalid
79
+ console.warn(`Cache read error for ${this.cacheFile}:`, (err as Error).message);
80
+ return null;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Store data in cache with current timestamp and file hashes
86
+ * @param data - Data to cache
87
+ * @param watchPaths - Array of file/directory paths to track
88
+ */
89
+ set(data: T, watchPaths: string[] = []): void {
90
+ try {
91
+ // Ensure cache directory exists
92
+ if (!existsSync(this.cacheDir)) {
93
+ mkdirSync(this.cacheDir, { recursive: true });
94
+ }
95
+
96
+ const entry: CacheEntry<T> = {
97
+ data,
98
+ timestamp: Date.now(),
99
+ fileHashes: this.computeFileHashes(watchPaths),
100
+ ttl: this.ttl
101
+ };
102
+
103
+ // Convert Map to plain object for JSON serialization
104
+ const serializable = {
105
+ ...entry,
106
+ fileHashes: Object.fromEntries(entry.fileHashes)
107
+ };
108
+
109
+ writeFileSync(this.cacheFile, JSON.stringify(serializable, null, 2), 'utf8');
110
+ } catch (err) {
111
+ console.warn(`Cache write error for ${this.cacheFile}:`, (err as Error).message);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Invalidate (delete) the cache
117
+ */
118
+ invalidate(): void {
119
+ try {
120
+ if (existsSync(this.cacheFile)) {
121
+ const fs = require('fs');
122
+ fs.unlinkSync(this.cacheFile);
123
+ }
124
+ } catch (err) {
125
+ console.warn(`Cache invalidation error for ${this.cacheFile}:`, (err as Error).message);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Check if cache is valid without retrieving data
131
+ * @param watchPaths - Array of file/directory paths to check
132
+ * @returns True if cache exists and is valid
133
+ */
134
+ isValid(watchPaths: string[] = []): boolean {
135
+ return this.get(watchPaths) !== null;
136
+ }
137
+
138
+ /**
139
+ * Compute file modification times for all watched paths
140
+ * @param watchPaths - Array of file/directory paths
141
+ * @returns Map of path to mtime
142
+ */
143
+ private computeFileHashes(watchPaths: string[]): Map<string, number> {
144
+ const hashes = new Map<string, number>();
145
+
146
+ for (const path of watchPaths) {
147
+ try {
148
+ if (!existsSync(path)) {
149
+ continue;
150
+ }
151
+
152
+ const stats = statSync(path);
153
+
154
+ if (stats.isDirectory()) {
155
+ // For directories, use directory mtime (detects file additions/deletions)
156
+ hashes.set(path, stats.mtimeMs);
157
+
158
+ // Also recursively scan for workflow session files
159
+ this.scanDirectory(path, hashes);
160
+ } else {
161
+ // For files, use file mtime
162
+ hashes.set(path, stats.mtimeMs);
163
+ }
164
+ } catch (err) {
165
+ // Skip paths that can't be accessed
166
+ console.warn(`Cannot access path ${path}:`, (err as Error).message);
167
+ }
168
+ }
169
+
170
+ return hashes;
171
+ }
172
+
173
+ /**
174
+ * Recursively scan directory for important files
175
+ * @param dirPath - Directory to scan
176
+ * @param hashes - Map to store file hashes
177
+ * @param depth - Current recursion depth (max 3)
178
+ */
179
+ private scanDirectory(dirPath: string, hashes: Map<string, number>, depth: number = 0): void {
180
+ if (depth > 3) return; // Limit recursion depth
181
+
182
+ try {
183
+ const fs = require('fs');
184
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
185
+
186
+ for (const entry of entries) {
187
+ const fullPath = join(dirPath, entry.name);
188
+
189
+ if (entry.isDirectory()) {
190
+ // Track important directories
191
+ if (entry.name === '.task' || entry.name === '.review' || entry.name === '.summaries') {
192
+ const stats = statSync(fullPath);
193
+ hashes.set(fullPath, stats.mtimeMs);
194
+ this.scanDirectory(fullPath, hashes, depth + 1);
195
+ } else if (entry.name.startsWith('WFS-')) {
196
+ // Scan WFS session directories
197
+ const stats = statSync(fullPath);
198
+ hashes.set(fullPath, stats.mtimeMs);
199
+ this.scanDirectory(fullPath, hashes, depth + 1);
200
+ }
201
+ } else if (entry.isFile()) {
202
+ // Track important files
203
+ if (
204
+ entry.name.endsWith('.json') ||
205
+ entry.name === 'IMPL_PLAN.md' ||
206
+ entry.name === 'TODO_LIST.md' ||
207
+ entry.name === 'workflow-session.json'
208
+ ) {
209
+ const stats = statSync(fullPath);
210
+ hashes.set(fullPath, stats.mtimeMs);
211
+ }
212
+ }
213
+ }
214
+ } catch (err) {
215
+ // Skip directories that can't be read
216
+ console.warn(`Cannot scan directory ${dirPath}:`, (err as Error).message);
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Compare two file hash maps
222
+ * @param oldHashes - Previous hashes
223
+ * @param newHashes - Current hashes
224
+ * @returns True if hashes match (no changes)
225
+ */
226
+ private hashesMatch(oldHashes: Map<string, number>, newHashes: Map<string, number>): boolean {
227
+ // Check if any files were added or removed
228
+ if (oldHashes.size !== newHashes.size) {
229
+ return false;
230
+ }
231
+
232
+ // Check if any file mtimes changed
233
+ const entries = Array.from(oldHashes.entries());
234
+ for (let i = 0; i < entries.length; i++) {
235
+ const path = entries[i][0];
236
+ const oldMtime = entries[i][1];
237
+ const newMtime = newHashes.get(path);
238
+ if (newMtime === undefined || newMtime !== oldMtime) {
239
+ return false;
240
+ }
241
+ }
242
+
243
+ return true;
244
+ }
245
+
246
+ /**
247
+ * Get cache statistics
248
+ * @returns Cache info object
249
+ */
250
+ getStats(): { exists: boolean; age?: number; fileCount?: number; size?: number } {
251
+ if (!existsSync(this.cacheFile)) {
252
+ return { exists: false };
253
+ }
254
+
255
+ try {
256
+ const stats = statSync(this.cacheFile);
257
+ const content = readFileSync(this.cacheFile, 'utf8');
258
+ const entry = JSON.parse(content);
259
+
260
+ return {
261
+ exists: true,
262
+ age: Date.now() - entry.timestamp,
263
+ fileCount: Object.keys(entry.fileHashes || {}).length,
264
+ size: stats.size
265
+ };
266
+ } catch {
267
+ return { exists: false };
268
+ }
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Extract project path from workflow directory
274
+ * @param workflowDir - Path to .workflow directory (e.g., /project/.workflow)
275
+ * @returns Project root path
276
+ */
277
+ function extractProjectPath(workflowDir: string): string {
278
+ // workflowDir is typically {projectPath}/.workflow
279
+ return workflowDir.replace(/[\/\\]\.workflow$/, '') || workflowDir;
280
+ }
281
+
282
+ /**
283
+ * Create a cache manager for dashboard data
284
+ * @param workflowDir - Path to .workflow directory
285
+ * @param ttl - Optional TTL in milliseconds
286
+ * @returns CacheManager instance
287
+ */
288
+ export function createDashboardCache(workflowDir: string, ttl?: number): CacheManager<any> {
289
+ // Use centralized storage path
290
+ const projectPath = extractProjectPath(workflowDir);
291
+ const cacheDir = StoragePaths.project(projectPath).cache;
292
+ ensureStorageDir(cacheDir);
293
+ return new CacheManager('dashboard-data', { cacheDir, ttl });
294
+ }
@@ -0,0 +1,319 @@
1
+ /**
2
+ * CLAUDE.md Freshness Calculator
3
+ * Calculates freshness scores based on git changes since last update
4
+ */
5
+
6
+ import { execSync } from 'child_process';
7
+ import { existsSync, statSync, readdirSync } from 'fs';
8
+ import { dirname, extname, relative, join } from 'path';
9
+ import { getCoreMemoryStore, ClaudeUpdateRecord } from './core-memory-store.js';
10
+
11
+ // Source file extensions to track (from detect-changed-modules.ts)
12
+ const SOURCE_EXTENSIONS = [
13
+ '.md', '.js', '.ts', '.jsx', '.tsx',
14
+ '.py', '.go', '.rs', '.java', '.cpp', '.c', '.h',
15
+ '.sh', '.ps1', '.json', '.yaml', '.yml'
16
+ ];
17
+
18
+ // Directories to exclude
19
+ const EXCLUDE_DIRS = [
20
+ '.git', '__pycache__', 'node_modules', '.venv', 'venv', 'env',
21
+ 'dist', 'build', '.cache', '.pytest_cache', '.mypy_cache',
22
+ 'coverage', '.nyc_output', 'logs', 'tmp', 'temp', '.ccw', '.workflow'
23
+ ];
24
+
25
+ export interface FreshnessResult {
26
+ path: string;
27
+ level: 'user' | 'project' | 'module';
28
+ relativePath: string;
29
+ parentDirectory?: string;
30
+ lastUpdated: string | null;
31
+ lastModified: string;
32
+ changedFilesCount: number;
33
+ freshness: number;
34
+ updateSource?: string;
35
+ needsUpdate: boolean;
36
+ changedFiles?: string[];
37
+ }
38
+
39
+ export interface FreshnessSummary {
40
+ totalFiles: number;
41
+ staleCount: number;
42
+ averageFreshness: number;
43
+ lastScanAt: string;
44
+ }
45
+
46
+ export interface FreshnessResponse {
47
+ files: FreshnessResult[];
48
+ summary: FreshnessSummary;
49
+ }
50
+
51
+ /**
52
+ * Check if git is available and we're in a repo
53
+ */
54
+ function isGitRepo(basePath: string): boolean {
55
+ try {
56
+ execSync('git rev-parse --git-dir', { cwd: basePath, stdio: 'pipe' });
57
+ return true;
58
+ } catch (e) {
59
+ return false;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Get current git commit hash
65
+ */
66
+ export function getCurrentGitCommit(basePath: string): string | null {
67
+ try {
68
+ const output = execSync('git rev-parse HEAD', {
69
+ cwd: basePath,
70
+ encoding: 'utf8',
71
+ stdio: ['pipe', 'pipe', 'pipe']
72
+ }).trim();
73
+ return output || null;
74
+ } catch (e) {
75
+ return null;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Get files changed since a specific date within a directory
81
+ */
82
+ function getChangedFilesSince(basePath: string, modulePath: string, sinceDate: string): string[] {
83
+ try {
84
+ // Format date for git
85
+ const date = new Date(sinceDate);
86
+ const formattedDate = date.toISOString().split('T')[0];
87
+
88
+ // Get files changed since the date
89
+ const output = execSync(
90
+ `git log --name-only --since="${formattedDate}" --pretty=format: -- "${modulePath}"`,
91
+ {
92
+ cwd: basePath,
93
+ encoding: 'utf8',
94
+ stdio: ['pipe', 'pipe', 'pipe']
95
+ }
96
+ ).trim();
97
+
98
+ if (!output) return [];
99
+
100
+ // Get unique files and filter by source extensions
101
+ const files = [...new Set(output.split('\n').filter(f => f.trim()))];
102
+ return files.filter(f => {
103
+ const ext = extname(f).toLowerCase();
104
+ return SOURCE_EXTENSIONS.includes(ext);
105
+ });
106
+ } catch (e) {
107
+ // Fallback to mtime-based detection
108
+ return findFilesModifiedSince(modulePath, sinceDate);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Fallback: Find files modified since a date using mtime
114
+ */
115
+ function findFilesModifiedSince(dirPath: string, sinceDate: string): string[] {
116
+ const results: string[] = [];
117
+ const cutoffTime = new Date(sinceDate).getTime();
118
+
119
+ function scan(currentPath: string): void {
120
+ try {
121
+ const entries = readdirSync(currentPath, { withFileTypes: true });
122
+
123
+ for (const entry of entries) {
124
+ if (entry.isDirectory()) {
125
+ if (EXCLUDE_DIRS.includes(entry.name)) continue;
126
+ scan(join(currentPath, entry.name));
127
+ } else if (entry.isFile()) {
128
+ const ext = extname(entry.name).toLowerCase();
129
+ if (!SOURCE_EXTENSIONS.includes(ext)) continue;
130
+
131
+ const fullPath = join(currentPath, entry.name);
132
+ try {
133
+ const stat = statSync(fullPath);
134
+ if (stat.mtimeMs > cutoffTime) {
135
+ results.push(relative(dirPath, fullPath));
136
+ }
137
+ } catch (e) {
138
+ // Skip files we can't stat
139
+ }
140
+ }
141
+ }
142
+ } catch (e) {
143
+ // Ignore permission errors
144
+ }
145
+ }
146
+
147
+ if (existsSync(dirPath)) {
148
+ scan(dirPath);
149
+ }
150
+ return results;
151
+ }
152
+
153
+ /**
154
+ * Calculate freshness for a single CLAUDE.md file
155
+ */
156
+ export function calculateFreshness(
157
+ filePath: string,
158
+ fileLevel: 'user' | 'project' | 'module',
159
+ lastUpdateTime: string | null,
160
+ lastModified: string,
161
+ projectPath: string,
162
+ threshold: number = 20
163
+ ): FreshnessResult {
164
+ // Use lastUpdateTime from history, or fall back to file mtime
165
+ const effectiveUpdateTime = lastUpdateTime || lastModified;
166
+
167
+ // Calculate module path for change detection
168
+ let modulePath: string | null = null;
169
+ let changedFiles: string[] = [];
170
+
171
+ if (fileLevel === 'module') {
172
+ // For module-level files, scan the parent directory
173
+ modulePath = dirname(filePath);
174
+ } else if (fileLevel === 'project') {
175
+ // For project-level files, scan the project root
176
+ modulePath = projectPath;
177
+ }
178
+
179
+ // Only calculate changes for module/project level in git repos
180
+ if (modulePath && isGitRepo(projectPath)) {
181
+ changedFiles = getChangedFilesSince(projectPath, modulePath, effectiveUpdateTime);
182
+ // Exclude the CLAUDE.md file itself
183
+ changedFiles = changedFiles.filter(f => !f.endsWith('CLAUDE.md'));
184
+ }
185
+
186
+ // Calculate freshness percentage
187
+ const changedCount = changedFiles.length;
188
+ const freshness = Math.max(0, 100 - Math.floor((changedCount / threshold) * 100));
189
+
190
+ // Determine parent directory for display
191
+ const parentDirectory = fileLevel === 'module'
192
+ ? filePath.split(/[\\/]/).slice(-2, -1)[0]
193
+ : undefined;
194
+
195
+ return {
196
+ path: filePath,
197
+ level: fileLevel,
198
+ relativePath: relative(projectPath, filePath).replace(/\\/g, '/'),
199
+ parentDirectory,
200
+ lastUpdated: lastUpdateTime,
201
+ lastModified,
202
+ changedFilesCount: changedCount,
203
+ freshness,
204
+ needsUpdate: freshness < 50,
205
+ changedFiles: changedFiles.slice(0, 20) // Limit to first 20 for detail view
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Calculate freshness for all CLAUDE.md files in a project
211
+ */
212
+ export function calculateAllFreshness(
213
+ claudeFiles: Array<{
214
+ path: string;
215
+ level: 'user' | 'project' | 'module';
216
+ lastModified: string;
217
+ }>,
218
+ projectPath: string,
219
+ threshold: number = 20
220
+ ): FreshnessResponse {
221
+ // Get update records from store
222
+ const store = getCoreMemoryStore(projectPath);
223
+ const updateRecords = store.getAllClaudeUpdateRecords();
224
+
225
+ // Create a map for quick lookup
226
+ const updateMap = new Map<string, ClaudeUpdateRecord>();
227
+ for (const record of updateRecords) {
228
+ updateMap.set(record.file_path, record);
229
+ }
230
+
231
+ const results: FreshnessResult[] = [];
232
+
233
+ for (const file of claudeFiles) {
234
+ const updateRecord = updateMap.get(file.path);
235
+
236
+ const result = calculateFreshness(
237
+ file.path,
238
+ file.level,
239
+ updateRecord?.updated_at || null,
240
+ file.lastModified,
241
+ projectPath,
242
+ threshold
243
+ );
244
+
245
+ if (updateRecord) {
246
+ result.updateSource = updateRecord.update_source;
247
+ }
248
+
249
+ results.push(result);
250
+ }
251
+
252
+ // Calculate summary
253
+ const staleCount = results.filter(r => r.needsUpdate).length;
254
+ const totalFreshness = results.reduce((sum, r) => sum + r.freshness, 0);
255
+ const averageFreshness = results.length > 0 ? Math.round(totalFreshness / results.length) : 100;
256
+
257
+ return {
258
+ files: results,
259
+ summary: {
260
+ totalFiles: results.length,
261
+ staleCount,
262
+ averageFreshness,
263
+ lastScanAt: new Date().toISOString()
264
+ }
265
+ };
266
+ }
267
+
268
+ /**
269
+ * Mark a CLAUDE.md file as updated
270
+ */
271
+ export function markFileAsUpdated(
272
+ filePath: string,
273
+ fileLevel: 'user' | 'project' | 'module',
274
+ updateSource: 'manual' | 'cli_sync' | 'dashboard' | 'api',
275
+ projectPath: string,
276
+ metadata?: object
277
+ ): ClaudeUpdateRecord {
278
+ const store = getCoreMemoryStore(projectPath);
279
+ const now = new Date().toISOString();
280
+
281
+ // Get current git commit
282
+ const gitCommit = getCurrentGitCommit(projectPath);
283
+
284
+ // Calculate changed files count before this update
285
+ const lastUpdate = store.getLastClaudeUpdate(filePath);
286
+ let filesChangedCount = 0;
287
+
288
+ if (lastUpdate && isGitRepo(projectPath)) {
289
+ const modulePath = fileLevel === 'module' ? dirname(filePath) : projectPath;
290
+ const changedFiles = getChangedFilesSince(projectPath, modulePath, lastUpdate.updated_at);
291
+ filesChangedCount = changedFiles.filter(f => !f.endsWith('CLAUDE.md')).length;
292
+ }
293
+
294
+ // Insert update record
295
+ const record = store.insertClaudeUpdateRecord({
296
+ file_path: filePath,
297
+ file_level: fileLevel,
298
+ module_path: fileLevel === 'module' ? dirname(filePath) : undefined,
299
+ updated_at: now,
300
+ update_source: updateSource,
301
+ git_commit_hash: gitCommit || undefined,
302
+ files_changed_before_update: filesChangedCount,
303
+ metadata: metadata ? JSON.stringify(metadata) : undefined
304
+ });
305
+
306
+ return record;
307
+ }
308
+
309
+ /**
310
+ * Get update history for a file
311
+ */
312
+ export function getUpdateHistory(
313
+ filePath: string,
314
+ projectPath: string,
315
+ limit: number = 50
316
+ ): ClaudeUpdateRecord[] {
317
+ const store = getCoreMemoryStore(projectPath);
318
+ return store.getClaudeUpdateHistory(filePath, limit);
319
+ }