claude-code-workflow 6.1.4 → 6.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/.claude/CLAUDE.md +10 -0
  2. package/.claude/agents/action-planning-agent.md +857 -778
  3. package/.claude/agents/cli-execution-agent.md +266 -269
  4. package/.claude/agents/cli-explore-agent.md +2 -2
  5. package/.claude/agents/cli-lite-planning-agent.md +142 -92
  6. package/.claude/agents/cli-planning-agent.md +4 -4
  7. package/.claude/agents/code-developer.md +7 -6
  8. package/.claude/agents/conceptual-planning-agent.md +2 -2
  9. package/.claude/agents/context-search-agent.md +31 -32
  10. package/.claude/agents/doc-generator.md +4 -4
  11. package/.claude/agents/memory-bridge.md +93 -93
  12. package/.claude/agents/test-context-search-agent.md +8 -7
  13. package/.claude/agents/test-fix-agent.md +7 -6
  14. package/.claude/commands/clean.md +516 -0
  15. package/.claude/commands/memory/compact.md +383 -0
  16. package/.claude/commands/memory/docs-full-cli.md +471 -471
  17. package/.claude/commands/memory/docs-related-cli.md +386 -386
  18. package/.claude/commands/memory/docs.md +615 -615
  19. package/.claude/commands/memory/load.md +5 -5
  20. package/.claude/commands/memory/tech-research-rules.md +310 -0
  21. package/.claude/commands/memory/update-full.md +332 -332
  22. package/.claude/commands/memory/workflow-skill-memory.md +4 -4
  23. package/.claude/commands/task/create.md +151 -151
  24. package/.claude/commands/version.md +254 -254
  25. package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
  26. package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
  27. package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
  28. package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
  29. package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
  30. package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
  31. package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
  32. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  33. package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
  34. package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
  35. package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
  36. package/.claude/commands/workflow/debug.md +321 -0
  37. package/.claude/commands/workflow/execute.md +13 -0
  38. package/.claude/commands/workflow/init.md +165 -164
  39. package/.claude/commands/workflow/lite-execute.md +119 -13
  40. package/.claude/commands/workflow/lite-fix.md +623 -621
  41. package/.claude/commands/workflow/lite-plan.md +610 -592
  42. package/.claude/commands/workflow/plan.md +5 -5
  43. package/.claude/commands/workflow/review-module-cycle.md +2 -0
  44. package/.claude/commands/workflow/review-session-cycle.md +2 -0
  45. package/.claude/commands/workflow/review.md +297 -291
  46. package/.claude/commands/workflow/session/complete.md +153 -500
  47. package/.claude/commands/workflow/session/list.md +95 -95
  48. package/.claude/commands/workflow/session/resume.md +60 -60
  49. package/.claude/commands/workflow/session/start.md +199 -199
  50. package/.claude/commands/workflow/tdd-plan.md +3 -3
  51. package/.claude/commands/workflow/tdd-verify.md +23 -9
  52. package/.claude/commands/workflow/test-cycle-execute.md +2 -0
  53. package/.claude/commands/workflow/test-fix-gen.md +699 -699
  54. package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
  55. package/.claude/commands/workflow/tools/context-gather.md +436 -434
  56. package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
  57. package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
  58. package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
  59. package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
  60. package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
  61. package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
  62. package/.claude/skills/command-guide/SKILL.md +5 -5
  63. package/.claude/skills/command-guide/index/all-commands.json +1 -1
  64. package/.claude/skills/command-guide/index/by-category.json +1 -1
  65. package/.claude/skills/command-guide/index/by-use-case.json +1 -1
  66. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
  67. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
  68. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
  69. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
  70. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
  71. package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
  72. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
  73. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
  74. package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
  75. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
  76. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
  77. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
  78. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
  79. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
  80. package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
  81. package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
  82. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
  83. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
  84. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
  85. package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
  86. package/.claude/skills/command-guide/reference/commands/version.md +254 -254
  87. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
  88. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
  89. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
  90. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
  91. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
  92. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
  93. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  94. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
  95. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
  96. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
  97. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
  98. package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
  99. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
  100. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
  101. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
  102. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
  103. package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
  104. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
  105. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
  106. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
  107. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
  108. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
  109. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
  110. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
  111. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
  112. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
  113. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
  114. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
  115. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
  116. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
  117. package/.claude/workflows/chinese-response.md +38 -0
  118. package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
  119. package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
  120. package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
  121. package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
  122. package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
  123. package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
  124. package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
  125. package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
  126. package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
  127. package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
  128. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
  129. package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
  130. package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
  131. package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
  132. package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
  133. package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
  134. package/.claude/workflows/cli-tools-usage.md +526 -0
  135. package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
  136. package/.claude/workflows/context-tools.md +84 -0
  137. package/.claude/workflows/file-modification.md +64 -0
  138. package/.claude/workflows/tool-strategy.md +216 -79
  139. package/.claude/workflows/windows-platform.md +16 -0
  140. package/.claude/workflows/workflow-architecture.md +942 -942
  141. package/.codex/AGENTS.md +63 -330
  142. package/.codex/prompts/debug.md +318 -0
  143. package/.codex/prompts/execute.md +273 -0
  144. package/.codex/prompts/lite-execute.md +164 -0
  145. package/.codex/prompts/lite-plan.md +469 -0
  146. package/.codex/prompts.zip +0 -0
  147. package/.gemini/GEMINI.md +25 -164
  148. package/.qwen/QWEN.md +0 -139
  149. package/README.md +29 -9
  150. package/ccw/README.md +30 -6
  151. package/ccw/bin/ccw-mcp.js +7 -0
  152. package/ccw/bin/ccw.js +9 -9
  153. package/ccw/package.json +65 -47
  154. package/ccw/src/.workflow/.cli-history/history.db +0 -0
  155. package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
  156. package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
  157. package/ccw/src/cli.ts +244 -0
  158. package/ccw/src/commands/cli.ts +740 -0
  159. package/ccw/src/commands/core-memory.ts +770 -0
  160. package/ccw/src/commands/hook.ts +315 -0
  161. package/ccw/src/commands/install.ts +519 -0
  162. package/ccw/src/commands/{list.js → list.ts} +1 -1
  163. package/ccw/src/commands/memory.ts +1090 -0
  164. package/ccw/src/commands/{serve.js → serve.ts} +14 -5
  165. package/ccw/src/commands/session-path-resolver.ts +372 -0
  166. package/ccw/src/commands/session.ts +1141 -0
  167. package/ccw/src/commands/{stop.js → stop.ts} +16 -6
  168. package/ccw/src/commands/tool.ts +201 -0
  169. package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
  170. package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
  171. package/ccw/src/commands/{view.js → view.ts} +22 -8
  172. package/ccw/src/config/storage-paths.ts +670 -0
  173. package/ccw/src/core/cache-manager.ts +294 -0
  174. package/ccw/src/core/claude-freshness.ts +319 -0
  175. package/ccw/src/core/core-memory-store.ts +1528 -0
  176. package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
  177. package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
  178. package/ccw/src/core/data-aggregator.ts +584 -0
  179. package/ccw/src/core/history-importer.ts +625 -0
  180. package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
  181. package/ccw/src/core/lite-scanner.ts +469 -0
  182. package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
  183. package/ccw/src/core/memory-embedder-bridge.ts +262 -0
  184. package/ccw/src/core/memory-store.ts +978 -0
  185. package/ccw/src/core/routes/ccw-routes.ts +96 -0
  186. package/ccw/src/core/routes/claude-routes.ts +1183 -0
  187. package/ccw/src/core/routes/cli-routes.ts +561 -0
  188. package/ccw/src/core/routes/codexlens-routes.ts +806 -0
  189. package/ccw/src/core/routes/core-memory-routes.ts +605 -0
  190. package/ccw/src/core/routes/files-routes.ts +428 -0
  191. package/ccw/src/core/routes/graph-routes.md +164 -0
  192. package/ccw/src/core/routes/graph-routes.ts +626 -0
  193. package/ccw/src/core/routes/help-routes.ts +308 -0
  194. package/ccw/src/core/routes/hooks-routes.ts +405 -0
  195. package/ccw/src/core/routes/mcp-routes.ts +1271 -0
  196. package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
  197. package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
  198. package/ccw/src/core/routes/memory-routes.ts +1206 -0
  199. package/ccw/src/core/routes/rules-routes.ts +526 -0
  200. package/ccw/src/core/routes/session-routes.ts +467 -0
  201. package/ccw/src/core/routes/skills-routes.ts +599 -0
  202. package/ccw/src/core/routes/status-routes.ts +57 -0
  203. package/ccw/src/core/routes/system-routes.ts +427 -0
  204. package/ccw/src/core/server.ts +431 -0
  205. package/ccw/src/core/session-clustering-service.ts +1258 -0
  206. package/ccw/src/core/session-scanner.ts +283 -0
  207. package/ccw/src/core/websocket.ts +190 -0
  208. package/ccw/src/{index.js → index.ts} +1 -0
  209. package/ccw/src/mcp-server/index.ts +186 -0
  210. package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
  211. package/ccw/src/templates/assets/css/github.min.css +10 -0
  212. package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
  213. package/ccw/src/templates/assets/js/d3.min.js +2 -0
  214. package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
  215. package/ccw/src/templates/assets/js/lucide.min.js +12 -0
  216. package/ccw/src/templates/assets/js/marked.min.js +69 -0
  217. package/ccw/src/templates/assets/js/tailwind.js +83 -0
  218. package/ccw/src/templates/dashboard-css/01-base.css +11 -0
  219. package/ccw/src/templates/dashboard-css/02-session.css +22 -0
  220. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
  221. package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
  222. package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
  223. package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
  224. package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
  225. package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
  226. package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
  227. package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
  228. package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
  229. package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
  230. package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
  231. package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
  232. package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
  233. package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
  234. package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
  235. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
  236. package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
  237. package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
  238. package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
  239. package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
  240. package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
  241. package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
  242. package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
  243. package/ccw/src/templates/dashboard-css/29-help.css +264 -0
  244. package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
  245. package/ccw/src/templates/dashboard-js/api.js +162 -142
  246. package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
  247. package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
  248. package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
  249. package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
  250. package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
  251. package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
  252. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
  253. package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
  254. package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
  255. package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
  256. package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
  257. package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
  258. package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
  259. package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
  260. package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
  261. package/ccw/src/templates/dashboard-js/main.js +15 -0
  262. package/ccw/src/templates/dashboard-js/state.js +243 -42
  263. package/ccw/src/templates/dashboard-js/utils.js +47 -1
  264. package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
  265. package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
  266. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
  267. package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
  268. package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
  269. package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
  270. package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
  271. package/ccw/src/templates/dashboard-js/views/help.js +856 -0
  272. package/ccw/src/templates/dashboard-js/views/history.js +337 -0
  273. package/ccw/src/templates/dashboard-js/views/home.js +61 -15
  274. package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
  275. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
  276. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
  277. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
  278. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
  279. package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
  280. package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
  281. package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
  282. package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
  283. package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
  284. package/ccw/src/templates/dashboard.html +185 -85
  285. package/ccw/src/templates/hooks-config-example.json +60 -0
  286. package/ccw/src/tools/classify-folders.ts +245 -0
  287. package/ccw/src/tools/cli-config-manager.ts +268 -0
  288. package/ccw/src/tools/cli-executor.ts +2014 -0
  289. package/ccw/src/tools/cli-history-store.ts +1195 -0
  290. package/ccw/src/tools/codex-lens.ts +1141 -0
  291. package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
  292. package/ccw/src/tools/core-memory.ts +444 -0
  293. package/ccw/src/tools/detect-changed-modules.ts +325 -0
  294. package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
  295. package/ccw/src/tools/edit-file.ts +568 -0
  296. package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
  297. package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
  298. package/ccw/src/tools/index.ts +370 -0
  299. package/ccw/src/tools/native-session-discovery.ts +795 -0
  300. package/ccw/src/tools/notifier.ts +129 -0
  301. package/ccw/src/tools/read-file.ts +410 -0
  302. package/ccw/src/tools/resume-strategy.ts +345 -0
  303. package/ccw/src/tools/session-content-parser.ts +619 -0
  304. package/ccw/src/tools/session-manager.ts +1026 -0
  305. package/ccw/src/tools/smart-context.ts +228 -0
  306. package/ccw/src/tools/smart-search.ts +2065 -0
  307. package/ccw/src/tools/smart-search.ts.backup +1233 -0
  308. package/ccw/src/tools/storage-manager.ts +455 -0
  309. package/ccw/src/tools/write-file.ts +222 -0
  310. package/ccw/src/types/config.ts +11 -0
  311. package/ccw/src/types/index.ts +3 -0
  312. package/ccw/src/types/session.ts +25 -0
  313. package/ccw/src/types/tool.ts +41 -0
  314. package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
  315. package/ccw/src/utils/file-utils.ts +48 -0
  316. package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
  317. package/ccw/src/utils/path-validator.ts +153 -0
  318. package/ccw/src/utils/{ui.js → ui.ts} +32 -25
  319. package/codex-lens/pyproject.toml +48 -0
  320. package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
  321. package/codex-lens/src/codexlens/__init__.py +28 -0
  322. package/codex-lens/src/codexlens/__main__.py +14 -0
  323. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
  324. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
  325. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  326. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  327. package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
  328. package/codex-lens/src/codexlens/cli/__init__.py +27 -0
  329. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  330. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  331. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  332. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  333. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  334. package/codex-lens/src/codexlens/cli/commands.py +1931 -0
  335. package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
  336. package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
  337. package/codex-lens/src/codexlens/cli/output.py +124 -0
  338. package/codex-lens/src/codexlens/config.py +201 -0
  339. package/codex-lens/src/codexlens/entities.py +121 -0
  340. package/codex-lens/src/codexlens/errors.py +55 -0
  341. package/codex-lens/src/codexlens/indexing/README.md +77 -0
  342. package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
  343. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  344. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  345. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
  346. package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
  347. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
  348. package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
  349. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  350. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
  351. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  352. package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
  353. package/codex-lens/src/codexlens/parsers/factory.py +256 -0
  354. package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
  355. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
  356. package/codex-lens/src/codexlens/search/__init__.py +15 -0
  357. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
  358. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  359. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  360. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  361. package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
  362. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  363. package/codex-lens/src/codexlens/search/chain_search.py +647 -0
  364. package/codex-lens/src/codexlens/search/enrichment.py +150 -0
  365. package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
  366. package/codex-lens/src/codexlens/search/query_parser.py +242 -0
  367. package/codex-lens/src/codexlens/search/ranking.py +274 -0
  368. package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
  369. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  370. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  371. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  372. package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
  373. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  374. package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
  375. package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
  376. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  377. package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
  378. package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
  379. package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
  380. package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
  381. package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
  382. package/codex-lens/src/codexlens/storage/__init__.py +29 -0
  383. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  384. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  385. package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
  386. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  387. package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
  388. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  389. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
  390. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  391. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
  392. package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
  393. package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
  394. package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
  395. package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
  396. package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
  397. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  398. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
  399. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
  400. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
  401. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  402. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
  403. package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
  404. package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
  405. package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
  406. package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
  407. package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
  408. package/codex-lens/src/codexlens/storage/registry.py +670 -0
  409. package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
  410. package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
  411. package/package.json +4 -1
  412. package/.claude/commands/memory/tech-research.md +0 -477
  413. package/.claude/scripts/classify-folders.sh +0 -39
  414. package/.claude/scripts/convert_tokens_to_css.sh +0 -229
  415. package/.claude/scripts/detect_changed_modules.sh +0 -161
  416. package/.claude/scripts/discover-design-files.sh +0 -87
  417. package/.claude/scripts/extract-animations.js +0 -243
  418. package/.claude/scripts/extract-computed-styles.js +0 -118
  419. package/.claude/scripts/extract-layout-structure.js +0 -411
  420. package/.claude/scripts/generate_module_docs.sh +0 -717
  421. package/.claude/scripts/get_modules_by_depth.sh +0 -170
  422. package/.claude/scripts/ui-generate-preview.sh +0 -395
  423. package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
  424. package/.claude/scripts/update_module_claude.sh +0 -337
  425. package/.claude/workflows/context-search-strategy.md +0 -77
  426. package/.claude/workflows/intelligent-tools-strategy.md +0 -662
  427. package/ccw/src/cli.js +0 -119
  428. package/ccw/src/commands/install.js +0 -324
  429. package/ccw/src/commands/tool.js +0 -138
  430. package/ccw/src/core/data-aggregator.js +0 -409
  431. package/ccw/src/core/server.js +0 -2063
  432. package/ccw/src/core/session-scanner.js +0 -235
  433. package/ccw/src/tools/classify-folders.js +0 -204
  434. package/ccw/src/tools/detect-changed-modules.js +0 -288
  435. package/ccw/src/tools/edit-file.js +0 -266
  436. package/ccw/src/tools/index.js +0 -176
  437. package/ccw/src/utils/file-utils.js +0 -48
@@ -1,219 +1,508 @@
1
- // ==========================================
2
- // GLOBAL NOTIFICATION SYSTEM
3
- // ==========================================
4
- // Floating notification panel accessible from any view
5
-
6
- /**
7
- * Initialize global notification panel
8
- */
9
- function initGlobalNotifications() {
10
- // Create FAB and panel if not exists
11
- if (!document.getElementById('globalNotificationFab')) {
12
- const fabHtml = `
13
- <div class="global-notif-fab" id="globalNotificationFab" onclick="toggleGlobalNotifications()" title="Notifications">
14
- <span class="fab-icon">🔔</span>
15
- <span class="fab-badge" id="globalNotifBadge">0</span>
16
- </div>
17
-
18
- <div class="global-notif-panel" id="globalNotificationPanel">
19
- <div class="global-notif-header">
20
- <span class="global-notif-title">🔔 Notifications</span>
21
- <button class="global-notif-close" onclick="toggleGlobalNotifications()">×</button>
22
- </div>
23
- <div class="global-notif-actions">
24
- <button class="notif-action-btn" onclick="clearGlobalNotifications()">
25
- <span>đŸ—‘ī¸</span> Clear All
26
- </button>
27
- </div>
28
- <div class="global-notif-list" id="globalNotificationList">
29
- <div class="global-notif-empty">
30
- <span>No notifications</span>
31
- <p>System events and task updates will appear here</p>
32
- </div>
33
- </div>
34
- </div>
35
- `;
36
-
37
- const container = document.createElement('div');
38
- container.id = 'globalNotificationContainer';
39
- container.innerHTML = fabHtml;
40
- document.body.appendChild(container);
41
- }
42
-
43
- renderGlobalNotifications();
44
- }
45
-
46
- /**
47
- * Toggle notification panel visibility
48
- */
49
- function toggleGlobalNotifications() {
50
- isNotificationPanelVisible = !isNotificationPanelVisible;
51
- const panel = document.getElementById('globalNotificationPanel');
52
- const fab = document.getElementById('globalNotificationFab');
53
-
54
- if (panel && fab) {
55
- if (isNotificationPanelVisible) {
56
- panel.classList.add('show');
57
- fab.classList.add('active');
58
- } else {
59
- panel.classList.remove('show');
60
- fab.classList.remove('active');
61
- }
62
- }
63
- }
64
-
65
- /**
66
- * Add a global notification
67
- * @param {string} type - 'info', 'success', 'warning', 'error'
68
- * @param {string} message - Main notification message
69
- * @param {string} details - Optional details
70
- * @param {string} source - Optional source identifier (e.g., 'explorer', 'mcp')
71
- */
72
- function addGlobalNotification(type, message, details = null, source = null) {
73
- const notification = {
74
- id: Date.now(),
75
- type,
76
- message,
77
- details,
78
- source,
79
- timestamp: new Date().toISOString(),
80
- read: false
81
- };
82
-
83
- globalNotificationQueue.unshift(notification);
84
-
85
- // Keep only last 100 notifications
86
- if (globalNotificationQueue.length > 100) {
87
- globalNotificationQueue = globalNotificationQueue.slice(0, 100);
88
- }
89
-
90
- renderGlobalNotifications();
91
- updateGlobalNotifBadge();
92
-
93
- // Show toast for important notifications
94
- if (type === 'error' || type === 'success') {
95
- showNotificationToast(notification);
96
- }
97
- }
98
-
99
- /**
100
- * Show a brief toast notification
101
- */
102
- function showNotificationToast(notification) {
103
- const typeIcon = {
104
- 'info': 'â„šī¸',
105
- 'success': '✅',
106
- 'warning': 'âš ī¸',
107
- 'error': '❌'
108
- }[notification.type] || 'â„šī¸';
109
-
110
- // Remove existing toast
111
- const existing = document.querySelector('.notif-toast');
112
- if (existing) existing.remove();
113
-
114
- const toast = document.createElement('div');
115
- toast.className = `notif-toast type-${notification.type}`;
116
- toast.innerHTML = `
117
- <span class="toast-icon">${typeIcon}</span>
118
- <span class="toast-message">${escapeHtml(notification.message)}</span>
119
- `;
120
- document.body.appendChild(toast);
121
-
122
- // Animate in
123
- requestAnimationFrame(() => toast.classList.add('show'));
124
-
125
- // Auto-remove
126
- setTimeout(() => {
127
- toast.classList.remove('show');
128
- setTimeout(() => toast.remove(), 300);
129
- }, 3000);
130
- }
131
-
132
- /**
133
- * Render notification list
134
- */
135
- function renderGlobalNotifications() {
136
- const listEl = document.getElementById('globalNotificationList');
137
- if (!listEl) return;
138
-
139
- if (globalNotificationQueue.length === 0) {
140
- listEl.innerHTML = `
141
- <div class="global-notif-empty">
142
- <span>No notifications</span>
143
- <p>System events and task updates will appear here</p>
144
- </div>
145
- `;
146
- return;
147
- }
148
-
149
- listEl.innerHTML = globalNotificationQueue.map(notif => {
150
- const typeIcon = {
151
- 'info': 'â„šī¸',
152
- 'success': '✅',
153
- 'warning': 'âš ī¸',
154
- 'error': '❌'
155
- }[notif.type] || 'â„šī¸';
156
-
157
- const time = formatNotifTime(notif.timestamp);
158
- const sourceLabel = notif.source ? `<span class="notif-source">${notif.source}</span>` : '';
159
-
160
- return `
161
- <div class="global-notif-item type-${notif.type} ${notif.read ? 'read' : ''}" data-id="${notif.id}">
162
- <div class="notif-item-header">
163
- <span class="notif-icon">${typeIcon}</span>
164
- <span class="notif-message">${escapeHtml(notif.message)}</span>
165
- ${sourceLabel}
166
- </div>
167
- ${notif.details ? `<div class="notif-details">${escapeHtml(notif.details)}</div>` : ''}
168
- <div class="notif-meta">
169
- <span class="notif-time">${time}</span>
170
- </div>
171
- </div>
172
- `;
173
- }).join('');
174
- }
175
-
176
- /**
177
- * Format notification time
178
- */
179
- function formatNotifTime(timestamp) {
180
- const date = new Date(timestamp);
181
- const now = new Date();
182
- const diff = now - date;
183
-
184
- if (diff < 60000) return 'Just now';
185
- if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
186
- if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
187
- return date.toLocaleDateString();
188
- }
189
-
190
- /**
191
- * Update notification badge
192
- */
193
- function updateGlobalNotifBadge() {
194
- const badge = document.getElementById('globalNotifBadge');
195
- if (badge) {
196
- const unreadCount = globalNotificationQueue.filter(n => !n.read).length;
197
- badge.textContent = unreadCount;
198
- badge.style.display = unreadCount > 0 ? 'flex' : 'none';
199
- }
200
- }
201
-
202
- /**
203
- * Clear all notifications
204
- */
205
- function clearGlobalNotifications() {
206
- globalNotificationQueue = [];
207
- renderGlobalNotifications();
208
- updateGlobalNotifBadge();
209
- }
210
-
211
- /**
212
- * Mark all as read
213
- */
214
- function markAllNotificationsRead() {
215
- globalNotificationQueue.forEach(n => n.read = true);
216
- renderGlobalNotifications();
217
- updateGlobalNotifBadge();
218
- }
219
-
1
+ // ==========================================
2
+ // GLOBAL NOTIFICATION SYSTEM - Right Sidebar
3
+ // ==========================================
4
+ // Right-side slide-out toolbar for notifications and quick actions
5
+ // Supports browser system notifications (cross-platform)
6
+
7
+ // Notification settings
8
+ let notifSettings = {
9
+ systemNotifEnabled: false,
10
+ soundEnabled: false
11
+ };
12
+
13
+ /**
14
+ * Initialize global notification sidebar
15
+ */
16
+ function initGlobalNotifications() {
17
+ // Load settings from localStorage
18
+ loadNotifSettings();
19
+
20
+ // Request notification permission if enabled
21
+ if (notifSettings.systemNotifEnabled) {
22
+ requestNotificationPermission();
23
+ }
24
+
25
+ // Create sidebar if not exists
26
+ if (!document.getElementById('notifSidebar')) {
27
+ const sidebarHtml = `
28
+ <div class="notif-sidebar" id="notifSidebar">
29
+ <div class="notif-sidebar-header">
30
+ <div class="notif-sidebar-title">
31
+ <span class="notif-title-icon">🔔</span>
32
+ <span>Notifications</span>
33
+ <span class="notif-count-badge" id="notifCountBadge">0</span>
34
+ </div>
35
+ <button class="notif-sidebar-close" onclick="toggleNotifSidebar()" title="Close">
36
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
37
+ <path d="M18 6L6 18M6 6l12 12"/>
38
+ </svg>
39
+ </button>
40
+ </div>
41
+
42
+ <div class="notif-sidebar-settings" id="notifSettings">
43
+ <label class="notif-setting-item">
44
+ <input type="checkbox" id="systemNotifToggle" onchange="toggleSystemNotifications(this.checked)">
45
+ <span class="notif-setting-label">
46
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
47
+ <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
48
+ <path d="M13.73 21a2 2 0 0 1-3.46 0"/>
49
+ </svg>
50
+ System Notifications
51
+ </span>
52
+ </label>
53
+ </div>
54
+
55
+ <div class="notif-sidebar-actions">
56
+ <button class="notif-action-btn" onclick="markAllNotificationsRead()" title="Mark all read">
57
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
58
+ <path d="M20 6L9 17l-5-5"/>
59
+ </svg>
60
+ <span>Mark Read</span>
61
+ </button>
62
+ <button class="notif-action-btn" onclick="clearGlobalNotifications()" title="Clear all">
63
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
64
+ <path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/>
65
+ </svg>
66
+ <span>Clear All</span>
67
+ </button>
68
+ </div>
69
+
70
+ <div class="notif-sidebar-content" id="notifSidebarContent">
71
+ <div class="notif-empty-state">
72
+ <div class="notif-empty-icon">🔔</div>
73
+ <div class="notif-empty-text">No notifications</div>
74
+ <div class="notif-empty-hint">System events and task updates will appear here</div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+
79
+ <div class="notif-sidebar-toggle" id="notifSidebarToggle" onclick="toggleNotifSidebar()" title="Notifications">
80
+ <span class="toggle-icon">🔔</span>
81
+ <span class="toggle-badge" id="notifToggleBadge"></span>
82
+ </div>
83
+
84
+ <div class="notif-sidebar-overlay" id="notifSidebarOverlay" onclick="toggleNotifSidebar()"></div>
85
+ `;
86
+
87
+ const container = document.createElement('div');
88
+ container.id = 'notifSidebarContainer';
89
+ container.innerHTML = sidebarHtml;
90
+ document.body.appendChild(container);
91
+
92
+ // Initialize toggle state
93
+ const toggle = document.getElementById('systemNotifToggle');
94
+ if (toggle) {
95
+ toggle.checked = notifSettings.systemNotifEnabled;
96
+ }
97
+ }
98
+
99
+ renderGlobalNotifications();
100
+ updateGlobalNotifBadge();
101
+ }
102
+
103
+ /**
104
+ * Load notification settings from localStorage
105
+ */
106
+ function loadNotifSettings() {
107
+ try {
108
+ const saved = localStorage.getItem('ccw_notif_settings');
109
+ if (saved) {
110
+ notifSettings = { ...notifSettings, ...JSON.parse(saved) };
111
+ }
112
+ } catch (e) {
113
+ console.error('[Notif] Failed to load settings:', e);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Save notification settings to localStorage
119
+ */
120
+ function saveNotifSettings() {
121
+ try {
122
+ localStorage.setItem('ccw_notif_settings', JSON.stringify(notifSettings));
123
+ } catch (e) {
124
+ console.error('[Notif] Failed to save settings:', e);
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Toggle system notifications
130
+ */
131
+ function toggleSystemNotifications(enabled) {
132
+ notifSettings.systemNotifEnabled = enabled;
133
+ saveNotifSettings();
134
+
135
+ if (enabled) {
136
+ requestNotificationPermission();
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Request browser notification permission
142
+ */
143
+ async function requestNotificationPermission() {
144
+ if (!('Notification' in window)) {
145
+ console.warn('[Notif] Browser does not support notifications');
146
+ return false;
147
+ }
148
+
149
+ if (Notification.permission === 'granted') {
150
+ return true;
151
+ }
152
+
153
+ if (Notification.permission !== 'denied') {
154
+ const permission = await Notification.requestPermission();
155
+ return permission === 'granted';
156
+ }
157
+
158
+ return false;
159
+ }
160
+
161
+ /**
162
+ * Show system notification (browser notification)
163
+ */
164
+ function showSystemNotification(notification) {
165
+ if (!notifSettings.systemNotifEnabled) return;
166
+ if (!('Notification' in window)) return;
167
+ if (Notification.permission !== 'granted') return;
168
+
169
+ const typeIcon = {
170
+ 'info': 'â„šī¸',
171
+ 'success': '✅',
172
+ 'warning': 'âš ī¸',
173
+ 'error': '❌'
174
+ }[notification.type] || '🔔';
175
+
176
+ const title = `${typeIcon} ${notification.message}`;
177
+ let body = '';
178
+
179
+ if (notification.source) {
180
+ body = `[${notification.source}]`;
181
+ }
182
+
183
+ // Extract plain text from details if HTML formatted
184
+ if (notification.details) {
185
+ const detailText = notification.details.replace(/<[^>]*>/g, '').trim();
186
+ if (detailText) {
187
+ body += body ? '\n' + detailText : detailText;
188
+ }
189
+ }
190
+
191
+ try {
192
+ const sysNotif = new Notification(title, {
193
+ body: body.substring(0, 200),
194
+ icon: '/favicon.ico',
195
+ tag: `ccw-notif-${notification.id}`,
196
+ requireInteraction: notification.type === 'error'
197
+ });
198
+
199
+ // Click to open sidebar
200
+ sysNotif.onclick = () => {
201
+ window.focus();
202
+ if (!isNotificationPanelVisible) {
203
+ toggleNotifSidebar();
204
+ }
205
+ sysNotif.close();
206
+ };
207
+
208
+ // Auto close after 5s (except errors)
209
+ if (notification.type !== 'error') {
210
+ setTimeout(() => sysNotif.close(), 5000);
211
+ }
212
+ } catch (e) {
213
+ console.error('[Notif] Failed to show system notification:', e);
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Toggle notification sidebar visibility
219
+ */
220
+ function toggleNotifSidebar() {
221
+ isNotificationPanelVisible = !isNotificationPanelVisible;
222
+ const sidebar = document.getElementById('notifSidebar');
223
+ const overlay = document.getElementById('notifSidebarOverlay');
224
+ const toggle = document.getElementById('notifSidebarToggle');
225
+
226
+ if (sidebar && overlay && toggle) {
227
+ if (isNotificationPanelVisible) {
228
+ sidebar.classList.add('open');
229
+ overlay.classList.add('show');
230
+ toggle.classList.add('hidden');
231
+ } else {
232
+ sidebar.classList.remove('open');
233
+ overlay.classList.remove('show');
234
+ toggle.classList.remove('hidden');
235
+ }
236
+ }
237
+ }
238
+
239
+ // Backward compatibility alias
240
+ function toggleGlobalNotifications() {
241
+ toggleNotifSidebar();
242
+ }
243
+
244
+ /**
245
+ * Add a global notification
246
+ * @param {string} type - 'info', 'success', 'warning', 'error'
247
+ * @param {string} message - Main notification message
248
+ * @param {string|object} details - Optional details (string or object)
249
+ * @param {string} source - Optional source identifier
250
+ */
251
+ function addGlobalNotification(type, message, details = null, source = null) {
252
+ // Format details if it's an object
253
+ let formattedDetails = details;
254
+ let rawDetails = details; // Keep raw for system notification
255
+
256
+ if (details && typeof details === 'object') {
257
+ formattedDetails = formatNotificationJson(details);
258
+ rawDetails = JSON.stringify(details, null, 2);
259
+ } else if (typeof details === 'string') {
260
+ // Try to parse and format if it looks like JSON
261
+ const trimmed = details.trim();
262
+ if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
263
+ (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
264
+ try {
265
+ const parsed = JSON.parse(trimmed);
266
+ formattedDetails = formatNotificationJson(parsed);
267
+ rawDetails = JSON.stringify(parsed, null, 2);
268
+ } catch (e) {
269
+ // Not valid JSON, use as-is
270
+ formattedDetails = details;
271
+ }
272
+ }
273
+ }
274
+
275
+ const notification = {
276
+ id: Date.now(),
277
+ type,
278
+ message,
279
+ details: formattedDetails,
280
+ rawDetails: rawDetails,
281
+ source,
282
+ timestamp: new Date().toISOString(),
283
+ read: false,
284
+ expanded: false
285
+ };
286
+
287
+ globalNotificationQueue.unshift(notification);
288
+
289
+ // Keep only last 100 notifications
290
+ if (globalNotificationQueue.length > 100) {
291
+ globalNotificationQueue = globalNotificationQueue.slice(0, 100);
292
+ }
293
+
294
+ // Persist to localStorage
295
+ if (typeof saveNotificationsToStorage === 'function') {
296
+ saveNotificationsToStorage();
297
+ }
298
+
299
+ renderGlobalNotifications();
300
+ updateGlobalNotifBadge();
301
+
302
+ // Show system notification instead of toast
303
+ showSystemNotification(notification);
304
+ }
305
+
306
+ /**
307
+ * Format JSON object for notification display
308
+ * @param {Object} obj - Object to format
309
+ * @returns {string} HTML formatted string
310
+ */
311
+ function formatNotificationJson(obj) {
312
+ if (obj === null || obj === undefined) return '';
313
+ if (typeof obj !== 'object') return String(obj);
314
+
315
+ // Handle arrays
316
+ if (Array.isArray(obj)) {
317
+ if (obj.length === 0) return '<span class="json-empty">(empty array)</span>';
318
+ const items = obj.slice(0, 5).map((item, i) => {
319
+ const itemStr = typeof item === 'object' ? JSON.stringify(item) : String(item);
320
+ const truncated = itemStr.length > 60 ? itemStr.substring(0, 57) + '...' : itemStr;
321
+ return `<div class="json-array-item"><span class="json-index">[${i}]</span> ${escapeHtml(truncated)}</div>`;
322
+ });
323
+ if (obj.length > 5) {
324
+ items.push(`<div class="json-more">... +${obj.length - 5} more items</div>`);
325
+ }
326
+ return items.join('');
327
+ }
328
+
329
+ // Handle objects
330
+ const entries = Object.entries(obj);
331
+ if (entries.length === 0) return '<span class="json-empty">(empty object)</span>';
332
+
333
+ const lines = entries.slice(0, 8).map(([key, val]) => {
334
+ let valStr;
335
+ let valClass = 'json-value';
336
+
337
+ if (val === null) {
338
+ valStr = 'null';
339
+ valClass = 'json-null';
340
+ } else if (val === undefined) {
341
+ valStr = 'undefined';
342
+ valClass = 'json-null';
343
+ } else if (typeof val === 'boolean') {
344
+ valStr = val ? 'true' : 'false';
345
+ valClass = 'json-bool';
346
+ } else if (typeof val === 'number') {
347
+ valStr = String(val);
348
+ valClass = 'json-number';
349
+ } else if (typeof val === 'object') {
350
+ valStr = JSON.stringify(val);
351
+ if (valStr.length > 50) valStr = valStr.substring(0, 47) + '...';
352
+ valClass = 'json-object';
353
+ } else {
354
+ valStr = String(val);
355
+ if (valStr.length > 60) valStr = valStr.substring(0, 57) + '...';
356
+ valClass = 'json-string';
357
+ }
358
+
359
+ return `<div class="json-field"><span class="json-key">${escapeHtml(key)}:</span> <span class="${valClass}">${escapeHtml(valStr)}</span></div>`;
360
+ });
361
+
362
+ if (entries.length > 8) {
363
+ lines.push(`<div class="json-more">... +${entries.length - 8} more fields</div>`);
364
+ }
365
+
366
+ return lines.join('');
367
+ }
368
+
369
+ /**
370
+ * Toggle notification item expansion
371
+ */
372
+ function toggleNotifExpand(notifId) {
373
+ const notif = globalNotificationQueue.find(n => n.id === notifId);
374
+ if (notif) {
375
+ notif.expanded = !notif.expanded;
376
+ renderGlobalNotifications();
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Render notification list in sidebar
382
+ */
383
+ function renderGlobalNotifications() {
384
+ const contentEl = document.getElementById('notifSidebarContent');
385
+ if (!contentEl) return;
386
+
387
+ if (globalNotificationQueue.length === 0) {
388
+ contentEl.innerHTML = `
389
+ <div class="notif-empty-state">
390
+ <div class="notif-empty-icon">🔔</div>
391
+ <div class="notif-empty-text">No notifications</div>
392
+ <div class="notif-empty-hint">System events and task updates will appear here</div>
393
+ </div>
394
+ `;
395
+ return;
396
+ }
397
+
398
+ contentEl.innerHTML = globalNotificationQueue.map(notif => {
399
+ const typeIcon = {
400
+ 'info': 'â„šī¸',
401
+ 'success': '✅',
402
+ 'warning': 'âš ī¸',
403
+ 'error': '❌'
404
+ }[notif.type] || 'â„šī¸';
405
+
406
+ const time = formatNotifTime(notif.timestamp);
407
+ const sourceLabel = notif.source ? `<span class="notif-source">${escapeHtml(notif.source)}</span>` : '';
408
+ const hasDetails = notif.details && notif.details.length > 0;
409
+ const expandIcon = hasDetails ? (notif.expanded ? 'â–ŧ' : 'â–ļ') : '';
410
+
411
+ // Details section - collapsed by default, show preview
412
+ let detailsHtml = '';
413
+ if (hasDetails) {
414
+ if (notif.expanded) {
415
+ // Expanded view - show full details
416
+ if (typeof notif.details === 'string' && notif.details.includes('class="json-')) {
417
+ detailsHtml = `<div class="notif-details-json notif-details-expanded">${notif.details}</div>`;
418
+ } else {
419
+ detailsHtml = `<div class="notif-details notif-details-expanded">${escapeHtml(String(notif.details))}</div>`;
420
+ }
421
+ } else {
422
+ // Collapsed view - show hint
423
+ detailsHtml = `<div class="notif-details-hint">Click to view details</div>`;
424
+ }
425
+ }
426
+
427
+ return `
428
+ <div class="notif-item type-${notif.type} ${notif.read ? 'read' : ''} ${hasDetails ? 'has-details' : ''} ${notif.expanded ? 'expanded' : ''}"
429
+ data-id="${notif.id}"
430
+ onclick="toggleNotifExpand(${notif.id})">
431
+ <div class="notif-item-header">
432
+ <span class="notif-icon">${typeIcon}</span>
433
+ <div class="notif-item-content">
434
+ <span class="notif-message">${escapeHtml(notif.message)}</span>
435
+ ${sourceLabel}
436
+ </div>
437
+ ${hasDetails ? `<span class="notif-expand-icon">${expandIcon}</span>` : ''}
438
+ </div>
439
+ ${detailsHtml}
440
+ <div class="notif-meta">
441
+ <span class="notif-time">${time}</span>
442
+ </div>
443
+ </div>
444
+ `;
445
+ }).join('');
446
+ }
447
+
448
+ /**
449
+ * Format notification time
450
+ */
451
+ function formatNotifTime(timestamp) {
452
+ const date = new Date(timestamp);
453
+ const now = new Date();
454
+ const diff = now - date;
455
+
456
+ if (diff < 60000) return 'Just now';
457
+ if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
458
+ if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
459
+ return date.toLocaleDateString();
460
+ }
461
+
462
+ /**
463
+ * Update notification badge counts
464
+ */
465
+ function updateGlobalNotifBadge() {
466
+ const unreadCount = globalNotificationQueue.filter(n => !n.read).length;
467
+
468
+ const countBadge = document.getElementById('notifCountBadge');
469
+ const toggleBadge = document.getElementById('notifToggleBadge');
470
+
471
+ if (countBadge) {
472
+ countBadge.textContent = globalNotificationQueue.length;
473
+ countBadge.style.display = globalNotificationQueue.length > 0 ? 'inline-flex' : 'none';
474
+ }
475
+
476
+ if (toggleBadge) {
477
+ toggleBadge.textContent = unreadCount;
478
+ toggleBadge.style.display = unreadCount > 0 ? 'flex' : 'none';
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Clear all notifications
484
+ */
485
+ function clearGlobalNotifications() {
486
+ globalNotificationQueue = [];
487
+
488
+ if (typeof saveNotificationsToStorage === 'function') {
489
+ saveNotificationsToStorage();
490
+ }
491
+
492
+ renderGlobalNotifications();
493
+ updateGlobalNotifBadge();
494
+ }
495
+
496
+ /**
497
+ * Mark all as read
498
+ */
499
+ function markAllNotificationsRead() {
500
+ globalNotificationQueue.forEach(n => n.read = true);
501
+
502
+ if (typeof saveNotificationsToStorage === 'function') {
503
+ saveNotificationsToStorage();
504
+ }
505
+
506
+ renderGlobalNotifications();
507
+ updateGlobalNotifBadge();
508
+ }