takt 0.49.0 → 0.51.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 (990) hide show
  1. package/README.md +31 -0
  2. package/builtins/en/config.yaml +6 -0
  3. package/builtins/en/facets/instructions/ai-antipattern-review.md +5 -0
  4. package/builtins/en/facets/instructions/findings-manager.md +6 -2
  5. package/builtins/en/facets/instructions/fix.md +9 -3
  6. package/builtins/en/facets/instructions/loop-monitor-fix-replan.md +21 -0
  7. package/builtins/en/facets/instructions/loop-monitor-replan.md +10 -0
  8. package/builtins/en/facets/instructions/loop-monitor-reviewers-fix.md +6 -0
  9. package/builtins/en/facets/instructions/plan-maintenance.md +10 -7
  10. package/builtins/en/facets/instructions/plan.md +17 -8
  11. package/builtins/en/facets/instructions/review-arch.md +5 -0
  12. package/builtins/en/facets/instructions/review-coding.md +15 -6
  13. package/builtins/en/facets/instructions/review-cqrs-es.md +9 -0
  14. package/builtins/en/facets/instructions/review-implementation-semantics.md +18 -0
  15. package/builtins/en/facets/instructions/review-merge-readiness.md +14 -0
  16. package/builtins/en/facets/instructions/supervise-maintenance.md +2 -2
  17. package/builtins/en/facets/instructions/supervise.md +8 -3
  18. package/builtins/en/facets/instructions/write-tests-first.md +23 -3
  19. package/builtins/en/facets/knowledge/architecture.md +36 -0
  20. package/builtins/en/facets/knowledge/backend.md +74 -0
  21. package/builtins/en/facets/knowledge/cqrs-es.md +767 -235
  22. package/builtins/en/facets/knowledge/frontend.md +5 -1
  23. package/builtins/en/facets/knowledge/implementation-semantics.md +104 -0
  24. package/builtins/en/facets/knowledge/security.md +3 -0
  25. package/builtins/en/facets/knowledge/takt.md +10 -2
  26. package/builtins/en/facets/knowledge/unit-testing.md +14 -0
  27. package/builtins/en/facets/output-contracts/ai-antipattern-review.md +11 -1
  28. package/builtins/en/facets/output-contracts/architecture-review.md +6 -1
  29. package/builtins/en/facets/output-contracts/coding-review.md +11 -1
  30. package/builtins/en/facets/output-contracts/findings-manager.md +14 -0
  31. package/builtins/en/facets/output-contracts/implementation-semantics-review-finding-contract.md +28 -0
  32. package/builtins/en/facets/output-contracts/implementation-semantics-review.md +50 -0
  33. package/builtins/en/facets/output-contracts/{pure-review-finding-contract.md → merge-readiness-review-finding-contract.md} +14 -8
  34. package/builtins/en/facets/output-contracts/{pure-review.md → merge-readiness-review.md} +17 -11
  35. package/builtins/en/facets/output-contracts/supervisor-validation.md +6 -2
  36. package/builtins/en/facets/output-contracts/test-report.md +25 -0
  37. package/builtins/en/facets/personas/coder.md +3 -3
  38. package/builtins/en/facets/personas/implementation-semantics-reviewer.md +27 -0
  39. package/builtins/en/facets/personas/merge-readiness-reviewer.md +28 -0
  40. package/builtins/en/facets/personas/supervisor.md +1 -1
  41. package/builtins/en/facets/policies/ai-antipattern.md +19 -0
  42. package/builtins/en/facets/policies/coding.md +31 -4
  43. package/builtins/en/facets/policies/review.md +17 -1
  44. package/builtins/en/facets/policies/testing.md +6 -2
  45. package/builtins/en/workflow-categories.yaml +13 -1
  46. package/builtins/en/workflows/audit-architecture-backend.yaml +1 -0
  47. package/builtins/en/workflows/audit-architecture-dual.yaml +1 -0
  48. package/builtins/en/workflows/audit-architecture-frontend.yaml +1 -0
  49. package/builtins/en/workflows/audit-architecture.yaml +1 -0
  50. package/builtins/en/workflows/audit-e2e.yaml +1 -0
  51. package/builtins/en/workflows/audit-security.yaml +1 -0
  52. package/builtins/en/workflows/audit-unit.yaml +1 -0
  53. package/builtins/en/workflows/backend-cqrs-for-local-llm.yaml +288 -0
  54. package/builtins/en/workflows/backend-cqrs-mini.yaml +1 -0
  55. package/builtins/en/workflows/backend-cqrs.yaml +28 -84
  56. package/builtins/en/workflows/backend-for-local-llm.yaml +284 -0
  57. package/builtins/en/workflows/backend-maintenance.yaml +32 -89
  58. package/builtins/en/workflows/backend-mini.yaml +1 -0
  59. package/builtins/en/workflows/backend.yaml +25 -83
  60. package/builtins/en/workflows/{takt-default-with-fc.yaml → cli.yaml} +16 -4
  61. package/builtins/en/workflows/deep-research.yaml +1 -0
  62. package/builtins/en/workflows/default-high.yaml +3 -32
  63. package/builtins/en/workflows/default-peer-review.yaml +16 -52
  64. package/builtins/en/workflows/default.yaml +2 -1
  65. package/builtins/en/workflows/draft.yaml +0 -1
  66. package/builtins/en/workflows/dual-cqrs-mini.yaml +1 -0
  67. package/builtins/en/workflows/dual-cqrs.yaml +28 -87
  68. package/builtins/en/workflows/dual-for-local-llm.yaml +312 -0
  69. package/builtins/en/workflows/dual-mini.yaml +1 -0
  70. package/builtins/en/workflows/dual.yaml +29 -58
  71. package/builtins/en/workflows/frontend-for-local-llm.yaml +289 -0
  72. package/builtins/en/workflows/frontend-maintenance.yaml +34 -91
  73. package/builtins/en/workflows/frontend-mini.yaml +1 -0
  74. package/builtins/en/workflows/frontend.yaml +27 -85
  75. package/builtins/en/workflows/merge-readiness-dual-final-gate.yaml +92 -0
  76. package/builtins/en/workflows/merge-readiness-final-gate.yaml +79 -0
  77. package/builtins/en/workflows/{peer-review-with-fc.yaml → peer-review-for-local-llm.yaml} +48 -37
  78. package/builtins/en/workflows/peer-review.yaml +25 -20
  79. package/builtins/en/workflows/research.yaml +1 -0
  80. package/builtins/en/workflows/review-backend-cqrs.yaml +63 -35
  81. package/builtins/en/workflows/review-backend.yaml +63 -35
  82. package/builtins/en/workflows/review-default.yaml +138 -107
  83. package/builtins/en/workflows/review-dual-cqrs.yaml +63 -35
  84. package/builtins/en/workflows/review-dual.yaml +63 -35
  85. package/builtins/en/workflows/review-fix-backend-cqrs.yaml +27 -87
  86. package/builtins/en/workflows/review-fix-backend.yaml +25 -86
  87. package/builtins/en/workflows/review-fix-default.yaml +17 -87
  88. package/builtins/en/workflows/review-fix-dual-cqrs.yaml +29 -90
  89. package/builtins/en/workflows/review-fix-dual.yaml +27 -89
  90. package/builtins/en/workflows/review-fix-frontend.yaml +25 -87
  91. package/builtins/en/workflows/review-fix-takt-default.yaml +67 -362
  92. package/builtins/en/workflows/review-frontend.yaml +63 -35
  93. package/builtins/en/workflows/review-takt-default.yaml +140 -109
  94. package/builtins/en/workflows/takt-default-for-local-llm.yaml +283 -0
  95. package/builtins/en/workflows/takt-default-refresh-all.yaml +20 -59
  96. package/builtins/en/workflows/takt-default-refresh-fast.yaml +19 -57
  97. package/builtins/en/workflows/takt-default.yaml +3 -25
  98. package/builtins/en/workflows/terraform.yaml +81 -44
  99. package/builtins/ja/config.yaml +6 -0
  100. package/builtins/ja/facets/instructions/ai-antipattern-review.md +5 -0
  101. package/builtins/ja/facets/instructions/findings-manager.md +6 -2
  102. package/builtins/ja/facets/instructions/fix.md +9 -3
  103. package/builtins/ja/facets/instructions/implement-maintenance.md +4 -15
  104. package/builtins/ja/facets/instructions/implement.md +2 -14
  105. package/builtins/ja/facets/instructions/loop-monitor-fix-replan.md +21 -0
  106. package/builtins/ja/facets/instructions/loop-monitor-replan.md +10 -0
  107. package/builtins/ja/facets/instructions/loop-monitor-reviewers-fix.md +7 -0
  108. package/builtins/ja/facets/instructions/plan-maintenance.md +10 -7
  109. package/builtins/ja/facets/instructions/plan.md +9 -6
  110. package/builtins/ja/facets/instructions/review-arch.md +5 -0
  111. package/builtins/ja/facets/instructions/review-coding.md +15 -6
  112. package/builtins/ja/facets/instructions/review-cqrs-es.md +9 -0
  113. package/builtins/ja/facets/instructions/review-implementation-semantics.md +17 -0
  114. package/builtins/ja/facets/instructions/review-merge-readiness.md +14 -0
  115. package/builtins/ja/facets/instructions/supervise-maintenance.md +2 -2
  116. package/builtins/ja/facets/instructions/supervise.md +8 -3
  117. package/builtins/ja/facets/instructions/write-tests-first.md +23 -3
  118. package/builtins/ja/facets/knowledge/architecture.md +36 -0
  119. package/builtins/ja/facets/knowledge/backend.md +74 -0
  120. package/builtins/ja/facets/knowledge/cqrs-es.md +260 -16
  121. package/builtins/ja/facets/knowledge/frontend.md +5 -1
  122. package/builtins/ja/facets/knowledge/implementation-semantics.md +104 -0
  123. package/builtins/ja/facets/knowledge/security.md +3 -0
  124. package/builtins/ja/facets/knowledge/takt.md +10 -2
  125. package/builtins/ja/facets/knowledge/unit-testing.md +14 -0
  126. package/builtins/ja/facets/output-contracts/ai-antipattern-review.md +11 -1
  127. package/builtins/ja/facets/output-contracts/architecture-review.md +6 -1
  128. package/builtins/ja/facets/output-contracts/coding-review.md +11 -1
  129. package/builtins/ja/facets/output-contracts/findings-manager.md +14 -0
  130. package/builtins/ja/facets/output-contracts/implementation-semantics-review-finding-contract.md +24 -0
  131. package/builtins/ja/facets/output-contracts/implementation-semantics-review.md +50 -0
  132. package/builtins/ja/facets/output-contracts/{pure-review-finding-contract.md → merge-readiness-review-finding-contract.md} +14 -8
  133. package/builtins/ja/facets/output-contracts/{pure-review.md → merge-readiness-review.md} +17 -11
  134. package/builtins/ja/facets/output-contracts/supervisor-validation.md +6 -2
  135. package/builtins/ja/facets/output-contracts/test-report.md +25 -0
  136. package/builtins/ja/facets/partials/instructions/implement-common.md +13 -0
  137. package/builtins/ja/facets/personas/coder.md +3 -3
  138. package/builtins/ja/facets/personas/implementation-semantics-reviewer.md +27 -0
  139. package/builtins/ja/facets/personas/merge-readiness-reviewer.md +28 -0
  140. package/builtins/ja/facets/personas/supervisor.md +1 -1
  141. package/builtins/ja/facets/policies/ai-antipattern.md +19 -0
  142. package/builtins/ja/facets/policies/coding.md +32 -4
  143. package/builtins/ja/facets/policies/review.md +17 -1
  144. package/builtins/ja/facets/policies/testing.md +11 -4
  145. package/builtins/ja/workflow-categories.yaml +13 -1
  146. package/builtins/ja/workflows/audit-architecture-backend.yaml +1 -0
  147. package/builtins/ja/workflows/audit-architecture-dual.yaml +1 -0
  148. package/builtins/ja/workflows/audit-architecture-frontend.yaml +1 -0
  149. package/builtins/ja/workflows/audit-architecture.yaml +1 -0
  150. package/builtins/ja/workflows/audit-e2e.yaml +1 -0
  151. package/builtins/ja/workflows/audit-security.yaml +1 -0
  152. package/builtins/ja/workflows/audit-unit.yaml +1 -0
  153. package/builtins/ja/workflows/backend-cqrs-for-local-llm.yaml +287 -0
  154. package/builtins/ja/workflows/backend-cqrs-mini.yaml +1 -0
  155. package/builtins/ja/workflows/backend-cqrs.yaml +28 -84
  156. package/builtins/ja/workflows/backend-for-local-llm.yaml +283 -0
  157. package/builtins/ja/workflows/backend-maintenance.yaml +32 -89
  158. package/builtins/ja/workflows/backend-mini.yaml +1 -0
  159. package/builtins/ja/workflows/backend.yaml +25 -83
  160. package/builtins/ja/workflows/{takt-default-with-fc.yaml → cli.yaml} +16 -4
  161. package/builtins/ja/workflows/deep-research.yaml +1 -0
  162. package/builtins/ja/workflows/default-high.yaml +3 -32
  163. package/builtins/ja/workflows/default-peer-review.yaml +16 -52
  164. package/builtins/ja/workflows/default.yaml +2 -1
  165. package/builtins/ja/workflows/draft.yaml +0 -1
  166. package/builtins/ja/workflows/dual-cqrs-mini.yaml +1 -0
  167. package/builtins/ja/workflows/dual-cqrs.yaml +28 -87
  168. package/builtins/ja/workflows/dual-for-local-llm.yaml +311 -0
  169. package/builtins/ja/workflows/dual-mini.yaml +1 -0
  170. package/builtins/ja/workflows/dual.yaml +29 -58
  171. package/builtins/ja/workflows/frontend-for-local-llm.yaml +288 -0
  172. package/builtins/ja/workflows/frontend-maintenance.yaml +34 -91
  173. package/builtins/ja/workflows/frontend-mini.yaml +1 -0
  174. package/builtins/ja/workflows/frontend.yaml +27 -85
  175. package/builtins/ja/workflows/merge-readiness-dual-final-gate.yaml +92 -0
  176. package/builtins/ja/workflows/merge-readiness-final-gate.yaml +79 -0
  177. package/builtins/ja/workflows/{peer-review-with-fc.yaml → peer-review-for-local-llm.yaml} +48 -37
  178. package/builtins/ja/workflows/peer-review.yaml +25 -20
  179. package/builtins/ja/workflows/research.yaml +1 -0
  180. package/builtins/ja/workflows/review-backend-cqrs.yaml +63 -35
  181. package/builtins/ja/workflows/review-backend.yaml +63 -35
  182. package/builtins/ja/workflows/review-default.yaml +111 -79
  183. package/builtins/ja/workflows/review-dual-cqrs.yaml +63 -35
  184. package/builtins/ja/workflows/review-dual.yaml +63 -35
  185. package/builtins/ja/workflows/review-fix-backend-cqrs.yaml +27 -87
  186. package/builtins/ja/workflows/review-fix-backend.yaml +25 -86
  187. package/builtins/ja/workflows/review-fix-default.yaml +17 -87
  188. package/builtins/ja/workflows/review-fix-dual-cqrs.yaml +29 -90
  189. package/builtins/ja/workflows/review-fix-dual.yaml +27 -89
  190. package/builtins/ja/workflows/review-fix-frontend.yaml +25 -87
  191. package/builtins/ja/workflows/review-fix-takt-default.yaml +67 -362
  192. package/builtins/ja/workflows/review-frontend.yaml +63 -35
  193. package/builtins/ja/workflows/review-takt-default.yaml +112 -80
  194. package/builtins/ja/workflows/takt-default-for-local-llm.yaml +282 -0
  195. package/builtins/ja/workflows/takt-default-refresh-all.yaml +20 -59
  196. package/builtins/ja/workflows/takt-default-refresh-fast.yaml +19 -57
  197. package/builtins/ja/workflows/takt-default.yaml +3 -25
  198. package/builtins/ja/workflows/terraform.yaml +81 -44
  199. package/builtins/skill/references/yaml-schema.md +21 -1
  200. package/builtins/skill-codex/references/yaml-schema.md +21 -1
  201. package/dist/agents/agent-usecases.d.ts +1 -0
  202. package/dist/agents/agent-usecases.d.ts.map +1 -1
  203. package/dist/agents/agent-usecases.js +1 -0
  204. package/dist/agents/agent-usecases.js.map +1 -1
  205. package/dist/agents/auto-routing-usecase.d.ts +23 -0
  206. package/dist/agents/auto-routing-usecase.d.ts.map +1 -0
  207. package/dist/agents/auto-routing-usecase.js +216 -0
  208. package/dist/agents/auto-routing-usecase.js.map +1 -0
  209. package/dist/agents/decompose-task-usecase.d.ts +1 -0
  210. package/dist/agents/decompose-task-usecase.d.ts.map +1 -1
  211. package/dist/agents/decompose-task-usecase.js +2 -0
  212. package/dist/agents/decompose-task-usecase.js.map +1 -1
  213. package/dist/agents/judge-utils.d.ts.map +1 -1
  214. package/dist/agents/judge-utils.js +4 -3
  215. package/dist/agents/judge-utils.js.map +1 -1
  216. package/dist/agents/runner.d.ts.map +1 -1
  217. package/dist/agents/runner.js +2 -3
  218. package/dist/agents/runner.js.map +1 -1
  219. package/dist/agents/structured-caller/prompt-based-structured-caller.d.ts.map +1 -1
  220. package/dist/agents/structured-caller/prompt-based-structured-caller.js +2 -0
  221. package/dist/agents/structured-caller/prompt-based-structured-caller.js.map +1 -1
  222. package/dist/agents/structured-caller/shared.js +1 -1
  223. package/dist/agents/structured-caller/shared.js.map +1 -1
  224. package/dist/app/acp/agent.d.ts +28 -0
  225. package/dist/app/acp/agent.d.ts.map +1 -0
  226. package/dist/app/acp/agent.js +279 -0
  227. package/dist/app/acp/agent.js.map +1 -0
  228. package/dist/app/acp/confirmationBridge.d.ts +5 -0
  229. package/dist/app/acp/confirmationBridge.d.ts.map +1 -0
  230. package/dist/app/acp/confirmationBridge.js +194 -0
  231. package/dist/app/acp/confirmationBridge.js.map +1 -0
  232. package/dist/app/acp/conversationFactory.d.ts +4 -0
  233. package/dist/app/acp/conversationFactory.d.ts.map +1 -0
  234. package/dist/app/acp/conversationFactory.js +33 -0
  235. package/dist/app/acp/conversationFactory.js.map +1 -0
  236. package/dist/app/acp/enqueue.d.ts +33 -0
  237. package/dist/app/acp/enqueue.d.ts.map +1 -0
  238. package/dist/app/acp/enqueue.js +45 -0
  239. package/dist/app/acp/enqueue.js.map +1 -0
  240. package/dist/app/acp/index.d.ts +7 -0
  241. package/dist/app/acp/index.d.ts.map +1 -0
  242. package/dist/app/acp/index.js +125 -0
  243. package/dist/app/acp/index.js.map +1 -0
  244. package/dist/app/acp/intent.d.ts +10 -0
  245. package/dist/app/acp/intent.d.ts.map +1 -0
  246. package/dist/app/acp/intent.js +210 -0
  247. package/dist/app/acp/intent.js.map +1 -0
  248. package/dist/app/acp/mcpServers.d.ts +4 -0
  249. package/dist/app/acp/mcpServers.d.ts.map +1 -0
  250. package/dist/app/acp/mcpServers.js +51 -0
  251. package/dist/app/acp/mcpServers.js.map +1 -0
  252. package/dist/app/acp/promptContent.d.ts +3 -0
  253. package/dist/app/acp/promptContent.d.ts.map +1 -0
  254. package/dist/app/acp/promptContent.js +23 -0
  255. package/dist/app/acp/promptContent.js.map +1 -0
  256. package/dist/app/acp/sessionStore.d.ts +19 -0
  257. package/dist/app/acp/sessionStore.d.ts.map +1 -0
  258. package/dist/app/acp/sessionStore.js +50 -0
  259. package/dist/app/acp/sessionStore.js.map +1 -0
  260. package/dist/app/acp/sessionUpdates.d.ts +8 -0
  261. package/dist/app/acp/sessionUpdates.d.ts.map +1 -0
  262. package/dist/app/acp/sessionUpdates.js +108 -0
  263. package/dist/app/acp/sessionUpdates.js.map +1 -0
  264. package/dist/app/acp/taskContext.d.ts +17 -0
  265. package/dist/app/acp/taskContext.d.ts.map +1 -0
  266. package/dist/app/acp/taskContext.js +81 -0
  267. package/dist/app/acp/taskContext.js.map +1 -0
  268. package/dist/app/acp/types.d.ts +33 -0
  269. package/dist/app/acp/types.d.ts.map +1 -0
  270. package/dist/app/acp/types.js +2 -0
  271. package/dist/app/acp/types.js.map +1 -0
  272. package/dist/app/cli/commands.js +28 -1
  273. package/dist/app/cli/commands.js.map +1 -1
  274. package/dist/app/cli/helpers.d.ts.map +1 -1
  275. package/dist/app/cli/helpers.js +13 -1
  276. package/dist/app/cli/helpers.js.map +1 -1
  277. package/dist/app/cli/program.d.ts.map +1 -1
  278. package/dist/app/cli/program.js +6 -5
  279. package/dist/app/cli/program.js.map +1 -1
  280. package/dist/app/cli/routing.d.ts.map +1 -1
  281. package/dist/app/cli/routing.js +56 -47
  282. package/dist/app/cli/routing.js.map +1 -1
  283. package/dist/app/mcp/index.d.ts +3 -0
  284. package/dist/app/mcp/index.d.ts.map +1 -0
  285. package/dist/app/mcp/index.js +16 -0
  286. package/dist/app/mcp/index.js.map +1 -0
  287. package/dist/app/mcp/server.d.ts +2 -0
  288. package/dist/app/mcp/server.d.ts.map +1 -0
  289. package/dist/app/mcp/server.js +2 -0
  290. package/dist/app/mcp/server.js.map +1 -0
  291. package/dist/core/config/provider-resolution.d.ts +1 -0
  292. package/dist/core/config/provider-resolution.d.ts.map +1 -1
  293. package/dist/core/config/provider-resolution.js +19 -0
  294. package/dist/core/config/provider-resolution.js.map +1 -1
  295. package/dist/core/logging/providerEvent.d.ts +3 -2
  296. package/dist/core/logging/providerEvent.d.ts.map +1 -1
  297. package/dist/core/logging/providerEvent.js.map +1 -1
  298. package/dist/core/logging/providerEventLogger.d.ts +2 -1
  299. package/dist/core/logging/providerEventLogger.d.ts.map +1 -1
  300. package/dist/core/logging/providerEventLogger.js.map +1 -1
  301. package/dist/core/logging/usageEventLogger.d.ts +2 -1
  302. package/dist/core/logging/usageEventLogger.d.ts.map +1 -1
  303. package/dist/core/logging/usageEventLogger.js +3 -0
  304. package/dist/core/logging/usageEventLogger.js.map +1 -1
  305. package/dist/core/models/config-schemas.d.ts +301 -97
  306. package/dist/core/models/config-schemas.d.ts.map +1 -1
  307. package/dist/core/models/config-schemas.js +8 -5
  308. package/dist/core/models/config-schemas.js.map +1 -1
  309. package/dist/core/models/config-types.d.ts +34 -2
  310. package/dist/core/models/config-types.d.ts.map +1 -1
  311. package/dist/core/models/finding-schemas.d.ts +167 -24
  312. package/dist/core/models/finding-schemas.d.ts.map +1 -1
  313. package/dist/core/models/finding-schemas.js +82 -9
  314. package/dist/core/models/finding-schemas.js.map +1 -1
  315. package/dist/core/models/finding-types.d.ts +43 -2
  316. package/dist/core/models/finding-types.d.ts.map +1 -1
  317. package/dist/core/models/finding-types.js +3 -2
  318. package/dist/core/models/finding-types.js.map +1 -1
  319. package/dist/core/models/index.d.ts +2 -1
  320. package/dist/core/models/index.d.ts.map +1 -1
  321. package/dist/core/models/index.js +1 -0
  322. package/dist/core/models/index.js.map +1 -1
  323. package/dist/core/models/part.d.ts +1 -0
  324. package/dist/core/models/part.d.ts.map +1 -1
  325. package/dist/core/models/schema-base.d.ts +189 -36
  326. package/dist/core/models/schema-base.d.ts.map +1 -1
  327. package/dist/core/models/schema-base.js +68 -0
  328. package/dist/core/models/schema-base.js.map +1 -1
  329. package/dist/core/models/types.d.ts +3 -2
  330. package/dist/core/models/types.d.ts.map +1 -1
  331. package/dist/core/models/types.js +1 -1
  332. package/dist/core/models/types.js.map +1 -1
  333. package/dist/core/models/workflow-condition-expression.d.ts +17 -0
  334. package/dist/core/models/workflow-condition-expression.d.ts.map +1 -1
  335. package/dist/core/models/workflow-condition-expression.js +85 -2
  336. package/dist/core/models/workflow-condition-expression.js.map +1 -1
  337. package/dist/core/models/workflow-provider-options.d.ts +1 -1
  338. package/dist/core/models/workflow-provider-options.d.ts.map +1 -1
  339. package/dist/core/models/workflow-schemas.d.ts +1134 -250
  340. package/dist/core/models/workflow-schemas.d.ts.map +1 -1
  341. package/dist/core/models/workflow-schemas.js +124 -60
  342. package/dist/core/models/workflow-schemas.js.map +1 -1
  343. package/dist/core/models/workflow-session-constraints.d.ts +3 -0
  344. package/dist/core/models/workflow-session-constraints.d.ts.map +1 -0
  345. package/dist/core/models/workflow-session-constraints.js +3 -0
  346. package/dist/core/models/workflow-session-constraints.js.map +1 -0
  347. package/dist/core/models/workflow-types.d.ts +44 -6
  348. package/dist/core/models/workflow-types.d.ts.map +1 -1
  349. package/dist/core/models/workflow-types.js +1 -0
  350. package/dist/core/models/workflow-types.js.map +1 -1
  351. package/dist/core/runtime/runtime-environment.d.ts.map +1 -1
  352. package/dist/core/runtime/runtime-environment.js +19 -0
  353. package/dist/core/runtime/runtime-environment.js.map +1 -1
  354. package/dist/core/workflow/auto-routing/resolver.d.ts +43 -0
  355. package/dist/core/workflow/auto-routing/resolver.d.ts.map +1 -0
  356. package/dist/core/workflow/auto-routing/resolver.js +218 -0
  357. package/dist/core/workflow/auto-routing/resolver.js.map +1 -0
  358. package/dist/core/workflow/auto-routing/workflow-auto-provider.d.ts +16 -0
  359. package/dist/core/workflow/auto-routing/workflow-auto-provider.d.ts.map +1 -0
  360. package/dist/core/workflow/auto-routing/workflow-auto-provider.js +64 -0
  361. package/dist/core/workflow/auto-routing/workflow-auto-provider.js.map +1 -0
  362. package/dist/core/workflow/engine/LoopMonitorJudgeRunner.d.ts +1 -1
  363. package/dist/core/workflow/engine/LoopMonitorJudgeRunner.d.ts.map +1 -1
  364. package/dist/core/workflow/engine/LoopMonitorJudgeRunner.js +15 -1
  365. package/dist/core/workflow/engine/LoopMonitorJudgeRunner.js.map +1 -1
  366. package/dist/core/workflow/engine/OptionsBuilder.d.ts +15 -5
  367. package/dist/core/workflow/engine/OptionsBuilder.d.ts.map +1 -1
  368. package/dist/core/workflow/engine/OptionsBuilder.js +122 -13
  369. package/dist/core/workflow/engine/OptionsBuilder.js.map +1 -1
  370. package/dist/core/workflow/engine/ParallelRunner.d.ts +12 -1
  371. package/dist/core/workflow/engine/ParallelRunner.d.ts.map +1 -1
  372. package/dist/core/workflow/engine/ParallelRunner.js +356 -33
  373. package/dist/core/workflow/engine/ParallelRunner.js.map +1 -1
  374. package/dist/core/workflow/engine/StepExecutor.d.ts +10 -0
  375. package/dist/core/workflow/engine/StepExecutor.d.ts.map +1 -1
  376. package/dist/core/workflow/engine/StepExecutor.js +89 -31
  377. package/dist/core/workflow/engine/StepExecutor.js.map +1 -1
  378. package/dist/core/workflow/engine/TeamLeaderRunner.d.ts +10 -2
  379. package/dist/core/workflow/engine/TeamLeaderRunner.d.ts.map +1 -1
  380. package/dist/core/workflow/engine/TeamLeaderRunner.js +111 -9
  381. package/dist/core/workflow/engine/TeamLeaderRunner.js.map +1 -1
  382. package/dist/core/workflow/engine/WorkflowCallExecutor.d.ts +11 -1
  383. package/dist/core/workflow/engine/WorkflowCallExecutor.d.ts.map +1 -1
  384. package/dist/core/workflow/engine/WorkflowCallExecutor.js +43 -7
  385. package/dist/core/workflow/engine/WorkflowCallExecutor.js.map +1 -1
  386. package/dist/core/workflow/engine/WorkflowCallRunner.d.ts +9 -0
  387. package/dist/core/workflow/engine/WorkflowCallRunner.d.ts.map +1 -1
  388. package/dist/core/workflow/engine/WorkflowCallRunner.js +65 -14
  389. package/dist/core/workflow/engine/WorkflowCallRunner.js.map +1 -1
  390. package/dist/core/workflow/engine/WorkflowEngine.d.ts.map +1 -1
  391. package/dist/core/workflow/engine/WorkflowEngine.js +27 -9
  392. package/dist/core/workflow/engine/WorkflowEngine.js.map +1 -1
  393. package/dist/core/workflow/engine/WorkflowEngineSetup.d.ts.map +1 -1
  394. package/dist/core/workflow/engine/WorkflowEngineSetup.js +29 -20
  395. package/dist/core/workflow/engine/WorkflowEngineSetup.js.map +1 -1
  396. package/dist/core/workflow/engine/WorkflowEngineStepCoordinator.d.ts +2 -2
  397. package/dist/core/workflow/engine/WorkflowEngineStepCoordinator.d.ts.map +1 -1
  398. package/dist/core/workflow/engine/WorkflowEngineStepCoordinator.js +2 -2
  399. package/dist/core/workflow/engine/WorkflowEngineStepCoordinator.js.map +1 -1
  400. package/dist/core/workflow/engine/WorkflowRunLoop.d.ts +1 -1
  401. package/dist/core/workflow/engine/WorkflowRunLoop.d.ts.map +1 -1
  402. package/dist/core/workflow/engine/WorkflowRunLoop.js +51 -7
  403. package/dist/core/workflow/engine/WorkflowRunLoop.js.map +1 -1
  404. package/dist/core/workflow/engine/WorkflowValidator.d.ts.map +1 -1
  405. package/dist/core/workflow/engine/WorkflowValidator.js +79 -7
  406. package/dist/core/workflow/engine/WorkflowValidator.js.map +1 -1
  407. package/dist/core/workflow/engine/engine-provider-options.d.ts +1 -0
  408. package/dist/core/workflow/engine/engine-provider-options.d.ts.map +1 -1
  409. package/dist/core/workflow/engine/engine-provider-options.js +12 -0
  410. package/dist/core/workflow/engine/engine-provider-options.js.map +1 -1
  411. package/dist/core/workflow/engine/session-compaction.d.ts +10 -0
  412. package/dist/core/workflow/engine/session-compaction.d.ts.map +1 -0
  413. package/dist/core/workflow/engine/session-compaction.js +42 -0
  414. package/dist/core/workflow/engine/session-compaction.js.map +1 -0
  415. package/dist/core/workflow/engine/team-leader-part-runner.d.ts.map +1 -1
  416. package/dist/core/workflow/engine/team-leader-part-runner.js +3 -1
  417. package/dist/core/workflow/engine/team-leader-part-runner.js.map +1 -1
  418. package/dist/core/workflow/evaluation/RuleEvaluator.d.ts +0 -1
  419. package/dist/core/workflow/evaluation/RuleEvaluator.d.ts.map +1 -1
  420. package/dist/core/workflow/evaluation/RuleEvaluator.js +22 -34
  421. package/dist/core/workflow/evaluation/RuleEvaluator.js.map +1 -1
  422. package/dist/core/workflow/evaluation/rule-utils.d.ts +33 -1
  423. package/dist/core/workflow/evaluation/rule-utils.d.ts.map +1 -1
  424. package/dist/core/workflow/evaluation/rule-utils.js +77 -5
  425. package/dist/core/workflow/evaluation/rule-utils.js.map +1 -1
  426. package/dist/core/workflow/evaluation/when-evaluator.d.ts +1 -0
  427. package/dist/core/workflow/evaluation/when-evaluator.d.ts.map +1 -1
  428. package/dist/core/workflow/evaluation/when-evaluator.js +18 -40
  429. package/dist/core/workflow/evaluation/when-evaluator.js.map +1 -1
  430. package/dist/core/workflow/findings/context.d.ts +4 -0
  431. package/dist/core/workflow/findings/context.d.ts.map +1 -1
  432. package/dist/core/workflow/findings/context.js +27 -0
  433. package/dist/core/workflow/findings/context.js.map +1 -1
  434. package/dist/core/workflow/findings/manager-output-validation.d.ts +14 -0
  435. package/dist/core/workflow/findings/manager-output-validation.d.ts.map +1 -1
  436. package/dist/core/workflow/findings/manager-output-validation.js +158 -8
  437. package/dist/core/workflow/findings/manager-output-validation.js.map +1 -1
  438. package/dist/core/workflow/findings/manager-runner.d.ts +17 -6
  439. package/dist/core/workflow/findings/manager-runner.d.ts.map +1 -1
  440. package/dist/core/workflow/findings/manager-runner.js +157 -59
  441. package/dist/core/workflow/findings/manager-runner.js.map +1 -1
  442. package/dist/core/workflow/findings/manager-step.d.ts +8 -0
  443. package/dist/core/workflow/findings/manager-step.d.ts.map +1 -0
  444. package/dist/core/workflow/findings/manager-step.js +27 -0
  445. package/dist/core/workflow/findings/manager-step.js.map +1 -0
  446. package/dist/core/workflow/findings/mechanical-classification.d.ts +24 -0
  447. package/dist/core/workflow/findings/mechanical-classification.d.ts.map +1 -0
  448. package/dist/core/workflow/findings/mechanical-classification.js +115 -0
  449. package/dist/core/workflow/findings/mechanical-classification.js.map +1 -0
  450. package/dist/core/workflow/findings/reconciler.d.ts +1 -0
  451. package/dist/core/workflow/findings/reconciler.d.ts.map +1 -1
  452. package/dist/core/workflow/findings/reconciler.js +90 -4
  453. package/dist/core/workflow/findings/reconciler.js.map +1 -1
  454. package/dist/core/workflow/instruction/InstructionBuilder.d.ts.map +1 -1
  455. package/dist/core/workflow/instruction/InstructionBuilder.js +7 -15
  456. package/dist/core/workflow/instruction/InstructionBuilder.js.map +1 -1
  457. package/dist/core/workflow/instruction/ReportInstructionBuilder.d.ts.map +1 -1
  458. package/dist/core/workflow/instruction/ReportInstructionBuilder.js +9 -11
  459. package/dist/core/workflow/instruction/ReportInstructionBuilder.js.map +1 -1
  460. package/dist/core/workflow/instruction/finding-contract-instruction.d.ts +36 -0
  461. package/dist/core/workflow/instruction/finding-contract-instruction.d.ts.map +1 -0
  462. package/dist/core/workflow/instruction/finding-contract-instruction.js +39 -0
  463. package/dist/core/workflow/instruction/finding-contract-instruction.js.map +1 -0
  464. package/dist/core/workflow/instruction/instruction-context.d.ts +16 -0
  465. package/dist/core/workflow/instruction/instruction-context.d.ts.map +1 -1
  466. package/dist/core/workflow/instruction/instruction-context.js +14 -18
  467. package/dist/core/workflow/instruction/instruction-context.js.map +1 -1
  468. package/dist/core/workflow/instruction/status-rules.d.ts.map +1 -1
  469. package/dist/core/workflow/instruction/status-rules.js +7 -2
  470. package/dist/core/workflow/instruction/status-rules.js.map +1 -1
  471. package/dist/core/workflow/permission-profile-resolution.d.ts +6 -0
  472. package/dist/core/workflow/permission-profile-resolution.d.ts.map +1 -1
  473. package/dist/core/workflow/permission-profile-resolution.js +11 -0
  474. package/dist/core/workflow/permission-profile-resolution.js.map +1 -1
  475. package/dist/core/workflow/phase-runner.d.ts +17 -10
  476. package/dist/core/workflow/phase-runner.d.ts.map +1 -1
  477. package/dist/core/workflow/phase-runner.js +1 -1
  478. package/dist/core/workflow/phase-runner.js.map +1 -1
  479. package/dist/core/workflow/provider-model-requirements.d.ts +6 -0
  480. package/dist/core/workflow/provider-model-requirements.d.ts.map +1 -0
  481. package/dist/core/workflow/provider-model-requirements.js +15 -0
  482. package/dist/core/workflow/provider-model-requirements.js.map +1 -0
  483. package/dist/core/workflow/provider-options-trace.d.ts +1 -1
  484. package/dist/core/workflow/provider-options-trace.d.ts.map +1 -1
  485. package/dist/core/workflow/provider-resolution.d.ts +14 -11
  486. package/dist/core/workflow/provider-resolution.d.ts.map +1 -1
  487. package/dist/core/workflow/provider-resolution.js +38 -26
  488. package/dist/core/workflow/provider-resolution.js.map +1 -1
  489. package/dist/core/workflow/report-phase-runner.d.ts +5 -2
  490. package/dist/core/workflow/report-phase-runner.d.ts.map +1 -1
  491. package/dist/core/workflow/report-phase-runner.js +135 -43
  492. package/dist/core/workflow/report-phase-runner.js.map +1 -1
  493. package/dist/core/workflow/status-judgment-phase.d.ts +2 -2
  494. package/dist/core/workflow/status-judgment-phase.d.ts.map +1 -1
  495. package/dist/core/workflow/status-judgment-phase.js +1 -7
  496. package/dist/core/workflow/status-judgment-phase.js.map +1 -1
  497. package/dist/core/workflow/system/system-step-effect-runner.js +2 -2
  498. package/dist/core/workflow/system/system-step-effect-runner.js.map +1 -1
  499. package/dist/core/workflow/system/system-step-services.d.ts +101 -0
  500. package/dist/core/workflow/system/system-step-services.d.ts.map +1 -1
  501. package/dist/core/workflow/types.d.ts +25 -8
  502. package/dist/core/workflow/types.d.ts.map +1 -1
  503. package/dist/features/analytics/events.d.ts +30 -3
  504. package/dist/features/analytics/events.d.ts.map +1 -1
  505. package/dist/features/analytics/events.js +1 -1
  506. package/dist/features/analytics/index.d.ts +2 -2
  507. package/dist/features/analytics/index.d.ts.map +1 -1
  508. package/dist/features/analytics/index.js.map +1 -1
  509. package/dist/features/analytics/writer.d.ts +8 -14
  510. package/dist/features/analytics/writer.d.ts.map +1 -1
  511. package/dist/features/analytics/writer.js +27 -17
  512. package/dist/features/analytics/writer.js.map +1 -1
  513. package/dist/features/exec/assistantSession.d.ts +2 -0
  514. package/dist/features/exec/assistantSession.d.ts.map +1 -1
  515. package/dist/features/exec/assistantSession.js +1 -1
  516. package/dist/features/exec/assistantSession.js.map +1 -1
  517. package/dist/features/exec/command.d.ts.map +1 -1
  518. package/dist/features/exec/command.js +98 -54
  519. package/dist/features/exec/command.js.map +1 -1
  520. package/dist/features/exec/commandAvailability.js +1 -1
  521. package/dist/features/exec/commandAvailability.js.map +1 -1
  522. package/dist/features/exec/configOps.d.ts.map +1 -1
  523. package/dist/features/exec/configOps.js +6 -5
  524. package/dist/features/exec/configOps.js.map +1 -1
  525. package/dist/features/exec/configValidation.d.ts +1 -1
  526. package/dist/features/exec/configValidation.d.ts.map +1 -1
  527. package/dist/features/exec/configValidation.js +9 -13
  528. package/dist/features/exec/configValidation.js.map +1 -1
  529. package/dist/features/exec/runtimeConfig.d.ts.map +1 -1
  530. package/dist/features/exec/runtimeConfig.js +4 -2
  531. package/dist/features/exec/runtimeConfig.js.map +1 -1
  532. package/dist/features/exec/setupMenu.js +2 -2
  533. package/dist/features/exec/setupMenu.js.map +1 -1
  534. package/dist/features/exec/workflowRunner.d.ts +2 -1
  535. package/dist/features/exec/workflowRunner.d.ts.map +1 -1
  536. package/dist/features/exec/workflowRunner.js +2 -1
  537. package/dist/features/exec/workflowRunner.js.map +1 -1
  538. package/dist/features/exec/workflowTemplate.d.ts.map +1 -1
  539. package/dist/features/exec/workflowTemplate.js +4 -4
  540. package/dist/features/exec/workflowTemplate.js.map +1 -1
  541. package/dist/features/interactive/aiCaller.d.ts +4 -2
  542. package/dist/features/interactive/aiCaller.d.ts.map +1 -1
  543. package/dist/features/interactive/aiCaller.js +38 -11
  544. package/dist/features/interactive/aiCaller.js.map +1 -1
  545. package/dist/features/interactive/assistantConfig.d.ts.map +1 -1
  546. package/dist/features/interactive/assistantConfig.js +3 -2
  547. package/dist/features/interactive/assistantConfig.js.map +1 -1
  548. package/dist/features/interactive/conversationLoop.d.ts.map +1 -1
  549. package/dist/features/interactive/conversationLoop.js +164 -141
  550. package/dist/features/interactive/conversationLoop.js.map +1 -1
  551. package/dist/features/interactive/conversationSession.d.ts +44 -0
  552. package/dist/features/interactive/conversationSession.d.ts.map +1 -0
  553. package/dist/features/interactive/conversationSession.js +133 -0
  554. package/dist/features/interactive/conversationSession.js.map +1 -0
  555. package/dist/features/interactive/imageAttachments.d.ts +12 -8
  556. package/dist/features/interactive/imageAttachments.d.ts.map +1 -1
  557. package/dist/features/interactive/imageAttachments.js +67 -14
  558. package/dist/features/interactive/imageAttachments.js.map +1 -1
  559. package/dist/features/interactive/index.d.ts +1 -0
  560. package/dist/features/interactive/index.d.ts.map +1 -1
  561. package/dist/features/interactive/index.js +1 -0
  562. package/dist/features/interactive/index.js.map +1 -1
  563. package/dist/features/interactive/instructModeTypes.d.ts +2 -2
  564. package/dist/features/interactive/instructModeTypes.d.ts.map +1 -1
  565. package/dist/features/interactive/interactive-summary.d.ts.map +1 -1
  566. package/dist/features/interactive/interactive-summary.js +8 -0
  567. package/dist/features/interactive/interactive-summary.js.map +1 -1
  568. package/dist/features/interactive/interactive.d.ts +9 -6
  569. package/dist/features/interactive/interactive.d.ts.map +1 -1
  570. package/dist/features/interactive/interactive.js +10 -4
  571. package/dist/features/interactive/interactive.js.map +1 -1
  572. package/dist/features/interactive/interactiveApplication.d.ts +5 -0
  573. package/dist/features/interactive/interactiveApplication.d.ts.map +1 -0
  574. package/dist/features/interactive/interactiveApplication.js +10 -0
  575. package/dist/features/interactive/interactiveApplication.js.map +1 -0
  576. package/dist/features/interactive/passthroughMode.d.ts.map +1 -1
  577. package/dist/features/interactive/passthroughMode.js +22 -16
  578. package/dist/features/interactive/passthroughMode.js.map +1 -1
  579. package/dist/features/interactive/promptSections.js +2 -2
  580. package/dist/features/interactive/promptSections.js.map +1 -1
  581. package/dist/features/interactive/quietMode.d.ts.map +1 -1
  582. package/dist/features/interactive/quietMode.js +55 -40
  583. package/dist/features/interactive/quietMode.js.map +1 -1
  584. package/dist/features/interactive/retryMode.d.ts.map +1 -1
  585. package/dist/features/interactive/retryMode.js +5 -4
  586. package/dist/features/interactive/retryMode.js.map +1 -1
  587. package/dist/features/mcp/operations.d.ts +25 -0
  588. package/dist/features/mcp/operations.d.ts.map +1 -0
  589. package/dist/features/mcp/operations.js +150 -0
  590. package/dist/features/mcp/operations.js.map +1 -0
  591. package/dist/features/mcp/schemas.d.ts +50 -0
  592. package/dist/features/mcp/schemas.d.ts.map +1 -0
  593. package/dist/features/mcp/schemas.js +59 -0
  594. package/dist/features/mcp/schemas.js.map +1 -0
  595. package/dist/features/mcp/server.d.ts +7 -0
  596. package/dist/features/mcp/server.d.ts.map +1 -0
  597. package/dist/features/mcp/server.js +36 -0
  598. package/dist/features/mcp/server.js.map +1 -0
  599. package/dist/features/pipeline/steps.d.ts +1 -1
  600. package/dist/features/pipeline/steps.d.ts.map +1 -1
  601. package/dist/features/pipeline/steps.js +6 -2
  602. package/dist/features/pipeline/steps.js.map +1 -1
  603. package/dist/features/prompt/preview.d.ts.map +1 -1
  604. package/dist/features/prompt/preview.js +37 -1
  605. package/dist/features/prompt/preview.js.map +1 -1
  606. package/dist/features/tasks/add/index.d.ts +8 -20
  607. package/dist/features/tasks/add/index.d.ts.map +1 -1
  608. package/dist/features/tasks/add/index.js +42 -61
  609. package/dist/features/tasks/add/index.js.map +1 -1
  610. package/dist/features/tasks/attachments.d.ts +4 -10
  611. package/dist/features/tasks/attachments.d.ts.map +1 -1
  612. package/dist/features/tasks/attachments.js +14 -42
  613. package/dist/features/tasks/attachments.js.map +1 -1
  614. package/dist/features/tasks/execute/analyticsEmitter.d.ts +7 -2
  615. package/dist/features/tasks/execute/analyticsEmitter.d.ts.map +1 -1
  616. package/dist/features/tasks/execute/analyticsEmitter.js +76 -2
  617. package/dist/features/tasks/execute/analyticsEmitter.js.map +1 -1
  618. package/dist/features/tasks/execute/outputFns.d.ts +1 -1
  619. package/dist/features/tasks/execute/outputFns.d.ts.map +1 -1
  620. package/dist/features/tasks/execute/outputFns.js +17 -1
  621. package/dist/features/tasks/execute/outputFns.js.map +1 -1
  622. package/dist/features/tasks/execute/postExecution.d.ts +4 -1
  623. package/dist/features/tasks/execute/postExecution.d.ts.map +1 -1
  624. package/dist/features/tasks/execute/postExecution.js +33 -14
  625. package/dist/features/tasks/execute/postExecution.js.map +1 -1
  626. package/dist/features/tasks/execute/resolveTask.d.ts +9 -3
  627. package/dist/features/tasks/execute/resolveTask.d.ts.map +1 -1
  628. package/dist/features/tasks/execute/resolveTask.js +46 -14
  629. package/dist/features/tasks/execute/resolveTask.js.map +1 -1
  630. package/dist/features/tasks/execute/runAllTasks.d.ts.map +1 -1
  631. package/dist/features/tasks/execute/runAllTasks.js +3 -0
  632. package/dist/features/tasks/execute/runAllTasks.js.map +1 -1
  633. package/dist/features/tasks/execute/runTaskExecution.d.ts +7 -1
  634. package/dist/features/tasks/execute/runTaskExecution.d.ts.map +1 -1
  635. package/dist/features/tasks/execute/runTaskExecution.js +11 -8
  636. package/dist/features/tasks/execute/runTaskExecution.js.map +1 -1
  637. package/dist/features/tasks/execute/taskExecution.d.ts +12 -3
  638. package/dist/features/tasks/execute/taskExecution.d.ts.map +1 -1
  639. package/dist/features/tasks/execute/taskExecution.js +63 -16
  640. package/dist/features/tasks/execute/taskExecution.js.map +1 -1
  641. package/dist/features/tasks/execute/taskResultHandler.d.ts +2 -2
  642. package/dist/features/tasks/execute/taskResultHandler.d.ts.map +1 -1
  643. package/dist/features/tasks/execute/taskResultHandler.js +8 -4
  644. package/dist/features/tasks/execute/taskResultHandler.js.map +1 -1
  645. package/dist/features/tasks/execute/taskWorkflowExecution.d.ts.map +1 -1
  646. package/dist/features/tasks/execute/taskWorkflowExecution.js +62 -9
  647. package/dist/features/tasks/execute/taskWorkflowExecution.js.map +1 -1
  648. package/dist/features/tasks/execute/traceTaskMetadata.js +3 -6
  649. package/dist/features/tasks/execute/traceTaskMetadata.js.map +1 -1
  650. package/dist/features/tasks/execute/types.d.ts +109 -7
  651. package/dist/features/tasks/execute/types.d.ts.map +1 -1
  652. package/dist/features/tasks/execute/workflowExecution.d.ts +3 -1
  653. package/dist/features/tasks/execute/workflowExecution.d.ts.map +1 -1
  654. package/dist/features/tasks/execute/workflowExecution.js +49 -5
  655. package/dist/features/tasks/execute/workflowExecution.js.map +1 -1
  656. package/dist/features/tasks/execute/workflowExecutionApi.d.ts +6 -0
  657. package/dist/features/tasks/execute/workflowExecutionApi.d.ts.map +1 -0
  658. package/dist/features/tasks/execute/workflowExecutionApi.js +25 -0
  659. package/dist/features/tasks/execute/workflowExecutionApi.js.map +1 -0
  660. package/dist/features/tasks/execute/workflowExecutionBootstrap.d.ts +3 -1
  661. package/dist/features/tasks/execute/workflowExecutionBootstrap.d.ts.map +1 -1
  662. package/dist/features/tasks/execute/workflowExecutionBootstrap.js +51 -20
  663. package/dist/features/tasks/execute/workflowExecutionBootstrap.js.map +1 -1
  664. package/dist/features/tasks/execute/workflowExecutionContext.d.ts.map +1 -1
  665. package/dist/features/tasks/execute/workflowExecutionContext.js +1 -1
  666. package/dist/features/tasks/execute/workflowExecutionContext.js.map +1 -1
  667. package/dist/features/tasks/execute/workflowExecutionEvents.d.ts +14 -1
  668. package/dist/features/tasks/execute/workflowExecutionEvents.d.ts.map +1 -1
  669. package/dist/features/tasks/execute/workflowExecutionEvents.js +246 -4
  670. package/dist/features/tasks/execute/workflowExecutionEvents.js.map +1 -1
  671. package/dist/features/tasks/list/instructMode.d.ts.map +1 -1
  672. package/dist/features/tasks/list/instructMode.js +5 -4
  673. package/dist/features/tasks/list/instructMode.js.map +1 -1
  674. package/dist/features/tasks/list/requeueHelpers.d.ts +1 -0
  675. package/dist/features/tasks/list/requeueHelpers.d.ts.map +1 -1
  676. package/dist/features/tasks/list/requeueHelpers.js +3 -0
  677. package/dist/features/tasks/list/requeueHelpers.js.map +1 -1
  678. package/dist/features/tasks/list/taskInstructionActions.d.ts.map +1 -1
  679. package/dist/features/tasks/list/taskInstructionActions.js +33 -25
  680. package/dist/features/tasks/list/taskInstructionActions.js.map +1 -1
  681. package/dist/features/tasks/list/taskRetryActions.d.ts.map +1 -1
  682. package/dist/features/tasks/list/taskRetryActions.js +34 -30
  683. package/dist/features/tasks/list/taskRetryActions.js.map +1 -1
  684. package/dist/features/tasks/resume/directInstructMode.d.ts.map +1 -1
  685. package/dist/features/tasks/resume/directInstructMode.js +11 -2
  686. package/dist/features/tasks/resume/directInstructMode.js.map +1 -1
  687. package/dist/features/tasks/resume/index.d.ts.map +1 -1
  688. package/dist/features/tasks/resume/index.js +73 -24
  689. package/dist/features/tasks/resume/index.js.map +1 -1
  690. package/dist/features/tasks/{list/retryTaskSpecAttachments.d.ts → retryTaskSpecAttachments.d.ts} +3 -1
  691. package/dist/features/tasks/retryTaskSpecAttachments.d.ts.map +1 -0
  692. package/dist/features/tasks/{list/retryTaskSpecAttachments.js → retryTaskSpecAttachments.js} +4 -3
  693. package/dist/features/tasks/retryTaskSpecAttachments.js.map +1 -0
  694. package/dist/features/tasks/taskContextValidation.d.ts +10 -0
  695. package/dist/features/tasks/taskContextValidation.d.ts.map +1 -0
  696. package/dist/features/tasks/taskContextValidation.js +73 -0
  697. package/dist/features/tasks/taskContextValidation.js.map +1 -0
  698. package/dist/features/tasks/watch/index.d.ts.map +1 -1
  699. package/dist/features/tasks/watch/index.js +1 -0
  700. package/dist/features/tasks/watch/index.js.map +1 -1
  701. package/dist/features/workflowAuthoring/doctor.d.ts.map +1 -1
  702. package/dist/features/workflowAuthoring/doctor.js +56 -1
  703. package/dist/features/workflowAuthoring/doctor.js.map +1 -1
  704. package/dist/infra/claude/image-input.d.ts.map +1 -1
  705. package/dist/infra/claude/image-input.js +3 -2
  706. package/dist/infra/claude/image-input.js.map +1 -1
  707. package/dist/infra/codex/client.d.ts.map +1 -1
  708. package/dist/infra/codex/client.js +29 -10
  709. package/dist/infra/codex/client.js.map +1 -1
  710. package/dist/infra/config/configNormalizers.d.ts +24 -2
  711. package/dist/infra/config/configNormalizers.d.ts.map +1 -1
  712. package/dist/infra/config/configNormalizers.js +77 -4
  713. package/dist/infra/config/configNormalizers.js.map +1 -1
  714. package/dist/infra/config/env/global-current-env-specs.d.ts.map +1 -1
  715. package/dist/infra/config/env/global-current-env-specs.js +2 -0
  716. package/dist/infra/config/env/global-current-env-specs.js.map +1 -1
  717. package/dist/infra/config/env/project-current-env-specs.d.ts.map +1 -1
  718. package/dist/infra/config/env/project-current-env-specs.js +2 -0
  719. package/dist/infra/config/env/project-current-env-specs.js.map +1 -1
  720. package/dist/infra/config/global/globalConfig.d.ts +1 -1
  721. package/dist/infra/config/global/globalConfig.d.ts.map +1 -1
  722. package/dist/infra/config/global/globalConfig.js +1 -1
  723. package/dist/infra/config/global/globalConfig.js.map +1 -1
  724. package/dist/infra/config/global/globalConfigAccessors.d.ts +6 -0
  725. package/dist/infra/config/global/globalConfigAccessors.d.ts.map +1 -1
  726. package/dist/infra/config/global/globalConfigAccessors.js +80 -1
  727. package/dist/infra/config/global/globalConfigAccessors.js.map +1 -1
  728. package/dist/infra/config/global/globalConfigCore.d.ts.map +1 -1
  729. package/dist/infra/config/global/globalConfigCore.js +5 -3
  730. package/dist/infra/config/global/globalConfigCore.js.map +1 -1
  731. package/dist/infra/config/global/globalConfigSerializer.d.ts.map +1 -1
  732. package/dist/infra/config/global/globalConfigSerializer.js +9 -1
  733. package/dist/infra/config/global/globalConfigSerializer.js.map +1 -1
  734. package/dist/infra/config/global/index.d.ts +1 -1
  735. package/dist/infra/config/global/index.d.ts.map +1 -1
  736. package/dist/infra/config/global/index.js +1 -1
  737. package/dist/infra/config/global/index.js.map +1 -1
  738. package/dist/infra/config/loaders/resource-resolver.d.ts.map +1 -1
  739. package/dist/infra/config/loaders/resource-resolver.js +22 -7
  740. package/dist/infra/config/loaders/resource-resolver.js.map +1 -1
  741. package/dist/infra/config/loaders/workflowCallContractValidator.d.ts.map +1 -1
  742. package/dist/infra/config/loaders/workflowCallContractValidator.js +11 -4
  743. package/dist/infra/config/loaders/workflowCallContractValidator.js.map +1 -1
  744. package/dist/infra/config/loaders/workflowCallContracts.d.ts.map +1 -1
  745. package/dist/infra/config/loaders/workflowCallContracts.js +5 -0
  746. package/dist/infra/config/loaders/workflowCallContracts.js.map +1 -1
  747. package/dist/infra/config/loaders/workflowCallResolver.d.ts +2 -2
  748. package/dist/infra/config/loaders/workflowCallResolver.d.ts.map +1 -1
  749. package/dist/infra/config/loaders/workflowCallResolver.js +3 -10
  750. package/dist/infra/config/loaders/workflowCallResolver.js.map +1 -1
  751. package/dist/infra/config/loaders/workflowCallableArgResolver.d.ts.map +1 -1
  752. package/dist/infra/config/loaders/workflowCallableArgResolver.js +27 -0
  753. package/dist/infra/config/loaders/workflowCallableArgResolver.js.map +1 -1
  754. package/dist/infra/config/loaders/workflowCallableRuleValidation.d.ts.map +1 -1
  755. package/dist/infra/config/loaders/workflowCallableRuleValidation.js +5 -0
  756. package/dist/infra/config/loaders/workflowCallableRuleValidation.js.map +1 -1
  757. package/dist/infra/config/loaders/workflowLoopMonitorNormalizer.d.ts.map +1 -1
  758. package/dist/infra/config/loaders/workflowLoopMonitorNormalizer.js +12 -1
  759. package/dist/infra/config/loaders/workflowLoopMonitorNormalizer.js.map +1 -1
  760. package/dist/infra/config/loaders/workflowPackageScope.d.ts +1 -0
  761. package/dist/infra/config/loaders/workflowPackageScope.d.ts.map +1 -1
  762. package/dist/infra/config/loaders/workflowPackageScope.js +20 -2
  763. package/dist/infra/config/loaders/workflowPackageScope.js.map +1 -1
  764. package/dist/infra/config/loaders/workflowParser.d.ts.map +1 -1
  765. package/dist/infra/config/loaders/workflowParser.js +17 -7
  766. package/dist/infra/config/loaders/workflowParser.js.map +1 -1
  767. package/dist/infra/config/loaders/workflowPreview.d.ts +3 -0
  768. package/dist/infra/config/loaders/workflowPreview.d.ts.map +1 -1
  769. package/dist/infra/config/loaders/workflowPreview.js +43 -5
  770. package/dist/infra/config/loaders/workflowPreview.js.map +1 -1
  771. package/dist/infra/config/loaders/workflowRuleNormalizer.d.ts +10 -0
  772. package/dist/infra/config/loaders/workflowRuleNormalizer.d.ts.map +1 -1
  773. package/dist/infra/config/loaders/workflowRuleNormalizer.js +70 -1
  774. package/dist/infra/config/loaders/workflowRuleNormalizer.js.map +1 -1
  775. package/dist/infra/config/loaders/workflowStepNormalizer.d.ts.map +1 -1
  776. package/dist/infra/config/loaders/workflowStepNormalizer.js +41 -13
  777. package/dist/infra/config/loaders/workflowStepNormalizer.js.map +1 -1
  778. package/dist/infra/config/project/projectConfig.d.ts.map +1 -1
  779. package/dist/infra/config/project/projectConfig.js +19 -3
  780. package/dist/infra/config/project/projectConfig.js.map +1 -1
  781. package/dist/infra/config/project/sessionStore.d.ts +2 -2
  782. package/dist/infra/config/project/sessionStore.d.ts.map +1 -1
  783. package/dist/infra/config/project/sessionStore.js +12 -4
  784. package/dist/infra/config/project/sessionStore.js.map +1 -1
  785. package/dist/infra/config/providerModelRequirements.d.ts +2 -0
  786. package/dist/infra/config/providerModelRequirements.d.ts.map +1 -0
  787. package/dist/infra/config/providerModelRequirements.js +2 -0
  788. package/dist/infra/config/providerModelRequirements.js.map +1 -0
  789. package/dist/infra/config/resolveConfigValue.d.ts.map +1 -1
  790. package/dist/infra/config/resolveConfigValue.js +1 -0
  791. package/dist/infra/config/resolveConfigValue.js.map +1 -1
  792. package/dist/infra/config/traced/tracedConfigSchema.d.ts.map +1 -1
  793. package/dist/infra/config/traced/tracedConfigSchema.js +6 -0
  794. package/dist/infra/config/traced/tracedConfigSchema.js.map +1 -1
  795. package/dist/infra/git/format.d.ts +1 -0
  796. package/dist/infra/git/format.d.ts.map +1 -1
  797. package/dist/infra/git/format.js +21 -0
  798. package/dist/infra/git/format.js.map +1 -1
  799. package/dist/infra/git/index.d.ts +1 -1
  800. package/dist/infra/git/index.d.ts.map +1 -1
  801. package/dist/infra/git/types.d.ts +16 -4
  802. package/dist/infra/git/types.d.ts.map +1 -1
  803. package/dist/infra/github/GitHubProvider.d.ts +2 -1
  804. package/dist/infra/github/GitHubProvider.d.ts.map +1 -1
  805. package/dist/infra/github/GitHubProvider.js +4 -1
  806. package/dist/infra/github/GitHubProvider.js.map +1 -1
  807. package/dist/infra/github/issue.d.ts +2 -1
  808. package/dist/infra/github/issue.d.ts.map +1 -1
  809. package/dist/infra/github/issue.js +23 -2
  810. package/dist/infra/github/issue.js.map +1 -1
  811. package/dist/infra/gitlab/GitLabProvider.d.ts +2 -1
  812. package/dist/infra/gitlab/GitLabProvider.d.ts.map +1 -1
  813. package/dist/infra/gitlab/GitLabProvider.js +4 -1
  814. package/dist/infra/gitlab/GitLabProvider.js.map +1 -1
  815. package/dist/infra/gitlab/issue.d.ts +2 -1
  816. package/dist/infra/gitlab/issue.d.ts.map +1 -1
  817. package/dist/infra/gitlab/issue.js +30 -2
  818. package/dist/infra/gitlab/issue.js.map +1 -1
  819. package/dist/infra/opencode/OpenCodeStreamHandler.d.ts +4 -0
  820. package/dist/infra/opencode/OpenCodeStreamHandler.d.ts.map +1 -1
  821. package/dist/infra/opencode/OpenCodeStreamHandler.js.map +1 -1
  822. package/dist/infra/opencode/allowedTools.d.ts.map +1 -1
  823. package/dist/infra/opencode/allowedTools.js +0 -1
  824. package/dist/infra/opencode/allowedTools.js.map +1 -1
  825. package/dist/infra/opencode/client.d.ts +5 -1
  826. package/dist/infra/opencode/client.d.ts.map +1 -1
  827. package/dist/infra/opencode/client.js +519 -174
  828. package/dist/infra/opencode/client.js.map +1 -1
  829. package/dist/infra/opencode/index.d.ts +2 -2
  830. package/dist/infra/opencode/index.d.ts.map +1 -1
  831. package/dist/infra/opencode/index.js +1 -1
  832. package/dist/infra/opencode/index.js.map +1 -1
  833. package/dist/infra/opencode/types.d.ts +42 -0
  834. package/dist/infra/opencode/types.d.ts.map +1 -1
  835. package/dist/infra/opencode/types.js +88 -1
  836. package/dist/infra/opencode/types.js.map +1 -1
  837. package/dist/infra/opencode/unavailable-tool-loop.d.ts +25 -0
  838. package/dist/infra/opencode/unavailable-tool-loop.d.ts.map +1 -1
  839. package/dist/infra/opencode/unavailable-tool-loop.js +74 -0
  840. package/dist/infra/opencode/unavailable-tool-loop.js.map +1 -1
  841. package/dist/infra/providers/claude-headless.d.ts.map +1 -1
  842. package/dist/infra/providers/claude-headless.js +0 -2
  843. package/dist/infra/providers/claude-headless.js.map +1 -1
  844. package/dist/infra/providers/claude-terminal.d.ts.map +1 -1
  845. package/dist/infra/providers/claude-terminal.js +0 -2
  846. package/dist/infra/providers/claude-terminal.js.map +1 -1
  847. package/dist/infra/providers/claude.d.ts.map +1 -1
  848. package/dist/infra/providers/claude.js +0 -2
  849. package/dist/infra/providers/claude.js.map +1 -1
  850. package/dist/infra/providers/copilot.d.ts.map +1 -1
  851. package/dist/infra/providers/copilot.js +3 -0
  852. package/dist/infra/providers/copilot.js.map +1 -1
  853. package/dist/infra/providers/cursor.d.ts.map +1 -1
  854. package/dist/infra/providers/cursor.js +3 -0
  855. package/dist/infra/providers/cursor.js.map +1 -1
  856. package/dist/infra/providers/imageAttachmentPrompt.d.ts +0 -1
  857. package/dist/infra/providers/imageAttachmentPrompt.d.ts.map +1 -1
  858. package/dist/infra/providers/imageAttachmentPrompt.js +19 -2
  859. package/dist/infra/providers/imageAttachmentPrompt.js.map +1 -1
  860. package/dist/infra/providers/imageAttachments.d.ts +3 -0
  861. package/dist/infra/providers/imageAttachments.d.ts.map +1 -0
  862. package/dist/infra/providers/imageAttachments.js +47 -0
  863. package/dist/infra/providers/imageAttachments.js.map +1 -0
  864. package/dist/infra/providers/index.d.ts +1 -1
  865. package/dist/infra/providers/index.d.ts.map +1 -1
  866. package/dist/infra/providers/index.js.map +1 -1
  867. package/dist/infra/providers/mock.d.ts.map +1 -1
  868. package/dist/infra/providers/mock.js +5 -0
  869. package/dist/infra/providers/mock.js.map +1 -1
  870. package/dist/infra/providers/opencode.d.ts +3 -2
  871. package/dist/infra/providers/opencode.d.ts.map +1 -1
  872. package/dist/infra/providers/opencode.js +31 -6
  873. package/dist/infra/providers/opencode.js.map +1 -1
  874. package/dist/infra/providers/types.d.ts +8 -0
  875. package/dist/infra/providers/types.d.ts.map +1 -1
  876. package/dist/infra/task/clone-exec.d.ts.map +1 -1
  877. package/dist/infra/task/clone-exec.js +31 -0
  878. package/dist/infra/task/clone-exec.js.map +1 -1
  879. package/dist/infra/task/enqueueService.d.ts +115 -0
  880. package/dist/infra/task/enqueueService.d.ts.map +1 -0
  881. package/dist/infra/task/enqueueService.js +191 -0
  882. package/dist/infra/task/enqueueService.js.map +1 -0
  883. package/dist/infra/task/enqueuedTaskFile.d.ts +6 -0
  884. package/dist/infra/task/enqueuedTaskFile.d.ts.map +1 -0
  885. package/dist/infra/task/enqueuedTaskFile.js +55 -0
  886. package/dist/infra/task/enqueuedTaskFile.js.map +1 -0
  887. package/dist/infra/task/issueTask.d.ts +20 -0
  888. package/dist/infra/task/issueTask.d.ts.map +1 -0
  889. package/dist/{features/tasks/add → infra/task}/issueTask.js +61 -43
  890. package/dist/infra/task/issueTask.js.map +1 -0
  891. package/dist/infra/task/listSerializer.d.ts +1 -0
  892. package/dist/infra/task/listSerializer.d.ts.map +1 -1
  893. package/dist/infra/task/listSerializer.js +1 -0
  894. package/dist/infra/task/listSerializer.js.map +1 -1
  895. package/dist/infra/task/mapper.d.ts.map +1 -1
  896. package/dist/infra/task/mapper.js +1 -0
  897. package/dist/infra/task/mapper.js.map +1 -1
  898. package/dist/infra/task/taskExecutionSchemas.d.ts +3 -0
  899. package/dist/infra/task/taskExecutionSchemas.d.ts.map +1 -1
  900. package/dist/infra/task/taskExecutionSchemas.js +4 -2
  901. package/dist/infra/task/taskExecutionSchemas.js.map +1 -1
  902. package/dist/infra/task/taskRecordSchemas.d.ts +2 -0
  903. package/dist/infra/task/taskRecordSchemas.d.ts.map +1 -1
  904. package/dist/infra/workflow/system/DefaultSystemStepServices.d.ts.map +1 -1
  905. package/dist/infra/workflow/system/DefaultSystemStepServices.js +7 -7
  906. package/dist/infra/workflow/system/DefaultSystemStepServices.js.map +1 -1
  907. package/dist/infra/workflow/system/system-enqueue-effect.d.ts.map +1 -1
  908. package/dist/infra/workflow/system/system-enqueue-effect.js +78 -20
  909. package/dist/infra/workflow/system/system-enqueue-effect.js.map +1 -1
  910. package/dist/infra/workflow/system/system-git-context.d.ts +6 -6
  911. package/dist/infra/workflow/system/system-git-context.d.ts.map +1 -1
  912. package/dist/infra/workflow/system/system-git-context.js +13 -13
  913. package/dist/infra/workflow/system/system-git-context.js.map +1 -1
  914. package/dist/infra/workflow/system/system-issue-input-resolver.d.ts +3 -3
  915. package/dist/infra/workflow/system/system-issue-input-resolver.d.ts.map +1 -1
  916. package/dist/infra/workflow/system/system-issue-input-resolver.js +8 -8
  917. package/dist/infra/workflow/system/system-issue-input-resolver.js.map +1 -1
  918. package/dist/infra/workflow/system/system-pr-effects.d.ts.map +1 -1
  919. package/dist/infra/workflow/system/system-pr-effects.js +6 -3
  920. package/dist/infra/workflow/system/system-pr-effects.js.map +1 -1
  921. package/dist/infra/workflow/system/system-pr-input-resolver.d.ts +3 -3
  922. package/dist/infra/workflow/system/system-pr-input-resolver.d.ts.map +1 -1
  923. package/dist/infra/workflow/system/system-pr-input-resolver.js +8 -8
  924. package/dist/infra/workflow/system/system-pr-input-resolver.js.map +1 -1
  925. package/dist/infra/workflow/system/system-sync-effects.js +2 -2
  926. package/dist/infra/workflow/system/system-sync-effects.js.map +1 -1
  927. package/dist/shared/package-info.d.ts +2 -0
  928. package/dist/shared/package-info.d.ts.map +1 -0
  929. package/dist/shared/package-info.js +5 -0
  930. package/dist/shared/package-info.js.map +1 -0
  931. package/dist/shared/prompts/en/exec_assistant_instruct.md +2 -0
  932. package/dist/shared/prompts/en/finding_manager_instruction.md +9 -2
  933. package/dist/shared/prompts/en/opencode_review_agent_prompt.md +20 -23
  934. package/dist/shared/prompts/en/parts/finding_contract_instruction.md +25 -0
  935. package/dist/shared/prompts/en/parts/git_rules.md +5 -0
  936. package/dist/shared/prompts/{ja → en/parts}/structured_json_schema_instruction.md +2 -0
  937. package/dist/shared/prompts/en/{structured_json_step_instruction.md → parts/structured_json_step_instruction.md} +2 -0
  938. package/dist/shared/prompts/ja/exec_assistant_instruct.md +2 -0
  939. package/dist/shared/prompts/ja/finding_manager_instruction.md +9 -2
  940. package/dist/shared/prompts/ja/opencode_review_agent_prompt.md +20 -23
  941. package/dist/shared/prompts/ja/parts/finding_contract_instruction.md +25 -0
  942. package/dist/shared/prompts/ja/parts/git_rules.md +5 -0
  943. package/dist/shared/prompts/{en → ja/parts}/structured_json_schema_instruction.md +4 -2
  944. package/dist/shared/prompts/ja/{structured_json_step_instruction.md → parts/structured_json_step_instruction.md} +4 -2
  945. package/dist/shared/types/image-attachments.d.ts +10 -0
  946. package/dist/shared/types/image-attachments.d.ts.map +1 -0
  947. package/dist/shared/types/image-attachments.js +2 -0
  948. package/dist/shared/types/image-attachments.js.map +1 -0
  949. package/dist/shared/utils/entrypoint.d.ts +2 -0
  950. package/dist/shared/utils/entrypoint.d.ts.map +1 -0
  951. package/dist/shared/utils/entrypoint.js +15 -0
  952. package/dist/shared/utils/entrypoint.js.map +1 -0
  953. package/dist/shared/utils/imageAttachmentReferences.d.ts +7 -0
  954. package/dist/shared/utils/imageAttachmentReferences.d.ts.map +1 -0
  955. package/dist/shared/utils/imageAttachmentReferences.js +64 -0
  956. package/dist/shared/utils/imageAttachmentReferences.js.map +1 -0
  957. package/dist/shared/utils/index.d.ts +1 -0
  958. package/dist/shared/utils/index.d.ts.map +1 -1
  959. package/dist/shared/utils/index.js +1 -0
  960. package/dist/shared/utils/index.js.map +1 -1
  961. package/dist/shared/utils/safeExternalErrorMessage.d.ts +2 -0
  962. package/dist/shared/utils/safeExternalErrorMessage.d.ts.map +1 -0
  963. package/dist/shared/utils/safeExternalErrorMessage.js +22 -0
  964. package/dist/shared/utils/safeExternalErrorMessage.js.map +1 -0
  965. package/package.json +32 -13
  966. package/builtins/en/facets/instructions/review-pure.md +0 -9
  967. package/builtins/en/facets/personas/pure-reviewer.md +0 -22
  968. package/builtins/ja/facets/instructions/review-pure.md +0 -9
  969. package/builtins/ja/facets/personas/pure-reviewer.md +0 -22
  970. package/dist/core/workflow/claude-effort-compatibility.d.ts +0 -3
  971. package/dist/core/workflow/claude-effort-compatibility.d.ts.map +0 -1
  972. package/dist/core/workflow/claude-effort-compatibility.js +0 -28
  973. package/dist/core/workflow/claude-effort-compatibility.js.map +0 -1
  974. package/dist/core/workflow/provider-model-compatibility.d.ts +0 -6
  975. package/dist/core/workflow/provider-model-compatibility.d.ts.map +0 -1
  976. package/dist/core/workflow/provider-model-compatibility.js +0 -20
  977. package/dist/core/workflow/provider-model-compatibility.js.map +0 -1
  978. package/dist/features/tasks/add/issueTask.d.ts +0 -7
  979. package/dist/features/tasks/add/issueTask.d.ts.map +0 -1
  980. package/dist/features/tasks/add/issueTask.js.map +0 -1
  981. package/dist/features/tasks/list/retryTaskSpecAttachments.d.ts.map +0 -1
  982. package/dist/features/tasks/list/retryTaskSpecAttachments.js.map +0 -1
  983. package/dist/infra/config/providerModelCompatibility.d.ts +0 -2
  984. package/dist/infra/config/providerModelCompatibility.d.ts.map +0 -1
  985. package/dist/infra/config/providerModelCompatibility.js +0 -2
  986. package/dist/infra/config/providerModelCompatibility.js.map +0 -1
  987. /package/dist/shared/prompts/en/{source_context_section_guidance.md → parts/source_context_section_guidance.md} +0 -0
  988. /package/dist/shared/prompts/en/{source_context_system_guard.md → parts/source_context_system_guard.md} +0 -0
  989. /package/dist/shared/prompts/ja/{source_context_section_guidance.md → parts/source_context_section_guidance.md} +0 -0
  990. /package/dist/shared/prompts/ja/{source_context_system_guard.md → parts/source_context_system_guard.md} +0 -0
@@ -1,29 +1,126 @@
1
1
  # CQRS+ES Knowledge
2
2
 
3
+ ## CQRS+ES Adoption Decision
4
+
5
+ CQRS+ES is a design in which state changes are stored as domain events, and current state and Read Models are derived from them. Even when the backend as a whole or the workflow handles CQRS+ES, not every new feature needs to be implemented with event sourcing.
6
+
7
+ | Criteria | Judgment |
8
+ |----------|----------|
9
+ | User request, design material, or existing boundaries explicitly require CQRS+ES | Adopt CQRS+ES |
10
+ | State transitions, lifecycle, and business invariants are central to the feature | Consider CQRS+ES |
11
+ | Change events trigger other Aggregates, Sagas, or downstream processes | Consider CQRS+ES |
12
+ | Restoring state at a past point, event replay, or audit evidence itself is a requirement | Consider CQRS+ES |
13
+ | Read Models need to be projected asynchronously for multiple uses | Consider CQRS+ES |
14
+ | The feature is complete with current-value reference and updates only | Prefer CRUD |
15
+ | Security settings, feature flags, allowlists, thresholds, or similar values require immediate reflection | Prefer CRUD |
16
+ | There is no domain vocabulary beyond "create/update/delete" | Prefer CRUD |
17
+ | The task is merely being implemented in a CQRS+ES workflow | Do not use as adoption rationale |
18
+ | Adding CQRS+ES requirements to a task specification when they were absent from the original task | REJECT |
19
+
20
+ Adopt CQRS+ES based on requirements. An existing system containing CQRS+ES can justify aligning dependencies and boundaries, but it does not justify event-sourcing simple settings tables.
21
+
22
+ ### Requirement Transformation
23
+
24
+ If the original task or user request states only CRUD-equivalent business requirements, do not add "commands, events, and projections" as new requirements in the task specification. If it is unclear whether CQRS+ES is needed, state the adoption rationale or leave it as an open question.
25
+
26
+ | Original Request | How to Convert into a Specification |
27
+ |------------------|-------------------------------------|
28
+ | "Manage allowed IPs per facility" | Treat as CRUD-managed settings. The domain vocabulary is only "add/delete" and has no business rules |
29
+ | "Manage order approval, cancellation, and returns, and trigger billing or inventory depending on state" | Candidate for CQRS+ES. Complex state transitions and business invariants, with multiple Aggregates interacting |
30
+ | "For insurance contract changes, review rules differ by change type, and past assessment history affects future decisions" | Candidate for CQRS+ES. Business rules are complex and change over time; history itself is input to business decisions |
31
+ | "Show who changed what and when on the screen" | Check whether CRUD + audit logs is enough. If the requirement is only displaying change history, audit columns are often sufficient |
32
+ | "Toggle notification settings on/off" | Treat as CRUD-managed settings. It only references and updates current values |
33
+
34
+ CQRS+ES is most valuable in complex business domains, such as finance, insurance, or healthcare, where business rules are complex and change over time. Simple audit requirements or technical asynchronous processing alone are not sufficient conditions for CQRS+ES. The decision axis is business-logic complexity.
35
+
3
36
  ## Aggregate Design
4
37
 
5
38
  Aggregates hold only fields necessary for decision-making.
6
39
 
7
- Command Model (Aggregate) role is to "receive commands, make decisions, and emit events". Query data is handled by Read Model (Projection).
40
+ The Command Model (Aggregate) role is to "receive commands, make decisions, and emit events". Query data belongs to the Read Model (Projection).
8
41
 
9
- "Necessary for decision" means:
10
- - Used in `if`/`require` conditional branches
11
- - Field value referenced when emitting events in instance methods
42
+ "Necessary for decision-making" means:
43
+ - Used in `if` / `require` conditional branches
44
+ - Field values are referenced by instance methods when emitting events
12
45
 
13
46
  | Criteria | Judgment |
14
47
  |----------|----------|
15
48
  | Aggregate spans multiple transaction boundaries | REJECT |
16
- | Direct references between Aggregates (not ID references) | REJECT |
49
+ | Direct references between Aggregates, not ID references | REJECT |
17
50
  | Aggregate exceeds 100 lines | Consider splitting |
18
- | Business invariants exist outside Aggregate | REJECT |
51
+ | Business invariants exist outside the Aggregate | REJECT |
19
52
  | Holding fields not used for decisions | REJECT |
53
+ | Branching state transitions with origin metadata such as `source` / `input` / `origin` / `channel` / `type` | REJECT by default |
54
+ | Rejecting, only for a specific input source, a state allowed by the existing Aggregate's normal lifecycle | REJECT |
55
+ | Keeping the creation-time caller in Aggregate state and reusing it as the actor of later events | REJECT. Pass the performer with each command |
56
+
57
+ Being used in an `if` / `require` branch is not enough to justify keeping a field in Aggregate state. First verify that the branch or validation is an essential invariant of the whole Aggregate.
58
+
59
+ ### Origin Metadata and Invariants
60
+
61
+ Origin metadata such as input source, channel, producer, or integration source can be needed for display, search, audit, or integration tracing. That need alone does not justify restoring it as Aggregate state.
62
+
63
+ | Criteria | Judgment |
64
+ |----------|----------|
65
+ | Origin metadata is needed only for display, search, audit, or integration tracing | Keep it in the Event payload or Read Model |
66
+ | A branch based on origin metadata creates constraints that differ from the existing Aggregate's normal lifecycle | REJECT |
67
+ | A field that is normally optional becomes required only for one input source | REJECT |
68
+ | Invariants truly differ by input source | Consider a separate Aggregate, Command, or UseCase boundary |
69
+ | Adding origin metadata to Aggregate state only to support a `require` | REJECT |
70
+
71
+ ```kotlin
72
+ // NG - Origin metadata narrows the normal lifecycle of an existing Aggregate
73
+ data class Note(
74
+ val noteId: String,
75
+ val sourceType: SourceType?,
76
+ val targetIds: List<String>,
77
+ ) {
78
+ fun update(text: String, targetIds: List<String>): NoteUpdatedEvent {
79
+ if (sourceType == SourceType.EXTERNAL_IMPORT) {
80
+ require(targetIds.isNotEmpty())
81
+ }
82
+ return NoteUpdatedEvent(noteId, text, targetIds)
83
+ }
84
+ }
85
+
86
+ // OK - Track origin in events/read models and align Aggregate invariants with the normal lifecycle
87
+ data class Note(
88
+ val noteId: String,
89
+ val confirmed: Boolean,
90
+ ) {
91
+ fun update(text: String, targetIds: List<String>): NoteUpdatedEvent {
92
+ check(!confirmed)
93
+ return NoteUpdatedEvent(noteId, text, targetIds)
94
+ }
95
+ }
96
+
97
+ data class NoteCreatedEvent(
98
+ val noteId: String,
99
+ val text: String,
100
+ val targetIds: List<String>,
101
+ val sourceType: SourceType?, // Origin fact used by projections or audit
102
+ )
103
+ ```
104
+
105
+ ### Existing Lifecycle Priority
106
+
107
+ When integrating a new input flow into an existing Aggregate, prefer the existing normal lifecycle. Do not add input-source-specific commands, wrappers, services, or deletion paths merely because the input source differs.
108
+
109
+ | Criteria | Judgment |
110
+ |----------|----------|
111
+ | The existing Aggregate's normal command / event can represent the same fact | Use the existing lifecycle |
112
+ | An input-source-specific wrapper only thinly delegates to a normal command | REJECT |
113
+ | An input-source-specific command adds stricter required fields than the normal lifecycle | REJECT |
114
+ | Existing Aggregate deletion or update events can trigger derived processing | Separate into EventHandler |
115
+ | Display or search fields needed only by a specialized flow | Keep them in the Read Model |
116
+ | State transitions or invariants truly differ by input source | Consider a separate Aggregate / bounded context |
20
117
 
21
118
  Good Aggregate:
22
119
  ```kotlin
23
120
  // Only fields necessary for decisions
24
121
  data class Order(
25
122
  val orderId: String, // Used when emitting events
26
- val status: OrderStatus // Used for state checking
123
+ val status: OrderStatus // Used for state checks
27
124
  ) {
28
125
  fun confirm(confirmedBy: String): OrderConfirmedEvent {
29
126
  require(status == OrderStatus.PENDING) { "Cannot confirm in this state" }
@@ -38,15 +135,15 @@ data class Order(
38
135
  // Holding fields not used for decisions (NG)
39
136
  data class Order(
40
137
  val orderId: String,
41
- val customerId: String, // Not used for decisions
138
+ val customerId: String, // Not used for decisions
42
139
  val shippingAddress: Address, // Not used for decisions
43
140
  val status: OrderStatus
44
141
  )
45
142
  ```
46
143
 
47
- Aggregates with no additional operations have ID only:
144
+ Aggregates with no additional operations have only an ID:
48
145
  ```kotlin
49
- // When only creation, no additional operations
146
+ // Creation only, no additional operations
50
147
  data class Notification(val notificationId: String) {
51
148
  companion object {
52
149
  fun create(customerId: String, message: String): NotificationCreatedEvent {
@@ -60,61 +157,216 @@ data class Notification(val notificationId: String) {
60
157
  }
61
158
  ```
62
159
 
160
+ ### Adapter Pattern: Separating Domain from Framework
161
+
162
+ Do not put framework annotations such as `@Aggregate` or `@CommandHandler` directly on domain models. Adapter classes handle framework integration, and domain models focus on business logic.
163
+
164
+ ```kotlin
165
+ // Domain model: framework-independent business logic only
166
+ data class Order(
167
+ val orderId: String,
168
+ val status: OrderStatus = OrderStatus.PENDING
169
+ ) {
170
+ companion object {
171
+ fun place(orderId: String, customerId: String): OrderPlacedEvent {
172
+ require(customerId.isNotBlank()) { "Customer ID cannot be blank" }
173
+ return OrderPlacedEvent(orderId, customerId)
174
+ }
175
+
176
+ fun from(event: OrderPlacedEvent): Order {
177
+ return Order(orderId = event.orderId, status = OrderStatus.PENDING)
178
+ }
179
+ }
180
+
181
+ fun confirm(confirmedBy: String): OrderConfirmedEvent {
182
+ require(status == OrderStatus.PENDING) { "Cannot confirm in this state" }
183
+ return OrderConfirmedEvent(orderId, confirmedBy, LocalDateTime.now())
184
+ }
185
+
186
+ fun apply(event: OrderEvent): Order = when (event) {
187
+ is OrderPlacedEvent -> from(event)
188
+ is OrderConfirmedEvent -> copy(status = OrderStatus.CONFIRMED)
189
+ is OrderCancelledEvent -> copy(status = OrderStatus.CANCELLED)
190
+ }
191
+ }
192
+
193
+ // Adapter: framework integration. Domain call -> event publication bridge
194
+ @Aggregate
195
+ class OrderAggregateAdapter() {
196
+ private var order: Order? = null
197
+
198
+ @AggregateIdentifier
199
+ fun orderId(): String? = order?.orderId
200
+
201
+ @CommandHandler
202
+ constructor(command: PlaceOrderCommand) : this() {
203
+ val event = Order.place(command.orderId, command.customerId)
204
+ AggregateLifecycle.apply(event)
205
+ }
206
+
207
+ @CommandHandler
208
+ fun handle(command: ConfirmOrderCommand) {
209
+ val event = order!!.confirm(command.confirmedBy)
210
+ AggregateLifecycle.apply(event)
211
+ }
212
+
213
+ @EventSourcingHandler
214
+ fun on(event: OrderEvent) {
215
+ this.order = when (event) {
216
+ is OrderPlacedEvent -> Order.from(event)
217
+ else -> order?.apply(event)
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ Benefits of separation:
224
+ - Domain models can be unit-tested without a framework
225
+ - Domain models do not need to change when the framework changes
226
+ - Adapters are boilerplate for receiving commands, calling the domain, and publishing events
227
+
228
+ ### apply/from Pattern: Event Replay
229
+
230
+ A pattern in which a domain model rebuilds its own state from events.
231
+
232
+ - `from(event)`: factory that builds initial state from a creation event
233
+ - `apply(event)`: returns new state from an event, using immutable updates with `copy()`
234
+ - `when` expressions plus sealed interfaces let the compiler guarantee exhaustiveness over event types
235
+
236
+ ```kotlin
237
+ fun apply(event: OrderEvent): Order = when (event) {
238
+ is OrderPlacedEvent -> from(event)
239
+ is OrderConfirmedEvent -> copy(status = OrderStatus.CONFIRMED)
240
+ is OrderShippedEvent -> copy(status = OrderStatus.SHIPPED)
241
+ // Because the interface is sealed, adding an event type without handling it is a compile error
242
+ }
243
+ ```
244
+
245
+ | Criteria | Judgment |
246
+ |----------|----------|
247
+ | Business logic such as validation inside `apply` | REJECT. `apply` is state restoration only |
248
+ | `apply` has side effects such as DB operations or event emission | REJECT |
249
+ | `apply` throws exceptions | REJECT. Replay failures are not acceptable |
250
+
63
251
  ## Event Design
64
252
 
65
253
  | Criteria | Judgment |
66
254
  |----------|----------|
67
- | Event not in past tense (Created Create) | REJECT |
255
+ | Event is not in past tense, such as Created -> Create | REJECT |
68
256
  | Event contains logic | REJECT |
69
- | Event contains internal state of other Aggregates | REJECT |
70
- | Event schema not version controlled | Warning |
71
- | CRUD-style events (Updated, Deleted) | Needs review |
257
+ | Event contains internal state of another Aggregate | REJECT |
258
+ | Event schema is not versioned | Warning |
259
+ | CRUD-style events such as Updated or Deleted | Needs review |
72
260
 
73
- Good Events:
261
+ Good events:
74
262
  ```kotlin
75
- // Good: Domain intent is clear
263
+ // Good: domain intent is clear
76
264
  OrderPlaced, PaymentReceived, ItemShipped
77
265
 
78
266
  // Bad: CRUD style
79
267
  OrderUpdated, OrderDeleted
80
268
  ```
81
269
 
82
- Event Granularity:
83
- - Too fine: `OrderFieldChanged` → Domain intent unclear
84
- - Appropriate: `ShippingAddressChanged` Intent is clear
85
- - Too coarse: `OrderModified` → What changed is unclear
270
+ ### Fact Events vs Request Events
271
+
272
+ Events express facts that occurred, and their names come from business meaning. A `...Requested` suffix or the current number of consumers does not by itself distinguish a fact event from a command in disguise. Accepting or starting a request can be a business fact; a message whose only meaning is instructing a known destination to execute work is a command.
273
+
274
+ | Decision axis | Fact event | Consider a command |
275
+ |---------------|------------|--------------------|
276
+ | Business meaning | An occurrence such as acceptance, start, or rejection that matters to audit or replay | Its only purpose is to make a specific process run |
277
+ | Emitter lifecycle | Used by later decisions such as waiting, duplicate rejection, or timeout | The emitter tracks neither state nor outcome |
278
+ | Outcome | Continues to another uncertain fact such as completion or failure | Can run immediately within the same boundary and return its result there |
279
+ | Consumers | Consumers may change without changing event meaning | Destination and operation are the message's meaning |
280
+
281
+ Split events by independent business facts, not by technical consumers. Do not emit duplicate state and trigger events for the same occurrence; EventHandlers and projections subscribe to the fact owned by the emitting Aggregate. Multiple events are appropriate only when independently named, audited, and replayed facts occur together. Do not pack another Aggregate's internal state or initialization details into the event; resolve stable IDs or references at the boundary.
282
+
283
+ ```kotlin
284
+ // NG - One business fact duplicated as separate state and technical trigger events
285
+ fun addItem(itemId: String, productId: String, quantity: Int): List<OrderEvent> = listOf(
286
+ OrderItemLinkedEvent(orderId, itemId), // for state
287
+ OrderItemCreationRequestedEvent(orderId, itemId, productId, quantity), // for triggering (a command in effect)
288
+ )
289
+
290
+ // OK - A single event carrying the content that is factual for the emitting Aggregate
291
+ fun addItem(itemId: String, productId: String, quantity: Int): OrderItemAddedEvent =
292
+ OrderItemAddedEvent(orderId, itemId, productId, quantity)
293
+ ```
294
+
295
+ | Criteria | Judgment |
296
+ |----------|----------|
297
+ | Classifying a message as an event or command from its suffix or current consumer count alone | REJECT. Judge business meaning and lifecycle |
298
+ | Splitting the same business fact into a state event (Linked, etc.) and a trigger event (Requested, etc.) | REJECT. Merge them into the fact owned by the emitting Aggregate |
299
+ | An asynchronous request to an external service or another context where acceptance or waiting is a business fact and completion/failure is tracked | OK. It can be expressed as the fact that the request was accepted |
300
+ | Adding a dedicated request event for processing that an existing fact event (confirmed, approved, etc.) can drive | REJECT. Have an EventHandler, and a domain policy when needed, subscribe to the existing fact |
301
+ | Recording an occurrence that only changes another Aggregate's state as an event in one's own stream | REJECT. Facts belong to the stream of the Aggregate where they happened |
302
+ | Routing an operation unrelated to an Aggregate's own state or lifecycle through it and relaying it to the target Aggregate | REJECT. Send the command to the target Aggregate and perform membership or existence checks at the boundary that owns the invariant |
303
+
304
+ ### Event Type Hierarchy with sealed interface
305
+
306
+ Aggregate events should use a sealed interface type hierarchy. The Aggregate root ID should be required as a common field, enabling exhaustive `when` checks.
307
+
308
+ ```kotlin
309
+ sealed interface OrderEvent {
310
+ val orderId: String // Required on every event
311
+ }
312
+
313
+ data class OrderPlacedEvent(
314
+ override val orderId: String,
315
+ val customerId: String
316
+ ) : OrderEvent
317
+
318
+ data class OrderConfirmedEvent(
319
+ override val orderId: String,
320
+ val approvalInfo: ApprovalInfo
321
+ ) : OrderEvent
322
+
323
+ data class OrderCancelledEvent(
324
+ override val orderId: String,
325
+ val cancellationInfo: CancellationInfo
326
+ ) : OrderEvent
327
+ ```
328
+
329
+ Benefits:
330
+ - A `when (event)` expression must list every event type, otherwise compilation fails. This is especially important in `apply`
331
+ - The compiler guarantees that the Aggregate root ID exists
332
+ - Event-handler branching by type is safer
333
+
334
+ Event granularity:
335
+ - Too fine: `OrderFieldChanged` -> domain intent is unclear
336
+ - Appropriate: `ShippingAddressChanged` -> intent is clear
337
+ - Too coarse: `OrderModified` -> unclear what changed
86
338
 
87
339
  ## Event Evolution
88
340
 
89
- Events are persisted contracts. When the current event type changes, old events must still be replayable. Translation of old events belongs in the upcaster / migration layer at the event-store boundary, not in the event type itself or in domain logic.
341
+ Events are persisted contracts. If the current event type changes, old events must still be replayable. Translating old events belongs in the upcaster / migration layer at the event-store restoration boundary, not in event classes or domain logic.
90
342
 
91
343
  | Criteria | Judgment |
92
344
  |----------|----------|
93
- | Persisted event type or fields changed with no translation path | REJECT |
94
- | Current event type keeps aliases or compatibility-only properties for old field names | REJECT. Keep history compatibility in upcasters |
95
- | Aggregate or apply directly interprets old event shapes | REJECT. Convert to current events before replay |
96
- | Event carries "previous value" only for compatibility | REJECT. Events represent the fact after it happened |
97
- | Upcaster converts old payloads to the current event meaning | OK |
98
- | Tests verify old payloads deserialize into current events through the upcaster | OK |
345
+ | Persisted event type or fields changed without a translation path | REJECT |
346
+ | Current event type keeps old field aliases or compatibility-only properties | REJECT. Keep history compatibility in upcasters |
347
+ | Aggregate or `apply` directly interprets old event shapes | REJECT. Convert to current events before replay |
348
+ | Event adds "previous value" only for compatibility | REJECT. Events represent the fact after it happened |
349
+ | Upcaster converts old payloads into current event meaning | OK |
350
+ | Tests verify conversion from old payloads to current events | OK |
99
351
 
100
- Responsibility split for event evolution:
352
+ Responsibilities in event evolution:
101
353
 
102
- | Responsibility | Place |
103
- |----------------|-------|
354
+ | Responsibility | Location |
355
+ |----------------|----------|
104
356
  | Current event meaning and fields | Event type |
105
- | Translation of old payloads | Upcaster / migration layer |
106
- | State restoration by event replay | Aggregate `apply` |
107
- | Guarantee that old events can become current events | Upcaster tests |
357
+ | Reading old payloads | Upcaster / migration layer |
358
+ | State restoration from event replay | Aggregate `apply` |
359
+ | Guarantee that old events can be converted to current events | Upcaster tests |
108
360
 
109
361
  ```kotlin
110
- // NG - mixing old-field compatibility into the current event type
362
+ // NG - Mixing old field compatibility into the current event type
111
363
  data class OrderAssignedEvent(
112
364
  val orderId: String,
113
365
  @JsonAlias("assigneeId")
114
366
  val assigneeIds: List<String>
115
367
  )
116
368
 
117
- // OK - current event type represents only the current contract
369
+ // OK - Current event type represents only the current contract
118
370
  data class OrderAssignedEvent(
119
371
  val orderId: String,
120
372
  val assigneeIds: List<String>
@@ -122,7 +374,7 @@ data class OrderAssignedEvent(
122
374
  ```
123
375
 
124
376
  ```kotlin
125
- // OK - convert old payloads to current payloads in the upcaster
377
+ // OK - Convert old payloads to current payloads in an upcaster
126
378
  when (eventType) {
127
379
  OrderAssignedEvent::class.java.typeName -> {
128
380
  event.moveTextFieldToArray("assigneeId", "assigneeIds")
@@ -130,135 +382,326 @@ when (eventType) {
130
382
  }
131
383
  ```
132
384
 
133
- Whether to keep old event classes depends on the framework and operations policy. In general, do not treat old classes as normal domain events; treat old serialized type names and payloads as the upcaster input contract and cover them with tests.
385
+ Whether to keep old event types in application code depends on the framework and operational policy. In general, it is better not to treat old types as normal domain events. Instead, test the old serialized type and payload as input contracts for the upcaster, keeping the current model clean.
386
+
387
+ ### Migration Scope Decomposition
388
+
389
+ CQRS+ES migration must distinguish DB schema migration, data migration, event upcasters, Read Model rebuilds, and API compatibility work. Do not treat "migrate / do not migrate" as a single decision.
390
+
391
+ | Criteria | Judgment |
392
+ |----------|----------|
393
+ | The user says migration is unnecessary, but the migration type is not decomposed | REJECT |
394
+ | DB schema migration or data migration is added while the scope is unclear | REJECT |
395
+ | An upcaster is added even though no persisted old events exist | REJECT |
396
+ | Data migration is created even though the Read Model can be rebuilt from events | REJECT. Check whether rebuild is enough |
397
+ | Add an upcaster only when event payload compatibility is required | OK |
398
+ | Treat API compatibility and event compatibility as separate decisions | OK |
134
399
 
135
400
  ## Command Handlers
136
401
 
137
402
  | Criteria | Judgment |
138
403
  |----------|----------|
139
- | Handler directly manipulates DB | REJECT |
140
- | Handler modifies multiple Aggregates | REJECT |
141
- | No command validation | REJECT |
404
+ | Handler directly manipulates the DB | REJECT |
405
+ | Handler changes multiple Aggregates | REJECT |
406
+ | Command has no validation | REJECT |
142
407
  | Handler executes queries to make decisions | Needs review |
408
+ | The return contract does not match the number of events an operation can produce | Needs review. Choose a single, optional, collection, or result type from domain cardinality and language/framework conventions |
409
+
410
+ ### Contract Lifetimes of Commands and Events
411
+
412
+ Events are long-lived contracts persisted as history, so stored type identifiers and payloads must remain replayable. Whether the type identifier is a fully qualified class name or a logical name, and whether changes use an upcaster, alias, or migration, depends on the event store and serialization strategy.
143
413
 
144
- Good Command Handler:
414
+ Commands are usually short-lived messages created and handled at the application boundary, but some architectures persist them for scheduling, outbox delivery, retries, dead-letter handling, or audit. Decide placement and compatibility from responsibility and the actual storage contract, not from an assumption that every command is transient. Domain models should not depend on transport- or framework-specific command types; translate them into domain arguments and value objects at the application or adapter boundary.
415
+
416
+ | Criteria | Judgment |
417
+ |----------|----------|
418
+ | A domain model directly receives a transport- or framework-specific command type | REJECT. Translate it into domain input at the application or adapter boundary |
419
+ | An application message unused by domain classes sits in the domain package | Move it to the application boundary |
420
+ | A command package is moved or renamed without checking for persisted references | REJECT. Check scheduling, outbox, retry, dead-letter, and audit storage contracts |
421
+ | A stored event type identifier or payload changes without a conversion path | REJECT. Provide compatibility for the identifier and serialization strategy in use. Direct change is allowed only when no persisted events exist yet; release status is not the criterion |
422
+
423
+ Good command handler:
145
424
  ```
146
- 1. Receive command
147
- 2. Restore Aggregate from event store
148
- 3. Apply command to Aggregate
149
- 4. Save emitted events
425
+ 1. Receive a command
426
+ 2. Restore the Aggregate from the event store
427
+ 3. Apply the command to the Aggregate
428
+ 4. Store the emitted events
150
429
  ```
151
430
 
431
+ ### Multi-layer Validation
432
+
433
+ Validation responsibilities differ by layer. Do not collect every validation in one place.
434
+
435
+ | Layer | Responsibility | Means | Example |
436
+ |-------|----------------|-------|---------|
437
+ | API layer | Structural validation | `@NotBlank`, `init` block | Required fields, type, format |
438
+ | UseCase layer | Business-rule validation | Querying Read Models | Duplicate checks, existence of prerequisites |
439
+ | Domain layer | State-transition invariants | `require` | "Can only approve when PENDING" |
440
+
152
441
  ### Aggregate Decision Boundary
153
442
 
154
- Aggregates make decisions only from state that can be restored from their event history and facts explicitly carried by commands. They are not the place to interpret, normalize, or authorize boundary-originated inputs.
443
+ Aggregates make decisions only from state restored from their own event history and facts explicitly supplied as commands. They are not the place to interpret, normalize, or verify ownership of boundary-originated input.
444
+
445
+ Validation inside an Aggregate must be limited to state that can be reproduced solely by event replay. Other validation should be resolved at the boundary before command dispatch, and resolved facts should be passed to the Aggregate.
446
+
447
+ | Decision Target | Location |
448
+ |-----------------|----------|
449
+ | Whether the operation is possible in the current state | Aggregate |
450
+ | Whether command executor matches Aggregate owner | Aggregate |
451
+ | HTTP/API input shape is valid | API layer |
452
+ | Interpreting formats of external identifiers such as object keys, URLs, paths | UseCase layer or boundary policy/verifier |
453
+ | External identifier belongs to the current user/tenant | UseCase layer or boundary policy/verifier |
454
+ | Checking another Aggregate's Read Model or external facts | UseCase layer |
455
+ | State-transition decisions based on the same Aggregate's current state | Aggregate |
456
+ | Entity exists in an external service | Application-layer external-service integration |
155
457
 
156
- Validation inside an Aggregate should be limited to facts reproducible by event replay. Other validation should be resolved before command dispatch, and the Aggregate should receive already-resolved facts.
458
+ Example: in an upload-completion command, the Aggregate decides whether the session owner matches the executor and whether the current state allows completion. The string shape of the object key and whether that key belongs to the current user/tenant area are verified in the UseCase layer before the command is sent.
157
459
 
158
- | Decision target | Place |
159
- |-----------------|-------|
160
- | Whether the current state allows the operation | Aggregate |
161
- | Whether the command requester matches the Aggregate owner | Aggregate |
162
- | Whether HTTP/API input shape is valid | API layer |
163
- | Parsing external identifiers such as object keys, URLs, or paths | UseCase layer or boundary-side Policy/Verifier |
164
- | Whether an external identifier belongs to the current user/tenant | UseCase layer or boundary-side Policy/Verifier |
165
- | Checking Read Models or other Aggregate state | UseCase layer |
166
- | Checking that an external resource exists | Application-layer integration with the external service |
460
+ ### Command Intent and Pre-querying
167
461
 
168
- Example: for an upload-completed command, the Aggregate decides whether the session owner matches the requester and whether the current state can be completed. The storage object key format and whether the key belongs to the current user/tenant are validated in the UseCase layer before sending the command.
462
+ A Command represents what the user or external process intends to do, not which command should be selected after reading the current state. Decisions such as Add / Update / Delete / Noop based on current state should be pushed into the restored Aggregate, not decided from the same Aggregate's Read Model.
169
463
 
170
- ## UseCase Layer (Orchestration)
464
+ | Criteria | Judgment |
465
+ |----------|----------|
466
+ | Check existence or scope of other Aggregates or external facts, then pass resolved facts to the command | OK |
467
+ | Read the same Aggregate's Read Model to choose the command type | REJECT |
468
+ | The UseCase decides "update if it exists, add if it does not" from Query results | REJECT. Send an intent command such as Set / Attach / Upsert to the Aggregate |
469
+ | Aggregate or AggregateAdapter decides existence and transition validity from restored state | OK |
470
+ | EventHandler or UseCase suppresses duplicate commands with a pre-query even though the Aggregate could ignore them idempotently | REJECT. Protect with Aggregate state transitions |
171
471
 
172
- UseCases sit between Controllers and command dispatch when orchestration is needed. They validate preconditions from Read Models across aggregates and perform required preparation before sending commands.
472
+ ```kotlin
473
+ // NG - Query result chooses the command type
474
+ if (readService.exists(orderId)) {
475
+ commandGateway.send(UpdateOrderCommand(orderId, value))
476
+ } else {
477
+ commandGateway.send(AddOrderCommand(orderId, value))
478
+ }
173
479
 
480
+ // OK - Send an intent command; the Aggregate decides from restored state
481
+ commandGateway.send(SetOrderValueCommand(orderId, value))
174
482
  ```
175
- Controller → UseCase → CommandGateway → Aggregate
176
-
177
- QueryGateway / Repository (Read Model lookup)
483
+
484
+ ```kotlin
485
+ // API layer: structural validation
486
+ data class OrderPostRequest(
487
+ @field:NotBlank val customerId: String,
488
+ @field:NotNull val items: List<OrderItemRequest>
489
+ ) {
490
+ init {
491
+ require(items.isNotEmpty()) { "An order must have at least one item" }
492
+ }
493
+ }
494
+
495
+ // UseCase layer: business-rule validation by Read Model reference
496
+ @Service
497
+ class PlaceOrderUseCase(
498
+ private val commandGateway: CommandGateway,
499
+ private val customerRepository: CustomerRepository,
500
+ private val inventoryRepository: InventoryRepository
501
+ ) {
502
+ fun execute(input: PlaceOrderInput): Mono<PlaceOrderOutput> {
503
+ return Mono.fromCallable {
504
+ // Customer existence check
505
+ customerRepository.findById(input.customerId)
506
+ ?: throw CustomerNotFoundException("Customer does not exist")
507
+ // Inventory precheck
508
+ validateInventory(input.items)
509
+ // Command dispatch
510
+ val orderId = UUID.randomUUID().toString()
511
+ commandGateway.send<Any>(PlaceOrderCommand(orderId, input.customerId, input.items))
512
+ PlaceOrderOutput(orderId)
513
+ }
514
+ }
515
+ }
516
+
517
+ // Domain layer: state-transition invariant
518
+ fun confirm(confirmedBy: String): OrderConfirmedEvent {
519
+ require(status == OrderStatus.PENDING) { "Cannot confirm in this state" }
520
+ return OrderConfirmedEvent(orderId, confirmedBy, LocalDateTime.now())
521
+ }
522
+ ```
523
+
524
+ | Criteria | Judgment |
525
+ |----------|----------|
526
+ | Domain-layer validation exists in API layer | REJECT. State-transition rules belong in the domain |
527
+ | UseCase-layer validation exists in Controller | REJECT. Separate into UseCase layer |
528
+ | API-layer validation such as `@NotBlank` exists in domain | REJECT. Structural validation belongs in API layer |
529
+
530
+ ## UseCase Layer: Orchestration
531
+
532
+ Place a UseCase layer between Controller and CommandGateway. The UseCase layer gathers facts that must be resolved at the boundary and normally sends one intent command. Subsequent state changes are driven by EventHandlers for committed events.
533
+
534
+ ```
535
+ Controller -> UseCase -> CommandGateway -> Aggregate
536
+ |
537
+ QueryGateway / Repository (Read Model reference)
178
538
  ```
179
539
 
180
- Cases where UseCase is needed:
181
- - Read Model checks from multiple aggregates before command dispatch
182
- - Multiple validations executed in sequence
183
- - Result consistency waiting after command dispatch
184
- - External integration or multiple command dispatches
540
+ Cases that need a UseCase:
541
+ - Checking another Aggregate's Read Model or external facts before command dispatch
542
+ - Running multiple validations sequentially
543
+ - Waiting for eventual consistency after command dispatch only for a synchronous API contract
185
544
 
186
- Cases where UseCase is unnecessary:
187
- - Simple operation completed by sending one command from Controller
188
- - Simple read that only queries the query side and converts to response
189
- - Operation that checks resource existence/scope and then sends one command
545
+ Cases that do not need a UseCase:
546
+ - A simple operation where the Controller sends one command and is done
547
+ - A simple read where the Controller queries the Query side and converts to a response
548
+ - An operation that only checks existence/scope of an existing resource and then sends one command
190
549
 
191
550
  | Criteria | Judgment |
192
551
  |----------|----------|
193
552
  | Controller directly references Repository for validation | Separate into UseCase layer |
194
- | UseCase depends on HTTP requests/responses | REJECT. UseCase must be protocol-independent |
195
- | UseCase directly modifies Aggregate internal state | REJECT. Use CommandGateway |
196
- | UseCase waits for results via Subscription Query | REJECT. Does not work in distributed environments. Use reactive polling |
197
- | UseCase only delegates to a query boundary or command dispatch | Consider deleting |
553
+ | UseCase depends on HTTP request/response | REJECT. UseCase must be protocol-independent |
554
+ | UseCase directly changes Aggregate internal state | REJECT. Use CommandGateway |
555
+ | UseCase sends multiple commands sequentially for the same state transition | REJECT. Separate into EventHandlers for committed events |
556
+ | UseCase queries the same Aggregate's state to choose the command type | REJECT. Push the decision into the Aggregate |
557
+ | UseCase validates another Aggregate or external facts and passes resolved facts to one command | OK |
558
+ | EventHandler receives a committed event and sends a command to another Aggregate | OK |
559
+ | processStore / ProcessStore / operationProcess / completeStep stores projection completion or procedural progress | REJECT. Model it with Projection and EventHandlers |
560
+ | There is an explicit long-running business process, retry, compensation, or user-visible progress | Consider Saga / Process Manager |
561
+ | UseCase only thinly delegates to another query layer or command dispatch | Consider removing |
562
+
563
+ ## Event-driven Chaining
564
+
565
+ In CQRS+ES, chains of state changes start from committed events. Application Services, UseCases, and Controllers must not synchronously control the order of multiple Aggregate changes by sending commands sequentially for the same state transition.
566
+
567
+ Basic shape:
568
+
569
+ ```text
570
+ UseCase -> Command -> Aggregate -> Event
571
+ |
572
+ EventHandler -> Command -> another Aggregate
573
+ |
574
+ Projection -> Read Model
575
+ ```
576
+
577
+ | Criteria | Judgment |
578
+ |----------|----------|
579
+ | UseCase sends command B immediately after command A for the same state transition | REJECT. Let an EventHandler receive A's event and send B |
580
+ | Another command is sent after `sendAndWait` returns to create consistency | REJECT. Separate into event chaining |
581
+ | A normal event from an existing Aggregate becomes the trigger for derived processing | OK |
582
+ | EventHandler receives a committed event and sends an idempotent command to another Aggregate | OK |
583
+ | Projection update and next-command dispatch are mixed in the same handler | REJECT. Separate Projection from EventHandler |
584
+ | There is contention, compensation, long-running retry, or user-visible progress | Consider Saga / Process Manager |
585
+ | processStore is created only to remember intermediate progress | REJECT. Split responsibilities into Aggregate events, Projections, or Saga |
198
586
 
199
587
  ## Projection Design
200
588
 
201
589
  | Criteria | Judgment |
202
590
  |----------|----------|
203
- | Projection issues commands | REJECT |
204
- | Projection references Write model | REJECT |
205
- | Single projection serves multiple use cases | Needs review |
206
- | Design that cannot be rebuilt | REJECT |
591
+ | Projection dispatches commands | REJECT |
592
+ | Projection references Write Model | REJECT |
593
+ | One projection supports multiple use cases | Needs review |
594
+ | Cannot be rebuilt | REJECT |
595
+
596
+ Good projections:
597
+ - Optimized for a specific read use case
598
+ - Rebuildable idempotently from events
599
+ - Completely independent from Write Model
600
+
601
+ ### Distinguishing Projections from EventHandlers for Side Effects
207
602
 
208
- Good Projection:
209
- - Optimized for specific read use case
210
- - Idempotently reconstructible from events
211
- - Completely independent from Write model
603
+ Both use `@EventHandler`, but their responsibilities differ. Do not confuse them.
212
604
 
213
- ### External Work Triggers
605
+ | Type | Responsibility | Does | Does Not Do |
606
+ |------|----------------|------|-------------|
607
+ | Projection | Read Model update | Save/update Entity | Dispatch commands, call external APIs |
608
+ | EventHandler | Side effect | Dispatch commands to other Aggregates | Update Read Models |
214
609
 
215
- External workers and asynchronous work should start from domain events confirmed by the Aggregate. Application Services and Coordinators must not bundle command dispatch and external side effects in the same control flow.
610
+ ```kotlin
611
+ // Projection: Read Model update only
612
+ @Component
613
+ class OrderProjection(private val orderRepository: OrderRepository) {
614
+ @EventHandler
615
+ fun on(event: OrderPlacedEvent) {
616
+ val entity = OrderEntity(
617
+ orderId = event.orderId,
618
+ customerId = event.customerId,
619
+ status = OrderStatus.PENDING
620
+ )
621
+ orderRepository.save(entity)
622
+ }
623
+
624
+ @EventHandler
625
+ fun on(event: OrderConfirmedEvent) {
626
+ orderRepository.findById(event.orderId).ifPresent { entity ->
627
+ entity.status = OrderStatus.CONFIRMED
628
+ orderRepository.save(entity)
629
+ }
630
+ }
631
+ }
632
+
633
+ // EventHandler: side effect, command dispatch to another Aggregate
634
+ @Component
635
+ class InventoryReleaseHandler(private val commandGateway: CommandGateway) {
636
+ @EventHandler
637
+ fun on(event: OrderCancelledEvent) {
638
+ val command = ReleaseInventoryCommand(
639
+ productId = event.productId,
640
+ quantity = event.quantity
641
+ )
642
+ commandGateway.send<Any>(command)
643
+ }
644
+ }
645
+ ```
646
+
647
+ | Criteria | Judgment |
648
+ |----------|----------|
649
+ | Projection uses CommandGateway | REJECT. Separate into EventHandler |
650
+ | EventHandler saves with Repository | REJECT. Separate into Projection |
651
+ | One class mixes Projection and EventHandler responsibilities | REJECT. Split classes |
652
+
653
+ ### Starting External Processing
654
+
655
+ Starting external workers or asynchronous processing should be triggered by a domain event that an Aggregate has committed. An Application Service or Coordinator must not bundle command dispatch and external side effects in the same control flow for the same state transition.
216
656
 
217
657
  | Criteria | Judgment |
218
658
  |----------|----------|
219
- | Application Service or Coordinator dispatches a command, then starts external work for the same state transition | REJECT. Separate into an EventHandler for the confirmed event |
220
- | Aggregate emits an event that represents generation or processing start, and an EventHandler starts external work | OK |
221
- | EventHandler converts external start failure into a failure command back to the Aggregate | OK |
222
- | Inputs needed by external work are represented in the event or reloadable through stable identifiers | OK |
223
- | Inputs needed by external work exist only as local variables during command handling | REJECT. Move them to events or reloadable references |
224
- | Saga is used only to start simple external work without contention or compensation | REJECT. EventHandler is sufficient |
659
+ | Application Service or Coordinator starts external processing immediately after command dispatch for the same state transition | REJECT. Separate into EventHandler for committed events |
660
+ | Aggregate emits an event that represents generation start or processing start, and EventHandler starts external processing | OK |
661
+ | EventHandler reports external-processing start failure back to the Aggregate with a failure command | OK |
662
+ | Input needed for external processing is represented by the event or stable IDs that can be reloaded | OK |
663
+ | External-processing input exists only in local variables during command processing | REJECT. Move to events or reloadable references |
664
+ | Saga is used for simple external processing with no contention or compensation | REJECT. EventHandler is enough |
225
665
 
226
- ## Query Side Design
666
+ ## Query-side Design
227
667
 
228
- Query side operates on an event-driven PubSub model. Projections update Read Models via EventHandler, and queries read from Read Models.
668
+ The Query side operates as an event-driven PubSub model. Projections update Read Models with EventHandlers, and the Query side references those Read Models.
229
669
 
230
- Event distribution uses PubSub (via message broker) to deliver events to all instances. Do not use mechanisms that assume delivery to the same instance.
670
+ Event delivery should be PubSub, through a message broker, to all instances. Do not rely on mechanisms that deliver only to the same instance unless delivery guarantees are confirmed.
231
671
 
232
- - **Subscription Query** (e.g., Axon's `subscriptionQuery()`): delivers change notifications back to the subscribing instance, but in distributed environments or when using third-party event store plugins, the subscribing instance and the notified instance may differ, making it impossible to return the response on the same machine. When synchronous response is needed, use reactive polling to wait for Read Model updates.
233
- - **Subscribing event processor** (e.g., Axon's `SubscribingEventProcessor`): relies on local event bus subscription, so only the instance that emitted the event receives it. In distributed environments, other instances' Projections are not updated. Use PubSub to distribute events to all instances.
672
+ - **Subscription Query** (for example Axon's `subscriptionQuery()`): a mechanism that returns change notifications for query results to the subscriber. Use it only when it is already adopted as infrastructure and delivery to subscribers is guaranteed. In systems based on tracking processors or trackers, do not introduce subscription query only for a feature implementation.
673
+ - **Subscribing event processor** (for example Axon's `SubscribingEventProcessor`): depends on direct subscription from the local event bus, so only the instance that published the event receives it. In distributed environments, projections on other instances are not updated. Configure PubSub delivery to all instances.
234
674
 
235
675
  | Criteria | Judgment |
236
676
  |----------|----------|
237
- | Using Subscription Query (e.g., Axon's `subscriptionQuery()`) | REJECT. Does not work in distributed environments. Use reactive polling |
238
- | Using Subscribing event processor (e.g., Axon's `SubscribingEventProcessor`) | REJECT. Local delivery only. Other instances not updated in distributed environments |
239
- | Controller directly referencing Repository | REJECT. Must go through UseCase layer |
240
- | Query side referencing Command Model | REJECT |
241
- | QueryHandler issuing commands | REJECT |
677
+ | Use of Subscription Query already adopted as infrastructure with confirmed delivery guarantee, such as Axon Server `subscriptionQuery()` | OK |
678
+ | Introducing Subscription Query only for a feature implementation | REJECT. Use the existing tracker / Read Model polling |
679
+ | Use of Subscription Query with unknown delivery guarantee, such as Axon `subscriptionQuery()` | REJECT. Use the existing tracker / Read Model polling |
680
+ | Use of Subscribing event processor, such as Axon `SubscribingEventProcessor` | REJECT. Local delivery only; other instances are not updated in distributed environments |
681
+ | Controller directly references Repository | REJECT. Go through UseCase layer |
682
+ | Query side references Command Model | REJECT |
683
+ | QueryHandler dispatches commands | REJECT |
242
684
  | Query-side service or handler saves, deletes, or calls external APIs | REJECT |
243
- | Command and Query responsibilities mixed in the same service | REJECT. Separate responsibility and naming |
244
- | Query side checks existence or scope and caller dispatches command | OK |
685
+ | Command and Query are mixed in the same service | REJECT. Separate responsibilities and naming |
686
+ | Query side or ReadService reads Query results to choose the command type for the same Aggregate | REJECT |
687
+ | Query side checks existence/scope of another Aggregate or external facts, and the caller dispatches one command | OK |
245
688
 
246
689
  ### QueryHandler and ApplicationService Naming
247
690
 
248
- In CQRS, the component that receives a query is the QueryHandler, and the entrypoint for dispatching queries is the QueryGateway / QueryBus. A facade called by Controllers for read use cases should be named ApplicationService or ReadService so it is not confused with a QueryHandler.
691
+ In CQRS, the component that receives queries is called a QueryHandler, and the entry point that sends queries is treated as QueryGateway / QueryBus. A facade called from a Controller to coordinate read use cases should be named ApplicationService or ReadService so it is not confused with QueryHandler.
249
692
 
250
693
  | Criteria | Judgment |
251
694
  |----------|----------|
252
- | Receives a Query, reads the Read Model, and returns a query result type | QueryHandler |
253
- | Coordinates multiple Queries, authorization boundaries, pagination, or DTO assembly for Controllers | ApplicationService or ReadService |
254
- | Class that only dispatches queries or coordinates reads is named QueryService | Warning. Easy to confuse with QueryHandler |
255
- | QueryHandler knows HTTP requests/responses or Controller-specific error translation | REJECT |
256
- | Simple read wrapper with no additional decision-making | Consider deleting. Controller may call QueryGateway directly |
695
+ | Receives a Query, references Read Model, and returns a query-result type | QueryHandler |
696
+ | Coordinates multiple Queries, authorization boundary, paging, and DTO assembly from Controller | ApplicationService or ReadService |
697
+ | A class that only sends queries or coordinates reads is called QueryService | Warning. Easy to confuse with QueryHandler |
698
+ | QueryHandler knows HTTP request/response or Controller-specific error conversion | REJECT |
699
+ | Adds a simple read wrapper with no additional decision | Consider removing. Controller may call QueryGateway directly |
257
700
 
258
701
  Types between layers:
259
- - `application/query/` - Query result types (e.g., `OrderDetail`)
260
- - `adapter/protocol/` - REST response types (e.g., `OrderDetailResponse`)
261
- - QueryHandler returns application layer types, Controller converts to adapter layer types
702
+ - `application/query/` - query-result type, for example `OrderDetail`
703
+ - `adapter/protocol/` - REST response type, for example `OrderDetailResponse`
704
+ - QueryHandler returns application-layer types; Controller converts them to adapter-layer types
262
705
 
263
706
  ```kotlin
264
707
  // application/query/OrderDetail.kt
@@ -275,14 +718,14 @@ data class OrderDetailResponse(...) {
275
718
  }
276
719
  }
277
720
 
278
- // QueryHandler - returns application layer type
721
+ // QueryHandler - returns application-layer type
279
722
  @QueryHandler
280
723
  fun handle(query: GetOrderDetailQuery): OrderDetail? {
281
724
  val entity = repository.findById(query.id) ?: return null
282
725
  return OrderDetail(...)
283
726
  }
284
727
 
285
- // Controller - synchronous return is fine for simple reads
728
+ // Controller - simple reference can return synchronously
286
729
  @GetMapping("/{id}")
287
730
  fun getById(@PathVariable id: String): ResponseEntity<OrderDetailResponse> {
288
731
  val detail = queryGateway.query(
@@ -296,45 +739,57 @@ fun getById(@PathVariable id: String): ResponseEntity<OrderDetailResponse> {
296
739
 
297
740
  Structure:
298
741
  ```
299
- Controller (adapter) QueryGateway QueryHandler (application) Repository
300
-
742
+ Controller (adapter) -> QueryGateway -> QueryHandler (application) -> Repository
743
+ | |
301
744
  Response.from(detail) OrderDetail
302
745
 
303
746
  Event flow (PubSub):
304
- Aggregate Event Bus Projection(@EventHandler) Repository(Read Model)
305
-
306
- QueryHandler reads from here
747
+ Aggregate -> Event Bus -> Projection(@EventHandler) -> Repository(Read Model)
748
+ ^
749
+ QueryHandler references this
307
750
  ```
308
751
 
309
- ### Async Callbacks and Concurrency Control
752
+ ### Asynchronous Callbacks and Concurrency Control
310
753
 
311
- Completion notifications for asynchronous work must assume duplicates, delays, and reordering. Protect the workflow with Aggregate state transitions and command idempotency, not Controller-level or single-process locks.
754
+ Design asynchronous completion callbacks assuming duplicates, delays, and ordering inversions. Protect with Aggregate state transitions and command idempotency, not Controller or single-process locks.
312
755
 
313
756
  | Criteria | Judgment |
314
757
  |----------|----------|
315
- | Controller or application-process lock prevents duplicate callbacks | REJECT. It does not work across multiple instances |
316
- | Aggregate state decides whether work is processing | OK |
317
- | Aggregate verifies callback attempt/generation identifiers | OK |
318
- | Stale or duplicate callbacks are idempotently ignored by state transition | OK |
758
+ | Prevent duplicate callbacks with Controller or application-process locks | REJECT. Does not work across instances |
759
+ | Determine processing state from Aggregate state | OK |
760
+ | Aggregate verifies callback attempt ID or generation | OK |
761
+ | Idempotently ignore old or duplicate callbacks by state transition | OK |
319
762
  | Concurrency control is duplicated across Controller, UseCase, and Aggregate | REJECT |
320
763
 
321
764
  ## Eventual Consistency
322
765
 
323
- When synchronous response is needed after command dispatch, use reactive polling to wait for Projection updates.
766
+ Wait for Projection updates after command dispatch only when there is an explicit synchronous contract to return the updated Read Model in the same API response. If the client can keep the input values or generated ID, the server should not wait; Read Model convergence is handled through normal read APIs.
324
767
 
325
768
  | Criteria | Judgment |
326
769
  |----------|----------|
327
- | Using Subscription Query to wait for Projection updates | REJECT. Does not work in distributed environments. Use reactive polling |
328
- | UI expects immediate updates | Polling or WebSocket |
329
- | Consistency delay exceeds tolerance | Reconsider architecture |
330
- | Compensating transactions undefined | Request failure scenario review |
770
+ | No explicit contract to return the updated Read Model in the same response | Do not wait |
771
+ | The client or caller can keep the command input or generated ID | Do not wait |
772
+ | There is infrastructure guaranteeing Projection update notification delivery to the waiting process | OK. Notification-driven waiting is acceptable |
773
+ | Existing infrastructure such as Subscription Query confirms update notifications reach subscribers | OK |
774
+ | Kafka or similar guarantees destination, redelivery, and missing-message handling operationally | OK |
775
+ | Subscription Query or event notification destination assumes single process/single instance, or guarantee is unknown | REJECT. Use the existing tracker / Read Model polling |
776
+ | `Thread.sleep` or equivalent blocks request threads while waiting for Projection updates | REJECT. Causes thread starvation under high concurrency |
777
+ | `delayedExecutor` / `CompletableFuture` is used to implement custom Projection-wait retry | REJECT. Use a reactive HTTP stack or the existing tracker |
778
+ | processStore / ProcessStore / materialStore / completeStep manages Projection update progress | REJECT. Projections should update idempotently from events |
779
+ | Updated state must be returned in the same HTTP response | Wait non-blockingly on a reactive HTTP stack |
780
+ | Same response does not need to wait | `202 Accepted` plus frontend long polling, normal polling, SSE, or WebSocket |
781
+ | UI expects immediate update | Frontend polling, SSE, or WebSocket. Server-side waiting only for a synchronous API contract |
782
+ | Consistency delay exceeds acceptable range | Reconsider architecture |
783
+ | Compensation transaction is undefined | Require failure-scenario review |
331
784
 
332
785
  ### Reactive Polling
333
786
 
334
- Pattern: dispatch command poll for Projection update completion.
787
+ Reactive polling is the pattern of dispatching a command and then waiting non-blockingly for Projection update completion. It does not occupy a request thread and is not a synchronous `while` loop with `Thread.sleep`.
788
+
789
+ The polling condition should be checked by re-fetching the Read Model and testing whether it has reached the expected state, not by event notifications. Re-fetch at a fixed interval until the condition is met, timeout occurs, or max attempts are reached.
335
790
 
336
791
  ```kotlin
337
- // UseCase: send command poll for completion
792
+ // UseCase: command dispatch -> wait for completion with polling
338
793
  fun execute(input: PlaceOrderInput): Mono<PlaceOrderOutput> {
339
794
  val orderId = UUID.randomUUID().toString()
340
795
  return Mono.fromCallable { validatePreConditions(input) }
@@ -359,40 +814,56 @@ private fun pollForCompletion(orderId: String): Mono<Void> {
359
814
  }
360
815
  ```
361
816
 
362
- When polling is appropriate:
363
- - Need to wait for Saga completion before returning response
364
- - Need to return created resource ID after command dispatch
817
+ Avoid blocking waits:
818
+
819
+ ```kotlin
820
+ // NG - Occupies request threads and causes thread starvation under load
821
+ while (Instant.now().isBefore(deadline)) {
822
+ val order = orderRepository.findById(orderId).orElse(null)
823
+ if (order?.status == OrderStatus.CONFIRMED) return PlaceOrderOutput(orderId)
824
+ Thread.sleep(100)
825
+ }
826
+
827
+ // OK - If the same response must wait, put it on reactive waiting
828
+ return pollForCompletion(orderId).thenReturn(PlaceOrderOutput(orderId))
829
+ ```
830
+
831
+ Cases where polling is appropriate:
832
+ - The response should not return until Saga completion
833
+ - The command dispatch creates a resource ID and the response needs to return it
365
834
 
366
- When polling is not needed:
367
- - Simple operations that complete with just command dispatch (no result waiting)
368
- - UI does not require real-time updates
835
+ Cases where polling is unnecessary:
836
+ - A simple operation where command dispatch alone completes the work and the result is not waited on
837
+ - The UI does not need real-time update
838
+
839
+ If the server does not wait, return `202 Accepted` with a tracking ID after accepting the command, and let the frontend use long polling or normal polling on the read API. SSE or WebSocket can also be considered if the user experience requires immediacy.
369
840
 
370
841
  ## Saga vs EventHandler
371
842
 
372
- Saga is used only for "operations between multiple aggregates where contention occurs".
843
+ Use Saga only for operations involving contention between multiple Aggregates.
373
844
 
374
- Cases where Saga is needed:
845
+ Cases that need Saga:
375
846
  ```
376
- When multiple actors compete for the same resource
377
- Example: Inventory reservation (10 people ordering the same product simultaneously)
847
+ Multiple actors compete for the same resource
848
+ Example: inventory reservation, where 10 people order the same product at the same time
378
849
 
379
850
  OrderPlacedEvent
380
- InventoryReservationSaga
381
- ReserveInventoryCommand Inventory aggregate (serializes concurrent execution)
382
-
383
- InventoryReservedEvent ConfirmOrderCommand
384
- InventoryReservationFailedEvent CancelOrderCommand
851
+ -> InventoryReservationSaga
852
+ ReserveInventoryCommand -> Inventory Aggregate (serializes concurrency)
853
+ ->
854
+ InventoryReservedEvent -> ConfirmOrderCommand
855
+ InventoryReservationFailedEvent -> CancelOrderCommand
385
856
  ```
386
857
 
387
- Cases where Saga is not needed:
858
+ Cases that do not need Saga:
388
859
  ```
389
- Non-competing operations
390
- Example: Inventory release on order cancellation
860
+ Operation with no contention
861
+ Example: releasing inventory on order cancellation
391
862
 
392
863
  OrderCancelledEvent
393
- InventoryReleaseHandler (simple EventHandler)
864
+ -> InventoryReleaseHandler (simple EventHandler)
394
865
  ReleaseInventoryCommand
395
-
866
+ ->
396
867
  InventoryReleasedEvent
397
868
  ```
398
869
 
@@ -401,35 +872,35 @@ Decision criteria:
401
872
  | Situation | Saga | EventHandler |
402
873
  |-----------|------|--------------|
403
874
  | Resource contention exists | Use | - |
404
- | Compensating transaction needed | Use | - |
405
- | Non-competing simple coordination | - | Use |
406
- | Retry on failure is sufficient | - | Use |
875
+ | Compensation transaction is needed | Use | - |
876
+ | Simple integration with no contention | - | Use |
877
+ | Retry is enough on failure | - | Use |
407
878
 
408
879
  Anti-pattern:
409
880
  ```kotlin
410
881
  // NG - Using Saga for lifecycle management
411
882
  @Saga
412
883
  class OrderLifecycleSaga {
413
- // Tracking all order state transitions in Saga
414
- // PLACED CONFIRMED SHIPPED DELIVERED
884
+ // Tracks every order state transition
885
+ // PLACED -> CONFIRMED -> SHIPPED -> DELIVERED
415
886
  }
416
887
 
417
- // OK - Saga only for operations requiring eventual consistency
888
+ // OK - Saga only for operations that need eventual consistency
418
889
  @Saga
419
890
  class InventoryReservationSaga {
420
- // Only for inventory reservation concurrency control
891
+ // Concurrency control for inventory reservation only
421
892
  }
422
893
  ```
423
894
 
424
- Saga is not a lifecycle management tool. Create it per "operation" that requires eventual consistency.
895
+ Saga is not a lifecycle-management tool. Create it for an operation that needs eventual consistency.
425
896
 
426
- ## Exception vs Event (Failure Handling)
897
+ ## Exception vs Event: Failure Choice
427
898
 
428
- Failures not requiring audit use exceptions, failures requiring audit use events.
899
+ Failures that do not require audit are exceptions; failures that require audit are events.
429
900
 
430
- Exception approach (recommended: most cases):
901
+ Exception approach, recommended in most cases:
431
902
  ```kotlin
432
- // Domain model: Throws exception on validation failure
903
+ // Domain model: throw an exception on validation failure
433
904
  fun reserveInventory(orderId: String, quantity: Int): InventoryReservedEvent {
434
905
  if (availableQuantity < quantity) {
435
906
  throw InsufficientInventoryException("Insufficient inventory")
@@ -437,7 +908,7 @@ fun reserveInventory(orderId: String, quantity: Int): InventoryReservedEvent {
437
908
  return InventoryReservedEvent(productId, orderId, quantity)
438
909
  }
439
910
 
440
- // Saga: Catch with exceptionally and perform compensating action
911
+ // Saga: catch with exceptionally and issue compensation action
441
912
  commandGateway.send<Any>(command)
442
913
  .exceptionally { ex ->
443
914
  commandGateway.send<Any>(CancelOrderCommand(
@@ -448,7 +919,7 @@ commandGateway.send<Any>(command)
448
919
  }
449
920
  ```
450
921
 
451
- Event approach (rare cases):
922
+ Event approach, rare cases:
452
923
  ```kotlin
453
924
  // Only when audit is required
454
925
  data class PaymentFailedEvent(
@@ -462,37 +933,37 @@ Decision criteria:
462
933
 
463
934
  | Question | Exception | Event |
464
935
  |----------|-----------|-------|
465
- | Need to check this failure later? | No | Yes |
466
- | Required by regulations/compliance? | No | Yes |
467
- | Only Saga cares about the failure? | Yes | No |
468
- | Is there value in keeping it in Event Store? | No | Yes |
936
+ | Does this failure need to be reviewed later? | No | Yes |
937
+ | Is a record required by regulation or compliance? | No | Yes |
938
+ | Is only the Saga interested in the failure? | Yes | No |
939
+ | Is there value in storing it in the Event Store? | No | Yes |
469
940
 
470
- Default is exception approach. Consider events only when audit requirements exist.
941
+ Default to the exception approach. Consider events only when there is an audit requirement.
471
942
 
472
- ## Abstraction Level Evaluation
943
+ ## Abstraction-level Evaluation
473
944
 
474
- **Conditional branch proliferation detection:**
945
+ **Detecting bloated conditional branches**
475
946
 
476
947
  | Pattern | Judgment |
477
948
  |---------|----------|
478
- | Same if-else pattern in 3+ places | Abstract with polymorphism REJECT |
479
- | switch/case with 5+ branches | Consider Strategy/Map pattern |
480
- | Event type branching proliferating | Separate event handlers REJECT |
481
- | Complex state branching in Aggregate | Consider State Pattern |
949
+ | Same if-else pattern appears in 3 or more places | Abstract with polymorphism -> REJECT |
950
+ | switch/case has 5 or more branches | Consider Strategy/Map pattern |
951
+ | Branching by event type grows repeatedly | Split EventHandlers -> REJECT |
952
+ | State branching inside Aggregate is complex | Consider State Pattern |
482
953
 
483
- **Abstraction level mismatch detection:**
954
+ **Detecting mismatched abstraction levels**
484
955
 
485
956
  | Pattern | Problem | Fix |
486
957
  |---------|---------|-----|
487
- | DB operation details in CommandHandler | Responsibility violation | Separate to Repository layer |
958
+ | DB operation details in CommandHandler | Responsibility violation | Separate into Repository layer |
488
959
  | Business logic in EventHandler | Responsibility violation | Extract to domain service |
489
- | Persistence in Aggregate | Layer violation | Change to EventStore route |
960
+ | Persistence processing in Aggregate | Layer violation | Move behind EventStore |
490
961
  | Calculation logic in Projection | Hard to maintain | Extract to dedicated service |
491
962
 
492
963
  Good abstraction examples:
493
964
 
494
965
  ```kotlin
495
- // Event type branching proliferation (NG)
966
+ // Event-type branching grows repeatedly (NG)
496
967
  @EventHandler
497
968
  fun on(event: DomainEvent) {
498
969
  when (event) {
@@ -503,7 +974,7 @@ fun on(event: DomainEvent) {
503
974
  }
504
975
  }
505
976
 
506
- // Separate handlers per event (OK)
977
+ // Split by event (OK)
507
978
  @EventHandler
508
979
  fun on(event: OrderPlacedEvent) { ... }
509
980
 
@@ -520,11 +991,11 @@ fun process(command: ProcessCommand) {
520
991
  when (status) {
521
992
  PENDING -> if (command.type == "approve") { ... } else if (command.type == "reject") { ... }
522
993
  APPROVED -> if (command.type == "ship") { ... }
523
- // ...gets complex
994
+ // ...complexity grows
524
995
  }
525
996
  }
526
997
 
527
- // Abstracted with State Pattern (OK)
998
+ // State Pattern (OK)
528
999
  sealed class OrderState {
529
1000
  abstract fun handle(command: ProcessCommand): List<DomainEvent>
530
1001
  }
@@ -539,37 +1010,37 @@ class PendingState : OrderState() {
539
1010
 
540
1011
  ## Anti-pattern Detection
541
1012
 
542
- REJECT if found:
1013
+ Reject when any of the following is found:
543
1014
 
544
1015
  | Anti-pattern | Problem |
545
1016
  |--------------|---------|
546
- | CRUD Disguise | Just splitting CRUD into Command/Query |
547
- | Anemic Domain Model | Aggregate is just a data structure |
548
- | Event Soup | Meaningless events proliferate |
1017
+ | CRUD disguise | Only mimics the shape of CQRS while implementing CRUD |
1018
+ | Anemic Domain Model | Aggregate is only a data structure |
1019
+ | Event Soup | Meaningless events are emitted repeatedly |
549
1020
  | Temporal Coupling | Implicit dependency on event order |
550
1021
  | Missing Events | Important domain events are missing |
551
- | God Aggregate | All responsibilities in one Aggregate |
1022
+ | God Aggregate | One Aggregate concentrates all responsibilities |
552
1023
 
553
1024
  ## Test Strategy
554
1025
 
555
- Separate test strategies by layer.
1026
+ Separate test strategy by layer.
556
1027
 
557
- Test Pyramid:
1028
+ Test pyramid:
558
1029
  ```
559
- ┌─────────────┐
560
- E2E Test Few: Overall flow confirmation
561
- ├─────────────┤
562
- Integration CommandEventProjectionQuery coordination
563
- ├─────────────┤
564
- Unit Test Many: Each layer tested independently
565
- └─────────────┘
1030
+ +-------------+
1031
+ | E2E Test | <- Few: full-flow confirmation
1032
+ +-------------+
1033
+ | Integration | <- Command -> Event -> Projection -> Query integration
1034
+ +-------------+
1035
+ | Unit Test | <- Many: each layer isolated
1036
+ +-------------+
566
1037
  ```
567
1038
 
568
1039
  Command side (Aggregate):
569
1040
  ```kotlin
570
1041
  // Using AggregateTestFixture
571
1042
  @Test
572
- fun `confirm command emits event`() {
1043
+ fun `confirmation command emits event`() {
573
1044
  fixture
574
1045
  .given(OrderPlacedEvent(...))
575
1046
  .`when`(ConfirmOrderCommand(orderId, confirmedBy))
@@ -582,11 +1053,11 @@ Query side:
582
1053
  ```kotlin
583
1054
  // Direct Read Model setup + QueryGateway
584
1055
  @Test
585
- fun `can get order details`() {
586
- // Given: Setup Read Model directly
1056
+ fun `order detail is returned`() {
1057
+ // Given: set up Read Model directly
587
1058
  orderRepository.save(OrderEntity(...))
588
1059
 
589
- // When: Execute query via QueryGateway
1060
+ // When: execute query through QueryGateway
590
1061
  val detail = queryGateway.query(GetOrderDetailQuery(orderId), ...).join()
591
1062
 
592
1063
  // Then
@@ -596,41 +1067,102 @@ fun `can get order details`() {
596
1067
 
597
1068
  Checklist:
598
1069
 
599
- | Aspect | Judgment |
600
- |--------|----------|
601
- | Aggregate tests verify events not state | Required |
602
- | Query side tests don't create data via Command | Recommended |
603
- | Integration tests consider Axon async processing | Required |
1070
+ | Perspective | Judgment |
1071
+ |-------------|----------|
1072
+ | Aggregate tests verify events, not state | Required |
1073
+ | Query-side tests do not create data through commands | Recommended |
1074
+ | Integration tests account for Axon asynchronous processing | Required |
1075
+
1076
+ ## Value Object Design
1077
+
1078
+ Use value objects as Aggregate and event components. Do not rely only on primitive types such as String or Int.
604
1079
 
605
- ## Master Data and CRUD
1080
+ ```kotlin
1081
+ // NG - primitives only
1082
+ data class OrderPlacedEvent(
1083
+ val orderId: String,
1084
+ val categoryId: String, // Just a string
1085
+ val from: LocalDateTime, // Meaning is unclear
1086
+ val to: LocalDateTime
1087
+ )
1088
+
1089
+ // OK - Value objects express meaning and constraints
1090
+ data class OrderPlacedEvent(
1091
+ val orderId: String,
1092
+ val categoryId: CategoryId,
1093
+ val period: OrderPeriod
1094
+ )
1095
+ ```
1096
+
1097
+ Value object design rules:
1098
+ - Use `data class` to auto-generate equals/hashCode, comparing by value
1099
+ - Guarantee invariants in `init` blocks, validating at creation
1100
+ - Do not include domain logic such as state transitions; keep them as pure data holders
1101
+ - Use `@JsonValue` to control serialization
1102
+
1103
+ ```kotlin
1104
+ // ID type: single-value wrapper
1105
+ data class CategoryId(@get:JsonValue val value: String) {
1106
+ init {
1107
+ require(value.isNotBlank()) { "Category ID cannot be blank" }
1108
+ }
1109
+ override fun toString(): String = value
1110
+ }
606
1111
 
607
- Not everything in a CQRS+ES system needs event sourcing. Master data (reference data) with simple characteristics is better implemented as plain CRUD — it's simpler and easier to maintain.
1112
+ // Range type: invariant over multiple values
1113
+ data class OrderPeriod(
1114
+ val from: LocalDateTime,
1115
+ val to: LocalDateTime
1116
+ ) {
1117
+ init {
1118
+ require(!to.isBefore(from)) { "End date must be on or after start date" }
1119
+ }
1120
+ }
1121
+
1122
+ // Metadata type: associated data in event payload
1123
+ data class ApprovalInfo(
1124
+ val approvedBy: String,
1125
+ val approvalTime: LocalDateTime
1126
+ )
1127
+ ```
608
1128
 
609
- However, don't mechanically decide "it's master data, so CRUD". The more criteria below that apply, the more CRUD is suitable. Conversely, if even one requirement calls for CQRS+ES, consider adopting it.
1129
+ | Criteria | Judgment |
1130
+ |----------|----------|
1131
+ | Reusing IDs as raw String | Consider value object |
1132
+ | Same field combination, such as from/to, appears in multiple places | Extract value object |
1133
+ | Value object contains business logic such as state transitions | REJECT. Aggregate responsibility |
1134
+ | No `init` block to guarantee invariants | REJECT |
1135
+
1136
+ ## Master Data, Settings, and CRUD Use
610
1137
 
611
- **Criteria for determining CRUD is sufficient:**
1138
+ Even inside a CQRS+ES system, not everything needs to be event-sourced. Simple master data, reference data, managed settings, and allowlists are often simpler and easier to maintain as normal CRUD.
612
1139
 
613
- | Aspect | Leans CRUD | Leans CQRS+ES |
614
- |--------|-----------|---------------|
615
- | Business requirements | Just "manage X" with no special mentions | Specific business rules or constraints |
616
- | Logic evolution | Simple reference/update, no foreseeable complexity | State transitions or lifecycle may grow complex |
617
- | Change history / audit | No need to track "who changed what when" | Change history or audit trail required |
618
- | Domain events | Changes don't affect other aggregates or processes | Changes trigger downstream processes |
619
- | Consistency scope | Self-contained, no cross-aggregate consistency needed | Must maintain consistency with other aggregates |
620
- | Point-in-time queries | No "what was the state at time T" queries | Point-in-time queries required |
1140
+ Do not mechanically decide "master data means CRUD". The more the following criteria apply, the more suitable CRUD is. Conversely, if explicit requirements match CQRS+ES adoption criteria, consider CQRS+ES.
621
1141
 
622
- **Typical CRUD candidates:**
623
- - Code masters such as prefecture/country codes
624
- - Classification masters such as categories and tags
625
- - Configuration values, constant tables
1142
+ **Criteria for deciding CRUD is enough:**
626
1143
 
627
- **Cases where CQRS+ES is justified:**
628
- - Product master, but price change history tracking is needed
629
- - Organization master, but changes trigger permission recalculation
630
- - Business partner master, but has credit assessment state transitions
1144
+ | Perspective | CRUD-leaning | CQRS+ES-leaning |
1145
+ |-------------|--------------|-----------------|
1146
+ | Business requirement | Around "manage X" with no special mention | Specific business rules or constraints exist |
1147
+ | Logic evolution | Simple reference/update completes it, unlikely to evolve | State transitions or lifecycle can become complex |
1148
+ | Change history/audit | No need to track who changed what and when | Need change-history reference or audit evidence |
1149
+ | Domain events | This change does not affect other Aggregates or processes | Change triggers downstream processes |
1150
+ | Consistency scope | Self-contained, no need for consistency with other Aggregates | Needs consistency with other Aggregates |
1151
+ | Point-in-time reference | No question asks for "state at a past point" | Point-in-time queries are needed |
1152
+
1153
+ **Typical CRUD targets:**
1154
+ - Prefecture and country-code master data
1155
+ - Category and tag classification master data
1156
+ - Settings and constant tables
1157
+ - Current-value managed settings such as IP allowlists, feature flags, and notification settings
1158
+
1159
+ **Examples where CQRS+ES can be justified:**
1160
+ - Product master data where price-change history must be tracked
1161
+ - Organization master data where changes trigger permission recalculation
1162
+ - Customer/vendor master data with credit-review state transitions
631
1163
 
632
1164
  ```kotlin
633
- // CRUD is sufficient: Simple category master
1165
+ // CRUD is enough: simple category master
634
1166
  @Entity
635
1167
  data class Category(
636
1168
  @Id val categoryId: String,
@@ -638,7 +1170,7 @@ data class Category(
638
1170
  val displayOrder: Int
639
1171
  )
640
1172
 
641
- // CQRS+ES is appropriate: Product with price change history tracking
1173
+ // CQRS+ES is appropriate: product requiring price-change history
642
1174
  data class Product(
643
1175
  val productId: String,
644
1176
  val currentPrice: Money
@@ -650,12 +1182,12 @@ data class Product(
650
1182
  }
651
1183
  ```
652
1184
 
653
- Even when implementing with CRUD, other aggregates in the CQRS+ES system reference CRUD entities by ID. The principle that CRUD entities don't directly access aggregate internal state still applies.
1185
+ When implementing with CRUD, other Aggregates in a CQRS+ES system should still reference it by ID. It is the same principle that CRUD entities must not directly reference Aggregate internal state.
654
1186
 
655
1187
  ## Infrastructure Layer
656
1188
 
657
- Check:
658
- - Is event store choice appropriate?
659
- - Does messaging infrastructure meet requirements?
660
- - Is snapshot strategy defined?
661
- - Is event serialization format appropriate?
1189
+ Checklist:
1190
+ - Is the event-store choice appropriate?
1191
+ - Does the messaging infrastructure satisfy requirements?
1192
+ - Is the snapshot strategy defined?
1193
+ - Is the event serialization format appropriate?