@ngockhoale/ukit 1.1.6

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 (344) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -0
  4. package/bin/ukit +30 -0
  5. package/manifests/platform.full.yaml +1194 -0
  6. package/package.json +71 -0
  7. package/scripts/bug/triage.mjs +37 -0
  8. package/scripts/index/build-index.mjs +35 -0
  9. package/scripts/index/query-index.mjs +92 -0
  10. package/scripts/index/refresh-index.mjs +85 -0
  11. package/scripts/release/verify-release.mjs +56 -0
  12. package/src/bug/triageBug.js +123 -0
  13. package/src/cli/adapters.js +148 -0
  14. package/src/cli/commands/diff.js +51 -0
  15. package/src/cli/commands/doctor.js +125 -0
  16. package/src/cli/commands/indexArgs.js +73 -0
  17. package/src/cli/commands/indexTools.js +509 -0
  18. package/src/cli/commands/install.js +293 -0
  19. package/src/cli/commands/memory.js +126 -0
  20. package/src/cli/commands/status.js +8 -0
  21. package/src/cli/commands/uninstall.js +51 -0
  22. package/src/cli/index.js +109 -0
  23. package/src/context/detectProjectContext.js +49 -0
  24. package/src/context/detectProviders.js +12 -0
  25. package/src/core/applyPlan.js +89 -0
  26. package/src/core/buildPlan.js +228 -0
  27. package/src/core/compact/index.js +294 -0
  28. package/src/core/compact/threshold.js +936 -0
  29. package/src/core/diffPlan.js +73 -0
  30. package/src/core/ensureGitignore.js +117 -0
  31. package/src/core/fileOps.js +188 -0
  32. package/src/core/memory/hygiene.js +160 -0
  33. package/src/core/memory/index.js +2 -0
  34. package/src/core/memory/retrieval.js +476 -0
  35. package/src/core/memory/store.js +202 -0
  36. package/src/core/metadata.js +132 -0
  37. package/src/core/migrateLegacy.js +139 -0
  38. package/src/core/output/index.js +1309 -0
  39. package/src/core/paths.js +13 -0
  40. package/src/core/report.js +17 -0
  41. package/src/core/router/advisor.js +42 -0
  42. package/src/core/router/index.js +2 -0
  43. package/src/core/router/router.js +164 -0
  44. package/src/core/runInstallPipeline.js +365 -0
  45. package/src/core/runtimeConfig.js +190 -0
  46. package/src/core/runtimePaths.js +24 -0
  47. package/src/core/status.js +186 -0
  48. package/src/core/token/index.js +328 -0
  49. package/src/core/uninstall.js +246 -0
  50. package/src/core/validation/confidence.js +89 -0
  51. package/src/core/validation/index.js +2 -0
  52. package/src/core/validation/validator.js +165 -0
  53. package/src/index/buildIndex.js +1392 -0
  54. package/src/index/gitHooks.js +109 -0
  55. package/src/index/importResolution.js +377 -0
  56. package/src/index/languageTools.js +127 -0
  57. package/src/index/paths.js +27 -0
  58. package/src/index/queryIndex.js +637 -0
  59. package/src/index/relatedTests.js +237 -0
  60. package/src/index/resolveContext.js +345 -0
  61. package/src/index/routeCatalog.js +258 -0
  62. package/src/index/taskRouting.js +677 -0
  63. package/src/index/verificationPlan.js +437 -0
  64. package/src/manifest/loadManifest.js +22 -0
  65. package/src/manifest/selectItems.js +78 -0
  66. package/src/manifest/validateManifest.js +115 -0
  67. package/src/render/buildVariables.js +39 -0
  68. package/src/render/renderTemplate.js +44 -0
  69. package/src/stack/detectStack.js +213 -0
  70. package/templates/.claude/agents/bug-debugger.md +57 -0
  71. package/templates/.claude/agents/feature-implementer.md +55 -0
  72. package/templates/.claude/config/providers.md +25 -0
  73. package/templates/.claude/hooks/auto-allow-bash.sh +155 -0
  74. package/templates/.claude/hooks/auto-prune-bash.sh +75 -0
  75. package/templates/.claude/hooks/block-dangerous.sh +54 -0
  76. package/templates/.claude/hooks/compress-output.sh +17 -0
  77. package/templates/.claude/hooks/protect-files.sh +37 -0
  78. package/templates/.claude/hooks/reinject-context.sh +28 -0
  79. package/templates/.claude/hooks/session-start.md +13 -0
  80. package/templates/.claude/hooks/skill-router.sh +1681 -0
  81. package/templates/.claude/hooks/verification-guard.sh +271 -0
  82. package/templates/.claude/settings.json +144 -0
  83. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  84. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  85. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  86. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  87. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  88. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  89. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  90. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  91. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  92. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  93. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  94. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  95. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  96. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  97. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  98. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  99. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  100. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  101. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  102. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  103. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  104. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  105. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  106. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  107. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  108. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  109. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  110. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  111. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  112. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  113. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  114. package/templates/.claude/skills/_shared/ooxml/schemas/mce/mc.xsd +75 -0
  115. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  116. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  117. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  118. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  119. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  120. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  121. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  122. package/templates/.claude/skills/_shared/ooxml/scripts/pack.py +159 -0
  123. package/templates/.claude/skills/_shared/ooxml/scripts/unpack.py +29 -0
  124. package/templates/.claude/skills/_shared/ooxml/scripts/validate.py +69 -0
  125. package/templates/.claude/skills/_shared/ooxml/scripts/validation/__init__.py +15 -0
  126. package/templates/.claude/skills/_shared/ooxml/scripts/validation/base.py +951 -0
  127. package/templates/.claude/skills/_shared/ooxml/scripts/validation/docx.py +274 -0
  128. package/templates/.claude/skills/_shared/ooxml/scripts/validation/pptx.py +315 -0
  129. package/templates/.claude/skills/_shared/ooxml/scripts/validation/redlining.py +279 -0
  130. package/templates/.claude/skills/backend-api/SKILL.md +26 -0
  131. package/templates/.claude/skills/canvas-design/LICENSE.txt +202 -0
  132. package/templates/.claude/skills/canvas-design/SKILL.md +130 -0
  133. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  134. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  135. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  136. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  137. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  138. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  139. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  140. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  141. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  142. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  143. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  144. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  145. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  146. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  147. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  148. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  149. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  150. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  151. package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  152. package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  153. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  154. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  155. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  156. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  157. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  158. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  159. package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  160. package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  161. package/templates/.claude/skills/code-review/SKILL.md +97 -0
  162. package/templates/.claude/skills/debugging-toolkit/SKILL.md +156 -0
  163. package/templates/.claude/skills/delivery/SKILL.md +92 -0
  164. package/templates/.claude/skills/discover-security/SKILL.md +86 -0
  165. package/templates/.claude/skills/docker-packaging/SKILL.md +60 -0
  166. package/templates/.claude/skills/docs-manager/SKILL.md +465 -0
  167. package/templates/.claude/skills/docs-manager/init-project-docs.sh +70 -0
  168. package/templates/.claude/skills/docs-manager/templates/README.md.template +50 -0
  169. package/templates/.claude/skills/docs-manager/templates/agent-roles.md.template +24 -0
  170. package/templates/.claude/skills/docs-manager/templates/coding-conventions.md.template +28 -0
  171. package/templates/.claude/skills/docs-manager/templates/memory.md.template +30 -0
  172. package/templates/.claude/skills/docs-manager/templates/onboarding.md.template +20 -0
  173. package/templates/.claude/skills/docs-manager/templates/project.md.template +26 -0
  174. package/templates/.claude/skills/docs-quality/SKILL.md +148 -0
  175. package/templates/.claude/skills/docx/LICENSE.txt +30 -0
  176. package/templates/.claude/skills/docx/SKILL.md +197 -0
  177. package/templates/.claude/skills/docx/docx-js.md +350 -0
  178. package/templates/.claude/skills/docx/ooxml.md +610 -0
  179. package/templates/.claude/skills/docx/scripts/__init__.py +1 -0
  180. package/templates/.claude/skills/docx/scripts/document.py +1276 -0
  181. package/templates/.claude/skills/docx/scripts/templates/comments.xml +3 -0
  182. package/templates/.claude/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  183. package/templates/.claude/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  184. package/templates/.claude/skills/docx/scripts/templates/commentsIds.xml +3 -0
  185. package/templates/.claude/skills/docx/scripts/templates/people.xml +3 -0
  186. package/templates/.claude/skills/docx/scripts/utilities.py +374 -0
  187. package/templates/.claude/skills/duraone/SKILL.md +204 -0
  188. package/templates/.claude/skills/duraone/references/backend.md +636 -0
  189. package/templates/.claude/skills/duraone/references/frontend.md +1506 -0
  190. package/templates/.claude/skills/duraone/references/sql.md +631 -0
  191. package/templates/.claude/skills/duraone/references/workflow.md +520 -0
  192. package/templates/.claude/skills/executing-plans/SKILL.md +76 -0
  193. package/templates/.claude/skills/file-organizer/SKILL.md +433 -0
  194. package/templates/.claude/skills/frontend/SKILL.md +26 -0
  195. package/templates/.claude/skills/frontend-design/LICENSE.txt +177 -0
  196. package/templates/.claude/skills/frontend-design/SKILL.md +42 -0
  197. package/templates/.claude/skills/frontend-vue/SKILL.md +127 -0
  198. package/templates/.claude/skills/frontend-vue/components/Control/Box.vue +137 -0
  199. package/templates/.claude/skills/frontend-vue/components/Control/Button.vue +93 -0
  200. package/templates/.claude/skills/frontend-vue/components/Control/ButtonBar.vue +29 -0
  201. package/templates/.claude/skills/frontend-vue/components/Control/ButtonFloat.vue +62 -0
  202. package/templates/.claude/skills/frontend-vue/components/Control/CheckButton.vue +75 -0
  203. package/templates/.claude/skills/frontend-vue/components/Control/Checkbox.vue +58 -0
  204. package/templates/.claude/skills/frontend-vue/components/Control/Datetime.vue +148 -0
  205. package/templates/.claude/skills/frontend-vue/components/Control/Dropdownlist.vue +156 -0
  206. package/templates/.claude/skills/frontend-vue/components/Control/Input.vue +106 -0
  207. package/templates/.claude/skills/frontend-vue/components/Control/Label.vue +38 -0
  208. package/templates/.claude/skills/frontend-vue/components/Control/Master/BoxColumn.vue +24 -0
  209. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Confirm.vue +33 -0
  210. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Info.vue +32 -0
  211. package/templates/.claude/skills/frontend-vue/components/Control/Popup/ModalInfo.vue +39 -0
  212. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Reject.vue +64 -0
  213. package/templates/.claude/skills/frontend-vue/components/Control/Tag.vue +82 -0
  214. package/templates/.claude/skills/frontend-vue/components/Control/Upload.vue +61 -0
  215. package/templates/.claude/skills/frontend-vue/components/ControlMobile/Dropdownlist.vue +103 -0
  216. package/templates/.claude/skills/frontend-vue/components/ControlMobile/PagingBar.vue +108 -0
  217. package/templates/.claude/skills/frontend-vue/components/ControlMobile/UploadImage.vue +137 -0
  218. package/templates/.claude/skills/frontend-vue/components/Grid/AG.vue +806 -0
  219. package/templates/.claude/skills/frontend-vue/components/Grid/AntTable.vue +253 -0
  220. package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditor.vue +43 -0
  221. package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditorEnable.vue +55 -0
  222. package/templates/.claude/skills/frontend-vue/components/Grid/HtmlTable.vue +40 -0
  223. package/templates/.claude/skills/frontend-vue/components/PDFViewer.vue +25 -0
  224. package/templates/.claude/skills/frontend-vue/components/Panel/FormView.vue +309 -0
  225. package/templates/.claude/skills/frontend-vue/components/Partial/Footer.vue +23 -0
  226. package/templates/.claude/skills/frontend-vue/components/Partial/Header.vue +265 -0
  227. package/templates/.claude/skills/frontend-vue/components/Partial/Sidebar.vue +122 -0
  228. package/templates/.claude/skills/frontend-vue/components/Template.vue +16 -0
  229. package/templates/.claude/skills/frontend-vue/components/View/Form.vue +89 -0
  230. package/templates/.claude/skills/frontend-vue/composables/indexDBStore.js +140 -0
  231. package/templates/.claude/skills/frontend-vue/composables/masterApi.js +362 -0
  232. package/templates/.claude/skills/frontend-vue/composables/state.js +578 -0
  233. package/templates/.claude/skills/frontend-vue/composables/useRequest.js +221 -0
  234. package/templates/.claude/skills/frontend-vue/composables/useSession.js +179 -0
  235. package/templates/.claude/skills/frontend-vue/composables/useTranslation.js +54 -0
  236. package/templates/.claude/skills/frontend-vue/composables/useWebSocket.js +257 -0
  237. package/templates/.claude/skills/frontend-vue/composables/userObj.js +111 -0
  238. package/templates/.claude/skills/frontend-vue/composables/utils.js +322 -0
  239. package/templates/.claude/skills/frontend-vue/reference/composables-example.vue +320 -0
  240. package/templates/.claude/skills/frontend-vue/reference/form-example.vue +183 -0
  241. package/templates/.claude/skills/frontend-vue/reference/grid-example.vue +147 -0
  242. package/templates/.claude/skills/frontend-vue/reference/masterdata-example/[id].vue +106 -0
  243. package/templates/.claude/skills/frontend-vue/reference/masterdata-example/index.vue +58 -0
  244. package/templates/.claude/skills/frontend-vue/reference/popup-example.vue +159 -0
  245. package/templates/.claude/skills/pdf/LICENSE.txt +30 -0
  246. package/templates/.claude/skills/pdf/SKILL.md +294 -0
  247. package/templates/.claude/skills/pdf/forms.md +205 -0
  248. package/templates/.claude/skills/pdf/reference.md +612 -0
  249. package/templates/.claude/skills/pdf/scripts/check_bounding_boxes.py +70 -0
  250. package/templates/.claude/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  251. package/templates/.claude/skills/pdf/scripts/check_fillable_fields.py +12 -0
  252. package/templates/.claude/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  253. package/templates/.claude/skills/pdf/scripts/create_validation_image.py +41 -0
  254. package/templates/.claude/skills/pdf/scripts/extract_form_field_info.py +152 -0
  255. package/templates/.claude/skills/pdf/scripts/fill_fillable_fields.py +114 -0
  256. package/templates/.claude/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  257. package/templates/.claude/skills/pdf-processing/SKILL.md +107 -0
  258. package/templates/.claude/skills/pdf-processing-pro/FORMS.md +610 -0
  259. package/templates/.claude/skills/pdf-processing-pro/OCR.md +137 -0
  260. package/templates/.claude/skills/pdf-processing-pro/SKILL.md +296 -0
  261. package/templates/.claude/skills/pdf-processing-pro/TABLES.md +626 -0
  262. package/templates/.claude/skills/pdf-processing-pro/scripts/analyze_form.py +307 -0
  263. package/templates/.claude/skills/postgres/SKILL.md +69 -0
  264. package/templates/.claude/skills/postgres/reference/fn_get_examples.sql +208 -0
  265. package/templates/.claude/skills/postgres/reference/fn_rpt_examples.sql +239 -0
  266. package/templates/.claude/skills/postgres/reference/utility_functions.sql +94 -0
  267. package/templates/.claude/skills/pptx/LICENSE.txt +30 -0
  268. package/templates/.claude/skills/pptx/SKILL.md +484 -0
  269. package/templates/.claude/skills/pptx/html2pptx.md +625 -0
  270. package/templates/.claude/skills/pptx/ooxml.md +427 -0
  271. package/templates/.claude/skills/pptx/scripts/html2pptx.js +979 -0
  272. package/templates/.claude/skills/pptx/scripts/inventory.py +1020 -0
  273. package/templates/.claude/skills/pptx/scripts/rearrange.py +231 -0
  274. package/templates/.claude/skills/pptx/scripts/replace.py +385 -0
  275. package/templates/.claude/skills/pptx/scripts/thumbnail.py +450 -0
  276. package/templates/.claude/skills/repo-maintenance/SKILL.md +97 -0
  277. package/templates/.claude/skills/research/EXAMPLES.md +434 -0
  278. package/templates/.claude/skills/research/REFERENCE.md +399 -0
  279. package/templates/.claude/skills/research/SKILL.md +136 -0
  280. package/templates/.claude/skills/root-cause-tracing/SKILL.md +174 -0
  281. package/templates/.claude/skills/root-cause-tracing/find-polluter.sh +63 -0
  282. package/templates/.claude/skills/sharing-skills/SKILL.md +194 -0
  283. package/templates/.claude/skills/sql-optimization-patterns/SKILL.md +493 -0
  284. package/templates/.claude/skills/subagent-driven-development/SKILL.md +189 -0
  285. package/templates/.claude/skills/systematic-debugging/CREATION-LOG.md +119 -0
  286. package/templates/.claude/skills/systematic-debugging/SKILL.md +295 -0
  287. package/templates/.claude/skills/systematic-debugging/test-academic.md +14 -0
  288. package/templates/.claude/skills/systematic-debugging/test-pressure-1.md +58 -0
  289. package/templates/.claude/skills/systematic-debugging/test-pressure-2.md +68 -0
  290. package/templates/.claude/skills/systematic-debugging/test-pressure-3.md +69 -0
  291. package/templates/.claude/skills/test-driven-development/SKILL.md +364 -0
  292. package/templates/.claude/skills/testing-anti-patterns/SKILL.md +302 -0
  293. package/templates/.claude/skills/testing-quality/SKILL.md +97 -0
  294. package/templates/.claude/skills/verification-before-completion/SKILL.md +139 -0
  295. package/templates/.claude/skills/webapp-testing/LICENSE.txt +202 -0
  296. package/templates/.claude/skills/webapp-testing/SKILL.md +96 -0
  297. package/templates/.claude/skills/webapp-testing/examples/console_logging.py +35 -0
  298. package/templates/.claude/skills/webapp-testing/examples/element_discovery.py +40 -0
  299. package/templates/.claude/skills/webapp-testing/examples/static_html_automation.py +33 -0
  300. package/templates/.claude/skills/webapp-testing/scripts/with_server.py +106 -0
  301. package/templates/.claude/ukit/index/build-index.mjs +28 -0
  302. package/templates/.claude/ukit/index/cache-utils.mjs +140 -0
  303. package/templates/.claude/ukit/index/lib/index-core.mjs +2800 -0
  304. package/templates/.claude/ukit/index/query-index.mjs +150 -0
  305. package/templates/.claude/ukit/index/refresh-index.mjs +57 -0
  306. package/templates/.claude/ukit/index/reset-auto-permissions.mjs +76 -0
  307. package/templates/.claude/ukit/index/resolve-context.mjs +279 -0
  308. package/templates/.claude/ukit/index/route-catalog.mjs +258 -0
  309. package/templates/.claude/ukit/index/route-task.mjs +1994 -0
  310. package/templates/.claude/ukit/index/triage.mjs +133 -0
  311. package/templates/.claude/ukit/index/verify-context.mjs +689 -0
  312. package/templates/.claude/ukit/runtime/compact-threshold.mjs +1013 -0
  313. package/templates/.claude/ukit/runtime/output-compression.mjs +1340 -0
  314. package/templates/.claude/ukit/runtime/reinject-context.mjs +874 -0
  315. package/templates/.claude/ukit/runtime/token-utils.mjs +500 -0
  316. package/templates/.codex/README.md +83 -0
  317. package/templates/.codex/settings.json +187 -0
  318. package/templates/.gitignore +75 -0
  319. package/templates/AGENTS.md +116 -0
  320. package/templates/CLAUDE.md +93 -0
  321. package/templates/adapter-presets/antigravity/README.md +22 -0
  322. package/templates/adapter-presets/antigravity/rules.md +49 -0
  323. package/templates/adapter-presets/claude/settings.local.json +42 -0
  324. package/templates/adapter-presets/codex/settings.local.json +6 -0
  325. package/templates/adapter-presets/opencode/opencode.template.json +1 -0
  326. package/templates/docs/BUGFIX.md +20 -0
  327. package/templates/docs/BUG_INDEX.md +12 -0
  328. package/templates/docs/BUG_METRICS.md +7 -0
  329. package/templates/docs/BUG_TEMPLATE.md +13 -0
  330. package/templates/docs/CODE_MAP.md +35 -0
  331. package/templates/docs/INSTALL.md +113 -0
  332. package/templates/docs/MEMORY.md +49 -0
  333. package/templates/docs/PROJECT.md +50 -0
  334. package/templates/docs/UKIT_USAGE_GUIDE.md +147 -0
  335. package/templates/docs/WORKLOG.md +10 -0
  336. package/templates/ukit/README.md +14 -0
  337. package/templates/ukit/storage/cache/compact-history.json +3 -0
  338. package/templates/ukit/storage/cache/compact-pressure.json +1 -0
  339. package/templates/ukit/storage/cache/output-history.json +3 -0
  340. package/templates/ukit/storage/cache/prompt-cache.json +3 -0
  341. package/templates/ukit/storage/config.json +37 -0
  342. package/templates/ukit/storage/memory/projects/.gitkeep +2 -0
  343. package/templates/ukit/storage/memory/sessions/.gitkeep +0 -0
  344. package/templates/ukit/storage/memory/user.json +5 -0
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import crypto from 'node:crypto';
4
+ import * as indexCore from './lib/index-core.mjs';
5
+ import {
6
+ DEFAULT_RECENT_CACHE_MAX_ENTRIES,
7
+ readRecentCacheEntry,
8
+ writeRecentCacheEntry,
9
+ } from './cache-utils.mjs';
10
+
11
+ const {
12
+ queryCodeIndex,
13
+ buildCodeIndex,
14
+ DEFAULT_INDEX_CACHE_MAX_AGE_MS,
15
+ getIndexArtifactGeneratedAt,
16
+ } = indexCore;
17
+
18
+ const args = process.argv.slice(2);
19
+ const rootDir = getRootDir(args);
20
+ const limitArg = readFlagValue(args, '--limit');
21
+ const limit = Number.parseInt(limitArg ?? '5', 10);
22
+ const query = collectPositionalArgs(args, ['--root', '--limit']);
23
+
24
+ if (!query) {
25
+ console.error('Usage: node .claude/ukit/index/query-index.mjs "<error|symbol|path>"');
26
+ process.exitCode = 1;
27
+ } else {
28
+ const indexGeneratedAtMs = await ensureFreshIndex({ rootDir, logPrefix: 'index:query' });
29
+ const effectiveLimit = Number.isNaN(limit) ? 5 : limit;
30
+ const cachePath = path.join(rootDir, '.claude', 'ukit', 'query-index-cache.json');
31
+ const requestKey = buildQueryRequestKey({
32
+ indexGeneratedAtMs,
33
+ query,
34
+ limit: effectiveLimit,
35
+ });
36
+ const cached = await readRecentCacheEntry(cachePath, requestKey, {
37
+ maxEntries: DEFAULT_RECENT_CACHE_MAX_ENTRIES,
38
+ touch: true,
39
+ });
40
+ const results = cached?.result
41
+ ?? await queryCodeIndex({
42
+ rootDir,
43
+ query,
44
+ limit: effectiveLimit,
45
+ });
46
+
47
+ if (!cached) {
48
+ await writeRecentCacheEntry(cachePath, {
49
+ requestKey,
50
+ updatedAt: Date.now(),
51
+ result: results,
52
+ }, {
53
+ maxEntries: DEFAULT_RECENT_CACHE_MAX_ENTRIES,
54
+ });
55
+ }
56
+
57
+ if (results.length === 0) {
58
+ console.log('[ukit:index:query] no matches');
59
+ } else {
60
+ console.log(`[ukit:index:query] top ${results.length} matches for: ${query}`);
61
+ for (const [idx, item] of results.entries()) {
62
+ console.log(`${idx + 1}. ${item.filePath} (score=${item.score})`);
63
+ if ((item.tests ?? []).length > 0) {
64
+ console.log(` tests: ${item.tests.slice(0, 2).join(', ')}`);
65
+ }
66
+ if ((item.reasons ?? []).length > 0) {
67
+ console.log(` reasons: ${item.reasons.join(', ')}`);
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ async function ensureFreshIndex({ rootDir, logPrefix }) {
74
+ const lastRefreshMs = await getIndexArtifactGeneratedAt({ rootDir });
75
+ const stale = lastRefreshMs === null
76
+ ? true
77
+ : typeof indexCore.isIndexStale === 'function'
78
+ ? await indexCore.isIndexStale({
79
+ rootDir,
80
+ maxAgeMs: DEFAULT_INDEX_CACHE_MAX_AGE_MS,
81
+ now: Date.now(),
82
+ generatedAtMs: lastRefreshMs,
83
+ })
84
+ : (Date.now() - lastRefreshMs) > DEFAULT_INDEX_CACHE_MAX_AGE_MS;
85
+
86
+ if (!stale) {
87
+ return lastRefreshMs;
88
+ }
89
+
90
+ const summary = await buildCodeIndex({ rootDir });
91
+ if (lastRefreshMs !== null) {
92
+ console.log(`[ukit:${logPrefix}] stale index refreshed (last=${new Date(lastRefreshMs).toISOString()})`);
93
+ } else {
94
+ console.log(`[ukit:${logPrefix}] stale index refreshed (no previous cache timestamp)`);
95
+ }
96
+ return Number.isFinite(summary?.generatedAtMs)
97
+ ? summary.generatedAtMs
98
+ : getIndexArtifactGeneratedAt({ rootDir });
99
+ }
100
+
101
+ function buildQueryRequestKey({
102
+ indexGeneratedAtMs = null,
103
+ query = '',
104
+ limit = 5,
105
+ } = {}) {
106
+ return buildCompactMachineKey('query-v1', {
107
+ indexGeneratedAtMs,
108
+ query: String(query || '').trim(),
109
+ limit: Number(limit),
110
+ });
111
+ }
112
+
113
+ function buildCompactMachineKey(prefix, payload) {
114
+ return `${prefix}:${stableMachineDigest(payload)}`;
115
+ }
116
+
117
+ function stableMachineDigest(payload) {
118
+ return crypto
119
+ .createHash('sha256')
120
+ .update(JSON.stringify(payload))
121
+ .digest('base64url');
122
+ }
123
+
124
+ function getRootDir(argv) {
125
+ const value = readFlagValue(argv, '--root');
126
+ return value ? path.resolve(value) : process.cwd();
127
+ }
128
+
129
+ function readFlagValue(argv, flag) {
130
+ const exact = argv.indexOf(flag);
131
+ if (exact >= 0 && argv[exact + 1]) return argv[exact + 1];
132
+ const withEquals = argv.find((item) => item.startsWith(`${flag}=`));
133
+ return withEquals ? withEquals.slice(flag.length + 1) : null;
134
+ }
135
+
136
+ function collectPositionalArgs(argv, flagsWithValues = []) {
137
+ return argv
138
+ .filter((arg, index) => !isFlagOrValue(argv, index, flagsWithValues))
139
+ .join(' ')
140
+ .trim();
141
+ }
142
+
143
+ function isFlagOrValue(argv, index, flagsWithValues = []) {
144
+ const arg = argv[index];
145
+ if (!arg.startsWith('--')) {
146
+ const prev = argv[index - 1];
147
+ return Boolean(prev && flagsWithValues.includes(prev));
148
+ }
149
+ return true;
150
+ }
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import {
4
+ buildCodeIndex,
5
+ isIndexStale,
6
+ DEFAULT_INDEX_CACHE_MAX_AGE_MS,
7
+ getIndexArtifactGeneratedAt,
8
+ } from './lib/index-core.mjs';
9
+
10
+ const args = process.argv.slice(2);
11
+ const rootDir = getRootDir(args);
12
+ const changedArg = readFlagValue(args, '--changed');
13
+ const changedFiles = changedArg ? changedArg.split(',').map((x) => x.trim()).filter(Boolean) : [];
14
+ const force = args.includes('--force');
15
+
16
+ const lastRefreshMs = await getIndexArtifactGeneratedAt({ rootDir });
17
+ const stale = force
18
+ ? true
19
+ : await isIndexStale({ rootDir, maxAgeMs: DEFAULT_INDEX_CACHE_MAX_AGE_MS, generatedAtMs: lastRefreshMs });
20
+
21
+ if (!stale) {
22
+ console.log('[ukit:index:refresh] skipped (cache fresh)');
23
+ if (lastRefreshMs !== null) {
24
+ console.log(`lastRefresh: ${new Date(lastRefreshMs).toISOString()}`);
25
+ }
26
+ if (changedFiles.length > 0) {
27
+ console.log(`changed-files-hint: ${changedFiles.join(', ')}`);
28
+ }
29
+ console.log(`root: ${rootDir}`);
30
+ } else {
31
+ const summary = await buildCodeIndex({ rootDir });
32
+
33
+ console.log('[ukit:index:refresh] completed');
34
+ if (lastRefreshMs !== null) {
35
+ console.log(`lastRefreshBefore: ${new Date(lastRefreshMs).toISOString()}`);
36
+ }
37
+ if (changedFiles.length > 0) {
38
+ console.log(`changed-files-hint: ${changedFiles.join(', ')}`);
39
+ }
40
+ console.log(`root: ${rootDir}`);
41
+ console.log(`files: ${summary.fileCount}`);
42
+ console.log(`parsed: ${summary.parsedCodeFileCount}`);
43
+ console.log(`reused: ${summary.reusedCodeFileCount}`);
44
+ console.log(`indexDir: ${summary.indexDir}`);
45
+ }
46
+
47
+ function getRootDir(argv) {
48
+ const value = readFlagValue(argv, '--root');
49
+ return value ? path.resolve(value) : process.cwd();
50
+ }
51
+
52
+ function readFlagValue(argv, flag) {
53
+ const exact = argv.indexOf(flag);
54
+ if (exact >= 0 && argv[exact + 1]) return argv[exact + 1];
55
+ const withEquals = argv.find((item) => item.startsWith(`${flag}=`));
56
+ return withEquals ? withEquals.slice(flag.length + 1) : null;
57
+ }
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+
5
+ function parseArgs(argv) {
6
+ return {
7
+ dryRun: argv.includes('--dry-run'),
8
+ quiet: argv.includes('--quiet'),
9
+ };
10
+ }
11
+
12
+ async function readJson(filePath, fallback) {
13
+ try {
14
+ const raw = await fs.readFile(filePath, 'utf8');
15
+ return JSON.parse(raw);
16
+ } catch {
17
+ return fallback;
18
+ }
19
+ }
20
+
21
+ async function writeJson(filePath, value) {
22
+ await fs.writeFile(filePath, JSON.stringify(value, null, 2) + '\n', 'utf8');
23
+ }
24
+
25
+ async function main() {
26
+ const { dryRun, quiet } = parseArgs(process.argv.slice(2));
27
+ const rootDir = process.cwd();
28
+ const settingsLocalPath = path.join(rootDir, '.claude', 'settings.local.json');
29
+ const usagePath = path.join(rootDir, '.claude', 'ukit', 'permission-usage.json');
30
+ const auditPath = path.join(rootDir, '.claude', 'ukit', 'permission-audit.log');
31
+
32
+ const settings = await readJson(settingsLocalPath, {});
33
+ const usage = await readJson(usagePath, {});
34
+
35
+ const managedRules = Object.keys(usage?.managedRules || {});
36
+ const allow = Array.isArray(settings?.permissions?.allow) ? settings.permissions.allow : [];
37
+
38
+ const removedRules = allow.filter((rule) => managedRules.includes(rule));
39
+ if (managedRules.length === 0) {
40
+ if (!quiet) {
41
+ console.log('[UKit] No managed auto-permission rules to reset.');
42
+ }
43
+ return;
44
+ }
45
+
46
+ if (!dryRun) {
47
+ settings.permissions = settings.permissions && typeof settings.permissions === 'object' ? settings.permissions : {};
48
+ settings.permissions.allow = allow.filter((rule) => !managedRules.includes(rule));
49
+ await fs.mkdir(path.dirname(settingsLocalPath), { recursive: true });
50
+ await writeJson(settingsLocalPath, settings);
51
+
52
+ usage.managedRules = {};
53
+ usage.lastResetAt = new Date().toISOString();
54
+ await fs.mkdir(path.dirname(usagePath), { recursive: true });
55
+ await writeJson(usagePath, usage);
56
+
57
+ const lines = removedRules
58
+ .map((rule) => JSON.stringify({ ts: new Date().toISOString(), event: 'manual_reset', rule }))
59
+ .join('\n');
60
+ await fs.mkdir(path.dirname(auditPath), { recursive: true });
61
+ await fs.appendFile(auditPath, lines + '\n', 'utf8');
62
+ }
63
+
64
+ if (!quiet) {
65
+ const mode = dryRun ? 'Would remove' : 'Removed';
66
+ console.log(`[UKit] ${mode} ${managedRules.length} managed auto-permission rule(s).`);
67
+ for (const rule of removedRules) {
68
+ console.log(`- ${rule}`);
69
+ }
70
+ }
71
+ }
72
+
73
+ main().catch((error) => {
74
+ console.error('[UKit] Failed to reset auto permissions:', error?.message || String(error));
75
+ process.exitCode = 1;
76
+ });
@@ -0,0 +1,279 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import crypto from 'node:crypto';
4
+ import * as indexCore from './lib/index-core.mjs';
5
+ import {
6
+ DEFAULT_RECENT_CACHE_MAX_ENTRIES,
7
+ readRecentCacheEntry,
8
+ writeRecentCacheEntry,
9
+ } from './cache-utils.mjs';
10
+
11
+ const {
12
+ resolveContext,
13
+ buildCodeIndex,
14
+ DEFAULT_INDEX_CACHE_MAX_AGE_MS,
15
+ getIndexArtifactGeneratedAt,
16
+ } = indexCore;
17
+ const CONTEXT_DISPLAY_LIMIT = 2;
18
+ const CONTEXT_REASON_LIMIT = 2;
19
+
20
+ const args = process.argv.slice(2);
21
+ const rootDir = getRootDir(args);
22
+ const targetFile = readFlagValue(args, '--target');
23
+ const taskType = readFlagValue(args, '--type');
24
+ const intent = collectPositionalArgs(args, ['--root', '--target', '--type']);
25
+ const effectiveIntent = deriveHelperIntent({ intent, targetFile });
26
+
27
+ if (!intent && !targetFile) {
28
+ console.error('Usage: node .claude/ukit/index/resolve-context.mjs "<intent>" [--target <file>] [--type trivial|simple|non-trivial]');
29
+ process.exitCode = 1;
30
+ } else {
31
+ const indexGeneratedAtMs = await ensureFreshIndex({
32
+ rootDir,
33
+ logPrefix: 'context',
34
+ });
35
+ const cachePath = path.join(rootDir, '.claude', 'ukit', 'resolve-context-cache.json');
36
+ const requestKey = buildRequestKey({
37
+ indexGeneratedAtMs,
38
+ intent: effectiveIntent,
39
+ targetFile,
40
+ taskType,
41
+ });
42
+ const cached = await readRecentCacheEntry(cachePath, requestKey, {
43
+ maxEntries: DEFAULT_RECENT_CACHE_MAX_ENTRIES,
44
+ touch: true,
45
+ });
46
+ const computedResult = cached?.result
47
+ ?? await resolveContext({ rootDir, intent: effectiveIntent, targetFile, taskType });
48
+ const result = expandHelperContext(computedResult);
49
+
50
+ if (!cached) {
51
+ await writeRecentCacheEntry(cachePath, {
52
+ requestKey,
53
+ updatedAt: Date.now(),
54
+ result,
55
+ }, {
56
+ maxEntries: DEFAULT_RECENT_CACHE_MAX_ENTRIES,
57
+ });
58
+ }
59
+
60
+ printContextResult(result);
61
+ }
62
+
63
+ async function ensureFreshIndex({ rootDir, logPrefix }) {
64
+ const lastRefreshMs = await getIndexArtifactGeneratedAt({ rootDir });
65
+ const stale = lastRefreshMs === null
66
+ ? true
67
+ : typeof indexCore.isIndexStale === 'function'
68
+ ? await indexCore.isIndexStale({
69
+ rootDir,
70
+ maxAgeMs: DEFAULT_INDEX_CACHE_MAX_AGE_MS,
71
+ now: Date.now(),
72
+ generatedAtMs: lastRefreshMs,
73
+ })
74
+ : (Date.now() - lastRefreshMs) > DEFAULT_INDEX_CACHE_MAX_AGE_MS;
75
+
76
+ if (!stale) {
77
+ return lastRefreshMs;
78
+ }
79
+
80
+ const summary = await buildCodeIndex({ rootDir });
81
+ if (lastRefreshMs !== null) {
82
+ console.log(`[ukit:${logPrefix}] stale index refreshed (last=${new Date(lastRefreshMs).toISOString()})`);
83
+ } else {
84
+ console.log(`[ukit:${logPrefix}] stale index refreshed (no previous cache timestamp)`);
85
+ }
86
+ return Number.isFinite(summary?.generatedAtMs)
87
+ ? summary.generatedAtMs
88
+ : getIndexArtifactGeneratedAt({ rootDir });
89
+ }
90
+
91
+ function getRootDir(argv) {
92
+ const value = readFlagValue(argv, '--root');
93
+ return value ? path.resolve(value) : process.cwd();
94
+ }
95
+
96
+ function readFlagValue(argv, flag) {
97
+ const exact = argv.indexOf(flag);
98
+ if (exact >= 0 && argv[exact + 1]) return argv[exact + 1];
99
+ const withEquals = argv.find((item) => item.startsWith(`${flag}=`));
100
+ return withEquals ? withEquals.slice(flag.length + 1) : null;
101
+ }
102
+
103
+ function collectPositionalArgs(argv, flagsWithValues = []) {
104
+ return argv
105
+ .filter((arg, index) => !isFlagOrValue(argv, index, flagsWithValues))
106
+ .join(' ')
107
+ .trim();
108
+ }
109
+
110
+ function isFlagOrValue(argv, index, flagsWithValues = []) {
111
+ const arg = argv[index];
112
+ if (!arg.startsWith('--')) {
113
+ const prev = argv[index - 1];
114
+ return Boolean(prev && flagsWithValues.includes(prev));
115
+ }
116
+ return true;
117
+ }
118
+
119
+ function buildRequestKey({
120
+ indexGeneratedAtMs = null,
121
+ intent = '',
122
+ targetFile = null,
123
+ taskType = null,
124
+ } = {}) {
125
+ return buildCompactMachineKey('resolve-v1', {
126
+ indexGeneratedAtMs,
127
+ intent: String(intent || '').trim(),
128
+ targetFile: String(targetFile || '').trim(),
129
+ taskType: String(taskType || '').trim(),
130
+ });
131
+ }
132
+
133
+ function buildCompactMachineKey(prefix, payload) {
134
+ return `${prefix}:${stableMachineDigest(payload)}`;
135
+ }
136
+
137
+ function stableMachineDigest(payload) {
138
+ return crypto
139
+ .createHash('sha256')
140
+ .update(JSON.stringify(payload))
141
+ .digest('base64url');
142
+ }
143
+
144
+ function deriveHelperIntent({ intent = '', targetFile = null } = {}) {
145
+ const normalizedIntent = String(intent || '').trim();
146
+ if (normalizedIntent) {
147
+ return normalizedIntent;
148
+ }
149
+
150
+ const normalizedTarget = String(targetFile || '').trim();
151
+ if (!normalizedTarget) {
152
+ return '';
153
+ }
154
+
155
+ if (/^docs\//i.test(normalizedTarget)) {
156
+ return `update docs for ${normalizedTarget}`;
157
+ }
158
+
159
+ return `work on ${normalizedTarget}`;
160
+ }
161
+
162
+ function expandHelperContext(contextResult) {
163
+ if (!contextResult) {
164
+ return contextResult;
165
+ }
166
+
167
+ const directTests = (contextResult.primaryTargets ?? []).filter(isTestLikeFile);
168
+ if (directTests.length === 0) {
169
+ return contextResult;
170
+ }
171
+
172
+ const relatedTests = unique([
173
+ ...(contextResult.relatedTests ?? []),
174
+ ...directTests,
175
+ ]);
176
+ const relatedTestExplanations = mergeRelatedTestExplanations(
177
+ contextResult.explanations?.relatedTests ?? [],
178
+ directTests,
179
+ );
180
+
181
+ return {
182
+ ...contextResult,
183
+ relatedTests,
184
+ explanations: {
185
+ ...(contextResult.explanations ?? {}),
186
+ relatedTests: relatedTestExplanations,
187
+ },
188
+ };
189
+ }
190
+
191
+ function mergeRelatedTestExplanations(existingExplanations = [], directTests = []) {
192
+ const next = [...existingExplanations];
193
+
194
+ for (const filePath of directTests) {
195
+ const existing = next.find((entry) => entry.filePath === filePath);
196
+ const reason = `direct test target ${filePath}`;
197
+ if (!existing) {
198
+ next.push({ filePath, reason });
199
+ continue;
200
+ }
201
+ if (!String(existing.reason || '').includes(reason)) {
202
+ existing.reason = existing.reason
203
+ ? `${existing.reason}; ${reason}`
204
+ : reason;
205
+ }
206
+ }
207
+
208
+ return next;
209
+ }
210
+
211
+ function isTestLikeFile(filePath) {
212
+ return /\.(test|spec)\.[a-z0-9]+$/i.test(filePath)
213
+ || /(^|\/)(?:__tests__|tests?|specs?)\//i.test(filePath);
214
+ }
215
+
216
+ function unique(values = []) {
217
+ return [...new Set(values.filter(Boolean))];
218
+ }
219
+
220
+ function printContextResult(result) {
221
+ console.log('[ukit:context]');
222
+ console.log(`taskType: ${result.taskType}`);
223
+ console.log(`budget: ${result.contextBudget.minFiles}-${result.contextBudget.maxFiles} files`);
224
+ printContextGroup('primaryTargets', result.primaryTargets, result.explanations?.primaryTargets);
225
+ printContextGroup('sharedAbstractions', result.sharedAbstractions, result.explanations?.sharedAbstractions);
226
+ printContextGroup('analogFiles', result.analogFiles, result.explanations?.analogFiles);
227
+ printContextGroup('relatedTests', result.relatedTests, result.explanations?.relatedTests);
228
+ printContextGroup('styleFiles', result.styleFiles, result.explanations?.styleFiles);
229
+ }
230
+
231
+ function printContextGroup(label, filePaths = [], explanations = []) {
232
+ console.log(`${label}: ${formatCompactDisplayList(filePaths)}`);
233
+
234
+ const normalizedExplanations = uniqueContextExplanations(explanations);
235
+ for (const item of normalizedExplanations.slice(0, CONTEXT_REASON_LIMIT)) {
236
+ console.log(` - ${item.filePath}: ${item.reason}`);
237
+ }
238
+
239
+ const remainingReasonCount = normalizedExplanations.length - Math.min(normalizedExplanations.length, CONTEXT_REASON_LIMIT);
240
+ if (remainingReasonCount > 0) {
241
+ console.log(` - +${remainingReasonCount} more reasons`);
242
+ }
243
+ }
244
+
245
+ function formatCompactDisplayList(values = [], limit = CONTEXT_DISPLAY_LIMIT) {
246
+ const normalized = [...new Set((values ?? []).filter(Boolean))];
247
+ if (normalized.length === 0) {
248
+ return 'none';
249
+ }
250
+
251
+ const shown = normalized.slice(0, limit);
252
+ const remaining = normalized.length - shown.length;
253
+ return remaining > 0
254
+ ? `${shown.join(', ')}, +${remaining} more`
255
+ : shown.join(', ');
256
+ }
257
+
258
+ function uniqueContextExplanations(explanations = []) {
259
+ const seen = new Set();
260
+ const unique = [];
261
+
262
+ for (const item of explanations ?? []) {
263
+ const filePath = String(item?.filePath ?? '').trim();
264
+ const reason = String(item?.reason ?? '').trim();
265
+ if (!filePath && !reason) {
266
+ continue;
267
+ }
268
+
269
+ const key = `${filePath}::${reason}`;
270
+ if (seen.has(key)) {
271
+ continue;
272
+ }
273
+
274
+ seen.add(key);
275
+ unique.push({ filePath, reason });
276
+ }
277
+
278
+ return unique;
279
+ }