claude-code-workflow 6.3.18 → 6.3.20

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 (832) hide show
  1. package/.claude/CLAUDE.md +8 -5
  2. package/.claude/agents/action-planning-agent.md +26 -2
  3. package/.claude/agents/code-developer.md +132 -43
  4. package/.claude/agents/debug-explore-agent.md +434 -0
  5. package/.claude/agents/issue-plan-agent.md +31 -2
  6. package/.claude/agents/test-fix-agent.md +14 -0
  7. package/.claude/commands/issue/discover.md +41 -0
  8. package/.claude/commands/issue/execute.md +200 -19
  9. package/.claude/commands/issue/new.md +93 -3
  10. package/.claude/commands/issue/plan.md +9 -3
  11. package/.claude/commands/issue/queue.md +94 -39
  12. package/.claude/commands/memory/swagger-docs.md +773 -0
  13. package/.claude/commands/workflow/brainstorm/auto-parallel.md +21 -21
  14. package/.claude/commands/workflow/execute.md +54 -34
  15. package/.claude/commands/workflow/lite-execute.md +48 -164
  16. package/.claude/commands/workflow/lite-fix.md +4 -4
  17. package/.claude/commands/workflow/lite-plan.md +5 -5
  18. package/.claude/commands/workflow/plan.md +27 -27
  19. package/.claude/commands/workflow/review.md +42 -17
  20. package/.claude/commands/workflow/tdd-plan.md +25 -25
  21. package/.claude/commands/workflow/test-fix-gen.md +10 -10
  22. package/.claude/commands/workflow/test-gen.md +14 -14
  23. package/.claude/commands/workflow/ui-design/explore-auto.md +21 -21
  24. package/.claude/commands/workflow/ui-design/imitate-auto.md +24 -24
  25. package/.claude/skills/_shared/SKILL-DESIGN-SPEC.md +693 -0
  26. package/.claude/skills/ccw/SKILL.md +462 -0
  27. package/.claude/skills/ccw/index/command-capabilities.json +127 -0
  28. package/.claude/skills/ccw/index/intent-rules.json +136 -0
  29. package/.claude/skills/ccw/index/workflow-chains.json +451 -0
  30. package/.claude/skills/ccw/phases/actions/bugfix.md +218 -0
  31. package/.claude/skills/ccw/phases/actions/coupled.md +194 -0
  32. package/.claude/skills/ccw/phases/actions/docs.md +93 -0
  33. package/.claude/skills/ccw/phases/actions/full.md +154 -0
  34. package/.claude/skills/ccw/phases/actions/issue.md +201 -0
  35. package/.claude/skills/ccw/phases/actions/rapid.md +104 -0
  36. package/.claude/skills/ccw/phases/actions/review-fix.md +84 -0
  37. package/.claude/skills/ccw/phases/actions/tdd.md +66 -0
  38. package/.claude/skills/ccw/phases/actions/ui.md +79 -0
  39. package/.claude/skills/ccw/phases/orchestrator.md +435 -0
  40. package/.claude/skills/ccw/specs/intent-classification.md +336 -0
  41. package/.claude/skills/ccw-help/SKILL.md +177 -0
  42. package/.claude/skills/ccw-help/index/all-agents.json +82 -0
  43. package/.claude/skills/{command-guide → ccw-help}/index/all-commands.json +183 -73
  44. package/.claude/skills/{command-guide → ccw-help}/index/by-category.json +187 -73
  45. package/.claude/skills/{command-guide → ccw-help}/index/by-use-case.json +295 -185
  46. package/.claude/skills/{command-guide → ccw-help}/index/command-relationships.json +19 -166
  47. package/.claude/skills/{command-guide → ccw-help}/index/essential-commands.json +10 -10
  48. package/.claude/skills/ccw-help/scripts/analyze_commands.py +337 -0
  49. package/.claude/skills/code-reviewer/README.md +340 -0
  50. package/.claude/skills/code-reviewer/SKILL.md +308 -0
  51. package/.claude/skills/code-reviewer/phases/01-code-discovery.md +246 -0
  52. package/.claude/skills/code-reviewer/phases/02-security-analysis.md +442 -0
  53. package/.claude/skills/code-reviewer/phases/03-best-practices-review.md +36 -0
  54. package/.claude/skills/code-reviewer/phases/04-report-generation.md +278 -0
  55. package/.claude/skills/code-reviewer/specs/best-practices-requirements.md +346 -0
  56. package/.claude/skills/code-reviewer/specs/quality-standards.md +252 -0
  57. package/.claude/skills/code-reviewer/specs/security-requirements.md +243 -0
  58. package/.claude/skills/code-reviewer/templates/best-practice-finding.md +234 -0
  59. package/.claude/skills/code-reviewer/templates/report-template.md +316 -0
  60. package/.claude/skills/code-reviewer/templates/security-finding.md +161 -0
  61. package/.claude/skills/skill-generator/SKILL.md +187 -0
  62. package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +239 -0
  63. package/.claude/skills/skill-generator/phases/02-structure-generation.md +207 -0
  64. package/.claude/skills/skill-generator/phases/03-phase-generation.md +802 -0
  65. package/.claude/skills/skill-generator/phases/04-specs-templates.md +328 -0
  66. package/.claude/skills/skill-generator/phases/05-validation.md +334 -0
  67. package/.claude/skills/skill-generator/specs/cli-integration.md +448 -0
  68. package/.claude/skills/skill-generator/specs/execution-modes.md +396 -0
  69. package/.claude/skills/skill-generator/specs/scripting-integration.md +265 -0
  70. package/.claude/skills/skill-generator/specs/skill-requirements.md +466 -0
  71. package/.claude/skills/skill-generator/templates/autonomous-action.md +517 -0
  72. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +276 -0
  73. package/.claude/skills/skill-generator/templates/code-analysis-action.md +503 -0
  74. package/.claude/skills/skill-generator/templates/llm-action.md +355 -0
  75. package/.claude/skills/skill-generator/templates/script-bash.md +277 -0
  76. package/.claude/skills/skill-generator/templates/script-python.md +198 -0
  77. package/.claude/skills/skill-generator/templates/sequential-phase.md +441 -0
  78. package/.claude/skills/skill-generator/templates/skill-md.md +156 -0
  79. package/.claude/workflows/chinese-response.md +15 -28
  80. package/.claude/workflows/cli-templates/prompts/documentation/swagger-api.txt +266 -0
  81. package/.claude/workflows/cli-tools-usage.md +221 -177
  82. package/.claude/workflows/windows-platform.md +13 -10
  83. package/.codex/prompts/issue-execute.md +310 -82
  84. package/.codex/prompts/issue-queue.md +22 -0
  85. package/.codex/prompts/lite-execute.md +36 -11
  86. package/README.md +309 -305
  87. package/ccw/README.md +10 -4
  88. package/ccw/dist/cli.d.ts.map +1 -1
  89. package/ccw/dist/cli.js +4 -1
  90. package/ccw/dist/cli.js.map +1 -1
  91. package/ccw/dist/commands/cli.d.ts.map +1 -1
  92. package/ccw/dist/commands/cli.js +131 -34
  93. package/ccw/dist/commands/cli.js.map +1 -1
  94. package/ccw/dist/commands/issue.d.ts +152 -0
  95. package/ccw/dist/commands/issue.d.ts.map +1 -1
  96. package/ccw/dist/commands/issue.js +550 -85
  97. package/ccw/dist/commands/issue.js.map +1 -1
  98. package/ccw/dist/commands/serve.d.ts +1 -0
  99. package/ccw/dist/commands/serve.d.ts.map +1 -1
  100. package/ccw/dist/commands/serve.js +12 -5
  101. package/ccw/dist/commands/serve.js.map +1 -1
  102. package/ccw/dist/commands/stop.d.ts.map +1 -1
  103. package/ccw/dist/commands/stop.js +29 -5
  104. package/ccw/dist/commands/stop.js.map +1 -1
  105. package/ccw/dist/commands/tool.d.ts.map +1 -1
  106. package/ccw/dist/commands/tool.js +19 -2
  107. package/ccw/dist/commands/tool.js.map +1 -1
  108. package/ccw/dist/commands/view.d.ts +1 -0
  109. package/ccw/dist/commands/view.d.ts.map +1 -1
  110. package/ccw/dist/commands/view.js +10 -3
  111. package/ccw/dist/commands/view.js.map +1 -1
  112. package/ccw/dist/config/cli-settings-manager.d.ts +86 -0
  113. package/ccw/dist/config/cli-settings-manager.d.ts.map +1 -0
  114. package/ccw/dist/config/cli-settings-manager.js +392 -0
  115. package/ccw/dist/config/cli-settings-manager.js.map +1 -0
  116. package/ccw/dist/config/litellm-api-config-manager.d.ts +71 -5
  117. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  118. package/ccw/dist/config/litellm-api-config-manager.js +290 -20
  119. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  120. package/ccw/dist/core/auth/csrf-manager.d.ts +18 -0
  121. package/ccw/dist/core/auth/csrf-manager.d.ts.map +1 -0
  122. package/ccw/dist/core/auth/csrf-manager.js +80 -0
  123. package/ccw/dist/core/auth/csrf-manager.js.map +1 -0
  124. package/ccw/dist/core/auth/csrf-middleware.d.ts +8 -0
  125. package/ccw/dist/core/auth/csrf-middleware.d.ts.map +1 -0
  126. package/ccw/dist/core/auth/csrf-middleware.js +141 -0
  127. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -0
  128. package/ccw/dist/core/auth/middleware.d.ts +15 -0
  129. package/ccw/dist/core/auth/middleware.d.ts.map +1 -0
  130. package/ccw/dist/core/auth/middleware.js +76 -0
  131. package/ccw/dist/core/auth/middleware.js.map +1 -0
  132. package/ccw/dist/core/auth/token-manager.d.ts +41 -0
  133. package/ccw/dist/core/auth/token-manager.d.ts.map +1 -0
  134. package/ccw/dist/core/auth/token-manager.js +171 -0
  135. package/ccw/dist/core/auth/token-manager.js.map +1 -0
  136. package/ccw/dist/core/cache-manager.d.ts +6 -6
  137. package/ccw/dist/core/cache-manager.d.ts.map +1 -1
  138. package/ccw/dist/core/cache-manager.js +70 -48
  139. package/ccw/dist/core/cache-manager.js.map +1 -1
  140. package/ccw/dist/core/claude-freshness.d.ts.map +1 -1
  141. package/ccw/dist/core/claude-freshness.js +23 -3
  142. package/ccw/dist/core/claude-freshness.js.map +1 -1
  143. package/ccw/dist/core/core-memory-store.d.ts.map +1 -1
  144. package/ccw/dist/core/core-memory-store.js +2 -1
  145. package/ccw/dist/core/core-memory-store.js.map +1 -1
  146. package/ccw/dist/core/cors.d.ts +3 -0
  147. package/ccw/dist/core/cors.d.ts.map +1 -0
  148. package/ccw/dist/core/cors.js +10 -0
  149. package/ccw/dist/core/cors.js.map +1 -0
  150. package/ccw/dist/core/dashboard-generator-patch.js +0 -1
  151. package/ccw/dist/core/dashboard-generator-patch.js.map +1 -1
  152. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  153. package/ccw/dist/core/dashboard-generator.js +417 -416
  154. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  155. package/ccw/dist/core/data-aggregator.js +2 -2
  156. package/ccw/dist/core/data-aggregator.js.map +1 -1
  157. package/ccw/dist/core/lite-scanner.d.ts +1 -1
  158. package/ccw/dist/core/lite-scanner.d.ts.map +1 -1
  159. package/ccw/dist/core/lite-scanner.js +130 -127
  160. package/ccw/dist/core/lite-scanner.js.map +1 -1
  161. package/ccw/dist/core/routes/auth-routes.d.ts +12 -0
  162. package/ccw/dist/core/routes/auth-routes.d.ts.map +1 -0
  163. package/ccw/dist/core/routes/auth-routes.js +80 -0
  164. package/ccw/dist/core/routes/auth-routes.js.map +1 -0
  165. package/ccw/dist/core/routes/ccw-routes.d.ts +1 -14
  166. package/ccw/dist/core/routes/ccw-routes.d.ts.map +1 -1
  167. package/ccw/dist/core/routes/ccw-routes.js +9 -4
  168. package/ccw/dist/core/routes/ccw-routes.js.map +1 -1
  169. package/ccw/dist/core/routes/claude-routes.d.ts +1 -14
  170. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
  171. package/ccw/dist/core/routes/claude-routes.js +98 -39
  172. package/ccw/dist/core/routes/claude-routes.js.map +1 -1
  173. package/ccw/dist/core/routes/cli-routes.d.ts +14 -12
  174. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  175. package/ccw/dist/core/routes/cli-routes.js +122 -43
  176. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  177. package/ccw/dist/core/routes/cli-settings-routes.d.ts +11 -0
  178. package/ccw/dist/core/routes/cli-settings-routes.d.ts.map +1 -0
  179. package/ccw/dist/core/routes/cli-settings-routes.js +204 -0
  180. package/ccw/dist/core/routes/cli-settings-routes.js.map +1 -0
  181. package/ccw/dist/core/routes/codexlens/config-handlers.d.ts +6 -0
  182. package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -0
  183. package/ccw/dist/core/routes/codexlens/config-handlers.js +1195 -0
  184. package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -0
  185. package/ccw/dist/core/routes/codexlens/index-handlers.d.ts +10 -0
  186. package/ccw/dist/core/routes/codexlens/index-handlers.d.ts.map +1 -0
  187. package/ccw/dist/core/routes/codexlens/index-handlers.js +322 -0
  188. package/ccw/dist/core/routes/codexlens/index-handlers.js.map +1 -0
  189. package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts +6 -0
  190. package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts.map +1 -0
  191. package/ccw/dist/core/routes/codexlens/semantic-handlers.js +865 -0
  192. package/ccw/dist/core/routes/codexlens/semantic-handlers.js.map +1 -0
  193. package/ccw/dist/core/routes/codexlens/utils.d.ts +23 -0
  194. package/ccw/dist/core/routes/codexlens/utils.d.ts.map +1 -0
  195. package/ccw/dist/core/routes/codexlens/utils.js +85 -0
  196. package/ccw/dist/core/routes/codexlens/utils.js.map +1 -0
  197. package/ccw/dist/core/routes/codexlens/watcher-handlers.d.ts +13 -0
  198. package/ccw/dist/core/routes/codexlens/watcher-handlers.d.ts.map +1 -0
  199. package/ccw/dist/core/routes/codexlens/watcher-handlers.js +235 -0
  200. package/ccw/dist/core/routes/codexlens/watcher-handlers.js.map +1 -0
  201. package/ccw/dist/core/routes/codexlens-routes.d.ts +2 -11
  202. package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
  203. package/ccw/dist/core/routes/codexlens-routes.js +10 -981
  204. package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
  205. package/ccw/dist/core/routes/discovery-routes.d.ts +1 -35
  206. package/ccw/dist/core/routes/discovery-routes.d.ts.map +1 -1
  207. package/ccw/dist/core/routes/discovery-routes.js +25 -0
  208. package/ccw/dist/core/routes/discovery-routes.js.map +1 -1
  209. package/ccw/dist/core/routes/files-routes.d.ts +1 -14
  210. package/ccw/dist/core/routes/files-routes.d.ts.map +1 -1
  211. package/ccw/dist/core/routes/files-routes.js +57 -14
  212. package/ccw/dist/core/routes/files-routes.js.map +1 -1
  213. package/ccw/dist/core/routes/graph-routes.d.ts +1 -14
  214. package/ccw/dist/core/routes/graph-routes.d.ts.map +1 -1
  215. package/ccw/dist/core/routes/graph-routes.js +36 -37
  216. package/ccw/dist/core/routes/graph-routes.js.map +1 -1
  217. package/ccw/dist/core/routes/help-routes.d.ts +1 -14
  218. package/ccw/dist/core/routes/help-routes.d.ts.map +1 -1
  219. package/ccw/dist/core/routes/help-routes.js +5 -0
  220. package/ccw/dist/core/routes/help-routes.js.map +1 -1
  221. package/ccw/dist/core/routes/hooks-routes.d.ts +4 -14
  222. package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -1
  223. package/ccw/dist/core/routes/hooks-routes.js +43 -21
  224. package/ccw/dist/core/routes/hooks-routes.js.map +1 -1
  225. package/ccw/dist/core/routes/issue-routes.d.ts +1 -34
  226. package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
  227. package/ccw/dist/core/routes/issue-routes.js +24 -0
  228. package/ccw/dist/core/routes/issue-routes.js.map +1 -1
  229. package/ccw/dist/core/routes/litellm-api-routes.d.ts +1 -14
  230. package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
  231. package/ccw/dist/core/routes/litellm-api-routes.js +513 -48
  232. package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
  233. package/ccw/dist/core/routes/litellm-routes.d.ts +1 -14
  234. package/ccw/dist/core/routes/litellm-routes.d.ts.map +1 -1
  235. package/ccw/dist/core/routes/litellm-routes.js +28 -11
  236. package/ccw/dist/core/routes/litellm-routes.js.map +1 -1
  237. package/ccw/dist/core/routes/mcp-routes.d.ts +1 -14
  238. package/ccw/dist/core/routes/mcp-routes.d.ts.map +1 -1
  239. package/ccw/dist/core/routes/mcp-routes.js +99 -30
  240. package/ccw/dist/core/routes/mcp-routes.js.map +1 -1
  241. package/ccw/dist/core/routes/mcp-templates-db.d.ts.map +1 -1
  242. package/ccw/dist/core/routes/mcp-templates-db.js +30 -31
  243. package/ccw/dist/core/routes/mcp-templates-db.js.map +1 -1
  244. package/ccw/dist/core/routes/memory-routes.d.ts.map +1 -1
  245. package/ccw/dist/core/routes/memory-routes.js +74 -24
  246. package/ccw/dist/core/routes/memory-routes.js.map +1 -1
  247. package/ccw/dist/core/routes/nav-status-routes.d.ts +3 -0
  248. package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -0
  249. package/ccw/dist/core/routes/nav-status-routes.js +217 -0
  250. package/ccw/dist/core/routes/nav-status-routes.js.map +1 -0
  251. package/ccw/dist/core/routes/rules-routes.d.ts +1 -14
  252. package/ccw/dist/core/routes/rules-routes.d.ts.map +1 -1
  253. package/ccw/dist/core/routes/rules-routes.js +481 -58
  254. package/ccw/dist/core/routes/rules-routes.js.map +1 -1
  255. package/ccw/dist/core/routes/session-routes.d.ts +1 -14
  256. package/ccw/dist/core/routes/session-routes.d.ts.map +1 -1
  257. package/ccw/dist/core/routes/session-routes.js +15 -3
  258. package/ccw/dist/core/routes/session-routes.js.map +1 -1
  259. package/ccw/dist/core/routes/skills-routes.d.ts +1 -14
  260. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
  261. package/ccw/dist/core/routes/skills-routes.js +394 -112
  262. package/ccw/dist/core/routes/skills-routes.js.map +1 -1
  263. package/ccw/dist/core/routes/status-routes.d.ts +1 -14
  264. package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
  265. package/ccw/dist/core/routes/status-routes.js +4 -0
  266. package/ccw/dist/core/routes/status-routes.js.map +1 -1
  267. package/ccw/dist/core/routes/system-routes.d.ts +4 -10
  268. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  269. package/ccw/dist/core/routes/system-routes.js +6 -4
  270. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  271. package/ccw/dist/core/routes/types.d.ts +19 -0
  272. package/ccw/dist/core/routes/types.d.ts.map +1 -0
  273. package/ccw/dist/core/routes/types.js +2 -0
  274. package/ccw/dist/core/routes/types.js.map +1 -0
  275. package/ccw/dist/core/server.d.ts.map +1 -1
  276. package/ccw/dist/core/server.js +206 -29
  277. package/ccw/dist/core/server.js.map +1 -1
  278. package/ccw/dist/core/services/api-key-tester.d.ts +42 -0
  279. package/ccw/dist/core/services/api-key-tester.d.ts.map +1 -0
  280. package/ccw/dist/core/services/api-key-tester.js +126 -0
  281. package/ccw/dist/core/services/api-key-tester.js.map +1 -0
  282. package/ccw/dist/core/services/health-check-service.d.ts +88 -0
  283. package/ccw/dist/core/services/health-check-service.d.ts.map +1 -0
  284. package/ccw/dist/core/services/health-check-service.js +293 -0
  285. package/ccw/dist/core/services/health-check-service.js.map +1 -0
  286. package/ccw/dist/core/websocket.d.ts +9 -7
  287. package/ccw/dist/core/websocket.d.ts.map +1 -1
  288. package/ccw/dist/core/websocket.js +9 -4
  289. package/ccw/dist/core/websocket.js.map +1 -1
  290. package/ccw/dist/tools/claude-cli-tools.d.ts +152 -28
  291. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  292. package/ccw/dist/tools/claude-cli-tools.js +490 -100
  293. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  294. package/ccw/dist/tools/cli-config-manager.d.ts +24 -8
  295. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  296. package/ccw/dist/tools/cli-config-manager.js +76 -156
  297. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  298. package/ccw/dist/tools/cli-executor-core.d.ts +85 -0
  299. package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -0
  300. package/ccw/dist/tools/cli-executor-core.js +1310 -0
  301. package/ccw/dist/tools/cli-executor-core.js.map +1 -0
  302. package/ccw/dist/tools/cli-executor-state.d.ts +241 -0
  303. package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -0
  304. package/ccw/dist/tools/cli-executor-state.js +392 -0
  305. package/ccw/dist/tools/cli-executor-state.js.map +1 -0
  306. package/ccw/dist/tools/cli-executor-utils.d.ts +36 -0
  307. package/ccw/dist/tools/cli-executor-utils.d.ts.map +1 -0
  308. package/ccw/dist/tools/cli-executor-utils.js +298 -0
  309. package/ccw/dist/tools/cli-executor-utils.js.map +1 -0
  310. package/ccw/dist/tools/cli-executor.d.ts +3 -377
  311. package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
  312. package/ccw/dist/tools/cli-executor.js +3 -1884
  313. package/ccw/dist/tools/cli-executor.js.map +1 -1
  314. package/ccw/dist/tools/cli-history-store.d.ts +2 -0
  315. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  316. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  317. package/ccw/dist/tools/cli-output-converter.d.ts +192 -0
  318. package/ccw/dist/tools/cli-output-converter.d.ts.map +1 -0
  319. package/ccw/dist/tools/cli-output-converter.js +1047 -0
  320. package/ccw/dist/tools/cli-output-converter.js.map +1 -0
  321. package/ccw/dist/tools/cli-prompt-builder.d.ts +113 -0
  322. package/ccw/dist/tools/cli-prompt-builder.d.ts.map +1 -0
  323. package/ccw/dist/tools/cli-prompt-builder.js +363 -0
  324. package/ccw/dist/tools/cli-prompt-builder.js.map +1 -0
  325. package/ccw/dist/tools/codex-lens.d.ts +15 -1
  326. package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
  327. package/ccw/dist/tools/codex-lens.js +289 -55
  328. package/ccw/dist/tools/codex-lens.js.map +1 -1
  329. package/ccw/dist/tools/detect-changed-modules.d.ts.map +1 -1
  330. package/ccw/dist/tools/detect-changed-modules.js +22 -4
  331. package/ccw/dist/tools/detect-changed-modules.js.map +1 -1
  332. package/ccw/dist/tools/index.d.ts.map +1 -1
  333. package/ccw/dist/tools/index.js +2 -0
  334. package/ccw/dist/tools/index.js.map +1 -1
  335. package/ccw/dist/tools/litellm-client.d.ts.map +1 -1
  336. package/ccw/dist/tools/litellm-client.js +10 -4
  337. package/ccw/dist/tools/litellm-client.js.map +1 -1
  338. package/ccw/dist/tools/litellm-executor.d.ts +2 -4
  339. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
  340. package/ccw/dist/tools/litellm-executor.js +39 -8
  341. package/ccw/dist/tools/litellm-executor.js.map +1 -1
  342. package/ccw/dist/tools/native-session-discovery.d.ts +2 -0
  343. package/ccw/dist/tools/native-session-discovery.d.ts.map +1 -1
  344. package/ccw/dist/tools/native-session-discovery.js +197 -1
  345. package/ccw/dist/tools/native-session-discovery.js.map +1 -1
  346. package/ccw/dist/tools/session-manager.d.ts.map +1 -1
  347. package/ccw/dist/tools/session-manager.js +79 -0
  348. package/ccw/dist/tools/session-manager.js.map +1 -1
  349. package/ccw/dist/tools/skill-context-loader.d.ts +15 -0
  350. package/ccw/dist/tools/skill-context-loader.d.ts.map +1 -0
  351. package/ccw/dist/tools/skill-context-loader.js +198 -0
  352. package/ccw/dist/tools/skill-context-loader.js.map +1 -0
  353. package/ccw/dist/tools/smart-search.d.ts +8 -3
  354. package/ccw/dist/tools/smart-search.d.ts.map +1 -1
  355. package/ccw/dist/tools/smart-search.js +378 -75
  356. package/ccw/dist/tools/smart-search.js.map +1 -1
  357. package/ccw/dist/types/cli-settings.d.ts +86 -0
  358. package/ccw/dist/types/cli-settings.d.ts.map +1 -0
  359. package/ccw/dist/types/cli-settings.js +54 -0
  360. package/ccw/dist/types/cli-settings.js.map +1 -0
  361. package/ccw/dist/types/litellm-api-config.d.ts +40 -1
  362. package/ccw/dist/types/litellm-api-config.d.ts.map +1 -1
  363. package/ccw/dist/utils/exec-constants.d.ts +25 -0
  364. package/ccw/dist/utils/exec-constants.d.ts.map +1 -0
  365. package/ccw/dist/utils/exec-constants.js +25 -0
  366. package/ccw/dist/utils/exec-constants.js.map +1 -0
  367. package/ccw/dist/utils/path-resolver.d.ts +1 -0
  368. package/ccw/dist/utils/path-resolver.d.ts.map +1 -1
  369. package/ccw/dist/utils/path-resolver.js +48 -3
  370. package/ccw/dist/utils/path-resolver.js.map +1 -1
  371. package/ccw/dist/utils/path-validator.d.ts.map +1 -1
  372. package/ccw/dist/utils/path-validator.js +25 -6
  373. package/ccw/dist/utils/path-validator.js.map +1 -1
  374. package/ccw/dist/utils/python-utils.d.ts.map +1 -1
  375. package/ccw/dist/utils/python-utils.js +27 -7
  376. package/ccw/dist/utils/python-utils.js.map +1 -1
  377. package/ccw/dist/utils/shell-escape.d.ts +8 -0
  378. package/ccw/dist/utils/shell-escape.d.ts.map +1 -0
  379. package/ccw/dist/utils/shell-escape.js +24 -0
  380. package/ccw/dist/utils/shell-escape.js.map +1 -0
  381. package/ccw/dist/utils/uv-manager.d.ts +167 -0
  382. package/ccw/dist/utils/uv-manager.d.ts.map +1 -0
  383. package/ccw/dist/utils/uv-manager.js +644 -0
  384. package/ccw/dist/utils/uv-manager.js.map +1 -0
  385. package/ccw/src/cli.ts +4 -1
  386. package/ccw/src/commands/cli.ts +132 -34
  387. package/ccw/src/commands/issue.ts +605 -91
  388. package/ccw/src/commands/serve.ts +15 -5
  389. package/ccw/src/commands/stop.ts +32 -5
  390. package/ccw/src/commands/tool.ts +17 -2
  391. package/ccw/src/commands/view.ts +13 -3
  392. package/ccw/src/config/cli-settings-manager.ts +460 -0
  393. package/ccw/src/config/litellm-api-config-manager.ts +392 -57
  394. package/ccw/src/core/auth/csrf-manager.ts +104 -0
  395. package/ccw/src/core/auth/csrf-middleware.ts +159 -0
  396. package/ccw/src/core/auth/middleware.ts +94 -0
  397. package/ccw/src/core/auth/token-manager.ts +219 -0
  398. package/ccw/src/core/cache-manager.ts +64 -52
  399. package/ccw/src/core/claude-freshness.ts +26 -6
  400. package/ccw/src/core/core-memory-store.ts +2 -1
  401. package/ccw/src/core/cors.ts +10 -0
  402. package/ccw/src/core/dashboard-generator-patch.ts +47 -48
  403. package/ccw/src/core/dashboard-generator.ts +797 -744
  404. package/ccw/src/core/data-aggregator.ts +667 -667
  405. package/ccw/src/core/lite-scanner.ts +156 -140
  406. package/ccw/src/core/routes/auth-routes.ts +98 -0
  407. package/ccw/src/core/routes/ccw-routes.ts +10 -20
  408. package/ccw/src/core/routes/claude-routes.ts +101 -51
  409. package/ccw/src/core/routes/cli-routes.ts +152 -55
  410. package/ccw/src/core/routes/cli-settings-routes.ts +232 -0
  411. package/ccw/src/core/routes/codexlens/README.md +37 -0
  412. package/ccw/src/core/routes/codexlens/config-handlers.ts +1269 -0
  413. package/ccw/src/core/routes/codexlens/index-handlers.ts +354 -0
  414. package/ccw/src/core/routes/codexlens/semantic-handlers.ts +931 -0
  415. package/ccw/src/core/routes/codexlens/utils.ts +96 -0
  416. package/ccw/src/core/routes/codexlens/watcher-handlers.ts +265 -0
  417. package/ccw/src/core/routes/codexlens-routes.ts +11 -1044
  418. package/ccw/src/core/routes/discovery-routes.ts +1 -12
  419. package/ccw/src/core/routes/files-routes.ts +112 -40
  420. package/ccw/src/core/routes/graph-routes.ts +39 -46
  421. package/ccw/src/core/routes/help-routes.ts +2 -12
  422. package/ccw/src/core/routes/hooks-routes.ts +83 -44
  423. package/ccw/src/core/routes/issue-routes.ts +1 -12
  424. package/ccw/src/core/routes/litellm-api-routes.ts +574 -60
  425. package/ccw/src/core/routes/litellm-routes.ts +35 -27
  426. package/ccw/src/core/routes/mcp-routes.ts +157 -60
  427. package/ccw/src/core/routes/mcp-routes.ts.backup +549 -550
  428. package/ccw/src/core/routes/mcp-templates-db.ts +267 -268
  429. package/ccw/src/core/routes/memory-routes.ts +76 -22
  430. package/ccw/src/core/routes/nav-status-routes.ts +231 -0
  431. package/ccw/src/core/routes/rules-routes.ts +600 -81
  432. package/ccw/src/core/routes/session-routes.ts +28 -22
  433. package/ccw/src/core/routes/skills-routes.ts +452 -132
  434. package/ccw/src/core/routes/status-routes.ts +1 -12
  435. package/ccw/src/core/routes/system-routes.ts +15 -22
  436. package/ccw/src/core/routes/types.ts +25 -0
  437. package/ccw/src/core/server.ts +657 -468
  438. package/ccw/src/core/services/api-key-tester.ts +160 -0
  439. package/ccw/src/core/services/health-check-service.ts +366 -0
  440. package/ccw/src/core/websocket.ts +20 -12
  441. package/ccw/src/templates/dashboard-css/01-base.css +109 -0
  442. package/ccw/src/templates/dashboard-css/10-cli-status.css +202 -0
  443. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +308 -0
  444. package/ccw/src/templates/dashboard-css/30-core-memory.css +20 -0
  445. package/ccw/src/templates/dashboard-css/31-api-settings.css +751 -14
  446. package/ccw/src/templates/dashboard-css/33-cli-stream-viewer.css +230 -2
  447. package/ccw/src/templates/dashboard-js/api.js +5 -0
  448. package/ccw/src/templates/dashboard-js/components/cli-status.js +279 -107
  449. package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +262 -20
  450. package/ccw/src/templates/dashboard-js/components/hook-manager.js +105 -5
  451. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +317 -0
  452. package/ccw/src/templates/dashboard-js/components/navigation.js +45 -0
  453. package/ccw/src/templates/dashboard-js/components/notifications.js +128 -0
  454. package/ccw/src/templates/dashboard-js/i18n.js +4448 -3983
  455. package/ccw/src/templates/dashboard-js/main.js +71 -0
  456. package/ccw/src/templates/dashboard-js/services.js +289 -0
  457. package/ccw/src/templates/dashboard-js/views/api-settings.js +5613 -3361
  458. package/ccw/src/templates/dashboard-js/views/claude-manager.js +1 -7
  459. package/ccw/src/templates/dashboard-js/views/cli-manager.js +581 -87
  460. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +6101 -1965
  461. package/ccw/src/templates/dashboard-js/views/core-memory.js +129 -20
  462. package/ccw/src/templates/dashboard-js/views/hook-manager.js +17 -3
  463. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +63 -0
  464. package/ccw/src/templates/dashboard-js/views/project-overview.js +182 -37
  465. package/ccw/src/templates/dashboard-js/views/rules-manager.js +26 -3
  466. package/ccw/src/templates/dashboard-js/views/skills-manager.js +2 -42
  467. package/ccw/src/templates/dashboard.html +6 -0
  468. package/ccw/src/tools/README.md +29 -0
  469. package/ccw/src/tools/claude-cli-tools.ts +640 -125
  470. package/ccw/src/tools/cli-config-manager.ts +102 -172
  471. package/ccw/src/tools/cli-executor-core.ts +1533 -0
  472. package/ccw/src/tools/cli-executor-state.ts +560 -0
  473. package/ccw/src/tools/cli-executor-utils.ts +349 -0
  474. package/ccw/src/tools/cli-executor.ts +3 -2309
  475. package/ccw/src/tools/cli-history-store.ts +2 -0
  476. package/ccw/src/tools/cli-output-converter.ts +1237 -0
  477. package/ccw/src/tools/cli-prompt-builder.ts +487 -0
  478. package/ccw/src/tools/codex-lens.ts +324 -59
  479. package/ccw/src/tools/detect-changed-modules.ts +24 -6
  480. package/ccw/src/tools/index.ts +2 -0
  481. package/ccw/src/tools/litellm-client.ts +10 -4
  482. package/ccw/src/tools/litellm-executor.ts +146 -114
  483. package/ccw/src/tools/native-session-discovery.ts +209 -1
  484. package/ccw/src/tools/session-manager.ts +88 -0
  485. package/ccw/src/tools/skill-context-loader.ts +213 -0
  486. package/ccw/src/tools/smart-search.ts +427 -76
  487. package/ccw/src/types/cli-settings.ts +137 -0
  488. package/ccw/src/types/litellm-api-config.ts +55 -1
  489. package/ccw/src/utils/exec-constants.ts +24 -0
  490. package/ccw/src/utils/path-resolver.ts +49 -3
  491. package/ccw/src/utils/path-validator.ts +28 -6
  492. package/ccw/src/utils/python-utils.ts +140 -121
  493. package/ccw/src/utils/shell-escape.ts +30 -0
  494. package/ccw/src/utils/uv-manager.ts +796 -0
  495. package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-310.pyc +0 -0
  496. package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-312.pyc +0 -0
  497. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-310.pyc +0 -0
  498. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-312.pyc +0 -0
  499. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-310.pyc +0 -0
  500. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-312.pyc +0 -0
  501. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  502. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-310.pyc +0 -0
  503. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-312.pyc +0 -0
  504. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-313.pyc +0 -0
  505. package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +270 -251
  506. package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +33 -0
  507. package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-310.pyc +0 -0
  508. package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-312.pyc +0 -0
  509. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-310.pyc +0 -0
  510. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-312.pyc +0 -0
  511. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-313.pyc +0 -0
  512. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-310.pyc +0 -0
  513. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-312.pyc +0 -0
  514. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-313.pyc +0 -0
  515. package/ccw-litellm/src/ccw_litellm/config/loader.py +343 -316
  516. package/ccw-litellm/src/ccw_litellm/config/models.py +162 -130
  517. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-310.pyc +0 -0
  518. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-312.pyc +0 -0
  519. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-310.pyc +0 -0
  520. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-312.pyc +0 -0
  521. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-310.pyc +0 -0
  522. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-312.pyc +0 -0
  523. package/codex-lens/pyproject.toml +43 -0
  524. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-310.pyc +0 -0
  525. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-312.pyc +0 -0
  526. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-310.pyc +0 -0
  527. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-312.pyc +0 -0
  528. package/codex-lens/src/codexlens/__pycache__/config.cpython-310.pyc +0 -0
  529. package/codex-lens/src/codexlens/__pycache__/config.cpython-312.pyc +0 -0
  530. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  531. package/codex-lens/src/codexlens/__pycache__/entities.cpython-310.pyc +0 -0
  532. package/codex-lens/src/codexlens/__pycache__/entities.cpython-312.pyc +0 -0
  533. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  534. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-310.pyc +0 -0
  535. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-312.pyc +0 -0
  536. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-313.pyc +0 -0
  537. package/codex-lens/src/codexlens/__pycache__/errors.cpython-310.pyc +0 -0
  538. package/codex-lens/src/codexlens/__pycache__/errors.cpython-312.pyc +0 -0
  539. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  540. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  541. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-310.pyc +0 -0
  542. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-312.pyc +0 -0
  543. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  544. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-310.pyc +0 -0
  545. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-312.pyc +0 -0
  546. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  547. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-310.pyc +0 -0
  548. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-312.pyc +0 -0
  549. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  550. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-310.pyc +0 -0
  551. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-312.pyc +0 -0
  552. package/codex-lens/src/codexlens/cli/commands.py +4416 -2295
  553. package/codex-lens/src/codexlens/cli/embedding_manager.py +777 -15
  554. package/codex-lens/src/codexlens/cli/model_manager.py +676 -0
  555. package/codex-lens/src/codexlens/config.py +356 -12
  556. package/codex-lens/src/codexlens/entities.py +4 -1
  557. package/codex-lens/src/codexlens/env_config.py +304 -0
  558. package/codex-lens/src/codexlens/indexing/__init__.py +23 -1
  559. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  560. package/codex-lens/src/codexlens/indexing/__pycache__/embedding.cpython-313.pyc +0 -0
  561. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  562. package/codex-lens/src/codexlens/indexing/embedding.py +582 -0
  563. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +62 -28
  564. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-310.pyc +0 -0
  565. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-312.pyc +0 -0
  566. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-310.pyc +0 -0
  567. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-312.pyc +0 -0
  568. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  569. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-310.pyc +0 -0
  570. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-312.pyc +0 -0
  571. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-310.pyc +0 -0
  572. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-312.pyc +0 -0
  573. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  574. package/codex-lens/src/codexlens/parsers/factory.py +139 -10
  575. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +487 -13
  576. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-310.pyc +0 -0
  577. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-312.pyc +0 -0
  578. package/codex-lens/src/codexlens/search/__pycache__/binary_searcher.cpython-313.pyc +0 -0
  579. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-310.pyc +0 -0
  580. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-312.pyc +0 -0
  581. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  582. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  583. package/codex-lens/src/codexlens/search/__pycache__/graph_expander.cpython-313.pyc +0 -0
  584. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-310.pyc +0 -0
  585. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-312.pyc +0 -0
  586. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  587. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-310.pyc +0 -0
  588. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-312.pyc +0 -0
  589. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  590. package/codex-lens/src/codexlens/search/binary_searcher.py +277 -0
  591. package/codex-lens/src/codexlens/search/chain_search.py +1652 -8
  592. package/codex-lens/src/codexlens/search/enrichment.py +21 -0
  593. package/codex-lens/src/codexlens/search/graph_expander.py +264 -0
  594. package/codex-lens/src/codexlens/search/hybrid_search.py +772 -37
  595. package/codex-lens/src/codexlens/search/ranking.py +397 -8
  596. package/codex-lens/src/codexlens/semantic/SPLADE_IMPLEMENTATION.md +225 -0
  597. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-310.pyc +0 -0
  598. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-312.pyc +0 -0
  599. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-310.pyc +0 -0
  600. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-312.pyc +0 -0
  601. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  602. package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-310.pyc +0 -0
  603. package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-312.pyc +0 -0
  604. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-310.pyc +0 -0
  605. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-312.pyc +0 -0
  606. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  607. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-310.pyc +0 -0
  608. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-312.pyc +0 -0
  609. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-310.pyc +0 -0
  610. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-312.pyc +0 -0
  611. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-313.pyc +0 -0
  612. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-310.pyc +0 -0
  613. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-312.pyc +0 -0
  614. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
  615. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-310.pyc +0 -0
  616. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-312.pyc +0 -0
  617. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  618. package/codex-lens/src/codexlens/semantic/__pycache__/reranker.cpython-313.pyc +0 -0
  619. package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-310.pyc +0 -0
  620. package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-312.pyc +0 -0
  621. package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-313.pyc +0 -0
  622. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-310.pyc +0 -0
  623. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-312.pyc +0 -0
  624. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  625. package/codex-lens/src/codexlens/semantic/ann_index.py +654 -0
  626. package/codex-lens/src/codexlens/semantic/chunker.py +328 -23
  627. package/codex-lens/src/codexlens/semantic/factory.py +63 -3
  628. package/codex-lens/src/codexlens/semantic/gpu_support.py +19 -2
  629. package/codex-lens/src/codexlens/semantic/litellm_embedder.py +144 -144
  630. package/codex-lens/src/codexlens/semantic/reranker/__init__.py +25 -0
  631. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-310.pyc +0 -0
  632. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-312.pyc +0 -0
  633. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-313.pyc +0 -0
  634. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-310.pyc +0 -0
  635. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-312.pyc +0 -0
  636. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-313.pyc +0 -0
  637. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-310.pyc +0 -0
  638. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-312.pyc +0 -0
  639. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-313.pyc +0 -0
  640. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-310.pyc +0 -0
  641. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-312.pyc +0 -0
  642. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-313.pyc +0 -0
  643. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-310.pyc +0 -0
  644. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-312.pyc +0 -0
  645. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-313.pyc +0 -0
  646. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-310.pyc +0 -0
  647. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-312.pyc +0 -0
  648. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-313.pyc +0 -0
  649. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/litellm_reranker.cpython-313.pyc +0 -0
  650. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-310.pyc +0 -0
  651. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-312.pyc +0 -0
  652. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-313.pyc +0 -0
  653. package/codex-lens/src/codexlens/semantic/reranker/api_reranker.py +403 -0
  654. package/codex-lens/src/codexlens/semantic/reranker/base.py +46 -0
  655. package/codex-lens/src/codexlens/semantic/reranker/factory.py +159 -0
  656. package/codex-lens/src/codexlens/semantic/reranker/fastembed_reranker.py +257 -0
  657. package/codex-lens/src/codexlens/semantic/reranker/legacy.py +91 -0
  658. package/codex-lens/src/codexlens/semantic/reranker/litellm_reranker.py +214 -0
  659. package/codex-lens/src/codexlens/semantic/reranker/onnx_reranker.py +268 -0
  660. package/codex-lens/src/codexlens/semantic/splade_encoder.py +567 -0
  661. package/codex-lens/src/codexlens/semantic/vector_store.py +472 -352
  662. package/codex-lens/src/codexlens/storage/__init__.py +3 -0
  663. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-310.pyc +0 -0
  664. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-312.pyc +0 -0
  665. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  666. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-310.pyc +0 -0
  667. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-312.pyc +0 -0
  668. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  669. package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-310.pyc +0 -0
  670. package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-312.pyc +0 -0
  671. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-310.pyc +0 -0
  672. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-312.pyc +0 -0
  673. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  674. package/codex-lens/src/codexlens/storage/__pycache__/merkle_tree.cpython-313.pyc +0 -0
  675. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-310.pyc +0 -0
  676. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-312.pyc +0 -0
  677. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-310.pyc +0 -0
  678. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-312.pyc +0 -0
  679. package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-310.pyc +0 -0
  680. package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-312.pyc +0 -0
  681. package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-313.pyc +0 -0
  682. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-310.pyc +0 -0
  683. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-312.pyc +0 -0
  684. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  685. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-310.pyc +0 -0
  686. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-312.pyc +0 -0
  687. package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-310.pyc +0 -0
  688. package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-312.pyc +0 -0
  689. package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-313.pyc +0 -0
  690. package/codex-lens/src/codexlens/storage/dir_index.py +310 -12
  691. package/codex-lens/src/codexlens/storage/index_tree.py +240 -25
  692. package/codex-lens/src/codexlens/storage/merkle_tree.py +136 -0
  693. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-310.pyc +0 -0
  694. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
  695. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_006_enhance_relationships.cpython-313.pyc +0 -0
  696. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-310.pyc +0 -0
  697. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-312.pyc +0 -0
  698. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-313.pyc +0 -0
  699. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_008_add_merkle_hashes.cpython-313.pyc +0 -0
  700. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_009_add_splade.cpython-313.pyc +0 -0
  701. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_010_add_multi_vector_chunks.cpython-313.pyc +0 -0
  702. package/codex-lens/src/codexlens/storage/migrations/migration_006_enhance_relationships.py +37 -0
  703. package/codex-lens/src/codexlens/storage/migrations/migration_007_add_graph_neighbors.py +47 -0
  704. package/codex-lens/src/codexlens/storage/migrations/migration_008_add_merkle_hashes.py +81 -0
  705. package/codex-lens/src/codexlens/storage/migrations/migration_009_add_splade.py +103 -0
  706. package/codex-lens/src/codexlens/storage/migrations/migration_010_add_multi_vector_chunks.py +162 -0
  707. package/codex-lens/src/codexlens/storage/splade_index.py +578 -0
  708. package/codex-lens/src/codexlens/storage/sqlite_store.py +508 -184
  709. package/codex-lens/src/codexlens/storage/vector_meta_store.py +415 -0
  710. package/codex-lens/src/codexlens/watcher/__init__.py +17 -0
  711. package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-310.pyc +0 -0
  712. package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-312.pyc +0 -0
  713. package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-313.pyc +0 -0
  714. package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-310.pyc +0 -0
  715. package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-312.pyc +0 -0
  716. package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-313.pyc +0 -0
  717. package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-310.pyc +0 -0
  718. package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-312.pyc +0 -0
  719. package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-313.pyc +0 -0
  720. package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-310.pyc +0 -0
  721. package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-312.pyc +0 -0
  722. package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-313.pyc +0 -0
  723. package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-310.pyc +0 -0
  724. package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-312.pyc +0 -0
  725. package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-313.pyc +0 -0
  726. package/codex-lens/src/codexlens/watcher/events.py +82 -0
  727. package/codex-lens/src/codexlens/watcher/file_watcher.py +347 -0
  728. package/codex-lens/src/codexlens/watcher/incremental_indexer.py +369 -0
  729. package/codex-lens/src/codexlens/watcher/manager.py +255 -0
  730. package/package.json +4 -1
  731. package/.claude/commands/workflow/docs/analyze.md +0 -1467
  732. package/.claude/commands/workflow/docs/copyright.md +0 -1265
  733. package/.claude/skills/command-guide/SKILL.md +0 -388
  734. package/.claude/skills/command-guide/UPDATE-GUIDELINE.md +0 -592
  735. package/.claude/skills/command-guide/guides/cli-tools-guide.md +0 -410
  736. package/.claude/skills/command-guide/guides/examples.md +0 -537
  737. package/.claude/skills/command-guide/guides/getting-started.md +0 -242
  738. package/.claude/skills/command-guide/guides/implementation-details.md +0 -1010
  739. package/.claude/skills/command-guide/guides/index-structure.md +0 -326
  740. package/.claude/skills/command-guide/guides/troubleshooting.md +0 -92
  741. package/.claude/skills/command-guide/guides/ui-design-workflow-guide.md +0 -316
  742. package/.claude/skills/command-guide/guides/workflow-patterns.md +0 -662
  743. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +0 -855
  744. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +0 -267
  745. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +0 -182
  746. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +0 -446
  747. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +0 -558
  748. package/.claude/skills/command-guide/reference/agents/code-developer.md +0 -311
  749. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +0 -308
  750. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +0 -581
  751. package/.claude/skills/command-guide/reference/agents/doc-generator.md +0 -330
  752. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +0 -94
  753. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +0 -400
  754. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +0 -344
  755. package/.claude/skills/command-guide/reference/agents/ui-design-agent.md +0 -593
  756. package/.claude/skills/command-guide/reference/agents/universal-executor.md +0 -131
  757. package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +0 -440
  758. package/.claude/skills/command-guide/reference/commands/enhance-prompt.md +0 -93
  759. package/.claude/skills/command-guide/reference/commands/memory/code-map-memory.md +0 -687
  760. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +0 -471
  761. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +0 -386
  762. package/.claude/skills/command-guide/reference/commands/memory/docs.md +0 -616
  763. package/.claude/skills/command-guide/reference/commands/memory/load-skill-memory.md +0 -182
  764. package/.claude/skills/command-guide/reference/commands/memory/load.md +0 -240
  765. package/.claude/skills/command-guide/reference/commands/memory/skill-memory.md +0 -525
  766. package/.claude/skills/command-guide/reference/commands/memory/style-skill-memory.md +0 -396
  767. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +0 -314
  768. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +0 -332
  769. package/.claude/skills/command-guide/reference/commands/memory/update-related.md +0 -332
  770. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +0 -517
  771. package/.claude/skills/command-guide/reference/commands/task/breakdown.md +0 -204
  772. package/.claude/skills/command-guide/reference/commands/task/create.md +0 -152
  773. package/.claude/skills/command-guide/reference/commands/task/execute.md +0 -270
  774. package/.claude/skills/command-guide/reference/commands/task/replan.md +0 -437
  775. package/.claude/skills/command-guide/reference/commands/version.md +0 -254
  776. package/.claude/skills/command-guide/reference/commands/workflow/action-plan-verify.md +0 -447
  777. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +0 -585
  778. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +0 -452
  779. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +0 -443
  780. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +0 -220
  781. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +0 -200
  782. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +0 -200
  783. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +0 -200
  784. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
  785. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +0 -398
  786. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +0 -387
  787. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +0 -221
  788. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +0 -221
  789. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +0 -465
  790. package/.claude/skills/command-guide/reference/commands/workflow/init.md +0 -164
  791. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +0 -748
  792. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +0 -664
  793. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +0 -645
  794. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +0 -551
  795. package/.claude/skills/command-guide/reference/commands/workflow/replan.md +0 -515
  796. package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +0 -606
  797. package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +0 -765
  798. package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +0 -776
  799. package/.claude/skills/command-guide/reference/commands/workflow/review.md +0 -298
  800. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +0 -547
  801. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +0 -114
  802. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +0 -77
  803. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +0 -257
  804. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +0 -460
  805. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +0 -400
  806. package/.claude/skills/command-guide/reference/commands/workflow/test-cycle-execute.md +0 -498
  807. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +0 -699
  808. package/.claude/skills/command-guide/reference/commands/workflow/test-gen.md +0 -529
  809. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +0 -766
  810. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +0 -433
  811. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +0 -487
  812. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +0 -518
  813. package/.claude/skills/command-guide/reference/commands/workflow/tools/tdd-coverage-analysis.md +0 -309
  814. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +0 -163
  815. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +0 -232
  816. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +0 -254
  817. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/animation-extract.md +0 -1150
  818. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/codify-style.md +0 -652
  819. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/design-sync.md +0 -454
  820. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/explore-auto.md +0 -678
  821. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +0 -504
  822. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/imitate-auto.md +0 -745
  823. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +0 -537
  824. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/layout-extract.md +0 -788
  825. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/reference-page-generator.md +0 -356
  826. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/style-extract.md +0 -773
  827. package/.claude/skills/command-guide/scripts/analyze_commands.py +0 -502
  828. package/.claude/skills/command-guide/scripts/update-index.sh +0 -130
  829. package/.claude/skills/command-guide/templates/issue-bug.md +0 -104
  830. package/.claude/skills/command-guide/templates/issue-diagnosis.md +0 -275
  831. package/.claude/skills/command-guide/templates/issue-feature.md +0 -97
  832. package/.claude/skills/command-guide/templates/issue-question.md +0 -141
@@ -1,667 +1,667 @@
1
- import { glob } from 'glob';
2
- import { readFileSync, existsSync } from 'fs';
3
- import { join, basename } from 'path';
4
- import { scanLiteTasks } from './lite-scanner.js';
5
- import { createDashboardCache } from './cache-manager.js';
6
-
7
- interface SessionData {
8
- session_id: string;
9
- project: string;
10
- status: string;
11
- type: string;
12
- workflow_type: string | null;
13
- created_at: string | null;
14
- archived_at: string | null;
15
- path: string;
16
- tasks: TaskData[];
17
- taskCount: number;
18
- hasReview: boolean;
19
- reviewSummary: ReviewSummary | null;
20
- reviewDimensions: DimensionData[];
21
- }
22
-
23
- interface TaskData {
24
- task_id: string;
25
- title: string;
26
- status: string;
27
- type: string;
28
- meta?: Record<string, unknown>;
29
- context?: Record<string, unknown>;
30
- flow_control?: Record<string, unknown>;
31
- }
32
-
33
- interface ReviewSummary {
34
- phase: string;
35
- severityDistribution: Record<string, number>;
36
- criticalFiles: string[];
37
- status: string;
38
- }
39
-
40
- interface DimensionData {
41
- name: string;
42
- findings: Finding[];
43
- summary: unknown | null;
44
- status: string;
45
- }
46
-
47
- interface Finding {
48
- severity?: string;
49
- [key: string]: unknown;
50
- }
51
-
52
- interface SessionInput {
53
- session_id?: string;
54
- id?: string;
55
- project?: string;
56
- description?: string;
57
- status?: string;
58
- type?: string;
59
- workflow_type?: string | null;
60
- created_at?: string | null; // For backward compatibility
61
- created?: string; // From SessionMetadata
62
- updated?: string; // From SessionMetadata
63
- archived_at?: string | null;
64
- path: string;
65
- }
66
-
67
- interface ScanSessionsResult {
68
- active: SessionInput[];
69
- archived: SessionInput[];
70
- hasReviewData: boolean;
71
- }
72
-
73
- interface DashboardData {
74
- generatedAt: string;
75
- activeSessions: SessionData[];
76
- archivedSessions: SessionData[];
77
- liteTasks: {
78
- litePlan: unknown[];
79
- liteFix: unknown[];
80
- };
81
- reviewData: ReviewData | null;
82
- projectOverview: ProjectOverview | null;
83
- statistics: {
84
- totalSessions: number;
85
- activeSessions: number;
86
- totalTasks: number;
87
- completedTasks: number;
88
- reviewFindings: number;
89
- litePlanCount: number;
90
- liteFixCount: number;
91
- };
92
- }
93
-
94
- interface ReviewData {
95
- totalFindings: number;
96
- severityDistribution: {
97
- critical: number;
98
- high: number;
99
- medium: number;
100
- low: number;
101
- };
102
- dimensionSummary: Record<string, { count: number; sessions: string[] }>;
103
- sessions: SessionReviewData[];
104
- }
105
-
106
- interface SessionReviewData {
107
- session_id: string;
108
- progress: unknown | null;
109
- dimensions: DimensionData[];
110
- findings: Array<Finding & { dimension: string }>;
111
- }
112
-
113
- interface ProjectGuidelines {
114
- conventions: {
115
- coding_style: string[];
116
- naming_patterns: string[];
117
- file_structure: string[];
118
- documentation: string[];
119
- };
120
- constraints: {
121
- architecture: string[];
122
- tech_stack: string[];
123
- performance: string[];
124
- security: string[];
125
- };
126
- quality_rules: Array<{ rule: string; scope: string; enforced_by?: string }>;
127
- learnings: Array<{
128
- date: string;
129
- session_id?: string;
130
- insight: string;
131
- context?: string;
132
- category?: string;
133
- }>;
134
- _metadata?: {
135
- created_at: string;
136
- updated_at?: string;
137
- version: string;
138
- };
139
- }
140
-
141
- interface ProjectOverview {
142
- projectName: string;
143
- description: string;
144
- initializedAt: string | null;
145
- technologyStack: {
146
- languages: string[];
147
- frameworks: string[];
148
- build_tools: string[];
149
- test_frameworks: string[];
150
- };
151
- architecture: {
152
- style: string;
153
- layers: string[];
154
- patterns: string[];
155
- };
156
- keyComponents: string[];
157
- features: unknown[];
158
- developmentIndex: {
159
- feature: unknown[];
160
- enhancement: unknown[];
161
- bugfix: unknown[];
162
- refactor: unknown[];
163
- docs: unknown[];
164
- };
165
- statistics: {
166
- total_features: number;
167
- total_sessions: number;
168
- last_updated: string | null;
169
- };
170
- metadata: {
171
- initialized_by: string;
172
- analysis_timestamp: string | null;
173
- analysis_mode: string;
174
- };
175
- guidelines: ProjectGuidelines | null;
176
- }
177
-
178
- /**
179
- * Aggregate all data for dashboard rendering (with caching)
180
- * @param sessions - Scanned sessions from session-scanner
181
- * @param workflowDir - Path to .workflow directory
182
- * @returns Aggregated dashboard data
183
- */
184
- export async function aggregateData(sessions: ScanSessionsResult, workflowDir: string): Promise<DashboardData> {
185
- // Initialize cache manager
186
- const cache = createDashboardCache(workflowDir);
187
-
188
- // Prepare paths to watch for changes (includes both new dual files and legacy)
189
- const watchPaths = [
190
- join(workflowDir, 'active'),
191
- join(workflowDir, 'archives'),
192
- join(workflowDir, 'project-tech.json'),
193
- join(workflowDir, 'project-guidelines.json'),
194
- join(workflowDir, 'project.json'), // Legacy support
195
- ...sessions.active.map(s => s.path),
196
- ...sessions.archived.map(s => s.path)
197
- ];
198
-
199
- // Check cache first
200
- const cachedData = cache.get(watchPaths);
201
- if (cachedData !== null) {
202
- console.log('Using cached dashboard data');
203
- return cachedData;
204
- }
205
-
206
- console.log('Cache miss - regenerating dashboard data');
207
-
208
- const data: DashboardData = {
209
- generatedAt: new Date().toISOString(),
210
- activeSessions: [],
211
- archivedSessions: [],
212
- liteTasks: {
213
- litePlan: [],
214
- liteFix: []
215
- },
216
- reviewData: null,
217
- projectOverview: null,
218
- statistics: {
219
- totalSessions: 0,
220
- activeSessions: 0,
221
- totalTasks: 0,
222
- completedTasks: 0,
223
- reviewFindings: 0,
224
- litePlanCount: 0,
225
- liteFixCount: 0
226
- }
227
- };
228
-
229
- // Process active sessions
230
- for (const session of sessions.active) {
231
- const sessionData = await processSession(session, true);
232
- data.activeSessions.push(sessionData);
233
- data.statistics.totalTasks += sessionData.tasks.length;
234
- data.statistics.completedTasks += sessionData.tasks.filter(t => t.status === 'completed').length;
235
- }
236
-
237
- // Process archived sessions
238
- for (const session of sessions.archived) {
239
- const sessionData = await processSession(session, false);
240
- data.archivedSessions.push(sessionData);
241
- data.statistics.totalTasks += sessionData.taskCount || 0;
242
- data.statistics.completedTasks += sessionData.taskCount || 0;
243
- }
244
-
245
- // Aggregate review data if present
246
- if (sessions.hasReviewData) {
247
- data.reviewData = await aggregateReviewData(sessions.active);
248
- data.statistics.reviewFindings = data.reviewData.totalFindings;
249
- }
250
-
251
- data.statistics.totalSessions = sessions.active.length + sessions.archived.length;
252
- data.statistics.activeSessions = sessions.active.length;
253
-
254
- // Scan and include lite tasks
255
- try {
256
- const liteTasks = await scanLiteTasks(workflowDir);
257
- data.liteTasks = liteTasks;
258
- data.statistics.litePlanCount = liteTasks.litePlan.length;
259
- data.statistics.liteFixCount = liteTasks.liteFix.length;
260
- } catch (err) {
261
- console.error('Error scanning lite tasks:', (err as Error).message);
262
- }
263
-
264
- // Load project overview from project.json
265
- try {
266
- data.projectOverview = loadProjectOverview(workflowDir);
267
- } catch (err) {
268
- console.error('Error loading project overview:', (err as Error).message);
269
- }
270
-
271
- // Store in cache before returning
272
- cache.set(data, watchPaths);
273
-
274
- return data;
275
- }
276
-
277
- /**
278
- * Process a single session, loading tasks and review info
279
- * @param session - Session object from scanner
280
- * @param isActive - Whether session is active
281
- * @returns Processed session data
282
- */
283
- async function processSession(session: SessionInput, isActive: boolean): Promise<SessionData> {
284
- const result: SessionData = {
285
- session_id: session.session_id || session.id || '',
286
- project: session.project || session.description || session.session_id || session.id || '',
287
- status: session.status || (isActive ? 'active' : 'archived'),
288
- type: session.type || 'workflow', // Session type (workflow, review, test, docs)
289
- workflow_type: session.workflow_type || null, // Original workflow_type for reference
290
- created_at: session.created || session.created_at || null, // Prefer 'created' from SessionMetadata, fallback to 'created_at'
291
- archived_at: session.archived_at || null, // Raw ISO string - let frontend format
292
- path: session.path,
293
- tasks: [],
294
- taskCount: 0,
295
- hasReview: false,
296
- reviewSummary: null,
297
- reviewDimensions: []
298
- };
299
-
300
- // Load tasks for active sessions (full details)
301
- if (isActive) {
302
- const taskDir = join(session.path, '.task');
303
- if (existsSync(taskDir)) {
304
- const taskFiles = await safeGlob('IMPL-*.json', taskDir);
305
- for (const taskFile of taskFiles) {
306
- try {
307
- const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8')) as Record<string, unknown>;
308
- result.tasks.push({
309
- task_id: (taskData.id as string) || basename(taskFile, '.json'),
310
- title: (taskData.title as string) || 'Untitled Task',
311
- status: (taskData.status as string) || 'pending',
312
- type: ((taskData.meta as Record<string, unknown>)?.type as string) || 'task',
313
- meta: (taskData.meta as Record<string, unknown>) || {},
314
- context: (taskData.context as Record<string, unknown>) || {},
315
- flow_control: (taskData.flow_control as Record<string, unknown>) || {}
316
- });
317
- } catch {
318
- // Skip invalid task files
319
- }
320
- }
321
- // Sort tasks by ID
322
- result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id));
323
- }
324
- result.taskCount = result.tasks.length;
325
-
326
- // Check for review data
327
- const reviewDir = join(session.path, '.review');
328
- if (existsSync(reviewDir)) {
329
- result.hasReview = true;
330
- result.reviewSummary = loadReviewSummary(reviewDir);
331
- // Load dimension data for review sessions
332
- if (session.type === 'review') {
333
- result.reviewDimensions = await loadDimensionData(reviewDir);
334
- }
335
- }
336
- } else {
337
- // For archived, also load tasks (same as active)
338
- const taskDir = join(session.path, '.task');
339
- if (existsSync(taskDir)) {
340
- const taskFiles = await safeGlob('IMPL-*.json', taskDir);
341
- for (const taskFile of taskFiles) {
342
- try {
343
- const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8')) as Record<string, unknown>;
344
- result.tasks.push({
345
- task_id: (taskData.id as string) || basename(taskFile, '.json'),
346
- title: (taskData.title as string) || 'Untitled Task',
347
- status: (taskData.status as string) || 'completed', // Archived tasks are usually completed
348
- type: ((taskData.meta as Record<string, unknown>)?.type as string) || 'task'
349
- });
350
- } catch {
351
- // Skip invalid task files
352
- }
353
- }
354
- // Sort tasks by ID
355
- result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id));
356
- result.taskCount = result.tasks.length;
357
- }
358
-
359
- // Check for review data in archived sessions too
360
- const reviewDir = join(session.path, '.review');
361
- if (existsSync(reviewDir)) {
362
- result.hasReview = true;
363
- result.reviewSummary = loadReviewSummary(reviewDir);
364
- // Load dimension data for review sessions
365
- if (session.type === 'review') {
366
- result.reviewDimensions = await loadDimensionData(reviewDir);
367
- }
368
- }
369
- }
370
-
371
- return result;
372
- }
373
-
374
- /**
375
- * Aggregate review data from all active sessions with reviews
376
- * @param activeSessions - Active session objects
377
- * @returns Aggregated review data
378
- */
379
- async function aggregateReviewData(activeSessions: SessionInput[]): Promise<ReviewData> {
380
- const reviewData: ReviewData = {
381
- totalFindings: 0,
382
- severityDistribution: { critical: 0, high: 0, medium: 0, low: 0 },
383
- dimensionSummary: {},
384
- sessions: []
385
- };
386
-
387
- for (const session of activeSessions) {
388
- const reviewDir = join(session.path, '.review');
389
- if (!existsSync(reviewDir)) continue;
390
-
391
- const reviewProgress = loadReviewProgress(reviewDir);
392
- const dimensionData = await loadDimensionData(reviewDir);
393
-
394
- if (reviewProgress || dimensionData.length > 0) {
395
- const sessionReview: SessionReviewData = {
396
- session_id: session.session_id || session.id || '',
397
- progress: reviewProgress,
398
- dimensions: dimensionData,
399
- findings: []
400
- };
401
-
402
- // Collect and count findings
403
- for (const dim of dimensionData) {
404
- if (dim.findings && Array.isArray(dim.findings)) {
405
- for (const finding of dim.findings) {
406
- const severity = (finding.severity || 'low').toLowerCase();
407
- if (reviewData.severityDistribution.hasOwnProperty(severity)) {
408
- reviewData.severityDistribution[severity as keyof typeof reviewData.severityDistribution]++;
409
- }
410
- reviewData.totalFindings++;
411
- sessionReview.findings.push({
412
- ...finding,
413
- dimension: dim.name
414
- });
415
- }
416
- }
417
-
418
- // Track dimension summary
419
- if (!reviewData.dimensionSummary[dim.name]) {
420
- reviewData.dimensionSummary[dim.name] = { count: 0, sessions: [] };
421
- }
422
- reviewData.dimensionSummary[dim.name].count += dim.findings?.length || 0;
423
- reviewData.dimensionSummary[dim.name].sessions.push(session.session_id || session.id || '');
424
- }
425
-
426
- reviewData.sessions.push(sessionReview);
427
- }
428
- }
429
-
430
- return reviewData;
431
- }
432
-
433
- /**
434
- * Load review progress from review-progress.json
435
- * @param reviewDir - Path to .review directory
436
- * @returns Review progress data or null
437
- */
438
- function loadReviewProgress(reviewDir: string): unknown | null {
439
- const progressFile = join(reviewDir, 'review-progress.json');
440
- if (!existsSync(progressFile)) return null;
441
- try {
442
- return JSON.parse(readFileSync(progressFile, 'utf8'));
443
- } catch {
444
- return null;
445
- }
446
- }
447
-
448
- /**
449
- * Load review summary from review-state.json
450
- * @param reviewDir - Path to .review directory
451
- * @returns Review summary or null
452
- */
453
- function loadReviewSummary(reviewDir: string): ReviewSummary | null {
454
- const stateFile = join(reviewDir, 'review-state.json');
455
- if (!existsSync(stateFile)) return null;
456
- try {
457
- const state = JSON.parse(readFileSync(stateFile, 'utf8')) as Record<string, unknown>;
458
- return {
459
- phase: (state.phase as string) || 'unknown',
460
- severityDistribution: (state.severity_distribution as Record<string, number>) || {},
461
- criticalFiles: ((state.critical_files as string[]) || []).slice(0, 3),
462
- status: (state.status as string) || 'in_progress'
463
- };
464
- } catch {
465
- return null;
466
- }
467
- }
468
-
469
- /**
470
- * Load dimension data from .review/dimensions/
471
- * @param reviewDir - Path to .review directory
472
- * @returns Array of dimension data
473
- */
474
- async function loadDimensionData(reviewDir: string): Promise<DimensionData[]> {
475
- const dimensionsDir = join(reviewDir, 'dimensions');
476
- if (!existsSync(dimensionsDir)) return [];
477
-
478
- const dimensions: DimensionData[] = [];
479
- const dimFiles = await safeGlob('*.json', dimensionsDir);
480
-
481
- for (const file of dimFiles) {
482
- try {
483
- const data = JSON.parse(readFileSync(join(dimensionsDir, file), 'utf8'));
484
- // Handle array structure: [ { findings: [...], summary: {...} } ]
485
- let findings: Finding[] = [];
486
- let summary: unknown | null = null;
487
- let status = 'completed';
488
-
489
- if (Array.isArray(data) && data.length > 0) {
490
- const dimData = data[0] as Record<string, unknown>;
491
- findings = (dimData.findings as Finding[]) || [];
492
- summary = dimData.summary || null;
493
- status = (dimData.status as string) || 'completed';
494
- } else if ((data as Record<string, unknown>).findings) {
495
- const dataObj = data as Record<string, unknown>;
496
- findings = (dataObj.findings as Finding[]) || [];
497
- summary = dataObj.summary || null;
498
- status = (dataObj.status as string) || 'completed';
499
- }
500
-
501
- dimensions.push({
502
- name: basename(file, '.json'),
503
- findings: findings,
504
- summary: summary,
505
- status: status
506
- });
507
- } catch {
508
- // Skip invalid dimension files
509
- }
510
- }
511
-
512
- return dimensions;
513
- }
514
-
515
- /**
516
- * Safe glob wrapper that returns empty array on error
517
- * @param pattern - Glob pattern
518
- * @param cwd - Current working directory
519
- * @returns Array of matching file names
520
- */
521
- async function safeGlob(pattern: string, cwd: string): Promise<string[]> {
522
- try {
523
- return await glob(pattern, { cwd, absolute: false });
524
- } catch {
525
- return [];
526
- }
527
- }
528
-
529
- // formatDate removed - dates are now passed as raw ISO strings
530
- // Frontend (dashboard.js) handles all date formatting
531
-
532
- /**
533
- * Sort task IDs numerically (IMPL-1, IMPL-2, IMPL-1.1, etc.)
534
- * @param a - First task ID
535
- * @param b - Second task ID
536
- * @returns Comparison result
537
- */
538
- function sortTaskIds(a: string, b: string): number {
539
- const parseId = (id: string): [number, number] => {
540
- const match = id.match(/IMPL-(\d+)(?:\.(\d+))?/);
541
- if (!match) return [0, 0];
542
- return [parseInt(match[1]), parseInt(match[2] || '0')];
543
- };
544
- const [a1, a2] = parseId(a);
545
- const [b1, b2] = parseId(b);
546
- return a1 - b1 || a2 - b2;
547
- }
548
-
549
- /**
550
- * Load project overview from project-tech.json and project-guidelines.json
551
- * Supports dual file structure with backward compatibility for legacy project.json
552
- * @param workflowDir - Path to .workflow directory
553
- * @returns Project overview data or null if not found
554
- */
555
- function loadProjectOverview(workflowDir: string): ProjectOverview | null {
556
- const techFile = join(workflowDir, 'project-tech.json');
557
- const guidelinesFile = join(workflowDir, 'project-guidelines.json');
558
- const legacyFile = join(workflowDir, 'project.json');
559
-
560
- // Check for new dual file structure first, fallback to legacy
561
- const useLegacy = !existsSync(techFile) && existsSync(legacyFile);
562
- const projectFile = useLegacy ? legacyFile : techFile;
563
-
564
- if (!existsSync(projectFile)) {
565
- console.log(`Project file not found at: ${projectFile}`);
566
- return null;
567
- }
568
-
569
- try {
570
- const fileContent = readFileSync(projectFile, 'utf8');
571
- const projectData = JSON.parse(fileContent) as Record<string, unknown>;
572
-
573
- console.log(`Successfully loaded project overview: ${projectData.project_name || 'Unknown'} (${useLegacy ? 'legacy' : 'tech'})`);
574
-
575
- // Parse tech data (compatible with both legacy and new structure)
576
- const overview = projectData.overview as Record<string, unknown> | undefined;
577
- const technologyAnalysis = projectData.technology_analysis as Record<string, unknown> | undefined;
578
- const developmentStatus = projectData.development_status as Record<string, unknown> | undefined;
579
-
580
- // Support both old and new schema field names
581
- const technologyStack = (overview?.technology_stack || technologyAnalysis?.technology_stack) as Record<string, unknown[]> | undefined;
582
- const architecture = (overview?.architecture || technologyAnalysis?.architecture) as Record<string, unknown> | undefined;
583
- const developmentIndex = (projectData.development_index || developmentStatus?.development_index) as Record<string, unknown[]> | undefined;
584
- const statistics = (projectData.statistics || developmentStatus?.statistics) as Record<string, unknown> | undefined;
585
- const metadata = projectData._metadata as Record<string, unknown> | undefined;
586
-
587
- // Load guidelines from separate file if exists
588
- let guidelines: ProjectGuidelines | null = null;
589
- if (existsSync(guidelinesFile)) {
590
- try {
591
- const guidelinesContent = readFileSync(guidelinesFile, 'utf8');
592
- const guidelinesData = JSON.parse(guidelinesContent) as Record<string, unknown>;
593
-
594
- const conventions = guidelinesData.conventions as Record<string, string[]> | undefined;
595
- const constraints = guidelinesData.constraints as Record<string, string[]> | undefined;
596
-
597
- guidelines = {
598
- conventions: {
599
- coding_style: conventions?.coding_style || [],
600
- naming_patterns: conventions?.naming_patterns || [],
601
- file_structure: conventions?.file_structure || [],
602
- documentation: conventions?.documentation || []
603
- },
604
- constraints: {
605
- architecture: constraints?.architecture || [],
606
- tech_stack: constraints?.tech_stack || [],
607
- performance: constraints?.performance || [],
608
- security: constraints?.security || []
609
- },
610
- quality_rules: (guidelinesData.quality_rules as Array<{ rule: string; scope: string; enforced_by?: string }>) || [],
611
- learnings: (guidelinesData.learnings as Array<{
612
- date: string;
613
- session_id?: string;
614
- insight: string;
615
- context?: string;
616
- category?: string;
617
- }>) || [],
618
- _metadata: guidelinesData._metadata as ProjectGuidelines['_metadata'] | undefined
619
- };
620
- console.log(`Successfully loaded project guidelines`);
621
- } catch (guidelinesErr) {
622
- console.error(`Failed to parse project-guidelines.json:`, (guidelinesErr as Error).message);
623
- }
624
- }
625
-
626
- return {
627
- projectName: (projectData.project_name as string) || 'Unknown',
628
- description: (overview?.description as string) || '',
629
- initializedAt: (projectData.initialized_at as string) || null,
630
- technologyStack: {
631
- languages: (technologyStack?.languages as string[]) || [],
632
- frameworks: (technologyStack?.frameworks as string[]) || [],
633
- build_tools: (technologyStack?.build_tools as string[]) || [],
634
- test_frameworks: (technologyStack?.test_frameworks as string[]) || []
635
- },
636
- architecture: {
637
- style: (architecture?.style as string) || 'Unknown',
638
- layers: (architecture?.layers as string[]) || [],
639
- patterns: (architecture?.patterns as string[]) || []
640
- },
641
- keyComponents: (overview?.key_components as string[]) || [],
642
- features: (projectData.features as unknown[]) || [],
643
- developmentIndex: {
644
- feature: (developmentIndex?.feature as unknown[]) || [],
645
- enhancement: (developmentIndex?.enhancement as unknown[]) || [],
646
- bugfix: (developmentIndex?.bugfix as unknown[]) || [],
647
- refactor: (developmentIndex?.refactor as unknown[]) || [],
648
- docs: (developmentIndex?.docs as unknown[]) || []
649
- },
650
- statistics: {
651
- total_features: (statistics?.total_features as number) || 0,
652
- total_sessions: (statistics?.total_sessions as number) || 0,
653
- last_updated: (statistics?.last_updated as string) || null
654
- },
655
- metadata: {
656
- initialized_by: (metadata?.initialized_by as string) || 'unknown',
657
- analysis_timestamp: (metadata?.analysis_timestamp as string) || null,
658
- analysis_mode: (metadata?.analysis_mode as string) || 'unknown'
659
- },
660
- guidelines
661
- };
662
- } catch (err) {
663
- console.error(`Failed to parse project file at ${projectFile}:`, (err as Error).message);
664
- console.error('Error stack:', (err as Error).stack);
665
- return null;
666
- }
667
- }
1
+ import { glob } from 'glob';
2
+ import { readFileSync, existsSync } from 'fs';
3
+ import { join, basename } from 'path';
4
+ import { scanLiteTasks } from './lite-scanner.js';
5
+ import { createDashboardCache } from './cache-manager.js';
6
+
7
+ interface SessionData {
8
+ session_id: string;
9
+ project: string;
10
+ status: string;
11
+ type: string;
12
+ workflow_type: string | null;
13
+ created_at: string | null;
14
+ archived_at: string | null;
15
+ path: string;
16
+ tasks: TaskData[];
17
+ taskCount: number;
18
+ hasReview: boolean;
19
+ reviewSummary: ReviewSummary | null;
20
+ reviewDimensions: DimensionData[];
21
+ }
22
+
23
+ interface TaskData {
24
+ task_id: string;
25
+ title: string;
26
+ status: string;
27
+ type: string;
28
+ meta?: Record<string, unknown>;
29
+ context?: Record<string, unknown>;
30
+ flow_control?: Record<string, unknown>;
31
+ }
32
+
33
+ interface ReviewSummary {
34
+ phase: string;
35
+ severityDistribution: Record<string, number>;
36
+ criticalFiles: string[];
37
+ status: string;
38
+ }
39
+
40
+ interface DimensionData {
41
+ name: string;
42
+ findings: Finding[];
43
+ summary: unknown | null;
44
+ status: string;
45
+ }
46
+
47
+ interface Finding {
48
+ severity?: string;
49
+ [key: string]: unknown;
50
+ }
51
+
52
+ interface SessionInput {
53
+ session_id?: string;
54
+ id?: string;
55
+ project?: string;
56
+ description?: string;
57
+ status?: string;
58
+ type?: string;
59
+ workflow_type?: string | null;
60
+ created_at?: string | null; // For backward compatibility
61
+ created?: string; // From SessionMetadata
62
+ updated?: string; // From SessionMetadata
63
+ archived_at?: string | null;
64
+ path: string;
65
+ }
66
+
67
+ interface ScanSessionsResult {
68
+ active: SessionInput[];
69
+ archived: SessionInput[];
70
+ hasReviewData: boolean;
71
+ }
72
+
73
+ interface DashboardData {
74
+ generatedAt: string;
75
+ activeSessions: SessionData[];
76
+ archivedSessions: SessionData[];
77
+ liteTasks: {
78
+ litePlan: unknown[];
79
+ liteFix: unknown[];
80
+ };
81
+ reviewData: ReviewData | null;
82
+ projectOverview: ProjectOverview | null;
83
+ statistics: {
84
+ totalSessions: number;
85
+ activeSessions: number;
86
+ totalTasks: number;
87
+ completedTasks: number;
88
+ reviewFindings: number;
89
+ litePlanCount: number;
90
+ liteFixCount: number;
91
+ };
92
+ }
93
+
94
+ interface ReviewData {
95
+ totalFindings: number;
96
+ severityDistribution: {
97
+ critical: number;
98
+ high: number;
99
+ medium: number;
100
+ low: number;
101
+ };
102
+ dimensionSummary: Record<string, { count: number; sessions: string[] }>;
103
+ sessions: SessionReviewData[];
104
+ }
105
+
106
+ interface SessionReviewData {
107
+ session_id: string;
108
+ progress: unknown | null;
109
+ dimensions: DimensionData[];
110
+ findings: Array<Finding & { dimension: string }>;
111
+ }
112
+
113
+ interface ProjectGuidelines {
114
+ conventions: {
115
+ coding_style: string[];
116
+ naming_patterns: string[];
117
+ file_structure: string[];
118
+ documentation: string[];
119
+ };
120
+ constraints: {
121
+ architecture: string[];
122
+ tech_stack: string[];
123
+ performance: string[];
124
+ security: string[];
125
+ };
126
+ quality_rules: Array<{ rule: string; scope: string; enforced_by?: string }>;
127
+ learnings: Array<{
128
+ date: string;
129
+ session_id?: string;
130
+ insight: string;
131
+ context?: string;
132
+ category?: string;
133
+ }>;
134
+ _metadata?: {
135
+ created_at: string;
136
+ updated_at?: string;
137
+ version: string;
138
+ };
139
+ }
140
+
141
+ interface ProjectOverview {
142
+ projectName: string;
143
+ description: string;
144
+ initializedAt: string | null;
145
+ technologyStack: {
146
+ languages: string[];
147
+ frameworks: string[];
148
+ build_tools: string[];
149
+ test_frameworks: string[];
150
+ };
151
+ architecture: {
152
+ style: string;
153
+ layers: string[];
154
+ patterns: string[];
155
+ };
156
+ keyComponents: string[];
157
+ features: unknown[];
158
+ developmentIndex: {
159
+ feature: unknown[];
160
+ enhancement: unknown[];
161
+ bugfix: unknown[];
162
+ refactor: unknown[];
163
+ docs: unknown[];
164
+ };
165
+ statistics: {
166
+ total_features: number;
167
+ total_sessions: number;
168
+ last_updated: string | null;
169
+ };
170
+ metadata: {
171
+ initialized_by: string;
172
+ analysis_timestamp: string | null;
173
+ analysis_mode: string;
174
+ };
175
+ guidelines: ProjectGuidelines | null;
176
+ }
177
+
178
+ /**
179
+ * Aggregate all data for dashboard rendering (with caching)
180
+ * @param sessions - Scanned sessions from session-scanner
181
+ * @param workflowDir - Path to .workflow directory
182
+ * @returns Aggregated dashboard data
183
+ */
184
+ export async function aggregateData(sessions: ScanSessionsResult, workflowDir: string): Promise<DashboardData> {
185
+ // Initialize cache manager
186
+ const cache = createDashboardCache(workflowDir);
187
+
188
+ // Prepare paths to watch for changes (includes both new dual files and legacy)
189
+ const watchPaths = [
190
+ join(workflowDir, 'active'),
191
+ join(workflowDir, 'archives'),
192
+ join(workflowDir, 'project-tech.json'),
193
+ join(workflowDir, 'project-guidelines.json'),
194
+ join(workflowDir, 'project.json'), // Legacy support
195
+ ...sessions.active.map(s => s.path),
196
+ ...sessions.archived.map(s => s.path)
197
+ ];
198
+
199
+ // Check cache first
200
+ const cachedData = await cache.get(watchPaths);
201
+ if (cachedData !== null) {
202
+ console.log('Using cached dashboard data');
203
+ return cachedData;
204
+ }
205
+
206
+ console.log('Cache miss - regenerating dashboard data');
207
+
208
+ const data: DashboardData = {
209
+ generatedAt: new Date().toISOString(),
210
+ activeSessions: [],
211
+ archivedSessions: [],
212
+ liteTasks: {
213
+ litePlan: [],
214
+ liteFix: []
215
+ },
216
+ reviewData: null,
217
+ projectOverview: null,
218
+ statistics: {
219
+ totalSessions: 0,
220
+ activeSessions: 0,
221
+ totalTasks: 0,
222
+ completedTasks: 0,
223
+ reviewFindings: 0,
224
+ litePlanCount: 0,
225
+ liteFixCount: 0
226
+ }
227
+ };
228
+
229
+ // Process active sessions
230
+ for (const session of sessions.active) {
231
+ const sessionData = await processSession(session, true);
232
+ data.activeSessions.push(sessionData);
233
+ data.statistics.totalTasks += sessionData.tasks.length;
234
+ data.statistics.completedTasks += sessionData.tasks.filter(t => t.status === 'completed').length;
235
+ }
236
+
237
+ // Process archived sessions
238
+ for (const session of sessions.archived) {
239
+ const sessionData = await processSession(session, false);
240
+ data.archivedSessions.push(sessionData);
241
+ data.statistics.totalTasks += sessionData.taskCount || 0;
242
+ data.statistics.completedTasks += sessionData.taskCount || 0;
243
+ }
244
+
245
+ // Aggregate review data if present
246
+ if (sessions.hasReviewData) {
247
+ data.reviewData = await aggregateReviewData(sessions.active);
248
+ data.statistics.reviewFindings = data.reviewData.totalFindings;
249
+ }
250
+
251
+ data.statistics.totalSessions = sessions.active.length + sessions.archived.length;
252
+ data.statistics.activeSessions = sessions.active.length;
253
+
254
+ // Scan and include lite tasks
255
+ try {
256
+ const liteTasks = await scanLiteTasks(workflowDir);
257
+ data.liteTasks = liteTasks;
258
+ data.statistics.litePlanCount = liteTasks.litePlan.length;
259
+ data.statistics.liteFixCount = liteTasks.liteFix.length;
260
+ } catch (err) {
261
+ console.error('Error scanning lite tasks:', (err as Error).message);
262
+ }
263
+
264
+ // Load project overview from project.json
265
+ try {
266
+ data.projectOverview = loadProjectOverview(workflowDir);
267
+ } catch (err) {
268
+ console.error('Error loading project overview:', (err as Error).message);
269
+ }
270
+
271
+ // Store in cache before returning
272
+ await cache.set(data, watchPaths);
273
+
274
+ return data;
275
+ }
276
+
277
+ /**
278
+ * Process a single session, loading tasks and review info
279
+ * @param session - Session object from scanner
280
+ * @param isActive - Whether session is active
281
+ * @returns Processed session data
282
+ */
283
+ async function processSession(session: SessionInput, isActive: boolean): Promise<SessionData> {
284
+ const result: SessionData = {
285
+ session_id: session.session_id || session.id || '',
286
+ project: session.project || session.description || session.session_id || session.id || '',
287
+ status: session.status || (isActive ? 'active' : 'archived'),
288
+ type: session.type || 'workflow', // Session type (workflow, review, test, docs)
289
+ workflow_type: session.workflow_type || null, // Original workflow_type for reference
290
+ created_at: session.created || session.created_at || null, // Prefer 'created' from SessionMetadata, fallback to 'created_at'
291
+ archived_at: session.archived_at || null, // Raw ISO string - let frontend format
292
+ path: session.path,
293
+ tasks: [],
294
+ taskCount: 0,
295
+ hasReview: false,
296
+ reviewSummary: null,
297
+ reviewDimensions: []
298
+ };
299
+
300
+ // Load tasks for active sessions (full details)
301
+ if (isActive) {
302
+ const taskDir = join(session.path, '.task');
303
+ if (existsSync(taskDir)) {
304
+ const taskFiles = await safeGlob('IMPL-*.json', taskDir);
305
+ for (const taskFile of taskFiles) {
306
+ try {
307
+ const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8')) as Record<string, unknown>;
308
+ result.tasks.push({
309
+ task_id: (taskData.id as string) || basename(taskFile, '.json'),
310
+ title: (taskData.title as string) || 'Untitled Task',
311
+ status: (taskData.status as string) || 'pending',
312
+ type: ((taskData.meta as Record<string, unknown>)?.type as string) || 'task',
313
+ meta: (taskData.meta as Record<string, unknown>) || {},
314
+ context: (taskData.context as Record<string, unknown>) || {},
315
+ flow_control: (taskData.flow_control as Record<string, unknown>) || {}
316
+ });
317
+ } catch {
318
+ // Skip invalid task files
319
+ }
320
+ }
321
+ // Sort tasks by ID
322
+ result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id));
323
+ }
324
+ result.taskCount = result.tasks.length;
325
+
326
+ // Check for review data
327
+ const reviewDir = join(session.path, '.review');
328
+ if (existsSync(reviewDir)) {
329
+ result.hasReview = true;
330
+ result.reviewSummary = loadReviewSummary(reviewDir);
331
+ // Load dimension data for review sessions
332
+ if (session.type === 'review') {
333
+ result.reviewDimensions = await loadDimensionData(reviewDir);
334
+ }
335
+ }
336
+ } else {
337
+ // For archived, also load tasks (same as active)
338
+ const taskDir = join(session.path, '.task');
339
+ if (existsSync(taskDir)) {
340
+ const taskFiles = await safeGlob('IMPL-*.json', taskDir);
341
+ for (const taskFile of taskFiles) {
342
+ try {
343
+ const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8')) as Record<string, unknown>;
344
+ result.tasks.push({
345
+ task_id: (taskData.id as string) || basename(taskFile, '.json'),
346
+ title: (taskData.title as string) || 'Untitled Task',
347
+ status: (taskData.status as string) || 'completed', // Archived tasks are usually completed
348
+ type: ((taskData.meta as Record<string, unknown>)?.type as string) || 'task'
349
+ });
350
+ } catch {
351
+ // Skip invalid task files
352
+ }
353
+ }
354
+ // Sort tasks by ID
355
+ result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id));
356
+ result.taskCount = result.tasks.length;
357
+ }
358
+
359
+ // Check for review data in archived sessions too
360
+ const reviewDir = join(session.path, '.review');
361
+ if (existsSync(reviewDir)) {
362
+ result.hasReview = true;
363
+ result.reviewSummary = loadReviewSummary(reviewDir);
364
+ // Load dimension data for review sessions
365
+ if (session.type === 'review') {
366
+ result.reviewDimensions = await loadDimensionData(reviewDir);
367
+ }
368
+ }
369
+ }
370
+
371
+ return result;
372
+ }
373
+
374
+ /**
375
+ * Aggregate review data from all active sessions with reviews
376
+ * @param activeSessions - Active session objects
377
+ * @returns Aggregated review data
378
+ */
379
+ async function aggregateReviewData(activeSessions: SessionInput[]): Promise<ReviewData> {
380
+ const reviewData: ReviewData = {
381
+ totalFindings: 0,
382
+ severityDistribution: { critical: 0, high: 0, medium: 0, low: 0 },
383
+ dimensionSummary: {},
384
+ sessions: []
385
+ };
386
+
387
+ for (const session of activeSessions) {
388
+ const reviewDir = join(session.path, '.review');
389
+ if (!existsSync(reviewDir)) continue;
390
+
391
+ const reviewProgress = loadReviewProgress(reviewDir);
392
+ const dimensionData = await loadDimensionData(reviewDir);
393
+
394
+ if (reviewProgress || dimensionData.length > 0) {
395
+ const sessionReview: SessionReviewData = {
396
+ session_id: session.session_id || session.id || '',
397
+ progress: reviewProgress,
398
+ dimensions: dimensionData,
399
+ findings: []
400
+ };
401
+
402
+ // Collect and count findings
403
+ for (const dim of dimensionData) {
404
+ if (dim.findings && Array.isArray(dim.findings)) {
405
+ for (const finding of dim.findings) {
406
+ const severity = (finding.severity || 'low').toLowerCase();
407
+ if (reviewData.severityDistribution.hasOwnProperty(severity)) {
408
+ reviewData.severityDistribution[severity as keyof typeof reviewData.severityDistribution]++;
409
+ }
410
+ reviewData.totalFindings++;
411
+ sessionReview.findings.push({
412
+ ...finding,
413
+ dimension: dim.name
414
+ });
415
+ }
416
+ }
417
+
418
+ // Track dimension summary
419
+ if (!reviewData.dimensionSummary[dim.name]) {
420
+ reviewData.dimensionSummary[dim.name] = { count: 0, sessions: [] };
421
+ }
422
+ reviewData.dimensionSummary[dim.name].count += dim.findings?.length || 0;
423
+ reviewData.dimensionSummary[dim.name].sessions.push(session.session_id || session.id || '');
424
+ }
425
+
426
+ reviewData.sessions.push(sessionReview);
427
+ }
428
+ }
429
+
430
+ return reviewData;
431
+ }
432
+
433
+ /**
434
+ * Load review progress from review-progress.json
435
+ * @param reviewDir - Path to .review directory
436
+ * @returns Review progress data or null
437
+ */
438
+ function loadReviewProgress(reviewDir: string): unknown | null {
439
+ const progressFile = join(reviewDir, 'review-progress.json');
440
+ if (!existsSync(progressFile)) return null;
441
+ try {
442
+ return JSON.parse(readFileSync(progressFile, 'utf8'));
443
+ } catch {
444
+ return null;
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Load review summary from review-state.json
450
+ * @param reviewDir - Path to .review directory
451
+ * @returns Review summary or null
452
+ */
453
+ function loadReviewSummary(reviewDir: string): ReviewSummary | null {
454
+ const stateFile = join(reviewDir, 'review-state.json');
455
+ if (!existsSync(stateFile)) return null;
456
+ try {
457
+ const state = JSON.parse(readFileSync(stateFile, 'utf8')) as Record<string, unknown>;
458
+ return {
459
+ phase: (state.phase as string) || 'unknown',
460
+ severityDistribution: (state.severity_distribution as Record<string, number>) || {},
461
+ criticalFiles: ((state.critical_files as string[]) || []).slice(0, 3),
462
+ status: (state.status as string) || 'in_progress'
463
+ };
464
+ } catch {
465
+ return null;
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Load dimension data from .review/dimensions/
471
+ * @param reviewDir - Path to .review directory
472
+ * @returns Array of dimension data
473
+ */
474
+ async function loadDimensionData(reviewDir: string): Promise<DimensionData[]> {
475
+ const dimensionsDir = join(reviewDir, 'dimensions');
476
+ if (!existsSync(dimensionsDir)) return [];
477
+
478
+ const dimensions: DimensionData[] = [];
479
+ const dimFiles = await safeGlob('*.json', dimensionsDir);
480
+
481
+ for (const file of dimFiles) {
482
+ try {
483
+ const data = JSON.parse(readFileSync(join(dimensionsDir, file), 'utf8'));
484
+ // Handle array structure: [ { findings: [...], summary: {...} } ]
485
+ let findings: Finding[] = [];
486
+ let summary: unknown | null = null;
487
+ let status = 'completed';
488
+
489
+ if (Array.isArray(data) && data.length > 0) {
490
+ const dimData = data[0] as Record<string, unknown>;
491
+ findings = (dimData.findings as Finding[]) || [];
492
+ summary = dimData.summary || null;
493
+ status = (dimData.status as string) || 'completed';
494
+ } else if ((data as Record<string, unknown>).findings) {
495
+ const dataObj = data as Record<string, unknown>;
496
+ findings = (dataObj.findings as Finding[]) || [];
497
+ summary = dataObj.summary || null;
498
+ status = (dataObj.status as string) || 'completed';
499
+ }
500
+
501
+ dimensions.push({
502
+ name: basename(file, '.json'),
503
+ findings: findings,
504
+ summary: summary,
505
+ status: status
506
+ });
507
+ } catch {
508
+ // Skip invalid dimension files
509
+ }
510
+ }
511
+
512
+ return dimensions;
513
+ }
514
+
515
+ /**
516
+ * Safe glob wrapper that returns empty array on error
517
+ * @param pattern - Glob pattern
518
+ * @param cwd - Current working directory
519
+ * @returns Array of matching file names
520
+ */
521
+ async function safeGlob(pattern: string, cwd: string): Promise<string[]> {
522
+ try {
523
+ return await glob(pattern, { cwd, absolute: false });
524
+ } catch {
525
+ return [];
526
+ }
527
+ }
528
+
529
+ // formatDate removed - dates are now passed as raw ISO strings
530
+ // Frontend (dashboard.js) handles all date formatting
531
+
532
+ /**
533
+ * Sort task IDs numerically (IMPL-1, IMPL-2, IMPL-1.1, etc.)
534
+ * @param a - First task ID
535
+ * @param b - Second task ID
536
+ * @returns Comparison result
537
+ */
538
+ function sortTaskIds(a: string, b: string): number {
539
+ const parseId = (id: string): [number, number] => {
540
+ const match = id.match(/IMPL-(\d+)(?:\.(\d+))?/);
541
+ if (!match) return [0, 0];
542
+ return [parseInt(match[1]), parseInt(match[2] || '0')];
543
+ };
544
+ const [a1, a2] = parseId(a);
545
+ const [b1, b2] = parseId(b);
546
+ return a1 - b1 || a2 - b2;
547
+ }
548
+
549
+ /**
550
+ * Load project overview from project-tech.json and project-guidelines.json
551
+ * Supports dual file structure with backward compatibility for legacy project.json
552
+ * @param workflowDir - Path to .workflow directory
553
+ * @returns Project overview data or null if not found
554
+ */
555
+ function loadProjectOverview(workflowDir: string): ProjectOverview | null {
556
+ const techFile = join(workflowDir, 'project-tech.json');
557
+ const guidelinesFile = join(workflowDir, 'project-guidelines.json');
558
+ const legacyFile = join(workflowDir, 'project.json');
559
+
560
+ // Check for new dual file structure first, fallback to legacy
561
+ const useLegacy = !existsSync(techFile) && existsSync(legacyFile);
562
+ const projectFile = useLegacy ? legacyFile : techFile;
563
+
564
+ if (!existsSync(projectFile)) {
565
+ console.log(`Project file not found at: ${projectFile}`);
566
+ return null;
567
+ }
568
+
569
+ try {
570
+ const fileContent = readFileSync(projectFile, 'utf8');
571
+ const projectData = JSON.parse(fileContent) as Record<string, unknown>;
572
+
573
+ console.log(`Successfully loaded project overview: ${projectData.project_name || 'Unknown'} (${useLegacy ? 'legacy' : 'tech'})`);
574
+
575
+ // Parse tech data (compatible with both legacy and new structure)
576
+ const overview = projectData.overview as Record<string, unknown> | undefined;
577
+ const technologyAnalysis = projectData.technology_analysis as Record<string, unknown> | undefined;
578
+ const developmentStatus = projectData.development_status as Record<string, unknown> | undefined;
579
+
580
+ // Support both old and new schema field names
581
+ const technologyStack = (overview?.technology_stack || technologyAnalysis?.technology_stack) as Record<string, unknown[]> | undefined;
582
+ const architecture = (overview?.architecture || technologyAnalysis?.architecture) as Record<string, unknown> | undefined;
583
+ const developmentIndex = (projectData.development_index || developmentStatus?.development_index) as Record<string, unknown[]> | undefined;
584
+ const statistics = (projectData.statistics || developmentStatus?.statistics) as Record<string, unknown> | undefined;
585
+ const metadata = projectData._metadata as Record<string, unknown> | undefined;
586
+
587
+ // Load guidelines from separate file if exists
588
+ let guidelines: ProjectGuidelines | null = null;
589
+ if (existsSync(guidelinesFile)) {
590
+ try {
591
+ const guidelinesContent = readFileSync(guidelinesFile, 'utf8');
592
+ const guidelinesData = JSON.parse(guidelinesContent) as Record<string, unknown>;
593
+
594
+ const conventions = guidelinesData.conventions as Record<string, string[]> | undefined;
595
+ const constraints = guidelinesData.constraints as Record<string, string[]> | undefined;
596
+
597
+ guidelines = {
598
+ conventions: {
599
+ coding_style: conventions?.coding_style || [],
600
+ naming_patterns: conventions?.naming_patterns || [],
601
+ file_structure: conventions?.file_structure || [],
602
+ documentation: conventions?.documentation || []
603
+ },
604
+ constraints: {
605
+ architecture: constraints?.architecture || [],
606
+ tech_stack: constraints?.tech_stack || [],
607
+ performance: constraints?.performance || [],
608
+ security: constraints?.security || []
609
+ },
610
+ quality_rules: (guidelinesData.quality_rules as Array<{ rule: string; scope: string; enforced_by?: string }>) || [],
611
+ learnings: (guidelinesData.learnings as Array<{
612
+ date: string;
613
+ session_id?: string;
614
+ insight: string;
615
+ context?: string;
616
+ category?: string;
617
+ }>) || [],
618
+ _metadata: guidelinesData._metadata as ProjectGuidelines['_metadata'] | undefined
619
+ };
620
+ console.log(`Successfully loaded project guidelines`);
621
+ } catch (guidelinesErr) {
622
+ console.error(`Failed to parse project-guidelines.json:`, (guidelinesErr as Error).message);
623
+ }
624
+ }
625
+
626
+ return {
627
+ projectName: (projectData.project_name as string) || 'Unknown',
628
+ description: (overview?.description as string) || '',
629
+ initializedAt: (projectData.initialized_at as string) || null,
630
+ technologyStack: {
631
+ languages: (technologyStack?.languages as string[]) || [],
632
+ frameworks: (technologyStack?.frameworks as string[]) || [],
633
+ build_tools: (technologyStack?.build_tools as string[]) || [],
634
+ test_frameworks: (technologyStack?.test_frameworks as string[]) || []
635
+ },
636
+ architecture: {
637
+ style: (architecture?.style as string) || 'Unknown',
638
+ layers: (architecture?.layers as string[]) || [],
639
+ patterns: (architecture?.patterns as string[]) || []
640
+ },
641
+ keyComponents: (overview?.key_components as string[]) || [],
642
+ features: (projectData.features as unknown[]) || [],
643
+ developmentIndex: {
644
+ feature: (developmentIndex?.feature as unknown[]) || [],
645
+ enhancement: (developmentIndex?.enhancement as unknown[]) || [],
646
+ bugfix: (developmentIndex?.bugfix as unknown[]) || [],
647
+ refactor: (developmentIndex?.refactor as unknown[]) || [],
648
+ docs: (developmentIndex?.docs as unknown[]) || []
649
+ },
650
+ statistics: {
651
+ total_features: (statistics?.total_features as number) || 0,
652
+ total_sessions: (statistics?.total_sessions as number) || 0,
653
+ last_updated: (statistics?.last_updated as string) || null
654
+ },
655
+ metadata: {
656
+ initialized_by: (metadata?.initialized_by as string) || 'unknown',
657
+ analysis_timestamp: (metadata?.analysis_timestamp as string) || null,
658
+ analysis_mode: (metadata?.analysis_mode as string) || 'unknown'
659
+ },
660
+ guidelines
661
+ };
662
+ } catch (err) {
663
+ console.error(`Failed to parse project file at ${projectFile}:`, (err as Error).message);
664
+ console.error('Error stack:', (err as Error).stack);
665
+ return null;
666
+ }
667
+ }