cokit-cli 1.0.0 → 1.0.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 (599) hide show
  1. package/AGENTS.md +103 -0
  2. package/FAQ.md +5 -5
  3. package/QUICK-START.md +4 -4
  4. package/README.FLOW.md +237 -0
  5. package/README.md +153 -92
  6. package/agents/brainstormer.agent.md +71 -0
  7. package/agents/code-reviewer.agent.md +128 -0
  8. package/agents/database-admin.agent.md +91 -0
  9. package/agents/debugger.agent.md +128 -0
  10. package/agents/docs-manager.agent.md +121 -0
  11. package/agents/fullstack-developer.agent.md +96 -0
  12. package/agents/git-manager.agent.md +392 -0
  13. package/agents/mcp-manager.agent.md +93 -0
  14. package/agents/planner.agent.md +94 -0
  15. package/agents/project-manager.agent.md +124 -0
  16. package/agents/researcher.agent.md +32 -0
  17. package/agents/scout-external.agent.md +141 -0
  18. package/agents/scout.agent.md +107 -0
  19. package/agents/tester.agent.md +106 -0
  20. package/agents/ui-ux-designer.agent.md +225 -0
  21. package/collections/ck-core.collection.yml +30 -0
  22. package/collections/ck-development-rules.collection.yml +18 -0
  23. package/collections/ck-documentation.collection.yml +18 -0
  24. package/collections/ck-git-workflow.collection.yml +18 -0
  25. package/collections/ck-orchestration.collection.yml +22 -0
  26. package/collections/ck-ui-design.collection.yml +18 -0
  27. package/docs/README.md +85 -0
  28. package/docs/copilot-processing-flow.md +128 -0
  29. package/docs/migration-guide.md +12 -12
  30. package/instructions/ck-backend.instructions.md +48 -0
  31. package/instructions/ck-development.instructions.md +40 -0
  32. package/instructions/ck-frontend-design-pro.instructions.md +58 -0
  33. package/instructions/ck-frontend.instructions.md +44 -0
  34. package/instructions/ck-google-adk-python.instructions.md +242 -0
  35. package/instructions/ck-research.instructions.md +167 -0
  36. package/instructions/ck-testing.instructions.md +36 -0
  37. package/package.json +9 -2
  38. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-01-restructure-folders.md +183 -0
  39. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-02-convert-agents.md +206 -0
  40. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-03-convert-commands-to-prompts.md +284 -0
  41. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-04-convert-skills-to-instructions.md +349 -0
  42. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-05-create-collections.md +320 -0
  43. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-06-update-cli-build-scripts.md +450 -0
  44. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/phase-07-update-documentation.md +407 -0
  45. package/plans/260108-0924-rebuild-cokit-awesome-copilot-format/plan.md +136 -0
  46. package/prompts/ck-ask.prompt.md +57 -0
  47. package/prompts/ck-bootstrap-auto-fast.prompt.md +108 -0
  48. package/prompts/ck-bootstrap-auto-parallel.prompt.md +66 -0
  49. package/prompts/ck-bootstrap-auto.prompt.md +114 -0
  50. package/prompts/ck-bootstrap.prompt.md +136 -0
  51. package/prompts/ck-brainstorm.prompt.md +68 -0
  52. package/prompts/ck-ck-help.prompt.md +114 -0
  53. package/prompts/ck-code-auto.prompt.md +171 -0
  54. package/prompts/ck-code-no-test.prompt.md +159 -0
  55. package/prompts/ck-code-parallel.prompt.md +56 -0
  56. package/prompts/ck-code.prompt.md +177 -0
  57. package/prompts/ck-coding-level.prompt.md +54 -0
  58. package/prompts/ck-cook-auto-fast.prompt.md +26 -0
  59. package/prompts/ck-cook-auto-parallel.prompt.md +49 -0
  60. package/prompts/ck-cook-auto.prompt.md +15 -0
  61. package/prompts/ck-cook.prompt.md +96 -0
  62. package/prompts/ck-debug.prompt.md +14 -0
  63. package/prompts/ck-design-3d.prompt.md +84 -0
  64. package/prompts/ck-design-describe.prompt.md +24 -0
  65. package/prompts/ck-design-fast.prompt.md +32 -0
  66. package/prompts/ck-design-good.prompt.md +36 -0
  67. package/prompts/ck-design-screenshot.prompt.md +35 -0
  68. package/prompts/ck-design-video.prompt.md +35 -0
  69. package/prompts/ck-docs-init.prompt.md +27 -0
  70. package/prompts/ck-docs-summarize.prompt.md +23 -0
  71. package/prompts/ck-docs-update.prompt.md +36 -0
  72. package/prompts/ck-fix-ci.prompt.md +18 -0
  73. package/prompts/ck-fix-fast.prompt.md +18 -0
  74. package/prompts/ck-fix-hard.prompt.md +36 -0
  75. package/prompts/ck-fix-logs.prompt.md +27 -0
  76. package/prompts/ck-fix-parallel.prompt.md +54 -0
  77. package/prompts/ck-fix-test.prompt.md +19 -0
  78. package/prompts/ck-fix-types.prompt.md +11 -0
  79. package/prompts/ck-fix-ui.prompt.md +49 -0
  80. package/prompts/ck-fix.prompt.md +44 -0
  81. package/prompts/ck-git-cm.prompt.md +8 -0
  82. package/prompts/ck-git-cp.prompt.md +7 -0
  83. package/prompts/ck-git-merge.prompt.md +41 -0
  84. package/prompts/ck-git-pr.prompt.md +49 -0
  85. package/prompts/ck-kanban.prompt.md +77 -0
  86. package/prompts/ck-plan-archive.prompt.md +58 -0
  87. package/prompts/ck-plan-ci.prompt.md +34 -0
  88. package/prompts/ck-plan-cro.prompt.md +66 -0
  89. package/prompts/ck-plan-fast.prompt.md +67 -0
  90. package/prompts/ck-plan-hard.prompt.md +89 -0
  91. package/prompts/ck-plan-parallel.prompt.md +126 -0
  92. package/prompts/ck-plan-two.prompt.md +43 -0
  93. package/prompts/ck-plan-validate.prompt.md +118 -0
  94. package/prompts/ck-plan.prompt.md +29 -1
  95. package/prompts/ck-preview.prompt.md +65 -0
  96. package/prompts/ck-review-codebase.prompt.md +44 -0
  97. package/prompts/ck-scout-ext.prompt.md +35 -0
  98. package/prompts/ck-scout.prompt.md +25 -0
  99. package/prompts/ck-skill-add.prompt.md +36 -0
  100. package/prompts/ck-skill-create.prompt.md +29 -0
  101. package/prompts/ck-skill-fix-logs.prompt.md +22 -0
  102. package/prompts/ck-skill-optimize-auto.prompt.md +25 -0
  103. package/prompts/ck-skill-optimize.prompt.md +34 -0
  104. package/prompts/ck-skill-plan.prompt.md +46 -0
  105. package/prompts/ck-test-ui.prompt.md +92 -0
  106. package/prompts/ck-test.prompt.md +10 -0
  107. package/prompts/ck-use-mcp.prompt.md +27 -0
  108. package/prompts/ck-watzup.prompt.md +11 -0
  109. package/prompts/ck-worktree.prompt.md +127 -0
  110. package/rules/README.agents.md +55 -0
  111. package/rules/README.collections.md +78 -0
  112. package/rules/README.copilot-instructions.md +66 -0
  113. package/rules/README.instructions.md +73 -0
  114. package/rules/README.md +39 -0
  115. package/rules/README.prompts.md +76 -0
  116. package/rules/README.skills.md +71 -0
  117. package/skills/ck-ai-artist/SKILL.md +73 -0
  118. package/skills/ck-ai-artist/references/advanced-techniques.md +184 -0
  119. package/skills/ck-ai-artist/references/domain-code.md +66 -0
  120. package/skills/ck-ai-artist/references/domain-data.md +72 -0
  121. package/skills/ck-ai-artist/references/domain-marketing.md +66 -0
  122. package/skills/ck-ai-artist/references/domain-patterns.md +33 -0
  123. package/skills/ck-ai-artist/references/domain-writing.md +68 -0
  124. package/skills/ck-ai-artist/references/image-prompting.md +141 -0
  125. package/skills/ck-ai-artist/references/llm-prompting.md +165 -0
  126. package/skills/ck-ai-artist/references/nano-banana.md +59 -0
  127. package/skills/ck-ai-artist/references/reasoning-techniques.md +201 -0
  128. package/skills/ck-backend-development/SKILL.md +93 -0
  129. package/skills/ck-backend-development/references/backend-api-design.md +495 -0
  130. package/skills/ck-backend-development/references/backend-architecture.md +454 -0
  131. package/skills/ck-backend-development/references/backend-authentication.md +338 -0
  132. package/skills/ck-backend-development/references/backend-code-quality.md +659 -0
  133. package/skills/ck-backend-development/references/backend-debugging.md +904 -0
  134. package/skills/ck-backend-development/references/backend-devops.md +494 -0
  135. package/skills/ck-backend-development/references/backend-mindset.md +387 -0
  136. package/skills/ck-backend-development/references/backend-performance.md +397 -0
  137. package/skills/ck-backend-development/references/backend-security.md +290 -0
  138. package/skills/ck-backend-development/references/backend-technologies.md +256 -0
  139. package/skills/ck-backend-development/references/backend-testing.md +429 -0
  140. package/skills/ck-better-auth/SKILL.md +202 -0
  141. package/skills/ck-better-auth/references/advanced-features.md +553 -0
  142. package/skills/ck-better-auth/references/database-integration.md +577 -0
  143. package/skills/ck-better-auth/references/email-password-auth.md +416 -0
  144. package/skills/ck-better-auth/references/oauth-providers.md +430 -0
  145. package/skills/ck-better-auth/scripts/.coverage +0 -0
  146. package/skills/ck-better-auth/scripts/better_auth_init.py +521 -0
  147. package/skills/ck-better-auth/scripts/requirements.txt +15 -0
  148. package/skills/ck-better-auth/scripts/tests/.coverage +0 -0
  149. package/skills/ck-better-auth/scripts/tests/test_better_auth_init.py +421 -0
  150. package/skills/ck-chrome-devtools/SKILL.md +470 -0
  151. package/skills/ck-chrome-devtools/references/cdp-domains.md +694 -0
  152. package/skills/ck-chrome-devtools/references/performance-guide.md +940 -0
  153. package/skills/ck-chrome-devtools/references/puppeteer-reference.md +953 -0
  154. package/skills/ck-chrome-devtools/scripts/README.md +272 -0
  155. package/skills/ck-chrome-devtools/scripts/__tests__/selector.test.js +210 -0
  156. package/skills/ck-chrome-devtools/scripts/aria-snapshot.js +362 -0
  157. package/skills/ck-chrome-devtools/scripts/click.js +83 -0
  158. package/skills/ck-chrome-devtools/scripts/console.js +79 -0
  159. package/skills/ck-chrome-devtools/scripts/evaluate.js +53 -0
  160. package/skills/ck-chrome-devtools/scripts/fill.js +76 -0
  161. package/skills/ck-chrome-devtools/scripts/inject-auth.js +229 -0
  162. package/skills/ck-chrome-devtools/scripts/install-deps.sh +181 -0
  163. package/skills/ck-chrome-devtools/scripts/install.sh +83 -0
  164. package/skills/ck-chrome-devtools/scripts/lib/browser.js +318 -0
  165. package/skills/ck-chrome-devtools/scripts/lib/selector.js +178 -0
  166. package/skills/ck-chrome-devtools/scripts/navigate.js +54 -0
  167. package/skills/ck-chrome-devtools/scripts/network.js +106 -0
  168. package/skills/ck-chrome-devtools/scripts/package-lock.json +1589 -0
  169. package/skills/ck-chrome-devtools/scripts/package.json +16 -0
  170. package/skills/ck-chrome-devtools/scripts/performance.js +149 -0
  171. package/skills/ck-chrome-devtools/scripts/screenshot.js +198 -0
  172. package/skills/ck-chrome-devtools/scripts/select-ref.js +131 -0
  173. package/skills/ck-chrome-devtools/scripts/snapshot.js +135 -0
  174. package/skills/ck-code-review/SKILL.md +143 -0
  175. package/skills/ck-code-review/references/code-review-reception.md +209 -0
  176. package/skills/ck-code-review/references/requesting-code-review.md +105 -0
  177. package/skills/ck-code-review/references/verification-before-completion.md +139 -0
  178. package/skills/ck-databases/SKILL.md +231 -0
  179. package/skills/ck-databases/references/mongodb-aggregation.md +447 -0
  180. package/skills/ck-databases/references/mongodb-atlas.md +465 -0
  181. package/skills/ck-databases/references/mongodb-crud.md +408 -0
  182. package/skills/ck-databases/references/mongodb-indexing.md +442 -0
  183. package/skills/ck-databases/references/postgresql-administration.md +594 -0
  184. package/skills/ck-databases/references/postgresql-performance.md +527 -0
  185. package/skills/ck-databases/references/postgresql-psql-cli.md +467 -0
  186. package/skills/ck-databases/references/postgresql-queries.md +475 -0
  187. package/skills/ck-databases/scripts/.coverage +0 -0
  188. package/skills/ck-databases/scripts/db_backup.py +502 -0
  189. package/skills/ck-databases/scripts/db_migrate.py +425 -0
  190. package/skills/ck-databases/scripts/db_performance_check.py +456 -0
  191. package/skills/ck-databases/scripts/requirements.txt +20 -0
  192. package/skills/ck-databases/scripts/tests/coverage-db.json +1 -0
  193. package/skills/ck-databases/scripts/tests/requirements.txt +4 -0
  194. package/skills/ck-databases/scripts/tests/test_db_backup.py +340 -0
  195. package/skills/ck-databases/scripts/tests/test_db_migrate.py +277 -0
  196. package/skills/ck-databases/scripts/tests/test_db_performance_check.py +370 -0
  197. package/skills/ck-debugging/SKILL.md +82 -0
  198. package/skills/ck-debugging/references/defense-in-depth.md +124 -0
  199. package/skills/ck-debugging/references/root-cause-tracing.md +122 -0
  200. package/skills/ck-debugging/references/systematic-debugging.md +102 -0
  201. package/skills/ck-debugging/references/verification.md +123 -0
  202. package/skills/ck-debugging/scripts/find-polluter.sh +63 -0
  203. package/skills/ck-debugging/scripts/find-polluter.test.md +102 -0
  204. package/skills/ck-devops/.env.example +76 -0
  205. package/skills/ck-devops/SKILL.md +283 -0
  206. package/skills/ck-devops/references/browser-rendering.md +305 -0
  207. package/skills/ck-devops/references/cloudflare-d1-kv.md +123 -0
  208. package/skills/ck-devops/references/cloudflare-platform.md +271 -0
  209. package/skills/ck-devops/references/cloudflare-r2-storage.md +280 -0
  210. package/skills/ck-devops/references/cloudflare-workers-advanced.md +312 -0
  211. package/skills/ck-devops/references/cloudflare-workers-apis.md +309 -0
  212. package/skills/ck-devops/references/cloudflare-workers-basics.md +418 -0
  213. package/skills/ck-devops/references/docker-basics.md +297 -0
  214. package/skills/ck-devops/references/docker-compose.md +292 -0
  215. package/skills/ck-devops/references/gcloud-platform.md +297 -0
  216. package/skills/ck-devops/references/gcloud-services.md +304 -0
  217. package/skills/ck-devops/scripts/cloudflare_deploy.py +269 -0
  218. package/skills/ck-devops/scripts/docker_optimize.py +331 -0
  219. package/skills/ck-devops/scripts/requirements.txt +20 -0
  220. package/skills/ck-devops/scripts/tests/requirements.txt +3 -0
  221. package/skills/ck-devops/scripts/tests/test_cloudflare_deploy.py +285 -0
  222. package/skills/ck-devops/scripts/tests/test_docker_optimize.py +436 -0
  223. package/skills/ck-docs-seeker/.env.example +15 -0
  224. package/skills/ck-docs-seeker/SKILL.md +96 -0
  225. package/skills/ck-docs-seeker/package.json +25 -0
  226. package/skills/ck-docs-seeker/references/advanced.md +79 -0
  227. package/skills/ck-docs-seeker/references/context7-patterns.md +68 -0
  228. package/skills/ck-docs-seeker/references/errors.md +68 -0
  229. package/skills/ck-docs-seeker/scripts/analyze-llms-txt.js +211 -0
  230. package/skills/ck-docs-seeker/scripts/detect-topic.js +172 -0
  231. package/skills/ck-docs-seeker/scripts/fetch-docs.js +213 -0
  232. package/skills/ck-docs-seeker/scripts/tests/run-tests.js +72 -0
  233. package/skills/ck-docs-seeker/scripts/tests/test-analyze-llms.js +119 -0
  234. package/skills/ck-docs-seeker/scripts/tests/test-detect-topic.js +112 -0
  235. package/skills/ck-docs-seeker/scripts/tests/test-fetch-docs.js +84 -0
  236. package/skills/ck-docs-seeker/scripts/utils/env-loader.js +94 -0
  237. package/skills/ck-docs-seeker/workflows/library-search.md +87 -0
  238. package/skills/ck-docs-seeker/workflows/repo-analysis.md +91 -0
  239. package/skills/ck-docs-seeker/workflows/topic-search.md +77 -0
  240. package/skills/ck-frontend-design/SKILL.md +79 -0
  241. package/skills/ck-frontend-design/references/analysis-best-practices.md +80 -0
  242. package/skills/ck-frontend-design/references/analysis-prompts.md +141 -0
  243. package/skills/ck-frontend-design/references/analysis-techniques.md +118 -0
  244. package/skills/ck-frontend-design/references/animejs.md +396 -0
  245. package/skills/ck-frontend-design/references/design-extraction-overview.md +71 -0
  246. package/skills/ck-frontend-design/references/extraction-best-practices.md +141 -0
  247. package/skills/ck-frontend-design/references/extraction-output-templates.md +162 -0
  248. package/skills/ck-frontend-design/references/extraction-prompts.md +127 -0
  249. package/skills/ck-frontend-design/references/technical-accessibility.md +119 -0
  250. package/skills/ck-frontend-design/references/technical-best-practices.md +97 -0
  251. package/skills/ck-frontend-design/references/technical-optimization.md +44 -0
  252. package/skills/ck-frontend-design/references/technical-overview.md +90 -0
  253. package/skills/ck-frontend-design/references/technical-workflows.md +150 -0
  254. package/skills/ck-frontend-design/references/visual-analysis-overview.md +95 -0
  255. package/skills/ck-frontend-development/SKILL.md +399 -0
  256. package/skills/ck-frontend-development/resources/common-patterns.md +331 -0
  257. package/skills/ck-frontend-development/resources/complete-examples.md +872 -0
  258. package/skills/ck-frontend-development/resources/component-patterns.md +502 -0
  259. package/skills/ck-frontend-development/resources/data-fetching.md +767 -0
  260. package/skills/ck-frontend-development/resources/file-organization.md +502 -0
  261. package/skills/ck-frontend-development/resources/loading-and-error-states.md +501 -0
  262. package/skills/ck-frontend-development/resources/performance.md +406 -0
  263. package/skills/ck-frontend-development/resources/routing-guide.md +364 -0
  264. package/skills/ck-frontend-development/resources/styling-guide.md +428 -0
  265. package/skills/ck-frontend-development/resources/typescript-standards.md +418 -0
  266. package/skills/ck-markdown-novel-viewer/SKILL.md +190 -0
  267. package/skills/ck-markdown-novel-viewer/assets/directory-browser.css +215 -0
  268. package/skills/ck-markdown-novel-viewer/assets/favicon.png +0 -0
  269. package/skills/ck-markdown-novel-viewer/assets/novel-theme.css +818 -0
  270. package/skills/ck-markdown-novel-viewer/assets/reader.js +262 -0
  271. package/skills/ck-markdown-novel-viewer/assets/template.html +80 -0
  272. package/skills/ck-markdown-novel-viewer/package.json +15 -0
  273. package/skills/ck-markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
  274. package/skills/ck-markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +272 -0
  275. package/skills/ck-markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
  276. package/skills/ck-markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
  277. package/skills/ck-markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
  278. package/skills/ck-markdown-novel-viewer/scripts/server.cjs +411 -0
  279. package/skills/ck-markdown-novel-viewer/scripts/tests/server.test.cjs +283 -0
  280. package/skills/ck-markdown-novel-viewer/tests/dashboard-assets.test.cjs +340 -0
  281. package/skills/ck-markdown-novel-viewer/tests/dashboard-renderer.test.cjs +404 -0
  282. package/skills/ck-markdown-novel-viewer/tests/http-server.test.cjs +271 -0
  283. package/skills/ck-markdown-novel-viewer/tests/run-tests.cjs +51 -0
  284. package/skills/ck-markdown-novel-viewer/tests/test-framework.cjs +154 -0
  285. package/skills/ck-markdown-novel-viewer/tests/verify-xss.cjs +90 -0
  286. package/skills/ck-mcp-builder/LICENSE.txt +202 -0
  287. package/skills/ck-mcp-builder/SKILL.md +327 -0
  288. package/skills/ck-mcp-builder/reference/evaluation.md +602 -0
  289. package/skills/ck-mcp-builder/reference/mcp_best_practices.md +915 -0
  290. package/skills/ck-mcp-builder/reference/node_mcp_server.md +916 -0
  291. package/skills/ck-mcp-builder/reference/python_mcp_server.md +752 -0
  292. package/skills/ck-mcp-builder/scripts/connections.py +151 -0
  293. package/skills/ck-mcp-builder/scripts/evaluation.py +373 -0
  294. package/skills/ck-mcp-builder/scripts/example_evaluation.xml +22 -0
  295. package/skills/ck-mcp-builder/scripts/requirements.txt +2 -0
  296. package/skills/ck-mcp-management/README.md +219 -0
  297. package/skills/ck-mcp-management/SKILL.md +209 -0
  298. package/skills/ck-mcp-management/assets/tools.json +3146 -0
  299. package/skills/ck-mcp-management/references/configuration.md +114 -0
  300. package/skills/ck-mcp-management/references/gemini-cli-integration.md +215 -0
  301. package/skills/ck-mcp-management/references/mcp-protocol.md +116 -0
  302. package/skills/ck-mcp-management/scripts/.env.example +10 -0
  303. package/skills/ck-mcp-management/scripts/cli.ts +195 -0
  304. package/skills/ck-mcp-management/scripts/dist/analyze-tools.js +70 -0
  305. package/skills/ck-mcp-management/scripts/dist/cli.js +160 -0
  306. package/skills/ck-mcp-management/scripts/dist/mcp-client.js +183 -0
  307. package/skills/ck-mcp-management/scripts/mcp-client.ts +230 -0
  308. package/skills/ck-mcp-management/scripts/package.json +20 -0
  309. package/skills/ck-mcp-management/scripts/tsconfig.json +15 -0
  310. package/skills/ck-media-processing/SKILL.md +90 -0
  311. package/skills/ck-media-processing/references/common-workflows.md +132 -0
  312. package/skills/ck-media-processing/references/ffmpeg-encoding.md +358 -0
  313. package/skills/ck-media-processing/references/ffmpeg-filters.md +503 -0
  314. package/skills/ck-media-processing/references/ffmpeg-streaming.md +403 -0
  315. package/skills/ck-media-processing/references/format-compatibility.md +375 -0
  316. package/skills/ck-media-processing/references/imagemagick-batch.md +612 -0
  317. package/skills/ck-media-processing/references/imagemagick-editing.md +623 -0
  318. package/skills/ck-media-processing/references/rmbg-background-removal.md +66 -0
  319. package/skills/ck-media-processing/references/troubleshooting.md +109 -0
  320. package/skills/ck-media-processing/scripts/README.md +111 -0
  321. package/skills/ck-media-processing/scripts/batch-remove-background.sh +124 -0
  322. package/skills/ck-media-processing/scripts/batch_resize.py +342 -0
  323. package/skills/ck-media-processing/scripts/media_convert.py +311 -0
  324. package/skills/ck-media-processing/scripts/remove-background.sh +96 -0
  325. package/skills/ck-media-processing/scripts/remove-bg-node.js +158 -0
  326. package/skills/ck-media-processing/scripts/requirements.txt +24 -0
  327. package/skills/ck-media-processing/scripts/tests/.coverage +0 -0
  328. package/skills/ck-media-processing/scripts/tests/requirements.txt +2 -0
  329. package/skills/ck-media-processing/scripts/tests/test_batch_resize.py +372 -0
  330. package/skills/ck-media-processing/scripts/tests/test_media_convert.py +259 -0
  331. package/skills/ck-media-processing/scripts/tests/test_video_optimize.py +397 -0
  332. package/skills/ck-media-processing/scripts/video_optimize.py +414 -0
  333. package/skills/ck-mobile-development/SKILL.md +210 -0
  334. package/skills/ck-mobile-development/references/mobile-android.md +604 -0
  335. package/skills/ck-mobile-development/references/mobile-best-practices.md +545 -0
  336. package/skills/ck-mobile-development/references/mobile-debugging.md +1089 -0
  337. package/skills/ck-mobile-development/references/mobile-frameworks.md +465 -0
  338. package/skills/ck-mobile-development/references/mobile-ios.md +496 -0
  339. package/skills/ck-mobile-development/references/mobile-mindset.md +544 -0
  340. package/skills/ck-payment-integration/README.md +185 -0
  341. package/skills/ck-payment-integration/SKILL.md +116 -0
  342. package/skills/ck-payment-integration/references/polar/benefits.md +396 -0
  343. package/skills/ck-payment-integration/references/polar/best-practices.md +482 -0
  344. package/skills/ck-payment-integration/references/polar/checkouts.md +266 -0
  345. package/skills/ck-payment-integration/references/polar/overview.md +184 -0
  346. package/skills/ck-payment-integration/references/polar/products.md +244 -0
  347. package/skills/ck-payment-integration/references/polar/sdk.md +436 -0
  348. package/skills/ck-payment-integration/references/polar/subscriptions.md +340 -0
  349. package/skills/ck-payment-integration/references/polar/webhooks.md +405 -0
  350. package/skills/ck-payment-integration/references/sepay/api.md +140 -0
  351. package/skills/ck-payment-integration/references/sepay/best-practices.md +337 -0
  352. package/skills/ck-payment-integration/references/sepay/overview.md +138 -0
  353. package/skills/ck-payment-integration/references/sepay/qr-codes.md +228 -0
  354. package/skills/ck-payment-integration/references/sepay/sdk.md +213 -0
  355. package/skills/ck-payment-integration/references/sepay/webhooks.md +208 -0
  356. package/skills/ck-payment-integration/scripts/.env.example +20 -0
  357. package/skills/ck-payment-integration/scripts/checkout-helper.js +244 -0
  358. package/skills/ck-payment-integration/scripts/package.json +17 -0
  359. package/skills/ck-payment-integration/scripts/polar-webhook-verify.js +202 -0
  360. package/skills/ck-payment-integration/scripts/sepay-webhook-verify.js +193 -0
  361. package/skills/ck-payment-integration/scripts/test-scripts.js +237 -0
  362. package/skills/ck-planning/SKILL.md +112 -0
  363. package/skills/ck-planning/references/codebase-understanding.md +62 -0
  364. package/skills/ck-planning/references/output-standards.md +127 -0
  365. package/skills/ck-planning/references/plan-organization.md +150 -0
  366. package/skills/ck-planning/references/research-phase.md +49 -0
  367. package/skills/ck-planning/references/solution-design.md +63 -0
  368. package/skills/ck-problem-solving/SKILL.md +95 -0
  369. package/skills/ck-problem-solving/references/attribution.md +69 -0
  370. package/skills/ck-problem-solving/references/collision-zone-thinking.md +79 -0
  371. package/skills/ck-problem-solving/references/inversion-exercise.md +91 -0
  372. package/skills/ck-problem-solving/references/meta-pattern-recognition.md +87 -0
  373. package/skills/ck-problem-solving/references/scale-game.md +95 -0
  374. package/skills/ck-problem-solving/references/simplification-cascades.md +80 -0
  375. package/skills/ck-problem-solving/references/when-stuck.md +72 -0
  376. package/skills/ck-repomix/SKILL.md +247 -0
  377. package/skills/ck-repomix/references/configuration.md +211 -0
  378. package/skills/ck-repomix/references/usage-patterns.md +232 -0
  379. package/skills/ck-repomix/scripts/.coverage +0 -0
  380. package/skills/ck-repomix/scripts/README.md +179 -0
  381. package/skills/ck-repomix/scripts/repomix_batch.py +455 -0
  382. package/skills/ck-repomix/scripts/repos.example.json +15 -0
  383. package/skills/ck-repomix/scripts/requirements.txt +15 -0
  384. package/skills/ck-repomix/scripts/tests/test_repomix_batch.py +531 -0
  385. package/skills/ck-sequential-thinking/.env.example +8 -0
  386. package/skills/ck-sequential-thinking/README.md +183 -0
  387. package/skills/{sequential-thinking → ck-sequential-thinking}/SKILL.md +14 -2
  388. package/skills/ck-sequential-thinking/package.json +31 -0
  389. package/skills/ck-sequential-thinking/references/advanced-strategies.md +79 -0
  390. package/skills/{sequential-thinking → ck-sequential-thinking}/references/advanced-techniques.md +2 -14
  391. package/skills/{sequential-thinking → ck-sequential-thinking}/references/core-patterns.md +8 -0
  392. package/skills/ck-sequential-thinking/references/examples-api.md +88 -0
  393. package/skills/ck-sequential-thinking/references/examples-architecture.md +94 -0
  394. package/skills/ck-sequential-thinking/references/examples-debug.md +90 -0
  395. package/skills/ck-sequential-thinking/scripts/format-thought.js +159 -0
  396. package/skills/ck-sequential-thinking/scripts/process-thought.js +236 -0
  397. package/skills/ck-sequential-thinking/tests/format-thought.test.js +133 -0
  398. package/skills/ck-sequential-thinking/tests/process-thought.test.js +215 -0
  399. package/skills/ck-shopify/README.md +66 -0
  400. package/skills/ck-shopify/SKILL.md +319 -0
  401. package/skills/ck-shopify/references/app-development.md +470 -0
  402. package/skills/ck-shopify/references/extensions.md +493 -0
  403. package/skills/ck-shopify/references/themes.md +498 -0
  404. package/skills/ck-shopify/scripts/.coverage +0 -0
  405. package/skills/ck-shopify/scripts/requirements.txt +19 -0
  406. package/skills/ck-shopify/scripts/shopify_init.py +423 -0
  407. package/skills/ck-shopify/scripts/tests/.coverage +0 -0
  408. package/skills/ck-shopify/scripts/tests/test_shopify_init.py +385 -0
  409. package/skills/ck-skill-creator/LICENSE.txt +202 -0
  410. package/skills/ck-skill-creator/SKILL.md +265 -0
  411. package/skills/ck-skill-creator/scripts/init_skill.py +303 -0
  412. package/skills/ck-skill-creator/scripts/package_skill.py +110 -0
  413. package/skills/ck-skill-creator/scripts/quick_validate.py +65 -0
  414. package/skills/ck-threejs/SKILL.md +87 -0
  415. package/skills/ck-threejs/references/01-getting-started.md +177 -0
  416. package/skills/ck-threejs/references/02-loaders.md +169 -0
  417. package/skills/ck-threejs/references/03-textures.md +170 -0
  418. package/skills/ck-threejs/references/04-cameras.md +195 -0
  419. package/skills/ck-threejs/references/05-lights.md +183 -0
  420. package/skills/ck-threejs/references/06-animations.md +214 -0
  421. package/skills/ck-threejs/references/07-math.md +260 -0
  422. package/skills/ck-threejs/references/08-interaction.md +267 -0
  423. package/skills/ck-threejs/references/09-postprocessing.md +240 -0
  424. package/skills/ck-threejs/references/10-controls.md +259 -0
  425. package/skills/ck-threejs/references/11-materials-advanced.md +270 -0
  426. package/skills/ck-threejs/references/12-performance.md +269 -0
  427. package/skills/ck-threejs/references/13-node-materials.md +298 -0
  428. package/skills/ck-threejs/references/14-physics-vr.md +304 -0
  429. package/skills/ck-threejs/references/15-specialized-loaders.md +333 -0
  430. package/skills/ck-threejs/references/16-webgpu.md +302 -0
  431. package/skills/ck-ui-styling/LICENSE.txt +202 -0
  432. package/skills/ck-ui-styling/SKILL.md +319 -0
  433. package/skills/ck-ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  434. package/skills/ck-ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  435. package/skills/ck-ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  436. package/skills/ck-ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  437. package/skills/ck-ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  438. package/skills/ck-ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  439. package/skills/ck-ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  440. package/skills/ck-ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  441. package/skills/ck-ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  442. package/skills/ck-ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  443. package/skills/ck-ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  444. package/skills/ck-ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  445. package/skills/ck-ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  446. package/skills/ck-ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  447. package/skills/ck-ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  448. package/skills/ck-ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  449. package/skills/ck-ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  450. package/skills/ck-ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  451. package/skills/ck-ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  452. package/skills/ck-ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  453. package/skills/ck-ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  454. package/skills/ck-ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  455. package/skills/ck-ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  456. package/skills/ck-ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  457. package/skills/ck-ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  458. package/skills/ck-ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  459. package/skills/ck-ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  460. package/skills/ck-ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  461. package/skills/ck-ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  462. package/skills/ck-ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  463. package/skills/ck-ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  464. package/skills/ck-ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  465. package/skills/ck-ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  466. package/skills/ck-ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  467. package/skills/ck-ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  468. package/skills/ck-ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  469. package/skills/ck-ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  470. package/skills/ck-ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  471. package/skills/ck-ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  472. package/skills/ck-ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  473. package/skills/ck-ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  474. package/skills/ck-ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  475. package/skills/ck-ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  476. package/skills/ck-ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  477. package/skills/ck-ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  478. package/skills/ck-ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  479. package/skills/ck-ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  480. package/skills/ck-ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  481. package/skills/ck-ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  482. package/skills/ck-ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  483. package/skills/ck-ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  484. package/skills/ck-ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  485. package/skills/ck-ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  486. package/skills/ck-ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  487. package/skills/ck-ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  488. package/skills/ck-ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  489. package/skills/ck-ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  490. package/skills/ck-ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  491. package/skills/ck-ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  492. package/skills/ck-ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  493. package/skills/ck-ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  494. package/skills/ck-ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  495. package/skills/ck-ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  496. package/skills/ck-ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  497. package/skills/ck-ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  498. package/skills/ck-ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  499. package/skills/ck-ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  500. package/skills/ck-ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  501. package/skills/ck-ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  502. package/skills/ck-ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  503. package/skills/ck-ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  504. package/skills/ck-ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  505. package/skills/ck-ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  506. package/skills/ck-ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  507. package/skills/ck-ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  508. package/skills/ck-ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  509. package/skills/ck-ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  510. package/skills/ck-ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  511. package/skills/ck-ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  512. package/skills/ck-ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  513. package/skills/ck-ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  514. package/skills/ck-ui-styling/references/canvas-design-system.md +320 -0
  515. package/skills/ck-ui-styling/references/shadcn-accessibility.md +471 -0
  516. package/skills/ck-ui-styling/references/shadcn-components.md +424 -0
  517. package/skills/ck-ui-styling/references/shadcn-theming.md +373 -0
  518. package/skills/ck-ui-styling/references/tailwind-customization.md +483 -0
  519. package/skills/ck-ui-styling/references/tailwind-responsive.md +382 -0
  520. package/skills/ck-ui-styling/references/tailwind-utilities.md +455 -0
  521. package/skills/ck-ui-styling/scripts/.coverage +0 -0
  522. package/skills/ck-ui-styling/scripts/requirements.txt +17 -0
  523. package/skills/ck-ui-styling/scripts/shadcn_add.py +292 -0
  524. package/skills/ck-ui-styling/scripts/tailwind_config_gen.py +456 -0
  525. package/skills/ck-ui-styling/scripts/tests/coverage-ui.json +1 -0
  526. package/skills/ck-ui-styling/scripts/tests/requirements.txt +3 -0
  527. package/skills/ck-ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  528. package/skills/ck-ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -0
  529. package/skills/ck-ui-ux-pro-max/SKILL.md +227 -0
  530. package/skills/ck-ui-ux-pro-max/data/charts.csv +26 -0
  531. package/skills/ck-ui-ux-pro-max/data/colors.csv +97 -0
  532. package/skills/ck-ui-ux-pro-max/data/landing.csv +31 -0
  533. package/skills/ck-ui-ux-pro-max/data/products.csv +97 -0
  534. package/skills/ck-ui-ux-pro-max/data/prompts.csv +24 -0
  535. package/skills/ck-ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  536. package/skills/ck-ui-ux-pro-max/data/stacks/html-tailwind.csv +51 -0
  537. package/skills/ck-ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  538. package/skills/ck-ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  539. package/skills/ck-ui-ux-pro-max/data/stacks/react.csv +54 -0
  540. package/skills/ck-ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  541. package/skills/ck-ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  542. package/skills/ck-ui-ux-pro-max/data/stacks/vue.csv +50 -0
  543. package/skills/ck-ui-ux-pro-max/data/styles.csv +59 -0
  544. package/skills/ck-ui-ux-pro-max/data/typography.csv +58 -0
  545. package/skills/ck-ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  546. package/skills/ck-ui-ux-pro-max/scripts/core.py +236 -0
  547. package/skills/ck-ui-ux-pro-max/scripts/search.py +76 -0
  548. package/skills/ck-web-frameworks/SKILL.md +322 -0
  549. package/skills/ck-web-frameworks/references/nextjs-app-router.md +465 -0
  550. package/skills/ck-web-frameworks/references/nextjs-data-fetching.md +459 -0
  551. package/skills/ck-web-frameworks/references/nextjs-optimization.md +511 -0
  552. package/skills/ck-web-frameworks/references/nextjs-server-components.md +495 -0
  553. package/skills/ck-web-frameworks/references/remix-icon-integration.md +603 -0
  554. package/skills/ck-web-frameworks/references/turborepo-caching.md +551 -0
  555. package/skills/ck-web-frameworks/references/turborepo-pipelines.md +517 -0
  556. package/skills/ck-web-frameworks/references/turborepo-setup.md +542 -0
  557. package/skills/ck-web-frameworks/scripts/.coverage +0 -0
  558. package/skills/ck-web-frameworks/scripts/__init__.py +0 -0
  559. package/skills/ck-web-frameworks/scripts/nextjs_init.py +547 -0
  560. package/skills/ck-web-frameworks/scripts/requirements.txt +16 -0
  561. package/skills/ck-web-frameworks/scripts/tests/coverage-web.json +1 -0
  562. package/skills/ck-web-frameworks/scripts/tests/requirements.txt +3 -0
  563. package/skills/ck-web-frameworks/scripts/tests/test_nextjs_init.py +319 -0
  564. package/skills/ck-web-frameworks/scripts/tests/test_turborepo_migrate.py +374 -0
  565. package/skills/ck-web-frameworks/scripts/turborepo_migrate.py +394 -0
  566. package/src/commands/init.js +62 -31
  567. package/src/utils/paths.js +35 -4
  568. package/skills/code-review/SKILL.md +0 -86
  569. package/skills/code-review/references/code-review-reception.md +0 -76
  570. package/skills/code-review/references/verification-before-completion.md +0 -86
  571. package/skills/debugging/SKILL.md +0 -70
  572. package/skills/debugging/references/root-cause-tracing.md +0 -65
  573. package/skills/debugging/references/systematic-debugging.md +0 -74
  574. package/skills/debugging/references/verification.md +0 -74
  575. package/skills/docs-seeker/SKILL.md +0 -91
  576. package/skills/planning/SKILL.md +0 -82
  577. package/skills/planning/references/plan-organization.md +0 -88
  578. package/skills/planning/references/research-phase.md +0 -56
  579. package/skills/planning/references/solution-design.md +0 -65
  580. package/templates/repo/prompts/code.prompt.md +0 -40
  581. package/templates/repo/prompts/docs.prompt.md +0 -29
  582. package/templates/repo/prompts/fix.prompt.md +0 -35
  583. package/templates/repo/prompts/plan.prompt.md +0 -41
  584. package/templates/repo/prompts/review.prompt.md +0 -38
  585. package/templates/repo/prompts/test.prompt.md +0 -29
  586. /package/skills/{docs-seeker → ck-docs-seeker}/references/search-patterns.md +0 -0
  587. /package/skills/{docs-seeker → ck-docs-seeker}/references/source-evaluation.md +0 -0
  588. /package/templates/repo/.github/instructions/{backend.instructions.md → ck-backend.instructions.md} +0 -0
  589. /package/templates/repo/.github/instructions/{development.instructions.md → ck-development.instructions.md} +0 -0
  590. /package/templates/repo/.github/instructions/{frontend.instructions.md → ck-frontend.instructions.md} +0 -0
  591. /package/templates/repo/.github/instructions/{testing.instructions.md → ck-testing.instructions.md} +0 -0
  592. /package/templates/repo/.github/prompts/{code.prompt.md → ck-code.prompt.md} +0 -0
  593. /package/templates/repo/.github/prompts/{docs.prompt.md → ck-docs.prompt.md} +0 -0
  594. /package/templates/repo/.github/prompts/{fix.prompt.md → ck-fix.prompt.md} +0 -0
  595. /package/templates/repo/.github/prompts/{plan.prompt.md → ck-plan.prompt.md} +0 -0
  596. /package/templates/repo/.github/prompts/{review.prompt.md → ck-review.prompt.md} +0 -0
  597. /package/templates/repo/.github/prompts/{test.prompt.md → ck-test.prompt.md} +0 -0
  598. /package/templates/repo/.github/skills/{code-review → ck-code-review}/SKILL.md +0 -0
  599. /package/templates/repo/.github/skills/{debugging → ck-debugging}/SKILL.md +0 -0
@@ -0,0 +1,411 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Markdown Novel Viewer Server
5
+ * Background HTTP server rendering markdown files with calm, book-like UI
6
+ *
7
+ * Universal viewer - pass ANY path and view it:
8
+ * - Markdown files → novel-reader UI
9
+ * - Directories → file listing browser
10
+ *
11
+ * Usage:
12
+ * node server.cjs --file ./plan.md [--port 3456] [--no-open] [--stop] [--host 0.0.0.0]
13
+ * node server.cjs --dir ./plans [--port 3456] # Browse directory
14
+ *
15
+ * Options:
16
+ * --file <path> Path to markdown file
17
+ * --dir <path> Path to directory (browse mode)
18
+ * --port <number> Server port (default: 3456, auto-increment if busy)
19
+ * --host <addr> Host to bind (default: localhost, use 0.0.0.0 for all interfaces)
20
+ * --no-open Disable auto-open browser (opens by default)
21
+ * --stop Stop all running servers
22
+ * --background Run in background (detached) - legacy mode
23
+ * --foreground Run in foreground (for CC background tasks)
24
+ */
25
+
26
+ const fs = require('fs');
27
+ const path = require('path');
28
+ const os = require('os');
29
+ const { spawn, execSync } = require('child_process');
30
+
31
+ const { findAvailablePort, DEFAULT_PORT } = require('./lib/port-finder.cjs');
32
+ const { writePidFile, stopAllServers, setupShutdownHandlers, findRunningInstances } = require('./lib/process-mgr.cjs');
33
+ const { createHttpServer } = require('./lib/http-server.cjs');
34
+ const { renderMarkdownFile, renderTOCHtml } = require('./lib/markdown-renderer.cjs');
35
+ const { generateNavSidebar, generateNavFooter, detectPlan, getNavigationContext } = require('./lib/plan-navigator.cjs');
36
+
37
+ /**
38
+ * Parse command line arguments
39
+ */
40
+ function parseArgs(argv) {
41
+ const args = {
42
+ file: null,
43
+ dir: null,
44
+ port: DEFAULT_PORT,
45
+ host: 'localhost',
46
+ open: true, // Auto-open browser by default
47
+ stop: false,
48
+ background: false,
49
+ foreground: false,
50
+ isChild: false
51
+ };
52
+
53
+ for (let i = 2; i < argv.length; i++) {
54
+ const arg = argv[i];
55
+ if (arg === '--file' && argv[i + 1]) {
56
+ args.file = argv[++i];
57
+ } else if (arg === '--dir' && argv[i + 1]) {
58
+ args.dir = argv[++i];
59
+ } else if (arg === '--port' && argv[i + 1]) {
60
+ args.port = parseInt(argv[++i], 10);
61
+ } else if (arg === '--host' && argv[i + 1]) {
62
+ args.host = argv[++i];
63
+ } else if (arg === '--open') {
64
+ args.open = true;
65
+ } else if (arg === '--no-open') {
66
+ args.open = false;
67
+ } else if (arg === '--stop') {
68
+ args.stop = true;
69
+ } else if (arg === '--background') {
70
+ args.background = true;
71
+ } else if (arg === '--foreground') {
72
+ args.foreground = true;
73
+ } else if (arg === '--child') {
74
+ args.isChild = true;
75
+ } else if (!arg.startsWith('--') && !args.file && !args.dir) {
76
+ // Positional argument - could be file or directory
77
+ args.file = arg;
78
+ }
79
+ }
80
+
81
+ return args;
82
+ }
83
+
84
+ /**
85
+ * Resolve input path - simple logic, no smart detection
86
+ * @param {string} input - Input path
87
+ * @param {string} cwd - Current working directory
88
+ * @returns {{type: 'file'|'directory'|null, path: string|null}}
89
+ */
90
+ function resolveInput(input, cwd) {
91
+ if (!input) return { type: null, path: null };
92
+
93
+ // Resolve relative to CWD
94
+ const resolved = path.isAbsolute(input) ? input : path.resolve(cwd, input);
95
+
96
+ if (!fs.existsSync(resolved)) {
97
+ return { type: null, path: null };
98
+ }
99
+
100
+ const stats = fs.statSync(resolved);
101
+
102
+ // File mode
103
+ if (stats.isFile()) {
104
+ return { type: 'file', path: resolved };
105
+ }
106
+
107
+ // Directory mode - browse, no auto-detection of plan.md
108
+ if (stats.isDirectory()) {
109
+ return { type: 'directory', path: resolved };
110
+ }
111
+
112
+ return { type: null, path: null };
113
+ }
114
+
115
+ /**
116
+ * Open browser with URL
117
+ */
118
+ function openBrowser(url) {
119
+ const platform = process.platform;
120
+ let cmd;
121
+
122
+ if (platform === 'darwin') {
123
+ cmd = `open "${url}"`;
124
+ } else if (platform === 'win32') {
125
+ // On Windows, start command treats first quoted arg as window title
126
+ // Use empty title "" before the URL to prevent this
127
+ cmd = `start "" "${url}"`;
128
+ } else {
129
+ cmd = `xdg-open "${url}"`;
130
+ }
131
+
132
+ try {
133
+ execSync(cmd, { stdio: 'ignore' });
134
+ } catch {
135
+ // Ignore browser open errors
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Generate full HTML page from markdown
141
+ */
142
+ function generateFullPage(filePath, assetsDir) {
143
+ const { html, toc, frontmatter, title } = renderMarkdownFile(filePath);
144
+ const tocHtml = renderTOCHtml(toc);
145
+ const navSidebar = generateNavSidebar(filePath);
146
+ const navFooter = generateNavFooter(filePath);
147
+ const planInfo = detectPlan(filePath);
148
+ const navContext = getNavigationContext(filePath);
149
+
150
+ // Read template
151
+ const templatePath = path.join(assetsDir, 'template.html');
152
+ let template = fs.readFileSync(templatePath, 'utf8');
153
+
154
+ // Generate back button (links to parent directory browser)
155
+ const parentDir = path.dirname(filePath);
156
+ const backButton = `
157
+ <a href="/browse?dir=${encodeURIComponent(parentDir)}" class="icon-btn back-btn" title="Back to folder">
158
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
159
+ <path d="M19 12H5M12 19l-7-7 7-7"/>
160
+ </svg>
161
+ </a>`;
162
+
163
+ // Generate header nav (prev/next) for plan files
164
+ let headerNav = '';
165
+ if (navContext.prev || navContext.next) {
166
+ const prevBtn = navContext.prev && fs.existsSync(navContext.prev.file)
167
+ ? `<a href="/view?file=${encodeURIComponent(navContext.prev.file)}" class="header-nav-btn prev" title="${navContext.prev.name}">
168
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg>
169
+ <span>Prev</span>
170
+ </a>`
171
+ : '';
172
+ const nextBtn = navContext.next && fs.existsSync(navContext.next.file)
173
+ ? `<a href="/view?file=${encodeURIComponent(navContext.next.file)}" class="header-nav-btn next" title="${navContext.next.name}">
174
+ <span>Next</span>
175
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
176
+ </a>`
177
+ : '';
178
+ headerNav = `<div class="header-nav">${prevBtn}${nextBtn}</div>`;
179
+ }
180
+
181
+ // Replace placeholders
182
+ template = template
183
+ .replace(/\{\{title\}\}/g, title)
184
+ .replace('{{toc}}', tocHtml)
185
+ .replace('{{nav-sidebar}}', navSidebar)
186
+ .replace('{{nav-footer}}', navFooter)
187
+ .replace('{{content}}', html)
188
+ .replace('{{has-plan}}', planInfo.isPlan ? 'has-plan' : '')
189
+ .replace('{{frontmatter}}', JSON.stringify(frontmatter || {}))
190
+ .replace('{{back-button}}', backButton)
191
+ .replace('{{header-nav}}', headerNav);
192
+
193
+ return template;
194
+ }
195
+
196
+ /**
197
+ * Get local network IP address for remote access
198
+ * @returns {string|null} - Local IP or null if not found
199
+ */
200
+ function getLocalIP() {
201
+ const interfaces = os.networkInterfaces();
202
+ for (const name of Object.keys(interfaces)) {
203
+ for (const iface of interfaces[name]) {
204
+ // Skip internal (loopback) and non-IPv4 addresses
205
+ if (iface.family === 'IPv4' && !iface.internal) {
206
+ return iface.address;
207
+ }
208
+ }
209
+ }
210
+ return null;
211
+ }
212
+
213
+ /**
214
+ * Build URL with query parameters (fixes path conflicts)
215
+ * @returns {{url: string, networkUrl: string|null}} - Local and network URLs
216
+ */
217
+ function buildUrl(host, port, type, filePath) {
218
+ const displayHost = host === '0.0.0.0' ? 'localhost' : host;
219
+ const baseUrl = `http://${displayHost}:${port}`;
220
+
221
+ let urlPath = '';
222
+ if (type === 'file') {
223
+ urlPath = `/view?file=${encodeURIComponent(filePath)}`;
224
+ } else if (type === 'directory') {
225
+ urlPath = `/browse?dir=${encodeURIComponent(filePath)}`;
226
+ }
227
+
228
+ const url = baseUrl + urlPath;
229
+
230
+ // If binding to all interfaces, provide network URL for remote access
231
+ let networkUrl = null;
232
+ if (host === '0.0.0.0') {
233
+ const localIP = getLocalIP();
234
+ if (localIP) {
235
+ networkUrl = `http://${localIP}:${port}${urlPath}`;
236
+ }
237
+ }
238
+
239
+ return { url, networkUrl };
240
+ }
241
+
242
+ /**
243
+ * Main function
244
+ */
245
+ async function main() {
246
+ const args = parseArgs(process.argv);
247
+ const cwd = process.cwd();
248
+ const assetsDir = path.join(__dirname, '..', 'assets');
249
+
250
+ // Handle --stop
251
+ if (args.stop) {
252
+ const instances = findRunningInstances();
253
+ if (instances.length === 0) {
254
+ console.log('No server running to stop');
255
+ process.exit(0);
256
+ }
257
+ const stopped = stopAllServers();
258
+ console.log(`Stopped ${stopped} server(s)`);
259
+ process.exit(0);
260
+ }
261
+
262
+ // Determine input
263
+ const input = args.dir || args.file;
264
+
265
+ // Validate input
266
+ if (!input) {
267
+ console.error('Error: --file or --dir argument required');
268
+ console.error('Usage:');
269
+ console.error(' node server.cjs --file <path.md> [--port 3456] [--open]');
270
+ console.error(' node server.cjs --dir <path> [--port 3456] [--open] # Browse directory');
271
+ process.exit(1);
272
+ }
273
+
274
+ // Resolve input path - simple logic
275
+ let resolved = resolveInput(input, cwd);
276
+
277
+ // If --dir was explicitly used, force directory mode
278
+ if (args.dir && resolved.type === null) {
279
+ const dirPath = path.isAbsolute(args.dir) ? args.dir : path.resolve(cwd, args.dir);
280
+ if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
281
+ resolved = { type: 'directory', path: dirPath };
282
+ }
283
+ }
284
+
285
+ if (resolved.type === null) {
286
+ console.error(`Error: Invalid path: ${input}`);
287
+ console.error('Path must be a file or directory.');
288
+ process.exit(1);
289
+ }
290
+
291
+ // Background mode - spawn child and exit (legacy mode for manual runs)
292
+ // Skip if --foreground is set (for Claude Code background tasks)
293
+ if (args.background && !args.foreground && !args.isChild) {
294
+ const childArgs = ['--port', String(args.port), '--host', args.host, '--child'];
295
+ if (resolved.type === 'file') {
296
+ childArgs.unshift('--file', resolved.path);
297
+ } else {
298
+ childArgs.unshift('--dir', resolved.path);
299
+ }
300
+ if (args.open) childArgs.push('--open');
301
+
302
+ const child = spawn(process.execPath, [__filename, ...childArgs], {
303
+ detached: true,
304
+ stdio: 'ignore',
305
+ cwd: cwd
306
+ });
307
+ child.unref();
308
+
309
+ // Wait briefly for child to start
310
+ await new Promise(r => setTimeout(r, 500));
311
+
312
+ // Find the port the child is using
313
+ const instances = findRunningInstances();
314
+ const instance = instances.find(i => i.port >= args.port);
315
+ const port = instance ? instance.port : args.port;
316
+
317
+ const { url, networkUrl } = buildUrl(args.host, port, resolved.type, resolved.path);
318
+
319
+ const result = {
320
+ success: true,
321
+ url,
322
+ path: resolved.path,
323
+ port,
324
+ host: args.host,
325
+ mode: resolved.type
326
+ };
327
+ if (networkUrl) result.networkUrl = networkUrl;
328
+
329
+ console.log(JSON.stringify(result));
330
+
331
+ process.exit(0);
332
+ }
333
+
334
+ // Find available port
335
+ const port = await findAvailablePort(args.port);
336
+ if (port !== args.port) {
337
+ console.error(`Port ${args.port} in use, using ${port}`);
338
+ }
339
+
340
+ // Determine allowed directories for security
341
+ const allowedDirs = [assetsDir, cwd];
342
+ if (resolved.path) {
343
+ const targetDir = resolved.type === 'file' ? path.dirname(resolved.path) : resolved.path;
344
+ if (!allowedDirs.includes(targetDir)) {
345
+ allowedDirs.push(targetDir);
346
+ }
347
+ }
348
+
349
+ // Create server
350
+ const server = createHttpServer({
351
+ assetsDir,
352
+ renderMarkdown: (fp) => generateFullPage(fp, assetsDir),
353
+ allowedDirs
354
+ });
355
+
356
+ // Start server
357
+ server.listen(port, args.host, () => {
358
+ const { url, networkUrl } = buildUrl(args.host, port, resolved.type, resolved.path);
359
+
360
+ // Write PID file
361
+ writePidFile(port, process.pid);
362
+
363
+ // Setup shutdown handlers
364
+ setupShutdownHandlers(port, () => {
365
+ server.close();
366
+ });
367
+
368
+ // Output for CLI/command integration
369
+ // In foreground mode (CC background task), always output JSON
370
+ if (args.foreground || args.isChild || process.env.CLAUDE_COMMAND) {
371
+ const result = {
372
+ success: true,
373
+ url,
374
+ path: resolved.path,
375
+ port,
376
+ host: args.host,
377
+ mode: resolved.type
378
+ };
379
+ if (networkUrl) result.networkUrl = networkUrl;
380
+ console.log(JSON.stringify(result));
381
+ } else {
382
+ console.log(`\nMarkdown Novel Viewer`);
383
+ console.log(`${'─'.repeat(40)}`);
384
+ console.log(`URL: ${url}`);
385
+ if (networkUrl) {
386
+ console.log(`Network: ${networkUrl}`);
387
+ }
388
+ console.log(`Path: ${resolved.path}`);
389
+ console.log(`Port: ${port}`);
390
+ console.log(`Host: ${args.host}`);
391
+ console.log(`Mode: ${resolved.type === 'file' ? 'File Viewer' : 'Directory Browser'}`);
392
+ console.log(`\nPress Ctrl+C to stop\n`);
393
+ }
394
+
395
+ // Open browser
396
+ if (args.open) {
397
+ openBrowser(url);
398
+ }
399
+ });
400
+
401
+ server.on('error', (err) => {
402
+ console.error(`Server error: ${err.message}`);
403
+ process.exit(1);
404
+ });
405
+ }
406
+
407
+ // Run
408
+ main().catch(err => {
409
+ console.error(`Error: ${err.message}`);
410
+ process.exit(1);
411
+ });
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Tests for markdown-novel-viewer
5
+ * Run: node scripts/tests/server.test.cjs
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const http = require('http');
11
+
12
+ const { isPortAvailable, findAvailablePort, DEFAULT_PORT } = require('../lib/port-finder.cjs');
13
+ const { writePidFile, readPidFile, removePidFile, findRunningInstances } = require('../lib/process-mgr.cjs');
14
+ const { getMimeType, MIME_TYPES, isPathSafe, sanitizeErrorMessage } = require('../lib/http-server.cjs');
15
+ const { resolveImages, addHeadingIds, generateTOC, renderTOCHtml } = require('../lib/markdown-renderer.cjs');
16
+ const { detectPlan, parsePlanTable, getNavigationContext, generateNavSidebar } = require('../lib/plan-navigator.cjs');
17
+
18
+ // Test utilities
19
+ let passed = 0;
20
+ let failed = 0;
21
+
22
+ function test(name, fn) {
23
+ try {
24
+ fn();
25
+ passed++;
26
+ console.log(` ✓ ${name}`);
27
+ } catch (err) {
28
+ failed++;
29
+ console.log(` ✗ ${name}`);
30
+ console.log(` Error: ${err.message}`);
31
+ }
32
+ }
33
+
34
+ function assertEqual(actual, expected, message) {
35
+ if (actual !== expected) {
36
+ throw new Error(`${message}: expected "${expected}", got "${actual}"`);
37
+ }
38
+ }
39
+
40
+ function assertTrue(value, message) {
41
+ if (!value) {
42
+ throw new Error(`${message}: expected truthy value`);
43
+ }
44
+ }
45
+
46
+ function assertFalse(value, message) {
47
+ if (value) {
48
+ throw new Error(`${message}: expected falsy value`);
49
+ }
50
+ }
51
+
52
+ function assertIncludes(str, substr, message) {
53
+ if (!str.includes(substr)) {
54
+ throw new Error(`${message}: expected to include "${substr}"`);
55
+ }
56
+ }
57
+
58
+ // Test suites
59
+ console.log('\n--- Port Finder Tests ---');
60
+
61
+ test('DEFAULT_PORT is 3456', () => {
62
+ assertEqual(DEFAULT_PORT, 3456, 'Default port');
63
+ });
64
+
65
+ test('isPortAvailable returns boolean', () => {
66
+ // Sync test - function exists
67
+ assertTrue(typeof isPortAvailable === 'function', 'Should be function');
68
+ });
69
+
70
+ test('findAvailablePort returns number', () => {
71
+ // Sync test - actual async behavior tested in integration
72
+ assertTrue(typeof findAvailablePort === 'function', 'Should be function');
73
+ });
74
+
75
+ console.log('\n--- Process Manager Tests ---');
76
+
77
+ test('writePidFile and readPidFile work correctly', () => {
78
+ const testPort = 9876;
79
+ const testPid = 12345;
80
+
81
+ writePidFile(testPort, testPid);
82
+ const readPid = readPidFile(testPort);
83
+ assertEqual(readPid, testPid, 'PID should match');
84
+
85
+ removePidFile(testPort);
86
+ const afterRemove = readPidFile(testPort);
87
+ assertEqual(afterRemove, null, 'Should be null after remove');
88
+ });
89
+
90
+ test('findRunningInstances returns array', () => {
91
+ const instances = findRunningInstances();
92
+ assertTrue(Array.isArray(instances), 'Should return array');
93
+ });
94
+
95
+ console.log('\n--- HTTP Server Tests ---');
96
+
97
+ test('getMimeType returns correct types', () => {
98
+ assertEqual(getMimeType('test.html'), 'text/html', 'HTML type');
99
+ assertEqual(getMimeType('test.css'), 'text/css', 'CSS type');
100
+ assertEqual(getMimeType('test.js'), 'application/javascript', 'JS type');
101
+ assertEqual(getMimeType('test.png'), 'image/png', 'PNG type');
102
+ assertEqual(getMimeType('test.jpg'), 'image/jpeg', 'JPG type');
103
+ assertEqual(getMimeType('test.unknown'), 'application/octet-stream', 'Unknown type');
104
+ });
105
+
106
+ test('MIME_TYPES has common extensions', () => {
107
+ assertTrue(MIME_TYPES['.html'], 'Has .html');
108
+ assertTrue(MIME_TYPES['.css'], 'Has .css');
109
+ assertTrue(MIME_TYPES['.js'], 'Has .js');
110
+ assertTrue(MIME_TYPES['.png'], 'Has .png');
111
+ assertTrue(MIME_TYPES['.md'], 'Has .md');
112
+ });
113
+
114
+ console.log('\n--- Security Tests ---');
115
+
116
+ test('isPathSafe blocks path traversal', () => {
117
+ assertFalse(isPathSafe('/etc/../etc/passwd', ['/home']), 'Should block .. traversal');
118
+ assertFalse(isPathSafe('/path\0/file', ['/path']), 'Should block null bytes');
119
+ });
120
+
121
+ test('isPathSafe allows valid paths', () => {
122
+ assertTrue(isPathSafe('/tmp/test.md', ['/tmp']), 'Should allow path in allowed dir');
123
+ });
124
+
125
+ test('sanitizeErrorMessage removes paths', () => {
126
+ const sanitized = sanitizeErrorMessage('Error: /etc/passwd not found');
127
+ assertFalse(sanitized.includes('/etc/passwd'), 'Should not contain path');
128
+ assertIncludes(sanitized, '[path]', 'Should replace with placeholder');
129
+ });
130
+
131
+ console.log('\n--- Markdown Renderer Tests ---');
132
+
133
+ test('resolveImages converts relative paths', () => {
134
+ const md = '![Alt](./image.png)';
135
+ const resolved = resolveImages(md, '/base/path');
136
+ assertIncludes(resolved, '/file/', 'Should include /file/ route');
137
+ assertIncludes(resolved, '/base/path', 'Should include base path');
138
+ });
139
+
140
+ test('resolveImages preserves absolute URLs', () => {
141
+ const md = '![Alt](https://example.com/image.png)';
142
+ const resolved = resolveImages(md, '/base/path');
143
+ assertEqual(resolved, md, 'Should preserve absolute URL');
144
+ });
145
+
146
+ test('resolveImages handles reference-style definitions', () => {
147
+ const md = '![Step 1 Initial]\n\n[Step 1 Initial]: ./screenshots/step1.png';
148
+ const resolved = resolveImages(md, '/base/path');
149
+ assertIncludes(resolved, '/file/', 'Should include /file/ route in ref definition');
150
+ assertIncludes(resolved, '/base/path/screenshots/step1.png', 'Should resolve relative path');
151
+ });
152
+
153
+ test('resolveImages handles reference-style with titles', () => {
154
+ const md = '[logo]: ./images/logo.png "Company Logo"';
155
+ const resolved = resolveImages(md, '/project');
156
+ assertIncludes(resolved, '/file/project/images/logo.png', 'Should resolve path with title');
157
+ });
158
+
159
+ test('resolveImages handles inline images with titles', () => {
160
+ const md = '![Alt](./image.png "Title text")';
161
+ const resolved = resolveImages(md, '/base');
162
+ assertIncludes(resolved, '/file/base/image.png', 'Should resolve inline with title');
163
+ });
164
+
165
+ test('addHeadingIds adds id attributes', () => {
166
+ const html = '<h1>Test Heading</h1><h2>Another</h2>';
167
+ const withIds = addHeadingIds(html);
168
+ assertIncludes(withIds, 'id="test-heading"', 'Should add id to h1');
169
+ assertIncludes(withIds, 'id="another"', 'Should add id to h2');
170
+ });
171
+
172
+ test('addHeadingIds handles duplicates', () => {
173
+ const html = '<h1>Test</h1><h2>Test</h2>';
174
+ const withIds = addHeadingIds(html);
175
+ assertIncludes(withIds, 'id="test"', 'Should have first id');
176
+ assertIncludes(withIds, 'id="test-1"', 'Should have unique second id');
177
+ });
178
+
179
+ test('generateTOC extracts headings', () => {
180
+ const html = '<h1 id="one">One</h1><h2 id="two">Two</h2><h3 id="three">Three</h3>';
181
+ const toc = generateTOC(html);
182
+ assertEqual(toc.length, 3, 'Should find 3 headings');
183
+ assertEqual(toc[0].level, 1, 'First should be h1');
184
+ assertEqual(toc[0].id, 'one', 'First id should be "one"');
185
+ });
186
+
187
+ test('renderTOCHtml generates list', () => {
188
+ const toc = [{ level: 1, id: 'test', text: 'Test' }];
189
+ const html = renderTOCHtml(toc);
190
+ assertIncludes(html, '<ul', 'Should have ul');
191
+ assertIncludes(html, 'href="#test"', 'Should have anchor');
192
+ assertIncludes(html, 'Test', 'Should have text');
193
+ });
194
+
195
+ test('renderTOCHtml handles empty array', () => {
196
+ const html = renderTOCHtml([]);
197
+ assertEqual(html, '', 'Should return empty string');
198
+ });
199
+
200
+ console.log('\n--- Plan Navigator Tests ---');
201
+
202
+ // Create temp plan structure for testing
203
+ const testPlanDir = '/tmp/test-novel-viewer-plan';
204
+ const testPlanFile = path.join(testPlanDir, 'plan.md');
205
+ const testPhaseFile = path.join(testPlanDir, 'phase-01-test.md');
206
+
207
+ function setupTestPlan() {
208
+ if (!fs.existsSync(testPlanDir)) {
209
+ fs.mkdirSync(testPlanDir, { recursive: true });
210
+ }
211
+
212
+ fs.writeFileSync(testPlanFile, `# Test Plan
213
+
214
+ | Phase | Name | Status | Link |
215
+ |-------|------|--------|------|
216
+ | 1 | Test Phase | Pending | [phase-01-test.md](./phase-01-test.md) |
217
+ `);
218
+
219
+ fs.writeFileSync(testPhaseFile, `# Phase 1: Test Phase
220
+
221
+ Content here.
222
+ `);
223
+ }
224
+
225
+ function cleanupTestPlan() {
226
+ if (fs.existsSync(testPlanDir)) {
227
+ fs.rmSync(testPlanDir, { recursive: true });
228
+ }
229
+ }
230
+
231
+ setupTestPlan();
232
+
233
+ test('detectPlan identifies plan directory', () => {
234
+ const result = detectPlan(testPlanFile);
235
+ assertTrue(result.isPlan, 'Should detect as plan');
236
+ assertEqual(result.planDir, testPlanDir, 'Should have correct dir');
237
+ assertTrue(result.phases.length >= 1, 'Should find phases');
238
+ });
239
+
240
+ test('detectPlan returns false for non-plan', () => {
241
+ const result = detectPlan('/tmp/random-file.md');
242
+ assertFalse(result.isPlan, 'Should not be plan');
243
+ });
244
+
245
+ test('parsePlanTable extracts phases', () => {
246
+ const phases = parsePlanTable(testPlanFile);
247
+ assertTrue(phases.length >= 1, 'Should find phases');
248
+ assertEqual(phases[0].phase, 1, 'First phase number');
249
+ assertEqual(phases[0].name, 'Test Phase', 'Phase name');
250
+ assertEqual(phases[0].status, 'pending', 'Status should be lowercase');
251
+ });
252
+
253
+ test('getNavigationContext returns correct structure', () => {
254
+ const ctx = getNavigationContext(testPlanFile);
255
+ assertTrue(ctx.planInfo.isPlan, 'Should be plan');
256
+ assertTrue(ctx.allPhases.length >= 1, 'Should have phases');
257
+ assertEqual(ctx.currentIndex, 0, 'Plan.md should be index 0');
258
+ });
259
+
260
+ test('generateNavSidebar returns HTML', () => {
261
+ const html = generateNavSidebar(testPlanFile);
262
+ assertIncludes(html, '<nav', 'Should have nav element');
263
+ assertIncludes(html, 'phase-list', 'Should have phase list');
264
+ });
265
+
266
+ test('generateNavSidebar returns empty for non-plan', () => {
267
+ const html = generateNavSidebar('/tmp/random.md');
268
+ assertEqual(html, '', 'Should return empty string');
269
+ });
270
+
271
+ cleanupTestPlan();
272
+
273
+ // Summary
274
+ console.log('\n--- Test Results ---');
275
+ console.log(`Passed: ${passed}`);
276
+ console.log(`Failed: ${failed}`);
277
+ console.log(`Total: ${passed + failed}`);
278
+
279
+ if (failed > 0) {
280
+ process.exit(1);
281
+ }
282
+
283
+ console.log('\nAll tests passed!');