@yss123/cage-cli 0.2.0 → 0.3.1

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 (629) hide show
  1. package/README.md +47 -3
  2. package/bin/cage.js +5 -0
  3. package/bin/create-cage-app.js +5 -0
  4. package/dist/analyze.d.ts +16 -0
  5. package/dist/analyze.js +18 -2
  6. package/dist/analyze.js.map +1 -1
  7. package/dist/approval-tree.d.ts +88 -0
  8. package/dist/approval-tree.js +18 -0
  9. package/dist/approval-tree.js.map +1 -0
  10. package/dist/baseline.d.ts +8 -0
  11. package/dist/baseline.js +13 -0
  12. package/dist/baseline.js.map +1 -1
  13. package/dist/bootstrap.d.ts +20 -0
  14. package/dist/bootstrap.js +75 -0
  15. package/dist/bootstrap.js.map +1 -0
  16. package/dist/budget.d.ts +7 -0
  17. package/dist/budget.js +49 -5
  18. package/dist/budget.js.map +1 -1
  19. package/dist/capabilities.d.ts +38 -0
  20. package/dist/capabilities.js +148 -0
  21. package/dist/capabilities.js.map +1 -0
  22. package/dist/config.d.ts +31 -2
  23. package/dist/config.js +22 -0
  24. package/dist/config.js.map +1 -1
  25. package/dist/context.d.ts +14 -0
  26. package/dist/context.js +35 -2
  27. package/dist/context.js.map +1 -1
  28. package/dist/create-prompt.d.ts +7 -0
  29. package/dist/create-prompt.js +12 -0
  30. package/dist/create-prompt.js.map +1 -1
  31. package/dist/create.d.ts +21 -1
  32. package/dist/create.js +23 -1
  33. package/dist/create.js.map +1 -1
  34. package/dist/derive.d.ts +23 -0
  35. package/dist/derive.js +40 -0
  36. package/dist/derive.js.map +1 -1
  37. package/dist/dev.d.ts +6 -0
  38. package/dist/dev.js +11 -0
  39. package/dist/dev.js.map +1 -1
  40. package/dist/doctor.d.ts +98 -0
  41. package/dist/doctor.js +93 -0
  42. package/dist/doctor.js.map +1 -0
  43. package/dist/env.d.ts +6 -0
  44. package/dist/env.js +11 -0
  45. package/dist/env.js.map +1 -1
  46. package/dist/findings.d.ts +27 -0
  47. package/dist/findings.js +20 -0
  48. package/dist/findings.js.map +1 -1
  49. package/dist/gen/contracts.d.ts +28 -0
  50. package/dist/gen/contracts.js +52 -12
  51. package/dist/gen/contracts.js.map +1 -1
  52. package/dist/gen/index.d.ts +26 -0
  53. package/dist/gen/index.js +69 -1
  54. package/dist/gen/index.js.map +1 -1
  55. package/dist/gen/zod-code.d.ts +42 -0
  56. package/dist/gen/zod-code.js +178 -16
  57. package/dist/gen/zod-code.js.map +1 -1
  58. package/dist/graph-approvals.d.ts +70 -0
  59. package/dist/graph-approvals.js +93 -0
  60. package/dist/graph-approvals.js.map +1 -0
  61. package/dist/graph-business.d.ts +135 -0
  62. package/dist/graph-business.js +404 -0
  63. package/dist/graph-business.js.map +1 -0
  64. package/dist/graph-command.d.ts +17 -0
  65. package/dist/graph-command.js +21 -0
  66. package/dist/graph-command.js.map +1 -1
  67. package/dist/graph-model.d.ts +44 -0
  68. package/dist/graph-model.js +36 -3
  69. package/dist/graph-model.js.map +1 -1
  70. package/dist/graph-presentation.d.ts +16 -0
  71. package/dist/graph-presentation.js +10 -1
  72. package/dist/graph-presentation.js.map +1 -1
  73. package/dist/graph-query.d.ts +95 -0
  74. package/dist/graph-query.js +62 -0
  75. package/dist/graph-query.js.map +1 -1
  76. package/dist/graph-relations.d.ts +20 -0
  77. package/dist/graph-relations.js +42 -10
  78. package/dist/graph-relations.js.map +1 -1
  79. package/dist/graph-search.d.ts +35 -0
  80. package/dist/graph-search.js +36 -0
  81. package/dist/graph-search.js.map +1 -1
  82. package/dist/graph-snapshot.d.ts +26 -0
  83. package/dist/graph-snapshot.js +30 -1
  84. package/dist/graph-snapshot.js.map +1 -1
  85. package/dist/graph.d.ts +13 -2
  86. package/dist/graph.js +61 -4
  87. package/dist/graph.js.map +1 -1
  88. package/dist/impact.d.ts +50 -0
  89. package/dist/impact.js +62 -2
  90. package/dist/impact.js.map +1 -1
  91. package/dist/index.d.ts +10 -0
  92. package/dist/index.js +10 -0
  93. package/dist/index.js.map +1 -1
  94. package/dist/init.d.ts +12 -0
  95. package/dist/init.js +15 -0
  96. package/dist/init.js.map +1 -1
  97. package/dist/load.d.ts +10 -0
  98. package/dist/load.js +15 -0
  99. package/dist/load.js.map +1 -1
  100. package/dist/main.d.ts +6 -0
  101. package/dist/main.js +93 -5
  102. package/dist/main.js.map +1 -1
  103. package/dist/migrate.d.ts +12 -0
  104. package/dist/migrate.js +17 -0
  105. package/dist/migrate.js.map +1 -1
  106. package/dist/ontology.d.ts +67 -2
  107. package/dist/ontology.js +94 -4
  108. package/dist/ontology.js.map +1 -1
  109. package/dist/process-rules.d.ts +21 -0
  110. package/dist/process-rules.js +100 -0
  111. package/dist/process-rules.js.map +1 -0
  112. package/dist/process.d.ts +32 -0
  113. package/dist/process.js +32 -0
  114. package/dist/process.js.map +1 -1
  115. package/dist/project-structure.d.ts +5 -0
  116. package/dist/project-structure.js +10 -0
  117. package/dist/project-structure.js.map +1 -1
  118. package/dist/registration.d.ts +16 -0
  119. package/dist/registration.js +56 -0
  120. package/dist/registration.js.map +1 -0
  121. package/dist/rules.d.ts +52 -0
  122. package/dist/rules.js +58 -0
  123. package/dist/rules.js.map +1 -1
  124. package/dist/runtime-diagnostics.d.ts +27 -0
  125. package/dist/runtime-diagnostics.js +60 -0
  126. package/dist/runtime-diagnostics.js.map +1 -0
  127. package/dist/snapshots.d.ts +40 -0
  128. package/dist/snapshots.js +62 -0
  129. package/dist/snapshots.js.map +1 -0
  130. package/dist/static-check.d.ts +33 -0
  131. package/dist/static-check.js +37 -1
  132. package/dist/static-check.js.map +1 -1
  133. package/dist/sync.d.ts +11 -0
  134. package/dist/sync.js +66 -9
  135. package/dist/sync.js.map +1 -1
  136. package/dist/upgrade.d.ts +16 -0
  137. package/dist/upgrade.js +21 -0
  138. package/dist/upgrade.js.map +1 -1
  139. package/dist/verify.d.ts +14 -0
  140. package/dist/verify.js +19 -0
  141. package/dist/verify.js.map +1 -1
  142. package/dist/version.js +5 -0
  143. package/dist/version.js.map +1 -1
  144. package/graph-ui/app.js +321 -27
  145. package/graph-ui/approval-flow.js +185 -0
  146. package/graph-ui/approval-parallel.js +110 -0
  147. package/graph-ui/approval-tree.js +17 -0
  148. package/graph-ui/business.css +1011 -0
  149. package/graph-ui/business.js +566 -0
  150. package/graph-ui/flowchart-interaction.js +177 -0
  151. package/graph-ui/flowchart.js +1059 -0
  152. package/graph-ui/graph-approvals.js +92 -0
  153. package/graph-ui/graph-business.js +403 -0
  154. package/graph-ui/graph-model.js +36 -3
  155. package/graph-ui/graph-relations.js +42 -10
  156. package/graph-ui/graph-search.js +36 -0
  157. package/graph-ui/index.html +26 -12
  158. package/graph-ui/model.js +28 -0
  159. package/graph-ui/relations.js +4 -0
  160. package/graph-ui/structure.js +44 -0
  161. package/graph-ui/style.css +12 -0
  162. package/package.json +6 -4
  163. package/templates/app/.dockerignore +2 -0
  164. package/templates/app/.env.example +10 -0
  165. package/templates/app/AGENTS.md +50 -10
  166. package/templates/app/README.md +9 -5
  167. package/templates/app/_gitignore +1 -0
  168. package/templates/app/apps/api/package.json +2 -2
  169. package/templates/app/apps/api/src/main.ts +5 -1
  170. package/templates/app/apps/api/src/worker.ts +3 -0
  171. package/templates/app/apps/web/index.html +1 -0
  172. package/templates/app/apps/web/package.json +7 -3
  173. package/templates/app/apps/web/src/app/app.tsx +122 -12
  174. package/templates/app/apps/web/src/app/styles/global.css +88 -8
  175. package/templates/app/apps/web/src/app/use-session.ts +43 -0
  176. package/templates/app/apps/web/src/app/workspace-layout.tsx +58 -19
  177. package/templates/app/apps/web/src/main.tsx +5 -0
  178. package/templates/app/apps/web/src/modules/approval/components/task-operation-dialog.tsx +61 -0
  179. package/templates/app/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +13 -5
  180. package/templates/app/apps/web/src/modules/approval/index.ts +4 -0
  181. package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +89 -38
  182. package/templates/app/apps/web/src/modules/approval/pages/approval-tasks.css +18 -0
  183. package/templates/app/apps/web/src/modules/auth/index.ts +4 -0
  184. package/templates/app/apps/web/src/modules/auth/pages/login-page.tsx +12 -0
  185. package/templates/app/apps/web/src/modules/inventory/index.ts +4 -0
  186. package/templates/app/apps/web/src/modules/inventory/pages/inventory-page.tsx +29 -1
  187. package/templates/app/apps/web/src/modules/purchase/components/approval-history.tsx +67 -0
  188. package/templates/app/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
  189. package/templates/app/apps/web/src/modules/purchase/components/order-reviewers.tsx +38 -0
  190. package/templates/app/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
  191. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
  192. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +32 -3
  193. package/templates/app/apps/web/src/modules/purchase/index.ts +5 -0
  194. package/templates/app/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
  195. package/templates/app/apps/web/src/modules/purchase/pages/purchase-intelligence.css +17 -0
  196. package/templates/app/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +156 -0
  197. package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +54 -22
  198. package/templates/app/apps/web/src/modules/workspace/index.ts +5 -0
  199. package/templates/app/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
  200. package/templates/app/apps/web/src/shared/hooks/use-command.ts +13 -0
  201. package/templates/app/apps/web/src/shared/lib/error-message.ts +15 -1
  202. package/templates/app/apps/web/src/shared/lib/navigation.ts +21 -0
  203. package/templates/app/apps/web/src/shared/ui/approval-member-picker.css +10 -0
  204. package/templates/app/apps/web/src/shared/ui/approval-member-picker.tsx +51 -0
  205. package/templates/app/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
  206. package/templates/app/apps/web/src/shared/ui/assistant-panel.css +134 -0
  207. package/templates/app/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
  208. package/templates/app/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
  209. package/templates/app/apps/web/src/shared/ui/attachment-upload.css +28 -0
  210. package/templates/app/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
  211. package/templates/app/apps/web/src/shared/ui/notice.tsx +7 -0
  212. package/templates/app/apps/web/src/shared/ui/page-heading.tsx +7 -0
  213. package/templates/app/apps/web/src/shared/ui/page-state.css +47 -0
  214. package/templates/app/apps/web/src/shared/ui/page-state.tsx +76 -0
  215. package/templates/app/apps/web/src/shared/ui/require-capability.tsx +34 -0
  216. package/templates/app/apps/web/vite.config.ts +5 -0
  217. package/templates/app/cage.config.json +23 -0
  218. package/templates/app/db/migrations/0002_draft.sql +12 -0
  219. package/templates/app/db/migrations/0003_draft.sql +8 -0
  220. package/templates/app/db/migrations/0004_draft.sql +27 -0
  221. package/templates/app/deploy/nginx.conf +52 -0
  222. package/templates/app/docs/ai/README.md +28 -2
  223. package/templates/app/docs/ai/approvals.md +260 -0
  224. package/templates/app/docs/ai/architecture.md +26 -0
  225. package/templates/app/docs/ai/commenting.md +203 -0
  226. package/templates/app/docs/ai/diagnostics.md +80 -0
  227. package/templates/app/docs/ai/files.md +93 -0
  228. package/templates/app/docs/ai/intelligence.md +348 -0
  229. package/templates/app/docs/ai/ontology-context.md +59 -4
  230. package/templates/app/docs/ai/primitives.md +34 -1
  231. package/templates/app/docs/ai/project-structure.md +8 -3
  232. package/templates/app/docs/ai/purchase-example.md +35 -7
  233. package/templates/app/docs/ai/recipes.md +10 -2
  234. package/templates/app/docs/ai/routing.md +86 -0
  235. package/templates/app/docs/ai/troubleshooting.md +5 -0
  236. package/templates/app/docs/ai/workflow.md +24 -11
  237. package/templates/app/docs/errors/CAGE-AI-001.md +61 -0
  238. package/templates/app/docs/errors/CAGE-APPR-001.md +13 -9
  239. package/templates/app/docs/errors/CAGE-APPR-002.md +2 -2
  240. package/templates/app/docs/errors/CAGE-APPR-003.md +1 -1
  241. package/templates/app/docs/errors/CAGE-APPR-004.md +4 -4
  242. package/templates/app/docs/errors/CAGE-APPR-005.md +4 -4
  243. package/templates/app/docs/errors/CAGE-APPR-006.md +29 -8
  244. package/templates/app/docs/errors/CAGE-APPR-007.md +9 -7
  245. package/templates/app/docs/errors/CAGE-APPR-010.md +5 -5
  246. package/templates/app/docs/errors/CAGE-AUDIT-001.md +53 -0
  247. package/templates/app/docs/errors/CAGE-AUTH-001.md +1 -1
  248. package/templates/app/docs/errors/CAGE-BIZ-001.md +51 -0
  249. package/templates/app/docs/errors/CAGE-BIZ-002.md +49 -0
  250. package/templates/app/docs/errors/CAGE-BUDGET-001.md +1 -1
  251. package/templates/app/docs/errors/CAGE-BUDGET-002.md +1 -1
  252. package/templates/app/docs/errors/CAGE-BUDGET-003.md +1 -1
  253. package/templates/app/docs/errors/CAGE-CMD-002.md +1 -1
  254. package/templates/app/docs/errors/CAGE-CMD-003.md +1 -1
  255. package/templates/app/docs/errors/CAGE-CONN-001.md +3 -3
  256. package/templates/app/docs/errors/CAGE-CONN-002.md +1 -1
  257. package/templates/app/docs/errors/CAGE-CONN-003.md +1 -1
  258. package/templates/app/docs/errors/CAGE-CONN-004.md +1 -1
  259. package/templates/app/docs/errors/CAGE-CONN-005.md +1 -1
  260. package/templates/app/docs/errors/CAGE-CONN-006.md +1 -1
  261. package/templates/app/docs/errors/CAGE-CONN-007.md +6 -6
  262. package/templates/app/docs/errors/CAGE-CONN-008.md +5 -5
  263. package/templates/app/docs/errors/CAGE-CONN-009.md +6 -6
  264. package/templates/app/docs/errors/CAGE-CONN-010.md +6 -6
  265. package/templates/app/docs/errors/CAGE-CONN-011.md +1 -1
  266. package/templates/app/docs/errors/CAGE-CONN-012.md +1 -1
  267. package/templates/app/docs/errors/CAGE-CONN-013.md +49 -0
  268. package/templates/app/docs/errors/CAGE-CONN-014.md +48 -0
  269. package/templates/app/docs/errors/CAGE-CONN-015.md +49 -0
  270. package/templates/app/docs/errors/CAGE-CREATE-001.md +10 -9
  271. package/templates/app/docs/errors/CAGE-DECL-001.md +2 -2
  272. package/templates/app/docs/errors/CAGE-DECL-002.md +7 -6
  273. package/templates/app/docs/errors/CAGE-DECL-003.md +1 -1
  274. package/templates/app/docs/errors/CAGE-DECL-004.md +1 -1
  275. package/templates/app/docs/errors/CAGE-DEP-001.md +2 -2
  276. package/templates/app/docs/errors/CAGE-DEP-002.md +1 -1
  277. package/templates/app/docs/errors/CAGE-DEP-003.md +2 -2
  278. package/templates/app/docs/errors/CAGE-DEP-004.md +1 -1
  279. package/templates/app/docs/errors/CAGE-DEP-005.md +1 -1
  280. package/templates/app/docs/errors/CAGE-DIAG-001.md +53 -0
  281. package/templates/app/docs/errors/CAGE-DLQ-001.md +2 -2
  282. package/templates/app/docs/errors/CAGE-ENV-001.md +4 -4
  283. package/templates/app/docs/errors/CAGE-ENV-002.md +51 -0
  284. package/templates/app/docs/errors/CAGE-ENV-003.md +48 -0
  285. package/templates/app/docs/errors/CAGE-EVENT-001.md +1 -1
  286. package/templates/app/docs/errors/CAGE-EVENT-002.md +7 -7
  287. package/templates/app/docs/errors/CAGE-FIELD-001.md +2 -2
  288. package/templates/app/docs/errors/CAGE-FIELD-002.md +1 -1
  289. package/templates/app/docs/errors/CAGE-FIELD-003.md +1 -1
  290. package/templates/app/docs/errors/CAGE-FIELD-004.md +1 -1
  291. package/templates/app/docs/errors/CAGE-FILE-001.md +56 -0
  292. package/templates/app/docs/errors/CAGE-GEN-001.md +2 -2
  293. package/templates/app/docs/errors/CAGE-GEN-002.md +1 -1
  294. package/templates/app/docs/errors/CAGE-GEN-003.md +53 -0
  295. package/templates/app/docs/errors/CAGE-GRANT-001.md +3 -3
  296. package/templates/app/docs/errors/CAGE-GRANT-002.md +2 -2
  297. package/templates/app/docs/errors/CAGE-GRANT-003.md +7 -6
  298. package/templates/app/docs/errors/CAGE-IMPACT-001.md +2 -2
  299. package/templates/app/docs/errors/CAGE-IMPACT-002.md +52 -0
  300. package/templates/app/docs/errors/CAGE-INIT-001.md +1 -1
  301. package/templates/app/docs/errors/CAGE-INIT-002.md +1 -1
  302. package/templates/app/docs/errors/CAGE-INIT-003.md +2 -2
  303. package/templates/app/docs/errors/CAGE-INIT-004.md +1 -1
  304. package/templates/app/docs/errors/CAGE-INIT-005.md +52 -0
  305. package/templates/app/docs/errors/CAGE-JOB-001.md +1 -1
  306. package/templates/app/docs/errors/CAGE-JOB-002.md +1 -1
  307. package/templates/app/docs/errors/CAGE-JOB-003.md +1 -1
  308. package/templates/app/docs/errors/CAGE-LINT-001.md +1 -1
  309. package/templates/app/docs/errors/CAGE-MIG-001.md +1 -1
  310. package/templates/app/docs/errors/CAGE-MIG-002.md +1 -1
  311. package/templates/app/docs/errors/CAGE-MIG-005.md +1 -1
  312. package/templates/app/docs/errors/CAGE-NAME-001.md +1 -1
  313. package/templates/app/docs/errors/CAGE-NAME-002.md +1 -1
  314. package/templates/app/docs/errors/CAGE-NAME-003.md +3 -3
  315. package/templates/app/docs/errors/CAGE-NAME-004.md +1 -1
  316. package/templates/app/docs/errors/CAGE-NAME-005.md +1 -1
  317. package/templates/app/docs/errors/CAGE-NAME-006.md +1 -1
  318. package/templates/app/docs/errors/CAGE-ORG-001.md +7 -6
  319. package/templates/app/docs/errors/CAGE-PAIR-002.md +6 -5
  320. package/templates/app/docs/errors/CAGE-QUERY-001.md +1 -1
  321. package/templates/app/docs/errors/CAGE-QUERY-002.md +2 -2
  322. package/templates/app/docs/errors/CAGE-QUERY-003.md +7 -6
  323. package/templates/app/docs/errors/CAGE-REACT-001.md +3 -3
  324. package/templates/app/docs/errors/CAGE-REACT-002.md +1 -1
  325. package/templates/app/docs/errors/CAGE-REACT-003.md +50 -0
  326. package/templates/app/docs/errors/CAGE-READS-001.md +9 -6
  327. package/templates/app/docs/errors/CAGE-REG-001.md +13 -12
  328. package/templates/app/docs/errors/CAGE-REG-002.md +2 -1
  329. package/templates/app/docs/errors/CAGE-REG-003.md +1 -1
  330. package/templates/app/docs/errors/CAGE-REL-001.md +14 -14
  331. package/templates/app/docs/errors/CAGE-ROUTE-001.md +7 -6
  332. package/templates/app/docs/errors/CAGE-SCOPE-001.md +1 -1
  333. package/templates/app/docs/errors/CAGE-SCOPE-002.md +2 -2
  334. package/templates/app/docs/errors/CAGE-SECRET-001.md +2 -2
  335. package/templates/app/docs/errors/CAGE-SECRET-002.md +1 -1
  336. package/templates/app/docs/errors/CAGE-SENS-001.md +5 -5
  337. package/templates/app/docs/errors/CAGE-SQL-001.md +1 -1
  338. package/templates/app/docs/errors/CAGE-SQL-002.md +1 -1
  339. package/templates/app/docs/errors/CAGE-STATE-001.md +3 -3
  340. package/templates/app/docs/errors/CAGE-STATE-002.md +1 -1
  341. package/templates/app/docs/errors/CAGE-STATE-003.md +1 -1
  342. package/templates/app/docs/errors/CAGE-STATE-004.md +1 -1
  343. package/templates/app/docs/errors/CAGE-STATE-005.md +3 -2
  344. package/templates/app/docs/errors/CAGE-STATE-010.md +5 -5
  345. package/templates/app/docs/errors/CAGE-STATE-011.md +5 -5
  346. package/templates/app/docs/errors/CAGE-STRUCT-001.md +1 -1
  347. package/templates/app/docs/errors/CAGE-STRUCT-002.md +1 -1
  348. package/templates/app/docs/errors/CAGE-SYNC-001.md +3 -2
  349. package/templates/app/docs/errors/CAGE-TEST-001.md +1 -1
  350. package/templates/app/docs/errors/CAGE-TEST-002.md +50 -0
  351. package/templates/app/docs/errors/CAGE-TEST-003.md +52 -0
  352. package/templates/app/docs/errors/CAGE-UNSAFE-001.md +3 -2
  353. package/templates/app/docs/errors/CAGE-UPGRADE-001.md +2 -2
  354. package/templates/app/docs/errors/CAGE-WORKER-001.md +48 -0
  355. package/templates/app/docs/errors/CAGE-WORKER-002.md +50 -0
  356. package/templates/app/docs/errors/CAGE-WORKER-003.md +48 -0
  357. package/templates/app/docs/errors/README.md +52 -2
  358. package/templates/app/package.json +3 -3
  359. package/templates/app/packages/contracts/package.json +1 -1
  360. package/templates/app/packages/contracts/src/aggregates/approval-member/index.ts +70 -0
  361. package/templates/app/packages/contracts/src/aggregates/dept/index.ts +10 -10
  362. package/templates/app/packages/contracts/src/aggregates/inventory/index.ts +5 -5
  363. package/templates/app/packages/contracts/src/aggregates/inventory-lock/index.ts +4 -4
  364. package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +34 -12
  365. package/templates/app/packages/contracts/src/aggregates/role/index.ts +15 -15
  366. package/templates/app/packages/contracts/src/aggregates/user/index.ts +16 -16
  367. package/templates/app/packages/contracts/src/index.ts +16 -1
  368. package/templates/app/packages/contracts/src/queries/index.ts +2 -2
  369. package/templates/app/packages/domain/package.json +5 -4
  370. package/templates/app/packages/domain/src/index.ts +4 -0
  371. package/templates/app/packages/domain/src/integrations/erp.ts +15 -0
  372. package/templates/app/packages/domain/src/integrations/intelligence.ts +20 -0
  373. package/templates/app/packages/domain/src/modules/inventory/index.ts +1 -0
  374. package/templates/app/packages/domain/src/modules/inventory/inventory.ts +12 -0
  375. package/templates/app/packages/domain/src/modules/purchase/approval-members.ts +54 -0
  376. package/templates/app/packages/domain/src/modules/purchase/approvals.ts +38 -6
  377. package/templates/app/packages/domain/src/modules/purchase/index.ts +2 -0
  378. package/templates/app/packages/domain/src/modules/purchase/intelligence.test.ts +224 -0
  379. package/templates/app/packages/domain/src/modules/purchase/jobs.ts +5 -0
  380. package/templates/app/packages/domain/src/modules/purchase/purchase-order.test.ts +9 -0
  381. package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +125 -4
  382. package/templates/app/packages/domain/src/modules/purchase/queries.ts +5 -0
  383. package/templates/app/packages/domain/src/workflows/purchase-inventory.ts +6 -0
  384. package/templates/app/packages/domain/src/workflows/purchase-process.ts +42 -0
  385. package/templates/blank/.dockerignore +2 -0
  386. package/templates/blank/.env.example +10 -0
  387. package/templates/blank/AGENTS.md +50 -10
  388. package/templates/blank/README.md +4 -1
  389. package/templates/blank/_gitignore +1 -0
  390. package/templates/blank/apps/api/package.json +1 -1
  391. package/templates/blank/apps/api/src/main.ts +4 -1
  392. package/templates/blank/apps/api/src/worker.ts +2 -0
  393. package/templates/blank/apps/web/index.html +1 -0
  394. package/templates/blank/apps/web/package.json +7 -3
  395. package/templates/blank/apps/web/src/app/app.tsx +80 -18
  396. package/templates/blank/apps/web/src/app/styles/global.css +90 -0
  397. package/templates/blank/apps/web/src/app/use-session.ts +43 -0
  398. package/templates/blank/apps/web/src/app/workspace-layout.tsx +30 -5
  399. package/templates/blank/apps/web/src/main.tsx +5 -0
  400. package/templates/blank/apps/web/src/modules/auth/index.ts +4 -0
  401. package/templates/blank/apps/web/src/modules/auth/pages/login-page.tsx +18 -1
  402. package/templates/blank/apps/web/src/modules/directory/index.ts +7 -0
  403. package/templates/blank/apps/web/src/modules/directory/pages/user-detail-page.tsx +78 -0
  404. package/templates/blank/apps/web/src/modules/directory/pages/users-page.tsx +93 -0
  405. package/templates/blank/apps/web/src/modules/workspace/index.ts +4 -0
  406. package/templates/blank/apps/web/src/modules/workspace/pages/home-page.tsx +17 -0
  407. package/templates/blank/apps/web/src/shared/lib/error-message.ts +11 -0
  408. package/templates/blank/apps/web/src/shared/lib/navigation.ts +21 -0
  409. package/templates/blank/apps/web/src/shared/ui/brand.tsx +10 -2
  410. package/templates/blank/apps/web/src/shared/ui/page-state.css +47 -0
  411. package/templates/blank/apps/web/src/shared/ui/page-state.tsx +76 -0
  412. package/templates/blank/apps/web/src/shared/ui/require-capability.tsx +34 -0
  413. package/templates/blank/apps/web/vite.config.ts +5 -0
  414. package/templates/blank/deploy/nginx.conf +52 -0
  415. package/templates/blank/docs/ai/README.md +28 -2
  416. package/templates/blank/docs/ai/approvals.md +260 -0
  417. package/templates/blank/docs/ai/architecture.md +26 -0
  418. package/templates/blank/docs/ai/commenting.md +203 -0
  419. package/templates/blank/docs/ai/diagnostics.md +80 -0
  420. package/templates/blank/docs/ai/files.md +93 -0
  421. package/templates/blank/docs/ai/intelligence.md +348 -0
  422. package/templates/blank/docs/ai/ontology-context.md +59 -4
  423. package/templates/blank/docs/ai/primitives.md +34 -1
  424. package/templates/blank/docs/ai/project-structure.md +8 -3
  425. package/templates/blank/docs/ai/purchase-example.md +35 -7
  426. package/templates/blank/docs/ai/recipes.md +10 -2
  427. package/templates/blank/docs/ai/routing.md +86 -0
  428. package/templates/blank/docs/ai/troubleshooting.md +5 -0
  429. package/templates/blank/docs/ai/workflow.md +24 -11
  430. package/templates/blank/docs/errors/CAGE-AI-001.md +61 -0
  431. package/templates/blank/docs/errors/CAGE-APPR-001.md +13 -9
  432. package/templates/blank/docs/errors/CAGE-APPR-002.md +2 -2
  433. package/templates/blank/docs/errors/CAGE-APPR-003.md +1 -1
  434. package/templates/blank/docs/errors/CAGE-APPR-004.md +4 -4
  435. package/templates/blank/docs/errors/CAGE-APPR-005.md +4 -4
  436. package/templates/blank/docs/errors/CAGE-APPR-006.md +29 -8
  437. package/templates/blank/docs/errors/CAGE-APPR-007.md +9 -7
  438. package/templates/blank/docs/errors/CAGE-APPR-010.md +5 -5
  439. package/templates/blank/docs/errors/CAGE-AUDIT-001.md +53 -0
  440. package/templates/blank/docs/errors/CAGE-AUTH-001.md +1 -1
  441. package/templates/blank/docs/errors/CAGE-BIZ-001.md +51 -0
  442. package/templates/blank/docs/errors/CAGE-BIZ-002.md +49 -0
  443. package/templates/blank/docs/errors/CAGE-BUDGET-001.md +1 -1
  444. package/templates/blank/docs/errors/CAGE-BUDGET-002.md +1 -1
  445. package/templates/blank/docs/errors/CAGE-BUDGET-003.md +1 -1
  446. package/templates/blank/docs/errors/CAGE-CMD-002.md +1 -1
  447. package/templates/blank/docs/errors/CAGE-CMD-003.md +1 -1
  448. package/templates/blank/docs/errors/CAGE-CONN-001.md +3 -3
  449. package/templates/blank/docs/errors/CAGE-CONN-002.md +1 -1
  450. package/templates/blank/docs/errors/CAGE-CONN-003.md +1 -1
  451. package/templates/blank/docs/errors/CAGE-CONN-004.md +1 -1
  452. package/templates/blank/docs/errors/CAGE-CONN-005.md +1 -1
  453. package/templates/blank/docs/errors/CAGE-CONN-006.md +1 -1
  454. package/templates/blank/docs/errors/CAGE-CONN-007.md +6 -6
  455. package/templates/blank/docs/errors/CAGE-CONN-008.md +5 -5
  456. package/templates/blank/docs/errors/CAGE-CONN-009.md +6 -6
  457. package/templates/blank/docs/errors/CAGE-CONN-010.md +6 -6
  458. package/templates/blank/docs/errors/CAGE-CONN-011.md +1 -1
  459. package/templates/blank/docs/errors/CAGE-CONN-012.md +1 -1
  460. package/templates/blank/docs/errors/CAGE-CONN-013.md +49 -0
  461. package/templates/blank/docs/errors/CAGE-CONN-014.md +48 -0
  462. package/templates/blank/docs/errors/CAGE-CONN-015.md +49 -0
  463. package/templates/blank/docs/errors/CAGE-CREATE-001.md +10 -9
  464. package/templates/blank/docs/errors/CAGE-DECL-001.md +2 -2
  465. package/templates/blank/docs/errors/CAGE-DECL-002.md +7 -6
  466. package/templates/blank/docs/errors/CAGE-DECL-003.md +1 -1
  467. package/templates/blank/docs/errors/CAGE-DECL-004.md +1 -1
  468. package/templates/blank/docs/errors/CAGE-DEP-001.md +2 -2
  469. package/templates/blank/docs/errors/CAGE-DEP-002.md +1 -1
  470. package/templates/blank/docs/errors/CAGE-DEP-003.md +2 -2
  471. package/templates/blank/docs/errors/CAGE-DEP-004.md +1 -1
  472. package/templates/blank/docs/errors/CAGE-DEP-005.md +1 -1
  473. package/templates/blank/docs/errors/CAGE-DIAG-001.md +53 -0
  474. package/templates/blank/docs/errors/CAGE-DLQ-001.md +2 -2
  475. package/templates/blank/docs/errors/CAGE-ENV-001.md +4 -4
  476. package/templates/blank/docs/errors/CAGE-ENV-002.md +51 -0
  477. package/templates/blank/docs/errors/CAGE-ENV-003.md +48 -0
  478. package/templates/blank/docs/errors/CAGE-EVENT-001.md +1 -1
  479. package/templates/blank/docs/errors/CAGE-EVENT-002.md +7 -7
  480. package/templates/blank/docs/errors/CAGE-FIELD-001.md +2 -2
  481. package/templates/blank/docs/errors/CAGE-FIELD-002.md +1 -1
  482. package/templates/blank/docs/errors/CAGE-FIELD-003.md +1 -1
  483. package/templates/blank/docs/errors/CAGE-FIELD-004.md +1 -1
  484. package/templates/blank/docs/errors/CAGE-FILE-001.md +56 -0
  485. package/templates/blank/docs/errors/CAGE-GEN-001.md +2 -2
  486. package/templates/blank/docs/errors/CAGE-GEN-002.md +1 -1
  487. package/templates/blank/docs/errors/CAGE-GEN-003.md +53 -0
  488. package/templates/blank/docs/errors/CAGE-GRANT-001.md +3 -3
  489. package/templates/blank/docs/errors/CAGE-GRANT-002.md +2 -2
  490. package/templates/blank/docs/errors/CAGE-GRANT-003.md +7 -6
  491. package/templates/blank/docs/errors/CAGE-IMPACT-001.md +2 -2
  492. package/templates/blank/docs/errors/CAGE-IMPACT-002.md +52 -0
  493. package/templates/blank/docs/errors/CAGE-INIT-001.md +1 -1
  494. package/templates/blank/docs/errors/CAGE-INIT-002.md +1 -1
  495. package/templates/blank/docs/errors/CAGE-INIT-003.md +2 -2
  496. package/templates/blank/docs/errors/CAGE-INIT-004.md +1 -1
  497. package/templates/blank/docs/errors/CAGE-INIT-005.md +52 -0
  498. package/templates/blank/docs/errors/CAGE-JOB-001.md +1 -1
  499. package/templates/blank/docs/errors/CAGE-JOB-002.md +1 -1
  500. package/templates/blank/docs/errors/CAGE-JOB-003.md +1 -1
  501. package/templates/blank/docs/errors/CAGE-LINT-001.md +1 -1
  502. package/templates/blank/docs/errors/CAGE-MIG-001.md +1 -1
  503. package/templates/blank/docs/errors/CAGE-MIG-002.md +1 -1
  504. package/templates/blank/docs/errors/CAGE-MIG-005.md +1 -1
  505. package/templates/blank/docs/errors/CAGE-NAME-001.md +1 -1
  506. package/templates/blank/docs/errors/CAGE-NAME-002.md +1 -1
  507. package/templates/blank/docs/errors/CAGE-NAME-003.md +3 -3
  508. package/templates/blank/docs/errors/CAGE-NAME-004.md +1 -1
  509. package/templates/blank/docs/errors/CAGE-NAME-005.md +1 -1
  510. package/templates/blank/docs/errors/CAGE-NAME-006.md +1 -1
  511. package/templates/blank/docs/errors/CAGE-ORG-001.md +7 -6
  512. package/templates/blank/docs/errors/CAGE-PAIR-002.md +6 -5
  513. package/templates/blank/docs/errors/CAGE-QUERY-001.md +1 -1
  514. package/templates/blank/docs/errors/CAGE-QUERY-002.md +2 -2
  515. package/templates/blank/docs/errors/CAGE-QUERY-003.md +7 -6
  516. package/templates/blank/docs/errors/CAGE-REACT-001.md +3 -3
  517. package/templates/blank/docs/errors/CAGE-REACT-002.md +1 -1
  518. package/templates/blank/docs/errors/CAGE-REACT-003.md +50 -0
  519. package/templates/blank/docs/errors/CAGE-READS-001.md +9 -6
  520. package/templates/blank/docs/errors/CAGE-REG-001.md +13 -12
  521. package/templates/blank/docs/errors/CAGE-REG-002.md +2 -1
  522. package/templates/blank/docs/errors/CAGE-REG-003.md +1 -1
  523. package/templates/blank/docs/errors/CAGE-REL-001.md +14 -14
  524. package/templates/blank/docs/errors/CAGE-ROUTE-001.md +7 -6
  525. package/templates/blank/docs/errors/CAGE-SCOPE-001.md +1 -1
  526. package/templates/blank/docs/errors/CAGE-SCOPE-002.md +2 -2
  527. package/templates/blank/docs/errors/CAGE-SECRET-001.md +2 -2
  528. package/templates/blank/docs/errors/CAGE-SECRET-002.md +1 -1
  529. package/templates/blank/docs/errors/CAGE-SENS-001.md +5 -5
  530. package/templates/blank/docs/errors/CAGE-SQL-001.md +1 -1
  531. package/templates/blank/docs/errors/CAGE-SQL-002.md +1 -1
  532. package/templates/blank/docs/errors/CAGE-STATE-001.md +3 -3
  533. package/templates/blank/docs/errors/CAGE-STATE-002.md +1 -1
  534. package/templates/blank/docs/errors/CAGE-STATE-003.md +1 -1
  535. package/templates/blank/docs/errors/CAGE-STATE-004.md +1 -1
  536. package/templates/blank/docs/errors/CAGE-STATE-005.md +3 -2
  537. package/templates/blank/docs/errors/CAGE-STATE-010.md +5 -5
  538. package/templates/blank/docs/errors/CAGE-STATE-011.md +5 -5
  539. package/templates/blank/docs/errors/CAGE-STRUCT-001.md +1 -1
  540. package/templates/blank/docs/errors/CAGE-STRUCT-002.md +1 -1
  541. package/templates/blank/docs/errors/CAGE-SYNC-001.md +3 -2
  542. package/templates/blank/docs/errors/CAGE-TEST-001.md +1 -1
  543. package/templates/blank/docs/errors/CAGE-TEST-002.md +50 -0
  544. package/templates/blank/docs/errors/CAGE-TEST-003.md +52 -0
  545. package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +3 -2
  546. package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +2 -2
  547. package/templates/blank/docs/errors/CAGE-WORKER-001.md +48 -0
  548. package/templates/blank/docs/errors/CAGE-WORKER-002.md +50 -0
  549. package/templates/blank/docs/errors/CAGE-WORKER-003.md +48 -0
  550. package/templates/blank/docs/errors/README.md +52 -2
  551. package/templates/blank/docs/examples/purchase-admin/apps/api/src/main.ts +5 -1
  552. package/templates/blank/docs/examples/purchase-admin/apps/api/src/worker.ts +3 -0
  553. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/app.tsx +122 -12
  554. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/styles/global.css +88 -8
  555. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/use-session.ts +43 -0
  556. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/workspace-layout.tsx +58 -19
  557. package/templates/blank/docs/examples/purchase-admin/apps/web/src/main.tsx +5 -0
  558. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/components/task-operation-dialog.tsx +61 -0
  559. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +13 -5
  560. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/index.ts +4 -0
  561. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +89 -38
  562. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks.css +18 -0
  563. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/index.ts +4 -0
  564. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/pages/login-page.tsx +12 -0
  565. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/index.ts +4 -0
  566. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/pages/inventory-page.tsx +29 -1
  567. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/approval-history.tsx +67 -0
  568. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
  569. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/order-reviewers.tsx +38 -0
  570. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
  571. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
  572. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +32 -3
  573. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/index.ts +5 -0
  574. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
  575. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-intelligence.css +17 -0
  576. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +156 -0
  577. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +54 -22
  578. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/index.ts +5 -0
  579. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
  580. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/hooks/use-command.ts +13 -0
  581. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +15 -1
  582. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/navigation.ts +21 -0
  583. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/approval-member-picker.css +10 -0
  584. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/approval-member-picker.tsx +51 -0
  585. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
  586. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.css +134 -0
  587. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
  588. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
  589. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.css +28 -0
  590. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
  591. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/notice.tsx +7 -0
  592. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-heading.tsx +7 -0
  593. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.css +47 -0
  594. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.tsx +76 -0
  595. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/require-capability.tsx +34 -0
  596. package/templates/blank/docs/examples/purchase-admin/cage.config.json +23 -0
  597. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/approval-member/index.ts +70 -0
  598. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/dept/index.ts +10 -10
  599. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory/index.ts +5 -5
  600. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory-lock/index.ts +4 -4
  601. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +34 -12
  602. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/role/index.ts +15 -15
  603. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/user/index.ts +16 -16
  604. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +16 -1
  605. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/queries/index.ts +2 -2
  606. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/index.ts +4 -0
  607. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/erp.ts +15 -0
  608. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/intelligence.ts +20 -0
  609. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/index.ts +1 -0
  610. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/inventory.ts +12 -0
  611. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approval-members.ts +54 -0
  612. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approvals.ts +38 -6
  613. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +2 -0
  614. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/intelligence.test.ts +224 -0
  615. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/jobs.ts +5 -0
  616. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.test.ts +9 -0
  617. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +125 -4
  618. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/queries.ts +5 -0
  619. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-inventory.ts +6 -0
  620. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-process.ts +42 -0
  621. package/templates/blank/package.json +3 -3
  622. package/templates/blank/packages/contracts/package.json +1 -1
  623. package/templates/blank/packages/contracts/src/aggregates/dept/index.ts +10 -10
  624. package/templates/blank/packages/contracts/src/aggregates/role/index.ts +15 -15
  625. package/templates/blank/packages/contracts/src/aggregates/user/index.ts +16 -16
  626. package/templates/blank/packages/contracts/src/index.ts +1 -1
  627. package/templates/blank/packages/contracts/src/queries/index.ts +1 -1
  628. package/templates/blank/packages/domain/package.json +5 -4
  629. package/templates/blank/packages/domain/src/index.ts +2 -1
@@ -25,16 +25,28 @@
25
25
  | 1 | [架构与执行模型](architecture.md) | 聚合是什么?为什么写入必须走命令?数据库由谁连接? |
26
26
  | 2 | [工程目录与代码组织](project-structure.md) | 新业务放哪里?页面如何拆分?哪些依赖会被门禁阻止? |
27
27
  | 3 | [原语与最小业务](primitives.md) | 如何新增字段、CRUD 命令、读依赖、事件和查询? |
28
+ | 编码必读 | [详细中文注释规范](commenting.md) | 如何说明文件职责、API、字段、关键流程、权限/事务与失败边界,并同步维护注释? |
28
29
  | 开发前 | [本体查询与 AI 上下文](ontology-context.md) | 按需求查哪些代码?为什么关联?候选、证据与子图边界怎么判断? |
30
+ | 开发与排错 | [能力发现与状态诊断](diagnostics.md) | 公开 API 有什么?注册/契约/进程哪里过期?如何查执行时间线和授权拒绝? |
29
31
  | 按需 | [对象关系](relations.md) | 如何在 fields 中声明一对一、一对多、多对多,修改关联并分页读取? |
32
+ | 复杂审批 | [审批流转、并行与流程时效](approvals.md) | 如何声明 AND 并行与汇合,按字段选人、候选领取、转办/委派/加签,并使用框架节点时限、站内提醒、催办和已读? |
33
+ | 前端必读 | [业务路由与浏览器验收](routing.md) | 列表/详情如何获得独立 URL?登录回跳、404、/admin 和部署回退怎样验收? |
34
+ | 原生 AI | [智能助理与 AI 审批](intelligence.md) | 如何启用后端、配置三态审核、生成工具、传入页面快照和接入 SDK? |
30
35
  | 4 | [标准采购范例导读](purchase-example.md) | 一次提交如何进入审批、锁库存、推 ERP、释放资源? |
31
36
  | 5 | [开发步骤](workflow.md) | 改哪个文件?运行哪些命令?检查结果在哪里? |
32
37
  | 6 | [业务任务配方](recipes.md) | 如何从采购演示换成自己的业务?常见需求如何交给 AI? |
33
38
  | 7 | [业务页导入导出](transfers.md) | 如何提交任务、准备 CSV、查询状态、下载和展示报告? |
34
39
  | 8 | [排错方法](troubleshooting.md)、[错误码册](../errors/README.md) | 如何区分配置、权限、业务失败和异步死信? |
40
+ | 按需 | [文件字段与断点续传](files.md) | 私有上传、分片恢复、命令绑定、下载授权和存储部署 |
35
41
 
36
42
  第一次先读架构、目录规范和原语,再沿范例读代码。接到业务需求后先运行 `pnpm exec cage context "需求关键词"`,确认候选入口,再按源码位置阅读对应实现。
37
43
 
44
+ 框架源码与脚手架应用都要求详细中文注释。新建或修改代码时按[注释规范](commenting.md)同步说明文件职责与调用链、导出 API/类型字段、组件/hooks 和关键流程的“做什么、为什么、怎么做、边界”;修改既有行为时连同相关上下游说明一起更新。注释属于交付内容,不能用“代码自解释”免除,也不能以逐行翻译或注释字数代替质量。
45
+
46
+ 不确定框架支持什么时先用 `pnpm exec cage capabilities 关键词 --format json` 查看当前版本公开签名;功能未生效时用 `pnpm exec cage doctor` 区分注册、生成、构建、迁移、授权和实际进程。未检查项为 `unknown`,不能作为验证通过。
47
+
48
+ 遇到 AI 审批、业务助理、随页助理、模型管理、性格或 Responses 需求,先读[原生智能化指南](intelligence.md)。这些是框架可选能力:后端循环、工具、会话与偏好记忆、HTTP 和 SDK 由框架提供;应用配置声明、策略、授权、页面快照及界面。入口不要求每次加载整份本体或全部指南,按本次任务读取相关章节即可。
49
+
38
50
  ## 按任务找入口
39
51
 
40
52
  | 用户需求 | 优先修改 | 需要一起考虑 |
@@ -42,11 +54,18 @@
42
54
  | 增加业务对象、字段 | `packages/domain/src/modules/<业务>` | 模块公开入口、范围字段、不变量、契约、迁移、角色授权、图谱中文名 |
43
55
  | 增加对象关联 | `fields` 的 ref / hasMany / manyToMany;见[关系指南](relations.md) | 归属命令、双侧权限与范围、目标分页、迁移;纯关联不手写中间表聚合 |
44
56
  | 增加操作按钮 | 领域命令 + `apps/web/src/modules/<业务>` | 状态迁移、调用身份、错误展示、提交幂等键 |
57
+ | 增加列表、详情或新页面 | 模块 pages + app 路由表 | URL、查询条件、深链接、刷新、前进后退、登录回跳;见[路由指南](routing.md) |
45
58
  | 增加报表 | 所属领域模块 `queries.ts` | `reads`、`safe.*`、参数化、调用人 read 权限 |
46
- | 修改审批顺序/条件/选人 | 所属领域模块 `approvals.ts` | `routable`、角色/负责人数据、结论命令约束 |
59
+ | 修改审批顺序/条件/并行/选人 | 所属领域模块 `approvals.ts` | `parallel/branch` 的 AND 汇合与完整 currentSteps、`routable`、`approver.field` 的 UUID/数组、角色/负责人数据、同租户 active 用户及结论命令约束;见[任务流转](approvals.md) |
60
+ | 候选领取、转办、委派和前后加签 | 人工 `step` 的 `assignment/actions` + 客户端任务接口 | 候选规则与权限实时检查、waiting 依赖、任务 revision、旧实例快照、系统迁移;Admin/采购已有领取、释放、归还,采购还提供协作名录选人、转办/委派/三种加签及分页人工历史 |
61
+ | 节点时限、流程提醒与申请人催办 | `step.sla`、`route.reminders` + 导出的 `approvalOperations()` | 自然分钟、逐节点开启计时、同实例共享催办冷却;并行催办携带 expectedSteps;沿用框架 Admin 申请/提醒页或 SDK,见[流程时效](approvals.md) |
62
+ | AI 预审、退回修改、转人工 | 现有 `step` 的 `kind: 'ai'` + `approval` 绑定 | 策略、取证字段/查询、`automatedBy` 角色、结论命令及 `handoff`;见[智能化指南](intelligence.md) |
63
+ | 业务助理、随页悬浮窗 | domain 导出 `ai()`;页面接 `useAssistant` 与 `useAiPageContext` | 业务权限、页面快照、流式 Markdown、写入确认;界面由应用实现 |
64
+ | 模型动态配置、Responses、性格 | `managedModel` 与框架 Admin 页面 | 部署加密密钥、管理权限、实际网关能力、性格仅影响表达 |
47
65
  | 取消后释放占用 | `workflows/<相关业务>.ts` + 领域事件/命令 | 所有离开持有状态的路径、同事务/异步选择 |
48
66
  | 接 ERP 或其他系统 | `integrations/<系统名>.ts` | schema、密钥名、白名单、幂等、回调验签、重试 |
49
67
  | 业务页导入/导出 | 业务前端调用已有接口 | 任务状态、worker、权限、导入目标命令;不固定到系统管理页 |
68
+ | 文件上传/业务附件 | file/files 字段 + 用户命令 + 客户端上传任务 | 断点续传、当前权限、命令绑定、私有存储及清理;见[文件指南](files.md) |
50
69
  | 新业务没出现在图或 API | domain 统一入口 | 顶层 `export const`、导出名唯一、入口 re-export |
51
70
  | 框架无法表达业务 | 先核对公开导出与范例 | 说明能力缺口;不要编造 API 或把业务分支塞进内核 |
52
71
 
@@ -68,9 +87,16 @@
68
87
  | 聚合/命令、能力与范围、掩码、审计、outbox、worker | handler 不做数据库/网络 IO;生产角色不会自动拿到新能力 |
69
88
  | fields 中的 ref / hasMany / manyToMany | hasMany 为只读反查;manyToMany 自动中间表并随主对象事务写入,公开读取独立分页;双向集合不会自动互为镜像 |
70
89
  | 本体抽取、中文检索/节点/路径/AI 上下文、图规则、图谱、生成、影响分析与门禁 | 上下文注明证据、源码和覆盖边界;名称与测试匹配是候选线索,不能证明任意 JS 正确;跳过用例仍需补足 |
71
- | 代码审批路由与适配接口 | 顺序步骤、条件步骤、步骤内任一/全部审批;没有通用可视化流程设计器、任意 JS 选人、转签/加签 API |
90
+ | 有界集合 reactionEach、显式步骤 order | 稳定唯一键排序后串行调用目标命令;同事务整体回滚,异步链按 outbox 恢复;不是并行写表接口 |
91
+ | capabilities、doctor、timeline、explain、snapshot | 实际运行诊断需要受控会话与权限;未取得的证据为 unknown,授权解释不执行 handler |
92
+ | 代码审批路由与任务流转 | 顺序/条件、`parallel/branch` 结构化 AND 分支与汇合、any/all、字段选人、候选领取/释放、转办、单层委派归还、前后/并行必签和动作历史;候选池仅支持 any,追加票全部必签。条件和依赖随提交冻结,currentStep 仅为最小活动索引;尚无任意连线/循环/OR 网关、岗位/代理规则、通用恢复、任意 JS 选人或在途迁移,见[任务流转](approvals.md) |
93
+ | 审批时限、站内提醒与催办 | 人工节点按实际开启时间计算自然分钟 SLA,worker 持久投递临期/超时提醒;申请人可按完整活动集合催办,同实例共享冷却,接收人可标已读。旧快照不自动获得政策;尚无工作日历、自动升级、抄送或邮件/短信通知 |
94
+ | 审批界面与 SDK | Admin/采购待办可领取、释放、归还受托任务并查看等待加签;采购另有协作名录选人器、转办/委派/三种加签及分页人工历史,view 查询参数保留视图。启用运营后通用 Admin 提供我的申请、催办和流程提醒;页面仍需应用启用、真实授权与浏览器验收。AI 助理目前只查询本人待办及提交决定,无人员管理写工具 |
95
+ | 原生 AI 审批与领域助理 | 现有 `step` 支持 `kind: 'ai'`;三态审核、自动工具、会话及偏好记忆可复用;需显式启用、授权并做模型质量验收 |
96
+ | Admin 模型与性格、助理 SDK | 动态模型连接和性格管理;Chat Completions / Responses 兼容性以实际服务为准;SDK 提供流式状态与页面快照,悬浮窗和 Markdown 由应用实现 |
72
97
  | 连接器 fake、出站、入站验签、同步记录 | fake 不等于真实 ERP 联调,也不等于完整请求录制/回放平台 |
73
98
  | 异步 CSV 导入/导出接口与客户端任务查询 | 界面由业务项目决定;导出结果不是可直接回导的命令输入模板 |
99
+ | 私有文件字段、流式分片上传、暂停与续传、范围下载 | 默认本地存储,提供对象存储适配接口;尚无内置 S3/OSS、签名直传、病毒扫描及文件共享 |
74
100
  | 组织模型、系统管理界面 | 暂无移动部门(改上级)的完整支持、菜单配置页 |
75
101
  | 库存锁采购范例 | 演示资源生命周期;不是仓库级并发库存扣减、退货或 ERP 撤销补偿系统 |
76
102
 
@@ -0,0 +1,260 @@
1
+ # 审批任务流转、并行分支与流程时效
2
+
3
+ [返回学习入口](README.md) · [审批原语](primitives.md) · [AI 审批](intelligence.md)
4
+
5
+ 本页描述 Cage 原生审批引擎的顺序/条件/结构化 AND 并行、字段选人、候选领取/释放、转办、委派归还、前后/并行必签、操作记录,以及框架通用的自然分钟时限、站内提醒和申请人催办。它参考 Flowable 的任务责任划分和并行汇合语义,不表示支持全部 BPMN 或与 Flowable XML 兼容。
6
+
7
+ ## 声明选人和节点操作
8
+
9
+ 人工步骤默认 `assignment: 'direct'`,为每位选中的人分别建立已分配任务。`mode: 'any'` 表示至少一位原审批人通过,`mode: 'all'` 表示全部原审批人通过。转办、委派和加签通过 `actions` 逐项开放,未写的动作关闭。
10
+
11
+ 以下是局部步骤片段,需放进应用已经导出的 `route`,并与自己的 `approval` 绑定配合:
12
+
13
+ ```ts
14
+ import { approver, step } from '@yss123/cage-approval';
15
+
16
+ // 为角色中的每位审批人直派一票;任一原票通过后仍需等待所有追加的必签票。
17
+ step('部门审核', approver.role('reviewer'), {
18
+ mode: 'any',
19
+ actions: { transfer: true, delegate: true, addSign: true },
20
+ });
21
+
22
+ // reviewers 必须是本聚合的公开字段并列入 approval.routable;领取成功不产生新的业务权限。
23
+ step('专业审核', approver.field('reviewers'), {
24
+ assignment: 'candidate',
25
+ actions: { transfer: true, delegate: true, addSign: true },
26
+ });
27
+ ```
28
+
29
+ `assignment: 'candidate'` 只创建一项 `assigneeId: null` 的共享任务,候选人必须先领取才能决定。它独立开放 `claim/unclaim`,无需在 `actions` 中增加字段;即使没有其他动作政策也能领取/释放。候选池只支持 `any`,`candidate + all` 在声明时拒绝;逐人会签使用默认的 `direct`。
30
+
31
+ 流程启动时保存选人规则、分配方式和动作政策的步骤快照。新 `step` 在 `actions.addSign: true` 时自动记录 `signPositions: ['parallel', 'before', 'after']`,应用无需另传签序配置。修改代码不会改变在途实例政策,也不会把旧直派任务合并为候选池。角色和部门规则在候选列表及领取时查询当前组织数据,字段选人使用提交时保存的路由变量;规则快照不等于冻结一份候选成员名单。AI 步骤的人工接管仍使用原来的直派方式,不开放任务管理动作。
32
+
33
+ ### 按单据字段选人
34
+
35
+ `approver.field('reviewers')` 支持单个 UUID 字符串或原数组长度为 1–200 的 UUID 数组,重复人员去重。字段必须存在、不是 hidden,并列入对应 `approval.routable`;不满足时声明检查报 `CAGE-APPR-001`。数组可用 `list(id())` 声明,单人可用已有的 UUID 或用户引用字段;选人器不执行任意 JS、SQL 或字符串表达式。
36
+
37
+ 字段缺失或为 `null` 时解析为空候选,开启节点报 `CAGE-APPR-007`;空数组、非法 UUID、数组中包含非字符串或超过 200 项报 `INVALID_INPUT`。开启字段选人或候选节点时,所有选中的 ID 必须属于当前租户且账号 active,否则整批失败,不静默去掉无效人员或默认批准。旧的固定用户/部门负责人直派规则保持原有开启行为。
38
+
39
+ 开启节点的账号校验不会替用户授予批准/read 能力或数据范围。领取、转办、委派、加签和实际决定仍按当时的权限核验;配置了有效用户也不代表其最终额度、职责分离等业务硬约束一定满足。
40
+
41
+ ## 结构化并行分支与 AND 汇合
42
+
43
+ `parallel(title, ...branches)` 声明同时推进的分支组,`branch(title, ...nodes)` 声明其中一条具名分支。分支内部可以有多个顺序步骤、条件和嵌套并行组;所有实际展开的分支都完成后,才开启组后面的节点。下例是应用路由片段,需要从 domain 入口导出,并绑定自己的 `approval`;`requiresLegal` 必须列入该绑定的 `routable`,角色与相应业务权限由应用明确配置。
44
+
45
+ ```ts
46
+ import { approver, branch, eq, parallel, route, step, when } from '@yss123/cage-approval';
47
+
48
+ /**
49
+ * 材料审核后同时推进业务与专业两条线;专业线的法务条件在提交时求值。
50
+ * 各线均完成才创建最终确认待办,结论仍由 approval 绑定的领域命令落实。
51
+ */
52
+ export const documentRoute = route('document-review', [
53
+ step('材料审核', approver.role('reviewer')),
54
+ parallel('联合审查',
55
+ branch('业务线',
56
+ step('业务复核', approver.role('business-reviewer')),
57
+ step('预算核对', approver.role('budget-reviewer')),
58
+ ),
59
+ branch('专业线',
60
+ step('专业评估', approver.role('specialist')),
61
+ when(eq('requiresLegal', true),
62
+ step('法务审查', approver.role('legal-reviewer')),
63
+ ),
64
+ ),
65
+ ),
66
+ step('最终确认', approver.role('final-reviewer')),
67
+ ]);
68
+ ```
69
+
70
+ 业务复核通过后即可进入预算核对,无需等待专业评估;专业线也独立前进。只有两条线均通过,最终确认才出现。节点内 `mode: 'all'` 是同一节点的多人会签,`addSign` 的 `placement: 'parallel'` 是同一节点的追加必签,两者都不会创建流程分支;它们可以继续用于某条分支中的人工节点。
71
+
72
+ 条件只在实例启动时依据提交变量求值,执行中不重新读取单据来改变路线。声明中的容器不能为空;如果某条分支的全部条件均不满足,展开后该分支直接通过汇合,不生成虚假任务。如果整个路由没有展开出任何办理节点,则明确拒绝启动。每个并行组要求 2–16 条名称不重复的分支;整份声明最多 128 个人工/AI 办理节点、512 个结构节点和 8 层容器。条件不满足不会绕过声明结构校验。
73
+
74
+ 拒绝、退回或取消结束整个审批轮次,关闭其他分支中的活动节点和 pending/waiting 任务;尚未开启的后续节点不再创建。正常推进在实例锁内检查持久前驱状态,节点唯一键防止并发分支重复创建同一汇合后继。若同一次启动或推进中的任一新节点无法开启,整个本次事务回滚,不留下部分成功的分支入口。已经在较早事务中通过的票仍保留。
75
+
76
+ 最终业务结论仍以实际推进完成的办理人身份调用领域命令。并行组后没有明确的最终审批节点时,最后完成分支的人可能承担该身份;额度、职责分离或状态约束不满足会回滚本次决定。需要固定最终责任人时,应像上例一样在 AND 汇合后声明明确的最终节点。
77
+
78
+ ### 快照、历史和界面定位
79
+
80
+ 执行计划保存在既有 `flow.approval_instance.steps` JSON 中,每个叶子步骤附带 `execution.schema/dependsOn/branchPath/definitionVersion`。`dependsOn` 是本实例内的前驱索引,全部前驱 approved 才能开启当前节点;数组中的声明遍历顺序不是实际完成顺序。`branchPath` 按外层到内层记录并行组及分支名称,普通主线为空数组。无需为这次并行能力新增 DDL 迁移;仍需完成当前版本已发布的 AI、任务流转和时效迁移,并让 API/worker 使用同一版本。
81
+
82
+ `definitionVersion` 是流程名、路由节点和催办政策等路由声明的 SHA256 内容指纹,不包含领域命令实现。它用于识别实例启动时保存的路线,不能替代完整的定义发布、版本回滚、领域命令版本绑定或在途迁移。代码更新不重算已有实例的依赖和政策;没有 `execution` 的历史快照仍按相邻顺序执行,历史版本指纹为 null,不追溯伪造。
83
+
84
+ 任务摘要提供 `branchPath`;`client.approvalHistory(aggregate, id)` 提供 `currentSteps`、`definitionVersion` 及各步骤的 `branchPath/dependsOn`,仍遵守当前单据与详情读取权限。`currentSteps` 是完整活动节点集合,包含排队、运行、人工接管和待诊断的失败节点;只有通过状态满足后继依赖。`currentStep` 只保留最小活动索引作为旧客户端摘要,不能代表整轮只有一个节点,也不能据此判断其他分支是否前进。申请列表另有 `activeSteps`,提供各活动节点的名称、截止时间和分支路径。
85
+
86
+ `cage graph` 递归展示条件和 AND 分叉/汇合;节点编号只定位声明,图中分列的分支才表达并发关系。它展示已声明的结构,不是运行时设计器,也不直接证明某个实例已完成。当前只支持这种有界结构树,不支持任意连线、循环、OR/包容网关、事件竞争、指定节点跳转或在途实例迁移。
87
+
88
+ ## 迁移和部署
89
+
90
+ 通过应用原有 `pnpm migrate` 执行系统迁移,再将 API 与 worker 切换到同一版本:
91
+
92
+ | 系统迁移 | 数据含义 |
93
+ | --- | --- |
94
+ | `cage:approval_task_actions_001` | 任务 revision、委派责任、original/additional 和追加式动作历史;旧任务保持 original、revision=0 |
95
+ | `cage:approval_task_stages_002` | 新增 assignment、父任务和签序;仅候选任务允许持有人为空,旧任务保持 direct |
96
+ | `cage:approval_deadlines_003` | 节点截止/临期/扫描时间、实例催办政策与冷却、持久站内提醒及已读;旧值为 null,不自动开始计时 |
97
+
98
+ 已发布的审批 DDL 和旧迁移没有改写。旧原票及旧版并行加签的 `parentTaskId/signPosition` 为空;升级不伪造旧签序或历史操作。升级后新创建的加签票保存父任务和签序。旧快照不会自动增加 actions、assignment 或 signPositions;升级前已经保存 `addSign: true` 但没有 signPositions 的节点只允许 parallel,before/after 返回 FORBIDDEN。没有 addSign 政策的旧实例仍完全禁止加签。不能把旧库基线测试中可创建直派任务理解为支持新版 API/worker 在未迁移数据库上运行。
99
+
100
+ ## 六种操作的区别
101
+
102
+ | 操作 | 结果 | 边界 |
103
+ | --- | --- | --- |
104
+ | claim 领取 | 未分配候选任务归当前用户处理,离开可领取列表 | 实时检查候选资格、active、批准/read 和单据范围;一个任务只能有一位持有人 |
105
+ | unclaim 释放 | 当前持有人清空分配,任务重新进入候选池 | 仅 candidate;委派未归还或存在未完成子票时拒绝;保留已完成子票和历史 |
106
+ | transfer 转办 | 接收人成为当前审批人,原审批人失去该任务决定权 | 双方须有单据 read/范围及批准能力;不转移角色授权 |
107
+ | delegate 委派 | 保存原负责人,将待办交受托人处理 | 受托人只能 resolve;不能批准、拒绝、退回、再次转办/委派/加签或释放 |
108
+ | resolve 归还 | 返回服务端保存的原负责人,等待其审批 | 不推进节点;原负责人停用或失去批准/read 时拒绝 |
109
+ | addSign 加签 | 当前节点添加独立必签任务,按 placement 控制签署顺序 | 仅原始任务可发起,每次 1–20 人、每节点累计最多 20 人;不创建新流程节点 |
110
+
111
+ 领取后移出候选角色不会自动取消已经承担的任务责任。只要仍有当前批准/read 权限和单据范围,该持有人可以正常决定或释放;失去这些业务权限后会拒绝操作。候选任务可以在动作政策允许时转办给有业务权限的非候选人,转办后仍保留 candidate 属性,新持有人也能按规则释放。没有管理员强制释放或无可用人员的通用恢复入口,不能在文档中以直接改表代替恢复功能。
112
+
113
+ 接收人不能是本人或同节点其他任务的当前/保留负责人,包括已经决定的人。候选领取也不能领取本人已经承担另一票的节点原票;例如完成前签的人不能在原票被释放后再领原票。转办或释放不能把独立会签名额压缩为同人多票。
114
+
115
+ ## 前签、后签和并行必签
116
+
117
+ `addSign` 的 `placement` 省略时为 `parallel`,已有客户端保持原来的并行含义。请求的位置还必须包含在当前实例的 signPositions 中,客户端不能仅凭新版声明替旧实例开放前后签。同一次追加的多位签署人彼此并行,不表示按 `userIds` 顺序逐人串签。
118
+
119
+ | placement | 创建时 | 何时恢复或激活 |
120
+ | --- | --- | --- |
121
+ | `parallel` | 原票和新加签票均可处理 | 原票通过仍须等待全部追加票 |
122
+ | `before` | 父任务变为 waiting,新加签票为 pending | 全部前签批准后,仍在 waiting 的父任务恢复为 pending |
123
+ | `after` | 父任务可处理,新加签票为 waiting | all 等自己的父票批准;any 等本节点任意原票批准 |
124
+
125
+ waiting 任务只能查看,不能决定或执行任务管理动作。前签完成恢复父票、后签从 waiting 激活为 pending 时都会增加该任务的 revision;原来等待页面保存的版本不可直接提交。
126
+
127
+ `any` 需要至少一张原票和全部追加票通过。其他原审批人先批准时,其余 pending/waiting 原票会 skipped,已经创建的前签、并行签、后签全部保留为必签;全部 waiting 后签此时激活。前签随后完成不会复活已经 skipped 的父票。`all` 需要全部原票和追加票通过,每张父票只激活自己的后签。
128
+
129
+ 任一当前可决定的任务拒绝或退回,会调用原有领域结论命令;成功后关闭同轮次剩余 pending 和 waiting。取消或重新提交也会关闭旧轮次两种状态的任务。不能通过释放仍带未完成前/后/并行子票的候选任务来丢弃必签责任。
130
+
131
+ 最终推进流程的实际决定人必须通过领域结论命令的额度、职责分离、状态和版本约束。后签人可能成为最终签署人;若其额度不足,最后决定、版本、阶段变化及本次历史共同回滚,之前已提交的父票保留。引擎不会自动改用更早审批人的身份。
132
+
133
+ ## 客户端调用
134
+
135
+ ```ts
136
+ import { client } from '@app/contracts';
137
+
138
+ const candidates = await client.approvalCandidateTasks();
139
+ if (candidates.ok && candidates.data.length) {
140
+ const task = candidates.data[0];
141
+ // 展示候选不代表任务已被占用;服务端在领取事务中再次检查候选规则、权限和版本。
142
+ const claimed = await client.approvalTaskAction(task.id, {
143
+ action: 'claim', expectedRevision: task.revision, reason: '由我负责核查材料',
144
+ });
145
+ if (claimed.ok) {
146
+ // 领取已增加任务版本,后续界面读取本人待办并使用新版本;此处不自动替用户批准。
147
+ await client.approvalTasks();
148
+ }
149
+ }
150
+ ```
151
+
152
+ 其他已提供的调用如下,目标用户 ID 由应用选人界面提供,不在页面写死员工 ID:
153
+
154
+ - `client.approvalTasks()` 读取本人 pending;`client.approvalTasks('waiting')` 查看等待签署依赖的本人任务。
155
+ - `client.approvalCandidateTasks()` 读取当前可领取的共享任务,不把它们混入本人的可决定清单。
156
+ - `approvalTaskAction(id, { action: 'claim' | 'unclaim' | 'resolve', expectedRevision, reason })` 不接受目标用户字段。
157
+ - 转办/委派为 `{ action: 'transfer' | 'delegate', targetUserId, expectedRevision, reason }`。
158
+ - 加签为 `{ action: 'addSign', userIds, placement?: 'parallel' | 'before' | 'after', expectedRevision, reason }`;目标数组不能重复。
159
+ - `client.decideApprovalTask(id, 'approve' | 'reject' | 'return', { expectedRevision, comment? })` 提交审批决定。
160
+ - `client.approvalTaskHistory(process, aggregate, id, { after?, limit? })` 返回 `items/nextCursor`;默认 50,最多 200 条。
161
+
162
+ 摘要中的 `assigneeId` 是当前持有人,未领取时为 null;`assignment` 区分 direct/candidate,`parentTaskId/signPosition` 表示加签来源和顺序,`signPositions` 提供本实例允许发起的签序,`delegation: 'pending'` 表示只能归还。`actions/signPositions` 仅提示实例开放的管理政策,不能代替当前用户权限或任务状态校验。
163
+
164
+ 任务 `revision` 与单据 `version` 不同。candidate 节点或启用了任一任务管理动作的节点,决定也必须携带 `expectedRevision`;其他旧直派节点保留不带版本的引擎/HTTP 兼容调用,SDK 始终要求版本。领取、释放、转办、决定、激活或关闭任务都会使相应版本递增。冲突后重新读取并让用户核对;接口没有跨请求成功回执缓存,超时不表示服务端未提交,不可盲目重发。
165
+
166
+ 助理的 `approval_tasks` 只查询本人 pending 待办,`approval_decide` 可以保存并提交读取到的 `expectedRevision`,决定时仍检查委派状态、归属和权限。助理目前没有候选领取/释放、转办、委派归还或加签的管理写工具;这些功能由页面直接调用 SDK。
167
+
168
+ ## HTTP、可见性与操作记录
169
+
170
+ | HTTP | 输入/行为 |
171
+ | --- | --- |
172
+ | GET `/api/approval/tasks` | `status` 默认 pending,可用 waiting 查看本人等待任务 |
173
+ | GET `/api/approval/candidate-tasks` | 当前未领取、规则和权限均符合的任务 |
174
+ | POST `/api/approval/tasks/:id/claim`、`unclaim` | `expectedRevision/reason` |
175
+ | POST `/api/approval/tasks/:id/transfer`、`delegate` | `targetUserId/expectedRevision/reason` |
176
+ | POST `/api/approval/tasks/:id/resolve` | `expectedRevision/reason` |
177
+ | POST `/api/approval/tasks/:id/add-sign` | `userIds/placement?/expectedRevision/reason` |
178
+ | POST `/api/approval/tasks/:id/approve`、`reject`、`return` | `expectedRevision/comment` |
179
+ | GET `/api/approval/task-history/:process/:aggregate/:id` | `after` 记录 ID 字符串,`limit` 分页大小 |
180
+
181
+ 所有写入沿用会话与 CSRF。意见/原因最多 1000 字,管理动作原因去首尾空白后必须非空;未知字段、伪造 action 和非法 placement 拒绝。任务不在当前租户、不是本人持有,或领取时已经归别人,返回 NOT_FOUND;策略未开放、候选资格或能力不符返回 FORBIDDEN;仍可操作的任务版本过期返回 CONFLICT;waiting、已关闭、委派状态不允许或非当前步骤返回 INVALID_TRANSITION。并发抢领失败不保证都返回版本冲突,另一个人已持有时会返回 NOT_FOUND。
182
+
183
+ 每个流程分别扫描本人对应状态最近 200 条任务,或最近 200 条未领取候选任务,再按当前单据 read/范围过滤;候选还检查批准能力、当前选人规则和同节点是否已经承担其他票。停用或失去当前读取权限后不会继续披露相应摘要。过滤后可能不足 200 条,当前没有分页游标,不能据此断言更早没有符合条件的任务。
184
+
185
+ `vars` 保留提交时路由变量的含义,但始终去 hidden 并对敏感字段掩码。即使具备明文能力,也需另经正式业务读取接口获得带审计的明文。
186
+
187
+ 领取、释放、转办、委派、归还、加签、激活、人工决定、跳过和取消写入独立动作记录,与本次任务变更共同事务提交或回滚。应用账号只有记录 INSERT/SELECT 权限;这不是数据库管理员也无法修改的防篡改存储。当前单据授权读者可分页查看人工意见,处理过任务不产生永久读权。不要把凭据或无权共享的额外明文写入原因;迁移前发生的操作不会自动补录。
188
+
189
+ ## 当前界面和验收边界
190
+
191
+ 框架 Admin 用同一收件箱表格展示本人、可领取和等待加签任务及各类数量;采购范例提供“待我处理 / 可领取 / 等待加签”三个视图。两者都有领取、释放、受托任务归还及正常决定入口。waiting 仅展示,不显示决定按钮;候选和受托任务分别显示领取、归还入口。采购 `/approvals` 用 `view=candidates`、`view=waiting` 保存视图,默认本人待办不需要 view 参数。界面可提示操作,未完成子票等动态限制仍由服务端拒绝。
192
+
193
+ 采购范例后续已接入协作名录选人、转办/委派/三种加签及分页人工操作历史,详见 [采购导读](purchase-example.md)。框架 Admin 保留通用任务收件箱,启用审批运营后新增“我的申请”和“流程提醒”,不依赖采购的页面、名录或额外业务字段。框架支持、应用路由启用、浏览器验收仍是不同状态。
194
+
195
+ 本批真实 PostgreSQL/HTTP 定向回归共 144 项通过、最终 0 跳过:新增候选/签序 38 项、既有人员动作 27 项和内核/HTTP/AI/恢复 79 项。先执行六文件 143 项,再补旧实例签序权限用例并复跑两个审批文件 65 项,重复用例不累加。包含 8 人抢领、超过五连接池容量的并发、字段非法/停用/跨租户、动态候选身份、前后签 any/all、取消、领域命令失败回滚和真实旧库升级。首次内嵌测试数据库短暂拒绝连接造成的跳过,已由后续完整执行覆盖;该次跳过不计入通过。
196
+
197
+ 上述第二批基础页面曾使用真实构建和内存 HTTP 夹具验收;后续采购场景已另做真实隔离 PostgreSQL、API、worker 和账号登录的浏览器验证。各次记录不累加为全部功能验收;本页 API 说明也不能代替部署后的实际验证。
198
+
199
+ 尚未实现受限岗位规则、代理时间段、嵌套委派、无可用人员的通用恢复、减签/撤销加签、任意串行加签链、指定节点退回、任意流程图/循环/OR 网关、工作日计时、自动升级、抄送、邮件/短信通知和可视化运行时设计器。应用接入仍需检查真实角色、路由、迁移与浏览器路径;上述历史测试数量不作为本次 AND 并行的验证数量。
200
+
201
+ ## 框架通用时限、提醒与催办
202
+
203
+ 这组能力实现在 `@yss123/cage-approval`,复用内核的 runtime/worker 扩展,不需要业务项目创建通知表或编写定时任务。应用只需声明政策,沿用正常迁移、API 与 worker 启动流程。旧实例未声明时限或催办政策时不会被升级自动开放。
204
+
205
+ ```ts
206
+ import { approvalOperations, approver, route, step } from '@yss123/cage-approval';
207
+
208
+ /** 通用站内运营服务,从 domain 入口导出,worker 才会扫描到期节点。 */
209
+ export const approvalOps = approvalOperations();
210
+
211
+ /** 局部接入示意:对应 approval 必须已绑定,并把 createdBy 列入 routable。 */
212
+ export const documentRoute = route('document-review', [
213
+ step('部门审核', approver.role('reviewer'), {
214
+ sla: { durationMinutes: 1440, remindBeforeMinutes: 60 },
215
+ actions: { transfer: true, delegate: true, addSign: true },
216
+ }),
217
+ ], { reminders: { requesterField: 'createdBy', cooldownMinutes: 15 } });
218
+ ```
219
+
220
+ `durationMinutes` 是进入人工节点后可用的**自然分钟总时限**,`remindBeforeMinutes` 是截止前多少分钟进入临期提醒。两者允许小数分钟,换算后至少一毫秒、至多 525600 分钟,提前量严格小于时限;省略提前量则只发超时提醒。每条并行分支的节点在实际开启时独立开始计时,尚未满足前驱的节点不提前计时。时限以数据库持久时间计算,加签、转办、委派、领取和释放都不重置;后签激活时该节点可能已经超时。AI 节点及其人工接管不使用此人工节点 SLA,已有人工接管待办仍可接收申请人催办。没有工作日历、节假日扣除或按员工时区计算的工作时间。
221
+
222
+ 临期/超时由 worker 扫描各分支的持久活动节点并写入站内提醒。同一节点阶段、任务、收件人去重;worker 重启或并发扫描不重复投递同一项。已经跨过截止时间时只补超时,不补过时临期。转办或后签激活后的新办理人可在下一次扫描收到当前阶段提醒。waiting 票不会收到“请处理”提醒,取消、完成和不再活动的步骤停止投递;提醒不会自动批准、自动转办或替人取得能力。
223
+
224
+ 每次 tick 最多扫描 25 个节点,每个节点最多投递 100 个尚未收到当前阶段提醒的任务/接收人配对,后续扫描继续补齐;扫描位置保存在数据库并轮转,完成投递的旧节点不会永久占满批次。角色选人仍读取当前完整候选集合,尚未验证大组织生产规模性能。手动催办最多 200 个合格配对,超出明确返回 INVALID_TRANSITION 且不写通知或冷却。提醒实际到达时间受 worker 轮询和队列积压影响,不是精确到毫秒的送达承诺。
225
+
226
+ 接收人根据当前 pending 任务的持有人、未归还委派的原负责人或未领取候选规则计算,并实时过滤 active、批准/read 能力与单据范围。候选人已承担本节点另一票时不接收可领取提醒。通知读取与标已读仍核对本人、当前权限及接收关系,转出或撤权后不能凭旧通知继续查看原因。它是当前协作收件箱;永久操作追溯仍用 `approvalTaskHistory`。
227
+
228
+ 申请人由路由 `reminders.requesterField` 指定,必须是公开且进入 `routable` 的单个用户 UUID 字段,并随提交冻结。仅能读取单据不等于能催办。催办绑定实例 UUID 与 `expectedStep`,并行实例还必须提交完整且按升序排列的 `expectedSteps`,其值使用最近一次申请摘要中的 `currentSteps`。即使并行实例暂时只剩一个活动节点,也不能省略该集合;否则返回 INVALID_INPUT。最小索引未变而另一分支已推进时,旧集合仍会返回 CONFLICT,页面应刷新后由用户重新核对。
229
+
230
+ 催办事务同时检查活动集合、业务提交版本、申请人和冷却时间,向全部活动节点的合格任务/接收人配对投递。同实例跨分支、跨节点共享冷却,冷却中或旧业务版本返回 CONFLICT;无合格接收人明确失败且不消耗冷却。催办只增加提醒和操作记录,不修改业务 version 或待办 revision。本人申请从最近 200 个匹配实例中再按当前可见性过滤,未提供分页,不能把返回数量当作完整历史总数。
231
+
232
+ 公共 SDK 使用与其他命令相同的会话和 CSRF:
233
+
234
+ | 调用 | 用途 |
235
+ | --- | --- |
236
+ | `client.approvalRequests()` | 本人发起且开放催办的运行实例,含 currentSteps、逐节点 activeSteps、最近截止 dueAt 和 nextUrgeAt |
237
+ | `client.urgeApproval(instanceId, { expectedStep, expectedSteps, reason })` | 并行必填完整 expectedSteps;原因 1–1000 字;返回任务/接收人配对数及再次可催办时间 |
238
+ | `client.approvalNotices({ after?, limit?, unreadOnly? })` | 本人当前可见提醒,返回 items/nextCursor,游标始终为字符串 |
239
+ | `client.readApprovalNotice(id)` | 标已读;重复请求保留首次已读时间 |
240
+
241
+ ```ts
242
+ const requests = await client.approvalRequests();
243
+ if (requests.ok && requests.data.length) {
244
+ const selected = requests.data[0];
245
+ // 页面应先让申请人选择实例并填写原因;同时提交最小索引与完整集合,防止旧页面误催已变化的分支。
246
+ const result = await client.urgeApproval(selected.id, {
247
+ expectedStep: selected.currentStep,
248
+ expectedSteps: selected.currentSteps,
249
+ reason: '材料已补齐,请继续审核',
250
+ });
251
+ if (result.ok) {
252
+ // recipientCount 按任务与接收人配对计数;同一人处理两条分支可收到两条提醒,不是去重人数。
253
+ console.log(`已发送 ${result.data.recipientCount} 条站内催办提醒`);
254
+ }
255
+ }
256
+ ```
257
+
258
+ 对应接口为 GET `/api/approval/requests`、POST `/api/approval/instances/:id/urge`、GET `/api/approval/notices`、POST `/api/approval/notices/:id/read`。只有启用运行时才注册,并写入 OpenAPI。提醒分页按底层稳定记录游标推进,授权过滤后空页也可能有 nextCursor,应继续加载直到 null;单条通知不包含整份路由变量。
259
+
260
+ 框架 Admin 的 `/admin/#/requests` 可填写原因并催办,`/admin/#/notices?view=unread` 可筛选、翻页和标已读;`view=all` 展示当前可见的全部提醒,`#/tasks` 展示截止时间。业务应用可以直接使用这些页面,也可以消费公共 SDK 构建自己的界面。采购仅作为接入验收载体,框架功能不依赖采购业务代码。
@@ -69,6 +69,14 @@ worker → 消费 outbox → 异步反应 / 审批 / 连接器
69
69
 
70
70
  资源标签 `acquires: 'inventory.lock'`、`releases: 'inventory.lock'` 为图规则提供证据。它们不会自动加锁或释放,真正效果来自 `acquireLock/releaseLock` 命令。
71
71
 
72
+ 有界批量步骤可用 `reactionEach`:声明目标命令、最大项数、唯一排序键和映射,按稳定顺序串行调用。`order` 表达同一事件的步骤依赖,同事务链仍整体回滚。具体声明见[原语指南](primitives.md#有界集合与步骤顺序)。
73
+
74
+ 出站分成外部执行与短事务回写两个阶段。框架先领取本地执行租约,用 `${tenantId}:${declaredKey}` 作为远端幂等键,可靠保存回执后再在短事务调用成功命令;回写失败可复用已保存回执。远端必须实际支持幂等,框架不能承诺任意外部系统恰好一次。不可安全重试的写入结果未知时隔离并要求核对,不能把超时当作远端未执行。
75
+
76
+ 当前没有通用的远端回执确认或解除 `unknown` 的管理入口,普通死信重放不会解除未知状态。此类操作要按连接器实际协议制定受控恢复或业务补偿;不能发明恢复 API,也不能直接 SQL 改执行状态后重发。
77
+
78
+ 首阶段按单机、API 与 worker 同版本升级部署。worker 启动校验必要引擎,发布消费者清单、注册指纹和心跳;不认识事件或缺少必要消费者时不会静默完成。停止时先停新任务、取消可取消 IO,再有界等待在途工作;定时任务同时使用本地运行标记与数据库互斥锁防止跨周期/实例重叠。连接器限流和认证队列均为单进程预算,多实例共享限流另需设计。
79
+
72
80
  ## 权限是几层判断
73
81
 
74
82
  | 层 | 例子 | 说明 |
@@ -84,6 +92,23 @@ worker → 消费 outbox → 异步反应 / 审批 / 连接器
84
92
 
85
93
  `useCan()`、`can()` 只决定按钮呈现;前端隐藏按钮不能代替后端授权。新增命令不会自动授给已有生产角色,角色分配和额度调整也受防提权约束。
86
94
 
95
+ 授权通知监听异常时不再复用缓存,每次重新读取授权;重新订阅后清空缓存,并阻止旧请求回填旧上下文。`/readyz` 反映数据库和授权监听健康,`/healthz` 仅表示存活。诊断入口受 `Sys.ops.read` 及相关对象 read/范围控制,`explain` 解释调用身份、能力、范围、状态与硬约束,不能预测 handler 的业务结果;新建对象的最终范围无法提前确定时返回 unknown。
96
+
97
+ ## 审计保证
98
+
99
+ | 入口 | 保证与失败行为 |
100
+ | --- | --- |
101
+ | 命令成功 | 与业务变更、版本和 outbox 同事务提交;写审计失败整笔回滚 |
102
+ | 命令拒绝 | FORBIDDEN / NOT_FOUND / CONSTRAINT_VIOLATED 异步尽力记录;失败有日志,不宣称所有错误均已留痕 |
103
+ | 密码登录失败 | 等待尝试写审计;失败有日志,请求仍拒绝登录,属于尽力记录 |
104
+ | get / list / related 的潜在敏感明文 | 具备相应 unmask 能力时先完成可靠审计再交付;失败拒绝结果 |
105
+ | 自定义 query | 按 reads 保守审计潜在敏感明文;声明 audit.purpose 时另外可靠记录目的;任一可靠审计失败均拒绝交付 |
106
+ | 导出生成、下载 | 可靠审计;下载还复核当前权限与访问指纹;失败不交付文件 |
107
+ | 导入任务及成功行 | 任务提交与目标命令按各自事务审计;异步逐行/原子方式见任务协议 |
108
+ | 普通掩码读取、诊断元数据 | 默认无统一专门审计 |
109
+
110
+ 成功登录、step-up 和退出目前没有统一专门审计。审计保证按入口区分,不能把“有审计”理解为每一种请求都可靠留痕。可靠读取失败使用 `CAGE-AUDIT-001`,凭 requestId 定位数据库与权限故障;默认日志只保留允许的执行元数据,错误文本、原始 payload 与外部响应不进入默认结构化日志。
111
+
87
112
  ## 数据库连接属于框架核心能力
88
113
 
89
114
  项目提供连接配置,框架管理连接池、事务、上下文变量和 SQL。普通业务不需要自己编写 `pg.Pool`、表仓储或连接释放逻辑。
@@ -103,6 +128,7 @@ APP、READ、MIGRATE 指向**同一个已经存在的数据库**,用不同账
103
128
  | `init` | 角色、schema、授权、随机凭证及 `.env` | 安装 PG、启动 Docker、创建数据库、创建业务表 |
104
129
  | `gen` | 本地 contracts、SQL、状态图、迁移草稿 | 应用数据库迁移 |
105
130
  | `migrate` | 已有库的表、索引、安全视图、迁移历史 | 每次启动新建数据库 |
131
+ | `bootstrap` | 显式初始化组织,将初始凭据交付到新的受限文件 | 自动授予业务能力、日常启动时重置密码 |
106
132
  | `dev` | 连接已有库,启动 API、worker、Web,监听声明重新生成 | 自动迁移或内嵌临时数据库兜底 |
107
133
 
108
134
  读路径使用 `safe.*`,业务表位于 `core.*`,组织和运行数据位于 `sys.*`。安全视图结合会话上下文执行范围过滤与掩码;手写报表也必须走这层。连接现有库不意味着自动把历史任意表变成 Cage 聚合,需要专门的映射与迁移方案。
@@ -0,0 +1,203 @@
1
+ # 详细中文注释规范
2
+
3
+ [返回学习入口](README.md) · [工程目录](project-structure.md) · [开发步骤](workflow.md)
4
+
5
+ 本规范同时适用于 Cage 框架源码、标准范例,以及通过脚手架创建后由 Codex 等 agent 编写和维护的应用源码。**详细中文注释是代码交付的一部分。** 新建或修改代码时,必须让后续开发者仅凭源码及其注释理解职责、输入输出、关键步骤、设计原因、调用关系和行为边界,不能只在聊天回复或外部设计文档中解释。
6
+
7
+ 注释需要回答“做什么、为什么这样做、具体怎么做、在哪些条件下成立、失败后怎样处理”。按照下面的覆盖项写到足以理解和修改代码的程度,不用每行注释、字数、行数比例衡量质量。不允许以“代码自解释”“名字已经足够清楚”免除必要的职责和接口说明;也不要把 `if`、赋值、循环等语法逐句翻译成没有信息量的中文。
8
+
9
+ ## 新建与修改时的执行范围
10
+
11
+ 1. 新建手写源码文件时,同步完成文件头、导出声明、类型字段以及关键流程的中文注释,再交付代码。测试、脚本、入口文件、React 组件、hooks、样式和手写 SQL 也属于源码。
12
+ 2. 修改已有文件时,核对并补齐文件职责说明;为本次涉及的声明、参数、字段和流程补足注释。沿实际调用链同步更新受到影响的调用方、消费者、测试和配置说明,不能只改当前一行而留下上下游过时描述。与本次修改无关的整个仓库不要求一次性重写。
13
+ 3. 调整行为、默认值、错误、权限、单位、状态或事务边界时,在同一变更中更新对应注释。移动代码时同时修正职责归属与引用,删除失效注释,不留下两个相互矛盾的解释。
14
+ 4. 手写源码使用该语言支持的注释形式:TypeScript/JavaScript 的文件与接口说明优先 JSDoc,关键步骤用块注释或行注释,CSS/SQL 使用各自合法注释。JSON 等不支持注释的配置保持合法语法,在相邻文档说明字段含义并给出明确文件入口。
15
+ 5. 生成契约、自动 SQL、派生测试等从声明与生成器维护注释,不能直接编辑生成结果;已执行或已发布的历史迁移不可因补注释而重写。具体边界见下文“生成物与迁移”。
16
+
17
+ ## 每个文件先说明它在系统中的位置
18
+
19
+ 每个新增或涉及修改的手写源码文件,开头应有中文职责说明。保留必须位于首行的 shebang 或工具指令,职责说明放在它们之后、普通实现之前。内容至少覆盖:
20
+
21
+ - **负责什么**:对应业务对象或技术能力,处理的主要问题;指出不由本文件承担但容易混淆的责任。
22
+ - **谁调用、调用谁**:所属模块、公开入口、主要上游和下游。入口文件说明如何装配注册表、服务或 Provider;纯转导出的 `index.ts` 说明对外暴露哪些职责、为什么从这里导出。
23
+ - **关键流程**:按实际顺序概述输入经过哪些处理,得到什么输出或产生什么副作用。简单纯函数文件可合并成一段;持久化、异步或多阶段流程需逐阶段解释。
24
+ - **运行与边界**:运行在浏览器、API、worker、CLI 还是测试进程,权限、事务、资源生命周期及配置由谁保证。存在 IO、缓存、共享状态或初始化行为时必须指出。
25
+
26
+ 文件头写稳定的模块名和符号名,不维护易过期的代码行号或完整依赖清单。详细规则靠近实际声明,文件头负责建立读代码的路线,不能把所有实现细节堆成一份长篇设计文档。
27
+
28
+ ## 导出 API、函数、类、组件和类型
29
+
30
+ 对新增或修改的导出函数、类及公开成员、常量、领域声明、React 组件、hooks、接口和类型别名,紧邻声明编写中文 JSDoc。模块转导出保留原声明的详细 JSDoc,入口说明其对外职责;不要为同一接口复制多份会独立漂移的说明。
31
+
32
+ | 对象 | 必须说明的内容 |
33
+ | --- | --- |
34
+ | 函数与方法 | 解决什么问题、适用调用阶段、参数语义与约束、返回值含义、是否修改输入、是否执行 IO、失败如何返回或抛出;关键算法和取舍放在实现附近 |
35
+ | 类与公开成员 | 实例由谁创建/持有/关闭、内部状态与生命周期、依赖要求、并发访问是否支持;构造参数、方法和可读写属性分别说明 |
36
+ | 导出常量与声明对象 | 表达的业务或协议含义、使用方、取值来源、单位/默认值、改变它影响哪些行为;声明对象与实际执行不能混为一谈 |
37
+ | 接口、类型与字段 | 整体用途及数据来源,每个字段的业务语义、单位/格式、是否可空/可省略、缺省含义、只读或可写边界;联合类型逐个说明分支含义 |
38
+ | React 组件与 props | 对应页面或交互、输入数据和事件回调、状态由谁持有、可见性与权限提示、成功/失败后的页面行为;组件返回的 UI 及副作用 |
39
+ | hooks 与返回字段 | 何时读取或订阅、依赖与触发条件、状态含义、返回操作的完成条件、取消/卸载清理、缓存刷新及错误处理责任 |
40
+
41
+ 函数使用真实参数名填写 `@param`,返回值使用 `@returns`,确实会抛出的错误使用 `@throws`。标签写不下的调用、权限或事务条件用正文说明。没有返回值的函数应说明副作用和完成条件,不能为了填标签编造一个结果;领域声明是配置对象,不要把 `@param` 写成不存在的顶层函数参数。泛型参数影响调用约束时说明其关系,不重复 TypeScript 已表达的类型文本。
42
+
43
+ 复杂私有函数和回调同样需要说明:包括多阶段计算、SQL 构建、缓存合并、递归、重试、并发协调、状态转换及非直观数据映射。靠近相应分支解释分支成立的条件、处理顺序和保证范围。简单局部表达式可以由所在函数的说明覆盖,但不能让影响行为的隐藏规则失去解释。
44
+
45
+ ## 数据与领域声明要写清业务含义
46
+
47
+ 领域代码既是运行规则,也是后续 agent 理解业务的主要依据。聚合、状态、命令、事件、审批、反应、查询、任务、连接器应有各自的中文说明;框架支持的 `description` 用于简短公开说明,详细 JSDoc 用于源码维护,二者需要保持一致。普通源码注释不会自动成为权限规则、运行时校验或图谱声明,仍要填写真实 API 支持的配置。
48
+
49
+ | 声明 | 注释覆盖项 |
50
+ | --- | --- |
51
+ | 聚合与业务字段 | 对象的业务边界;字段由谁填写/计算;金额的币种和精度、数量单位、时间的时区与格式;空字符串、null、undefined、空集合分别意味着什么;敏感性、可修改阶段及关系归属 |
52
+ | 状态与不变量 | 每个状态代表的业务事实、进入和退出条件、终态允许行为;不变量保护什么规则、何时校验、拒绝后的影响,不能仅写“检查金额” |
53
+ | 命令与输入 | 调用身份和能力点、数据范围、起始/目标状态;输入来源、必填/默认/空值语义、校验与规范化;读取依赖和用途;handler 返回哪些变化;事件、事务、副作用及失败语义 |
54
+ | 事件与反应 | 事件表示哪项已发生事实、载荷字段来源、旧值/新值区别、兼容要求;消费者调用哪个命令、映射与跳过条件、执行顺序、同事务或 outbox、失败后的资源状态 |
55
+ | 审批 | 启动/取消条件、分支依据、选人来源、顺序与会签规则、结论命令、退回或转人工路径;选人不等于授予能力,AI 判断不等于硬约束已满足 |
56
+ | 查询 | 使用的安全视图/reads、调用人的 read 能力和范围、参数绑定、联表与聚合含义、排序/分页/截断、空结果含义、敏感数据及审计目的 |
57
+ | 定时任务与连接器 | 触发条件、读取/调用清单、处理上限和运行顺序;外部请求/响应映射、超时、重试分类、幂等依据、回执与补偿;fake 能验证与不能验证的范围 |
58
+
59
+ 命令的状态、版本、幂等、权限、事务与审计由内核落实时,要明确这一责任分配;handler 注释不能把返回草稿描述成“已写入数据库”。`reads` 是显式只读依赖,资源 `acquires/releases` 是静态配对标签,二者都不代替真实业务动作。已有记录 `to: null` 表示保留当前状态,不能注释成“不检查状态”。
60
+
61
+ 下面沿用[原语指南](primitives.md)的 Note 公开 API,展示一个完整文件的注释层次。应用仍需导出组织模型,并将本模块逐层从 domain 入口导出。示例不添加自动授权、额外持久化或不存在的框架选项。
62
+
63
+ ```ts
64
+ /**
65
+ * 部门便笺领域:声明便笺字段、状态和创建/改标题操作。
66
+ * 模块经 domain 入口进入注册表,生成契约供业务页面调用;HTTP 将写请求交给内核。
67
+ * 本文件只描述业务规则和字段变化,不启动服务或自行执行数据库/网络 IO。
68
+ * 内核处理授权、范围、版本、字段校验及审计;实际可见部门由角色授权决定。
69
+ */
70
+ import { aggregate, command, ref, scope, states, text } from '@yss123/cage-kernel';
71
+ import { z } from 'zod';
72
+
73
+ /**
74
+ * 部门便笺:标题与归属信息作为同一个聚合维护。
75
+ * active 表示可编辑,archived 表示归档终态;归档命令可按原语指南另行声明。
76
+ * 本示例只开放创建和改标题,不会因声明 archived 就自动生成归档操作。
77
+ */
78
+ export const Note = aggregate('Note', {
79
+ description: '部门便笺',
80
+ fields: {
81
+ /** 便笺标题,最多 120 个字符;命令去除首尾空白后要求非空,不接受 null。 */
82
+ title: text(120),
83
+ /** 所属部门 UUID;创建输入不允许指定,内核从当前主体部门补入,用于范围判断。 */
84
+ deptId: ref('Dept'),
85
+ /** 创建人 UUID;内核在新建结果中填入操作者,已有记录更新时保留原值。 */
86
+ createdBy: ref('User'),
87
+ },
88
+ /** active 可改标题;archived 为终态,update 的 from 会拒绝对归档记录的修改。 */
89
+ states: states('active', 'archived', { terminal: ['archived'] }),
90
+ /** 声明部门范围字段和建议范围,实际授权由角色决定,并非自动授予部门可见权。 */
91
+ scope: scope.deptSubtree('deptId'),
92
+ invariants: {
93
+ /** 对合并后的对象再次保证标题非空,避免其他命令将便笺写成无标题记录。 */
94
+ titleNotBlank: (note) => note.title.trim().length > 0,
95
+ },
96
+ });
97
+
98
+ /**
99
+ * 创建便笺:user 身份调用 Note.create,由 new 进入 active。
100
+ * 输入仅接收标题并去除首尾空白,归属字段交由内核按主体补入,不能由页面选择他人。
101
+ * 没有 reads 或业务事件;handler 返回的草稿由内核继续校验和持久化。
102
+ * 输入、权限或最终对象校验失败时不提交业务变更;声明不会给角色自动增加能力。
103
+ */
104
+ export const createNote = command(Note, {
105
+ name: 'create',
106
+ description: '创建部门便笺',
107
+ from: 'new',
108
+ to: 'active',
109
+ input: z.object({
110
+ /** 用户填写的标题;trim 发生在长度校验前,最终持久化的是规范化后的文字。 */
111
+ title: z.string().trim().min(1).max(120),
112
+ }),
113
+ // 新建草稿已带规范化输入和部门,返回它继续走内核流水线;这里不执行数据库写入。
114
+ handler: (draft) => draft,
115
+ });
116
+
117
+ /**
118
+ * 修改有效便笺的标题:user 身份调用 Note.update,只有 active 记录允许执行。
119
+ * 内核先按调用人范围加载并锁定记录;to: null 保留已加载状态,仍检查 from 和权限。
120
+ * 页面应传入读到的版本以检测并发修改;版本不匹配时重新加载并让用户核对内容。
121
+ * handler 只返回标题变化,归属、状态与系统版本由内核维护;不发布业务事件。
122
+ */
123
+ export const updateNote = command(Note, {
124
+ name: 'update',
125
+ description: '修改便笺标题',
126
+ from: 'active',
127
+ to: null,
128
+ input: z.object({
129
+ /** 待修改便笺的 UUID;存在不代表当前调用人有权访问。 */
130
+ id: z.string().uuid(),
131
+ /** 完整替换原标题,不是追加文本;不允许空标题,也不改变部门或创建人。 */
132
+ title: z.string().trim().min(1).max(120),
133
+ }),
134
+ // 显式只返回标题,避免把前端传入的字段扩散为未经声明的其他业务变化。
135
+ handler: (_draft, input) => ({ title: input.title }),
136
+ });
137
+ ```
138
+
139
+ 公开函数或类型的说明可以按下面的方式写。这个应用辅助函数只处理失败前缀的展示计数,不是新增 Cage API;实际业务中应明确使用它的页面或诊断模块。
140
+
141
+ ```ts
142
+ /** 回放页面中已观察到的失败前缀位置;用于显示,不代表全局最小反例。 */
143
+ export interface FailurePosition {
144
+ /** 失败动作在已观察序列中的零基索引;null 表示尚未执行到失败动作。 */
145
+ failedIndex: number | null;
146
+ }
147
+
148
+ /**
149
+ * 将失败位置转换为页面显示的动作序号,避免把零基索引直接交给使用者。
150
+ * 不修改输入,也不发起回放或数据库访问;索引的合法性由创建该位置的诊断层保证。
151
+ * @param position 诊断层提供的位置,failedIndex 为非负整数或 null。
152
+ * @returns 一基动作序号;尚无失败位置时返回 null,让页面显示“未发生失败”。
153
+ */
154
+ export function failureStepNumber(position: FailurePosition): number | null {
155
+ return position.failedIndex === null ? null : position.failedIndex + 1;
156
+ }
157
+ ```
158
+
159
+ ## 异步、并发和恢复流程必须解释保证范围
160
+
161
+ 涉及异步任务、worker、事务、重试、锁、缓存、队列、流式响应及清理时,除函数说明外,还要在关键步骤前写清以下事实:
162
+
163
+ - 任务何时被接受、何时实际执行、何时持久化、何时可视为业务完成;各阶段状态由谁更新,调用方等待的 Promise 到底表示哪个阶段结束。
164
+ - 同事务部分和事务外 IO 的边界,执行顺序的原因,失败会回滚哪些变化、哪些已发生效果无法回滚;多个步骤共同提交还是分别提交。
165
+ - 并发控制依据:版本、行锁、租约、互斥或唯一键各保护什么,保护到哪个进程/数据库范围;排序是否稳定,是否可能重复领取或乱序到达。
166
+ - 幂等键对应哪一次业务动作、由谁生成并保存、有效期和去重边界;重试是否复用原输入,结果未知时如何核对,不能把超时写成“远端未执行”。
167
+ - 失败的分类、重试条件、次数/时间预算、死信和人工恢复入口;已经持久化的回执怎样避免再次提交。不存在的恢复接口不得出现在注释中。
168
+ - 取消、断连、进程退出及卸载分别取消什么、清理什么;浏览器取消等待不保证服务端事务被取消,清理失败不能用空 catch 描述为成功。
169
+ - 缓存的数据来源、有效期、失效时机、账号/租户隔离及旧请求回填处理;权限变化时不能把仍未验证的缓存当作当前授权事实。
170
+
171
+ 注释中的“原子”“恰好一次”“线程安全”“永不重复”“一定可恢复”等表述必须有实际实现支持,并写明限定范围。无法保证时直接描述当前行为、已知限制和调用方责任,不承诺超出实现的效果。
172
+
173
+ ## 页面、组件、hooks 与样式
174
+
175
+ 页面文件说明 URL 与参数来源、数据通过哪个生成契约或客户端获取、登录守卫与模块入口的关系。列表解释筛选/分页如何进入查询参数;详情解释如何独立按 URL 加载,不能依赖先访问列表。组件和 props 说明职责、数据归属与回调时机,hooks 说明触发、状态与清理。
176
+
177
+ 在实际处理位置解释加载、空数据、网络错误、401、403、404、版本冲突和提交中状态;只描述该页面实际实现的分支,不机械列出所有错误码。明确前端 `can/useCan` 控制交互提示,真正授权由服务端完成。表单需解释草稿与已保存数据的区别、前后端校验分工、提交幂等键的生命周期以及成功后刷新哪些缓存。
178
+
179
+ effect、订阅和流式回调解释依赖为何需要、何时启动/终止、怎样阻止旧会话结果覆盖新状态。复杂布局、响应式断点、层叠与滚动、无障碍交互的样式注释说明对应使用场景与约束,不能只写“这里设置颜色”。样式文件仍需要职责说明,简单规则组可统一解释。
180
+
181
+ ## 测试与维护脚本
182
+
183
+ 测试文件说明被保护的业务或框架保证、使用真实数据库还是 fake、夹具的来源与隔离方式、该组测试的覆盖边界。用例名使用明确的中文行为描述;涉及边界或回归时,在用例附近解释“这个数据为什么这样准备、触发了什么风险、断言排除了什么错误”。测试 helper、共享夹具及复杂 mock 需要函数与字段说明,不能只把断言翻译成注释;fake 成功不应被写成真实第三方联调通过。
184
+
185
+ 脚本文件头说明执行目录、前置配置、输入参数/环境变量的用途、读取和写入哪些路径或外部系统、是否覆盖文件、能否重复执行、失败后保留什么、如何清理。导出函数和关键阶段继续遵守本规范;不因脚本短或只供维护使用而省略副作用说明。命令示例只写变量名、示例路径和无秘密的占位值,不写真实连接串、密钥、Cookie、令牌、个人数据或初始化凭据。新增或维护脚本使用 TypeScript,不新增 `.mjs`。
186
+
187
+ ## 生成物与迁移
188
+
189
+ 生成文件必须由生成器写明来源、用途、重新生成入口和编辑边界;需要详细接口注释时,优先从领域 `description`、输入 schema 和真实生成规则形成,框架维护者修改生成器并验证产物。业务项目使用已安装的框架生成器;发现生成注释缺失时说明缺口,不能手改 contracts 来维持表面一致。不要声称任意 JSDoc 都会自动复制到契约,实际支持以生成器为准。
190
+
191
+ 新建或尚未执行的迁移草稿应说明结构变动目的、数据兼容性、回填顺序、锁/停机影响及验证方式;无法证明影响时注明需要核对的条件。**已执行或已发布的历史迁移保持原样。** 对历史迁移的补充解释写在新文档或后续变更说明中,不为了补注释更改校验和。新增结构和数据变更使用新的迁移,仍须审查。
192
+
193
+ ## 交付前逐项核对
194
+
195
+ - 新建文件是否有中文职责、调用链和运行边界;涉及的导出 API、类型字段、组件和 hooks 是否有完整 JSDoc。
196
+ - 本次改动的数据单位、空值、默认值、状态和授权条件是否解释明确;handler、框架和下游消费者的责任是否分清。
197
+ - 复杂流程是否解释关键步骤、条件、设计原因、失败与恢复;注释中的事务、幂等、并发与性能承诺是否符合实现。
198
+ - 调用方、测试、样式和脚本的相关说明是否同步更新;是否存在过时描述、机械复述或只写在聊天记录里的关键信息。
199
+ - 生成物是否通过声明/生成器更新,历史迁移是否保持不变,注释和示例是否包含秘密或真实个人数据。
200
+
201
+ 代码检查和文档链接检查不能证明注释准确完整,必须结合本次 diff 阅读核对。交付说明列出注释覆盖的主要职责与边界,以及真实未覆盖项;验证仍分别报告通过、跳过和未执行。只修改注释时执行适合的格式/文档检查即可,不需要为注释新增复述实现的测试或重复全套数据库回归。
202
+
203
+ 框架维护者还需注意:`cage budget` 按 TypeScript 语法 token 所占的原始物理行统计内核体积,排除普通注释、JSDoc 和纯空白;字符串、正则与跨行模板中的内容仍属于代码。同一行只计一次,不因格式化重新排版。新增详细注释不会增加实现预算;真实代码超出 5000 行仍触发 `CAGE-BUDGET-001`。应如实报告检查结果,不为通过预算删除必要说明、提高阈值或把未通过写成通过。统计逻辑的修改属于功能改动,不能混入“只补注释”的任务。