aiwf 0.3.22 → 0.4.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 (456) hide show
  1. package/.claude-plugin/marketplace.json +146 -0
  2. package/CHANGELOG.md +49 -1
  3. package/README.ko.md +118 -309
  4. package/README.md +68 -254
  5. package/docs/modernization/BROWNFIELD-GREENFIELD.ko.md +105 -0
  6. package/docs/modernization/CLAUDE-PLAN-REVIEW-2026-10-03.ko.md +77 -0
  7. package/docs/modernization/CLI-PRODUCTIVITY-REVIEWED-2026-10-03.ko.md +177 -0
  8. package/docs/modernization/CLI-PRODUCTIVITY.ko.md +193 -0
  9. package/docs/modernization/CORE-PACKAGE-PLAN.md +7 -0
  10. package/docs/modernization/DEEP-REVERSE-ENGINEERING.ko.md +88 -0
  11. package/docs/modernization/DELEGATION-OPTIONAL.ko.md +57 -0
  12. package/docs/modernization/DIRECTION.ko.md +56 -0
  13. package/docs/modernization/FULL-TEST-2026-10-03.md +49 -0
  14. package/docs/modernization/LEGACY-REMOVAL-PLAN.md +9 -0
  15. package/docs/modernization/PILOT-RESULT-2026-10-03.ko.md +85 -0
  16. package/docs/modernization/PILOT-UC-001.ko.md +79 -0
  17. package/docs/modernization/PLAN.md +28 -0
  18. package/docs/modernization/SKILLS.ko.md +105 -0
  19. package/docs/modernization/SPRINTABLE.ko.md +47 -0
  20. package/docs/modernization/SYNC-DOCS-VALIDATION-2026-10-04.ko.md +38 -0
  21. package/docs/modernization/VALIDATION.md +79 -0
  22. package/docs/modernization/evidence/example-review-packet.json +115 -0
  23. package/docs/modernization/evidence/example-spec-pin.json +48 -0
  24. package/docs/modernization/evidence/full-test-20261003/claude-lint.md +22 -0
  25. package/docs/modernization/evidence/full-test-20261003/claude-review-retry.md +56 -0
  26. package/docs/modernization/evidence/full-test-20261003/codex-review-packet.json +159 -0
  27. package/docs/modernization/evidence/full-test-20261003/src/expense.mjs +40 -0
  28. package/docs/modernization/evidence/full-test-20261003/summary.json +106 -0
  29. package/docs/modernization/evidence/full-test-20261003/tests/expense.test.mjs +61 -0
  30. package/docs/modernization/evidence/local-pilot-20261003/README.ko.md +40 -0
  31. package/docs/modernization/evidence/local-pilot-20261003/execution.json +1055 -0
  32. package/docs/modernization/evidence/local-pilot-20261003/maintenance/dependencies.json +24 -0
  33. package/docs/modernization/evidence/local-pilot-20261003/maintenance/dependencies.stderr.txt +0 -0
  34. package/docs/modernization/evidence/local-pilot-20261003/maintenance/dependencies.stdout.txt +5 -0
  35. package/docs/modernization/evidence/local-pilot-20261003/maintenance/docs.json +24 -0
  36. package/docs/modernization/evidence/local-pilot-20261003/maintenance/docs.stderr.txt +0 -0
  37. package/docs/modernization/evidence/local-pilot-20261003/maintenance/docs.stdout.txt +6 -0
  38. package/docs/modernization/evidence/local-pilot-20261003/maintenance/example.json +24 -0
  39. package/docs/modernization/evidence/local-pilot-20261003/maintenance/example.stderr.txt +0 -0
  40. package/docs/modernization/evidence/local-pilot-20261003/maintenance/example.stdout.txt +5 -0
  41. package/docs/modernization/evidence/local-pilot-20261003/maintenance/local-docs.json +24 -0
  42. package/docs/modernization/evidence/local-pilot-20261003/maintenance/local-docs.stderr.txt +0 -0
  43. package/docs/modernization/evidence/local-pilot-20261003/maintenance/local-docs.stdout.txt +6 -0
  44. package/docs/modernization/evidence/local-pilot-20261003/maintenance/node.json +23 -0
  45. package/docs/modernization/evidence/local-pilot-20261003/maintenance/node.stderr.txt +0 -0
  46. package/docs/modernization/evidence/local-pilot-20261003/maintenance/node.stdout.txt +535 -0
  47. package/docs/modernization/evidence/local-pilot-20261003/maintenance/provenance.json +24 -0
  48. package/docs/modernization/evidence/local-pilot-20261003/maintenance/provenance.stderr.txt +0 -0
  49. package/docs/modernization/evidence/local-pilot-20261003/maintenance/provenance.stdout.txt +5 -0
  50. package/docs/modernization/evidence/local-pilot-20261003/maintenance/readme-replay.json +24 -0
  51. package/docs/modernization/evidence/local-pilot-20261003/maintenance/readme-replay.stderr.txt +0 -0
  52. package/docs/modernization/evidence/local-pilot-20261003/maintenance/readme-replay.stdout.txt +273 -0
  53. package/docs/modernization/evidence/local-pilot-20261003/maintenance/upstream.json +24 -0
  54. package/docs/modernization/evidence/local-pilot-20261003/maintenance/upstream.stderr.txt +0 -0
  55. package/docs/modernization/evidence/local-pilot-20261003/maintenance/upstream.stdout.txt +7 -0
  56. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/archive-service.stderr.txt +0 -0
  57. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/archive-service.stdout.txt +148 -0
  58. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/archive-structure.stderr.txt +0 -0
  59. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/archive-structure.stdout.txt +9 -0
  60. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-check.stderr.txt +0 -0
  61. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-check.stdout.txt +67 -0
  62. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-evidence.json +34 -0
  63. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-packet.json +128 -0
  64. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-packet.stderr.txt +0 -0
  65. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-packet.stdout.txt +128 -0
  66. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-pin.json +54 -0
  67. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-pin.stderr.txt +0 -0
  68. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-pin.stdout.txt +60 -0
  69. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-readback.json +15 -0
  70. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-service.stderr.txt +0 -0
  71. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-service.stdout.txt +82 -0
  72. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-structure.stderr.txt +0 -0
  73. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/baseline-structure.stdout.txt +9 -0
  74. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-check.stderr.txt +0 -0
  75. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-check.stdout.txt +79 -0
  76. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-packet-refused.stderr.txt +0 -0
  77. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-packet-refused.stdout.txt +7 -0
  78. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-pin-refresh.stderr.txt +0 -0
  79. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-pin-refresh.stdout.txt +66 -0
  80. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-pin.json +60 -0
  81. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-structure.stderr.txt +0 -0
  82. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/changed-structure.stdout.txt +9 -0
  83. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-check.stderr.txt +0 -0
  84. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-check.stdout.txt +73 -0
  85. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-evidence.json +34 -0
  86. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-packet.json +134 -0
  87. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-packet.stderr.txt +0 -0
  88. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-packet.stdout.txt +134 -0
  89. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-readback.json +15 -0
  90. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-service.stderr.txt +0 -0
  91. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-service.stdout.txt +148 -0
  92. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-structure.stderr.txt +0 -0
  93. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/final-structure.stdout.txt +9 -0
  94. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/node-version.stderr.txt +0 -0
  95. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/node-version.stdout.txt +1 -0
  96. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/python-version.stderr.txt +0 -0
  97. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/python-version.stdout.txt +1 -0
  98. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-evidence.json +34 -0
  99. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-packet.json +134 -0
  100. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-packet.stderr.txt +0 -0
  101. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-packet.stdout.txt +134 -0
  102. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-readback.json +15 -0
  103. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-service.stderr.txt +0 -0
  104. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-service.stdout.txt +266 -0
  105. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-structure.stderr.txt +0 -0
  106. package/docs/modernization/evidence/local-pilot-20261003/project/artifacts/red-structure.stdout.txt +9 -0
  107. package/docs/modernization/evidence/local-pilot-20261003/project/docs/entity_model.md +33 -0
  108. package/docs/modernization/evidence/local-pilot-20261003/project/docs/glossary.md +9 -0
  109. package/docs/modernization/evidence/local-pilot-20261003/project/docs/plans/UC-001.md +20 -0
  110. package/docs/modernization/evidence/local-pilot-20261003/project/docs/requirements.md +10 -0
  111. package/docs/modernization/evidence/local-pilot-20261003/project/docs/test_cases/TC-001-submit-expense.md +37 -0
  112. package/docs/modernization/evidence/local-pilot-20261003/project/docs/test_cases/TC-002-description-limit.md +42 -0
  113. package/docs/modernization/evidence/local-pilot-20261003/project/docs/use_cases/UC-001-submit-expense.md +76 -0
  114. package/docs/modernization/evidence/local-pilot-20261003/project/docs/use_cases.puml +12 -0
  115. package/docs/modernization/evidence/local-pilot-20261003/project/docs/vision.md +21 -0
  116. package/docs/modernization/evidence/local-pilot-20261003/project/src/expense.mjs +48 -0
  117. package/docs/modernization/evidence/local-pilot-20261003/project/tests/expense.test.mjs +116 -0
  118. package/docs/modernization/evidence/local-pilot-20261003/scope.json +31 -0
  119. package/docs/modernization/reviews/2026-10-03-claude-cli/CONTRACTS.ko.md +122 -0
  120. package/docs/modernization/reviews/2026-10-03-claude-cli/DIRECTION.ko.md +84 -0
  121. package/examples/spec-workflow/README.md +54 -0
  122. package/examples/spec-workflow/docs/entity_model.md +33 -0
  123. package/examples/spec-workflow/docs/glossary.md +9 -0
  124. package/examples/spec-workflow/docs/requirements.md +10 -0
  125. package/examples/spec-workflow/docs/test_cases/TC-001-submit-expense.md +37 -0
  126. package/examples/spec-workflow/docs/use_cases/UC-001-submit-expense.md +63 -0
  127. package/examples/spec-workflow/docs/use_cases.puml +12 -0
  128. package/examples/spec-workflow/docs/vision.md +21 -0
  129. package/package.json +37 -104
  130. package/plugins/aiwf-angular-jpa/.claude-plugin/plugin.json +11 -0
  131. package/plugins/aiwf-angular-jpa/LICENSE +201 -0
  132. package/plugins/aiwf-angular-jpa/NOTICE +16 -0
  133. package/plugins/aiwf-angular-jpa/README.md +54 -0
  134. package/plugins/aiwf-angular-jpa/UPSTREAM.json +35 -0
  135. package/plugins/aiwf-angular-jpa/agents/uc-coverage.md +263 -0
  136. package/plugins/aiwf-angular-jpa/rules/mcp-servers.md +64 -0
  137. package/plugins/aiwf-angular-jpa/skills/coverage-check/SKILL.md +190 -0
  138. package/plugins/aiwf-angular-jpa/skills/flyway-migration/SKILL.md +119 -0
  139. package/plugins/aiwf-angular-jpa/skills/implement/SKILL.md +528 -0
  140. package/plugins/aiwf-angular-jpa/skills/implement/references/module-layout.md +95 -0
  141. package/plugins/aiwf-angular-jpa/skills/playwright-test/SKILL.md +360 -0
  142. package/plugins/aiwf-angular-jpa/skills/spring-boot-test/SKILL.md +504 -0
  143. package/plugins/aiwf-angular-jpa/skills/vitest-test/SKILL.md +309 -0
  144. package/plugins/aiwf-blazor-dotnet/.claude-plugin/plugin.json +11 -0
  145. package/plugins/aiwf-blazor-dotnet/LICENSE +201 -0
  146. package/plugins/aiwf-blazor-dotnet/NOTICE +16 -0
  147. package/plugins/aiwf-blazor-dotnet/README.md +53 -0
  148. package/plugins/aiwf-blazor-dotnet/UPSTREAM.json +31 -0
  149. package/plugins/aiwf-blazor-dotnet/rules/mcp-servers.md +25 -0
  150. package/plugins/aiwf-blazor-dotnet/skills/bunit-test/SKILL.md +110 -0
  151. package/plugins/aiwf-blazor-dotnet/skills/dotnet-test/SKILL.md +108 -0
  152. package/plugins/aiwf-blazor-dotnet/skills/ef-migration/SKILL.md +43 -0
  153. package/plugins/aiwf-blazor-dotnet/skills/implement/SKILL.md +149 -0
  154. package/plugins/aiwf-blazor-dotnet/skills/playwright-test/SKILL.md +130 -0
  155. package/plugins/aiwf-core/.claude-plugin/plugin.json +11 -0
  156. package/plugins/aiwf-core/LICENSE +201 -0
  157. package/plugins/aiwf-core/NOTICE +20 -0
  158. package/plugins/aiwf-core/README.md +38 -0
  159. package/plugins/aiwf-core/UPSTREAM.json +50 -0
  160. package/plugins/aiwf-core/skills/entity-model/SKILL.md +160 -0
  161. package/plugins/aiwf-core/skills/entity-model/references/REFERENCE.md +36 -0
  162. package/plugins/aiwf-core/skills/requirements/SKILL.md +157 -0
  163. package/plugins/aiwf-core/skills/requirements/references/REFERENCE.md +70 -0
  164. package/plugins/aiwf-core/skills/requirements/references/glossary.md +7 -0
  165. package/plugins/aiwf-core/skills/reverse-engineer/SKILL.md +509 -0
  166. package/plugins/aiwf-core/skills/reverse-engineer/references/stack-signals.md +210 -0
  167. package/plugins/aiwf-core/skills/spec-review/SKILL.md +197 -0
  168. package/plugins/aiwf-core/skills/spec-review/references/lint-codes.md +63 -0
  169. package/plugins/aiwf-core/skills/spec-review/references/review-checklist.md +189 -0
  170. package/plugins/aiwf-core/skills/spec-review/scripts/spec_lint.py +1216 -0
  171. package/plugins/aiwf-core/skills/test-case/SKILL.md +138 -0
  172. package/plugins/aiwf-core/skills/test-case/references/example-process.bpmn +118 -0
  173. package/plugins/aiwf-core/skills/test-case/references/example.md +38 -0
  174. package/plugins/aiwf-core/skills/test-case/references/test-case.md +35 -0
  175. package/plugins/aiwf-core/skills/test-case/scripts/bpmn_paths.py +542 -0
  176. package/plugins/aiwf-core/skills/use-case-diagram/SKILL.md +99 -0
  177. package/plugins/aiwf-core/skills/use-case-spec/SKILL.md +257 -0
  178. package/plugins/aiwf-core/skills/use-case-spec/references/clarify-checklist.md +70 -0
  179. package/plugins/aiwf-core/skills/use-case-spec/references/example.md +88 -0
  180. package/plugins/aiwf-core/skills/use-case-spec/references/format-spec.md +246 -0
  181. package/plugins/aiwf-core/skills/use-case-spec/references/use-case.md +50 -0
  182. package/plugins/aiwf-core/skills/use-case-spec/scripts/validate_use_case.py +941 -0
  183. package/plugins/aiwf-delegate-claude/.claude-plugin/plugin.json +9 -0
  184. package/{src/lib/resources/templates/npm-library/template → plugins/aiwf-delegate-claude}/LICENSE +2 -2
  185. package/plugins/aiwf-delegate-claude/NOTICE +4 -0
  186. package/plugins/aiwf-delegate-claude/README.md +10 -0
  187. package/plugins/aiwf-delegate-claude/plugin.json +13 -0
  188. package/plugins/aiwf-delegate-claude/skills/delegate-claude/LICENSE +21 -0
  189. package/plugins/aiwf-delegate-claude/skills/delegate-claude/NOTICE +4 -0
  190. package/plugins/aiwf-delegate-claude/skills/delegate-claude/SKILL.md +49 -0
  191. package/plugins/aiwf-delegate-claude/skills/delegate-claude/agents/openai.yaml +2 -0
  192. package/plugins/aiwf-delegate-codex/.claude-plugin/plugin.json +9 -0
  193. package/plugins/aiwf-delegate-codex/LICENSE +21 -0
  194. package/plugins/aiwf-delegate-codex/NOTICE +4 -0
  195. package/plugins/aiwf-delegate-codex/README.md +10 -0
  196. package/plugins/aiwf-delegate-codex/plugin.json +13 -0
  197. package/plugins/aiwf-delegate-codex/skills/delegate-codex/LICENSE +21 -0
  198. package/plugins/aiwf-delegate-codex/skills/delegate-codex/NOTICE +4 -0
  199. package/plugins/aiwf-delegate-codex/skills/delegate-codex/SKILL.md +47 -0
  200. package/plugins/aiwf-delegate-codex/skills/delegate-codex/agents/openai.yaml +2 -0
  201. package/plugins/aiwf-nestjs-nextjs/.claude-plugin/plugin.json +11 -0
  202. package/plugins/aiwf-nestjs-nextjs/LICENSE +201 -0
  203. package/plugins/aiwf-nestjs-nextjs/NOTICE +16 -0
  204. package/plugins/aiwf-nestjs-nextjs/README.md +53 -0
  205. package/plugins/aiwf-nestjs-nextjs/UPSTREAM.json +32 -0
  206. package/plugins/aiwf-nestjs-nextjs/rules/mcp-servers.md +59 -0
  207. package/plugins/aiwf-nestjs-nextjs/skills/drizzle-migration/SKILL.md +222 -0
  208. package/plugins/aiwf-nestjs-nextjs/skills/implement/SKILL.md +393 -0
  209. package/plugins/aiwf-nestjs-nextjs/skills/implement/references/project-layout.md +158 -0
  210. package/plugins/aiwf-nestjs-nextjs/skills/nest-test/SKILL.md +300 -0
  211. package/plugins/aiwf-nestjs-nextjs/skills/playwright-test/SKILL.md +245 -0
  212. package/plugins/aiwf-nestjs-nextjs/skills/react-test/SKILL.md +217 -0
  213. package/plugins/aiwf-spec/.claude-plugin/plugin.json +9 -0
  214. package/plugins/aiwf-spec/LICENSE +201 -0
  215. package/plugins/aiwf-spec/NOTICE +20 -0
  216. package/plugins/aiwf-spec/README.md +36 -0
  217. package/plugins/aiwf-spec/skills/sync-docs/SKILL.md +47 -0
  218. package/plugins/aiwf-spec/skills/workflow/SKILL.md +42 -0
  219. package/plugins/aiwf-vaadin-jooq/.claude-plugin/plugin.json +11 -0
  220. package/plugins/aiwf-vaadin-jooq/LICENSE +201 -0
  221. package/plugins/aiwf-vaadin-jooq/NOTICE +16 -0
  222. package/plugins/aiwf-vaadin-jooq/README.md +56 -0
  223. package/plugins/aiwf-vaadin-jooq/UPSTREAM.json +43 -0
  224. package/plugins/aiwf-vaadin-jooq/agents/uc-coverage.md +260 -0
  225. package/plugins/aiwf-vaadin-jooq/rules/mcp-servers.md +44 -0
  226. package/plugins/aiwf-vaadin-jooq/skills/browserless-test/SKILL.md +407 -0
  227. package/plugins/aiwf-vaadin-jooq/skills/browserless-test/references/UC001ManagePersonsTest.java +111 -0
  228. package/plugins/aiwf-vaadin-jooq/skills/coverage-check/SKILL.md +190 -0
  229. package/plugins/aiwf-vaadin-jooq/skills/flyway-migration/SKILL.md +70 -0
  230. package/plugins/aiwf-vaadin-jooq/skills/hilla-test/SKILL.md +350 -0
  231. package/plugins/aiwf-vaadin-jooq/skills/hilla-test/references/UC001ManagePersonsServiceTest.java +81 -0
  232. package/plugins/aiwf-vaadin-jooq/skills/hilla-test/references/UC001ManagePersonsViewTest.tsx +87 -0
  233. package/plugins/aiwf-vaadin-jooq/skills/implement/SKILL.md +196 -0
  234. package/plugins/aiwf-vaadin-jooq/skills/implement-hilla/SKILL.md +216 -0
  235. package/plugins/aiwf-vaadin-jooq/skills/karibu-test/SKILL.md +298 -0
  236. package/plugins/aiwf-vaadin-jooq/skills/karibu-test/references/UC001ManagePersonsTest.java +93 -0
  237. package/plugins/aiwf-vaadin-jooq/skills/playwright-test/SKILL.md +237 -0
  238. package/plugins/aiwf-vaadin-jooq/skills/playwright-test/references/ExampleViewIT.java +143 -0
  239. package/plugins/aiwf-vaadin-jooq/skills/playwright-test/references/TC001CustomerOnboardingIT.java +144 -0
  240. package/plugins/aiwf-vaadin-jooq/skills/playwright-test/references/dramafinder-api.md +190 -0
  241. package/scripts/check-dependencies.js +26 -96
  242. package/scripts/install-spec-skills.mjs +126 -0
  243. package/scripts/validate-spec-plugin.mjs +145 -0
  244. package/src/cli/spec-cli.js +292 -0
  245. package/src/lib/spec-workflow.js +982 -0
  246. package/docs/ADR_MANAGEMENT_GUIDE.ko.md +0 -602
  247. package/docs/ADR_MANAGEMENT_GUIDE.md +0 -602
  248. package/docs/AI-WORKFLOW.ko.md +0 -299
  249. package/docs/AI-WORKFLOW.md +0 -401
  250. package/docs/API_REFERENCE_FULL.ko.md +0 -1135
  251. package/docs/API_REFERENCE_FULL.md +0 -1135
  252. package/docs/ARCHITECTURE.ko.md +0 -314
  253. package/docs/ARCHITECTURE.md +0 -314
  254. package/docs/CLI_USAGE_GUIDE.ko.md +0 -634
  255. package/docs/CLI_USAGE_GUIDE.md +0 -640
  256. package/docs/CODE_CLEANUP_GUIDE.ko.md +0 -415
  257. package/docs/CODE_CLEANUP_GUIDE.md +0 -415
  258. package/docs/COMMANDS_GUIDE.ko.md +0 -1037
  259. package/docs/COMMANDS_GUIDE.md +0 -1037
  260. package/docs/CONTRIBUTING.ko.md +0 -408
  261. package/docs/CONTRIBUTING.md +0 -408
  262. package/docs/DEVELOPMENT_GUIDE.ko.md +0 -440
  263. package/docs/DEVELOPMENT_GUIDE.md +0 -727
  264. package/docs/EXAMPLES.ko.md +0 -695
  265. package/docs/EXAMPLES.md +0 -693
  266. package/docs/GETTING_STARTED.ko.md +0 -219
  267. package/docs/GETTING_STARTED.md +0 -476
  268. package/docs/MODULE_MANAGEMENT_GUIDE.ko.md +0 -289
  269. package/docs/MODULE_MANAGEMENT_GUIDE.md +0 -289
  270. package/docs/PERFORMANCE_ARCHITECTURE.md +0 -494
  271. package/docs/PERFORMANCE_GUIDELINES.ko.md +0 -388
  272. package/docs/PERFORMANCE_GUIDELINES.md +0 -553
  273. package/docs/PRD.ko.md +0 -148
  274. package/docs/PRD.md +0 -150
  275. package/docs/ROADMAP_v0.4.0.md +0 -286
  276. package/docs/STATE_MANAGEMENT_GUIDE.ko.md +0 -278
  277. package/docs/STATE_MANAGEMENT_GUIDE.md +0 -278
  278. package/docs/TROUBLESHOOTING.ko.md +0 -366
  279. package/docs/TROUBLESHOOTING.md +0 -722
  280. package/docs/VALIDATOR_API.ko.md +0 -324
  281. package/docs/VALIDATOR_API.md +0 -324
  282. package/docs/YOLO_SYSTEM_GUIDE.ko.md +0 -542
  283. package/docs/YOLO_SYSTEM_GUIDE.md +0 -542
  284. package/docs/designs/AI_PERSONA_SYSTEM_DESIGN.md +0 -516
  285. package/docs/designs/API_DOCUMENTATION.md +0 -932
  286. package/docs/designs/API_REFERENCE.md +0 -979
  287. package/docs/designs/Enhanced_Installation_Flow_Design.md +0 -498
  288. package/docs/designs/aiwf-metadata-system-prd.md +0 -127
  289. package/docs/designs/offline-template-cache.md +0 -323
  290. package/docs/designs/persona-aware-compression.md +0 -168
  291. package/docs/guides/ai-personas-guide-ko.md +0 -239
  292. package/docs/guides/ai-personas-guide.md +0 -239
  293. package/docs/guides/checkpoint-system-guide-ko.md +0 -356
  294. package/docs/guides/checkpoint-system-guide.md +0 -356
  295. package/docs/guides/context-compression-guide-ko.md +0 -313
  296. package/docs/guides/context-compression-guide.md +0 -313
  297. package/docs/guides/independent-sprint-guide-ko.md +0 -321
  298. package/docs/guides/independent-sprint-guide.md +0 -321
  299. package/rules/global/aiwf-code-style-guide.md +0 -30
  300. package/rules/global/aiwf-coding-principles.md +0 -33
  301. package/rules/global/aiwf-development-process.md +0 -41
  302. package/rules/global/aiwf-global-rules.md +0 -84
  303. package/rules/manual/aiwf-generate-plan-docs.md +0 -280
  304. package/scripts/run-integration-tests.js +0 -317
  305. package/scripts/update-file-lists.js +0 -267
  306. package/scripts/validate-commands.js +0 -254
  307. package/src/DEPENDENCY_MAP.md +0 -90
  308. package/src/cli/cache-cli.js +0 -459
  309. package/src/cli/checkpoint-cli.js +0 -417
  310. package/src/cli/index.js +0 -481
  311. package/src/cli/language-cli.js +0 -286
  312. package/src/cli/sprint-cli.js +0 -287
  313. package/src/commands/ai-tool.js +0 -383
  314. package/src/commands/compress.js +0 -60
  315. package/src/commands/create-project.js +0 -160
  316. package/src/commands/evaluate.js +0 -459
  317. package/src/commands/persona.js +0 -309
  318. package/src/commands/sprint-independent.js +0 -393
  319. package/src/commands/sprint-task.js +0 -262
  320. package/src/commands/state.js +0 -1164
  321. package/src/commands/token.js +0 -312
  322. package/src/commands/yolo-config.js +0 -502
  323. package/src/config/file-lists.js +0 -147
  324. package/src/config/yolo-config-template.yaml +0 -168
  325. package/src/lib/ai-persona-manager.js +0 -711
  326. package/src/lib/backup-manager.js +0 -271
  327. package/src/lib/cache-system.js +0 -332
  328. package/src/lib/context-engine.js +0 -568
  329. package/src/lib/file-downloader.js +0 -304
  330. package/src/lib/github-integration.js +0 -402
  331. package/src/lib/installer.js +0 -1066
  332. package/src/lib/memory-profiler.js +0 -471
  333. package/src/lib/metrics-collector.js +0 -885
  334. package/src/lib/offline-detector.js +0 -386
  335. package/src/lib/resource-loader-enhanced.js +0 -399
  336. package/src/lib/resource-loader.js +0 -250
  337. package/src/lib/resources/commands/ai-persona.js +0 -602
  338. package/src/lib/resources/commands/compress-context.js +0 -389
  339. package/src/lib/resources/commands/evaluate.js +0 -246
  340. package/src/lib/resources/commands/persona-context-apply.js +0 -562
  341. package/src/lib/resources/commands/token-tracking.js +0 -443
  342. package/src/lib/resources/config/commit-patterns.js +0 -103
  343. package/src/lib/resources/config/language.json +0 -6
  344. package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
  345. package/src/lib/resources/personas/analyst.json +0 -44
  346. package/src/lib/resources/personas/architect/best_practices.md +0 -136
  347. package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
  348. package/src/lib/resources/personas/architect.json +0 -44
  349. package/src/lib/resources/personas/backend/best_practices.md +0 -766
  350. package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
  351. package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
  352. package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
  353. package/src/lib/resources/personas/developer.json +0 -44
  354. package/src/lib/resources/personas/developer.md +0 -37
  355. package/src/lib/resources/personas/evaluation_criteria.json +0 -137
  356. package/src/lib/resources/personas/frontend/best_practices.md +0 -445
  357. package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
  358. package/src/lib/resources/personas/persona-index.json +0 -31
  359. package/src/lib/resources/personas/reviewer.json +0 -44
  360. package/src/lib/resources/personas/security/best_practices.md +0 -307
  361. package/src/lib/resources/personas/security/knowledge_base.md +0 -498
  362. package/src/lib/resources/personas/tester.json +0 -44
  363. package/src/lib/resources/templates/README.md +0 -78
  364. package/src/lib/resources/templates/api-server/config.json +0 -64
  365. package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
  366. package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
  367. package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
  368. package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
  369. package/src/lib/resources/templates/api-server/template/.env.example +0 -29
  370. package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
  371. package/src/lib/resources/templates/api-server/template/README.md +0 -171
  372. package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
  373. package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
  374. package/src/lib/resources/templates/api-server/template/package.json +0 -61
  375. package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
  376. package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
  377. package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
  378. package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
  379. package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
  380. package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
  381. package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
  382. package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
  383. package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
  384. package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
  385. package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
  386. package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
  387. package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
  388. package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
  389. package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
  390. package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
  391. package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
  392. package/src/lib/resources/templates/npm-library/config.json +0 -61
  393. package/src/lib/resources/templates/npm-library/template/README.md +0 -201
  394. package/src/lib/resources/templates/npm-library/template/package.json +0 -78
  395. package/src/lib/resources/templates/web-app/config.json +0 -53
  396. package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
  397. package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
  398. package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
  399. package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
  400. package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
  401. package/src/lib/resources/templates/web-app/template/README.md +0 -151
  402. package/src/lib/resources/templates/web-app/template/index.html +0 -14
  403. package/src/lib/resources/templates/web-app/template/package.json +0 -44
  404. package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
  405. package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
  406. package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
  407. package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
  408. package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
  409. package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
  410. package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
  411. package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
  412. package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
  413. package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
  414. package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
  415. package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
  416. package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
  417. package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
  418. package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
  419. package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
  420. package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
  421. package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
  422. package/src/lib/resources/utils/background-monitor.js +0 -223
  423. package/src/lib/resources/utils/compression-metrics.js +0 -1031
  424. package/src/lib/resources/utils/compression-strategies.js +0 -557
  425. package/src/lib/resources/utils/content-normalizer.js +0 -455
  426. package/src/lib/resources/utils/context-compressor.js +0 -583
  427. package/src/lib/resources/utils/context-rule-parser.js +0 -180
  428. package/src/lib/resources/utils/context-token-monitor.js +0 -463
  429. package/src/lib/resources/utils/context-update-manager.js +0 -502
  430. package/src/lib/resources/utils/git-utils.js +0 -220
  431. package/src/lib/resources/utils/importance-classifier.js +0 -645
  432. package/src/lib/resources/utils/information-filter.js +0 -710
  433. package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
  434. package/src/lib/resources/utils/prompt-injector.js +0 -242
  435. package/src/lib/resources/utils/simplified-evaluator.js +0 -119
  436. package/src/lib/resources/utils/text-summarizer.js +0 -492
  437. package/src/lib/resources/utils/token-counter.js +0 -177
  438. package/src/lib/resources/utils/token-monitor.js +0 -484
  439. package/src/lib/resources/utils/token-reporter.js +0 -452
  440. package/src/lib/resources/utils/token-storage.js +0 -433
  441. package/src/lib/resources/utils/token-tracker.js +0 -283
  442. package/src/lib/rollback-manager.js +0 -418
  443. package/src/lib/state/priority-calculator.js +0 -217
  444. package/src/lib/state/state-index.js +0 -155
  445. package/src/lib/state/task-scanner.js +0 -328
  446. package/src/lib/task-analyzer.js +0 -599
  447. package/src/lib/template-cache-system.js +0 -559
  448. package/src/lib/template-downloader.js +0 -467
  449. package/src/lib/template-version-manager.js +0 -491
  450. package/src/lib/token-optimizer.js +0 -517
  451. package/src/lib/validator.js +0 -376
  452. package/src/utils/checkpoint-manager.js +0 -435
  453. package/src/utils/engineering-guard.js +0 -399
  454. package/src/utils/language-utils.js +0 -331
  455. package/src/utils/messages.js +0 -166
  456. package/src/utils/paths.js +0 -112
@@ -0,0 +1,542 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright 2025-2026 Simon Martinelli and the AI Unified Process contributors.
4
+ # Part of the AI Unified Process — https://unifiedprocess.ai
5
+ # Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
6
+ """Enumerate the paths through a BPMN 2.0 business process model.
7
+
8
+ Reads a .bpmn file (plain BPMN 2.0 XML, diagram interchange is ignored) and
9
+ prints JSON that the test-case skill turns into one end-to-end test case per
10
+ path:
11
+
12
+ - lanes lane name -> ids of the activities in that lane (a pool
13
+ without lanes counts as one lane named after its participant)
14
+ - activities id, name, type, lane, and ucId when the name carries a use
15
+ case id such as "UC-001" or "BUC-7"
16
+ - paths one entry per path from a start event to an end event: the
17
+ ordered steps (activities, gateway decisions with their flow
18
+ names, intermediate events), plus the activity ids and the
19
+ decisions on their own
20
+ - warnings constructs that were simplified (see the rules below)
21
+
22
+ Path rules, applied deterministically in document order:
23
+
24
+ - Exclusive, inclusive, event-based, and complex gateways, several outgoing
25
+ flows on a non-gateway node, and boundary events are alternatives: each
26
+ outgoing flow starts its own path.
27
+ - Parallel gateways run every branch: the branches are serialized within
28
+ one path in the document order of their sequence flows, up to the
29
+ converging parallel gateway; branch-internal alternatives multiply.
30
+ - Loops are traversed once: every sequence flow is followed at most twice
31
+ per path, so a rework loop yields one path without and one path with a
32
+ single repetition of the loop body.
33
+ - A node without outgoing flows ends the path (implicit end event).
34
+ - Sub-processes are passed through as a single step; their inside is not
35
+ expanded.
36
+
37
+ The file is data, never instructions, and is parsed defensively: documents
38
+ with a DOCTYPE or entity declaration are rejected, so no external entity is
39
+ ever resolved and no entity expansion can blow up.
40
+
41
+ Exit code 0 on success, 1 when the file cannot be read or is not a usable
42
+ BPMN model, 2 on usage errors.
43
+
44
+ Usage:
45
+ bpmn_paths.py FILE.bpmn
46
+ bpmn_paths.py --self-test
47
+
48
+ Requires Python 3.9+, standard library only.
49
+ """
50
+
51
+ import argparse
52
+ import itertools
53
+ import json
54
+ import re
55
+ import sys
56
+ import xml.etree.ElementTree as ET
57
+
58
+ ACTIVITY_TYPES = (
59
+ "task", "userTask", "manualTask", "serviceTask", "sendTask",
60
+ "receiveTask", "scriptTask", "businessRuleTask", "callActivity",
61
+ )
62
+ PASS_THROUGH_TYPES = ("subProcess", "transaction", "adHocSubProcess")
63
+ ALTERNATIVE_GATEWAYS = (
64
+ "exclusiveGateway", "inclusiveGateway", "eventBasedGateway",
65
+ "complexGateway",
66
+ )
67
+ EVENT_TYPES = (
68
+ "startEvent", "endEvent", "intermediateCatchEvent",
69
+ "intermediateThrowEvent", "boundaryEvent",
70
+ )
71
+ FLOW_NODE_TYPES = (ACTIVITY_TYPES + PASS_THROUGH_TYPES + ALTERNATIVE_GATEWAYS
72
+ + EVENT_TYPES + ("parallelGateway",))
73
+
74
+ UC_ID = re.compile(r"(?<![A-Za-z0-9])([SB]?UC-[A-Za-z0-9_-]+)")
75
+ FORBIDDEN_DECLARATION = re.compile(rb"<!\s*(DOCTYPE|ENTITY)", re.IGNORECASE)
76
+ MAX_PATHS = 500
77
+
78
+
79
+ class BpmnError(Exception):
80
+ pass
81
+
82
+
83
+ def local(tag):
84
+ return tag.rsplit("}", 1)[-1]
85
+
86
+
87
+ def clean(text):
88
+ return " ".join((text or "").split())
89
+
90
+
91
+ def uc_id(name):
92
+ match = UC_ID.search(name)
93
+ return match.group(1).rstrip("-_") if match else None
94
+
95
+
96
+ # ---------------------------------------------------------------------------
97
+ # Parsing
98
+ # ---------------------------------------------------------------------------
99
+
100
+ def parse_xml(data):
101
+ if FORBIDDEN_DECLARATION.search(data):
102
+ raise BpmnError("DOCTYPE or ENTITY declarations are not allowed "
103
+ "in a BPMN file")
104
+ try:
105
+ root = ET.fromstring(data)
106
+ except ET.ParseError as exc:
107
+ raise BpmnError("not well-formed XML: " + str(exc))
108
+ if local(root.tag) != "definitions":
109
+ raise BpmnError("root element is <" + local(root.tag)
110
+ + ">, expected BPMN <definitions>")
111
+ return root
112
+
113
+
114
+ class Process:
115
+ def __init__(self, element, pool_name):
116
+ self.id = element.get("id", "")
117
+ self.nodes = {} # id -> (type, name), direct children only
118
+ self.order = [] # node ids in document order
119
+ self.flows = [] # (id, name, source, target) in document order
120
+ self.boundaries = {} # activity id -> [boundary event ids]
121
+ self.lane_of = {} # node id -> lane name
122
+ for child in element:
123
+ kind = local(child.tag)
124
+ node_id = child.get("id")
125
+ if kind in FLOW_NODE_TYPES and node_id:
126
+ self.nodes[node_id] = (kind, clean(child.get("name")))
127
+ self.order.append(node_id)
128
+ if kind == "boundaryEvent" and child.get("attachedToRef"):
129
+ self.boundaries.setdefault(
130
+ child.get("attachedToRef"), []).append(node_id)
131
+ elif kind == "sequenceFlow":
132
+ self.flows.append((child.get("id", ""),
133
+ clean(child.get("name")),
134
+ child.get("sourceRef"),
135
+ child.get("targetRef")))
136
+ elif kind == "laneSet":
137
+ self._read_lanes(child)
138
+ if not self.lane_of and pool_name:
139
+ for node_id in self.order:
140
+ self.lane_of[node_id] = pool_name
141
+ self.outgoing = {}
142
+ self.incoming = {}
143
+ for flow in self.flows:
144
+ if flow[2] in self.nodes and flow[3] in self.nodes:
145
+ self.outgoing.setdefault(flow[2], []).append(flow)
146
+ self.incoming.setdefault(flow[3], []).append(flow)
147
+
148
+ def _read_lanes(self, lane_set):
149
+ # Nested lanes: the innermost lane wins because it is visited last.
150
+ for lane in lane_set:
151
+ if local(lane.tag) != "lane":
152
+ continue
153
+ name = clean(lane.get("name")) or lane.get("id", "")
154
+ for ref in lane:
155
+ if local(ref.tag) == "flowNodeRef" and ref.text:
156
+ self.lane_of[ref.text.strip()] = name
157
+ elif local(ref.tag) == "childLaneSet":
158
+ self._read_lanes(ref)
159
+
160
+ def kind(self, node_id):
161
+ return self.nodes[node_id][0]
162
+
163
+ def name(self, node_id):
164
+ return self.nodes[node_id][1]
165
+
166
+
167
+ # ---------------------------------------------------------------------------
168
+ # Path enumeration
169
+ # ---------------------------------------------------------------------------
170
+
171
+ class Walker:
172
+ """Enumerates (steps, terminal, followed flows) for one process.
173
+
174
+ terminal is ("end", node id) or ("join", parallel gateway id); a join
175
+ terminal is only produced inside a parallel branch and is consumed by
176
+ the split that started the branch.
177
+ """
178
+
179
+ def __init__(self, process, warnings):
180
+ self.p = process
181
+ self.warnings = warnings
182
+ self.truncated = False
183
+
184
+ def warn(self, message):
185
+ if message not in self.warnings:
186
+ self.warnings.append(message)
187
+
188
+ def step(self, node_id):
189
+ kind = self.p.kind(node_id)
190
+ entry = {"id": node_id, "name": self.p.name(node_id), "type": kind}
191
+ if kind in ACTIVITY_TYPES:
192
+ entry["kind"] = "activity"
193
+ elif kind in PASS_THROUGH_TYPES:
194
+ entry["kind"] = "subprocess"
195
+ else:
196
+ entry["kind"] = "event"
197
+ return entry
198
+
199
+ def choices(self, node_id):
200
+ """Outgoing alternatives: sequence flows plus attached boundary events."""
201
+ result = [(flow, flow[3]) for flow in self.p.outgoing.get(node_id, [])]
202
+ for boundary in self.p.boundaries.get(node_id, []):
203
+ result.append((None, boundary))
204
+ return result
205
+
206
+ def walk(self, node_id, used, in_split):
207
+ kind = self.p.kind(node_id)
208
+
209
+ if kind == "parallelGateway":
210
+ if len(self.p.incoming.get(node_id, [])) > 1 and in_split:
211
+ return [([], ("join", node_id), used)]
212
+ outgoing = self.p.outgoing.get(node_id, [])
213
+ if len(outgoing) > 1:
214
+ return self.split(node_id, outgoing, used, in_split)
215
+ return self.follow(node_id, [], outgoing, used, in_split, None)
216
+
217
+ if kind in ALTERNATIVE_GATEWAYS:
218
+ return self.follow(node_id, [], self.p.outgoing.get(node_id, []),
219
+ used, in_split, node_id)
220
+
221
+ prefix = [self.step(node_id)]
222
+ if kind == "endEvent":
223
+ return [(prefix, ("end", node_id), used)]
224
+ if kind in PASS_THROUGH_TYPES:
225
+ self.warn("sub-process " + node_id
226
+ + " is passed through as one step; its inside is "
227
+ "not expanded")
228
+ choices = self.choices(node_id)
229
+ if not choices:
230
+ self.warn("node " + node_id + " has no outgoing flow and ends "
231
+ "the path as an implicit end event")
232
+ return [(prefix, ("end", node_id), used)]
233
+ results = []
234
+ for flow, target in choices:
235
+ if flow is None:
236
+ decision = {"kind": "decision", "gateway": node_id,
237
+ "gatewayName": self.p.name(node_id),
238
+ "flow": None,
239
+ "flowName": "boundary: "
240
+ + (self.p.name(target) or target),
241
+ "target": target}
242
+ for steps, terminal, u in self.walk(target, used, in_split):
243
+ results.append((prefix + [decision] + steps, terminal, u))
244
+ else:
245
+ decision_at = node_id if len(choices) > 1 else None
246
+ results.extend(self.follow(node_id, prefix, [flow], used,
247
+ in_split, decision_at))
248
+ self.check_limit(results)
249
+ return results
250
+
251
+ def follow(self, node_id, prefix, flows, used, in_split, decision_at):
252
+ """Continue along each flow; records a decision when decision_at is set."""
253
+ if not flows:
254
+ self.warn("node " + node_id + " has no outgoing flow and ends "
255
+ "the path")
256
+ return [(prefix, ("end", node_id), used)]
257
+ alternatives = decision_at is not None and len(flows) > 1
258
+ if decision_at is not None and not alternatives and \
259
+ self.p.kind(node_id) in ALTERNATIVE_GATEWAYS:
260
+ decision_at = None # converging gateway: no decision
261
+ results = []
262
+ for flow in flows:
263
+ flow_id, flow_name, _, target = flow
264
+ if used.count(flow_id) >= 2:
265
+ continue # loop already traversed once
266
+ head = list(prefix)
267
+ if decision_at is not None:
268
+ head.append({"kind": "decision", "gateway": decision_at,
269
+ "gatewayName": self.p.name(decision_at),
270
+ "flow": flow_id, "flowName": flow_name,
271
+ "target": target})
272
+ for steps, terminal, u in self.walk(target, used + (flow_id,),
273
+ in_split):
274
+ results.append((head + steps, terminal, u))
275
+ self.check_limit(results)
276
+ return results
277
+
278
+ def split(self, node_id, outgoing, used, in_split):
279
+ branches = []
280
+ for flow in outgoing:
281
+ if used.count(flow[0]) >= 2:
282
+ continue
283
+ branches.append(self.walk(flow[3], used + (flow[0],),
284
+ in_split + 1))
285
+ branches = [b for b in branches if b]
286
+ if not branches:
287
+ return []
288
+ results = []
289
+ for combination in itertools.product(*branches):
290
+ steps = []
291
+ merged = used
292
+ joins = []
293
+ last_end = None
294
+ for branch_steps, terminal, u in combination:
295
+ steps.extend(branch_steps)
296
+ merged += u[len(used):]
297
+ if terminal[0] == "join":
298
+ if terminal[1] not in joins:
299
+ joins.append(terminal[1])
300
+ else:
301
+ last_end = terminal
302
+ if not joins:
303
+ results.append((steps, last_end, merged))
304
+ continue
305
+ if len(joins) > 1:
306
+ self.warn("parallel gateway " + node_id + " converges in "
307
+ "several gateways; continuing after " + joins[0])
308
+ join = joins[0]
309
+ for rest, terminal, u in self.follow(
310
+ join, [], self.p.outgoing.get(join, []), merged,
311
+ in_split, None):
312
+ results.append((steps + rest, terminal, u))
313
+ self.check_limit(results)
314
+ return results
315
+
316
+ def check_limit(self, results):
317
+ if len(results) > MAX_PATHS:
318
+ del results[MAX_PATHS:]
319
+ if not self.truncated:
320
+ self.truncated = True
321
+ self.warn("more than %d paths; the rest were dropped"
322
+ % MAX_PATHS)
323
+
324
+
325
+ def analyze(data):
326
+ root = parse_xml(data)
327
+ pools = {}
328
+ for element in root.iter():
329
+ if local(element.tag) == "participant" and element.get("processRef"):
330
+ pools[element.get("processRef")] = clean(element.get("name"))
331
+
332
+ processes = [Process(el, pools.get(el.get("id"))) for el in root
333
+ if local(el.tag) == "process"]
334
+ if not processes:
335
+ raise BpmnError("the model contains no <process>")
336
+
337
+ warnings = []
338
+ lanes = {}
339
+ activities = []
340
+ paths = []
341
+ for process in processes:
342
+ for node_id in process.order:
343
+ kind = process.kind(node_id)
344
+ if kind not in ACTIVITY_TYPES:
345
+ continue
346
+ name = process.name(node_id)
347
+ lane = process.lane_of.get(node_id)
348
+ activity = {"id": node_id, "name": name, "type": kind,
349
+ "lane": lane, "process": process.id}
350
+ if uc_id(name):
351
+ activity["ucId"] = uc_id(name)
352
+ if not name:
353
+ warnings.append("activity " + node_id + " has no name")
354
+ activities.append(activity)
355
+ if lane:
356
+ lanes.setdefault(lane, []).append(node_id)
357
+
358
+ starts = [n for n in process.order
359
+ if process.kind(n) == "startEvent"
360
+ and not process.incoming.get(n)]
361
+ if not starts:
362
+ warnings.append("process " + process.id + " has no start event")
363
+ walker = Walker(process, warnings)
364
+ for start in starts:
365
+ found = walker.walk(start, (), 0)
366
+ if not found:
367
+ warnings.append("no complete path from start event " + start)
368
+ for steps, terminal, _ in found:
369
+ if len(paths) >= MAX_PATHS:
370
+ break
371
+ paths.append(make_path(len(paths) + 1, process, start,
372
+ terminal, steps))
373
+
374
+ return {"lanes": lanes, "activities": activities, "paths": paths,
375
+ "warnings": warnings}
376
+
377
+
378
+ def make_path(number, process, start, terminal, steps):
379
+ end = terminal[1] if terminal else None
380
+ return {
381
+ "id": "P%d" % number,
382
+ "process": process.id,
383
+ "start": start,
384
+ "startName": process.name(start),
385
+ "end": end,
386
+ "endName": process.name(end) if end else "",
387
+ "activities": [s["id"] for s in steps if s["kind"] == "activity"],
388
+ "decisions": [{k: v for k, v in s.items() if k != "kind"}
389
+ for s in steps if s["kind"] == "decision"],
390
+ "steps": steps,
391
+ }
392
+
393
+
394
+ # ---------------------------------------------------------------------------
395
+ # Self-test
396
+ # ---------------------------------------------------------------------------
397
+
398
+ NS = ('xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" '
399
+ 'id="defs" targetNamespace="http://example.com/bpmn"')
400
+
401
+ EXCLUSIVE_WITH_LANES = """<?xml version="1.0" encoding="UTF-8"?>
402
+ <definitions %s>
403
+ <collaboration id="c"><participant id="pool" name="Shop" processRef="p"/></collaboration>
404
+ <process id="p">
405
+ <laneSet id="ls">
406
+ <lane id="l1" name="Customer"><flowNodeRef>s</flowNodeRef><flowNodeRef>a</flowNodeRef></lane>
407
+ <lane id="l2" name="Clerk"><flowNodeRef>g</flowNodeRef><flowNodeRef>b</flowNodeRef>
408
+ <flowNodeRef>c</flowNodeRef><flowNodeRef>e1</flowNodeRef><flowNodeRef>e2</flowNodeRef></lane>
409
+ </laneSet>
410
+ <startEvent id="s" name="Order wanted"/>
411
+ <userTask id="a" name="UC-001 Place&#10;Order"/>
412
+ <exclusiveGateway id="g" name="In stock?"/>
413
+ <serviceTask id="b" name="Ship Order (UC-002)"/>
414
+ <task id="c" name="Cancel Order"/>
415
+ <endEvent id="e1" name="Shipped"/>
416
+ <endEvent id="e2" name="Cancelled"/>
417
+ <sequenceFlow id="f1" sourceRef="s" targetRef="a"/>
418
+ <sequenceFlow id="f2" sourceRef="a" targetRef="g"/>
419
+ <sequenceFlow id="f3" name="yes" sourceRef="g" targetRef="b"/>
420
+ <sequenceFlow id="f4" name="no" sourceRef="g" targetRef="c"/>
421
+ <sequenceFlow id="f5" sourceRef="b" targetRef="e1"/>
422
+ <sequenceFlow id="f6" sourceRef="c" targetRef="e2"/>
423
+ </process>
424
+ </definitions>
425
+ """ % NS
426
+
427
+ PARALLEL_AND_LOOP = """<?xml version="1.0" encoding="UTF-8"?>
428
+ <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" id="d">
429
+ <bpmn:process id="p">
430
+ <bpmn:startEvent id="s"/>
431
+ <bpmn:parallelGateway id="fork"/>
432
+ <bpmn:task id="a" name="Pack"/>
433
+ <bpmn:task id="b" name="Invoice"/>
434
+ <bpmn:parallelGateway id="join"/>
435
+ <bpmn:task id="r" name="Review"/>
436
+ <bpmn:exclusiveGateway id="ok" name="Approved?"/>
437
+ <bpmn:task id="fix" name="Rework"/>
438
+ <bpmn:endEvent id="e"/>
439
+ <bpmn:sequenceFlow id="f1" sourceRef="s" targetRef="fork"/>
440
+ <bpmn:sequenceFlow id="f2" sourceRef="fork" targetRef="a"/>
441
+ <bpmn:sequenceFlow id="f3" sourceRef="fork" targetRef="b"/>
442
+ <bpmn:sequenceFlow id="f4" sourceRef="a" targetRef="join"/>
443
+ <bpmn:sequenceFlow id="f5" sourceRef="b" targetRef="join"/>
444
+ <bpmn:sequenceFlow id="f6" sourceRef="join" targetRef="r"/>
445
+ <bpmn:sequenceFlow id="f7" sourceRef="r" targetRef="ok"/>
446
+ <bpmn:sequenceFlow id="f8" name="yes" sourceRef="ok" targetRef="e"/>
447
+ <bpmn:sequenceFlow id="f9" name="no" sourceRef="ok" targetRef="fix"/>
448
+ <bpmn:sequenceFlow id="f10" sourceRef="fix" targetRef="r"/>
449
+ </bpmn:process>
450
+ </bpmn:definitions>
451
+ """
452
+
453
+ XXE = """<?xml version="1.0"?>
454
+ <!DOCTYPE definitions [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
455
+ <definitions %s><process id="p"><task id="t" name="&xxe;"/></process></definitions>
456
+ """ % NS
457
+
458
+
459
+ def self_test():
460
+ failures = []
461
+
462
+ def check(name, condition):
463
+ if not condition:
464
+ failures.append(name)
465
+
466
+ result = analyze(EXCLUSIVE_WITH_LANES.encode("utf-8"))
467
+ check("exclusive: two paths", len(result["paths"]) == 2)
468
+ check("exclusive: path activities",
469
+ [p["activities"] for p in result["paths"]] == [["a", "b"],
470
+ ["a", "c"]])
471
+ check("exclusive: flow names",
472
+ [p["decisions"][0]["flowName"] for p in result["paths"]]
473
+ == ["yes", "no"])
474
+ check("exclusive: lanes",
475
+ result["lanes"] == {"Customer": ["a"], "Clerk": ["b", "c"]})
476
+ ucs = {a["id"]: a.get("ucId") for a in result["activities"]}
477
+ check("exclusive: uc ids", ucs == {"a": "UC-001", "b": "UC-002",
478
+ "c": None})
479
+ check("exclusive: name whitespace normalized",
480
+ result["activities"][0]["name"] == "UC-001 Place Order")
481
+ check("exclusive: no warnings", result["warnings"] == [])
482
+
483
+ result = analyze(PARALLEL_AND_LOOP.encode("utf-8"))
484
+ check("parallel+loop: activity sequences",
485
+ [p["activities"] for p in result["paths"]]
486
+ == [["a", "b", "r"], ["a", "b", "r", "fix", "r"]])
487
+ check("parallel+loop: rework decision recorded",
488
+ [d["flowName"] for d in result["paths"][1]["decisions"]]
489
+ == ["no", "yes"])
490
+
491
+ try:
492
+ analyze(XXE.encode("utf-8"))
493
+ failures.append("xxe: DOCTYPE was accepted")
494
+ except BpmnError:
495
+ pass
496
+ try:
497
+ analyze(b"<html/>")
498
+ failures.append("non-bpmn: accepted")
499
+ except BpmnError:
500
+ pass
501
+
502
+ if failures:
503
+ for failure in failures:
504
+ print("SELF-TEST FAIL: " + failure)
505
+ return 1
506
+ print("self-test passed")
507
+ return 0
508
+
509
+
510
+ # ---------------------------------------------------------------------------
511
+ # CLI
512
+ # ---------------------------------------------------------------------------
513
+
514
+ def main(argv):
515
+ parser = argparse.ArgumentParser(
516
+ description="Enumerate the paths through a BPMN 2.0 process model.")
517
+ parser.add_argument("file", nargs="?", help=".bpmn file to analyze")
518
+ parser.add_argument("--self-test", action="store_true",
519
+ help="run the built-in fixtures and exit")
520
+ args = parser.parse_args(argv)
521
+
522
+ if args.self_test:
523
+ return self_test()
524
+ if not args.file:
525
+ parser.print_usage()
526
+ return 2
527
+ try:
528
+ with open(args.file, "rb") as handle:
529
+ result = analyze(handle.read())
530
+ except OSError as exc:
531
+ print(args.file + ": ERROR IO: " + str(exc), file=sys.stderr)
532
+ return 1
533
+ except BpmnError as exc:
534
+ print(args.file + ": ERROR: " + str(exc), file=sys.stderr)
535
+ return 1
536
+ result = dict({"file": args.file}, **result)
537
+ print(json.dumps(result, indent=2, ensure_ascii=False))
538
+ return 0
539
+
540
+
541
+ if __name__ == "__main__":
542
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: use-case-diagram
3
+ description: >
4
+ Creates or updates PlantUML use case diagrams defining actors, use cases,
5
+ and their relationships from requirements. Use when the user asks to
6
+ "create a use case diagram", "draw a UML diagram", "map actors to use cases",
7
+ "generate a .puml file", or mentions PlantUML, use case overview, actor
8
+ diagram, or system use cases.
9
+ ---
10
+
11
+ <!--
12
+ Copyright 2025-2026 Simon Martinelli and the AI Unified Process contributors.
13
+ Part of the AI Unified Process — https://unifiedprocess.ai
14
+ Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
15
+ -->
16
+
17
+ # Use Case Diagram
18
+
19
+ ## Instructions
20
+
21
+ Create or update the PlantUML use case diagram at `docs/use_cases.puml` based on `docs/requirements.md`.
22
+
23
+ ## DO NOT
24
+
25
+ - Create diagrams without reading the requirements first
26
+ - Use non-standard PlantUML syntax
27
+ - Include implementation details in use case names
28
+ - Model technical steps such as validating, loading, or persisting data as separate use cases (see "Goal level")
29
+
30
+ ## Template
31
+
32
+ ```plantuml
33
+ @startuml Use Cases Overview
34
+ left to right direction
35
+
36
+ actor "User" as user
37
+ actor "Administrator" as admin
38
+
39
+ rectangle "System Name" {
40
+ usecase "UC-001\nDescription" as UC001
41
+ usecase "UC-002\nDescription" as UC002
42
+ usecase "UC-003\nDescription" as UC003
43
+ }
44
+
45
+ admin --> UC001
46
+ user --> UC002
47
+ user --> UC003
48
+
49
+ @enduml
50
+ ```
51
+
52
+ ## Goal level
53
+
54
+ Every use case in the diagram is a **user goal** — what Cockburn calls the sea level: one actor, one sitting, a
55
+ result the primary actor walks away with. Test each use case with one question:
56
+
57
+ > Is this use case a complete goal that the primary actor would recognize as valuable?
58
+
59
+ - **Too low (subfunction):** a step of a larger goal, often a technical one — "Validate METAR", "Load NOTAM",
60
+ "Persist Result". No dispatcher sits down to validate a METAR; they want to know whether an airport is suitable.
61
+ Fold such steps into the user goal they serve ("Determine Airport Suitability"), where they become steps of its
62
+ main success scenario. Keep a subfunction as its own use case only when several user goals share it, and then draw
63
+ it with `<<include>>` from each of them.
64
+ - **Too high (summary):** a whole area of work that spans many sittings — "Manage Flight Operations". Split it into
65
+ the user goals it is made of. A use case is a summary, too, when its flow hands the work over to another role,
66
+ waits for an outside event or a deadline, or runs branches in parallel for different actors — "Process Insurance
67
+ Claim" with a clerk, an assessor, and a payout after approval. Each role's part is a user goal of its own; the
68
+ flow that connects them is a business process, modeled in BPMN in `docs/processes/`, whose activities are those
69
+ use cases and from which `/test-case` derives the test cases. Do not describe the process inside a use case or
70
+ attach a process model to it.
71
+
72
+ A functional requirement that describes a step rather than a goal traces to the user goal use case that contains
73
+ the step.
74
+
75
+ ## Conventions
76
+
77
+ - Each use case has a unique id and a description
78
+ - Use Case ID: UC-{3-digit} (UC-001, UC-002, ...)
79
+ - Each use case should trace to at least one functional requirement
80
+ - Secondary actors (supporting roles and external systems such as a payment or weather service) are drawn as
81
+ actors too and connected to the use cases they support; they appear as `**Secondary Actors:**` in the use case
82
+ specification
83
+ - Add notes sparingly, only where relationships need clarification
84
+
85
+ ## Workflow
86
+
87
+ 1. Read the requirements at `docs/requirements.md`
88
+ 2. Read existing diagram at `docs/use_cases.puml` (if exists)
89
+ 3. Identify actors and use cases from requirements
90
+ 4. Check every use case against the question in "Goal level": fold subfunctions into the user goal they serve,
91
+ split summary goals, and tell the user which use cases you merged or split and why
92
+ 5. Create/update the PlantUML use case diagram
93
+ 6. Validate the diagram:
94
+ - Each use case is a user goal (see "Goal level"); a subfunction appears only as an `<<include>>` shared by
95
+ several use cases
96
+ - Each use case traces to at least one functional requirement in `docs/requirements.md`
97
+ - All actors are connected to at least one use case
98
+ - Use case IDs follow the UC-{3-digit} convention
99
+ - PlantUML syntax is valid (no missing `@enduml`, proper arrow syntax)