@thanhvn14/csvibe 0.1.4 → 0.1.5

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 (392) hide show
  1. package/.github/agents/schemas/base-output.schema.json +88 -0
  2. package/.github/agents/schemas/brainstorm-output.schema.json +88 -0
  3. package/.github/agents/schemas/scout-output.schema.json +60 -0
  4. package/.github/agents/scripts/fetch-copilot-tools.js +245 -0
  5. package/.github/agents/scripts/lib/parse-agent-file.js +275 -0
  6. package/.github/agents/scripts/package-lock.json +78 -0
  7. package/.github/agents/scripts/package.json +22 -0
  8. package/.github/agents/scripts/schemas/agent-frontmatter.schema.json +83 -0
  9. package/.github/agents/scripts/validate-agent-all.js +157 -0
  10. package/.github/agents/scripts/validate-agent-frontmatter.js +96 -0
  11. package/.github/agents/scripts/validate-agent-handoffs.js +169 -0
  12. package/.github/agents/scripts/validate-agent-output.js +157 -0
  13. package/.github/agents/scripts/validate-agent-tools.js +278 -0
  14. package/.github/skills/.env.example +100 -0
  15. package/.github/skills/.install-state.json +23 -0
  16. package/.github/skills/README.md +149 -0
  17. package/.github/skills/ai-multimodal/.env.example +204 -0
  18. package/.github/skills/ai-multimodal/scripts/.coverage +0 -0
  19. package/.github/skills/ai-multimodal/scripts/check_setup.py +305 -0
  20. package/.github/skills/ai-multimodal/scripts/document_converter.py +395 -0
  21. package/.github/skills/ai-multimodal/scripts/gemini_batch_process.py +1184 -0
  22. package/.github/skills/ai-multimodal/scripts/media_optimizer.py +506 -0
  23. package/.github/skills/ai-multimodal/scripts/requirements.txt +26 -0
  24. package/.github/skills/better-auth/scripts/.coverage +0 -0
  25. package/.github/skills/better-auth/scripts/better_auth_init.py +521 -0
  26. package/.github/skills/better-auth/scripts/requirements.txt +15 -0
  27. package/.github/skills/chrome-devtools/scripts/README.md +272 -0
  28. package/.github/skills/chrome-devtools/scripts/__tests__/selector.test.js +210 -0
  29. package/.github/skills/chrome-devtools/scripts/aria-snapshot.js +362 -0
  30. package/.github/skills/chrome-devtools/scripts/click.js +83 -0
  31. package/.github/skills/chrome-devtools/scripts/console.js +79 -0
  32. package/.github/skills/chrome-devtools/scripts/evaluate.js +53 -0
  33. package/.github/skills/chrome-devtools/scripts/fill.js +76 -0
  34. package/.github/skills/chrome-devtools/scripts/inject-auth.js +229 -0
  35. package/.github/skills/chrome-devtools/scripts/install-deps.sh +181 -0
  36. package/.github/skills/chrome-devtools/scripts/install.sh +83 -0
  37. package/.github/skills/chrome-devtools/scripts/lib/browser.js +318 -0
  38. package/.github/skills/chrome-devtools/scripts/lib/selector.js +178 -0
  39. package/.github/skills/chrome-devtools/scripts/navigate.js +54 -0
  40. package/.github/skills/chrome-devtools/scripts/network.js +106 -0
  41. package/.github/skills/chrome-devtools/scripts/package-lock.json +1589 -0
  42. package/.github/skills/chrome-devtools/scripts/package.json +16 -0
  43. package/.github/skills/chrome-devtools/scripts/performance.js +149 -0
  44. package/.github/skills/chrome-devtools/scripts/screenshot.js +198 -0
  45. package/.github/skills/chrome-devtools/scripts/select-ref.js +131 -0
  46. package/.github/skills/chrome-devtools/scripts/snapshot.js +135 -0
  47. package/.github/skills/common/README.md +120 -0
  48. package/.github/skills/common/api_key_helper.py +411 -0
  49. package/.github/skills/common/api_key_rotator.py +248 -0
  50. package/.github/skills/databases/scripts/.coverage +0 -0
  51. package/.github/skills/databases/scripts/db_backup.py +502 -0
  52. package/.github/skills/databases/scripts/db_migrate.py +425 -0
  53. package/.github/skills/databases/scripts/db_performance_check.py +456 -0
  54. package/.github/skills/databases/scripts/requirements.txt +20 -0
  55. package/.github/skills/debugging/scripts/find-polluter.sh +63 -0
  56. package/.github/skills/devops/.env.example +76 -0
  57. package/.github/skills/devops/scripts/cloudflare_deploy.py +269 -0
  58. package/.github/skills/devops/scripts/docker_optimize.py +331 -0
  59. package/.github/skills/devops/scripts/requirements.txt +20 -0
  60. package/.github/skills/docs-seeker/.env.example +15 -0
  61. package/.github/skills/docs-seeker/package.json +25 -0
  62. package/.github/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
  63. package/.github/skills/docs-seeker/scripts/detect-topic.js +172 -0
  64. package/.github/skills/docs-seeker/scripts/fetch-docs.js +213 -0
  65. package/.github/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
  66. package/.github/skills/document-skills/docx/LICENSE.txt +30 -0
  67. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  68. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  69. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  70. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  71. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  72. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  73. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  74. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  75. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  76. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  77. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  78. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  79. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  80. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  81. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  82. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  83. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  84. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  85. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  86. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  87. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  88. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  89. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  90. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  91. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  92. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  93. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  94. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  95. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  96. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  97. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  98. package/.github/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  99. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  100. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  101. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  102. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  103. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  104. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  105. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  106. package/.github/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
  107. package/.github/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
  108. package/.github/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
  109. package/.github/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  110. package/.github/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
  111. package/.github/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
  112. package/.github/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  113. package/.github/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  114. package/.github/skills/document-skills/docx/scripts/__init__.py +1 -0
  115. package/.github/skills/document-skills/docx/scripts/document.py +1276 -0
  116. package/.github/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
  117. package/.github/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
  118. package/.github/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  119. package/.github/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
  120. package/.github/skills/document-skills/docx/scripts/templates/people.xml +3 -0
  121. package/.github/skills/document-skills/docx/scripts/utilities.py +374 -0
  122. package/.github/skills/document-skills/pdf/LICENSE.txt +30 -0
  123. package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
  124. package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  125. package/.github/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
  126. package/.github/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  127. package/.github/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
  128. package/.github/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
  129. package/.github/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
  130. package/.github/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  131. package/.github/skills/document-skills/pptx/LICENSE.txt +30 -0
  132. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  133. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  134. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  135. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  136. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  137. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  138. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  139. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  140. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  141. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  142. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  143. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  144. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  145. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  146. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  147. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  148. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  149. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  150. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  151. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  152. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  153. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  154. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  155. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  156. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  157. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  158. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  159. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  160. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  161. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  162. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  163. package/.github/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  164. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  165. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  166. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  167. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  168. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  169. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  170. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  171. package/.github/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
  172. package/.github/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
  173. package/.github/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
  174. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  175. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
  176. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  177. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  178. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  179. package/.github/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
  180. package/.github/skills/document-skills/pptx/scripts/inventory.py +1020 -0
  181. package/.github/skills/document-skills/pptx/scripts/rearrange.py +231 -0
  182. package/.github/skills/document-skills/pptx/scripts/replace.py +385 -0
  183. package/.github/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
  184. package/.github/skills/document-skills/xlsx/LICENSE.txt +30 -0
  185. package/.github/skills/document-skills/xlsx/recalc.py +190 -0
  186. package/.github/skills/install.ps1 +1220 -0
  187. package/.github/skills/install.sh +1032 -0
  188. package/.github/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
  189. package/.github/skills/markdown-novel-viewer/assets/favicon.png +0 -0
  190. package/.github/skills/markdown-novel-viewer/assets/novel-theme.css +818 -0
  191. package/.github/skills/markdown-novel-viewer/assets/reader.js +262 -0
  192. package/.github/skills/markdown-novel-viewer/assets/template.html +80 -0
  193. package/.github/skills/markdown-novel-viewer/package-lock.json +146 -0
  194. package/.github/skills/markdown-novel-viewer/package.json +15 -0
  195. package/.github/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
  196. package/.github/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +272 -0
  197. package/.github/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
  198. package/.github/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
  199. package/.github/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
  200. package/.github/skills/markdown-novel-viewer/scripts/server.cjs +411 -0
  201. package/.github/skills/mcp-builder/LICENSE.txt +202 -0
  202. package/.github/skills/mcp-builder/scripts/connections.py +151 -0
  203. package/.github/skills/mcp-builder/scripts/evaluation.py +373 -0
  204. package/.github/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  205. package/.github/skills/mcp-builder/scripts/requirements.txt +2 -0
  206. package/.github/skills/mcp-management/README.md +219 -0
  207. package/.github/skills/mcp-management/assets/tools.json +3146 -0
  208. package/.github/skills/mcp-management/package-lock.json +6 -0
  209. package/.github/skills/mcp-management/scripts/.env.example +10 -0
  210. package/.github/skills/mcp-management/scripts/cli.ts +195 -0
  211. package/.github/skills/mcp-management/scripts/dist/analyze-tools.js +70 -0
  212. package/.github/skills/mcp-management/scripts/dist/cli.js +160 -0
  213. package/.github/skills/mcp-management/scripts/dist/mcp-client.js +183 -0
  214. package/.github/skills/mcp-management/scripts/mcp-client.ts +230 -0
  215. package/.github/skills/mcp-management/scripts/package.json +20 -0
  216. package/.github/skills/media-processing/scripts/README.md +111 -0
  217. package/.github/skills/media-processing/scripts/batch-remove-background.sh +124 -0
  218. package/.github/skills/media-processing/scripts/batch_resize.py +342 -0
  219. package/.github/skills/media-processing/scripts/media_convert.py +311 -0
  220. package/.github/skills/media-processing/scripts/remove-background.sh +96 -0
  221. package/.github/skills/media-processing/scripts/remove-bg-node.js +158 -0
  222. package/.github/skills/media-processing/scripts/requirements.txt +24 -0
  223. package/.github/skills/media-processing/scripts/video_optimize.py +414 -0
  224. package/.github/skills/payment-integration/README.md +185 -0
  225. package/.github/skills/payment-integration/scripts/.env.example +20 -0
  226. package/.github/skills/payment-integration/scripts/checkout-helper.js +244 -0
  227. package/.github/skills/payment-integration/scripts/package.json +17 -0
  228. package/.github/skills/payment-integration/scripts/polar-webhook-verify.js +202 -0
  229. package/.github/skills/payment-integration/scripts/sepay-webhook-verify.js +193 -0
  230. package/.github/skills/payment-integration/scripts/test-scripts.js +237 -0
  231. package/.github/skills/plans-kanban/assets/dashboard-template.html +119 -0
  232. package/.github/skills/plans-kanban/assets/dashboard.css +1594 -0
  233. package/.github/skills/plans-kanban/assets/dashboard.js +596 -0
  234. package/.github/skills/plans-kanban/assets/favicon.png +0 -0
  235. package/.github/skills/plans-kanban/package-lock.json +123 -0
  236. package/.github/skills/plans-kanban/package.json +13 -0
  237. package/.github/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +884 -0
  238. package/.github/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
  239. package/.github/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
  240. package/.github/skills/plans-kanban/scripts/lib/plan-parser.cjs +175 -0
  241. package/.github/skills/plans-kanban/scripts/lib/plan-scanner.cjs +272 -0
  242. package/.github/skills/plans-kanban/scripts/lib/port-finder.cjs +48 -0
  243. package/.github/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
  244. package/.github/skills/plans-kanban/scripts/server.cjs +260 -0
  245. package/.github/skills/repomix/scripts/.coverage +0 -0
  246. package/.github/skills/repomix/scripts/README.md +179 -0
  247. package/.github/skills/repomix/scripts/repomix_batch.py +455 -0
  248. package/.github/skills/repomix/scripts/repos.example.json +15 -0
  249. package/.github/skills/repomix/scripts/requirements.txt +15 -0
  250. package/.github/skills/scout-validation/scripts/lib/broad-pattern-detector.cjs +124 -0
  251. package/.github/skills/scout-validation/scripts/lib/path-checker.cjs +66 -0
  252. package/.github/skills/scout-validation/scripts/lib/schema-validator.cjs +45 -0
  253. package/.github/skills/scout-validation/scripts/package.json +11 -0
  254. package/.github/skills/scout-validation/scripts/validate-scout-output.cjs +219 -0
  255. package/.github/skills/scout-validation/test/broad-pattern-output.json +18 -0
  256. package/.github/skills/scout-validation/test/invalid-path-output.json +18 -0
  257. package/.github/skills/scout-validation/test/valid-scout-output.json +26 -0
  258. package/.github/skills/sequential-thinking/.env.example +8 -0
  259. package/.github/skills/sequential-thinking/README.md +183 -0
  260. package/.github/skills/sequential-thinking/package.json +31 -0
  261. package/.github/skills/sequential-thinking/scripts/format-thought.js +159 -0
  262. package/.github/skills/sequential-thinking/scripts/process-thought.js +236 -0
  263. package/.github/skills/shopify/README.md +66 -0
  264. package/.github/skills/shopify/scripts/.coverage +0 -0
  265. package/.github/skills/shopify/scripts/requirements.txt +19 -0
  266. package/.github/skills/shopify/scripts/shopify_init.py +423 -0
  267. package/.github/skills/skill-creator/LICENSE.txt +202 -0
  268. package/.github/skills/skill-creator/scripts/init_skill.py +303 -0
  269. package/.github/skills/skill-creator/scripts/package_skill.py +110 -0
  270. package/.github/skills/skill-creator/scripts/quick_validate.py +65 -0
  271. package/.github/skills/ui-styling/LICENSE.txt +202 -0
  272. package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  273. package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  274. package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  275. package/.github/skills/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  276. package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  277. package/.github/skills/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  278. package/.github/skills/ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  279. package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  280. package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  281. package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  282. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  283. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  284. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  285. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  286. package/.github/skills/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  287. package/.github/skills/ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  288. package/.github/skills/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  289. package/.github/skills/ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  290. package/.github/skills/ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  291. package/.github/skills/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  292. package/.github/skills/ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  293. package/.github/skills/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  294. package/.github/skills/ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  295. package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  296. package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  297. package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  298. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  299. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  300. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  301. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  302. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  303. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  304. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  305. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  306. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  307. package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  308. package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  309. package/.github/skills/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  310. package/.github/skills/ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  311. package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  312. package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  313. package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  314. package/.github/skills/ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  315. package/.github/skills/ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  316. package/.github/skills/ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  317. package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  318. package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  319. package/.github/skills/ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  320. package/.github/skills/ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  321. package/.github/skills/ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  322. package/.github/skills/ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  323. package/.github/skills/ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  324. package/.github/skills/ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  325. package/.github/skills/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  326. package/.github/skills/ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  327. package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  328. package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  329. package/.github/skills/ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  330. package/.github/skills/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  331. package/.github/skills/ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  332. package/.github/skills/ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  333. package/.github/skills/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  334. package/.github/skills/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  335. package/.github/skills/ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  336. package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  337. package/.github/skills/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  338. package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  339. package/.github/skills/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  340. package/.github/skills/ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  341. package/.github/skills/ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  342. package/.github/skills/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  343. package/.github/skills/ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  344. package/.github/skills/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  345. package/.github/skills/ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  346. package/.github/skills/ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  347. package/.github/skills/ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  348. package/.github/skills/ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  349. package/.github/skills/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  350. package/.github/skills/ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  351. package/.github/skills/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  352. package/.github/skills/ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  353. package/.github/skills/ui-styling/scripts/.coverage +0 -0
  354. package/.github/skills/ui-styling/scripts/requirements.txt +17 -0
  355. package/.github/skills/ui-styling/scripts/shadcn_add.py +292 -0
  356. package/.github/skills/ui-styling/scripts/tailwind_config_gen.py +456 -0
  357. package/.github/skills/ui-ux-pro-max/data/charts.csv +26 -0
  358. package/.github/skills/ui-ux-pro-max/data/colors.csv +97 -0
  359. package/.github/skills/ui-ux-pro-max/data/landing.csv +31 -0
  360. package/.github/skills/ui-ux-pro-max/data/products.csv +97 -0
  361. package/.github/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  362. package/.github/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  363. package/.github/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +51 -0
  364. package/.github/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  365. package/.github/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  366. package/.github/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  367. package/.github/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  368. package/.github/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  369. package/.github/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  370. package/.github/skills/ui-ux-pro-max/data/styles.csv +59 -0
  371. package/.github/skills/ui-ux-pro-max/data/typography.csv +58 -0
  372. package/.github/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  373. package/.github/skills/ui-ux-pro-max/scripts/core.py +236 -0
  374. package/.github/skills/ui-ux-pro-max/scripts/search.py +76 -0
  375. package/.github/skills/web-frameworks/scripts/.coverage +0 -0
  376. package/.github/skills/web-frameworks/scripts/__init__.py +0 -0
  377. package/.github/skills/web-frameworks/scripts/nextjs_init.py +547 -0
  378. package/.github/skills/web-frameworks/scripts/requirements.txt +16 -0
  379. package/.github/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
  380. package/dist/config/constants.d.ts +2 -0
  381. package/dist/config/constants.d.ts.map +1 -1
  382. package/dist/config/constants.js +4 -1
  383. package/dist/config/constants.js.map +1 -1
  384. package/dist/domains/github/github-client.d.ts +5 -0
  385. package/dist/domains/github/github-client.d.ts.map +1 -1
  386. package/dist/domains/github/github-client.js +44 -0
  387. package/dist/domains/github/github-client.js.map +1 -1
  388. package/dist/utils/downloader.d.ts +3 -1
  389. package/dist/utils/downloader.d.ts.map +1 -1
  390. package/dist/utils/downloader.js +48 -11
  391. package/dist/utils/downloader.js.map +1 -1
  392. package/package.json +3 -1
@@ -0,0 +1,489 @@
1
+ /**
2
+ * Plan Metadata Extractor
3
+ * Extracts rich metadata from plan.md files including dates, effort, priority, issues
4
+ * Supports YAML frontmatter (primary) with regex fallback for legacy plans
5
+ *
6
+ * @module plan-metadata-extractor
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const matter = require('gray-matter');
12
+
13
+ /**
14
+ * Normalize status string to standard format
15
+ * @param {string} status - Raw status string
16
+ * @returns {string} - Normalized status (pending|in-progress|completed|cancelled)
17
+ */
18
+ function normalizeStatus(status) {
19
+ if (!status) return 'pending';
20
+ const s = String(status).toLowerCase().trim();
21
+ if (s === 'complete' || s === 'completed' || s === 'done') return 'completed';
22
+ if (s === 'in-progress' || s === 'in_progress' || s === 'active' || s === 'wip') return 'in-progress';
23
+ if (s === 'cancelled' || s === 'canceled') return 'cancelled';
24
+ if (s === 'in-review' || s === 'review') return 'in-review';
25
+ return 'pending';
26
+ }
27
+
28
+ /**
29
+ * Normalize priority to P1/P2/P3 format
30
+ * @param {string} priority - Raw priority string
31
+ * @returns {string|null} - Normalized priority (P1|P2|P3) or null
32
+ */
33
+ function normalizePriority(priority) {
34
+ if (!priority) return null;
35
+ const p = String(priority).toUpperCase().trim();
36
+ if (p === 'P1' || p === 'HIGH' || p === 'CRITICAL') return 'P1';
37
+ if (p === 'P2' || p === 'MEDIUM' || p === 'NORMAL') return 'P2';
38
+ if (p === 'P3' || p === 'LOW') return 'P3';
39
+ if (p.match(/^P[0-3]$/)) return p;
40
+ return null;
41
+ }
42
+
43
+ /**
44
+ * Extract metadata from YAML frontmatter (primary method)
45
+ * @param {string} content - File content
46
+ * @returns {Object|null} - Extracted metadata or null if no frontmatter
47
+ */
48
+ function extractFromFrontmatter(content) {
49
+ if (!content || !content.trim().startsWith('---')) return null;
50
+
51
+ try {
52
+ const { data } = matter(content);
53
+ if (!data || Object.keys(data).length === 0) return null;
54
+
55
+ return {
56
+ title: data.title || null,
57
+ description: data.description || null,
58
+ status: normalizeStatus(data.status),
59
+ priority: normalizePriority(data.priority),
60
+ effort: data.effort || null,
61
+ issue: data.issue ? String(data.issue) : null,
62
+ branch: data.branch || null,
63
+ tags: Array.isArray(data.tags) ? data.tags : [],
64
+ createdDate: data.created ? new Date(data.created) : null,
65
+ completedDate: data.completed ? new Date(data.completed) : null,
66
+ assignee: data.assignee || null
67
+ };
68
+ } catch (e) {
69
+ // YAML parse error - fall back to regex
70
+ return null;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Extract description from ## Overview section
76
+ * @param {string} content - File content
77
+ * @returns {string|null} - First paragraph of Overview section or null
78
+ */
79
+ function extractDescriptionFromOverview(content) {
80
+ if (!content) return null;
81
+
82
+ // Look for ## Overview section
83
+ const overviewMatch = content.match(/##\s*Overview\s*\n+([^\n#]+)/i);
84
+ if (overviewMatch) {
85
+ const desc = overviewMatch[1].trim();
86
+ // Return first sentence or first 150 chars
87
+ const firstSentence = desc.match(/^[^.!?]+[.!?]/);
88
+ if (firstSentence) return firstSentence[0].trim();
89
+ return desc.slice(0, 150).trim();
90
+ }
91
+
92
+ return null;
93
+ }
94
+
95
+ /**
96
+ * Parse date from plan directory name (YYMMDD or YYYYMMDD format)
97
+ * @param {string} dirName - Directory name like "251211-feature-name"
98
+ * @returns {Date|null} - Parsed date or null
99
+ */
100
+ function parseDateFromDirName(dirName) {
101
+ // Match YYMMDD-HHMM- or YYMMDD- or YYYYMMDD-
102
+ const match = dirName.match(/^(\d{6,8})(?:-(\d{4}))?-/);
103
+ if (!match) return null;
104
+
105
+ const dateStr = match[1];
106
+ let year, month, day;
107
+
108
+ if (dateStr.length === 6) {
109
+ // YYMMDD format
110
+ year = 2000 + parseInt(dateStr.slice(0, 2), 10);
111
+ month = parseInt(dateStr.slice(2, 4), 10) - 1;
112
+ day = parseInt(dateStr.slice(4, 6), 10);
113
+ } else {
114
+ // YYYYMMDD format
115
+ year = parseInt(dateStr.slice(0, 4), 10);
116
+ month = parseInt(dateStr.slice(4, 6), 10) - 1;
117
+ day = parseInt(dateStr.slice(6, 8), 10);
118
+ }
119
+
120
+ const date = new Date(year, month, day);
121
+ return isNaN(date.getTime()) ? null : date;
122
+ }
123
+
124
+ /**
125
+ * Extract metadata from plan.md header section
126
+ * Looks for patterns like **Key:** Value or **Key**: Value
127
+ * @param {string} content - Plan file content
128
+ * @returns {Object} - Extracted metadata
129
+ */
130
+ function extractHeaderMetadata(content) {
131
+ const metadata = {
132
+ createdDate: null,
133
+ completedDate: null,
134
+ priority: null,
135
+ issue: null,
136
+ branch: null,
137
+ planId: null,
138
+ headerStatus: null
139
+ };
140
+
141
+ // Only look at first ~50 lines for header metadata
142
+ const headerSection = content.split('\n').slice(0, 50).join('\n');
143
+
144
+ // **Created:** 2025-12-01 or **Date:** 2025-12-11
145
+ const createdMatch = headerSection.match(/\*\*(?:Created|Date):?\*\*:?\s*(\d{4}-\d{2}-\d{2})/i);
146
+ if (createdMatch) {
147
+ metadata.createdDate = new Date(createdMatch[1]);
148
+ }
149
+
150
+ // **Status:** ✓ Complete (2025-12-01) - extract completion date
151
+ const statusMatch = headerSection.match(/\*\*Status:?\*\*:?\s*(.+)/i);
152
+ if (statusMatch) {
153
+ metadata.headerStatus = statusMatch[1].trim();
154
+ const completedMatch = statusMatch[1].match(/(?:complete|done).*?(\d{4}-\d{2}-\d{2})/i);
155
+ if (completedMatch) {
156
+ metadata.completedDate = new Date(completedMatch[1]);
157
+ }
158
+ }
159
+
160
+ // **Priority:** P1 - High
161
+ const priorityMatch = headerSection.match(/\*\*Priority:?\*\*:?\s*(P[0-3]|High|Medium|Low)/i);
162
+ if (priorityMatch) {
163
+ metadata.priority = priorityMatch[1].toUpperCase();
164
+ }
165
+
166
+ // **Issue:** #74 or **Issue**: https://github.com/.../issues/74
167
+ const issueMatch = headerSection.match(/\*\*Issue:?\*\*:?\s*(?:#(\d+)|.*?issues\/(\d+))/i);
168
+ if (issueMatch) {
169
+ metadata.issue = issueMatch[1] || issueMatch[2];
170
+ }
171
+
172
+ // **Branch:** `kai/feat/feature-name` or **Branch:** kai/feat/feature-name
173
+ const branchMatch = headerSection.match(/\*\*Branch:?\*\*:?\s*`?([^`\n]+)`?/i);
174
+ if (branchMatch) {
175
+ metadata.branch = branchMatch[1].trim();
176
+ }
177
+
178
+ // **Plan ID:** 20251201-1849-cli-ui-enhancement
179
+ const planIdMatch = headerSection.match(/\*\*Plan ID\*\*:?\s*(\S+)/i);
180
+ if (planIdMatch) {
181
+ metadata.planId = planIdMatch[1].trim();
182
+ }
183
+
184
+ return metadata;
185
+ }
186
+
187
+ /**
188
+ * Parse effort/time string to hours
189
+ * @param {string} effortStr - Effort string like "4h", "2 hours", "30m", "1.5h"
190
+ * @returns {number} - Hours as decimal
191
+ */
192
+ function parseEffortToHours(effortStr) {
193
+ if (!effortStr) return 0;
194
+
195
+ const str = effortStr.toLowerCase().trim();
196
+
197
+ // Match patterns: 4h, 4 hours, 4hr, 30m, 30 min, 1.5h
198
+ const hoursMatch = str.match(/(\d+(?:\.\d+)?)\s*(?:h|hours?|hrs?)/);
199
+ if (hoursMatch) {
200
+ return parseFloat(hoursMatch[1]);
201
+ }
202
+
203
+ const minutesMatch = str.match(/(\d+)\s*(?:m|min|minutes?)/);
204
+ if (minutesMatch) {
205
+ return parseInt(minutesMatch[1], 10) / 60;
206
+ }
207
+
208
+ const daysMatch = str.match(/(\d+(?:\.\d+)?)\s*(?:d|days?)/);
209
+ if (daysMatch) {
210
+ return parseFloat(daysMatch[1]) * 8; // Assume 8h work day
211
+ }
212
+
213
+ return 0;
214
+ }
215
+
216
+ /**
217
+ * Extract effort estimates from phase table
218
+ * Looks for Effort/Time/Estimate columns in tables
219
+ * @param {string} content - Plan file content
220
+ * @returns {{totalEffort: number, phaseEfforts: Array<{phase: number, effort: number, effortStr: string}>}}
221
+ */
222
+ function extractEffortFromTable(content) {
223
+ const result = {
224
+ totalEffort: 0,
225
+ phaseEfforts: []
226
+ };
227
+
228
+ // Match table rows with effort column
229
+ // Pattern: | Phase | Description | Status | Effort |
230
+ // Or: | [Phase 1](path) | Description | Status | 4h |
231
+ const tableRowRegex = /\|[^|]*\|[^|]*\|[^|]*\|\s*(\d+(?:\.\d+)?\s*(?:h|m|d|hours?|min|days?)?)\s*\|/gi;
232
+
233
+ let match;
234
+ let phaseNum = 1;
235
+ while ((match = tableRowRegex.exec(content)) !== null) {
236
+ const effortStr = match[1].trim();
237
+ const effort = parseEffortToHours(effortStr);
238
+ if (effort > 0) {
239
+ result.phaseEfforts.push({
240
+ phase: phaseNum,
241
+ effort,
242
+ effortStr
243
+ });
244
+ result.totalEffort += effort;
245
+ phaseNum++;
246
+ }
247
+ }
248
+
249
+ return result;
250
+ }
251
+
252
+ /**
253
+ * Calculate plan duration in days
254
+ * @param {Date} startDate - Start date
255
+ * @param {Date} endDate - End date (or now if not completed)
256
+ * @returns {number} - Duration in days
257
+ */
258
+ function calculateDuration(startDate, endDate) {
259
+ if (!startDate) return 0;
260
+ const end = endDate || new Date();
261
+ const diffMs = end.getTime() - startDate.getTime();
262
+ return Math.ceil(diffMs / (1000 * 60 * 60 * 24));
263
+ }
264
+
265
+ /**
266
+ * Format duration as human-readable string
267
+ * @param {number} days - Duration in days
268
+ * @returns {string} - Formatted string like "3 days" or "2 weeks"
269
+ */
270
+ function formatDuration(days) {
271
+ if (days === 0) return 'Today';
272
+ if (days === 1) return '1 day';
273
+ if (days < 7) return `${days} days`;
274
+ if (days < 14) return '1 week';
275
+ if (days < 30) return `${Math.floor(days / 7)} weeks`;
276
+ if (days < 60) return '1 month';
277
+ return `${Math.floor(days / 30)} months`;
278
+ }
279
+
280
+ /**
281
+ * Extract all rich metadata from a plan
282
+ * Tries YAML frontmatter first, falls back to regex extraction
283
+ * @param {string} planFilePath - Path to plan.md
284
+ * @returns {Object} - Complete metadata object
285
+ */
286
+ function extractPlanMetadata(planFilePath) {
287
+ const content = fs.readFileSync(planFilePath, 'utf8');
288
+ const dir = path.dirname(planFilePath);
289
+ const dirName = path.basename(dir);
290
+ const stats = fs.statSync(planFilePath);
291
+
292
+ // Try YAML frontmatter first (new format)
293
+ const frontmatter = extractFromFrontmatter(content);
294
+
295
+ // Get header metadata (legacy regex extraction)
296
+ const headerMeta = extractHeaderMetadata(content);
297
+
298
+ // Get date from directory name as fallback
299
+ const dirDate = parseDateFromDirName(dirName);
300
+
301
+ // Merge frontmatter with regex fallback
302
+ // Frontmatter takes priority, regex fills gaps
303
+ const createdDate = frontmatter?.createdDate || headerMeta.createdDate || dirDate || null;
304
+ const completedDate = frontmatter?.completedDate || headerMeta.completedDate || null;
305
+ const priority = frontmatter?.priority || normalizePriority(headerMeta.priority);
306
+ const issue = frontmatter?.issue || headerMeta.issue;
307
+ const branch = frontmatter?.branch || headerMeta.branch;
308
+
309
+ // Extract description: frontmatter > Overview section
310
+ const description = frontmatter?.description || extractDescriptionFromOverview(content);
311
+
312
+ // Tags from frontmatter only (no regex extraction for tags)
313
+ const tags = frontmatter?.tags || [];
314
+
315
+ // Get effort data from table
316
+ const effortData = extractEffortFromTable(content);
317
+ // Override with frontmatter effort if present
318
+ let totalEffort = effortData.totalEffort;
319
+ if (frontmatter?.effort) {
320
+ const parsed = parseEffortToHours(frontmatter.effort);
321
+ if (parsed > 0) totalEffort = parsed;
322
+ }
323
+
324
+ // Calculate duration
325
+ const duration = calculateDuration(createdDate, completedDate);
326
+
327
+ return {
328
+ // Dates
329
+ createdDate: createdDate ? createdDate.toISOString() : null,
330
+ completedDate: completedDate ? completedDate.toISOString() : null,
331
+ lastModified: stats.mtime.toISOString(),
332
+
333
+ // Duration
334
+ durationDays: duration,
335
+ durationFormatted: formatDuration(duration),
336
+ isCompleted: !!completedDate,
337
+
338
+ // Effort
339
+ totalEffortHours: totalEffort,
340
+ totalEffortFormatted: totalEffort > 0
341
+ ? `${totalEffort.toFixed(1)}h`
342
+ : null,
343
+ phaseEfforts: effortData.phaseEfforts,
344
+
345
+ // Metadata (merged from frontmatter + regex)
346
+ title: frontmatter?.title || null,
347
+ description,
348
+ priority,
349
+ issue,
350
+ branch,
351
+ tags,
352
+ assignee: frontmatter?.assignee || null,
353
+ planId: headerMeta.planId,
354
+ // Use frontmatter status if available, otherwise regex-extracted header status
355
+ headerStatus: frontmatter?.status || headerMeta.headerStatus,
356
+
357
+ // Source indicator for debugging
358
+ hasFrontmatter: !!frontmatter
359
+ };
360
+ }
361
+
362
+ /**
363
+ * Generate timeline data for multiple plans
364
+ * @param {Array} plans - Array of plan objects with metadata
365
+ * @returns {Object} - Timeline statistics
366
+ */
367
+ function generateTimelineStats(plans) {
368
+ const now = new Date();
369
+ const stats = {
370
+ totalPlans: plans.length,
371
+ completedPlans: 0,
372
+ activePlans: 0,
373
+ pendingPlans: 0,
374
+ avgDurationDays: 0,
375
+ longestPlan: null,
376
+ totalEffortHours: 0,
377
+ completedEffortHours: 0,
378
+ thisWeekCompleted: 0,
379
+ thisMonthCompleted: 0
380
+ };
381
+
382
+ const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
383
+ const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
384
+ let totalDuration = 0;
385
+ let durationCount = 0;
386
+
387
+ for (const plan of plans) {
388
+ // Count by status
389
+ if (plan.status === 'completed') {
390
+ stats.completedPlans++;
391
+ if (plan.completedDate) {
392
+ const completed = new Date(plan.completedDate);
393
+ if (completed >= weekAgo) stats.thisWeekCompleted++;
394
+ if (completed >= monthAgo) stats.thisMonthCompleted++;
395
+ }
396
+ if (plan.totalEffortHours) {
397
+ stats.completedEffortHours += plan.totalEffortHours;
398
+ }
399
+ } else if (plan.status === 'in-progress') {
400
+ stats.activePlans++;
401
+ } else {
402
+ stats.pendingPlans++;
403
+ }
404
+
405
+ // Track duration
406
+ if (plan.durationDays > 0) {
407
+ totalDuration += plan.durationDays;
408
+ durationCount++;
409
+ if (!stats.longestPlan || plan.durationDays > stats.longestPlan.durationDays) {
410
+ stats.longestPlan = { name: plan.name, durationDays: plan.durationDays };
411
+ }
412
+ }
413
+
414
+ // Sum effort
415
+ if (plan.totalEffortHours) {
416
+ stats.totalEffortHours += plan.totalEffortHours;
417
+ }
418
+ }
419
+
420
+ stats.avgDurationDays = durationCount > 0
421
+ ? Math.round(totalDuration / durationCount)
422
+ : 0;
423
+
424
+ return stats;
425
+ }
426
+
427
+ /**
428
+ * Generate activity data for heatmap (last 12 weeks)
429
+ * @param {Array} plans - Array of plan objects with metadata
430
+ * @returns {Array} - Array of weekly activity counts
431
+ */
432
+ function generateActivityHeatmap(plans) {
433
+ const now = new Date();
434
+ const weeks = [];
435
+
436
+ // Generate 12 weeks of data
437
+ for (let w = 11; w >= 0; w--) {
438
+ const weekStart = new Date(now.getTime() - w * 7 * 24 * 60 * 60 * 1000);
439
+ weekStart.setHours(0, 0, 0, 0);
440
+ weekStart.setDate(weekStart.getDate() - weekStart.getDay()); // Start of week (Sunday)
441
+
442
+ const weekEnd = new Date(weekStart.getTime() + 7 * 24 * 60 * 60 * 1000);
443
+
444
+ let activity = 0;
445
+ for (const plan of plans) {
446
+ // Count plans created or completed in this week
447
+ if (plan.createdDate) {
448
+ const created = new Date(plan.createdDate);
449
+ if (created >= weekStart && created < weekEnd) activity++;
450
+ }
451
+ if (plan.completedDate) {
452
+ const completed = new Date(plan.completedDate);
453
+ if (completed >= weekStart && completed < weekEnd) activity++;
454
+ }
455
+ }
456
+
457
+ weeks.push({
458
+ weekStart: weekStart.toISOString(),
459
+ weekLabel: weekStart.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
460
+ activity,
461
+ level: activity === 0 ? 0 : activity === 1 ? 1 : activity <= 3 ? 2 : 3
462
+ });
463
+ }
464
+
465
+ return weeks;
466
+ }
467
+
468
+ module.exports = {
469
+ // Core extraction functions
470
+ extractPlanMetadata,
471
+ extractFromFrontmatter,
472
+ extractDescriptionFromOverview,
473
+ extractHeaderMetadata,
474
+ extractEffortFromTable,
475
+
476
+ // Normalization helpers
477
+ normalizeStatus,
478
+ normalizePriority,
479
+
480
+ // Date/time utilities
481
+ parseDateFromDirName,
482
+ parseEffortToHours,
483
+ calculateDuration,
484
+ formatDuration,
485
+
486
+ // Statistics generators
487
+ generateTimelineStats,
488
+ generateActivityHeatmap
489
+ };
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Plan Parser - parses plan.md files to extract phase metadata
3
+ * Standalone module for plans-kanban skill
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ /**
10
+ * Normalize status string to standard format
11
+ * @param {string} raw - Raw status text
12
+ * @returns {string} - Normalized status (completed, in-progress, pending)
13
+ */
14
+ function normalizeStatus(raw) {
15
+ const s = (raw || '').toLowerCase().trim();
16
+ if (s.includes('complete') || s.includes('done') || s.includes('✓') || s.includes('✅')) {
17
+ return 'completed';
18
+ }
19
+ if (s.includes('progress') || s.includes('active') || s.includes('wip') || s.includes('🔄')) {
20
+ return 'in-progress';
21
+ }
22
+ return 'pending';
23
+ }
24
+
25
+ /**
26
+ * Parse plan.md to extract phase metadata from table
27
+ * Supports multiple table formats
28
+ * @param {string} planFilePath - Path to plan.md
29
+ * @returns {Array<{phase: number, name: string, status: string, file: string}>}
30
+ */
31
+ function parsePlanTable(planFilePath) {
32
+ const content = fs.readFileSync(planFilePath, 'utf8');
33
+ const dir = path.dirname(planFilePath);
34
+ const phases = [];
35
+ let match;
36
+
37
+ // Format 1: Standard table | Phase | Name | Status | [Link](path) |
38
+ const standardRegex = /\|\s*(\d+)\s*\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)/g;
39
+ while ((match = standardRegex.exec(content)) !== null) {
40
+ const [, phase, name, status, linkText, linkPath] = match;
41
+ phases.push({
42
+ phase: parseInt(phase, 10),
43
+ name: name.trim(),
44
+ status: normalizeStatus(status),
45
+ file: path.resolve(dir, linkPath),
46
+ linkText: linkText.trim()
47
+ });
48
+ }
49
+
50
+ // Format 2: Link-first table | [Phase X](path) | Description | Status |
51
+ if (phases.length === 0) {
52
+ const linkFirstRegex = /\|\s*\[(?:Phase\s*)?(\d+)\]\(([^)]+)\)\s*\|\s*([^|]+)\s*\|\s*([^|]+)/g;
53
+ while ((match = linkFirstRegex.exec(content)) !== null) {
54
+ const [, phase, linkPath, name, status] = match;
55
+ phases.push({
56
+ phase: parseInt(phase, 10),
57
+ name: name.trim(),
58
+ status: normalizeStatus(status),
59
+ file: path.resolve(dir, linkPath),
60
+ linkText: `Phase ${phase}`
61
+ });
62
+ }
63
+ }
64
+
65
+ // Format 2b: Number-first with link | 1 | [Name](path) | Status |
66
+ if (phases.length === 0) {
67
+ const numLinkRegex = /\|\s*(\d+)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)\s*\|\s*([^|]+)/g;
68
+ while ((match = numLinkRegex.exec(content)) !== null) {
69
+ const [, phase, name, linkPath, status] = match;
70
+ phases.push({
71
+ phase: parseInt(phase, 10),
72
+ name: name.trim(),
73
+ status: normalizeStatus(status),
74
+ file: path.resolve(dir, linkPath),
75
+ linkText: name.trim()
76
+ });
77
+ }
78
+ }
79
+
80
+ // Format 2c: Simple table | Phase | Description | Status |
81
+ if (phases.length === 0) {
82
+ const simpleTblRegex = /\|\s*0?(\d+)\s*\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|/g;
83
+ while ((match = simpleTblRegex.exec(content)) !== null) {
84
+ const [, phase, name, status] = match;
85
+ if (name.trim().toLowerCase() === 'description' || name.trim().toLowerCase() === 'name') continue;
86
+ if (name.includes('---') || name.includes('===')) continue;
87
+ phases.push({
88
+ phase: parseInt(phase, 10),
89
+ name: name.trim(),
90
+ status: normalizeStatus(status),
91
+ file: planFilePath,
92
+ linkText: name.trim()
93
+ });
94
+ }
95
+ }
96
+
97
+ // Format 3: Heading-based phases (### Phase X: Name)
98
+ if (phases.length === 0) {
99
+ const contentLines = content.split('\n');
100
+ let currentPhase = null;
101
+
102
+ for (const line of contentLines) {
103
+ const headingMatch = /###\s*Phase\s*(\d+)[:\s]+(.+)/i.exec(line);
104
+ if (headingMatch) {
105
+ if (currentPhase) phases.push(currentPhase);
106
+ const phaseNum = parseInt(headingMatch[1], 10);
107
+ currentPhase = {
108
+ phase: phaseNum,
109
+ name: headingMatch[2].trim(),
110
+ status: 'pending',
111
+ file: planFilePath,
112
+ linkText: `Phase ${phaseNum}`
113
+ };
114
+ }
115
+ if (currentPhase) {
116
+ const statusMatch = /-\s*Status:\s*(.+)/i.exec(line);
117
+ if (statusMatch) {
118
+ currentPhase.status = normalizeStatus(statusMatch[1]);
119
+ }
120
+ }
121
+ }
122
+ if (currentPhase) phases.push(currentPhase);
123
+ }
124
+
125
+ // Format 4: Numbered list with checkbox
126
+ if (phases.length === 0) {
127
+ const numberedPhaseRegex = /^(\d+)[)\.]\s*\*\*([^*]+)\*\*/gm;
128
+ const phaseMap = new Map();
129
+ while ((match = numberedPhaseRegex.exec(content)) !== null) {
130
+ const [, num, name] = match;
131
+ phaseMap.set(name.trim().toLowerCase(), {
132
+ phase: parseInt(num, 10),
133
+ name: name.trim(),
134
+ status: 'pending',
135
+ file: planFilePath,
136
+ linkText: name.trim()
137
+ });
138
+ }
139
+
140
+ const checkboxRegex = /^-\s*\[(x| )\]\s*([^:]+)/gmi;
141
+ while ((match = checkboxRegex.exec(content)) !== null) {
142
+ const [, checked, name] = match;
143
+ const key = name.trim().toLowerCase();
144
+ if (phaseMap.has(key)) {
145
+ phaseMap.get(key).status = checked.toLowerCase() === 'x' ? 'completed' : 'pending';
146
+ }
147
+ }
148
+
149
+ if (phaseMap.size > 0) {
150
+ phases.push(...Array.from(phaseMap.values()).sort((a, b) => a.phase - b.phase));
151
+ }
152
+ }
153
+
154
+ // Format 5: Checkbox list with bold links
155
+ if (phases.length === 0) {
156
+ const checkboxLinkRegex = /^-\s*\[(x| )\]\s*\*\*\[(?:Phase\s*)?(\d+)[:\s]*([^\]]*)\]\(([^)]+)\)\*\*/gmi;
157
+ while ((match = checkboxLinkRegex.exec(content)) !== null) {
158
+ const [, checked, phase, name, linkPath] = match;
159
+ phases.push({
160
+ phase: parseInt(phase, 10),
161
+ name: name.trim() || `Phase ${phase}`,
162
+ status: checked.toLowerCase() === 'x' ? 'completed' : 'pending',
163
+ file: path.resolve(dir, linkPath),
164
+ linkText: name.trim() || `Phase ${phase}`
165
+ });
166
+ }
167
+ }
168
+
169
+ return phases;
170
+ }
171
+
172
+ module.exports = {
173
+ parsePlanTable,
174
+ normalizeStatus
175
+ };