@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,631 @@
1
+ # DuraOne SQL Reference
2
+ ## PostgreSQL — Views, Functions, Stored Procedures
3
+
4
+ > Nguồn sự thật cho phong cách viết SQL của LeNK.
5
+ > Database: PostgreSQL với 2 schema: `qas` (test) và `prd` (production)
6
+
7
+ ---
8
+
9
+ ## MỤC LỤC
10
+ 1. [Schema Organization](#1-schema-organization)
11
+ 2. [Data Types — Quy Tắc Bắt Buộc](#2-data-types)
12
+ 3. [Naming Conventions](#3-naming-conventions)
13
+ 4. [View Pattern (v_)](#4-view-pattern)
14
+ 5. [Function Pattern (fn_)](#5-function-pattern)
15
+ 6. [Stored Procedure Pattern (sp_)](#6-stored-procedure-pattern)
16
+ 7. [Table Design Conventions](#7-table-design-conventions)
17
+ 8. [Common SQL Patterns](#8-common-sql-patterns)
18
+ 9. [File Organization](#9-file-organization)
19
+
20
+ ---
21
+
22
+ ## 1. Schema Organization
23
+
24
+ ```
25
+ PostgreSQL Database: duraone
26
+ ├── qas (schema — QA/Testing)
27
+ │ ├── Tables
28
+ │ ├── Views: v_*
29
+ │ ├── Functions: fn_*
30
+ │ └── Procedures: sp_*
31
+
32
+ └── prd (schema — Production)
33
+ ├── Tables (mirrors qas)
34
+ ├── Views: v_*
35
+ ├── Functions: fn_*
36
+ └── Procedures: sp_*
37
+ ```
38
+
39
+ **Quy tắc:**
40
+ - Tất cả SQL objects LUÔN có schema prefix: `qas.` hoặc `prd.`
41
+ - Không viết SQL mà không có schema prefix
42
+ - Khi deploy, chạy SQL trên cả 2 schema (qas trước, prd sau)
43
+ - View/Function/Procedure trong qas và prd có cùng tên, chỉ khác schema prefix
44
+
45
+ ---
46
+
47
+ ## 2. Data Types — QUY TẮC BẮT BUỘC
48
+
49
+ **CHỈ dùng 3 data type này. KHÔNG dùng bất kỳ loại nào khác:**
50
+
51
+ | Type | Khi nào dùng | Default |
52
+ |------|-------------|---------|
53
+ | `varchar` | Text, ngày tháng, UUID, enum, mọi thứ dạng chuỗi | `default ''` |
54
+ | `numeric` | Số (integer, decimal, float, quantity) | `default 0` |
55
+ | `boolean` | True/false flags | `default false` |
56
+
57
+ **KHÔNG ĐƯỢC dùng:**
58
+ - ❌ `integer`, `int`, `bigint`, `serial` — dùng `numeric` thay thế
59
+ - ❌ `date`, `timestamp`, `timestamptz`, `datetime` — dùng `varchar` với format string
60
+ - ❌ `text` — dùng `varchar`
61
+ - ❌ `jsonb`, `json` — dùng `varchar` chứa JSON string
62
+ - ❌ `uuid` — dùng `varchar` với UUID generator default
63
+ - ❌ `NULL` — LUÔN có default value: `''` cho varchar, `0` cho numeric, `false` cho boolean
64
+
65
+ **Ngày tháng lưu dạng varchar:**
66
+ ```sql
67
+ -- created_at: varchar với timezone Asia/Ho_Chi_Minh
68
+ created_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
69
+ 'YYYY-MM-DD HH24:MI:SS')::character varying
70
+ -- → lưu thành string "2024-01-15 10:30:00"
71
+ ```
72
+
73
+ ---
74
+
75
+ ## 3. Naming Conventions
76
+
77
+ | Loại Object | Prefix | Ví dụ |
78
+ |------------|--------|-------|
79
+ | View | `v_` | `v_agreement`, `v_clearance_request` |
80
+ | Function | `fn_` | `fn_get_agreement`, `fn_get_review_list` |
81
+ | Stored Procedure | `sp_` | `sp_generate_running_no`, `sp_after_approve` |
82
+ | Table | snake_case | `agreement`, `clearance_request`, `user` |
83
+ | Global Function | `glb_fn_` | `glb_fn_convert_query_to_json` |
84
+ | Column | snake_case | `id_agreement`, `created_at`, `is_active` |
85
+ | ID Column | `id_` prefix | `id_agreement`, `id_user`, `id_type` |
86
+ | Boolean Column | `is_`/`can_`/`has_` | `is_active`, `can_approve`, `has_file` |
87
+
88
+ **File naming (SQL files):**
89
+ ```
90
+ mainapp/SQL/duraone/qas/
91
+ ├── view/
92
+ │ └── v_agreement.sql
93
+ ├── function/
94
+ │ └── fn_get_agreement.sql
95
+ └── store/
96
+ └── sp_generate_running_no.sql
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 4. View Pattern (v_)
102
+
103
+ View là layer chính để FE đọc data — luôn dùng view thay vì query raw table.
104
+
105
+ ```sql
106
+ -- ──────────────────────────────────────────────
107
+ -- TEMPLATE: View cơ bản
108
+ -- ──────────────────────────────────────────────
109
+ CREATE OR REPLACE VIEW qas.v_agreement AS
110
+ SELECT
111
+ -- Primary key
112
+ a.id_agreement,
113
+
114
+ -- Core fields
115
+ a.agreement_number,
116
+ a.status,
117
+
118
+ -- Date fields — substring để lấy date part
119
+ a.created_at,
120
+ SUBSTRING(a.created_at::text, 1, 10) AS created_date,
121
+
122
+ -- Computed numeric — LUÔN COALESCE để tránh null
123
+ COALESCE(a.amount, 0)::numeric(16, 2) AS amount,
124
+ COALESCE(a.discount, 0)::numeric(16, 2) AS discount,
125
+ COALESCE(a.amount, 0) - COALESCE(a.discount, 0) AS net_amount,
126
+
127
+ -- Boolean flags — computed từ business logic
128
+ CASE WHEN a.status IN ('draft', 'rejected') THEN TRUE ELSE FALSE END AS can_edit,
129
+ CASE WHEN a.status = 'approved' THEN TRUE ELSE FALSE END AS is_locked,
130
+ FALSE AS can_delete,
131
+
132
+ -- Joined fields
133
+ b.branch_name,
134
+ u.fullname AS created_by_name,
135
+
136
+ -- JSON aggregation cho nested data
137
+ COALESCE(
138
+ (SELECT json_agg(json_build_object(
139
+ 'id_media', m.id_media,
140
+ 'media_name', m.media_name,
141
+ 'amount', COALESCE(m.amount, 0)
142
+ ))
143
+ FROM qas.agreement_media m
144
+ WHERE m.id_agreement = a.id_agreement),
145
+ '[]'::json
146
+ ) AS media_list,
147
+
148
+ -- Count
149
+ (SELECT COUNT(*) FROM qas.agreement_media m
150
+ WHERE m.id_agreement = a.id_agreement) AS media_count
151
+
152
+ FROM qas.agreement a
153
+ LEFT JOIN qas.branch b ON b.id_branch = a.id_branch
154
+ LEFT JOIN qas.user u ON u.username = a.created_by
155
+ WHERE a.is_deleted = FALSE -- soft delete pattern
156
+ ORDER BY a.created_at DESC;
157
+ ```
158
+
159
+ **Conventions trong View:**
160
+ ```sql
161
+ -- ✅ LUÔN COALESCE numeric
162
+ COALESCE(field, 0)::numeric(16, 2)
163
+
164
+ -- ✅ LUÔN có boolean flags
165
+ TRUE AS can_edit,
166
+ FALSE AS can_delete,
167
+ CASE WHEN status = 'approved' THEN TRUE ELSE FALSE END AS is_approved,
168
+
169
+ -- ✅ Date format
170
+ SUBSTRING(created_at::text, 1, 10) AS created_date -- YYYY-MM-DD
171
+
172
+ -- ✅ NULL-safe string concat
173
+ COALESCE(first_name, '') || ' ' || COALESCE(last_name, '') AS full_name
174
+
175
+ -- ✅ Soft delete filter trong view
176
+ WHERE is_deleted = FALSE
177
+
178
+ -- ✅ JSON array cho 1-to-many
179
+ COALESCE(json_agg(...) FILTER (WHERE id IS NOT NULL), '[]'::json) AS items
180
+ ```
181
+
182
+ ---
183
+
184
+ ## 5. Function Pattern (fn_)
185
+
186
+ Function dùng khi cần filter phức tạp hoặc business logic:
187
+
188
+ ```sql
189
+ -- ──────────────────────────────────────────────
190
+ -- TEMPLATE: Function trả về SETOF view
191
+ -- ──────────────────────────────────────────────
192
+ CREATE OR REPLACE FUNCTION qas.fn_get_agreement(
193
+ _username VARCHAR DEFAULT NULL,
194
+ _from_date DATE DEFAULT NULL,
195
+ _to_date DATE DEFAULT NULL,
196
+ _status VARCHAR DEFAULT NULL
197
+ )
198
+ RETURNS SETOF qas.v_agreement AS
199
+ $$
200
+ DECLARE
201
+ v_query TEXT;
202
+ v_conditions TEXT := 'WHERE TRUE';
203
+ BEGIN
204
+ -- Build dynamic conditions
205
+ IF _username IS NOT NULL AND _username <> '' THEN
206
+ v_conditions := v_conditions || format(' AND created_by = %L', _username);
207
+ END IF;
208
+
209
+ IF _from_date IS NOT NULL THEN
210
+ v_conditions := v_conditions || format(' AND created_date >= %L', _from_date);
211
+ END IF;
212
+
213
+ IF _to_date IS NOT NULL THEN
214
+ v_conditions := v_conditions || format(' AND created_date <= %L', _to_date);
215
+ END IF;
216
+
217
+ IF _status IS NOT NULL AND _status <> '' THEN
218
+ v_conditions := v_conditions || format(' AND status = %L', _status);
219
+ END IF;
220
+
221
+ v_query := 'SELECT * FROM qas.v_agreement ' || v_conditions || ' ORDER BY created_at DESC';
222
+
223
+ RETURN QUERY EXECUTE v_query;
224
+ END;
225
+ $$ LANGUAGE plpgsql;
226
+
227
+
228
+ -- ──────────────────────────────────────────────
229
+ -- TEMPLATE: Function trả về SETOF TABLE (custom shape)
230
+ -- ──────────────────────────────────────────────
231
+ CREATE OR REPLACE FUNCTION qas.fn_get_summary_by_branch(
232
+ _from_date VARCHAR,
233
+ _to_date VARCHAR
234
+ )
235
+ RETURNS TABLE(
236
+ id_branch VARCHAR,
237
+ branch_name VARCHAR,
238
+ total_amount NUMERIC(16, 2),
239
+ total_count NUMERIC
240
+ ) AS
241
+ $$
242
+ BEGIN
243
+ RETURN QUERY
244
+ SELECT
245
+ b.id_branch,
246
+ b.branch_name,
247
+ COALESCE(SUM(a.amount), 0)::numeric(16, 2) AS total_amount,
248
+ COUNT(a.id_agreement)::numeric AS total_count
249
+ FROM qas.branch b
250
+ LEFT JOIN qas.agreement a
251
+ ON a.id_branch = b.id_branch
252
+ AND a.created_date BETWEEN _from_date AND _to_date
253
+ AND a.is_deleted = FALSE
254
+ GROUP BY b.id_branch, b.branch_name
255
+ ORDER BY b.branch_name;
256
+ END;
257
+ $$ LANGUAGE plpgsql;
258
+ ```
259
+
260
+ **Conventions trong Function:**
261
+ ```sql
262
+ -- ✅ Parameter prefix _
263
+ _username VARCHAR
264
+
265
+ -- ✅ Variable prefix v_
266
+ v_query TEXT;
267
+ v_count NUMERIC;
268
+
269
+ -- ✅ Default NULL cho optional params
270
+ _status VARCHAR DEFAULT NULL
271
+
272
+ -- ✅ Guard với IS NOT NULL AND <> ''
273
+ IF _param IS NOT NULL AND _param <> '' THEN
274
+
275
+ -- ✅ format() cho dynamic SQL (SQL injection safe)
276
+ format(' AND field = %L', _value)
277
+ format(' AND id = %s', _id::text)
278
+
279
+ -- ✅ RETURN QUERY EXECUTE cho dynamic
280
+ RETURN QUERY EXECUTE v_query;
281
+
282
+ -- ✅ RETURN QUERY cho static
283
+ RETURN QUERY SELECT ... FROM ...;
284
+ ```
285
+
286
+ ---
287
+
288
+ ## 6. Stored Procedure Pattern (sp_)
289
+
290
+ Dùng cho business operations (running numbers, audit logs, cascade updates):
291
+
292
+ ```sql
293
+ -- ──────────────────────────────────────────────
294
+ -- TEMPLATE: Generate running number
295
+ -- ──────────────────────────────────────────────
296
+ CREATE OR REPLACE FUNCTION qas.sp_generate_running_no(
297
+ _prefix VARCHAR,
298
+ _year NUMERIC DEFAULT EXTRACT(YEAR FROM NOW())::NUMERIC
299
+ )
300
+ RETURNS VARCHAR AS
301
+ $$
302
+ DECLARE
303
+ v_running_no NUMERIC;
304
+ v_result VARCHAR;
305
+ BEGIN
306
+ -- Lock table row để tránh concurrent issues
307
+ SELECT COALESCE(MAX(seq_no), 0) + 1
308
+ INTO v_running_no
309
+ FROM qas.running_number
310
+ WHERE prefix = _prefix
311
+ AND year = _year
312
+ FOR UPDATE;
313
+
314
+ -- Insert hoặc update sequence
315
+ INSERT INTO qas.running_number (prefix, year, seq_no)
316
+ VALUES (_prefix, _year, v_running_no)
317
+ ON CONFLICT (prefix, year)
318
+ DO UPDATE SET seq_no = v_running_no;
319
+
320
+ -- Format: PREFIX-YYYY-XXXXX
321
+ v_result := _prefix || '-' || _year::TEXT || '-' || LPAD(v_running_no::TEXT, 5, '0');
322
+
323
+ RETURN v_result;
324
+ END;
325
+ $$ LANGUAGE plpgsql;
326
+
327
+
328
+ -- ──────────────────────────────────────────────
329
+ -- TEMPLATE: After-approve procedure
330
+ -- ──────────────────────────────────────────────
331
+ CREATE OR REPLACE FUNCTION qas.sp_after_approve(
332
+ _id_agreement VARCHAR
333
+ )
334
+ RETURNS JSON AS
335
+ $$
336
+ DECLARE
337
+ v_agreement RECORD;
338
+ v_result JSON;
339
+ BEGIN
340
+ -- Get agreement data
341
+ SELECT * INTO v_agreement
342
+ FROM qas.agreement
343
+ WHERE id_agreement = _id_agreement;
344
+
345
+ IF NOT FOUND THEN
346
+ RETURN json_build_object('success', false, 'message', 'Agreement not found');
347
+ END IF;
348
+
349
+ -- Update related records
350
+ UPDATE qas.agreement_media
351
+ SET status = 'confirmed',
352
+ confirmed_at = NOW()
353
+ WHERE id_agreement = _id_agreement;
354
+
355
+ -- Create audit log
356
+ INSERT INTO qas.audit_log (
357
+ table_name, record_id, action, changed_at
358
+ ) VALUES (
359
+ 'agreement', _id_agreement, 'approved', NOW()
360
+ );
361
+
362
+ RETURN json_build_object('success', true, 'id_agreement', _id_agreement);
363
+
364
+ EXCEPTION WHEN OTHERS THEN
365
+ RETURN json_build_object('success', false, 'message', SQLERRM);
366
+ END;
367
+ $$ LANGUAGE plpgsql;
368
+ ```
369
+
370
+ ---
371
+
372
+ ## 7. Table Design Conventions
373
+
374
+ ```sql
375
+ -- ──────────────────────────────────────────────
376
+ -- TEMPLATE: Standard table
377
+ -- Rules: chỉ varchar/numeric/boolean, không NULL
378
+ -- ──────────────────────────────────────────────
379
+ create table qas.agreement
380
+ (
381
+ -- Primary Key: uuid varchar
382
+ id_agreement varchar default uuid_in(overlay(
383
+ overlay(md5(random()::text || ':' || random()::text) placing '4' from 13)
384
+ placing to_hex(floor(random() * (11 - 8 + 1) + 8)::int)::text from 17)::cstring)
385
+ constraint agreement_pkey primary key,
386
+
387
+ -- Business fields — LUÔN có default
388
+ agreement_number varchar default '',
389
+ status varchar default 'draft',
390
+ amount numeric default 0,
391
+ note varchar default '',
392
+
393
+ -- Foreign keys: id_ prefix (varchar)
394
+ id_branch varchar default '' references qas.branch (id_branch),
395
+ id_type varchar default '' references qas.agreement_type (id_type),
396
+
397
+ -- Data phụ (JSON string dạng varchar)
398
+ extra_data varchar default '',
399
+
400
+ -- Boolean flags: is_ prefix
401
+ is_active boolean default true,
402
+ is_deleted boolean default false,
403
+
404
+ -- Audit fields — varchar timezone VN
405
+ created_by varchar default '',
406
+ created_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
407
+ 'YYYY-MM-DD HH24:MI:SS')::character varying,
408
+ updated_by varchar default '',
409
+ updated_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
410
+ 'YYYY-MM-DD HH24:MI:SS')::character varying
411
+ );
412
+
413
+ create index if not exists idx_agreement_status on qas.agreement (status);
414
+ create index if not exists idx_agreement_branch on qas.agreement (id_branch);
415
+ create index if not exists idx_agreement_created on qas.agreement (created_at);
416
+ ```
417
+
418
+ **UUID Generator Pattern — dùng cho mọi table:**
419
+ ```sql
420
+ -- Macro UUID (copy nguyên cụm này cho mỗi PK mới)
421
+ id_<table_name> varchar default uuid_in(overlay(
422
+ overlay(md5(random()::text || ':' || random()::text) placing '4' from 13) placing
423
+ to_hex(floor(random() * (11 - 8 + 1) + 8)::int)::text from 17)::cstring)
424
+ constraint <table_name>_pkey primary key
425
+
426
+ -- Ví dụ:
427
+ id_user varchar default uuid_in(overlay(
428
+ overlay(md5(random()::text || ':' || random()::text) placing '4' from 13) placing
429
+ to_hex(floor(random() * (11 - 8 + 1) + 8)::int)::text from 17)::cstring)
430
+ constraint user_pkey primary key,
431
+
432
+ id_branch varchar default uuid_in(overlay(
433
+ overlay(md5(random()::text || ':' || random()::text) placing '4' from 13) placing
434
+ to_hex(floor(random() * (11 - 8 + 1) + 8)::int)::text from 17)::cstring)
435
+ constraint branch_pkey primary key,
436
+ ```
437
+
438
+ **Audit fields LUÔN có trong mọi table — varchar, timezone VN:**
439
+ ```sql
440
+ created_by varchar default '',
441
+ created_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
442
+ 'YYYY-MM-DD HH24:MI:SS')::character varying,
443
+ updated_by varchar default '',
444
+ updated_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
445
+ 'YYYY-MM-DD HH24:MI:SS')::character varying
446
+ ```
447
+
448
+ **Full Table Template với tất cả conventions:**
449
+ ```sql
450
+ create table prd.table_name
451
+ (
452
+ id_table_name varchar default uuid_in(overlay(
453
+ overlay(md5(random()::text || ':' || random()::text) placing '4' from 13) placing
454
+ to_hex(floor(random() * (11 - 8 + 1) + 8)::int)::text from 17)::cstring)
455
+ constraint table_name_pkey primary key,
456
+
457
+ -- business fields — LUÔN plain varchar/numeric/boolean, LUÔN có default
458
+ field_name varchar default '',
459
+ amount numeric default 0,
460
+ status varchar default 'draft',
461
+ is_active boolean default true,
462
+ is_deleted boolean default false,
463
+
464
+ -- foreign keys (varchar UUID, default '')
465
+ id_parent varchar default '' references prd.parent_table (id_parent),
466
+
467
+ -- audit fields
468
+ created_by varchar default '',
469
+ created_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
470
+ 'YYYY-MM-DD HH24:MI:SS')::character varying,
471
+ updated_by varchar default '',
472
+ updated_at varchar default TO_CHAR(date_trunc('second', now() AT TIME ZONE 'Asia/Ho_Chi_Minh'),
473
+ 'YYYY-MM-DD HH24:MI:SS')::character varying
474
+ );
475
+ ```
476
+
477
+ > ⚠️ **Lưu ý `updated_at`:** `DEFAULT` chỉ chạy khi `INSERT`. Khi `UPDATE`, backend phải tự set tường minh:
478
+ > ```sql
479
+ > updated_at = TO_CHAR(NOW() AT TIME ZONE 'Asia/Ho_Chi_Minh', 'YYYY-MM-DD HH24:MI:SS'),
480
+ > updated_by = _username
481
+ > ```
482
+ > Hoặc dùng `/api/save` generic endpoint — endpoint này tự inject `updated_at` / `updated_by` vào mọi UPDATE.
483
+
484
+ ---
485
+
486
+ ## 8. Common SQL Patterns
487
+
488
+ ### JSON Aggregation
489
+ ```sql
490
+ -- Array of objects
491
+ json_agg(json_build_object(
492
+ 'id', m.id_media,
493
+ 'name', m.media_name,
494
+ 'amount', COALESCE(m.amount, 0)
495
+ )) AS media_list
496
+
497
+ -- Null-safe array
498
+ COALESCE(
499
+ json_agg(obj) FILTER (WHERE obj IS NOT NULL),
500
+ '[]'::json
501
+ ) AS items
502
+ ```
503
+
504
+ ### Date Calculations
505
+
506
+ > ⚠️ DuraOne lưu ngày tháng dạng **varchar** (`'2024-01-15'` hoặc `'2024-01-15 10:30:00'`).
507
+ > Khi dùng date functions của PostgreSQL, cần cast sang `DATE` hoặc `TIMESTAMP` trước.
508
+
509
+ ```sql
510
+ -- Lưu ý: cast varchar → DATE trước khi dùng date functions
511
+ -- age()
512
+ EXTRACT(YEAR FROM age(end_date::DATE, start_date::DATE)) AS years
513
+ EXTRACT(MONTH FROM age(end_date::DATE, start_date::DATE)) AS months
514
+
515
+ -- Date truncation
516
+ DATE_TRUNC('month', created_at::TIMESTAMP) AS month_start
517
+
518
+ -- Date comparison — cast cả 2 vế
519
+ created_at::DATE BETWEEN _from_date::DATE AND _to_date::DATE
520
+
521
+ -- Hoặc dùng SUBSTRING (không cần cast — đơn giản hơn khi chỉ so sánh YYYY-MM-DD)
522
+ SUBSTRING(created_at, 1, 10) BETWEEN _from_date AND _to_date
523
+ ```
524
+
525
+ ### Conditional Aggregation
526
+ ```sql
527
+ -- Sum with filter
528
+ SUM(amount) FILTER (WHERE status = 'approved') AS approved_amount
529
+ COUNT(*) FILTER (WHERE is_active = TRUE) AS active_count
530
+ ```
531
+
532
+ ### CTEs (Common Table Expressions)
533
+ ```sql
534
+ WITH monthly_data AS (
535
+ SELECT
536
+ DATE_TRUNC('month', created_at) AS month,
537
+ SUM(amount) AS total
538
+ FROM qas.agreement
539
+ WHERE is_deleted = FALSE
540
+ GROUP BY 1
541
+ ),
542
+ cumulative AS (
543
+ SELECT
544
+ month,
545
+ total,
546
+ SUM(total) OVER (ORDER BY month) AS running_total
547
+ FROM monthly_data
548
+ )
549
+ SELECT * FROM cumulative ORDER BY month;
550
+ ```
551
+
552
+ ### Window Functions
553
+ ```sql
554
+ -- Rank/Row Number
555
+ ROW_NUMBER() OVER (PARTITION BY id_branch ORDER BY created_at DESC) AS row_num
556
+ RANK() OVER (ORDER BY amount DESC) AS rank
557
+
558
+ -- Running totals
559
+ SUM(amount) OVER (ORDER BY created_at) AS running_total
560
+ LAG(amount, 1) OVER (ORDER BY created_at) AS prev_amount
561
+ ```
562
+
563
+ ### String Operations
564
+ ```sql
565
+ -- Concat with null safety
566
+ COALESCE(first_name, '') || ' ' || COALESCE(last_name, '') AS full_name
567
+
568
+ -- Format number
569
+ TO_CHAR(amount, 'FM999,999,999.00') AS amount_formatted
570
+
571
+ -- String array
572
+ string_agg(tag_name, ', ' ORDER BY tag_name) AS tags
573
+ ```
574
+
575
+ ### Type Casting
576
+ ```sql
577
+ -- Numeric với precision
578
+ COALESCE(field, 0)::numeric(16, 2)
579
+
580
+ -- Date extraction
581
+ SUBSTRING(created_at::text, 1, 10) -- → 'YYYY-MM-DD'
582
+
583
+ -- Int
584
+ -- Numeric (KHÔNG dùng ::INT)
585
+ field::NUMERIC
586
+
587
+ -- Boolean
588
+ (status = 'active')::BOOLEAN AS is_active
589
+ ```
590
+
591
+ ---
592
+
593
+ ## 9. File Organization
594
+
595
+ ```
596
+ mainapp/SQL/duraone/
597
+ ├── qas/
598
+ │ ├── view/
599
+ │ │ ├── v_agreement.sql
600
+ │ │ ├── v_clearance_request.sql
601
+ │ │ └── v_[entity].sql
602
+ │ │
603
+ │ ├── function/
604
+ │ │ ├── fn_get_agreement.sql
605
+ │ │ ├── fn_get_review_list.sql
606
+ │ │ └── fn_[operation]_[entity].sql
607
+ │ │
608
+ │ ├── store/
609
+ │ │ ├── sp_generate_running_no.sql
610
+ │ │ ├── sp_after_approve.sql
611
+ │ │ └── sp_[action]_[entity].sql
612
+ │ │
613
+ │ └── [feature]/ # Feature-specific (linechat, clearance, etc.)
614
+ │ ├── view/
615
+ │ ├── function/
616
+ │ └── store/
617
+
618
+ └── prd/ # Mirrors qas — same files, schema = prd
619
+ ├── view/
620
+ ├── function/
621
+ └── store/
622
+ ```
623
+
624
+ **Cách chạy SQL khi deploy:**
625
+ ```bash
626
+ # QAS
627
+ psql $QAS_CONN -f mainapp/SQL/duraone/qas/view/v_agreement.sql
628
+
629
+ # PRD (thay qas. → prd. trong file hoặc chạy riêng)
630
+ psql $PRD_CONN -f mainapp/SQL/duraone/prd/view/v_agreement.sql
631
+ ```