@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,328 @@
1
+ import crypto from 'node:crypto';
2
+ import { readJsonIfExists, writeJson } from '../fileOps.js';
3
+ import { buildRuntimePaths } from '../runtimePaths.js';
4
+
5
+ export const DEFAULT_PROMPT_CACHE_MAX_ENTRIES = 20;
6
+
7
+ const HEADER_RE = /^\s*(?:#{1,6}\s|={3,}|-{3,})/;
8
+ const CODE_FENCE_RE = /^\s*```/;
9
+ const BULLET_RE = /^(\s*[-*]\s+)(.*)$/;
10
+ const COMMAND_RE = /^\s*(?:[$>#]\s*)?(?:node|npm|pnpm|yarn|bun|python(?:3)?|pip|git|docker|kubectl|make|cargo|go|java|pytest|vitest|npx)\b/i;
11
+ const STRUCTURED_LINE_RE = /https?:\/\/|(?:^|[\s(])(?:src|tests?|docs|ukit|\.claude|\.codex|app|lib|packages|scripts)\//i;
12
+ const VERBOSE_REPLACEMENTS = [
13
+ [/\bplease\b/gi, ''],
14
+ [/\bremember to\b/gi, ''],
15
+ [/\bmake sure to\b/gi, 'ensure '],
16
+ [/\bin order to\b/gi, 'to'],
17
+ [/\bfor the current task\b/gi, 'for this task'],
18
+ [/\bcurrent task\b/gi, 'task'],
19
+ [/\bprevious context block\b/gi, 'context block'],
20
+ [/\bshould still\b/gi, 'still'],
21
+ [/\bdo not wait for the user to\b/gi, "don't wait for the user to"],
22
+ ];
23
+
24
+ export function estimateTokenCount(value) {
25
+ const text = String(value ?? '').trim();
26
+ if (!text) {
27
+ return 0;
28
+ }
29
+
30
+ return Math.max(1, Math.ceil(text.length / 4));
31
+ }
32
+
33
+ export function buildCompactMachineKey(prefix, payload = {}) {
34
+ return `${prefix}:${crypto.createHash('sha256').update(JSON.stringify(payload)).digest('base64url')}`;
35
+ }
36
+
37
+ function isStructuredLine(line) {
38
+ return (
39
+ CODE_FENCE_RE.test(line)
40
+ || HEADER_RE.test(line)
41
+ || COMMAND_RE.test(line)
42
+ || STRUCTURED_LINE_RE.test(line)
43
+ || line.includes('`')
44
+ );
45
+ }
46
+
47
+ function normalizeWhitespace(value) {
48
+ return value
49
+ .replace(/\s+\|\s+/g, ' | ')
50
+ .replace(/\s*[:;]\s*/g, ': ')
51
+ .replace(/\s*,\s*/g, ', ')
52
+ .replace(/\s+/g, ' ')
53
+ .trim();
54
+ }
55
+
56
+ export function compressLine(line) {
57
+ const raw = String(line ?? '');
58
+ if (!raw.trim()) {
59
+ return '';
60
+ }
61
+
62
+ const trimmed = raw.trim();
63
+ if (isStructuredLine(trimmed)) {
64
+ return trimmed;
65
+ }
66
+
67
+ const bulletMatch = raw.match(BULLET_RE);
68
+ const prefix = bulletMatch ? '- ' : '';
69
+ let next = bulletMatch ? bulletMatch[2].trim() : trimmed;
70
+
71
+ for (const [pattern, replacement] of VERBOSE_REPLACEMENTS) {
72
+ next = next.replace(pattern, replacement);
73
+ }
74
+
75
+ next = normalizeWhitespace(next);
76
+ return prefix ? `${prefix}${next}` : next;
77
+ }
78
+
79
+ export function compressMarkdownLines(
80
+ lines,
81
+ {
82
+ maxTokens = 300,
83
+ maxLines = 12,
84
+ preserveFirstLine = true,
85
+ } = {},
86
+ ) {
87
+ const sourceLines = Array.isArray(lines) ? lines : [];
88
+ const selected = [];
89
+ const seen = new Set();
90
+ let usedTokens = 0;
91
+ let nonEmptyCount = 0;
92
+ let pendingBlankLine = false;
93
+
94
+ for (const [index, line] of sourceLines.entries()) {
95
+ const compressed = compressLine(line);
96
+ if (!compressed) {
97
+ pendingBlankLine = selected.length > 0 && selected[selected.length - 1] !== '';
98
+ continue;
99
+ }
100
+
101
+ const dedupeKey = compressed.toLowerCase();
102
+ if (seen.has(dedupeKey)) {
103
+ continue;
104
+ }
105
+
106
+ const tokens = estimateTokenCount(compressed);
107
+ const wouldOverflow = selected.length > 0 && (usedTokens + tokens) > maxTokens;
108
+ const wouldExceedLines = index > 0 && nonEmptyCount >= maxLines;
109
+
110
+ if (wouldOverflow || wouldExceedLines) {
111
+ break;
112
+ }
113
+
114
+ if (pendingBlankLine && selected.length > 0) {
115
+ selected.push('');
116
+ pendingBlankLine = false;
117
+ }
118
+
119
+ selected.push(compressed);
120
+ seen.add(dedupeKey);
121
+ usedTokens += tokens;
122
+ nonEmptyCount += 1;
123
+ }
124
+
125
+ if (preserveFirstLine && selected.length === 0 && sourceLines.length > 0) {
126
+ const fallback = compressLine(sourceLines[0]);
127
+ if (fallback) {
128
+ return [fallback];
129
+ }
130
+ }
131
+
132
+ return selected;
133
+ }
134
+
135
+ export function compressPromptBlock(text, options = {}) {
136
+ const rawText = String(text ?? '');
137
+ const rawLines = rawText.split(/\r?\n/);
138
+ const compactedLines = compressMarkdownLines(rawLines, options);
139
+ const compactedText = compactedLines.join('\n').trim();
140
+ const tokensBefore = estimateTokenCount(rawText);
141
+ const tokensAfter = estimateTokenCount(compactedText);
142
+
143
+ return {
144
+ text: compactedText,
145
+ tokensBefore,
146
+ tokensAfter,
147
+ savedTokens: Math.max(0, tokensBefore - tokensAfter),
148
+ };
149
+ }
150
+
151
+ function normalizePromptCacheEntry(entry) {
152
+ if (!entry || typeof entry !== 'object') {
153
+ return null;
154
+ }
155
+
156
+ const requestKey = typeof entry.requestKey === 'string' ? entry.requestKey.trim() : '';
157
+ if (!requestKey) {
158
+ return null;
159
+ }
160
+
161
+ const updatedAt = Number(entry.updatedAt);
162
+ const hitCount = Number(entry.hitCount);
163
+ const lastHitAt = Number(entry.lastHitAt);
164
+ const normalizedEntry = {
165
+ ...entry,
166
+ requestKey,
167
+ updatedAt: Number.isFinite(updatedAt) ? updatedAt : Date.now(),
168
+ hitCount: Number.isFinite(hitCount) && hitCount >= 0 ? hitCount : 0,
169
+ lastHitAt: Number.isFinite(lastHitAt) ? lastHitAt : null,
170
+ };
171
+ delete normalizedEntry.entries;
172
+ return normalizedEntry;
173
+ }
174
+
175
+ function normalizePromptCacheDocument(raw, { maxEntries = DEFAULT_PROMPT_CACHE_MAX_ENTRIES } = {}) {
176
+ const candidates = [];
177
+
178
+ if (Array.isArray(raw?.entries)) {
179
+ candidates.push(...raw.entries);
180
+ }
181
+
182
+ if (
183
+ !Array.isArray(raw?.entries)
184
+ && raw
185
+ && typeof raw === 'object'
186
+ && typeof raw.requestKey === 'string'
187
+ && raw.requestKey.trim()
188
+ ) {
189
+ candidates.push(raw);
190
+ }
191
+
192
+ const entries = candidates
193
+ .map((entry) => normalizePromptCacheEntry(entry))
194
+ .filter(Boolean)
195
+ .sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))
196
+ .filter((entry, index, list) => list.findIndex((candidate) => candidate.requestKey === entry.requestKey) === index)
197
+ .slice(0, maxEntries);
198
+
199
+ return {
200
+ entries,
201
+ };
202
+ }
203
+
204
+ async function readPromptCacheDocument(projectRoot, options = {}) {
205
+ const runtimePaths = buildRuntimePaths(projectRoot);
206
+ const raw = await readJsonIfExists(runtimePaths.promptCachePath);
207
+ return normalizePromptCacheDocument(raw, options);
208
+ }
209
+
210
+ async function writePromptCacheDocument(projectRoot, document) {
211
+ const runtimePaths = buildRuntimePaths(projectRoot);
212
+ await writeJson(runtimePaths.promptCachePath, document);
213
+ }
214
+
215
+ export async function readPromptCache(projectRoot, options = {}) {
216
+ return readPromptCacheDocument(projectRoot, options);
217
+ }
218
+
219
+ export async function readPromptCacheEntry(
220
+ projectRoot,
221
+ requestKey,
222
+ {
223
+ maxEntries = DEFAULT_PROMPT_CACHE_MAX_ENTRIES,
224
+ touch = false,
225
+ } = {},
226
+ ) {
227
+ if (typeof requestKey !== 'string' || !requestKey.trim()) {
228
+ return null;
229
+ }
230
+
231
+ const cache = await readPromptCacheDocument(projectRoot, { maxEntries });
232
+ const entryIndex = cache.entries.findIndex((entry) => entry.requestKey === requestKey);
233
+ if (entryIndex < 0) {
234
+ return null;
235
+ }
236
+
237
+ const entry = cache.entries[entryIndex];
238
+ if (!touch) {
239
+ return entry;
240
+ }
241
+
242
+ const touchedEntry = {
243
+ ...entry,
244
+ updatedAt: Date.now(),
245
+ lastHitAt: Date.now(),
246
+ hitCount: (entry.hitCount ?? 0) + 1,
247
+ };
248
+ const entries = [
249
+ touchedEntry,
250
+ ...cache.entries.slice(0, entryIndex),
251
+ ...cache.entries.slice(entryIndex + 1),
252
+ ].slice(0, maxEntries);
253
+ const nextDocument = normalizePromptCacheDocument({ entries }, { maxEntries });
254
+ await writePromptCacheDocument(projectRoot, nextDocument);
255
+ return nextDocument.entries[0] ?? touchedEntry;
256
+ }
257
+
258
+ export async function writePromptCacheEntry(
259
+ projectRoot,
260
+ entry,
261
+ {
262
+ maxEntries = DEFAULT_PROMPT_CACHE_MAX_ENTRIES,
263
+ } = {},
264
+ ) {
265
+ const normalizedEntry = normalizePromptCacheEntry(entry);
266
+ if (!normalizedEntry) {
267
+ return readPromptCacheDocument(projectRoot, { maxEntries });
268
+ }
269
+
270
+ const cache = await readPromptCacheDocument(projectRoot, { maxEntries });
271
+ const entries = [
272
+ normalizedEntry,
273
+ ...cache.entries.filter((existingEntry) => existingEntry.requestKey !== normalizedEntry.requestKey),
274
+ ].slice(0, maxEntries);
275
+ const nextDocument = normalizePromptCacheDocument({ entries }, { maxEntries });
276
+ await writePromptCacheDocument(projectRoot, nextDocument);
277
+ return nextDocument;
278
+ }
279
+
280
+ export function buildPromptCacheStats(rawCache) {
281
+ const cache = normalizePromptCacheDocument(rawCache);
282
+ const totalEntries = cache.entries.length;
283
+ const totalHits = cache.entries.reduce((sum, entry) => sum + (entry.hitCount ?? 0), 0);
284
+ const totalBefore = cache.entries.reduce((sum, entry) => sum + (entry.tokensBefore ?? 0), 0);
285
+ const totalSaved = cache.entries.reduce((sum, entry) => sum + (entry.savedTokens ?? 0), 0);
286
+ const savingsPercent = totalBefore > 0 ? Math.trunc((totalSaved / totalBefore) * 100) : 0;
287
+ const byKindMap = new Map();
288
+
289
+ for (const entry of cache.entries) {
290
+ const kind = typeof entry.kind === 'string' && entry.kind.trim()
291
+ ? entry.kind.trim()
292
+ : 'unknown';
293
+ const bucket = byKindMap.get(kind) ?? {
294
+ kind,
295
+ entryCount: 0,
296
+ totalHits: 0,
297
+ totalBefore: 0,
298
+ totalSaved: 0,
299
+ };
300
+ bucket.entryCount += 1;
301
+ bucket.totalHits += Number(entry.hitCount ?? 0);
302
+ bucket.totalBefore += Number(entry.tokensBefore ?? 0);
303
+ bucket.totalSaved += Number(entry.savedTokens ?? 0);
304
+ byKindMap.set(kind, bucket);
305
+ }
306
+
307
+ const byKind = [...byKindMap.values()]
308
+ .map((bucket) => ({
309
+ ...bucket,
310
+ savingsLabel: bucket.entryCount > 0 && bucket.totalBefore > 0
311
+ ? `${Math.trunc((bucket.totalSaved / bucket.totalBefore) * 100)}% avg`
312
+ : 'n/a',
313
+ }))
314
+ .sort((left, right) => (
315
+ right.totalHits - left.totalHits
316
+ || right.totalSaved - left.totalSaved
317
+ || left.kind.localeCompare(right.kind)
318
+ ));
319
+
320
+ return {
321
+ entryCount: totalEntries,
322
+ totalHits,
323
+ totalBefore,
324
+ totalSaved,
325
+ savingsLabel: totalEntries > 0 && totalBefore > 0 ? `${savingsPercent}% avg` : 'n/a',
326
+ byKind,
327
+ };
328
+ }
@@ -0,0 +1,246 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import {
4
+ readJsonIfExists,
5
+ removeLinkOrDir,
6
+ removeLinkOnly,
7
+ resolveProjectRelativePath,
8
+ } from './fileOps.js';
9
+ import { removeGitignoreBlock } from './ensureGitignore.js';
10
+
11
+ async function isDirEmpty(dirPath) {
12
+ try {
13
+ const entries = await fs.readdir(dirPath);
14
+ return entries.length === 0;
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+
20
+ async function cleanupEmptyParents(targetPath, projectRoot) {
21
+ let currentDir = path.dirname(targetPath);
22
+ const stopDir = path.resolve(projectRoot);
23
+
24
+ while (currentDir.startsWith(stopDir) && currentDir !== stopDir) {
25
+ let stat;
26
+ try {
27
+ stat = await fs.lstat(currentDir);
28
+ } catch {
29
+ currentDir = path.dirname(currentDir);
30
+ continue;
31
+ }
32
+
33
+ if (!stat.isDirectory()) {
34
+ break;
35
+ }
36
+
37
+ if (!(await isDirEmpty(currentDir))) {
38
+ break;
39
+ }
40
+
41
+ await fs.rmdir(currentDir);
42
+ currentDir = path.dirname(currentDir);
43
+ }
44
+ }
45
+
46
+ // Use lstat (not access) so broken symlinks are also detected as existing.
47
+ async function pathExistsLstat(targetPath) {
48
+ try {
49
+ await fs.lstat(targetPath);
50
+ return true;
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+
56
+ const ALLOWED_UNINSTALL_PREFIXES = [
57
+ 'CLAUDE.md',
58
+ 'AGENTS.md',
59
+ 'docs/',
60
+ '.claude/',
61
+ '.antigravity/',
62
+ '.codex/',
63
+ '.ukit/',
64
+ 'opencode.json',
65
+ ];
66
+
67
+ function normalizeToProjectRelative(projectRoot, absolutePath) {
68
+ const root = path.resolve(projectRoot);
69
+ const relative = path.relative(root, absolutePath);
70
+ if (!relative) {
71
+ return null;
72
+ }
73
+ return relative.replace(/\\/g, '/');
74
+ }
75
+
76
+ function isAllowedProjectPath(relativePath) {
77
+ if (!relativePath) {
78
+ return false;
79
+ }
80
+
81
+ return ALLOWED_UNINSTALL_PREFIXES.some((prefix) => {
82
+ if (prefix.endsWith('/')) {
83
+ // Only allow descendants under managed roots, never the root directory
84
+ // itself (e.g. ".claude"). Deleting the root could remove user content.
85
+ return relativePath.startsWith(prefix);
86
+ }
87
+ return relativePath === prefix;
88
+ });
89
+ }
90
+
91
+ function isSameOrDescendantProjectPath(candidatePath, parentPath) {
92
+ if (!candidatePath || !parentPath) {
93
+ return false;
94
+ }
95
+
96
+ return candidatePath === parentPath || candidatePath.startsWith(`${parentPath}/`);
97
+ }
98
+
99
+ // Hardcoded fallback for installs that predate file tracking (no 'files' field
100
+ // in install.json). New installs always have a 'files' list, so this fallback
101
+ // only applies when upgrading from a very old UKit version.
102
+ function buildFallbackPaths(projectRoot) {
103
+ const stateDir = path.join(projectRoot, '.claude', 'ukit', '.ukit');
104
+ return {
105
+ regularPaths: [
106
+ path.join(projectRoot, 'CLAUDE.md'),
107
+ path.join(projectRoot, 'AGENTS.md'),
108
+ path.join(projectRoot, '.claude', 'commands', 'ukit.md'),
109
+ path.join(projectRoot, '.claude', 'ukit', 'mcp'),
110
+ path.join(projectRoot, '.claude', 'ukit', 'scripts', 'setup-mcp.sh'),
111
+ path.join(projectRoot, '.claude', 'ukit', '.env.example'),
112
+ path.join(projectRoot, '.claude', 'ukit', 'permission-usage.json'),
113
+ path.join(projectRoot, '.claude', 'ukit', 'permission-audit.log'),
114
+ path.join(projectRoot, '.antigravity', 'rules', 'rules.md'),
115
+ path.join(projectRoot, '.antigravity', 'README.md'),
116
+ path.join(projectRoot, '.codex', 'README.md'),
117
+ path.join(projectRoot, 'opencode.json'),
118
+ path.join(projectRoot, '.ukit'),
119
+ stateDir,
120
+ ],
121
+ linkPaths: [
122
+ path.join(projectRoot, '.antigravity', 'skills'),
123
+ path.join(projectRoot, '.antigravity', 'ukit'),
124
+ path.join(projectRoot, '.codex', 'skills'),
125
+ path.join(projectRoot, '.codex', 'ukit'),
126
+ ],
127
+ };
128
+ }
129
+
130
+ export async function uninstallUkit({ projectRoot, dryRun = false }) {
131
+ const installMetaPath = path.join(projectRoot, '.claude', 'ukit', '.ukit', 'install.json');
132
+
133
+ // Read and validate install.json — checking existence alone is not sufficient.
134
+ // An attacker (or confused user) could forge the file to trigger uninstall of
135
+ // the hardcoded managed paths. Requiring 'tool: ukit' ensures the file was
136
+ // written by the UKit installer, not created manually.
137
+ const installData = await readJsonIfExists(installMetaPath);
138
+ if (!installData || installData.tool !== 'ukit') {
139
+ return { removed: 0, attempted: 0, wasInstalled: false };
140
+ }
141
+
142
+ // Build the deletion list. When install.json contains a 'files' manifest (written
143
+ // by new UKit versions), use it for precise ownership — only delete files UKit
144
+ // actually created. Fall back to the hardcoded list for old installs.
145
+ let regularPaths;
146
+ let linkPaths;
147
+
148
+ const stateDir = path.join(projectRoot, '.claude', 'ukit', '.ukit');
149
+
150
+ if (Array.isArray(installData.files)) {
151
+ // New format: tracked files give us ownership metadata even when the list is
152
+ // empty. Skip invalid entries to avoid path traversal.
153
+ regularPaths = [stateDir]; // always delete state dir — it's always UKit-owned
154
+ linkPaths = [];
155
+
156
+ const skipped = [];
157
+ const trackedEntries = [];
158
+
159
+ for (const entry of installData.files) {
160
+ const relPath = typeof entry === 'string' ? entry : entry?.p;
161
+ const type = typeof entry === 'string' ? 'file' : typeof entry?.t === 'string' ? entry.t : 'file';
162
+ const absolutePath = resolveProjectRelativePath(projectRoot, relPath);
163
+ if (!absolutePath) {
164
+ continue;
165
+ }
166
+
167
+ const normalizedRelative = normalizeToProjectRelative(projectRoot, absolutePath);
168
+ if (!isAllowedProjectPath(normalizedRelative)) {
169
+ skipped.push(relPath ?? normalizedRelative ?? absolutePath);
170
+ continue;
171
+ }
172
+
173
+ trackedEntries.push({ absolutePath, normalizedRelative, type });
174
+ }
175
+
176
+ const trackedLinkRelativePaths = [
177
+ ...new Set(trackedEntries.filter((entry) => entry.type === 'link').map((entry) => entry.normalizedRelative)),
178
+ ];
179
+
180
+ for (const entry of trackedEntries) {
181
+ if (entry.type === 'link') {
182
+ linkPaths.push(entry.absolutePath);
183
+ continue;
184
+ }
185
+
186
+ const isUnderTrackedLinkPath = trackedLinkRelativePaths.some((linkRelativePath) =>
187
+ isSameOrDescendantProjectPath(entry.normalizedRelative, linkRelativePath),
188
+ );
189
+
190
+ if (isUnderTrackedLinkPath) {
191
+ skipped.push(entry.normalizedRelative);
192
+ continue;
193
+ }
194
+
195
+ regularPaths.push(entry.absolutePath);
196
+ }
197
+
198
+ if (skipped.length > 0 && dryRun) {
199
+ console.warn('[UKit] Skipping invalid uninstall paths from install metadata:', skipped);
200
+ }
201
+ } else {
202
+ // Old format (no files list): fall back to hardcoded managed paths.
203
+ // NOTE: docs/PROJECT.md, MEMORY.md, WORKLOG.md are intentionally excluded.
204
+ // These are user-created content (mergeStrategy: skip) — deleting them
205
+ // would cause data loss. Users must remove them manually if desired.
206
+ const fallback = buildFallbackPaths(projectRoot);
207
+ regularPaths = fallback.regularPaths;
208
+ linkPaths = fallback.linkPaths;
209
+ }
210
+
211
+ const allEntries = [
212
+ ...regularPaths.map((abs) => ({ abs, useLink: false })),
213
+ ...linkPaths.map((abs) => ({ abs, useLink: true })),
214
+ ];
215
+
216
+ if (dryRun) {
217
+ // Use lstat (not access) so broken symlinks are included in the report.
218
+ const wouldRemove = [];
219
+ for (const { abs } of allEntries) {
220
+ if (await pathExistsLstat(abs)) wouldRemove.push(abs);
221
+ }
222
+ return { removed: 0, attempted: allEntries.length, wasInstalled: true, wouldRemove };
223
+ }
224
+
225
+ // Remove all paths in parallel
226
+ const results = await Promise.all(
227
+ allEntries.map(({ abs, useLink }) => {
228
+ const remove = useLink ? removeLinkOnly : removeLinkOrDir;
229
+ return remove(abs).then((didRemove) => ({ abs, didRemove }));
230
+ }),
231
+ );
232
+
233
+ // Clean up .gitignore block added during install
234
+ await removeGitignoreBlock(projectRoot);
235
+
236
+ // Cleanup empty parent directories sequentially (order matters)
237
+ let removed = 0;
238
+ for (const { abs, didRemove } of results) {
239
+ if (didRemove) {
240
+ removed += 1;
241
+ await cleanupEmptyParents(abs, projectRoot);
242
+ }
243
+ }
244
+
245
+ return { removed, attempted: allEntries.length, wasInstalled: true };
246
+ }
@@ -0,0 +1,89 @@
1
+ const HEDGING_WORDS = [
2
+ 'maybe',
3
+ 'might',
4
+ 'i think',
5
+ 'probably',
6
+ 'possibly',
7
+ 'could be',
8
+ 'perhaps',
9
+ 'có thể',
10
+ 'chắc là',
11
+ 'hình như',
12
+ ];
13
+
14
+ const VERIFICATION_WORDS = [
15
+ 'verified',
16
+ 'tested',
17
+ 'passes',
18
+ 'passed',
19
+ 'checked',
20
+ 'confirmed',
21
+ 'validated',
22
+ 'đã test',
23
+ 'đã kiểm tra',
24
+ ];
25
+
26
+ function normalize(text) {
27
+ return String(text ?? '').toLowerCase();
28
+ }
29
+
30
+ function buildResult(score, factors) {
31
+ const clamped = Math.max(0, Math.min(100, Math.round(score)));
32
+ const level = clamped >= 80 ? 'high' : clamped >= 50 ? 'medium' : 'low';
33
+ const action = clamped >= 80 ? 'respond' : clamped >= 50 ? 'warn' : 'clarify';
34
+
35
+ return {
36
+ score: clamped,
37
+ level,
38
+ factors,
39
+ action,
40
+ };
41
+ }
42
+
43
+ export function scoreConfidence(output, taskType, context = '') {
44
+ const normalizedOutput = normalize(output);
45
+ const normalizedContext = normalize(context);
46
+ const factors = [];
47
+ let score = 50;
48
+
49
+ if (normalizedContext.trim().length >= 24) {
50
+ score += 15;
51
+ factors.push({ name: 'context_availability', impact: 'positive', reason: 'Enough task context is available.' });
52
+ } else {
53
+ score -= 20;
54
+ factors.push({ name: 'context_availability', impact: 'negative', reason: 'Very little context is available.' });
55
+ }
56
+
57
+ if (normalizedOutput.length >= 60 && !HEDGING_WORDS.some((word) => normalizedOutput.includes(word))) {
58
+ score += 15;
59
+ factors.push({ name: 'task_clarity', impact: 'positive', reason: 'Output is specific and direct.' });
60
+ } else if (normalizedOutput.length < 30) {
61
+ score -= 10;
62
+ factors.push({ name: 'task_clarity', impact: 'negative', reason: 'Output is too short to inspire confidence.' });
63
+ }
64
+
65
+ const hedges = HEDGING_WORDS.filter((word) => normalizedOutput.includes(word));
66
+ if (hedges.length > 0) {
67
+ score -= 30;
68
+ factors.push({ name: 'model_certainty', impact: 'negative', reason: `Hedging language detected: ${hedges.join(', ')}.` });
69
+ } else {
70
+ score += 10;
71
+ factors.push({ name: 'model_certainty', impact: 'positive', reason: 'Language is direct rather than hedged.' });
72
+ }
73
+
74
+ const verificationHits = VERIFICATION_WORDS.filter((word) => normalizedOutput.includes(word));
75
+ if (verificationHits.length > 0) {
76
+ score += 20;
77
+ factors.push({ name: 'verification', impact: 'positive', reason: `Verification signals found: ${verificationHits.join(', ')}.` });
78
+ } else if (taskType === 'coding' || taskType === 'debug' || taskType === 'debug_hard') {
79
+ score -= 10;
80
+ factors.push({ name: 'verification', impact: 'negative', reason: 'No verification evidence was provided for a technical task.' });
81
+ }
82
+
83
+ if (/\b(previous|existing|again|recall|memory)\b/.test(normalizedContext)) {
84
+ score += 5;
85
+ factors.push({ name: 'prior_knowledge', impact: 'positive', reason: 'Context suggests continuity with prior knowledge.' });
86
+ }
87
+
88
+ return buildResult(score, factors);
89
+ }
@@ -0,0 +1,2 @@
1
+ export { scoreConfidence } from './confidence.js';
2
+ export { validateOutput } from './validator.js';