@tailor-platform/erp-kit 0.1.1 → 0.2.0

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 (342) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +158 -62
  3. package/dist/cli.js +1010 -270
  4. package/package.json +11 -8
  5. package/schemas/module/command.yml +1 -0
  6. package/schemas/module/model.yml +14 -0
  7. package/schemas/module/query.yml +53 -0
  8. package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/SKILL.md +2 -2
  9. package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/SKILL.md +3 -3
  10. package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/SKILL.md +2 -2
  11. package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/SKILL.md +3 -3
  12. package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/SKILL.md +4 -4
  13. package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/SKILL.md +3 -3
  14. package/skills/{mock-scenario → erp-kit-mock-scenario}/SKILL.md +1 -1
  15. package/skills/{1-module-docs → erp-kit-module-1-docs}/SKILL.md +2 -2
  16. package/skills/{2-module-feature-breakdown → erp-kit-module-2-feature-breakdown}/SKILL.md +13 -9
  17. package/skills/erp-kit-module-2-feature-breakdown/references/naming.md +59 -0
  18. package/skills/{3-module-doc-review → erp-kit-module-3-doc-review}/SKILL.md +83 -25
  19. package/skills/erp-kit-module-4-tdd/SKILL.md +94 -0
  20. package/skills/erp-kit-module-4-tdd/references/cross-module-dependency.md +133 -0
  21. package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/db-relations.md +5 -1
  22. package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/exports.md +1 -1
  23. package/skills/erp-kit-module-4-tdd/references/generated-code.md +32 -0
  24. package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/SKILL.md +46 -44
  25. package/skills/erp-kit-module-5-impl-review/references/commands.md +62 -0
  26. package/skills/erp-kit-module-5-impl-review/references/errors.md +10 -0
  27. package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/references/testing.md +1 -1
  28. package/skills/erp-kit-module-shared/SKILL.md +16 -0
  29. package/skills/erp-kit-module-shared/references/commands.md +203 -0
  30. package/skills/erp-kit-module-shared/references/errors.md +35 -0
  31. package/skills/erp-kit-module-shared/references/queries.md +168 -0
  32. package/skills/erp-kit-module-shared/references/structure.md +36 -0
  33. package/skills/{3-module-doc-review → erp-kit-module-shared}/references/testing.md +4 -3
  34. package/skills/erp-kit-update/SKILL.md +64 -0
  35. package/src/cli.doc.test.ts +65 -0
  36. package/src/cli.ts +3 -117
  37. package/src/commands/app/index.ts +74 -0
  38. package/src/commands/check.test.ts +3 -2
  39. package/src/commands/check.ts +3 -2
  40. package/src/commands/index.ts +73 -0
  41. package/src/commands/init.test.ts +22 -5
  42. package/src/commands/init.ts +25 -16
  43. package/src/commands/license.ts +193 -0
  44. package/src/commands/mock/index.ts +2 -2
  45. package/src/commands/mock/start.ts +1 -1
  46. package/src/commands/mock/validate.test.ts +1 -1
  47. package/src/commands/module/generate.ts +35 -0
  48. package/src/commands/module/index.ts +87 -0
  49. package/src/commands/module/list.test.ts +57 -0
  50. package/src/commands/module/list.ts +64 -0
  51. package/src/commands/scaffold-templates.ts +65 -0
  52. package/src/commands/scaffold.test.ts +97 -2
  53. package/src/commands/scaffold.ts +24 -3
  54. package/src/commands/sync-check.test.ts +88 -1
  55. package/src/commands/sync-check.ts +41 -2
  56. package/src/generator/generate-code.test.ts +200 -0
  57. package/src/generator/generate-code.ts +260 -0
  58. package/src/generator/parse-command-doc.test.ts +159 -0
  59. package/src/generator/parse-command-doc.ts +116 -0
  60. package/src/integration.test.ts +6 -8
  61. package/src/module.ts +10 -9
  62. package/src/modules/item-management/README.md +38 -0
  63. package/src/modules/item-management/command/activateItem.generated.ts +6 -0
  64. package/src/modules/item-management/command/activateItem.test.ts +76 -0
  65. package/src/modules/item-management/command/activateItem.ts +42 -0
  66. package/src/modules/item-management/command/assignItemToTaxonomy.generated.ts +6 -0
  67. package/src/modules/item-management/command/assignItemToTaxonomy.test.ts +88 -0
  68. package/src/modules/item-management/command/assignItemToTaxonomy.ts +63 -0
  69. package/src/modules/item-management/command/createItem.generated.ts +6 -0
  70. package/src/modules/item-management/command/createItem.test.ts +152 -0
  71. package/src/modules/item-management/command/createItem.ts +72 -0
  72. package/src/modules/item-management/command/createTaxonomyNode.generated.ts +6 -0
  73. package/src/modules/item-management/command/createTaxonomyNode.test.ts +126 -0
  74. package/src/modules/item-management/command/createTaxonomyNode.ts +70 -0
  75. package/src/modules/item-management/command/deactivateItem.generated.ts +6 -0
  76. package/src/modules/item-management/command/deactivateItem.test.ts +76 -0
  77. package/src/modules/item-management/command/deactivateItem.ts +42 -0
  78. package/src/modules/item-management/command/deleteItem.generated.ts +6 -0
  79. package/src/modules/item-management/command/deleteItem.test.ts +61 -0
  80. package/src/modules/item-management/command/deleteItem.ts +38 -0
  81. package/src/modules/item-management/command/deleteTaxonomyNode.generated.ts +6 -0
  82. package/src/modules/item-management/command/deleteTaxonomyNode.test.ts +73 -0
  83. package/src/modules/item-management/command/deleteTaxonomyNode.ts +50 -0
  84. package/src/modules/item-management/command/moveTaxonomyNode.generated.ts +6 -0
  85. package/src/modules/item-management/command/moveTaxonomyNode.test.ts +136 -0
  86. package/src/modules/item-management/command/moveTaxonomyNode.ts +85 -0
  87. package/src/modules/item-management/command/reactivateItem.generated.ts +6 -0
  88. package/src/modules/item-management/command/reactivateItem.test.ts +76 -0
  89. package/src/modules/item-management/command/reactivateItem.ts +42 -0
  90. package/src/modules/item-management/command/removeItemFromTaxonomy.generated.ts +6 -0
  91. package/src/modules/item-management/command/removeItemFromTaxonomy.test.ts +43 -0
  92. package/src/modules/item-management/command/removeItemFromTaxonomy.ts +30 -0
  93. package/src/modules/item-management/command/updateItem.generated.ts +6 -0
  94. package/src/modules/item-management/command/updateItem.test.ts +178 -0
  95. package/src/modules/item-management/command/updateItem.ts +103 -0
  96. package/src/modules/item-management/command/updateTaxonomyNode.generated.ts +6 -0
  97. package/src/modules/item-management/command/updateTaxonomyNode.test.ts +88 -0
  98. package/src/modules/item-management/command/updateTaxonomyNode.ts +62 -0
  99. package/src/modules/item-management/db/item.ts +47 -0
  100. package/src/modules/item-management/db/itemTaxonomyAssignment.ts +49 -0
  101. package/src/modules/item-management/db/taxonomyNode.ts +34 -0
  102. package/src/modules/item-management/docs/commands/ActivateItem.md +32 -0
  103. package/src/modules/item-management/docs/commands/AssignItemToTaxonomy.md +38 -0
  104. package/src/modules/item-management/docs/commands/CreateItem.md +44 -0
  105. package/src/modules/item-management/docs/commands/CreateTaxonomyNode.md +44 -0
  106. package/src/modules/item-management/docs/commands/DeactivateItem.md +34 -0
  107. package/src/modules/item-management/docs/commands/DeleteItem.md +35 -0
  108. package/src/modules/item-management/docs/commands/DeleteTaxonomyNode.md +39 -0
  109. package/src/modules/item-management/docs/commands/MoveTaxonomyNode.md +45 -0
  110. package/src/modules/item-management/docs/commands/ReactivateItem.md +34 -0
  111. package/src/modules/item-management/docs/commands/RemoveItemFromTaxonomy.md +30 -0
  112. package/src/modules/item-management/docs/commands/UpdateItem.md +55 -0
  113. package/src/modules/item-management/docs/commands/UpdateTaxonomyNode.md +36 -0
  114. package/src/modules/item-management/docs/features/item-lifecycle.md +60 -0
  115. package/src/modules/item-management/docs/features/item-taxonomy.md +65 -0
  116. package/src/modules/item-management/docs/models/ItemTaxonomyAssignment.md +36 -0
  117. package/src/modules/item-management/docs/models/TaxonomyNode.md +47 -0
  118. package/src/modules/item-management/docs/models/item.md +59 -0
  119. package/src/modules/item-management/docs/queries/CalculateNodeDepth.md +36 -0
  120. package/src/modules/item-management/docs/queries/CalculateSubtreeDepth.md +40 -0
  121. package/src/modules/item-management/docs/queries/DetectCircularReference.md +41 -0
  122. package/src/modules/item-management/docs/queries/GetItem.md +38 -0
  123. package/src/modules/item-management/docs/queries/GetItemTaxonomyAssignment.md +29 -0
  124. package/src/modules/item-management/docs/queries/GetTaxonomyNode.md +35 -0
  125. package/src/modules/item-management/docs/queries/GetTaxonomyNodeAssignments.md +29 -0
  126. package/src/modules/item-management/docs/queries/GetTaxonomyNodeChildren.md +29 -0
  127. package/src/modules/item-management/generated/enums.ts +9 -0
  128. package/src/modules/item-management/generated/kysely-tailordb.ts +62 -0
  129. package/src/modules/item-management/index.ts +53 -0
  130. package/src/modules/item-management/lib/_db_deps.ts +13 -0
  131. package/src/modules/item-management/lib/errors.generated.ts +117 -0
  132. package/src/modules/item-management/lib/permissions.generated.ts +17 -0
  133. package/src/modules/item-management/lib/types.ts +19 -0
  134. package/src/modules/item-management/module.ts +97 -0
  135. package/src/modules/item-management/query/calculateNodeDepth.generated.ts +5 -0
  136. package/src/modules/item-management/query/calculateNodeDepth.test.ts +56 -0
  137. package/src/modules/item-management/query/calculateNodeDepth.ts +28 -0
  138. package/src/modules/item-management/query/calculateSubtreeDepth.generated.ts +5 -0
  139. package/src/modules/item-management/query/calculateSubtreeDepth.test.ts +75 -0
  140. package/src/modules/item-management/query/calculateSubtreeDepth.ts +29 -0
  141. package/src/modules/item-management/query/detectCircularReference.generated.ts +5 -0
  142. package/src/modules/item-management/query/detectCircularReference.test.ts +61 -0
  143. package/src/modules/item-management/query/detectCircularReference.ts +32 -0
  144. package/src/modules/item-management/query/getItem.generated.ts +5 -0
  145. package/src/modules/item-management/query/getItem.test.ts +67 -0
  146. package/src/modules/item-management/query/getItem.ts +20 -0
  147. package/src/modules/item-management/query/getItemTaxonomyAssignment.generated.ts +5 -0
  148. package/src/modules/item-management/query/getItemTaxonomyAssignment.test.ts +25 -0
  149. package/src/modules/item-management/query/getItemTaxonomyAssignment.ts +18 -0
  150. package/src/modules/item-management/query/getTaxonomyNode.generated.ts +5 -0
  151. package/src/modules/item-management/query/getTaxonomyNode.test.ts +47 -0
  152. package/src/modules/item-management/query/getTaxonomyNode.ts +18 -0
  153. package/src/modules/item-management/query/getTaxonomyNodeAssignments.generated.ts +5 -0
  154. package/src/modules/item-management/query/getTaxonomyNodeAssignments.test.ts +25 -0
  155. package/src/modules/item-management/query/getTaxonomyNodeAssignments.ts +16 -0
  156. package/src/modules/item-management/query/getTaxonomyNodeChildren.generated.ts +5 -0
  157. package/src/modules/item-management/query/getTaxonomyNodeChildren.test.ts +34 -0
  158. package/src/modules/item-management/query/getTaxonomyNodeChildren.ts +16 -0
  159. package/src/modules/item-management/tailor.config.ts +11 -0
  160. package/src/modules/item-management/testing/fixtures.ts +81 -0
  161. package/src/modules/primitives/command/activateCategory.generated.ts +6 -0
  162. package/src/modules/primitives/command/activateCategory.test.ts +11 -29
  163. package/src/modules/primitives/command/activateCategory.ts +27 -34
  164. package/src/modules/primitives/command/activateCurrency.generated.ts +6 -0
  165. package/src/modules/primitives/command/activateCurrency.test.ts +11 -29
  166. package/src/modules/primitives/command/activateCurrency.ts +27 -34
  167. package/src/modules/primitives/command/activateUnit.generated.ts +6 -0
  168. package/src/modules/primitives/command/activateUnit.test.ts +11 -15
  169. package/src/modules/primitives/command/activateUnit.ts +27 -34
  170. package/src/modules/primitives/command/createCategory.generated.ts +6 -0
  171. package/src/modules/primitives/command/createCategory.test.ts +27 -39
  172. package/src/modules/primitives/command/createCategory.ts +53 -62
  173. package/src/modules/primitives/command/createCurrency.generated.ts +6 -0
  174. package/src/modules/primitives/command/createCurrency.test.ts +78 -71
  175. package/src/modules/primitives/command/createCurrency.ts +43 -48
  176. package/src/modules/primitives/command/createExchangeRate.generated.ts +6 -0
  177. package/src/modules/primitives/command/createExchangeRate.test.ts +101 -100
  178. package/src/modules/primitives/command/createExchangeRate.ts +50 -59
  179. package/src/modules/primitives/command/createUnit.generated.ts +6 -0
  180. package/src/modules/primitives/command/createUnit.test.ts +92 -95
  181. package/src/modules/primitives/command/createUnit.ts +54 -57
  182. package/src/modules/primitives/command/deactivateCategory.generated.ts +6 -0
  183. package/src/modules/primitives/command/deactivateCategory.test.ts +27 -28
  184. package/src/modules/primitives/command/deactivateCategory.ts +43 -50
  185. package/src/modules/primitives/command/deactivateCurrency.generated.ts +6 -0
  186. package/src/modules/primitives/command/deactivateCurrency.test.ts +23 -38
  187. package/src/modules/primitives/command/deactivateCurrency.ts +31 -38
  188. package/src/modules/primitives/command/deactivateUnit.generated.ts +6 -0
  189. package/src/modules/primitives/command/deactivateUnit.test.ts +27 -23
  190. package/src/modules/primitives/command/deactivateUnit.ts +39 -49
  191. package/src/modules/primitives/command/setBaseCurrency.generated.ts +6 -0
  192. package/src/modules/primitives/command/setBaseCurrency.test.ts +40 -33
  193. package/src/modules/primitives/command/setBaseCurrency.ts +43 -50
  194. package/src/modules/primitives/command/setReferenceUnit.generated.ts +6 -0
  195. package/src/modules/primitives/command/setReferenceUnit.test.ts +39 -35
  196. package/src/modules/primitives/command/setReferenceUnit.ts +46 -59
  197. package/src/modules/primitives/db/unit.ts +13 -3
  198. package/src/modules/primitives/docs/commands/ActivateCategory.md +1 -2
  199. package/src/modules/primitives/docs/commands/ActivateCurrency.md +1 -2
  200. package/src/modules/primitives/docs/commands/ActivateUnit.md +1 -2
  201. package/src/modules/primitives/docs/commands/CreateCategory.md +1 -4
  202. package/src/modules/primitives/docs/commands/CreateCurrency.md +3 -4
  203. package/src/modules/primitives/docs/commands/CreateExchangeRate.md +4 -5
  204. package/src/modules/primitives/docs/commands/CreateUnit.md +5 -5
  205. package/src/modules/primitives/docs/commands/DeactivateCategory.md +2 -3
  206. package/src/modules/primitives/docs/commands/DeactivateCurrency.md +2 -3
  207. package/src/modules/primitives/docs/commands/DeactivateUnit.md +2 -3
  208. package/src/modules/primitives/docs/commands/SetBaseCurrency.md +2 -3
  209. package/src/modules/primitives/docs/commands/SetReferenceUnit.md +2 -3
  210. package/src/modules/primitives/docs/models/Currency.md +4 -0
  211. package/src/modules/primitives/docs/models/ExchangeRate.md +4 -1
  212. package/src/modules/primitives/docs/models/Unit.md +4 -1
  213. package/src/modules/primitives/docs/models/UoMCategory.md +2 -0
  214. package/src/modules/primitives/docs/{commands → queries}/ConvertAmount.md +3 -5
  215. package/src/modules/primitives/docs/{commands → queries}/ConvertQuantity.md +3 -5
  216. package/src/modules/primitives/docs/queries/GetBaseCurrency.md +32 -0
  217. package/src/modules/primitives/docs/queries/GetCurrency.md +36 -0
  218. package/src/modules/primitives/docs/queries/GetUnit.md +36 -0
  219. package/src/modules/primitives/docs/queries/GetUoMCategory.md +36 -0
  220. package/src/modules/primitives/docs/queries/ListUnitsByCategory.md +26 -0
  221. package/src/modules/primitives/generated/kysely-tailordb.ts +24 -45
  222. package/src/modules/primitives/index.ts +17 -6
  223. package/src/modules/primitives/lib/errors.generated.ts +112 -0
  224. package/src/modules/primitives/{permissions.ts → lib/permissions.generated.ts} +9 -10
  225. package/src/modules/primitives/module.ts +39 -27
  226. package/src/modules/primitives/query/convertAmount.generated.ts +5 -0
  227. package/src/modules/primitives/{command → query}/convertAmount.test.ts +4 -21
  228. package/src/modules/primitives/query/convertAmount.ts +121 -0
  229. package/src/modules/primitives/query/convertQuantity.generated.ts +5 -0
  230. package/src/modules/primitives/{command → query}/convertQuantity.test.ts +8 -15
  231. package/src/modules/primitives/query/convertQuantity.ts +63 -0
  232. package/src/modules/primitives/query/getBaseCurrency.generated.ts +5 -0
  233. package/src/modules/primitives/query/getBaseCurrency.test.ts +28 -0
  234. package/src/modules/primitives/query/getBaseCurrency.ts +16 -0
  235. package/src/modules/primitives/query/getCurrency.generated.ts +5 -0
  236. package/src/modules/primitives/query/getCurrency.test.ts +47 -0
  237. package/src/modules/primitives/query/getCurrency.ts +18 -0
  238. package/src/modules/primitives/query/getUnit.generated.ts +5 -0
  239. package/src/modules/primitives/query/getUnit.test.ts +47 -0
  240. package/src/modules/primitives/query/getUnit.ts +18 -0
  241. package/src/modules/primitives/query/getUoMCategory.generated.ts +5 -0
  242. package/src/modules/primitives/query/getUoMCategory.test.ts +47 -0
  243. package/src/modules/primitives/query/getUoMCategory.ts +18 -0
  244. package/src/modules/primitives/query/listUnitsByCategory.generated.ts +5 -0
  245. package/src/modules/primitives/query/listUnitsByCategory.ts +16 -0
  246. package/src/modules/primitives/tailor.config.ts +3 -3
  247. package/src/modules/shared/defineCommand.test.ts +23 -10
  248. package/src/modules/shared/defineCommand.ts +23 -10
  249. package/src/modules/shared/defineQuery.test.ts +28 -0
  250. package/src/modules/shared/defineQuery.ts +16 -0
  251. package/src/modules/shared/internal.ts +3 -1
  252. package/src/modules/shared/requirePermission.test.ts +22 -21
  253. package/src/modules/shared/requirePermission.ts +8 -2
  254. package/src/modules/shared/result.ts +12 -0
  255. package/src/modules/shared/types.ts +8 -0
  256. package/src/modules/testing/index.ts +36 -11
  257. package/src/modules/user-management/command/activateUser.generated.ts +6 -0
  258. package/src/modules/user-management/command/activateUser.test.ts +27 -27
  259. package/src/modules/user-management/command/activateUser.ts +40 -48
  260. package/src/modules/user-management/command/assignPermissionToRole.generated.ts +6 -0
  261. package/src/modules/user-management/command/assignPermissionToRole.test.ts +42 -43
  262. package/src/modules/user-management/command/assignPermissionToRole.ts +59 -62
  263. package/src/modules/user-management/command/assignRoleToUser.generated.ts +6 -0
  264. package/src/modules/user-management/command/assignRoleToUser.test.ts +70 -63
  265. package/src/modules/user-management/command/assignRoleToUser.ts +63 -66
  266. package/src/modules/user-management/command/createPermission.generated.ts +6 -0
  267. package/src/modules/user-management/command/createPermission.test.ts +45 -38
  268. package/src/modules/user-management/command/createPermission.ts +42 -46
  269. package/src/modules/user-management/command/createRole.generated.ts +6 -0
  270. package/src/modules/user-management/command/createRole.test.ts +30 -29
  271. package/src/modules/user-management/command/createRole.ts +33 -33
  272. package/src/modules/user-management/command/createUser.generated.ts +6 -0
  273. package/src/modules/user-management/command/createUser.test.ts +64 -42
  274. package/src/modules/user-management/command/createUser.ts +54 -56
  275. package/src/modules/user-management/command/deactivateUser.generated.ts +6 -0
  276. package/src/modules/user-management/command/deactivateUser.test.ts +27 -27
  277. package/src/modules/user-management/command/deactivateUser.ts +40 -48
  278. package/src/modules/user-management/command/logAuditEvent.generated.ts +6 -0
  279. package/src/modules/user-management/command/logAuditEvent.test.ts +50 -42
  280. package/src/modules/user-management/command/logAuditEvent.ts +25 -28
  281. package/src/modules/user-management/command/reactivateUser.generated.ts +6 -0
  282. package/src/modules/user-management/command/reactivateUser.test.ts +31 -27
  283. package/src/modules/user-management/command/reactivateUser.ts +40 -48
  284. package/src/modules/user-management/command/revokePermissionFromRole.generated.ts +6 -0
  285. package/src/modules/user-management/command/revokePermissionFromRole.test.ts +52 -51
  286. package/src/modules/user-management/command/revokePermissionFromRole.ts +60 -57
  287. package/src/modules/user-management/command/revokeRoleFromUser.generated.ts +6 -0
  288. package/src/modules/user-management/command/revokeRoleFromUser.test.ts +53 -48
  289. package/src/modules/user-management/command/revokeRoleFromUser.ts +58 -57
  290. package/src/modules/user-management/docs/commands/CreatePermission.md +2 -2
  291. package/src/modules/user-management/docs/commands/CreateRole.md +1 -1
  292. package/src/modules/user-management/docs/models/AuditEvent.md +2 -0
  293. package/src/modules/user-management/docs/models/Permission.md +2 -0
  294. package/src/modules/user-management/docs/models/Role.md +2 -0
  295. package/src/modules/user-management/docs/models/RolePermission.md +2 -0
  296. package/src/modules/user-management/docs/models/User.md +2 -0
  297. package/src/modules/user-management/docs/models/UserRole.md +2 -0
  298. package/src/modules/user-management/generated/enums.ts +11 -11
  299. package/src/modules/user-management/generated/kysely-tailordb.ts +27 -56
  300. package/src/modules/user-management/index.ts +2 -2
  301. package/src/modules/user-management/lib/errors.generated.ts +67 -0
  302. package/src/modules/user-management/{permissions.ts → lib/permissions.generated.ts} +8 -7
  303. package/src/modules/user-management/module.ts +22 -22
  304. package/src/modules/user-management/tailor.config.ts +3 -3
  305. package/src/schemas.ts +2 -1
  306. package/skills/1-module-docs/references/structure.md +0 -22
  307. package/skills/2-module-feature-breakdown/references/commands.md +0 -48
  308. package/skills/2-module-feature-breakdown/references/structure.md +0 -22
  309. package/skills/3-module-doc-review/references/commands.md +0 -54
  310. package/skills/3-module-doc-review/references/models.md +0 -29
  311. package/skills/4-module-tdd-implementation/SKILL.md +0 -74
  312. package/skills/4-module-tdd-implementation/references/commands.md +0 -45
  313. package/skills/4-module-tdd-implementation/references/errors.md +0 -7
  314. package/skills/4-module-tdd-implementation/references/models.md +0 -30
  315. package/skills/4-module-tdd-implementation/references/structure.md +0 -22
  316. package/skills/4-module-tdd-implementation/references/testing.md +0 -37
  317. package/skills/5-module-implementation-review/references/commands.md +0 -45
  318. package/skills/5-module-implementation-review/references/errors.md +0 -7
  319. package/skills/5-module-implementation-review/references/exports.md +0 -8
  320. package/skills/5-module-implementation-review/references/models.md +0 -30
  321. package/src/modules/primitives/command/convertAmount.ts +0 -126
  322. package/src/modules/primitives/command/convertQuantity.ts +0 -73
  323. package/src/modules/primitives/lib/errors.ts +0 -138
  324. package/src/modules/user-management/lib/errors.ts +0 -81
  325. /package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/references/structure.md +0 -0
  326. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-detailview.md +0 -0
  327. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-form.md +0 -0
  328. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-listview.md +0 -0
  329. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/structure.md +0 -0
  330. /package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/references/structure.md +0 -0
  331. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/component.md +0 -0
  332. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-detailview.md +0 -0
  333. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-form.md +0 -0
  334. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-listview.md +0 -0
  335. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/structure.md +0 -0
  336. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/component.md +0 -0
  337. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-detailview.md +0 -0
  338. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-form.md +0 -0
  339. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-listview.md +0 -0
  340. /package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/references/auth.md +0 -0
  341. /package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/references/structure.md +0 -0
  342. /package/skills/{2-module-feature-breakdown → erp-kit-module-4-tdd}/references/models.md +0 -0
package/dist/cli.js CHANGED
@@ -1,30 +1,310 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
+ import { runMain } from "politty";
5
+
6
+ // src/commands/index.ts
7
+ import { z as z5 } from "zod";
8
+ import { defineCommand as defineCommand5, arg as arg5 } from "politty";
9
+
10
+ // src/commands/init.ts
11
+ import fs from "fs";
12
+ import path2 from "path";
13
+ import chalk from "chalk";
14
+
15
+ // src/util.ts
16
+ import path from "path";
17
+ var PACKAGE_ROOT = path.resolve(import.meta.dirname, "..");
18
+
19
+ // src/commands/init.ts
20
+ var SKILLS_SRC = path2.join(PACKAGE_ROOT, "skills");
21
+ function discoverFrameworkSkills() {
22
+ if (!fs.existsSync(SKILLS_SRC)) return [];
23
+ return fs.readdirSync(SKILLS_SRC, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("erp-kit-")).map((entry) => entry.name);
24
+ }
25
+ function copyDirectoryRecursive(srcDir, destDir, force) {
26
+ let copied = 0;
27
+ let skipped = 0;
28
+ for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
29
+ const srcPath = path2.join(srcDir, entry.name);
30
+ const destPath = path2.join(destDir, entry.name);
31
+ if (entry.isDirectory()) {
32
+ const sub = copyDirectoryRecursive(srcPath, destPath, force);
33
+ copied += sub.copied;
34
+ skipped += sub.skipped;
35
+ } else {
36
+ if (!force && fs.existsSync(destPath)) {
37
+ skipped++;
38
+ continue;
39
+ }
40
+ fs.mkdirSync(destDir, { recursive: true });
41
+ fs.copyFileSync(srcPath, destPath);
42
+ copied++;
43
+ }
44
+ }
45
+ return { copied, skipped };
46
+ }
47
+ function runInit(cwd5, force) {
48
+ console.log(chalk.bold("erp-kit init\n"));
49
+ const skillsDest = path2.join(cwd5, ".agents", "skills");
50
+ if (force && fs.existsSync(skillsDest)) {
51
+ let removedCount = 0;
52
+ for (const entry of fs.readdirSync(skillsDest)) {
53
+ if (entry.startsWith("erp-kit-")) {
54
+ fs.rmSync(path2.join(skillsDest, entry), { recursive: true, force: true });
55
+ removedCount++;
56
+ }
57
+ }
58
+ if (removedCount > 0) {
59
+ console.log(chalk.green(` Removed ${removedCount} existing erp-kit-* skills`));
60
+ }
61
+ }
62
+ let copiedCount = 0;
63
+ let skippedCount = 0;
64
+ const frameworkSkills = discoverFrameworkSkills();
65
+ for (const skill of frameworkSkills) {
66
+ const srcSkillDir = path2.join(SKILLS_SRC, skill);
67
+ if (!fs.existsSync(srcSkillDir)) continue;
68
+ const destDir = path2.join(skillsDest, skill);
69
+ const result = copyDirectoryRecursive(srcSkillDir, destDir, force);
70
+ copiedCount += result.copied;
71
+ if (result.skipped > 0) {
72
+ console.log(chalk.yellow(` Skipped ${skill}/ (${result.skipped} existing files)`));
73
+ skippedCount += result.skipped;
74
+ }
75
+ }
76
+ console.log(chalk.green(` Copied ${copiedCount} skill files to .agents/skills/`));
77
+ if (skippedCount > 0) {
78
+ console.log(
79
+ chalk.yellow(` Skipped ${skippedCount} existing files (use --force to overwrite)`)
80
+ );
81
+ }
82
+ const claudeSkills = path2.join(cwd5, ".claude", "skills");
83
+ const relTarget = path2.relative(path2.dirname(claudeSkills), skillsDest);
84
+ const claudeSkillsExists = (() => {
85
+ try {
86
+ fs.lstatSync(claudeSkills);
87
+ return true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ })();
92
+ if (claudeSkillsExists) {
93
+ const stat2 = fs.lstatSync(claudeSkills);
94
+ if (stat2.isSymbolicLink()) {
95
+ const current = fs.readlinkSync(claudeSkills);
96
+ if (current === relTarget) {
97
+ console.log(chalk.green(" .claude/skills -> .agents/skills/ (already linked)"));
98
+ } else if (force) {
99
+ fs.unlinkSync(claudeSkills);
100
+ fs.symlinkSync(relTarget, claudeSkills);
101
+ console.log(chalk.green(" .claude/skills -> .agents/skills/ (relinked)"));
102
+ } else {
103
+ console.log(
104
+ chalk.yellow(` Skipped .claude/skills (symlink exists -> ${current}, use --force)`)
105
+ );
106
+ }
107
+ } else {
108
+ console.log(chalk.yellow(" Skipped .claude/skills (directory exists, not a symlink)"));
109
+ }
110
+ } else {
111
+ fs.mkdirSync(path2.dirname(claudeSkills), { recursive: true });
112
+ fs.symlinkSync(relTarget, claudeSkills);
113
+ console.log(chalk.green(" .claude/skills -> .agents/skills/ (linked)"));
114
+ }
115
+ console.log(chalk.bold.green("\nDone! Run `erp-kit check` to validate your docs."));
116
+ return 0;
117
+ }
118
+
119
+ // src/commands/license.ts
120
+ import fs2 from "fs";
121
+ import { execSync } from "child_process";
122
+ var licenseGroups = {
123
+ // https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L225
124
+ reciprocal: [
125
+ "APSL-1.0",
126
+ "APSL-1.1",
127
+ "APSL-1.2",
128
+ "APSL-2.0",
129
+ "CDDL-1.0",
130
+ "CDDL-1.1",
131
+ "CPL-1.0",
132
+ "EPL-1.0",
133
+ "EPL-2.0",
134
+ "FreeImage",
135
+ "IPL-1.0",
136
+ "MPL-1.0",
137
+ "MPL-1.1",
138
+ "MPL-2.0",
139
+ "Ruby"
140
+ ],
141
+ // https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L249
142
+ notice: [
143
+ "AFL-1.1",
144
+ "AFL-1.2",
145
+ "AFL-2.0",
146
+ "AFL-2.1",
147
+ "AFL-3.0",
148
+ "Apache-1.0",
149
+ "Apache-1.1",
150
+ "Apache-2.0",
151
+ "Artistic-1.0-cl8",
152
+ "Artistic-1.0-Perl",
153
+ "Artistic-1.0",
154
+ "Artistic-2.0",
155
+ "BSL-1.0",
156
+ "BSD-2-Clause-FreeBSD",
157
+ "BSD-2-Clause-NetBSD",
158
+ "BSD-2-Clause",
159
+ "BSD-3-Clause-Attribution",
160
+ "BSD-3-Clause-Clear",
161
+ "BSD-3-Clause-LBNL",
162
+ "BSD-3-Clause",
163
+ "BSD-4-Clause",
164
+ "BSD-4-Clause-UC",
165
+ "BSD-Protection",
166
+ "CC-BY-1.0",
167
+ "CC-BY-2.0",
168
+ "CC-BY-2.5",
169
+ "CC-BY-3.0",
170
+ "CC-BY-4.0",
171
+ "FTL",
172
+ "ISC",
173
+ "ImageMagick",
174
+ "Libpng",
175
+ "Lil-1.0",
176
+ "Linux-OpenIB",
177
+ "LPL-1.02",
178
+ "LPL-1.0",
179
+ "MS-PL",
180
+ "MIT",
181
+ "NCSA",
182
+ "OpenSSL",
183
+ "PHP-3.01",
184
+ "PHP-3.0",
185
+ "PIL",
186
+ "Python-2.0",
187
+ "Python-2.0-complete",
188
+ "PostgreSQL",
189
+ "SGI-B-1.0",
190
+ "SGI-B-1.1",
191
+ "SGI-B-2.0",
192
+ "Unicode-DFS-2015",
193
+ "Unicode-DFS-2016",
194
+ "Unicode-TOU",
195
+ "UPL-1.0",
196
+ "W3C-19980720",
197
+ "W3C-20150513",
198
+ "W3C",
199
+ "X11",
200
+ "Xnet",
201
+ "Zend-2.0",
202
+ "zlib-acknowledgement",
203
+ "Zlib",
204
+ "ZPL-1.1",
205
+ "ZPL-2.0",
206
+ "ZPL-2.1"
207
+ ],
208
+ // https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L324
209
+ unencumbered: ["CC0-1.0", "Unlicense", "0BSD"]
210
+ };
211
+ function buildAllowSet(config) {
212
+ const set = /* @__PURE__ */ new Set();
213
+ for (const group of config.groups) {
214
+ for (const license of licenseGroups[group]) {
215
+ set.add(license);
216
+ }
217
+ }
218
+ if (config.allow) {
219
+ for (const license of config.allow) {
220
+ set.add(license);
221
+ }
222
+ }
223
+ if (config.deny) {
224
+ for (const license of config.deny) {
225
+ set.delete(license);
226
+ }
227
+ }
228
+ return set;
229
+ }
230
+ function isLicenseAllowed(licenseString, allowSet) {
231
+ if (/\s+(?:OR|AND)\s+/i.test(licenseString)) {
232
+ const licenses = licenseString.replace(/[()]/g, "").trim().split(/\s+(?:OR|AND)\s+/i).map((l) => l.trim()).filter((l) => l.length > 0);
233
+ return licenses.every((l) => allowSet.has(l));
234
+ }
235
+ return allowSet.has(licenseString);
236
+ }
237
+ function runLicenseList() {
238
+ for (const [group, licenses] of Object.entries(licenseGroups)) {
239
+ console.log(`${group} (${licenses.length} licenses):`);
240
+ for (const license of licenses) {
241
+ console.log(` ${license}`);
242
+ }
243
+ console.log();
244
+ }
245
+ return 0;
246
+ }
247
+ function runLicenseCheck(configPath) {
248
+ const raw = fs2.readFileSync(configPath, "utf-8");
249
+ const config = JSON.parse(raw);
250
+ const validGroups = Object.keys(licenseGroups);
251
+ for (const group of config.groups) {
252
+ if (!validGroups.includes(group)) {
253
+ console.error(`Unknown license group: "${group}". Valid groups: ${validGroups.join(", ")}`);
254
+ return 2;
255
+ }
256
+ }
257
+ const allowSet = buildAllowSet(config);
258
+ console.log("Checking licenses...\n");
259
+ execSync("pnpm licenses list", { stdio: "inherit" });
260
+ const output = execSync("pnpm licenses list --json");
261
+ const licensesJson = JSON.parse(output.toString());
262
+ const violations = [];
263
+ for (const [license, packages] of Object.entries(licensesJson)) {
264
+ if (!isLicenseAllowed(license, allowSet)) {
265
+ for (const pkg of packages) {
266
+ violations.push({ package: pkg.name, license });
267
+ }
268
+ }
269
+ }
270
+ if (violations.length === 0) {
271
+ console.log("All licenses are allowed.");
272
+ return 0;
273
+ }
274
+ console.error("Found dependencies with disallowed licenses:\n");
275
+ for (const violation of violations) {
276
+ console.error(` - ${violation.package}`);
277
+ console.error(` License: ${violation.license}
278
+ `);
279
+ }
280
+ return 1;
281
+ }
282
+
283
+ // src/commands/module/index.ts
4
284
  import { z as z2 } from "zod";
5
- import { defineCommand as defineCommand2, runMain, arg as arg2 } from "politty";
285
+ import { defineCommand as defineCommand2, arg as arg2 } from "politty";
6
286
 
7
287
  // src/mdschema.ts
8
- import path from "path";
9
- import fs from "fs";
288
+ import path3 from "path";
289
+ import fs3 from "fs";
10
290
  import { execFile } from "child_process";
11
291
  import { createRequire } from "module";
12
292
  var require2 = createRequire(import.meta.url);
13
293
  function getMdschemaBin() {
14
294
  const pkgPath = require2.resolve("@jackchuka/mdschema/package.json");
15
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
295
+ const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
16
296
  const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.mdschema;
17
297
  if (!bin) {
18
298
  throw new Error("Could not resolve mdschema binary from package.json bin field");
19
299
  }
20
- return path.join(path.dirname(pkgPath), bin);
300
+ return path3.join(path3.dirname(pkgPath), bin);
21
301
  }
22
- function runMdschema(args, cwd2) {
302
+ function runMdschema(args, cwd5) {
23
303
  return new Promise((resolve4) => {
24
304
  execFile(
25
305
  getMdschemaBin(),
26
306
  args,
27
- { encoding: "utf-8", cwd: cwd2, timeout: 3e4 },
307
+ { encoding: "utf-8", cwd: cwd5, timeout: 3e4 },
28
308
  (error, stdout, stderr) => {
29
309
  if (error) {
30
310
  const execError = error;
@@ -42,27 +322,22 @@ function runMdschema(args, cwd2) {
42
322
  }
43
323
 
44
324
  // src/schemas.ts
45
- import path3 from "path";
46
-
47
- // src/util.ts
48
- import path2 from "path";
49
- var PACKAGE_ROOT = path2.resolve(import.meta.dirname, "..");
50
-
51
- // src/schemas.ts
52
- var SCHEMAS_ROOT = path3.join(PACKAGE_ROOT, "schemas");
325
+ import path4 from "path";
326
+ var SCHEMAS_ROOT = path4.join(PACKAGE_ROOT, "schemas");
53
327
  var MODULE_SCHEMAS = {
54
- module: path3.join(SCHEMAS_ROOT, "module", "module.yml"),
55
- command: path3.join(SCHEMAS_ROOT, "module", "command.yml"),
56
- model: path3.join(SCHEMAS_ROOT, "module", "model.yml"),
57
- feature: path3.join(SCHEMAS_ROOT, "module", "feature.yml")
328
+ module: path4.join(SCHEMAS_ROOT, "module", "module.yml"),
329
+ command: path4.join(SCHEMAS_ROOT, "module", "command.yml"),
330
+ model: path4.join(SCHEMAS_ROOT, "module", "model.yml"),
331
+ feature: path4.join(SCHEMAS_ROOT, "module", "feature.yml"),
332
+ query: path4.join(SCHEMAS_ROOT, "module", "query.yml")
58
333
  };
59
334
  var APP_COMPOSE_SCHEMAS = {
60
- requirements: path3.join(SCHEMAS_ROOT, "app-compose", "requirements.yml"),
61
- actors: path3.join(SCHEMAS_ROOT, "app-compose", "actors.yml"),
62
- "business-flow": path3.join(SCHEMAS_ROOT, "app-compose", "business-flow.yml"),
63
- story: path3.join(SCHEMAS_ROOT, "app-compose", "story.yml"),
64
- screen: path3.join(SCHEMAS_ROOT, "app-compose", "screen.yml"),
65
- resolver: path3.join(SCHEMAS_ROOT, "app-compose", "resolver.yml")
335
+ requirements: path4.join(SCHEMAS_ROOT, "app-compose", "requirements.yml"),
336
+ actors: path4.join(SCHEMAS_ROOT, "app-compose", "actors.yml"),
337
+ "business-flow": path4.join(SCHEMAS_ROOT, "app-compose", "business-flow.yml"),
338
+ story: path4.join(SCHEMAS_ROOT, "app-compose", "story.yml"),
339
+ screen: path4.join(SCHEMAS_ROOT, "app-compose", "screen.yml"),
340
+ resolver: path4.join(SCHEMAS_ROOT, "app-compose", "resolver.yml")
66
341
  };
67
342
  var ALL_SCHEMAS = {
68
343
  ...MODULE_SCHEMAS,
@@ -78,6 +353,7 @@ function buildCheckTargets(config) {
78
353
  { glob: `${m}/[a-zA-Z]*/docs/features/*.md`, schemaKey: "feature" },
79
354
  { glob: `${m}/[a-zA-Z]*/docs/commands/*.md`, schemaKey: "command" },
80
355
  { glob: `${m}/[a-zA-Z]*/docs/models/*.md`, schemaKey: "model" },
356
+ { glob: `${m}/[a-zA-Z]*/docs/queries/*.md`, schemaKey: "query" },
81
357
  { glob: `${m}/[a-zA-Z]*/README.md`, schemaKey: "module" }
82
358
  );
83
359
  }
@@ -94,7 +370,7 @@ function buildCheckTargets(config) {
94
370
  }
95
371
  return targets;
96
372
  }
97
- async function runCheck(config, cwd2) {
373
+ async function runCheck(config, cwd5) {
98
374
  const targets = buildCheckTargets(config);
99
375
  const results = await Promise.all(
100
376
  targets.map(async (target) => {
@@ -105,7 +381,7 @@ async function runCheck(config, cwd2) {
105
381
  }
106
382
  const { exitCode, stdout, stderr } = await runMdschema(
107
383
  ["check", target.glob, "--schema", schemaPath],
108
- cwd2
384
+ cwd5
109
385
  );
110
386
  if (stdout.trim()) console.log(stdout);
111
387
  if (stderr.trim()) console.error(stderr);
@@ -117,22 +393,28 @@ async function runCheck(config, cwd2) {
117
393
  }
118
394
 
119
395
  // src/commands/sync-check.ts
120
- import path4 from "path";
396
+ import path5 from "path";
121
397
  import fg from "fast-glob";
122
- import chalk from "chalk";
398
+ import chalk2 from "chalk";
123
399
  function moduleCategories(root) {
124
400
  return [
125
401
  {
126
402
  name: "command",
127
403
  sourcePattern: `${root}/*/command/*.ts`,
128
404
  docPattern: `${root}/*/docs/commands/*.md`,
129
- exclusions: [/\.test\.ts$/]
405
+ exclusions: [/\.test\.ts$/, /\.generated\.ts$/]
130
406
  },
131
407
  {
132
408
  name: "model",
133
409
  sourcePattern: `${root}/*/db/*.ts`,
134
410
  docPattern: `${root}/*/docs/models/*.md`,
135
411
  exclusions: [/\.test\.ts$/, /^index\.ts$/]
412
+ },
413
+ {
414
+ name: "query",
415
+ sourcePattern: `${root}/*/query/*.ts`,
416
+ docPattern: `${root}/*/docs/queries/*.md`,
417
+ exclusions: [/\.test\.ts$/]
136
418
  }
137
419
  ];
138
420
  }
@@ -149,7 +431,7 @@ function appComposeCategories(root) {
149
431
  function shouldExclude(fileName, exclusions) {
150
432
  return exclusions.some((pattern) => pattern.test(fileName));
151
433
  }
152
- async function runSyncCheck(config, cwd2) {
434
+ async function runSyncCheck(config, cwd5) {
153
435
  const errors = [];
154
436
  let totalSources = 0;
155
437
  let totalDocs = 0;
@@ -161,18 +443,21 @@ async function runSyncCheck(config, cwd2) {
161
443
  allCategories.push(...appComposeCategories(config.appRoot));
162
444
  }
163
445
  for (const category of allCategories) {
164
- const sources = await fg(category.sourcePattern, { cwd: cwd2 });
165
- const docs = await fg(category.docPattern, { cwd: cwd2 });
446
+ const sources = await fg(category.sourcePattern, { cwd: cwd5 });
447
+ const docs = await fg(category.docPattern, { cwd: cwd5 });
166
448
  const sourceBasenames = /* @__PURE__ */ new Map();
167
449
  const docBasenames = /* @__PURE__ */ new Map();
168
450
  for (const sourcePath of sources) {
169
- const fileName = path4.basename(sourcePath);
451
+ const fileName = path5.basename(sourcePath);
170
452
  if (shouldExclude(fileName, category.exclusions)) continue;
171
- const basename2 = path4.basename(sourcePath, path4.extname(sourcePath));
453
+ let basename2 = path5.basename(sourcePath, path5.extname(sourcePath));
454
+ if (basename2.endsWith(".generated")) {
455
+ basename2 = basename2.slice(0, -".generated".length);
456
+ }
172
457
  sourceBasenames.set(basename2.toLowerCase(), sourcePath);
173
458
  }
174
459
  for (const docPath of docs) {
175
- const basename2 = path4.basename(docPath, path4.extname(docPath));
460
+ const basename2 = path5.basename(docPath, path5.extname(docPath));
176
461
  docBasenames.set(basename2.toLowerCase(), docPath);
177
462
  }
178
463
  for (const [basename2, sourcePath] of sourceBasenames) {
@@ -210,9 +495,9 @@ async function runSyncCheck(config, cwd2) {
210
495
  }
211
496
  function formatSyncCheckReport(result) {
212
497
  const lines = [];
213
- lines.push(chalk.bold("docs-sync-check: Checking source-documentation correspondence...\n"));
498
+ lines.push(chalk2.bold("docs-sync-check: Checking source-documentation correspondence...\n"));
214
499
  if (result.errors.length > 0) {
215
- lines.push(chalk.red.bold("Errors:\n"));
500
+ lines.push(chalk2.red.bold("Errors:\n"));
216
501
  const byCategory = /* @__PURE__ */ new Map();
217
502
  for (const error of result.errors) {
218
503
  const existing = byCategory.get(error.category) ?? [];
@@ -220,45 +505,105 @@ function formatSyncCheckReport(result) {
220
505
  byCategory.set(error.category, existing);
221
506
  }
222
507
  for (const [category, categoryErrors] of byCategory) {
223
- lines.push(chalk.cyan(` Category: ${category}
508
+ lines.push(chalk2.cyan(` Category: ${category}
224
509
  `));
225
510
  for (const error of categoryErrors) {
226
511
  if (error.type === "missing-doc") {
227
- lines.push(` ${chalk.red(error.sourcePath)}`);
228
- lines.push(` ${chalk.yellow("Missing documentation for:")} ${error.expectedBasename}`);
512
+ lines.push(` ${chalk2.red(error.sourcePath)}`);
513
+ lines.push(` ${chalk2.yellow("Missing documentation for:")} ${error.expectedBasename}`);
229
514
  } else {
230
- lines.push(` ${chalk.red(error.docPath)}`);
515
+ lines.push(` ${chalk2.red(error.docPath)}`);
231
516
  lines.push(
232
- ` ${chalk.yellow("Orphaned documentation:")} no source file for ${error.expectedBasename}`
517
+ ` ${chalk2.yellow("Orphaned documentation:")} no source file for ${error.expectedBasename}`
233
518
  );
234
519
  }
235
520
  lines.push("");
236
521
  }
237
522
  }
238
523
  } else {
239
- lines.push(chalk.green("All source files have corresponding documentation.\n"));
524
+ lines.push(chalk2.green("All source files have corresponding documentation.\n"));
240
525
  }
241
- lines.push(chalk.bold("Summary:"));
526
+ lines.push(chalk2.bold("Summary:"));
242
527
  lines.push(` Categories checked: ${result.summary.categoriesChecked}`);
243
528
  lines.push(
244
529
  ` Source files: ${result.summary.totalSources}, Doc files: ${result.summary.totalDocs}`
245
530
  );
246
531
  if (result.errors.length > 0) {
247
- lines.push(chalk.red(` Errors: ${result.errors.length}`));
532
+ lines.push(chalk2.red(` Errors: ${result.errors.length}`));
248
533
  lines.push("");
249
- lines.push(chalk.red.bold(`docs-sync-check failed with ${result.errors.length} error(s).`));
534
+ lines.push(chalk2.red.bold(`docs-sync-check failed with ${result.errors.length} error(s).`));
250
535
  } else {
251
- lines.push(chalk.green(" Errors: 0"));
536
+ lines.push(chalk2.green(" Errors: 0"));
252
537
  lines.push("");
253
- lines.push(chalk.green.bold("docs-sync-check passed."));
538
+ lines.push(chalk2.green.bold("docs-sync-check passed."));
254
539
  }
255
540
  return lines.join("\n");
256
541
  }
257
542
 
258
543
  // src/commands/scaffold.ts
259
- import path5 from "path";
260
- import fs2 from "fs";
261
- var MODULE_TYPES = ["module", "feature", "command", "model"];
544
+ import path6 from "path";
545
+ import fs4 from "fs";
546
+
547
+ // src/commands/scaffold-templates.ts
548
+ function getModuleSrcTemplates() {
549
+ return [
550
+ { type: "dir", path: "db" },
551
+ { type: "dir", path: "command" },
552
+ { type: "dir", path: "executor" },
553
+ { type: "dir", path: "generated" },
554
+ { type: "dir", path: "query" },
555
+ { type: "file", path: "module.ts", content: () => MODULE_TEMPLATE },
556
+ { type: "file", path: "index.ts", content: () => INDEX_TEMPLATE },
557
+ { type: "file", path: "permissions.ts", content: (n) => permissionsTemplate(n) },
558
+ { type: "file", path: "tailor.config.ts", content: (n) => tailorConfigTemplate(n) },
559
+ { type: "file", path: "lib/errors.ts", content: () => ERRORS_TEMPLATE },
560
+ { type: "file", path: "lib/types.ts", content: () => TYPES_TEMPLATE },
561
+ { type: "file", path: "testing/fixtures.ts", content: () => FIXTURES_TEMPLATE }
562
+ ];
563
+ }
564
+ var MODULE_TEMPLATE = `export const defineModule = () => {
565
+ return {
566
+ db: {},
567
+ commands: {},
568
+ queries: {},
569
+ };
570
+ };
571
+ `;
572
+ var INDEX_TEMPLATE = `export { defineModule } from "./module";
573
+ export { permissions, own, all } from "./permissions";
574
+ `;
575
+ var ERRORS_TEMPLATE = `import { createDomainError } from "../../shared/internal";
576
+ `;
577
+ var TYPES_TEMPLATE = `import type { InferSchema, Selectable, Insertable, Updateable } from "../../shared/internal";
578
+ import type { DB } from "../generated/kysely-tailordb";
579
+
580
+ export type Schema = InferSchema<DB>;
581
+ `;
582
+ var FIXTURES_TEMPLATE = `// Add test fixtures here
583
+ `;
584
+ function permissionsTemplate(moduleName) {
585
+ return `import { definePermissions } from "../shared/internal";
586
+
587
+ export const { permissions, own, all } = definePermissions("${moduleName}", [] as const);
588
+ `;
589
+ }
590
+ function tailorConfigTemplate(moduleName) {
591
+ return `import { defineConfig, defineGenerators } from "@tailor-platform/sdk";
592
+
593
+ export default defineConfig({
594
+ name: "${moduleName}",
595
+ db: { "main-db": { files: [\`./db/*.ts\`] } },
596
+ });
597
+
598
+ export const generators = defineGenerators(
599
+ ["@tailor-platform/kysely-type", { distPath: \`./generated/kysely-tailordb.ts\` }],
600
+ ["@tailor-platform/enum-constants", { distPath: "./generated/enums.ts" }],
601
+ );
602
+ `;
603
+ }
604
+
605
+ // src/commands/scaffold.ts
606
+ var MODULE_TYPES = ["module", "feature", "command", "model", "query"];
262
607
  var APP_TYPES = [
263
608
  "requirements",
264
609
  "actors",
@@ -271,7 +616,8 @@ var ALL_TYPES = [...MODULE_TYPES, ...APP_TYPES];
271
616
  var MODULE_DIR_MAP = {
272
617
  feature: "docs/features",
273
618
  command: "docs/commands",
274
- model: "docs/models"
619
+ model: "docs/models",
620
+ query: "docs/queries"
275
621
  };
276
622
  var APP_DIR_MAP = {
277
623
  actors: "docs/actors",
@@ -279,18 +625,15 @@ var APP_DIR_MAP = {
279
625
  screen: "docs/screen",
280
626
  resolver: "docs/resolver"
281
627
  };
282
- function isModuleType(type) {
283
- return MODULE_TYPES.includes(type);
284
- }
285
628
  function resolveScaffoldPath(type, parentName, name, root) {
286
629
  if (type === "module" || type === "requirements") {
287
- return path5.join(root, parentName, "README.md");
630
+ return path6.join(root, parentName, "README.md");
288
631
  }
289
632
  if (!name) {
290
633
  throw new Error(`Name is required for scaffold type "${type}"`);
291
634
  }
292
635
  if (type === "business-flow") {
293
- return path5.join(root, parentName, "docs/business-flow", name, "README.md");
636
+ return path6.join(root, parentName, "docs/business-flow", name, "README.md");
294
637
  }
295
638
  if (type === "story") {
296
639
  const parts = name.split("/");
@@ -299,20 +642,20 @@ function resolveScaffoldPath(type, parentName, name, root) {
299
642
  `Story name must be "<flow>/<story>" (e.g., "onboarding/admin--create-user")`
300
643
  );
301
644
  }
302
- return path5.join(root, parentName, "docs/business-flow", parts[0], "story", `${parts[1]}.md`);
645
+ return path6.join(root, parentName, "docs/business-flow", parts[0], "story", `${parts[1]}.md`);
303
646
  }
304
647
  if (MODULE_DIR_MAP[type]) {
305
- return path5.join(root, parentName, MODULE_DIR_MAP[type], `${name}.md`);
648
+ return path6.join(root, parentName, MODULE_DIR_MAP[type], `${name}.md`);
306
649
  }
307
650
  if (APP_DIR_MAP[type]) {
308
- return path5.join(root, parentName, APP_DIR_MAP[type], `${name}.md`);
651
+ return path6.join(root, parentName, APP_DIR_MAP[type], `${name}.md`);
309
652
  }
310
653
  throw new Error(`Unknown scaffold type: ${type}`);
311
654
  }
312
- async function runScaffold(type, parentName, name, root, cwd2) {
655
+ async function runScaffold(type, parentName, name, root, cwd5) {
313
656
  const outputPath = resolveScaffoldPath(type, parentName, name, root);
314
- const absoluteOutput = path5.resolve(cwd2, outputPath);
315
- if (fs2.existsSync(absoluteOutput)) {
657
+ const absoluteOutput = path6.resolve(cwd5, outputPath);
658
+ if (fs4.existsSync(absoluteOutput)) {
316
659
  console.error(`File already exists: ${outputPath}`);
317
660
  return 1;
318
661
  }
@@ -322,7 +665,7 @@ async function runScaffold(type, parentName, name, root, cwd2) {
322
665
  return 2;
323
666
  }
324
667
  try {
325
- fs2.mkdirSync(path5.dirname(absoluteOutput), { recursive: true });
668
+ fs4.mkdirSync(path6.dirname(absoluteOutput), { recursive: true });
326
669
  } catch (err) {
327
670
  console.error(
328
671
  `Failed to create directory: ${err instanceof Error ? err.message : String(err)}`
@@ -331,122 +674,562 @@ async function runScaffold(type, parentName, name, root, cwd2) {
331
674
  }
332
675
  const { exitCode, stdout, stderr } = await runMdschema(
333
676
  ["generate", "--schema", schemaPath, "--output", absoluteOutput],
334
- cwd2
677
+ cwd5
335
678
  );
336
679
  if (stdout.trim()) console.log(stdout);
337
680
  if (stderr.trim()) console.error(stderr);
681
+ if (exitCode !== 0) return exitCode;
682
+ if (type === "module") {
683
+ scaffoldModuleSrc(path6.dirname(absoluteOutput), parentName);
684
+ }
338
685
  return exitCode;
339
686
  }
340
-
341
- // src/commands/init.ts
342
- import fs3 from "fs";
343
- import path6 from "path";
344
- import chalk2 from "chalk";
345
- var SKILLS_SRC = path6.join(PACKAGE_ROOT, "skills");
346
- var FRAMEWORK_SKILLS = [
347
- "1-module-docs",
348
- "2-module-feature-breakdown",
349
- "3-module-doc-review",
350
- "4-module-tdd-implementation",
351
- "5-module-implementation-review",
352
- "app-compose-1-requirement-analysis",
353
- "app-compose-2-requirements-breakdown",
354
- "app-compose-3-doc-review",
355
- "app-compose-4-design-mock",
356
- "app-compose-5-design-mock-review",
357
- "app-compose-6-implementation-spec",
358
- "mock-scenario"
359
- ];
360
- function copyDirectoryRecursive(srcDir, destDir, force) {
361
- let copied = 0;
362
- let skipped = 0;
363
- for (const entry of fs3.readdirSync(srcDir, { withFileTypes: true })) {
364
- const srcPath = path6.join(srcDir, entry.name);
365
- const destPath = path6.join(destDir, entry.name);
366
- if (entry.isDirectory()) {
367
- const sub = copyDirectoryRecursive(srcPath, destPath, force);
368
- copied += sub.copied;
369
- skipped += sub.skipped;
687
+ function scaffoldModuleSrc(moduleDir, moduleName) {
688
+ for (const entry of getModuleSrcTemplates()) {
689
+ const fullPath = path6.join(moduleDir, entry.path);
690
+ if (entry.type === "dir") {
691
+ fs4.mkdirSync(fullPath, { recursive: true });
692
+ fs4.writeFileSync(path6.join(fullPath, ".gitkeep"), "");
370
693
  } else {
371
- if (!force && fs3.existsSync(destPath)) {
372
- skipped++;
694
+ fs4.mkdirSync(path6.dirname(fullPath), { recursive: true });
695
+ fs4.writeFileSync(fullPath, entry.content(moduleName));
696
+ }
697
+ }
698
+ }
699
+
700
+ // src/commands/module/list.ts
701
+ import { readdirSync, existsSync } from "fs";
702
+ import { join } from "path";
703
+ import chalk3 from "chalk";
704
+ var MODULES_DIR = join(PACKAGE_ROOT, "src", "modules");
705
+ var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["shared", "testing"]);
706
+ function countFiles(dir, pattern, exclusions) {
707
+ if (!existsSync(dir)) return 0;
708
+ return readdirSync(dir).filter((f) => pattern.test(f) && !exclusions.some((p) => p.test(f))).length;
709
+ }
710
+ function listModules() {
711
+ if (!existsSync(MODULES_DIR)) return [];
712
+ return readdirSync(MODULES_DIR, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DIRS.has(d.name)).map((d) => {
713
+ const modDir = join(MODULES_DIR, d.name);
714
+ return {
715
+ name: d.name,
716
+ commands: countFiles(join(modDir, "command"), /\.ts$/, [/\.test\.ts$/]),
717
+ models: countFiles(join(modDir, "db"), /\.ts$/, [/\.test\.ts$/, /^index\.ts$/]),
718
+ features: countFiles(join(modDir, "docs", "features"), /\.md$/, [])
719
+ };
720
+ }).sort((a, b) => a.name.localeCompare(b.name));
721
+ }
722
+ function formatModuleList(modules) {
723
+ if (modules.length === 0) return "No modules found.";
724
+ const lines = [];
725
+ lines.push(chalk3.bold("Modules:\n"));
726
+ const nameWidth = Math.max(...modules.map((m) => m.name.length), 4);
727
+ for (const mod of modules) {
728
+ const counts = [
729
+ `${mod.commands} commands`,
730
+ `${mod.models} models`,
731
+ `${mod.features} features`
732
+ ].join(", ");
733
+ lines.push(` ${mod.name.padEnd(nameWidth)} ${counts}`);
734
+ }
735
+ lines.push("");
736
+ lines.push(`${modules.length} modules`);
737
+ return lines.join("\n");
738
+ }
739
+ function runModuleList() {
740
+ const modules = listModules();
741
+ console.log(formatModuleList(modules));
742
+ return 0;
743
+ }
744
+
745
+ // src/commands/module/generate.ts
746
+ import path8 from "path";
747
+ import { defineCommand, arg } from "politty";
748
+ import { z } from "zod";
749
+
750
+ // src/generator/generate-code.ts
751
+ import fs5 from "fs";
752
+ import path7 from "path";
753
+
754
+ // src/generator/parse-command-doc.ts
755
+ import { fromMarkdown } from "mdast-util-from-markdown";
756
+ import { toString } from "mdast-util-to-string";
757
+ function parseCommandDoc(fileName, markdown) {
758
+ const commandName = fileName.charAt(0).toLowerCase() + fileName.slice(1);
759
+ const tree = fromMarkdown(markdown);
760
+ return {
761
+ commandName,
762
+ errors: parseErrorScenarios(tree),
763
+ externalDependencies: parseExternalDependencies(tree)
764
+ };
765
+ }
766
+ function errorCodeToClassName(code) {
767
+ const pascal = code.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
768
+ return pascal + "Error";
769
+ }
770
+ function isHeading(node) {
771
+ return node.type === "heading";
772
+ }
773
+ function isList(node) {
774
+ return node.type === "list";
775
+ }
776
+ function getNodesUnderHeading(tree, headingText) {
777
+ const nodes = [];
778
+ let collecting = false;
779
+ for (const node of tree.children) {
780
+ if (isHeading(node)) {
781
+ if (collecting) break;
782
+ if (node.depth === 2 && toString(node) === headingText) {
783
+ collecting = true;
373
784
  continue;
374
785
  }
375
- fs3.mkdirSync(destDir, { recursive: true });
376
- fs3.copyFileSync(srcPath, destPath);
377
- copied++;
786
+ }
787
+ if (collecting) {
788
+ nodes.push(node);
378
789
  }
379
790
  }
380
- return { copied, skipped };
791
+ return nodes;
381
792
  }
382
- function runInit(cwd2, force) {
383
- console.log(chalk2.bold("erp-kit init\n"));
384
- const skillsDest = path6.join(cwd2, ".agents", "skills");
385
- let copiedCount = 0;
386
- let skippedCount = 0;
387
- for (const skill of FRAMEWORK_SKILLS) {
388
- const srcSkillDir = path6.join(SKILLS_SRC, skill);
389
- if (!fs3.existsSync(srcSkillDir)) continue;
390
- const destDir = path6.join(skillsDest, skill);
391
- const result = copyDirectoryRecursive(srcSkillDir, destDir, force);
392
- copiedCount += result.copied;
393
- if (result.skipped > 0) {
394
- console.log(chalk2.yellow(` Skipped ${skill}/ (${result.skipped} existing files)`));
395
- skippedCount += result.skipped;
793
+ var ERROR_PATTERN = /^([A-Z_]+):\s*(.+)$/;
794
+ function parseErrorScenarios(tree) {
795
+ const nodes = getNodesUnderHeading(tree, "Error Scenarios");
796
+ const errors = [];
797
+ for (const node of nodes) {
798
+ if (!isList(node)) continue;
799
+ for (const item of node.children) {
800
+ const text = toString(item);
801
+ const match = ERROR_PATTERN.exec(text);
802
+ if (match) {
803
+ errors.push({ code: match[1], description: match[2].trim() });
804
+ }
396
805
  }
397
806
  }
398
- console.log(chalk2.green(` Copied ${copiedCount} skill files to .agents/skills/`));
399
- if (skippedCount > 0) {
400
- console.log(
401
- chalk2.yellow(` Skipped ${skippedCount} existing files (use --force to overwrite)`)
402
- );
807
+ return errors;
808
+ }
809
+ var DEPENDENCY_PATTERN = /^([^:]+)::(.+)$/;
810
+ function parseExternalDependencies(tree) {
811
+ const nodes = getNodesUnderHeading(tree, "External Dependencies");
812
+ const deps = [];
813
+ for (const node of nodes) {
814
+ if (!isList(node)) continue;
815
+ for (const item of node.children) {
816
+ const firstChild = item.children[0];
817
+ if (firstChild?.type !== "paragraph") continue;
818
+ for (const inline of firstChild.children) {
819
+ if (inline.type === "link" || inline.type === "linkReference") {
820
+ const linkText = toString(inline);
821
+ const match = DEPENDENCY_PATTERN.exec(linkText);
822
+ if (match) {
823
+ deps.push({ module: match[1], entity: match[2] });
824
+ }
825
+ }
826
+ }
827
+ }
403
828
  }
404
- const claudeSkills = path6.join(cwd2, ".claude", "skills");
405
- const relTarget = path6.relative(path6.dirname(claudeSkills), skillsDest);
406
- const claudeSkillsExists = (() => {
407
- try {
408
- fs3.lstatSync(claudeSkills);
409
- return true;
410
- } catch {
411
- return false;
829
+ return deps;
830
+ }
831
+
832
+ // src/generator/generate-code.ts
833
+ function generateErrors(docs) {
834
+ const seen = /* @__PURE__ */ new Set();
835
+ const lines = [];
836
+ for (const doc of docs) {
837
+ for (const error of doc.errors) {
838
+ if (seen.has(error.code)) continue;
839
+ seen.add(error.code);
840
+ const className = errorCodeToClassName(error.code);
841
+ lines.push(`export const ${className} = createDomainError(`);
842
+ lines.push(` "${className}", "${error.code}",`);
843
+ const escapedDesc = error.description.replace(/`/g, "'");
844
+ lines.push(` (identifier: string) => \`${escapedDesc}: \${identifier}\`,`);
845
+ lines.push(`);`);
846
+ lines.push(``);
412
847
  }
413
- })();
414
- if (claudeSkillsExists) {
415
- const stat2 = fs3.lstatSync(claudeSkills);
416
- if (stat2.isSymbolicLink()) {
417
- const current = fs3.readlinkSync(claudeSkills);
418
- if (current === relTarget) {
419
- console.log(chalk2.green(" .claude/skills -> .agents/skills/ (already linked)"));
420
- } else if (force) {
421
- fs3.unlinkSync(claudeSkills);
422
- fs3.symlinkSync(relTarget, claudeSkills);
423
- console.log(chalk2.green(" .claude/skills -> .agents/skills/ (relinked)"));
424
- } else {
425
- console.log(
426
- chalk2.yellow(` Skipped .claude/skills (symlink exists -> ${current}, use --force)`)
427
- );
848
+ }
849
+ if (lines.length === 0) return "";
850
+ return `// @generated \u2014 do not edit
851
+ import { createDomainError } from "../../shared/internal";
852
+
853
+ ${lines.join("\n")}`;
854
+ }
855
+ function generateCommandStub(doc) {
856
+ const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
857
+ const inputType = `${pascal}Input`;
858
+ return `import { ok, type CommandContext } from "../../shared/internal";
859
+ import type { DB } from "../generated/kysely-tailordb";
860
+
861
+ export interface ${inputType} {
862
+ // TODO: define input fields
863
+ }
864
+
865
+ export async function run(db: DB, input: ${inputType}, ctx: CommandContext) {
866
+ // TODO: implement
867
+ return ok({});
868
+ }
869
+ `;
870
+ }
871
+ function generateTestStub(doc) {
872
+ const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
873
+ return `import { describe, expect, it } from "vitest";
874
+ import { createMockDb } from "../../testing/index";
875
+ import type { CommandContext } from "../../shared/internal";
876
+ import type { DB } from "../generated/kysely-tailordb";
877
+ import { run, ${pascal}Input } from "./${doc.commandName}";
878
+
879
+ describe("${doc.commandName} - test scenario", () => {
880
+ const ctx: CommandContext = {
881
+ actorId: "test-actor",
882
+ permissions: ["TODO:${doc.commandName}"],
883
+ };
884
+
885
+ it("should be implemented", async () => {
886
+ const { db } = createMockDb<DB>();
887
+ const result = await run(db, {} as ${pascal}Input, ctx);
888
+ expect(result.ok).toBe(true);
889
+ });
890
+ });
891
+ `;
892
+ }
893
+ function generateCommandShell(doc) {
894
+ const lines = [
895
+ `// @generated \u2014 do not edit`,
896
+ `import { defineCommand } from "../../shared/internal";`,
897
+ `import { permissions } from "../lib/permissions.generated";`,
898
+ `import { run } from "./${doc.commandName}";`,
899
+ ``,
900
+ `export const ${doc.commandName} = defineCommand(permissions.${doc.commandName}, run);`,
901
+ ``
902
+ ];
903
+ return lines.join("\n");
904
+ }
905
+ function generateQueryShell(doc) {
906
+ const lines = [
907
+ `// @generated \u2014 do not edit`,
908
+ `import { defineQuery } from "../../shared/internal";`,
909
+ `import { run } from "./${doc.commandName}";`,
910
+ ``,
911
+ `export const ${doc.commandName} = defineQuery(run);`,
912
+ ``
913
+ ];
914
+ return lines.join("\n");
915
+ }
916
+ function generateQueryStub(doc) {
917
+ const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
918
+ const inputType = `${pascal}Input`;
919
+ return `import type { ReadonlyDB } from "../../shared/internal";
920
+ import type { DB } from "../generated/kysely-tailordb";
921
+
922
+ export interface ${inputType} {
923
+ // TODO: define input fields
924
+ }
925
+
926
+ export async function run(db: ReadonlyDB<DB>, input: ${inputType}) {
927
+ // TODO: implement
928
+ return {};
929
+ }
930
+ `;
931
+ }
932
+ function generateQueryTestStub(doc) {
933
+ const pascal = doc.commandName.charAt(0).toUpperCase() + doc.commandName.slice(1);
934
+ const inputType = `${pascal}Input`;
935
+ return `import { describe, expect, it } from "vitest";
936
+ import { createMockDb } from "../../testing/index";
937
+ import type { DB } from "../generated/kysely-tailordb";
938
+ import { run, type ${inputType} } from "./${doc.commandName}";
939
+
940
+ describe("${doc.commandName}", () => {
941
+ it("should be implemented", async () => {
942
+ const { db } = createMockDb<DB>();
943
+ const result = await run(db, {} as ${inputType});
944
+ expect(result).toBeDefined();
945
+ });
946
+ });
947
+ `;
948
+ }
949
+ function generatePermissions(moduleName, commandNames) {
950
+ const sorted = [...commandNames].sort();
951
+ const entries = sorted.map((name) => ` "${name}",`).join("\n");
952
+ return `// @generated \u2014 do not edit
953
+ import { definePermissions } from "../../shared/internal";
954
+
955
+ export const { permissions, own, all } = definePermissions("${moduleName}", [
956
+ ${entries}
957
+ ] as const);
958
+ `;
959
+ }
960
+ function runGenerateCode(modulePath, moduleName) {
961
+ const docsDir = path7.join(modulePath, "docs", "commands");
962
+ const libDir = path7.join(modulePath, "lib");
963
+ const commandDir = path7.join(modulePath, "command");
964
+ if (!fs5.existsSync(docsDir)) {
965
+ console.error(`No docs/commands/ directory found at ${docsDir}`);
966
+ return 1;
967
+ }
968
+ const mdFiles = fs5.readdirSync(docsDir).filter((f) => f.endsWith(".md"));
969
+ if (mdFiles.length === 0) {
970
+ console.error(`No command docs found in ${docsDir}`);
971
+ return 1;
972
+ }
973
+ const parsedDocs = [];
974
+ for (const file of mdFiles) {
975
+ const content = fs5.readFileSync(path7.join(docsDir, file), "utf-8");
976
+ const name = path7.basename(file, ".md");
977
+ parsedDocs.push(parseCommandDoc(name, content));
978
+ }
979
+ const queryDocsDir = path7.join(modulePath, "docs", "queries");
980
+ const allDocsForErrors = [...parsedDocs];
981
+ if (fs5.existsSync(queryDocsDir)) {
982
+ const queryFiles = fs5.readdirSync(queryDocsDir).filter((f) => f.endsWith(".md"));
983
+ for (const file of queryFiles) {
984
+ const content = fs5.readFileSync(path7.join(queryDocsDir, file), "utf-8");
985
+ const name = path7.basename(file, ".md");
986
+ allDocsForErrors.push(parseCommandDoc(name, content));
987
+ }
988
+ }
989
+ let generated = 0;
990
+ const errorsContent = generateErrors(allDocsForErrors);
991
+ if (errorsContent) {
992
+ fs5.mkdirSync(libDir, { recursive: true });
993
+ const errorsFile = path7.join(libDir, "errors.generated.ts");
994
+ fs5.writeFileSync(errorsFile, errorsContent);
995
+ console.log(` wrote ${path7.relative(modulePath, errorsFile)}`);
996
+ generated++;
997
+ }
998
+ const commandNames = parsedDocs.map((d) => d.commandName);
999
+ const permissionsContent = generatePermissions(moduleName, commandNames);
1000
+ const permissionsFile = path7.join(libDir, "permissions.generated.ts");
1001
+ fs5.writeFileSync(permissionsFile, permissionsContent);
1002
+ console.log(` wrote ${path7.relative(modulePath, permissionsFile)}`);
1003
+ generated++;
1004
+ fs5.mkdirSync(commandDir, { recursive: true });
1005
+ for (const doc of parsedDocs) {
1006
+ const implFile = path7.join(commandDir, `${doc.commandName}.ts`);
1007
+ const shellContent = generateCommandShell(doc);
1008
+ const shellFile = path7.join(commandDir, `${doc.commandName}.generated.ts`);
1009
+ fs5.writeFileSync(shellFile, shellContent);
1010
+ console.log(` wrote ${path7.relative(modulePath, shellFile)}`);
1011
+ generated++;
1012
+ if (!fs5.existsSync(implFile)) {
1013
+ fs5.writeFileSync(implFile, generateCommandStub(doc));
1014
+ console.log(` scaffolded ${path7.relative(modulePath, implFile)}`);
1015
+ }
1016
+ const testFile = path7.join(commandDir, `${doc.commandName}.test.ts`);
1017
+ if (!fs5.existsSync(testFile)) {
1018
+ fs5.writeFileSync(testFile, generateTestStub(doc));
1019
+ console.log(` scaffolded ${path7.relative(modulePath, testFile)}`);
1020
+ }
1021
+ }
1022
+ if (fs5.existsSync(queryDocsDir)) {
1023
+ const queryFiles = fs5.readdirSync(queryDocsDir).filter((f) => f.endsWith(".md"));
1024
+ if (queryFiles.length > 0) {
1025
+ const queryDir = path7.join(modulePath, "query");
1026
+ fs5.mkdirSync(queryDir, { recursive: true });
1027
+ for (const file of queryFiles) {
1028
+ const content = fs5.readFileSync(path7.join(queryDocsDir, file), "utf-8");
1029
+ const name = path7.basename(file, ".md");
1030
+ const doc = parseCommandDoc(name, content);
1031
+ const shellFile = path7.join(queryDir, `${doc.commandName}.generated.ts`);
1032
+ fs5.writeFileSync(shellFile, generateQueryShell(doc));
1033
+ console.log(` wrote ${path7.relative(modulePath, shellFile)}`);
1034
+ generated++;
1035
+ const implFile = path7.join(queryDir, `${doc.commandName}.ts`);
1036
+ if (!fs5.existsSync(implFile)) {
1037
+ fs5.writeFileSync(implFile, generateQueryStub(doc));
1038
+ console.log(` scaffolded ${path7.relative(modulePath, implFile)}`);
1039
+ }
1040
+ const testFile = path7.join(queryDir, `${doc.commandName}.test.ts`);
1041
+ if (!fs5.existsSync(testFile)) {
1042
+ fs5.writeFileSync(testFile, generateQueryTestStub(doc));
1043
+ console.log(` scaffolded ${path7.relative(modulePath, testFile)}`);
1044
+ }
428
1045
  }
429
- } else {
430
- console.log(chalk2.yellow(" Skipped .claude/skills (directory exists, not a symlink)"));
431
1046
  }
432
- } else {
433
- fs3.mkdirSync(path6.dirname(claudeSkills), { recursive: true });
434
- fs3.symlinkSync(relTarget, claudeSkills);
435
- console.log(chalk2.green(" .claude/skills -> .agents/skills/ (linked)"));
436
1047
  }
437
- console.log(chalk2.bold.green("\nDone! Run `erp-kit check` to validate your docs."));
1048
+ console.log(`Generated ${generated} file(s) for ${moduleName}`);
438
1049
  return 0;
439
1050
  }
440
1051
 
1052
+ // src/commands/module/generate.ts
1053
+ var cwd = process.cwd();
1054
+ var codeCommand = defineCommand({
1055
+ name: "code",
1056
+ description: "Generate errors, permissions, command shells, and query shells from docs",
1057
+ args: z.object({
1058
+ root: arg(z.string(), {
1059
+ alias: "r",
1060
+ description: "Path to modules directory"
1061
+ }),
1062
+ module: arg(z.string(), {
1063
+ positional: true,
1064
+ description: "Module name (e.g., primitives, item-management)"
1065
+ })
1066
+ }),
1067
+ run: (args) => {
1068
+ const modulePath = path8.resolve(cwd, args.root, args.module);
1069
+ console.log(`Generating code for ${args.module}...`);
1070
+ const exitCode = runGenerateCode(modulePath, args.module);
1071
+ process.exit(exitCode);
1072
+ }
1073
+ });
1074
+ var generateCommand = defineCommand({
1075
+ name: "generate",
1076
+ description: "Generate code from model definitions and docs",
1077
+ subCommands: {
1078
+ code: codeCommand
1079
+ }
1080
+ });
1081
+
1082
+ // src/commands/module/index.ts
1083
+ var cwd2 = process.cwd();
1084
+ var rootArgs = z2.object({
1085
+ root: arg2(z2.string(), {
1086
+ alias: "r",
1087
+ description: "Path to modules directory"
1088
+ })
1089
+ });
1090
+ var listCommand = defineCommand2({
1091
+ name: "list",
1092
+ description: "List available modules",
1093
+ run: () => {
1094
+ const exitCode = runModuleList();
1095
+ process.exit(exitCode);
1096
+ }
1097
+ });
1098
+ var checkCommand = defineCommand2({
1099
+ name: "check",
1100
+ description: "Validate module docs against schemas",
1101
+ args: rootArgs,
1102
+ run: async (args) => {
1103
+ const exitCode = await runCheck({ modulesRoot: args.root }, cwd2);
1104
+ process.exit(exitCode);
1105
+ }
1106
+ });
1107
+ var syncCheckCommand = defineCommand2({
1108
+ name: "sync-check",
1109
+ description: "Validate source <-> doc correspondence",
1110
+ args: rootArgs,
1111
+ run: async (args) => {
1112
+ const result = await runSyncCheck({ modulesRoot: args.root }, cwd2);
1113
+ console.log(formatSyncCheckReport(result));
1114
+ process.exit(result.exitCode);
1115
+ }
1116
+ });
1117
+ var scaffoldCommand = defineCommand2({
1118
+ name: "scaffold",
1119
+ description: "Generate module doc from schema template",
1120
+ args: rootArgs.extend({
1121
+ type: arg2(z2.enum(MODULE_TYPES), {
1122
+ positional: true,
1123
+ description: `Scaffold type (${MODULE_TYPES.join(", ")})`
1124
+ }),
1125
+ parent: arg2(z2.string(), {
1126
+ positional: true,
1127
+ description: "Module name"
1128
+ }),
1129
+ name: arg2(z2.string().optional(), {
1130
+ positional: true,
1131
+ description: "Item name (required for feature, command, model)"
1132
+ })
1133
+ }),
1134
+ run: async (args) => {
1135
+ const exitCode = await runScaffold(
1136
+ args.type,
1137
+ args.parent,
1138
+ args.name,
1139
+ args.root,
1140
+ cwd2
1141
+ );
1142
+ process.exit(exitCode);
1143
+ }
1144
+ });
1145
+ var moduleCommand = defineCommand2({
1146
+ name: "module",
1147
+ description: "Module management",
1148
+ subCommands: {
1149
+ list: listCommand,
1150
+ check: checkCommand,
1151
+ "sync-check": syncCheckCommand,
1152
+ scaffold: scaffoldCommand,
1153
+ generate: generateCommand
1154
+ }
1155
+ });
1156
+
1157
+ // src/commands/app/index.ts
1158
+ import { z as z3 } from "zod";
1159
+ import { defineCommand as defineCommand3, arg as arg3 } from "politty";
1160
+ var cwd3 = process.cwd();
1161
+ var rootArgs2 = z3.object({
1162
+ root: arg3(z3.string(), {
1163
+ alias: "r",
1164
+ description: "Path to app-compose directory"
1165
+ })
1166
+ });
1167
+ var checkCommand2 = defineCommand3({
1168
+ name: "check",
1169
+ description: "Validate app docs against schemas",
1170
+ args: rootArgs2,
1171
+ run: async (args) => {
1172
+ const exitCode = await runCheck({ appRoot: args.root }, cwd3);
1173
+ process.exit(exitCode);
1174
+ }
1175
+ });
1176
+ var syncCheckCommand2 = defineCommand3({
1177
+ name: "sync-check",
1178
+ description: "Validate source <-> doc correspondence",
1179
+ args: rootArgs2,
1180
+ run: async (args) => {
1181
+ const result = await runSyncCheck({ appRoot: args.root }, cwd3);
1182
+ console.log(formatSyncCheckReport(result));
1183
+ process.exit(result.exitCode);
1184
+ }
1185
+ });
1186
+ var scaffoldCommand2 = defineCommand3({
1187
+ name: "scaffold",
1188
+ description: "Generate app doc from schema template",
1189
+ args: rootArgs2.extend({
1190
+ type: arg3(z3.enum(APP_TYPES), {
1191
+ positional: true,
1192
+ description: `Scaffold type (${APP_TYPES.join(", ")})`
1193
+ }),
1194
+ parent: arg3(z3.string(), {
1195
+ positional: true,
1196
+ description: "App name"
1197
+ }),
1198
+ name: arg3(z3.string().optional(), {
1199
+ positional: true,
1200
+ description: "Item name (required for most types)"
1201
+ })
1202
+ }),
1203
+ run: async (args) => {
1204
+ const exitCode = await runScaffold(
1205
+ args.type,
1206
+ args.parent,
1207
+ args.name,
1208
+ args.root,
1209
+ cwd3
1210
+ );
1211
+ process.exit(exitCode);
1212
+ }
1213
+ });
1214
+ var appCommand = defineCommand3({
1215
+ name: "app",
1216
+ description: "App-compose management",
1217
+ subCommands: {
1218
+ check: checkCommand2,
1219
+ "sync-check": syncCheckCommand2,
1220
+ scaffold: scaffoldCommand2
1221
+ }
1222
+ });
1223
+
441
1224
  // src/commands/mock/index.ts
442
- import { z } from "zod";
443
- import { defineCommand, arg } from "politty";
1225
+ import { z as z4 } from "zod";
1226
+ import { defineCommand as defineCommand4, arg as arg4 } from "politty";
444
1227
 
445
1228
  // src/commands/mock/start.ts
446
1229
  import { createServer, request as httpRequest } from "http";
447
1230
  import { createServer as createNetServer } from "net";
448
- import { existsSync, readdirSync } from "fs";
449
- import { resolve as resolve2, relative, join } from "path";
1231
+ import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
1232
+ import { resolve as resolve2, relative, join as join2 } from "path";
450
1233
 
451
1234
  // src/mockServer.ts
452
1235
  import { readFileSync } from "fs";
@@ -489,7 +1272,7 @@ async function createMockServer(mockJsonPath, port) {
489
1272
  // src/commands/mock/start.ts
490
1273
  function readdirSafe(dir) {
491
1274
  try {
492
- return readdirSync(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1275
+ return readdirSync2(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
493
1276
  } catch {
494
1277
  return [];
495
1278
  }
@@ -497,10 +1280,10 @@ function readdirSafe(dir) {
497
1280
  function discoverMocks(mocksDir, filters) {
498
1281
  const mocks = [];
499
1282
  for (const provider of readdirSafe(mocksDir)) {
500
- const providerDir = join(mocksDir, provider);
1283
+ const providerDir = join2(mocksDir, provider);
501
1284
  for (const scenario of readdirSafe(providerDir)) {
502
- const mockPath = join(providerDir, scenario, "mock.json");
503
- if (!existsSync(mockPath)) continue;
1285
+ const mockPath = join2(providerDir, scenario, "mock.json");
1286
+ if (!existsSync2(mockPath)) continue;
504
1287
  mocks.push({ provider, scenario, mockPath });
505
1288
  }
506
1289
  }
@@ -619,20 +1402,20 @@ Reverse proxy listening on http://localhost:${port}`);
619
1402
 
620
1403
  // src/commands/mock/validate.ts
621
1404
  import { readdir, readFile, stat } from "fs/promises";
622
- import { join as join2, resolve as resolve3, relative as relative2, dirname as dirname2, basename } from "path";
623
- import chalk3 from "chalk";
1405
+ import { join as join3, resolve as resolve3, relative as relative2, dirname as dirname2, basename } from "path";
1406
+ import chalk4 from "chalk";
624
1407
  function pass(msg) {
625
- console.log(chalk3.green(`\u2713 ${msg}`));
1408
+ console.log(chalk4.green(`\u2713 ${msg}`));
626
1409
  }
627
1410
  function fail(ctx, msg) {
628
- console.log(chalk3.red(`\u2717 ${msg}`));
1411
+ console.log(chalk4.red(`\u2717 ${msg}`));
629
1412
  ctx.failures++;
630
1413
  }
631
1414
  async function subdirs(dir) {
632
1415
  const entries = await readdir(dir);
633
1416
  const dirs = [];
634
1417
  for (const entry of entries) {
635
- const full = join2(dir, entry);
1418
+ const full = join3(dir, entry);
636
1419
  const s = await stat(full);
637
1420
  if (s.isDirectory()) dirs.push(entry);
638
1421
  }
@@ -702,21 +1485,21 @@ async function discoverAllScenarios(mocksDir) {
702
1485
  const scenarios = [];
703
1486
  const providers = await subdirs(mocksDir);
704
1487
  for (const provider of providers) {
705
- const providerDir = join2(mocksDir, provider);
1488
+ const providerDir = join3(mocksDir, provider);
706
1489
  for (const scenario of await subdirs(providerDir)) {
707
1490
  scenarios.push(`${provider}/${scenario}`);
708
1491
  }
709
1492
  }
710
1493
  return scenarios;
711
1494
  }
712
- function resolveScenarioDir(arg3) {
713
- const abs = resolve3(arg3);
1495
+ function resolveScenarioDir(arg6) {
1496
+ const abs = resolve3(arg6);
714
1497
  if (basename(abs) === "mock.json") return dirname2(abs);
715
1498
  return abs;
716
1499
  }
717
1500
  async function validateScenario(ctx, scenarioDir, mocksDir) {
718
1501
  const label = relative2(mocksDir, scenarioDir);
719
- console.log(chalk3.bold(`
1502
+ console.log(chalk4.bold(`
720
1503
  \u2500\u2500 ${label} \u2500\u2500`));
721
1504
  let entries;
722
1505
  try {
@@ -727,7 +1510,7 @@ async function validateScenario(ctx, scenarioDir, mocksDir) {
727
1510
  }
728
1511
  const hasMock = checkStructure(ctx, entries, label);
729
1512
  if (!hasMock) return;
730
- const mockPath = join2(scenarioDir, "mock.json");
1513
+ const mockPath = join3(scenarioDir, "mock.json");
731
1514
  let data;
732
1515
  try {
733
1516
  data = JSON.parse(await readFile(mockPath, "utf-8"));
@@ -743,37 +1526,37 @@ async function validateScenario(ctx, scenarioDir, mocksDir) {
743
1526
  async function runMockValidate(mocksRoot, paths) {
744
1527
  const ctx = { failures: 0 };
745
1528
  const mocksDir = resolve3(mocksRoot);
746
- const targets = paths.length > 0 ? paths.map(resolveScenarioDir) : (await discoverAllScenarios(mocksDir)).map((s) => join2(mocksDir, s));
1529
+ const targets = paths.length > 0 ? paths.map(resolveScenarioDir) : (await discoverAllScenarios(mocksDir)).map((s) => join3(mocksDir, s));
747
1530
  if (targets.length === 0) {
748
1531
  fail(ctx, "No scenarios found under mocks/");
749
1532
  return 1;
750
1533
  }
751
- console.log(chalk3.bold("\nValidating mock configs...\n"));
1534
+ console.log(chalk4.bold("\nValidating mock configs...\n"));
752
1535
  for (const target of targets) {
753
1536
  await validateScenario(ctx, target, mocksDir);
754
1537
  }
755
- console.log(chalk3.bold("\n\u2500\u2500 summary \u2500\u2500"));
1538
+ console.log(chalk4.bold("\n\u2500\u2500 summary \u2500\u2500"));
756
1539
  if (ctx.failures === 0) {
757
- console.log(chalk3.green("\u2713 All checks passed"));
1540
+ console.log(chalk4.green("\u2713 All checks passed"));
758
1541
  } else {
759
- console.log(chalk3.red(`\u2717 ${ctx.failures} check(s) failed`));
1542
+ console.log(chalk4.red(`\u2717 ${ctx.failures} check(s) failed`));
760
1543
  }
761
1544
  return ctx.failures === 0 ? 0 : 1;
762
1545
  }
763
1546
 
764
1547
  // src/commands/mock/index.ts
765
- var startCommand = defineCommand({
1548
+ var startCommand = defineCommand4({
766
1549
  name: "start",
767
1550
  description: "Start mock API servers with reverse proxy",
768
- args: z.object({
769
- mocksRoot: arg(z.string().default("./mocks"), {
1551
+ args: z4.object({
1552
+ mocksRoot: arg4(z4.string().default("./mocks"), {
770
1553
  description: "Path to mocks directory"
771
1554
  }),
772
- port: arg(z.coerce.number().default(3e3), {
1555
+ port: arg4(z4.coerce.number().default(3e3), {
773
1556
  alias: "p",
774
1557
  description: "Reverse proxy port"
775
1558
  }),
776
- filter: arg(z.array(z.string()).default([]), {
1559
+ filter: arg4(z4.array(z4.string()).default([]), {
777
1560
  positional: true,
778
1561
  description: "Filter by provider or provider/scenario"
779
1562
  })
@@ -783,14 +1566,14 @@ var startCommand = defineCommand({
783
1566
  process.exit(exitCode);
784
1567
  }
785
1568
  });
786
- var validateCommand = defineCommand({
1569
+ var validateCommand = defineCommand4({
787
1570
  name: "validate",
788
1571
  description: "Validate mock scenario configs",
789
- args: z.object({
790
- mocksRoot: arg(z.string().default("./mocks"), {
1572
+ args: z4.object({
1573
+ mocksRoot: arg4(z4.string().default("./mocks"), {
791
1574
  description: "Path to mocks directory"
792
1575
  }),
793
- paths: arg(z.array(z.string()).default([]), {
1576
+ paths: arg4(z4.array(z4.string()).default([]), {
794
1577
  positional: true,
795
1578
  description: "Specific scenario paths to validate"
796
1579
  })
@@ -800,7 +1583,7 @@ var validateCommand = defineCommand({
800
1583
  process.exit(exitCode);
801
1584
  }
802
1585
  });
803
- var mockCommand = defineCommand({
1586
+ var mockCommand = defineCommand4({
804
1587
  name: "mock",
805
1588
  description: "Mock API server management",
806
1589
  subCommands: {
@@ -809,106 +1592,63 @@ var mockCommand = defineCommand({
809
1592
  }
810
1593
  });
811
1594
 
812
- // src/cli.ts
813
- var cwd = process.cwd();
814
- var rootArgs = z2.object({
815
- modulesRoot: arg2(z2.string().optional(), {
816
- alias: "m",
817
- description: "Path to modules directory"
1595
+ // src/commands/index.ts
1596
+ var cwd4 = process.cwd();
1597
+ var initCommand = defineCommand5({
1598
+ name: "init",
1599
+ description: "Set up consumer repo with framework skills",
1600
+ args: z5.object({
1601
+ force: arg5(z5.boolean().default(false), {
1602
+ alias: "f",
1603
+ description: "Overwrite existing skills"
1604
+ })
818
1605
  }),
819
- appRoot: arg2(z2.string().optional(), {
820
- alias: "a",
821
- description: "Path to app-compose directory (apps/ or examples/)"
822
- })
823
- });
824
- function requireRoot(args) {
825
- const paths = { modulesRoot: args.modulesRoot, appRoot: args.appRoot };
826
- if (!paths.modulesRoot && !paths.appRoot) {
827
- console.error("At least one of --modules-root or --app-root is required.");
828
- process.exit(2);
829
- }
830
- return paths;
831
- }
832
- var checkCommand = defineCommand2({
833
- name: "check",
834
- description: "Validate docs against schemas",
835
- args: rootArgs,
836
- run: async (args) => {
837
- const paths = requireRoot(args);
838
- const exitCode = await runCheck(paths, cwd);
1606
+ run: (args) => {
1607
+ const exitCode = runInit(cwd4, args.force);
839
1608
  process.exit(exitCode);
840
1609
  }
841
1610
  });
842
- var syncCheckCommand = defineCommand2({
843
- name: "sync-check",
844
- description: "Validate source <-> doc correspondence",
845
- args: rootArgs,
846
- run: async (args) => {
847
- const paths = requireRoot(args);
848
- const result = await runSyncCheck(paths, cwd);
849
- console.log(formatSyncCheckReport(result));
850
- process.exit(result.exitCode);
851
- }
852
- });
853
- var scaffoldCommand = defineCommand2({
854
- name: "scaffold",
855
- description: "Generate doc file from schema template",
856
- args: rootArgs.extend({
857
- type: arg2(z2.enum(ALL_TYPES), {
858
- positional: true,
859
- description: `Scaffold type (${ALL_TYPES.join(", ")})`
860
- }),
861
- parent: arg2(z2.string(), {
862
- positional: true,
863
- description: "Parent name (module or app name)"
864
- }),
865
- name: arg2(z2.string().optional(), {
866
- positional: true,
867
- description: "Item name (required for most types)"
1611
+ var licenseCheckCommand = defineCommand5({
1612
+ name: "check",
1613
+ description: "Check dependency licenses against allowlist",
1614
+ args: z5.object({
1615
+ config: arg5(z5.string(), {
1616
+ alias: "c",
1617
+ description: "Path to license config JSON file"
868
1618
  })
869
1619
  }),
870
- run: async (args) => {
871
- const paths = requireRoot(args);
872
- const root = isModuleType(args.type) ? paths.modulesRoot : paths.appRoot;
873
- if (!root) {
874
- console.error(
875
- `--${isModuleType(args.type) ? "modules-root" : "app-root"} is required for scaffold type "${args.type}".`
876
- );
877
- process.exit(2);
878
- }
879
- const exitCode = await runScaffold(
880
- args.type,
881
- args.parent,
882
- args.name,
883
- root,
884
- cwd
885
- );
1620
+ run: (args) => {
1621
+ const exitCode = runLicenseCheck(args.config);
886
1622
  process.exit(exitCode);
887
1623
  }
888
1624
  });
889
- var initCommand = defineCommand2({
890
- name: "init",
891
- description: "Set up consumer repo with framework skills",
892
- args: z2.object({
893
- force: arg2(z2.boolean().default(false), {
894
- alias: "f",
895
- description: "Overwrite existing skills"
896
- })
897
- }),
898
- run: (args) => {
899
- const exitCode = runInit(cwd, args.force);
1625
+ var licenseListCommand = defineCommand5({
1626
+ name: "list",
1627
+ description: "List available license groups",
1628
+ run: () => {
1629
+ const exitCode = runLicenseList();
900
1630
  process.exit(exitCode);
901
1631
  }
902
1632
  });
903
- var main = defineCommand2({
1633
+ var licenseCommand = defineCommand5({
1634
+ name: "license",
1635
+ description: "License management",
1636
+ subCommands: {
1637
+ check: licenseCheckCommand,
1638
+ list: licenseListCommand
1639
+ }
1640
+ });
1641
+ var mainCommand = defineCommand5({
904
1642
  name: "erp-kit",
905
- description: "Documentation validation and scaffolding tool",
1643
+ description: "ERP module framework CLI",
906
1644
  subCommands: {
907
- check: checkCommand,
908
- "sync-check": syncCheckCommand,
909
- scaffold: scaffoldCommand,
1645
+ module: moduleCommand,
1646
+ app: appCommand,
1647
+ mock: mockCommand,
910
1648
  init: initCommand,
911
- mock: mockCommand
1649
+ license: licenseCommand
912
1650
  }
913
1651
  });
914
- void runMain(main);
1652
+
1653
+ // src/cli.ts
1654
+ void runMain(mainCommand);