@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,936 @@
1
+ import { readJsonIfExists, writeJson } from '../fileOps.js';
2
+ import { buildRuntimePaths } from '../runtimePaths.js';
3
+ import { buildCompactMachineKey, compressLine, estimateTokenCount } from '../token/index.js';
4
+ import { compactContextBlock } from './index.js';
5
+
6
+ const DEFAULT_MAX_PROMPT_ENTRIES = 12;
7
+ const DEFAULT_MAX_OUTPUT_ENTRIES = 12;
8
+ const DEFAULT_HISTORY_LAYER_COUNT = 2;
9
+ const SOFT_RELEASE_RATIO = 0.9;
10
+ const HARD_RELEASE_RATIO = 0.92;
11
+ const PHASE_COOLDOWN_MS = {
12
+ soft: 5 * 60 * 1000,
13
+ hard: 10 * 60 * 1000,
14
+ };
15
+ const STOPWORDS = new Set([
16
+ 'the', 'a', 'an', 'and', 'or', 'to', 'for', 'of', 'with', 'in', 'on', 'is', 'are',
17
+ 'this', 'that', 'it', 'as', 'by', 'be', 'use', 'using', 'implement', 'fix', 'task',
18
+ 'keep', 'please', 'remember', 'need', 'still',
19
+ 'cần', 'và', 'là', 'cho', 'một', 'những', 'dùng',
20
+ ]);
21
+ const EXPENDABLE_LINE_PATTERNS = [
22
+ /^-\s*debug\b/i,
23
+ /^-\s*progress\b/i,
24
+ /^-\s*download(?:ed|ing)?\b/i,
25
+ /^-\s*spinner\b/i,
26
+ /^-\s*duration\b/i,
27
+ /^-\s*start at\b/i,
28
+ /^-\s*trace\b/i,
29
+ ];
30
+
31
+ function finiteNumber(value, fallback = 0) {
32
+ const number = Number(value);
33
+ return Number.isFinite(number) ? number : fallback;
34
+ }
35
+
36
+ function uniqueStrings(values) {
37
+ const seen = new Set();
38
+ const unique = [];
39
+ for (const value of values ?? []) {
40
+ const normalized = String(value ?? '').trim();
41
+ if (!normalized) continue;
42
+ const key = normalized.toLowerCase();
43
+ if (seen.has(key)) continue;
44
+ seen.add(key);
45
+ unique.push(normalized);
46
+ }
47
+ return unique;
48
+ }
49
+
50
+ function normalizeWhitespace(value) {
51
+ return String(value ?? '')
52
+ .replace(/[^\p{L}\p{N}\s./:_-]/gu, ' ')
53
+ .replace(/\s+/g, ' ')
54
+ .trim();
55
+ }
56
+
57
+ function tokenizeFreeform(value) {
58
+ return normalizeWhitespace(value)
59
+ .split(/\s+/)
60
+ .filter((token) => token && token.length > 1);
61
+ }
62
+
63
+ function compressFreeformText(value, { maxWords = 18 } = {}) {
64
+ const words = tokenizeFreeform(value);
65
+ const selected = [];
66
+ const seen = new Set();
67
+
68
+ for (const word of words) {
69
+ const key = word.toLowerCase();
70
+ const keep = /[./:_-]/.test(word) || !STOPWORDS.has(key);
71
+ if (!keep || seen.has(key)) {
72
+ continue;
73
+ }
74
+ selected.push(word);
75
+ seen.add(key);
76
+ if (selected.length >= maxWords) {
77
+ break;
78
+ }
79
+ }
80
+
81
+ return selected.join(' ');
82
+ }
83
+
84
+ function normalizeTaskMode(taskMode) {
85
+ const normalized = String(taskMode ?? '').trim().toLowerCase();
86
+ return ['coding', 'chat', 'mixed'].includes(normalized) ? normalized : '';
87
+ }
88
+
89
+ function normalizePhase(phase) {
90
+ const normalized = String(phase ?? '').trim().toLowerCase();
91
+ return ['monitor', 'soft', 'hard'].includes(normalized) ? normalized : 'monitor';
92
+ }
93
+
94
+ function normalizeStats(rawStats = {}) {
95
+ return {
96
+ thresholdHits: finiteNumber(rawStats?.thresholdHits, 0),
97
+ softHits: finiteNumber(rawStats?.softHits, 0),
98
+ hardHits: finiteNumber(rawStats?.hardHits, 0),
99
+ };
100
+ }
101
+
102
+ function normalizeLatestPlan(latestPlan = null) {
103
+ if (!latestPlan || typeof latestPlan !== 'object') {
104
+ return null;
105
+ }
106
+
107
+ return {
108
+ ...latestPlan,
109
+ phase: normalizePhase(latestPlan.phase),
110
+ updatedAt: finiteNumber(latestPlan.updatedAt, Date.now()),
111
+ estimatedTotalTokens: finiteNumber(latestPlan.estimatedTotalTokens, 0),
112
+ tokensBefore: finiteNumber(latestPlan.tokensBefore, 0),
113
+ tokensAfter: finiteNumber(latestPlan.tokensAfter, 0),
114
+ savedTokens: finiteNumber(latestPlan.savedTokens, 0),
115
+ reusedCooldown: Boolean(latestPlan.reusedCooldown),
116
+ };
117
+ }
118
+
119
+ function summarizePromptText(promptText, routingContext = {}) {
120
+ const focus = compressFreeformText(promptText || routingContext?.lastExplicitUserPromptText || '', {
121
+ maxWords: 18,
122
+ });
123
+ const parts = [];
124
+ if (routingContext?.targetFile) {
125
+ parts.push(String(routingContext.targetFile).trim());
126
+ }
127
+ if (focus) {
128
+ parts.push(focus);
129
+ }
130
+ if (routingContext?.taskType) {
131
+ parts.unshift(`lane=${String(routingContext.taskType).trim()}`);
132
+ }
133
+ return parts.join(' | ');
134
+ }
135
+
136
+ function summarizeOutputText(summary, command) {
137
+ const summaryLines = String(summary ?? '')
138
+ .split(/\r?\n/)
139
+ .map((line) => compressLine(line))
140
+ .filter(Boolean)
141
+ .filter((line) => !EXPENDABLE_LINE_PATTERNS.some((pattern) => pattern.test(line)));
142
+ const lines = uniqueStrings([
143
+ command ? `command=${String(command).trim()}` : null,
144
+ ...summaryLines.slice(0, 3),
145
+ ]);
146
+ return lines.join(' | ');
147
+ }
148
+
149
+ function normalizePromptEntry(entry) {
150
+ if (!entry || typeof entry !== 'object') {
151
+ return null;
152
+ }
153
+
154
+ const summary = String(entry.summary ?? '').trim();
155
+ if (!summary) {
156
+ return null;
157
+ }
158
+
159
+ return {
160
+ kind: 'prompt',
161
+ timestamp: finiteNumber(entry.timestamp, Date.now()),
162
+ tokens: Math.max(1, finiteNumber(entry.tokens, estimateTokenCount(summary))),
163
+ summary,
164
+ targetFile: entry.targetFile ? String(entry.targetFile).trim() : null,
165
+ taskType: entry.taskType ? String(entry.taskType).trim() : null,
166
+ };
167
+ }
168
+
169
+ function normalizeOutputEntry(entry) {
170
+ if (!entry || typeof entry !== 'object') {
171
+ return null;
172
+ }
173
+
174
+ const summary = String(entry.summary ?? '').trim();
175
+ if (!summary) {
176
+ return null;
177
+ }
178
+
179
+ const tokensBefore = Math.max(1, finiteNumber(entry.tokensBefore, estimateTokenCount(summary)));
180
+ const tokensAfter = Math.max(1, finiteNumber(entry.tokensAfter, estimateTokenCount(summary)));
181
+
182
+ return {
183
+ kind: 'output',
184
+ timestamp: finiteNumber(entry.timestamp, Date.now()),
185
+ command: entry.command ? String(entry.command).trim() : '',
186
+ profile: entry.profile ? String(entry.profile).trim() : 'generic',
187
+ exitCode: Number.isFinite(Number(entry.exitCode)) ? Number(entry.exitCode) : null,
188
+ tokensBefore,
189
+ tokensAfter,
190
+ savedTokens: Math.max(0, finiteNumber(entry.savedTokens, tokensBefore - tokensAfter)),
191
+ summary,
192
+ };
193
+ }
194
+
195
+ function upsertEntry(entries, entry, { maxEntries = 10, keyBuilder } = {}) {
196
+ const key = typeof keyBuilder === 'function' ? keyBuilder(entry) : entry.summary;
197
+ const normalizedKey = String(key ?? '').trim().toLowerCase();
198
+ const remaining = (entries ?? []).filter((candidate) => {
199
+ const candidateKey = String(
200
+ typeof keyBuilder === 'function' ? keyBuilder(candidate) : candidate?.summary,
201
+ ).trim().toLowerCase();
202
+ return candidateKey !== normalizedKey;
203
+ });
204
+
205
+ return [entry, ...remaining].slice(0, maxEntries);
206
+ }
207
+
208
+ function deriveTaskMode({ routingContext = {}, recentOutputs = [], fallback = '' } = {}) {
209
+ const explicit = normalizeTaskMode(fallback);
210
+ const targetFile = String(routingContext?.targetFile ?? '').trim();
211
+ const promptText = String(routingContext?.lastExplicitUserPromptText ?? routingContext?.promptText ?? '').trim();
212
+ if (targetFile || /(src|tests?|docs|app|lib)\//i.test(promptText) || /\b(test|debug|fix|implement|refactor|build)\b/i.test(promptText)) {
213
+ return 'coding';
214
+ }
215
+
216
+ if ((recentOutputs ?? []).some((entry) => /(?:test-runner|search|paths|git|package-install|docker-logs)/.test(String(entry.profile ?? '')))) {
217
+ return 'coding';
218
+ }
219
+
220
+ if (promptText) {
221
+ return 'mixed';
222
+ }
223
+
224
+ if (explicit) {
225
+ return explicit;
226
+ }
227
+
228
+ return 'chat';
229
+ }
230
+
231
+ function summarizeHistoryLayer(items, { label, maxItems = 2 } = {}) {
232
+ const normalized = uniqueStrings((items ?? []).map((item) => String(item ?? '').trim()));
233
+ if (normalized.length === 0) {
234
+ return null;
235
+ }
236
+
237
+ const shown = normalized.slice(0, maxItems);
238
+ const remaining = normalized.length - shown.length;
239
+ return `- ${label}: ${shown.join(' | ')}${remaining > 0 ? ` | +${remaining} more` : ''}`;
240
+ }
241
+
242
+ function firstImportantOutputSignal(summary) {
243
+ const lines = String(summary ?? '')
244
+ .split(/\r?\n/)
245
+ .map((line) => compressLine(line))
246
+ .filter(Boolean)
247
+ .filter((line) => !/^-\s*recent command:/i.test(line));
248
+ return lines[0] ?? compressLine(summary);
249
+ }
250
+
251
+ function compactBridgeValue(value, { maxWords = 8 } = {}) {
252
+ const normalized = normalizeWhitespace(
253
+ String(value ?? '')
254
+ .replace(/\(\+\d+\s+more\)/gi, ' ')
255
+ .split(/\s*[;|]\s*/)[0] ?? '',
256
+ );
257
+ if (!normalized) {
258
+ return '';
259
+ }
260
+
261
+ const words = normalized.split(/\s+/).filter(Boolean);
262
+ return words.slice(0, Math.max(1, maxWords)).join(' ');
263
+ }
264
+
265
+ function parsePreviousContextBridge(previousLine) {
266
+ const summary = {};
267
+ const segments = String(previousLine ?? '')
268
+ .split(/\s+\|\s+(?=\[[^\]]+\])/)
269
+ .map((segment) => segment.trim())
270
+ .filter(Boolean);
271
+
272
+ for (const segment of segments) {
273
+ const clauses = segment
274
+ .split(/\s+—\s+/)
275
+ .map((clause) => clause.trim())
276
+ .filter(Boolean);
277
+ if (clauses.length === 0) {
278
+ continue;
279
+ }
280
+
281
+ const header = clauses.shift() ?? '';
282
+ const projectMatch = header.match(/^\[project\]\s*(.+)$/i);
283
+ const sessionMatch = header.match(/^\[session\]\s*(.+)$/i);
284
+ if (projectMatch && !summary.project) {
285
+ summary.project = compactBridgeValue(projectMatch[1], { maxWords: 6 });
286
+ }
287
+ if (sessionMatch && !summary.task) {
288
+ summary.task = compactBridgeValue(sessionMatch[1], { maxWords: 6 });
289
+ }
290
+
291
+ for (const clause of clauses) {
292
+ const separatorIndex = clause.indexOf(':');
293
+ if (separatorIndex <= 0) {
294
+ continue;
295
+ }
296
+
297
+ const rawKey = clause.slice(0, separatorIndex).trim().toLowerCase();
298
+ const value = compactBridgeValue(clause.slice(separatorIndex + 1), {
299
+ maxWords: rawKey === 'rules' ? 6 : 8,
300
+ });
301
+ if (!value) {
302
+ continue;
303
+ }
304
+
305
+ if (rawKey.startsWith('decision') && !summary.decision) {
306
+ summary.decision = value;
307
+ } else if ((rawKey === 'rule' || rawKey === 'rules') && !summary.rule) {
308
+ summary.rule = value;
309
+ } else if (rawKey === 'next' && !summary.next) {
310
+ summary.next = value;
311
+ } else if ((rawKey === 'action' || rawKey === 'actions') && !summary.action) {
312
+ summary.action = value;
313
+ } else if (rawKey === 'outcome' && !summary.outcome) {
314
+ summary.outcome = value;
315
+ }
316
+ }
317
+ }
318
+
319
+ return summary;
320
+ }
321
+
322
+ function parseRouteBridge(routeLine) {
323
+ const summary = {};
324
+ const segments = String(routeLine ?? '')
325
+ .split(/\s+\|\s+/)
326
+ .map((segment) => segment.trim())
327
+ .filter(Boolean);
328
+
329
+ for (const segment of segments) {
330
+ const separatorIndex = segment.indexOf('=');
331
+ if (separatorIndex <= 0) {
332
+ continue;
333
+ }
334
+
335
+ const rawKey = segment.slice(0, separatorIndex).trim().toLowerCase();
336
+ const value = compactBridgeValue(segment.slice(separatorIndex + 1), {
337
+ maxWords: rawKey === 'targets' ? 4 : 8,
338
+ });
339
+ if (!value) {
340
+ continue;
341
+ }
342
+
343
+ if (rawKey === 'task' && !summary.task) {
344
+ summary.task = value;
345
+ } else if ((rawKey === 'target' || rawKey === 'targets') && !summary.focus) {
346
+ summary.focus = value;
347
+ } else if (rawKey === 'next' && !summary.next) {
348
+ summary.next = value;
349
+ }
350
+ }
351
+
352
+ return summary;
353
+ }
354
+
355
+ function buildMemoryBridgeLine(routeState = {}, state = {}) {
356
+ const previousLine = String(routeState?.previousContext?.line ?? '').trim();
357
+ const routeLine = String(routeState?.routeSummary?.line ?? '').trim();
358
+ const promptSummary = String(state?.recentPrompts?.[0]?.summary ?? '').trim();
359
+ const previousBridge = parsePreviousContextBridge(previousLine);
360
+ const routeBridge = parseRouteBridge(routeLine);
361
+ const promptBridge = compactBridgeValue(promptSummary, { maxWords: 10 });
362
+ const parts = [];
363
+ const seenParts = new Set();
364
+ const trivialRouteTasks = new Set(['trivial', 'non-trivial', 'complex', 'mixed', 'chat', 'coding']);
365
+
366
+ function pushBridgePart(key, value) {
367
+ const normalizedValue = compactBridgeValue(value, {
368
+ maxWords: key === 'task' ? 6 : key === 'focus' ? 4 : 8,
369
+ });
370
+ if (!normalizedValue) {
371
+ return;
372
+ }
373
+
374
+ if (key === 'task' && trivialRouteTasks.has(normalizedValue.toLowerCase())) {
375
+ return;
376
+ }
377
+
378
+ const dedupeKey = `${key}:${normalizedValue}`.toLowerCase();
379
+ if (seenParts.has(dedupeKey)) {
380
+ return;
381
+ }
382
+ seenParts.add(dedupeKey);
383
+ parts.push(`${key}=${normalizedValue}`);
384
+ }
385
+
386
+ pushBridgePart('task', previousBridge.task || routeBridge.task || promptBridge);
387
+ pushBridgePart('decision', previousBridge.decision);
388
+ pushBridgePart('rule', previousBridge.rule);
389
+ pushBridgePart('next', previousBridge.next || routeBridge.next);
390
+ pushBridgePart('focus', routeBridge.focus);
391
+ if (parts.length === 0) {
392
+ pushBridgePart('project', previousBridge.project);
393
+ pushBridgePart('action', previousBridge.action);
394
+ pushBridgePart('outcome', previousBridge.outcome);
395
+ }
396
+
397
+ if (parts.length === 0 && !routeLine && !promptSummary) {
398
+ return null;
399
+ }
400
+
401
+ if (parts.length > 0) {
402
+ return `- Memory bridge: ${parts.join(' | ')}`;
403
+ }
404
+
405
+ return `- Memory bridge: ${uniqueStrings([routeLine, promptSummary]).join(' | ')}`;
406
+ }
407
+
408
+ function computeEstimatedContextTokens(state) {
409
+ return finiteNumber(state?.estimatedContextTokens, 0);
410
+ }
411
+
412
+ function computeEstimatedTotalTokens({
413
+ recentPrompts = [],
414
+ recentOutputs = [],
415
+ estimatedContextTokens = 0,
416
+ baselineTokens = 0,
417
+ }) {
418
+ const promptTokens = recentPrompts.reduce((sum, entry) => sum + finiteNumber(entry.tokens, 0), 0);
419
+ const outputTokens = recentOutputs.reduce((sum, entry) => sum + finiteNumber(entry.tokensBefore ?? entry.tokens, 0), 0);
420
+ return baselineTokens + estimatedContextTokens + promptTokens + outputTokens;
421
+ }
422
+
423
+ export function buildCompactThresholds(config = {}) {
424
+ const softThreshold = Math.max(1, finiteNumber(config?.compact?.tokenThreshold, 100_000));
425
+ const hardThreshold = Math.max(softThreshold + 1, Math.round(softThreshold * 1.2));
426
+ const baselineTokens = Math.max(120, Math.min(18_000, Math.round(softThreshold * 0.18)));
427
+
428
+ return {
429
+ softThreshold,
430
+ hardThreshold,
431
+ baselineTokens,
432
+ };
433
+ }
434
+
435
+ function buildReleaseThresholds(thresholds = buildCompactThresholds()) {
436
+ const softReleaseThreshold = Math.max(
437
+ Math.min(thresholds.softThreshold, Math.round(thresholds.softThreshold * SOFT_RELEASE_RATIO)),
438
+ 1,
439
+ );
440
+ const hardReleaseThreshold = Math.max(
441
+ thresholds.softThreshold,
442
+ Math.round(thresholds.hardThreshold * HARD_RELEASE_RATIO),
443
+ );
444
+
445
+ return {
446
+ softReleaseThreshold,
447
+ hardReleaseThreshold,
448
+ };
449
+ }
450
+
451
+ export function resolveCompactPhase(
452
+ estimatedTotalTokens,
453
+ thresholds = buildCompactThresholds(),
454
+ previousState = {},
455
+ ) {
456
+ const previousPhase = normalizePhase(previousState?.phase ?? previousState);
457
+ const releaseThresholds = buildReleaseThresholds(thresholds);
458
+ if (estimatedTotalTokens >= thresholds.hardThreshold) {
459
+ return 'hard';
460
+ }
461
+ if (previousPhase === 'hard' && estimatedTotalTokens >= releaseThresholds.hardReleaseThreshold) {
462
+ return 'hard';
463
+ }
464
+ if (estimatedTotalTokens >= thresholds.softThreshold) {
465
+ return 'soft';
466
+ }
467
+ if (previousPhase !== 'monitor' && estimatedTotalTokens >= releaseThresholds.softReleaseThreshold) {
468
+ return 'soft';
469
+ }
470
+ return 'monitor';
471
+ }
472
+
473
+ function resolvePhaseCooldownMs(phase) {
474
+ return PHASE_COOLDOWN_MS[normalizePhase(phase)] ?? 0;
475
+ }
476
+
477
+ function resolvePlanDeltaThreshold(phase, thresholds = buildCompactThresholds()) {
478
+ return normalizePhase(phase) === 'hard'
479
+ ? Math.max(60, Math.round(thresholds.hardThreshold * 0.14))
480
+ : Math.max(40, Math.round(thresholds.softThreshold * 0.12));
481
+ }
482
+
483
+ function isMaterialThresholdPlanChange(previousPlan, nextPlan, thresholds) {
484
+ if (!previousPlan || !nextPlan) {
485
+ return true;
486
+ }
487
+
488
+ if (normalizePhase(previousPlan.phase) !== normalizePhase(nextPlan.phase)) {
489
+ return true;
490
+ }
491
+
492
+ const estimatedDelta = Math.abs(
493
+ finiteNumber(nextPlan.estimatedTotalTokens, 0) - finiteNumber(previousPlan.estimatedTotalTokens, 0),
494
+ );
495
+ if (estimatedDelta >= resolvePlanDeltaThreshold(nextPlan.phase, thresholds)) {
496
+ return true;
497
+ }
498
+
499
+ const savedDelta = Math.abs(
500
+ finiteNumber(nextPlan.savedTokens, 0) - finiteNumber(previousPlan.savedTokens, 0),
501
+ );
502
+ if (savedDelta >= 40) {
503
+ return true;
504
+ }
505
+
506
+ const previousLines = Array.isArray(previousPlan.lines)
507
+ ? previousPlan.lines
508
+ : String(previousPlan.summary ?? '').split(/\r?\n/).filter(Boolean);
509
+ const nextLines = Array.isArray(nextPlan.lines)
510
+ ? nextPlan.lines
511
+ : String(nextPlan.summary ?? '').split(/\r?\n/).filter(Boolean);
512
+
513
+ if (previousLines.length === 0 || nextLines.length === 0) {
514
+ return false;
515
+ }
516
+
517
+ return Math.abs(nextLines.length - previousLines.length) >= 2;
518
+ }
519
+
520
+ export function resolveThresholdCompactBudget({
521
+ phase = 'monitor',
522
+ maxTokens = 280,
523
+ maxLines = 12,
524
+ } = {}) {
525
+ const normalizedPhase = normalizePhase(phase);
526
+ if (normalizedPhase === 'hard') {
527
+ return {
528
+ maxTokens: Math.max(170, Math.round(maxTokens * 0.68)),
529
+ maxLines: Math.min(maxLines, 8),
530
+ };
531
+ }
532
+
533
+ if (normalizedPhase === 'soft') {
534
+ return {
535
+ maxTokens: Math.max(190, Math.round(maxTokens * 0.84)),
536
+ maxLines: Math.min(maxLines, 10),
537
+ };
538
+ }
539
+
540
+ return {
541
+ maxTokens,
542
+ maxLines,
543
+ };
544
+ }
545
+
546
+ export function buildCompactPressureState(rawState = null, config = {}) {
547
+ const thresholds = buildCompactThresholds(config);
548
+ const rawSoftThreshold = finiteNumber(rawState?.softThreshold, 0);
549
+ const rawHardThreshold = finiteNumber(rawState?.hardThreshold, 0);
550
+ if (!finiteNumber(config?.compact?.tokenThreshold, 0) && rawSoftThreshold > 0) {
551
+ thresholds.softThreshold = rawSoftThreshold;
552
+ thresholds.hardThreshold = rawHardThreshold > rawSoftThreshold
553
+ ? rawHardThreshold
554
+ : Math.max(rawSoftThreshold + 1, Math.round(rawSoftThreshold * 1.2));
555
+ thresholds.baselineTokens = Math.max(120, Math.min(18_000, Math.round(thresholds.softThreshold * 0.18)));
556
+ }
557
+ const recentPrompts = (Array.isArray(rawState?.recentPrompts) ? rawState.recentPrompts : [])
558
+ .map((entry) => normalizePromptEntry(entry))
559
+ .filter(Boolean)
560
+ .sort((left, right) => (right.timestamp ?? 0) - (left.timestamp ?? 0))
561
+ .slice(0, DEFAULT_MAX_PROMPT_ENTRIES);
562
+ const recentOutputs = (Array.isArray(rawState?.recentOutputs) ? rawState.recentOutputs : [])
563
+ .map((entry) => normalizeOutputEntry(entry))
564
+ .filter(Boolean)
565
+ .sort((left, right) => (right.timestamp ?? 0) - (left.timestamp ?? 0))
566
+ .slice(0, DEFAULT_MAX_OUTPUT_ENTRIES);
567
+ const estimatedContextTokens = computeEstimatedContextTokens(rawState);
568
+ const estimatedTotalTokens = finiteNumber(
569
+ rawState?.estimatedTotalTokens,
570
+ computeEstimatedTotalTokens({
571
+ recentPrompts,
572
+ recentOutputs,
573
+ estimatedContextTokens,
574
+ baselineTokens: thresholds.baselineTokens,
575
+ }),
576
+ );
577
+ const releaseThresholds = buildReleaseThresholds(thresholds);
578
+ const taskMode = deriveTaskMode({
579
+ routingContext: rawState?.routingContext ?? {},
580
+ recentOutputs,
581
+ fallback: rawState?.taskMode,
582
+ });
583
+
584
+ return {
585
+ updatedAt: finiteNumber(rawState?.updatedAt, Date.now()),
586
+ softThreshold: thresholds.softThreshold,
587
+ hardThreshold: thresholds.hardThreshold,
588
+ softReleaseThreshold: releaseThresholds.softReleaseThreshold,
589
+ hardReleaseThreshold: releaseThresholds.hardReleaseThreshold,
590
+ baselineTokens: thresholds.baselineTokens,
591
+ estimatedContextTokens,
592
+ estimatedTotalTokens,
593
+ phase: resolveCompactPhase(estimatedTotalTokens, thresholds, rawState),
594
+ taskMode,
595
+ cooldownUntil: finiteNumber(rawState?.cooldownUntil, 0),
596
+ routingContext: rawState?.routingContext && typeof rawState.routingContext === 'object'
597
+ ? rawState.routingContext
598
+ : {},
599
+ recentPrompts,
600
+ recentOutputs,
601
+ latestPlan: normalizeLatestPlan(rawState?.latestPlan),
602
+ historyLayers: uniqueStrings(rawState?.historyLayers ?? []).slice(0, DEFAULT_HISTORY_LAYER_COUNT),
603
+ stats: normalizeStats(rawState?.stats),
604
+ };
605
+ }
606
+
607
+ export function registerPromptPressure(state, {
608
+ promptText = '',
609
+ routingContext = {},
610
+ previousContext = null,
611
+ routeSummary = null,
612
+ timestamp = Date.now(),
613
+ } = {}, config = {}) {
614
+ const current = buildCompactPressureState(state, config);
615
+ const normalizedPrompt = String(promptText || routingContext?.lastExplicitUserPromptText || '').trim();
616
+ if (!normalizedPrompt) {
617
+ return current;
618
+ }
619
+
620
+ const entry = normalizePromptEntry({
621
+ timestamp,
622
+ tokens: estimateTokenCount(normalizedPrompt),
623
+ summary: summarizePromptText(normalizedPrompt, routingContext),
624
+ targetFile: routingContext?.targetFile ?? null,
625
+ taskType: routingContext?.taskType ?? null,
626
+ });
627
+ const recentPrompts = entry
628
+ ? upsertEntry(current.recentPrompts, entry, {
629
+ maxEntries: DEFAULT_MAX_PROMPT_ENTRIES,
630
+ keyBuilder: (candidate) => `${candidate.targetFile ?? ''}|${candidate.summary ?? ''}`,
631
+ })
632
+ : current.recentPrompts;
633
+
634
+ return buildCompactPressureState({
635
+ ...current,
636
+ updatedAt: timestamp,
637
+ routingContext,
638
+ recentPrompts,
639
+ estimatedTotalTokens: undefined,
640
+ estimatedContextTokens: estimateTokenCount([
641
+ routeSummary?.line ?? '',
642
+ previousContext?.line ?? '',
643
+ summarizePromptText(normalizedPrompt, routingContext),
644
+ ].filter(Boolean).join('\n')),
645
+ taskMode: deriveTaskMode({
646
+ routingContext,
647
+ recentOutputs: current.recentOutputs,
648
+ fallback: current.taskMode,
649
+ }),
650
+ }, config);
651
+ }
652
+
653
+ export function registerOutputPressure(state, {
654
+ command = '',
655
+ profile = 'generic',
656
+ summary = '',
657
+ tokensBefore = 0,
658
+ tokensAfter = 0,
659
+ savedTokens = 0,
660
+ exitCode = null,
661
+ timestamp = Date.now(),
662
+ } = {}, config = {}) {
663
+ const current = buildCompactPressureState(state, config);
664
+ const normalizedSummary = summarizeOutputText(summary, command);
665
+ if (!normalizedSummary) {
666
+ return current;
667
+ }
668
+
669
+ const entry = normalizeOutputEntry({
670
+ timestamp,
671
+ command,
672
+ profile,
673
+ exitCode,
674
+ tokensBefore: Math.max(1, finiteNumber(tokensBefore, estimateTokenCount(summary || normalizedSummary))),
675
+ tokensAfter: Math.max(1, finiteNumber(tokensAfter, estimateTokenCount(normalizedSummary))),
676
+ savedTokens: Math.max(0, finiteNumber(savedTokens, 0)),
677
+ summary: normalizedSummary,
678
+ });
679
+ const recentOutputs = upsertEntry(current.recentOutputs, entry, {
680
+ maxEntries: DEFAULT_MAX_OUTPUT_ENTRIES,
681
+ keyBuilder: (candidate) => `${candidate.command ?? ''}|${candidate.summary ?? ''}`,
682
+ });
683
+
684
+ return buildCompactPressureState({
685
+ ...current,
686
+ updatedAt: timestamp,
687
+ recentOutputs,
688
+ estimatedTotalTokens: undefined,
689
+ taskMode: deriveTaskMode({
690
+ routingContext: current.routingContext ?? {},
691
+ recentOutputs,
692
+ fallback: current.taskMode || (profile ? 'coding' : ''),
693
+ }),
694
+ }, config);
695
+ }
696
+
697
+ export function registerThresholdCompactPlan(state, plan, config = {}) {
698
+ const current = buildCompactPressureState(state, config);
699
+ if (!plan?.active) {
700
+ return current;
701
+ }
702
+
703
+ const thresholds = {
704
+ softThreshold: current.softThreshold,
705
+ hardThreshold: current.hardThreshold,
706
+ };
707
+ const now = Date.now();
708
+ const fingerprint = buildCompactMachineKey('threshold-plan-v1', {
709
+ phase: plan.phase,
710
+ estimatedTotalTokens: plan.estimatedTotalTokens,
711
+ lines: plan.lines,
712
+ });
713
+ if (current.latestPlan?.fingerprint === fingerprint) {
714
+ return buildCompactPressureState({
715
+ ...current,
716
+ updatedAt: now,
717
+ latestPlan: {
718
+ ...current.latestPlan,
719
+ updatedAt: now,
720
+ },
721
+ }, config);
722
+ }
723
+
724
+ const withinCooldown = (
725
+ current.latestPlan
726
+ && normalizePhase(current.latestPlan.phase) === normalizePhase(plan.phase)
727
+ && finiteNumber(current.cooldownUntil, 0) > now
728
+ );
729
+ const materialChange = isMaterialThresholdPlanChange(current.latestPlan, plan, thresholds);
730
+
731
+ if (withinCooldown && !materialChange) {
732
+ return buildCompactPressureState({
733
+ ...current,
734
+ updatedAt: now,
735
+ latestPlan: {
736
+ ...current.latestPlan,
737
+ fingerprint,
738
+ phase: normalizePhase(plan.phase),
739
+ estimatedTotalTokens: finiteNumber(plan.estimatedTotalTokens, 0),
740
+ tokensBefore: finiteNumber(plan.tokensBefore, 0),
741
+ tokensAfter: finiteNumber(plan.tokensAfter, 0),
742
+ savedTokens: finiteNumber(plan.savedTokens, 0),
743
+ summary: Array.isArray(plan.lines) ? plan.lines.join('\n') : current.latestPlan?.summary ?? '',
744
+ updatedAt: now,
745
+ reusedCooldown: true,
746
+ },
747
+ }, config);
748
+ }
749
+
750
+ const stats = normalizeStats(current.stats);
751
+ stats.thresholdHits += 1;
752
+ if (plan.phase === 'hard') {
753
+ stats.hardHits += 1;
754
+ } else if (plan.phase === 'soft') {
755
+ stats.softHits += 1;
756
+ }
757
+
758
+ return buildCompactPressureState({
759
+ ...current,
760
+ updatedAt: now,
761
+ cooldownUntil: now + resolvePhaseCooldownMs(plan.phase),
762
+ historyLayers: uniqueStrings(plan.layers ?? []).slice(0, DEFAULT_HISTORY_LAYER_COUNT),
763
+ latestPlan: {
764
+ fingerprint,
765
+ updatedAt: now,
766
+ phase: plan.phase,
767
+ estimatedTotalTokens: plan.estimatedTotalTokens,
768
+ tokensBefore: plan.tokensBefore,
769
+ tokensAfter: plan.tokensAfter,
770
+ savedTokens: plan.savedTokens,
771
+ summary: Array.isArray(plan.lines) ? plan.lines.join('\n') : '',
772
+ reusedCooldown: false,
773
+ },
774
+ stats,
775
+ }, config);
776
+ }
777
+
778
+ export function buildThresholdCompactPlan({
779
+ state,
780
+ config = {},
781
+ routeState = {},
782
+ staticLines = [],
783
+ dynamicLines = [],
784
+ maxTokens = 280,
785
+ } = {}) {
786
+ const normalizedState = buildCompactPressureState(state, config);
787
+ const thresholds = buildCompactThresholds(config);
788
+ const phase = normalizedState.phase;
789
+ if (phase === 'monitor') {
790
+ return {
791
+ active: false,
792
+ phase,
793
+ estimatedTotalTokens: normalizedState.estimatedTotalTokens,
794
+ lines: [],
795
+ layers: normalizedState.historyLayers,
796
+ tokensBefore: 0,
797
+ tokensAfter: 0,
798
+ savedTokens: 0,
799
+ };
800
+ }
801
+
802
+ const budget = resolveThresholdCompactBudget({
803
+ phase,
804
+ maxTokens,
805
+ maxLines: 12,
806
+ });
807
+ const laneLine = (staticLines ?? []).find((line) => String(line ?? '').startsWith('- Current lane:'))
808
+ ?? (routeState?.routingContext?.taskType
809
+ ? `- Current lane: ${routeState.routingContext.taskType}`
810
+ : null);
811
+ const worklogLine = phase === 'hard'
812
+ ? null
813
+ : ((staticLines ?? []).find((line) => String(line ?? '').startsWith('- WORKLOG:')) ?? null);
814
+ const routeLine = (dynamicLines ?? []).find((line) => String(line ?? '').startsWith('- Recent routed lane:'))
815
+ ?? (routeState?.routeSummary?.line ? `- Recent routed lane: ${routeState.routeSummary.line}` : null);
816
+ const previousLine = (dynamicLines ?? []).find((line) => String(line ?? '').startsWith('- Previous context:'))
817
+ ?? (routeState?.previousContext?.line ? `- Previous context: ${routeState.previousContext.line}` : null);
818
+ const outputLine = (dynamicLines ?? []).find((line) => String(line ?? '').startsWith('- Recent command output:'))
819
+ ?? (
820
+ normalizedState.recentOutputs[0]?.summary
821
+ ? `- Recent command output: ${firstImportantOutputSignal(normalizedState.recentOutputs[0]?.summary)}`
822
+ : null
823
+ );
824
+ const verificationLine = (dynamicLines ?? []).find((line) => /broad verification/i.test(String(line ?? ''))) ?? null;
825
+ const thresholdLine = `- Threshold compact: ${phase} (est ${normalizedState.estimatedTotalTokens} / soft ${thresholds.softThreshold} / hard ${thresholds.hardThreshold}). Compact duplicates/logs only; preserve critical context.`;
826
+ const taskModeLine = `- Task-aware mode: ${normalizedState.taskMode || 'mixed'} => preserve active task, rules, decisions, and current code focus.`;
827
+ const memoryBridgeLine = buildMemoryBridgeLine(routeState, normalizedState);
828
+ const recentFocusLine = summarizeHistoryLayer([
829
+ normalizedState.recentPrompts[0]?.summary,
830
+ firstImportantOutputSignal(normalizedState.recentOutputs[0]?.summary),
831
+ ], {
832
+ label: 'Recent focus',
833
+ maxItems: 2,
834
+ });
835
+ const layerOne = summarizeHistoryLayer([
836
+ ...normalizedState.recentPrompts.slice(1, 3).map((entry) => entry.summary),
837
+ ...normalizedState.recentOutputs.slice(1, 3).map((entry) => firstImportantOutputSignal(entry.summary)),
838
+ ], {
839
+ label: 'Layer 1 summary',
840
+ maxItems: 2,
841
+ });
842
+ const layerTwo = phase === 'hard'
843
+ ? summarizeHistoryLayer([
844
+ ...normalizedState.recentPrompts.slice(3).map((entry) => entry.summary),
845
+ ...normalizedState.recentOutputs.slice(3).map((entry) => firstImportantOutputSignal(entry.summary)),
846
+ ], {
847
+ label: 'Layer 2 summary',
848
+ maxItems: 2,
849
+ })
850
+ : null;
851
+ const askBeforeDropLine = Boolean(config?.compact?.askBeforeDrop)
852
+ ? '- Ask-before-drop: if older decisions, rules, or unresolved failures still matter, confirm with the user before removing them.'
853
+ : null;
854
+
855
+ const rawLines = uniqueStrings([
856
+ thresholdLine,
857
+ taskModeLine,
858
+ laneLine,
859
+ worklogLine,
860
+ routeLine,
861
+ previousLine,
862
+ outputLine,
863
+ memoryBridgeLine,
864
+ recentFocusLine,
865
+ layerOne,
866
+ layerTwo,
867
+ askBeforeDropLine,
868
+ verificationLine,
869
+ ...(dynamicLines ?? []).filter((line) => {
870
+ const normalized = compressLine(line);
871
+ if (!normalized) return false;
872
+ if (normalized === routeLine || normalized === previousLine || normalized === outputLine || normalized === verificationLine) {
873
+ return false;
874
+ }
875
+ return !EXPENDABLE_LINE_PATTERNS.some((pattern) => pattern.test(normalized));
876
+ }),
877
+ ]);
878
+
879
+ const compacted = compactContextBlock(rawLines, {
880
+ maxTokens: budget.maxTokens,
881
+ maxLines: budget.maxLines,
882
+ anchorLines: [
883
+ thresholdLine,
884
+ routeLine,
885
+ previousLine,
886
+ outputLine,
887
+ memoryBridgeLine,
888
+ askBeforeDropLine,
889
+ ].filter(Boolean),
890
+ maxAnchors: 6,
891
+ });
892
+
893
+ return {
894
+ active: true,
895
+ phase,
896
+ estimatedTotalTokens: normalizedState.estimatedTotalTokens,
897
+ taskMode: normalizedState.taskMode,
898
+ budgetTokens: budget.maxTokens,
899
+ budgetLines: budget.maxLines,
900
+ lines: compacted.text ? compacted.text.split(/\r?\n/) : [],
901
+ layers: [layerOne, layerTwo].filter(Boolean),
902
+ tokensBefore: compacted.tokensBefore,
903
+ tokensAfter: compacted.tokensAfter,
904
+ savedTokens: compacted.savedTokens,
905
+ };
906
+ }
907
+
908
+ export async function readCompactPressureState(projectRoot, config = {}) {
909
+ const runtimePaths = buildRuntimePaths(projectRoot);
910
+ return buildCompactPressureState(await readJsonIfExists(runtimePaths.compactPressurePath), config);
911
+ }
912
+
913
+ export async function writeCompactPressureState(projectRoot, state, config = {}) {
914
+ const runtimePaths = buildRuntimePaths(projectRoot);
915
+ const normalized = buildCompactPressureState(state, config);
916
+ await writeJson(runtimePaths.compactPressurePath, normalized);
917
+ return normalized;
918
+ }
919
+
920
+ export async function updateCompactPressureFromPrompt(projectRoot, payload, config = {}) {
921
+ const current = await readCompactPressureState(projectRoot, config);
922
+ const next = registerPromptPressure(current, payload, config);
923
+ return writeCompactPressureState(projectRoot, next, config);
924
+ }
925
+
926
+ export async function updateCompactPressureFromOutput(projectRoot, payload, config = {}) {
927
+ const current = await readCompactPressureState(projectRoot, config);
928
+ const next = registerOutputPressure(current, payload, config);
929
+ return writeCompactPressureState(projectRoot, next, config);
930
+ }
931
+
932
+ export async function writeThresholdCompactPlan(projectRoot, plan, config = {}) {
933
+ const current = await readCompactPressureState(projectRoot, config);
934
+ const next = registerThresholdCompactPlan(current, plan, config);
935
+ return writeCompactPressureState(projectRoot, next, config);
936
+ }