@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,89 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { writeFileAtomic, copyFileSafe, createDirectoryLink, removeLinkOnly } from './fileOps.js';
4
+
5
+ export async function applyDiffResults(diffResults, { backupRoot, projectRoot } = {}) {
6
+ const writes = [];
7
+ let skippedUpdates = 0;
8
+
9
+ for (const entry of diffResults) {
10
+ if (entry.action !== 'create' && entry.action !== 'update') {
11
+ continue;
12
+ }
13
+
14
+ if (entry.type === 'link') {
15
+ // Remove existing symlink before recreating.
16
+ // Use removeLinkOnly — NOT removeLinkOrDir — to protect real directories that may
17
+ // contain user content. If the path is not a symlink, skip and warn instead of
18
+ // recursively deleting it.
19
+ if (entry.action === 'update') {
20
+ const removed = await removeLinkOnly(entry.targetPath);
21
+ if (!removed) {
22
+ // Determine what actually exists at this path for a precise warning message.
23
+ let existingKind = 'unknown path';
24
+ try {
25
+ const stat = await fs.lstat(entry.targetPath);
26
+ existingKind = stat.isDirectory() ? 'real directory' : 'regular file';
27
+ } catch {
28
+ existingKind = 'unknown path';
29
+ }
30
+ console.warn(
31
+ `[UKit] Warning: skipping link update for ${entry.targetPath} — exists as a ${existingKind} (possible user content). Remove it manually if intended.`,
32
+ );
33
+ skippedUpdates += 1;
34
+ continue;
35
+ }
36
+ }
37
+ await createDirectoryLink(entry.linkTarget, entry.targetPath);
38
+ writes.push({
39
+ id: entry.id,
40
+ targetPath: entry.targetPath,
41
+ action: entry.action,
42
+ type: entry.type,
43
+ });
44
+ continue;
45
+ }
46
+
47
+ // Back up the existing file before overwriting
48
+ if (
49
+ entry.action === 'update' &&
50
+ entry.mergeStrategy === 'overwrite_with_backup' &&
51
+ backupRoot &&
52
+ projectRoot
53
+ ) {
54
+ const relPath = path.relative(projectRoot, entry.targetPath);
55
+ const timestamp = Date.now();
56
+ const backupPath = path.join(backupRoot, `${relPath}.${timestamp}.bak`);
57
+ await copyFileSafe(entry.targetPath, backupPath);
58
+ }
59
+
60
+ const binaryEntry = Buffer.isBuffer(entry.renderedContent);
61
+ const nextContent =
62
+ entry.mergeStrategy === 'append' && entry.exists && entry.existingContent !== null
63
+ ? (
64
+ binaryEntry
65
+ ? Buffer.concat([entry.existingContent, entry.renderedContent])
66
+ : `${entry.existingContent}${entry.renderedContent}`
67
+ )
68
+ : entry.mergeStrategy === 'prepend' && entry.exists && entry.existingContent !== null
69
+ ? (
70
+ binaryEntry
71
+ ? Buffer.concat([entry.renderedContent, entry.existingContent])
72
+ : `${entry.renderedContent}${entry.existingContent}`
73
+ )
74
+ : entry.renderedContent;
75
+
76
+ await writeFileAtomic(entry.targetPath, nextContent);
77
+ if (typeof entry.mode === 'number') {
78
+ await fs.chmod(entry.targetPath, entry.mode);
79
+ }
80
+ writes.push({
81
+ id: entry.id,
82
+ targetPath: entry.targetPath,
83
+ action: entry.action,
84
+ type: entry.type,
85
+ });
86
+ }
87
+
88
+ return { writes, skippedUpdates };
89
+ }
@@ -0,0 +1,228 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { selectManifestItems } from '../manifest/selectItems.js';
4
+ import { renderTemplateString } from '../render/renderTemplate.js';
5
+
6
+ const BINARY_TEMPLATE_EXTENSIONS = new Set([
7
+ '.ttf',
8
+ '.otf',
9
+ '.woff',
10
+ '.woff2',
11
+ '.png',
12
+ '.jpg',
13
+ '.jpeg',
14
+ '.gif',
15
+ '.ico',
16
+ '.webp',
17
+ '.avif',
18
+ '.mp3',
19
+ '.mp4',
20
+ '.mov',
21
+ '.zip',
22
+ '.gz',
23
+ '.tgz',
24
+ '.tar',
25
+ '.pdf',
26
+ ]);
27
+
28
+ function safeResolve(basePath, relativePath) {
29
+ const resolvedPath = path.resolve(basePath, relativePath);
30
+ const relativeToBase = path.relative(basePath, resolvedPath);
31
+
32
+ if (relativeToBase.startsWith('..') || path.isAbsolute(relativeToBase)) {
33
+ throw new Error(`Path escapes base directory: ${relativePath}`);
34
+ }
35
+
36
+ return resolvedPath;
37
+ }
38
+
39
+ async function readTemplateFile(filePath, { binary = false } = {}) {
40
+ if (binary) {
41
+ return fs.readFile(filePath);
42
+ }
43
+ return fs.readFile(filePath, 'utf8');
44
+ }
45
+
46
+ async function walkDirectory(dir) {
47
+ const entries = await fs.readdir(dir, { withFileTypes: true });
48
+ const files = [];
49
+
50
+ for (const entry of entries) {
51
+ if (entry.name === '.DS_Store') {
52
+ continue;
53
+ }
54
+
55
+ const fullPath = path.join(dir, entry.name);
56
+ if (entry.isDirectory()) {
57
+ files.push(...(await walkDirectory(fullPath)));
58
+ } else if (entry.isFile()) {
59
+ files.push(fullPath);
60
+ }
61
+ }
62
+
63
+ return files;
64
+ }
65
+
66
+ function shouldTreatTemplateAsBinary(filePath) {
67
+ return BINARY_TEMPLATE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
68
+ }
69
+
70
+ export async function buildInstallPlan({
71
+ manifest,
72
+ stackContext,
73
+ templatesRoot,
74
+ variables,
75
+ projectRoot,
76
+ selectedAdapterItemIds,
77
+ }) {
78
+ const selectedItems = selectManifestItems({
79
+ items: manifest.items,
80
+ detectedPacks: stackContext.detectedPacks,
81
+ selectedAdapterItemIds,
82
+ });
83
+
84
+ const planEntries = [];
85
+ const manifestSourcePaths = new Set();
86
+ const explicitTargetPaths = new Set();
87
+ const selectedIds = new Set(selectedItems.map((item) => item.id));
88
+
89
+ // Collect source directories of excluded manifest items so auto-discovery
90
+ // does not install files that belong to filtered-out packs.
91
+ // Skip link items — their sourceTemplate is relative to projectRoot, not templatesRoot.
92
+ const excludedSourceDirs = [];
93
+ for (const item of manifest.items) {
94
+ if (!selectedIds.has(item.id) && item.type !== 'link') {
95
+ const sourcePath = safeResolve(templatesRoot, item.sourceTemplate);
96
+ const stat = await fs.stat(sourcePath);
97
+ const sourceDir = (stat.isDirectory() ? sourcePath : path.dirname(sourcePath)) + path.sep;
98
+ excludedSourceDirs.push(sourceDir);
99
+ }
100
+ }
101
+
102
+ // Prepare items: resolve paths and collect template reads to parallelize
103
+ const fileItems = [];
104
+
105
+ for (const item of selectedItems) {
106
+ if (item.type === 'link') {
107
+ const targetPath = safeResolve(projectRoot, item.targetPath);
108
+ explicitTargetPaths.add(targetPath);
109
+ const linkTarget = safeResolve(projectRoot, item.sourceTemplate);
110
+ planEntries.push({
111
+ id: item.id,
112
+ type: 'link',
113
+ linkTarget,
114
+ targetPath,
115
+ mergeStrategy: item.mergeStrategy ?? 'overwrite_with_backup',
116
+ renderedContent: null,
117
+ requires: item.requires ?? [],
118
+ });
119
+ } else {
120
+ const sourcePath = safeResolve(templatesRoot, item.sourceTemplate);
121
+ const stat = await fs.stat(sourcePath);
122
+ if (stat.isDirectory()) {
123
+ const nestedFiles = await walkDirectory(sourcePath);
124
+ const nestedStats = await Promise.all(nestedFiles.map((filePath) => fs.stat(filePath)));
125
+
126
+ for (let index = 0; index < nestedFiles.length; index += 1) {
127
+ const nestedSourcePath = nestedFiles[index];
128
+ const relativeChildPath = path.relative(sourcePath, nestedSourcePath);
129
+ const targetPath = safeResolve(projectRoot, path.join(item.targetPath, relativeChildPath));
130
+ manifestSourcePaths.add(nestedSourcePath);
131
+ explicitTargetPaths.add(targetPath);
132
+ fileItems.push({
133
+ item,
134
+ sourcePath: nestedSourcePath,
135
+ targetPath,
136
+ sourceMode: nestedStats[index].mode & 0o777,
137
+ binary: shouldTreatTemplateAsBinary(nestedSourcePath),
138
+ });
139
+ }
140
+ } else {
141
+ const targetPath = safeResolve(projectRoot, item.targetPath);
142
+ manifestSourcePaths.add(sourcePath);
143
+ explicitTargetPaths.add(targetPath);
144
+ fileItems.push({
145
+ item,
146
+ sourcePath,
147
+ targetPath,
148
+ sourceMode: stat.mode & 0o777,
149
+ binary: shouldTreatTemplateAsBinary(sourcePath),
150
+ });
151
+ }
152
+ }
153
+ }
154
+
155
+ // Read all template files in parallel
156
+ const templateContents = await Promise.all(
157
+ fileItems.map(({ sourcePath, binary }) => readTemplateFile(sourcePath, { binary })),
158
+ );
159
+
160
+ for (let i = 0; i < fileItems.length; i++) {
161
+ const { item, sourcePath, targetPath } = fileItems[i];
162
+ const renderedContent = fileItems[i].binary
163
+ ? templateContents[i]
164
+ : renderTemplateString(templateContents[i], variables);
165
+
166
+ planEntries.push({
167
+ id: item.id,
168
+ type: item.type,
169
+ sourcePath,
170
+ targetPath,
171
+ mergeStrategy: item.mergeStrategy,
172
+ renderedContent,
173
+ requires: item.requires ?? [],
174
+ mode: fileItems[i].sourceMode,
175
+ });
176
+ }
177
+
178
+ // Auto-discover files in templates/ not covered by manifest
179
+ if (manifest.autoDiscoverTemplates === true) {
180
+ const allTemplateFiles = await walkDirectory(templatesRoot);
181
+
182
+ // Filter eligible files first
183
+ const autoFiles = [];
184
+ for (const filePath of allTemplateFiles) {
185
+ if (manifestSourcePaths.has(filePath)) continue;
186
+ if (excludedSourceDirs.some((dir) => filePath.startsWith(dir))) continue;
187
+
188
+ const relativePath = path.relative(templatesRoot, filePath);
189
+ const targetPath = safeResolve(projectRoot, relativePath);
190
+ if (explicitTargetPaths.has(targetPath)) continue;
191
+
192
+ autoFiles.push({ filePath, relativePath, targetPath });
193
+ }
194
+
195
+ // Read all auto-discovered templates in parallel
196
+ const autoContents = await Promise.all(
197
+ autoFiles.map(({ filePath }) => readTemplateFile(filePath, {
198
+ binary: shouldTreatTemplateAsBinary(filePath),
199
+ })),
200
+ );
201
+
202
+ const autoStats = await Promise.all(autoFiles.map(({ filePath }) => fs.stat(filePath)));
203
+
204
+ for (let i = 0; i < autoFiles.length; i++) {
205
+ const { filePath, relativePath, targetPath } = autoFiles[i];
206
+ const renderedContent = shouldTreatTemplateAsBinary(filePath)
207
+ ? autoContents[i]
208
+ : renderTemplateString(autoContents[i], variables);
209
+ const mode = autoStats[i].mode & 0o777;
210
+
211
+ planEntries.push({
212
+ id: `auto:${relativePath}`,
213
+ type: 'auto',
214
+ sourcePath: filePath,
215
+ targetPath,
216
+ mergeStrategy: 'overwrite_with_backup',
217
+ renderedContent,
218
+ requires: [],
219
+ mode,
220
+ });
221
+ }
222
+ }
223
+
224
+ return {
225
+ selectedItems,
226
+ entries: planEntries,
227
+ };
228
+ }
@@ -0,0 +1,294 @@
1
+ import { readJsonIfExists, writeJson } from '../fileOps.js';
2
+ import { buildRuntimePaths } from '../runtimePaths.js';
3
+ import { compressLine, compressMarkdownLines, estimateTokenCount } from '../token/index.js';
4
+
5
+ export const DEFAULT_COMPACT_HISTORY_MAX_ENTRIES = 50;
6
+ const DEFAULT_MAX_COMPACT_ANCHORS = 3;
7
+
8
+ function normalizeCompactHistoryEntry(entry) {
9
+ if (!entry || typeof entry !== 'object') {
10
+ return null;
11
+ }
12
+
13
+ const timestamp = Number(entry.timestamp);
14
+ const tokensBefore = Number(entry.tokensBefore);
15
+ const tokensAfter = Number(entry.tokensAfter);
16
+ const savedTokens = Number(entry.savedTokens);
17
+
18
+ return {
19
+ ...entry,
20
+ timestamp: Number.isFinite(timestamp) ? timestamp : Date.now(),
21
+ tokensBefore: Number.isFinite(tokensBefore) ? tokensBefore : 0,
22
+ tokensAfter: Number.isFinite(tokensAfter) ? tokensAfter : 0,
23
+ savedTokens: Number.isFinite(savedTokens) ? savedTokens : 0,
24
+ };
25
+ }
26
+
27
+ function normalizeCompactHistoryDocument(raw, { maxEntries = DEFAULT_COMPACT_HISTORY_MAX_ENTRIES } = {}) {
28
+ const candidates = Array.isArray(raw?.entries)
29
+ ? raw.entries
30
+ : Array.isArray(raw)
31
+ ? raw
32
+ : [];
33
+
34
+ return {
35
+ entries: candidates
36
+ .map((entry) => normalizeCompactHistoryEntry(entry))
37
+ .filter(Boolean)
38
+ .sort((left, right) => (right.timestamp ?? 0) - (left.timestamp ?? 0))
39
+ .slice(0, maxEntries),
40
+ };
41
+ }
42
+
43
+ export function compactContextBlock(
44
+ lines,
45
+ {
46
+ header = null,
47
+ maxTokens = 300,
48
+ maxLines = 10,
49
+ anchorLines = [],
50
+ anchorPatterns = [],
51
+ maxAnchors = DEFAULT_MAX_COMPACT_ANCHORS,
52
+ } = {},
53
+ ) {
54
+ const contentLines = Array.isArray(lines)
55
+ ? lines.filter((line) => typeof line === 'string')
56
+ : [];
57
+ const rawLines = header ? [header, ...contentLines] : [...contentLines];
58
+ const rawText = rawLines.join('\n');
59
+ const normalizedMaxLines = header ? maxLines + 1 : maxLines;
60
+ const normalizedAnchorLines = resolveAnchorLines(rawLines, {
61
+ header,
62
+ anchorLines,
63
+ anchorPatterns,
64
+ maxAnchors,
65
+ });
66
+ const compactedLines = buildCompactedContextLines(rawLines, {
67
+ maxTokens,
68
+ maxLines: normalizedMaxLines,
69
+ preserveFirstLine: Boolean(header),
70
+ forceFirstCount: header ? 1 : 0,
71
+ });
72
+ let text = compactedLines.join('\n').trim();
73
+ let validationMode = 'default';
74
+
75
+ if (normalizedAnchorLines.length > 0 && findMissingAnchors(text, normalizedAnchorLines).length > 0) {
76
+ const anchorFirstLines = buildCompactedContextLines(
77
+ header
78
+ ? [header, ...normalizedAnchorLines, ...contentLines]
79
+ : [...normalizedAnchorLines, ...contentLines],
80
+ {
81
+ maxTokens,
82
+ maxLines: normalizedMaxLines,
83
+ preserveFirstLine: Boolean(header),
84
+ forceFirstCount: (header ? 1 : 0) + normalizedAnchorLines.length,
85
+ },
86
+ );
87
+ const anchorFirstText = anchorFirstLines.join('\n').trim();
88
+
89
+ if (findMissingAnchors(anchorFirstText, normalizedAnchorLines).length === 0) {
90
+ text = anchorFirstText;
91
+ validationMode = 'anchor-first';
92
+ } else {
93
+ text = buildCompactedContextLines(
94
+ header
95
+ ? [header, ...normalizedAnchorLines]
96
+ : [...normalizedAnchorLines],
97
+ {
98
+ maxTokens,
99
+ maxLines: normalizedMaxLines,
100
+ preserveFirstLine: Boolean(header),
101
+ forceFirstCount: (header ? 1 : 0) + normalizedAnchorLines.length,
102
+ },
103
+ ).join('\n').trim();
104
+ validationMode = 'forced-anchors';
105
+ }
106
+ }
107
+
108
+ const tokensBefore = estimateTokenCount(rawText);
109
+ const tokensAfter = estimateTokenCount(text);
110
+
111
+ return {
112
+ text,
113
+ tokensBefore,
114
+ tokensAfter,
115
+ savedTokens: Math.max(0, tokensBefore - tokensAfter),
116
+ validationMode,
117
+ anchorCount: normalizedAnchorLines.length,
118
+ };
119
+ }
120
+
121
+ function normalizeAnchorPattern(pattern) {
122
+ if (pattern instanceof RegExp) {
123
+ return (line) => pattern.test(line);
124
+ }
125
+ if (typeof pattern === 'string' && pattern.trim()) {
126
+ const prefix = pattern.trim();
127
+ return (line) => line.startsWith(prefix);
128
+ }
129
+ if (typeof pattern === 'function') {
130
+ return pattern;
131
+ }
132
+ return null;
133
+ }
134
+
135
+ function normalizeLineForDedupe(line) {
136
+ return String(line ?? '').trim().replace(/\s+/g, ' ').toLowerCase();
137
+ }
138
+
139
+ function uniqueLines(lines) {
140
+ const seen = new Set();
141
+ const unique = [];
142
+
143
+ for (const line of lines) {
144
+ const trimmed = String(line ?? '').trim();
145
+ const normalized = normalizeLineForDedupe(trimmed);
146
+ if (!normalized || seen.has(normalized)) {
147
+ continue;
148
+ }
149
+ seen.add(normalized);
150
+ unique.push(trimmed);
151
+ }
152
+
153
+ return unique;
154
+ }
155
+
156
+ function resolveAnchorLines(rawLines, { header = null, anchorLines = [], anchorPatterns = [], maxAnchors = DEFAULT_MAX_COMPACT_ANCHORS } = {}) {
157
+ const predicates = anchorPatterns
158
+ .map((pattern) => normalizeAnchorPattern(pattern))
159
+ .filter(Boolean);
160
+ const explicitAnchorLines = Array.isArray(anchorLines) ? anchorLines : [];
161
+ const matchedPatternLines = predicates.length > 0
162
+ ? rawLines.filter((line) => {
163
+ const trimmed = String(line ?? '').trim();
164
+ return trimmed && predicates.some((predicate) => predicate(trimmed));
165
+ })
166
+ : [];
167
+
168
+ return uniqueLines([
169
+ ...explicitAnchorLines,
170
+ ...matchedPatternLines,
171
+ ])
172
+ .filter((line) => !header || normalizeLineForDedupe(line) !== normalizeLineForDedupe(header))
173
+ .slice(0, Math.max(0, maxAnchors));
174
+ }
175
+
176
+ function buildCompactedContextLines(
177
+ lines,
178
+ {
179
+ maxTokens = 300,
180
+ maxLines = 10,
181
+ preserveFirstLine = true,
182
+ forceFirstCount = 0,
183
+ } = {},
184
+ ) {
185
+ const sourceLines = Array.isArray(lines) ? lines : [];
186
+ const selected = [];
187
+ const seen = new Set();
188
+ let usedTokens = 0;
189
+ let nonEmptyCount = 0;
190
+
191
+ for (const line of sourceLines) {
192
+ const compressed = compressLine(line);
193
+ if (!compressed) {
194
+ continue;
195
+ }
196
+
197
+ const dedupeKey = compressed.toLowerCase();
198
+ if (seen.has(dedupeKey)) {
199
+ continue;
200
+ }
201
+
202
+ const tokens = estimateTokenCount(compressed);
203
+ const forceLine = nonEmptyCount < forceFirstCount;
204
+ const wouldOverflow = selected.length > 0 && (usedTokens + tokens) > maxTokens;
205
+ const wouldExceedLines = nonEmptyCount >= maxLines;
206
+
207
+ if (!forceLine && (wouldOverflow || wouldExceedLines)) {
208
+ break;
209
+ }
210
+ if (forceLine && wouldExceedLines) {
211
+ break;
212
+ }
213
+
214
+ selected.push(compressed);
215
+ seen.add(dedupeKey);
216
+ usedTokens += tokens;
217
+ nonEmptyCount += 1;
218
+ }
219
+
220
+ if (selected.length === 0) {
221
+ return compressMarkdownLines(sourceLines, {
222
+ maxTokens,
223
+ maxLines,
224
+ preserveFirstLine,
225
+ });
226
+ }
227
+
228
+ return selected;
229
+ }
230
+
231
+ function findMissingAnchors(text, anchorLines) {
232
+ const normalizedText = String(text ?? '').toLowerCase();
233
+ return anchorLines.filter((line) => {
234
+ const compressed = compressLine(line).toLowerCase();
235
+ return compressed && !normalizedText.includes(compressed);
236
+ });
237
+ }
238
+
239
+ export async function readCompactHistory(projectRoot, options = {}) {
240
+ const runtimePaths = buildRuntimePaths(projectRoot);
241
+ const raw = await readJsonIfExists(runtimePaths.compactHistoryPath);
242
+ return normalizeCompactHistoryDocument(raw, options);
243
+ }
244
+
245
+ export async function appendCompactHistory(
246
+ projectRoot,
247
+ entry,
248
+ {
249
+ maxEntries = DEFAULT_COMPACT_HISTORY_MAX_ENTRIES,
250
+ } = {},
251
+ ) {
252
+ const normalizedEntry = normalizeCompactHistoryEntry(entry);
253
+ if (!normalizedEntry) {
254
+ return readCompactHistory(projectRoot, { maxEntries });
255
+ }
256
+
257
+ const runtimePaths = buildRuntimePaths(projectRoot);
258
+ const history = await readCompactHistory(projectRoot, { maxEntries });
259
+ const nextDocument = normalizeCompactHistoryDocument({
260
+ entries: [normalizedEntry, ...history.entries],
261
+ }, { maxEntries });
262
+ await writeJson(runtimePaths.compactHistoryPath, nextDocument);
263
+ return nextDocument;
264
+ }
265
+
266
+ export async function recordCompaction(
267
+ projectRoot,
268
+ {
269
+ source = 'unknown',
270
+ beforeText = '',
271
+ afterText = '',
272
+ timestamp = Date.now(),
273
+ metadata = null,
274
+ } = {},
275
+ ) {
276
+ const tokensBefore = estimateTokenCount(beforeText);
277
+ const tokensAfter = estimateTokenCount(afterText);
278
+ const savedTokens = Math.max(0, tokensBefore - tokensAfter);
279
+
280
+ if (savedTokens <= 0) {
281
+ return null;
282
+ }
283
+
284
+ const entry = {
285
+ timestamp,
286
+ source,
287
+ tokensBefore,
288
+ tokensAfter,
289
+ savedTokens,
290
+ metadata,
291
+ };
292
+ await appendCompactHistory(projectRoot, entry);
293
+ return entry;
294
+ }