@pennyfarthing/core 6.6.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 (599) hide show
  1. package/README.md +293 -0
  2. package/package.json +58 -0
  3. package/packages/core/bin/pennyfarthing.js +14 -0
  4. package/packages/core/dist/bmad/context-reader.d.ts +71 -0
  5. package/packages/core/dist/bmad/context-reader.d.ts.map +1 -0
  6. package/packages/core/dist/bmad/context-reader.js +369 -0
  7. package/packages/core/dist/bmad/context-reader.js.map +1 -0
  8. package/packages/core/dist/bmad/context-reader.test.d.ts +71 -0
  9. package/packages/core/dist/bmad/context-reader.test.d.ts.map +1 -0
  10. package/packages/core/dist/bmad/context-reader.test.js +878 -0
  11. package/packages/core/dist/bmad/context-reader.test.js.map +1 -0
  12. package/packages/core/dist/bmad/epics-parser.d.ts +61 -0
  13. package/packages/core/dist/bmad/epics-parser.d.ts.map +1 -0
  14. package/packages/core/dist/bmad/epics-parser.js +331 -0
  15. package/packages/core/dist/bmad/epics-parser.js.map +1 -0
  16. package/packages/core/dist/bmad/epics-parser.test.d.ts +7 -0
  17. package/packages/core/dist/bmad/epics-parser.test.d.ts.map +1 -0
  18. package/packages/core/dist/bmad/epics-parser.test.js +449 -0
  19. package/packages/core/dist/bmad/epics-parser.test.js.map +1 -0
  20. package/packages/core/dist/bmad/index.d.ts +11 -0
  21. package/packages/core/dist/bmad/index.d.ts.map +1 -0
  22. package/packages/core/dist/bmad/index.js +24 -0
  23. package/packages/core/dist/bmad/index.js.map +1 -0
  24. package/packages/core/dist/bmad/status-sync.d.ts +173 -0
  25. package/packages/core/dist/bmad/status-sync.d.ts.map +1 -0
  26. package/packages/core/dist/bmad/status-sync.js +463 -0
  27. package/packages/core/dist/bmad/status-sync.js.map +1 -0
  28. package/packages/core/dist/bmad/status-sync.test.d.ts +7 -0
  29. package/packages/core/dist/bmad/status-sync.test.d.ts.map +1 -0
  30. package/packages/core/dist/bmad/status-sync.test.js +702 -0
  31. package/packages/core/dist/bmad/status-sync.test.js.map +1 -0
  32. package/packages/core/dist/bmad/story-exporter.d.ts +55 -0
  33. package/packages/core/dist/bmad/story-exporter.d.ts.map +1 -0
  34. package/packages/core/dist/bmad/story-exporter.js +170 -0
  35. package/packages/core/dist/bmad/story-exporter.js.map +1 -0
  36. package/packages/core/dist/bmad/story-exporter.test.d.ts +51 -0
  37. package/packages/core/dist/bmad/story-exporter.test.d.ts.map +1 -0
  38. package/packages/core/dist/bmad/story-exporter.test.js +603 -0
  39. package/packages/core/dist/bmad/story-exporter.test.js.map +1 -0
  40. package/packages/core/dist/bmad/story-parser.d.ts +44 -0
  41. package/packages/core/dist/bmad/story-parser.d.ts.map +1 -0
  42. package/packages/core/dist/bmad/story-parser.js +307 -0
  43. package/packages/core/dist/bmad/story-parser.js.map +1 -0
  44. package/packages/core/dist/bmad/story-parser.test.d.ts +44 -0
  45. package/packages/core/dist/bmad/story-parser.test.d.ts.map +1 -0
  46. package/packages/core/dist/bmad/story-parser.test.js +693 -0
  47. package/packages/core/dist/bmad/story-parser.test.js.map +1 -0
  48. package/packages/core/dist/cli/commands/command.d.ts +28 -0
  49. package/packages/core/dist/cli/commands/command.d.ts.map +1 -0
  50. package/packages/core/dist/cli/commands/command.js +399 -0
  51. package/packages/core/dist/cli/commands/command.js.map +1 -0
  52. package/packages/core/dist/cli/commands/cyclist.d.ts +46 -0
  53. package/packages/core/dist/cli/commands/cyclist.d.ts.map +1 -0
  54. package/packages/core/dist/cli/commands/cyclist.js +191 -0
  55. package/packages/core/dist/cli/commands/cyclist.js.map +1 -0
  56. package/packages/core/dist/cli/commands/cyclist.test.d.ts +13 -0
  57. package/packages/core/dist/cli/commands/cyclist.test.d.ts.map +1 -0
  58. package/packages/core/dist/cli/commands/cyclist.test.js +243 -0
  59. package/packages/core/dist/cli/commands/cyclist.test.js.map +1 -0
  60. package/packages/core/dist/cli/commands/doctor.d.ts +9 -0
  61. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -0
  62. package/packages/core/dist/cli/commands/doctor.js +652 -0
  63. package/packages/core/dist/cli/commands/doctor.js.map +1 -0
  64. package/packages/core/dist/cli/commands/init.d.ts +8 -0
  65. package/packages/core/dist/cli/commands/init.d.ts.map +1 -0
  66. package/packages/core/dist/cli/commands/init.js +524 -0
  67. package/packages/core/dist/cli/commands/init.js.map +1 -0
  68. package/packages/core/dist/cli/commands/skill.d.ts +28 -0
  69. package/packages/core/dist/cli/commands/skill.d.ts.map +1 -0
  70. package/packages/core/dist/cli/commands/skill.js +416 -0
  71. package/packages/core/dist/cli/commands/skill.js.map +1 -0
  72. package/packages/core/dist/cli/commands/theme.d.ts +21 -0
  73. package/packages/core/dist/cli/commands/theme.d.ts.map +1 -0
  74. package/packages/core/dist/cli/commands/theme.js +201 -0
  75. package/packages/core/dist/cli/commands/theme.js.map +1 -0
  76. package/packages/core/dist/cli/commands/uninstall.d.ts +8 -0
  77. package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -0
  78. package/packages/core/dist/cli/commands/uninstall.js +237 -0
  79. package/packages/core/dist/cli/commands/uninstall.js.map +1 -0
  80. package/packages/core/dist/cli/commands/update.d.ts +9 -0
  81. package/packages/core/dist/cli/commands/update.d.ts.map +1 -0
  82. package/packages/core/dist/cli/commands/update.js +545 -0
  83. package/packages/core/dist/cli/commands/update.js.map +1 -0
  84. package/packages/core/dist/cli/commands/version.d.ts +2 -0
  85. package/packages/core/dist/cli/commands/version.d.ts.map +1 -0
  86. package/packages/core/dist/cli/commands/version.js +28 -0
  87. package/packages/core/dist/cli/commands/version.js.map +1 -0
  88. package/packages/core/dist/cli/customization.test.d.ts +12 -0
  89. package/packages/core/dist/cli/customization.test.d.ts.map +1 -0
  90. package/packages/core/dist/cli/customization.test.js +84 -0
  91. package/packages/core/dist/cli/customization.test.js.map +1 -0
  92. package/packages/core/dist/cli/cyclist-migration.test.d.ts +16 -0
  93. package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +1 -0
  94. package/packages/core/dist/cli/cyclist-migration.test.js +224 -0
  95. package/packages/core/dist/cli/cyclist-migration.test.js.map +1 -0
  96. package/packages/core/dist/cli/index.d.ts +3 -0
  97. package/packages/core/dist/cli/index.d.ts.map +1 -0
  98. package/packages/core/dist/cli/index.js +174 -0
  99. package/packages/core/dist/cli/index.js.map +1 -0
  100. package/packages/core/dist/cli/ocean-profiles.test.d.ts +13 -0
  101. package/packages/core/dist/cli/ocean-profiles.test.d.ts.map +1 -0
  102. package/packages/core/dist/cli/ocean-profiles.test.js +134 -0
  103. package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -0
  104. package/packages/core/dist/cli/theme-maker.test.d.ts +11 -0
  105. package/packages/core/dist/cli/theme-maker.test.d.ts.map +1 -0
  106. package/packages/core/dist/cli/theme-maker.test.js +356 -0
  107. package/packages/core/dist/cli/theme-maker.test.js.map +1 -0
  108. package/packages/core/dist/cli/utils/constants.d.ts +60 -0
  109. package/packages/core/dist/cli/utils/constants.d.ts.map +1 -0
  110. package/packages/core/dist/cli/utils/constants.js +52 -0
  111. package/packages/core/dist/cli/utils/constants.js.map +1 -0
  112. package/packages/core/dist/cli/utils/files.d.ts +71 -0
  113. package/packages/core/dist/cli/utils/files.d.ts.map +1 -0
  114. package/packages/core/dist/cli/utils/files.js +162 -0
  115. package/packages/core/dist/cli/utils/files.js.map +1 -0
  116. package/packages/core/dist/cli/utils/logger.d.ts +26 -0
  117. package/packages/core/dist/cli/utils/logger.d.ts.map +1 -0
  118. package/packages/core/dist/cli/utils/logger.js +88 -0
  119. package/packages/core/dist/cli/utils/logger.js.map +1 -0
  120. package/packages/core/dist/cli/utils/manifest.d.ts +47 -0
  121. package/packages/core/dist/cli/utils/manifest.d.ts.map +1 -0
  122. package/packages/core/dist/cli/utils/manifest.js +90 -0
  123. package/packages/core/dist/cli/utils/manifest.js.map +1 -0
  124. package/packages/core/dist/cli/utils/node-modules.d.ts +6 -0
  125. package/packages/core/dist/cli/utils/node-modules.d.ts.map +1 -0
  126. package/packages/core/dist/cli/utils/node-modules.js +22 -0
  127. package/packages/core/dist/cli/utils/node-modules.js.map +1 -0
  128. package/packages/core/dist/cli/utils/prompts.d.ts +34 -0
  129. package/packages/core/dist/cli/utils/prompts.d.ts.map +1 -0
  130. package/packages/core/dist/cli/utils/prompts.js +93 -0
  131. package/packages/core/dist/cli/utils/prompts.js.map +1 -0
  132. package/packages/core/dist/cli/utils/symlinks.d.ts +29 -0
  133. package/packages/core/dist/cli/utils/symlinks.d.ts.map +1 -0
  134. package/packages/core/dist/cli/utils/symlinks.js +181 -0
  135. package/packages/core/dist/cli/utils/symlinks.js.map +1 -0
  136. package/packages/core/dist/cli/utils/themes.d.ts +104 -0
  137. package/packages/core/dist/cli/utils/themes.d.ts.map +1 -0
  138. package/packages/core/dist/cli/utils/themes.js +393 -0
  139. package/packages/core/dist/cli/utils/themes.js.map +1 -0
  140. package/packages/core/dist/cli/utils/themes.test.d.ts +12 -0
  141. package/packages/core/dist/cli/utils/themes.test.d.ts.map +1 -0
  142. package/packages/core/dist/cli/utils/themes.test.js +144 -0
  143. package/packages/core/dist/cli/utils/themes.test.js.map +1 -0
  144. package/packages/core/dist/cli/utils/version.d.ts +10 -0
  145. package/packages/core/dist/cli/utils/version.d.ts.map +1 -0
  146. package/packages/core/dist/cli/utils/version.js +63 -0
  147. package/packages/core/dist/cli/utils/version.js.map +1 -0
  148. package/packages/core/dist/cli/workspace.test.d.ts +8 -0
  149. package/packages/core/dist/cli/workspace.test.d.ts.map +1 -0
  150. package/packages/core/dist/cli/workspace.test.js +154 -0
  151. package/packages/core/dist/cli/workspace.test.js.map +1 -0
  152. package/packages/core/dist/index.d.ts +6 -0
  153. package/packages/core/dist/index.d.ts.map +1 -0
  154. package/packages/core/dist/index.js +10 -0
  155. package/packages/core/dist/index.js.map +1 -0
  156. package/packages/core/dist/permissions/index.d.ts +9 -0
  157. package/packages/core/dist/permissions/index.d.ts.map +1 -0
  158. package/packages/core/dist/permissions/index.js +13 -0
  159. package/packages/core/dist/permissions/index.js.map +1 -0
  160. package/packages/core/dist/permissions/permission-schema.d.ts +89 -0
  161. package/packages/core/dist/permissions/permission-schema.d.ts.map +1 -0
  162. package/packages/core/dist/permissions/permission-schema.js +120 -0
  163. package/packages/core/dist/permissions/permission-schema.js.map +1 -0
  164. package/packages/core/dist/permissions/permission-schema.test.d.ts +40 -0
  165. package/packages/core/dist/permissions/permission-schema.test.d.ts.map +1 -0
  166. package/packages/core/dist/permissions/permission-schema.test.js +367 -0
  167. package/packages/core/dist/permissions/permission-schema.test.js.map +1 -0
  168. package/packages/core/dist/scripts/add-ocean-profiles.d.ts +9 -0
  169. package/packages/core/dist/scripts/add-ocean-profiles.d.ts.map +1 -0
  170. package/packages/core/dist/scripts/add-ocean-profiles.js +695 -0
  171. package/packages/core/dist/scripts/add-ocean-profiles.js.map +1 -0
  172. package/packages/core/dist/scripts/benchmark-integration.d.ts +182 -0
  173. package/packages/core/dist/scripts/benchmark-integration.d.ts.map +1 -0
  174. package/packages/core/dist/scripts/benchmark-integration.js +691 -0
  175. package/packages/core/dist/scripts/benchmark-integration.js.map +1 -0
  176. package/packages/core/dist/scripts/benchmark-integration.test.d.ts +13 -0
  177. package/packages/core/dist/scripts/benchmark-integration.test.d.ts.map +1 -0
  178. package/packages/core/dist/scripts/benchmark-integration.test.js +680 -0
  179. package/packages/core/dist/scripts/benchmark-integration.test.js.map +1 -0
  180. package/packages/core/dist/scripts/debugging-scenarios.test.d.ts +18 -0
  181. package/packages/core/dist/scripts/debugging-scenarios.test.d.ts.map +1 -0
  182. package/packages/core/dist/scripts/debugging-scenarios.test.js +317 -0
  183. package/packages/core/dist/scripts/debugging-scenarios.test.js.map +1 -0
  184. package/packages/core/dist/scripts/generate-all-faces.d.ts +10 -0
  185. package/packages/core/dist/scripts/generate-all-faces.d.ts.map +1 -0
  186. package/packages/core/dist/scripts/generate-all-faces.js +256 -0
  187. package/packages/core/dist/scripts/generate-all-faces.js.map +1 -0
  188. package/packages/core/dist/scripts/generate-all-faces.test.d.ts +17 -0
  189. package/packages/core/dist/scripts/generate-all-faces.test.d.ts.map +1 -0
  190. package/packages/core/dist/scripts/generate-all-faces.test.js +372 -0
  191. package/packages/core/dist/scripts/generate-all-faces.test.js.map +1 -0
  192. package/packages/core/dist/scripts/generate-all-spiders.d.ts +10 -0
  193. package/packages/core/dist/scripts/generate-all-spiders.d.ts.map +1 -0
  194. package/packages/core/dist/scripts/generate-all-spiders.js +306 -0
  195. package/packages/core/dist/scripts/generate-all-spiders.js.map +1 -0
  196. package/packages/core/dist/scripts/generate-ascii-face.d.ts +52 -0
  197. package/packages/core/dist/scripts/generate-ascii-face.d.ts.map +1 -0
  198. package/packages/core/dist/scripts/generate-ascii-face.js +155 -0
  199. package/packages/core/dist/scripts/generate-ascii-face.js.map +1 -0
  200. package/packages/core/dist/scripts/generate-face.d.ts +52 -0
  201. package/packages/core/dist/scripts/generate-face.d.ts.map +1 -0
  202. package/packages/core/dist/scripts/generate-face.js +199 -0
  203. package/packages/core/dist/scripts/generate-face.js.map +1 -0
  204. package/packages/core/dist/scripts/generate-face.test.d.ts +13 -0
  205. package/packages/core/dist/scripts/generate-face.test.d.ts.map +1 -0
  206. package/packages/core/dist/scripts/generate-face.test.js +301 -0
  207. package/packages/core/dist/scripts/generate-face.test.js.map +1 -0
  208. package/packages/core/dist/scripts/generate-report.d.ts +65 -0
  209. package/packages/core/dist/scripts/generate-report.d.ts.map +1 -0
  210. package/packages/core/dist/scripts/generate-report.js +378 -0
  211. package/packages/core/dist/scripts/generate-report.js.map +1 -0
  212. package/packages/core/dist/scripts/generate-report.test.d.ts +13 -0
  213. package/packages/core/dist/scripts/generate-report.test.d.ts.map +1 -0
  214. package/packages/core/dist/scripts/generate-report.test.js +363 -0
  215. package/packages/core/dist/scripts/generate-report.test.js.map +1 -0
  216. package/packages/core/dist/scripts/generate-spider-report.d.ts +65 -0
  217. package/packages/core/dist/scripts/generate-spider-report.d.ts.map +1 -0
  218. package/packages/core/dist/scripts/generate-spider-report.js +366 -0
  219. package/packages/core/dist/scripts/generate-spider-report.js.map +1 -0
  220. package/packages/core/dist/scripts/generate-spider-report.test.d.ts +13 -0
  221. package/packages/core/dist/scripts/generate-spider-report.test.d.ts.map +1 -0
  222. package/packages/core/dist/scripts/generate-spider-report.test.js +367 -0
  223. package/packages/core/dist/scripts/generate-spider-report.test.js.map +1 -0
  224. package/packages/core/dist/scripts/generate-spider.d.ts +37 -0
  225. package/packages/core/dist/scripts/generate-spider.d.ts.map +1 -0
  226. package/packages/core/dist/scripts/generate-spider.js +315 -0
  227. package/packages/core/dist/scripts/generate-spider.js.map +1 -0
  228. package/packages/core/dist/scripts/generate-spider.test.d.ts +14 -0
  229. package/packages/core/dist/scripts/generate-spider.test.d.ts.map +1 -0
  230. package/packages/core/dist/scripts/generate-spider.test.js +269 -0
  231. package/packages/core/dist/scripts/generate-spider.test.js.map +1 -0
  232. package/packages/core/dist/scripts/job-fair-aggregator.d.ts +150 -0
  233. package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +1 -0
  234. package/packages/core/dist/scripts/job-fair-aggregator.js +547 -0
  235. package/packages/core/dist/scripts/job-fair-aggregator.js.map +1 -0
  236. package/packages/core/dist/scripts/job-fair-aggregator.test.d.ts +14 -0
  237. package/packages/core/dist/scripts/job-fair-aggregator.test.d.ts.map +1 -0
  238. package/packages/core/dist/scripts/job-fair-aggregator.test.js +616 -0
  239. package/packages/core/dist/scripts/job-fair-aggregator.test.js.map +1 -0
  240. package/packages/core/dist/scripts/run-ci.test.d.ts +20 -0
  241. package/packages/core/dist/scripts/run-ci.test.d.ts.map +1 -0
  242. package/packages/core/dist/scripts/run-ci.test.js +127 -0
  243. package/packages/core/dist/scripts/run-ci.test.js.map +1 -0
  244. package/packages/core/dist/scripts/theme-detail.test.d.ts +10 -0
  245. package/packages/core/dist/scripts/theme-detail.test.d.ts.map +1 -0
  246. package/packages/core/dist/scripts/theme-detail.test.js +199 -0
  247. package/packages/core/dist/scripts/theme-detail.test.js.map +1 -0
  248. package/packages/core/dist/scripts/validate-ocean-profiles.d.ts +9 -0
  249. package/packages/core/dist/scripts/validate-ocean-profiles.d.ts.map +1 -0
  250. package/packages/core/dist/scripts/validate-ocean-profiles.js +130 -0
  251. package/packages/core/dist/scripts/validate-ocean-profiles.js.map +1 -0
  252. package/packages/core/dist/workflow/generic-handoff.d.ts +235 -0
  253. package/packages/core/dist/workflow/generic-handoff.d.ts.map +1 -0
  254. package/packages/core/dist/workflow/generic-handoff.js +358 -0
  255. package/packages/core/dist/workflow/generic-handoff.js.map +1 -0
  256. package/packages/core/dist/workflow/generic-handoff.test.d.ts +21 -0
  257. package/packages/core/dist/workflow/generic-handoff.test.d.ts.map +1 -0
  258. package/packages/core/dist/workflow/generic-handoff.test.js +499 -0
  259. package/packages/core/dist/workflow/generic-handoff.test.js.map +1 -0
  260. package/packages/core/dist/workflow/generic-sm-finish.d.ts +89 -0
  261. package/packages/core/dist/workflow/generic-sm-finish.d.ts.map +1 -0
  262. package/packages/core/dist/workflow/generic-sm-finish.js +157 -0
  263. package/packages/core/dist/workflow/generic-sm-finish.js.map +1 -0
  264. package/packages/core/dist/workflow/generic-sm-setup.d.ts +138 -0
  265. package/packages/core/dist/workflow/generic-sm-setup.d.ts.map +1 -0
  266. package/packages/core/dist/workflow/generic-sm-setup.js +382 -0
  267. package/packages/core/dist/workflow/generic-sm-setup.js.map +1 -0
  268. package/packages/core/dist/workflow/sm-subagents.test.d.ts +23 -0
  269. package/packages/core/dist/workflow/sm-subagents.test.d.ts.map +1 -0
  270. package/packages/core/dist/workflow/sm-subagents.test.js +727 -0
  271. package/packages/core/dist/workflow/sm-subagents.test.js.map +1 -0
  272. package/packages/core/dist/workflow/story-workflow-routing.test.d.ts +17 -0
  273. package/packages/core/dist/workflow/story-workflow-routing.test.d.ts.map +1 -0
  274. package/packages/core/dist/workflow/story-workflow-routing.test.js +559 -0
  275. package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -0
  276. package/packages/core/dist/workflow/test-cache.d.ts +131 -0
  277. package/packages/core/dist/workflow/test-cache.d.ts.map +1 -0
  278. package/packages/core/dist/workflow/test-cache.js +226 -0
  279. package/packages/core/dist/workflow/test-cache.js.map +1 -0
  280. package/packages/core/dist/workflow/test-cache.test.d.ts +17 -0
  281. package/packages/core/dist/workflow/test-cache.test.d.ts.map +1 -0
  282. package/packages/core/dist/workflow/test-cache.test.js +438 -0
  283. package/packages/core/dist/workflow/test-cache.test.js.map +1 -0
  284. package/packages/core/dist/workflow/workflow-loader.d.ts +76 -0
  285. package/packages/core/dist/workflow/workflow-loader.d.ts.map +1 -0
  286. package/packages/core/dist/workflow/workflow-loader.js +133 -0
  287. package/packages/core/dist/workflow/workflow-loader.js.map +1 -0
  288. package/packages/core/dist/workflow/workflow-loader.test.d.ts +15 -0
  289. package/packages/core/dist/workflow/workflow-loader.test.d.ts.map +1 -0
  290. package/packages/core/dist/workflow/workflow-loader.test.js +354 -0
  291. package/packages/core/dist/workflow/workflow-loader.test.js.map +1 -0
  292. package/packages/core/dist/workflow/workflow-migration.test.d.ts +17 -0
  293. package/packages/core/dist/workflow/workflow-migration.test.d.ts.map +1 -0
  294. package/packages/core/dist/workflow/workflow-migration.test.js +372 -0
  295. package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -0
  296. package/packages/core/dist/workflow/workflow-router.d.ts +55 -0
  297. package/packages/core/dist/workflow/workflow-router.d.ts.map +1 -0
  298. package/packages/core/dist/workflow/workflow-router.js +245 -0
  299. package/packages/core/dist/workflow/workflow-router.js.map +1 -0
  300. package/packages/core/dist/workflow/workflow-router.test.d.ts +20 -0
  301. package/packages/core/dist/workflow/workflow-router.test.d.ts.map +1 -0
  302. package/packages/core/dist/workflow/workflow-router.test.js +607 -0
  303. package/packages/core/dist/workflow/workflow-router.test.js.map +1 -0
  304. package/packages/core/dist/workflow/workflow-schema.d.ts +98 -0
  305. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -0
  306. package/packages/core/dist/workflow/workflow-schema.js +230 -0
  307. package/packages/core/dist/workflow/workflow-schema.js.map +1 -0
  308. package/packages/core/dist/workflow/workflow-schema.test.d.ts +45 -0
  309. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -0
  310. package/packages/core/dist/workflow/workflow-schema.test.js +512 -0
  311. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -0
  312. package/pennyfarthing-dist/agents/README.md +397 -0
  313. package/pennyfarthing-dist/agents/architect.md +171 -0
  314. package/pennyfarthing-dist/agents/dev.md +225 -0
  315. package/pennyfarthing-dist/agents/devops.md +183 -0
  316. package/pennyfarthing-dist/agents/generic-handoff.md +451 -0
  317. package/pennyfarthing-dist/agents/generic-sm-finish.md +261 -0
  318. package/pennyfarthing-dist/agents/generic-sm-setup.md +214 -0
  319. package/pennyfarthing-dist/agents/orchestrator.md +316 -0
  320. package/pennyfarthing-dist/agents/pm.md +153 -0
  321. package/pennyfarthing-dist/agents/reviewer-preflight.md +224 -0
  322. package/pennyfarthing-dist/agents/reviewer.md +315 -0
  323. package/pennyfarthing-dist/agents/sm-file-summary.md +109 -0
  324. package/pennyfarthing-dist/agents/sm-handoff.md +97 -0
  325. package/pennyfarthing-dist/agents/sm.md +480 -0
  326. package/pennyfarthing-dist/agents/tea.md +191 -0
  327. package/pennyfarthing-dist/agents/tech-writer.md +148 -0
  328. package/pennyfarthing-dist/agents/testing-runner.md +420 -0
  329. package/pennyfarthing-dist/agents/ux-designer.md +158 -0
  330. package/pennyfarthing-dist/agents/workflow-status-check.md +332 -0
  331. package/pennyfarthing-dist/commands/architect.md +62 -0
  332. package/pennyfarthing-dist/commands/benchmark-control.md +69 -0
  333. package/pennyfarthing-dist/commands/benchmark.md +467 -0
  334. package/pennyfarthing-dist/commands/brainstorm.md +91 -0
  335. package/pennyfarthing-dist/commands/check.md +156 -0
  336. package/pennyfarthing-dist/commands/chore.md +178 -0
  337. package/pennyfarthing-dist/commands/close-epic.md +136 -0
  338. package/pennyfarthing-dist/commands/continue-session.md +184 -0
  339. package/pennyfarthing-dist/commands/create-branches-from-story.md +374 -0
  340. package/pennyfarthing-dist/commands/create-theme.md +29 -0
  341. package/pennyfarthing-dist/commands/dev.md +60 -0
  342. package/pennyfarthing-dist/commands/devops.md +59 -0
  343. package/pennyfarthing-dist/commands/git-cleanup.md +340 -0
  344. package/pennyfarthing-dist/commands/health-check.md +108 -0
  345. package/pennyfarthing-dist/commands/help.md +264 -0
  346. package/pennyfarthing-dist/commands/job-fair.md +102 -0
  347. package/pennyfarthing-dist/commands/list-themes.md +17 -0
  348. package/pennyfarthing-dist/commands/new-work.md +127 -0
  349. package/pennyfarthing-dist/commands/orchestrator.md +56 -0
  350. package/pennyfarthing-dist/commands/parallel-work.md +71 -0
  351. package/pennyfarthing-dist/commands/party-mode.md +67 -0
  352. package/pennyfarthing-dist/commands/permissions.md +193 -0
  353. package/pennyfarthing-dist/commands/pm.md +60 -0
  354. package/pennyfarthing-dist/commands/prime.md +140 -0
  355. package/pennyfarthing-dist/commands/release.md +58 -0
  356. package/pennyfarthing-dist/commands/repo-status.md +49 -0
  357. package/pennyfarthing-dist/commands/retro.md +200 -0
  358. package/pennyfarthing-dist/commands/reviewer.md +64 -0
  359. package/pennyfarthing-dist/commands/run-ci.md +116 -0
  360. package/pennyfarthing-dist/commands/set-theme.md +52 -0
  361. package/pennyfarthing-dist/commands/show-theme.md +21 -0
  362. package/pennyfarthing-dist/commands/sm.md +70 -0
  363. package/pennyfarthing-dist/commands/solo.md +411 -0
  364. package/pennyfarthing-dist/commands/sprint-planning.md +109 -0
  365. package/pennyfarthing-dist/commands/start-epic.md +156 -0
  366. package/pennyfarthing-dist/commands/sync-epic-to-jira.md +184 -0
  367. package/pennyfarthing-dist/commands/sync-work-with-sprint.md +376 -0
  368. package/pennyfarthing-dist/commands/tea.md +63 -0
  369. package/pennyfarthing-dist/commands/tech-writer.md +53 -0
  370. package/pennyfarthing-dist/commands/theme-maker.md +671 -0
  371. package/pennyfarthing-dist/commands/update-domain-docs.md +83 -0
  372. package/pennyfarthing-dist/commands/ux-designer.md +62 -0
  373. package/pennyfarthing-dist/commands/work.md +111 -0
  374. package/pennyfarthing-dist/guides/AGENT-COORDINATION.md +480 -0
  375. package/pennyfarthing-dist/guides/AGENT-SCOPES.md +201 -0
  376. package/pennyfarthing-dist/guides/HOOKS.md +230 -0
  377. package/pennyfarthing-dist/guides/PROMPT-PATTERNS.md +338 -0
  378. package/pennyfarthing-dist/guides/SESSION-ARTIFACTS.md +193 -0
  379. package/pennyfarthing-dist/guides/agent-template-strategic.md +148 -0
  380. package/pennyfarthing-dist/guides/agent-template-tactical.md +162 -0
  381. package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +746 -0
  382. package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +574 -0
  383. package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +488 -0
  384. package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +402 -0
  385. package/pennyfarthing-dist/guides/permission-protocol.md +188 -0
  386. package/pennyfarthing-dist/guides/persona-loading.md +46 -0
  387. package/pennyfarthing-dist/guides/persona-system.md +294 -0
  388. package/pennyfarthing-dist/guides/shared-agent-behavior.md +388 -0
  389. package/pennyfarthing-dist/guides/shared-context.md +147 -0
  390. package/pennyfarthing-dist/guides/strategic-agent-behavior.md +348 -0
  391. package/pennyfarthing-dist/guides/tactical-agent-behavior.md +1041 -0
  392. package/pennyfarthing-dist/guides/workflow-schema.md +195 -0
  393. package/pennyfarthing-dist/guides/worktree-mode.md +113 -0
  394. package/pennyfarthing-dist/output-styles/teaching.md +33 -0
  395. package/pennyfarthing-dist/output-styles/terse.md +20 -0
  396. package/pennyfarthing-dist/output-styles/verbose.md +28 -0
  397. package/pennyfarthing-dist/personas/themes/1984.yaml +312 -0
  398. package/pennyfarthing-dist/personas/themes/a-team.yaml +207 -0
  399. package/pennyfarthing-dist/personas/themes/agatha-christie.yaml +300 -0
  400. package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +330 -0
  401. package/pennyfarthing-dist/personas/themes/all-stars.yaml +332 -0
  402. package/pennyfarthing-dist/personas/themes/ancient-philosophers.yaml +320 -0
  403. package/pennyfarthing-dist/personas/themes/ancient-strategists.yaml +306 -0
  404. package/pennyfarthing-dist/personas/themes/arcane.yaml +288 -0
  405. package/pennyfarthing-dist/personas/themes/arthurian-mythos.yaml +331 -0
  406. package/pennyfarthing-dist/personas/themes/avatar-the-last-airbender.yaml +288 -0
  407. package/pennyfarthing-dist/personas/themes/babylon-5.yaml +288 -0
  408. package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +288 -0
  409. package/pennyfarthing-dist/personas/themes/better-call-saul.yaml +288 -0
  410. package/pennyfarthing-dist/personas/themes/big-lebowski.yaml +300 -0
  411. package/pennyfarthing-dist/personas/themes/black-sails.yaml +300 -0
  412. package/pennyfarthing-dist/personas/themes/blade-runner.yaml +295 -0
  413. package/pennyfarthing-dist/personas/themes/bobiverse.yaml +288 -0
  414. package/pennyfarthing-dist/personas/themes/breaking-bad.yaml +327 -0
  415. package/pennyfarthing-dist/personas/themes/catch-22.yaml +316 -0
  416. package/pennyfarthing-dist/personas/themes/classical-composers.yaml +310 -0
  417. package/pennyfarthing-dist/personas/themes/control.yaml +197 -0
  418. package/pennyfarthing-dist/personas/themes/count-of-monte-cristo.yaml +320 -0
  419. package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +323 -0
  420. package/pennyfarthing-dist/personas/themes/deadwood.yaml +300 -0
  421. package/pennyfarthing-dist/personas/themes/dickens.yaml +320 -0
  422. package/pennyfarthing-dist/personas/themes/discworld.yaml +332 -0
  423. package/pennyfarthing-dist/personas/themes/doctor-who.yaml +290 -0
  424. package/pennyfarthing-dist/personas/themes/don-quixote.yaml +320 -0
  425. package/pennyfarthing-dist/personas/themes/dune.yaml +307 -0
  426. package/pennyfarthing-dist/personas/themes/enlightenment-thinkers.yaml +320 -0
  427. package/pennyfarthing-dist/personas/themes/expeditionary-force.yaml +288 -0
  428. package/pennyfarthing-dist/personas/themes/fargo.yaml +330 -0
  429. package/pennyfarthing-dist/personas/themes/film-auteurs.yaml +312 -0
  430. package/pennyfarthing-dist/personas/themes/firefly.yaml +328 -0
  431. package/pennyfarthing-dist/personas/themes/foundation.yaml +290 -0
  432. package/pennyfarthing-dist/personas/themes/futurama.yaml +321 -0
  433. package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +290 -0
  434. package/pennyfarthing-dist/personas/themes/gilligans-island.yaml +243 -0
  435. package/pennyfarthing-dist/personas/themes/gothic-literature.yaml +308 -0
  436. package/pennyfarthing-dist/personas/themes/great-gatsby.yaml +308 -0
  437. package/pennyfarthing-dist/personas/themes/greek-mythology.yaml +330 -0
  438. package/pennyfarthing-dist/personas/themes/hannibal.yaml +300 -0
  439. package/pennyfarthing-dist/personas/themes/harry-potter.yaml +324 -0
  440. package/pennyfarthing-dist/personas/themes/his-dark-materials.yaml +291 -0
  441. package/pennyfarthing-dist/personas/themes/historical-figures.yaml +288 -0
  442. package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +331 -0
  443. package/pennyfarthing-dist/personas/themes/house-md.yaml +321 -0
  444. package/pennyfarthing-dist/personas/themes/imperial-radch.yaml +289 -0
  445. package/pennyfarthing-dist/personas/themes/inspector-morse.yaml +300 -0
  446. package/pennyfarthing-dist/personas/themes/jane-austen.yaml +287 -0
  447. package/pennyfarthing-dist/personas/themes/jazz-legends.yaml +320 -0
  448. package/pennyfarthing-dist/personas/themes/justified.yaml +300 -0
  449. package/pennyfarthing-dist/personas/themes/legion-of-doom.yaml +219 -0
  450. package/pennyfarthing-dist/personas/themes/les-miserables.yaml +299 -0
  451. package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +334 -0
  452. package/pennyfarthing-dist/personas/themes/lovecraft-mythos.yaml +334 -0
  453. package/pennyfarthing-dist/personas/themes/mad-max.yaml +355 -0
  454. package/pennyfarthing-dist/personas/themes/mad-men.yaml +289 -0
  455. package/pennyfarthing-dist/personas/themes/marvel-mcu.yaml +300 -0
  456. package/pennyfarthing-dist/personas/themes/mash.yaml +334 -0
  457. package/pennyfarthing-dist/personas/themes/mass-effect.yaml +289 -0
  458. package/pennyfarthing-dist/personas/themes/military-commanders.yaml +306 -0
  459. package/pennyfarthing-dist/personas/themes/moby-dick.yaml +320 -0
  460. package/pennyfarthing-dist/personas/themes/monty-python.yaml +303 -0
  461. package/pennyfarthing-dist/personas/themes/neuromancer.yaml +300 -0
  462. package/pennyfarthing-dist/personas/themes/norse-mythology.yaml +329 -0
  463. package/pennyfarthing-dist/personas/themes/parks-and-rec.yaml +242 -0
  464. package/pennyfarthing-dist/personas/themes/peaky-blinders.yaml +298 -0
  465. package/pennyfarthing-dist/personas/themes/princess-bride.yaml +220 -0
  466. package/pennyfarthing-dist/personas/themes/renaissance-masters.yaml +320 -0
  467. package/pennyfarthing-dist/personas/themes/rome.yaml +300 -0
  468. package/pennyfarthing-dist/personas/themes/russian-masters.yaml +318 -0
  469. package/pennyfarthing-dist/personas/themes/sandman.yaml +288 -0
  470. package/pennyfarthing-dist/personas/themes/scientific-revolutionaries.yaml +320 -0
  471. package/pennyfarthing-dist/personas/themes/shakespeare.yaml +301 -0
  472. package/pennyfarthing-dist/personas/themes/sherlock-holmes.yaml +289 -0
  473. package/pennyfarthing-dist/personas/themes/snow-crash.yaml +288 -0
  474. package/pennyfarthing-dist/personas/themes/software-pioneers.yaml +300 -0
  475. package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +230 -0
  476. package/pennyfarthing-dist/personas/themes/star-trek-tos.yaml +210 -0
  477. package/pennyfarthing-dist/personas/themes/star-wars.yaml +303 -0
  478. package/pennyfarthing-dist/personas/themes/succession.yaml +300 -0
  479. package/pennyfarthing-dist/personas/themes/superfriends.yaml +208 -0
  480. package/pennyfarthing-dist/personas/themes/ted-lasso.yaml +236 -0
  481. package/pennyfarthing-dist/personas/themes/the-americans.yaml +300 -0
  482. package/pennyfarthing-dist/personas/themes/the-crown.yaml +300 -0
  483. package/pennyfarthing-dist/personas/themes/the-expanse.yaml +213 -0
  484. package/pennyfarthing-dist/personas/themes/the-good-place.yaml +322 -0
  485. package/pennyfarthing-dist/personas/themes/the-matrix.yaml +353 -0
  486. package/pennyfarthing-dist/personas/themes/the-odyssey.yaml +300 -0
  487. package/pennyfarthing-dist/personas/themes/the-office.yaml +330 -0
  488. package/pennyfarthing-dist/personas/themes/the-simpsons.yaml +308 -0
  489. package/pennyfarthing-dist/personas/themes/the-sopranos.yaml +300 -0
  490. package/pennyfarthing-dist/personas/themes/the-wire.yaml +311 -0
  491. package/pennyfarthing-dist/personas/themes/the-witcher.yaml +300 -0
  492. package/pennyfarthing-dist/personas/themes/twin-peaks.yaml +302 -0
  493. package/pennyfarthing-dist/personas/themes/vorkosigan-saga.yaml +300 -0
  494. package/pennyfarthing-dist/personas/themes/watchmen.yaml +291 -0
  495. package/pennyfarthing-dist/personas/themes/west-wing.yaml +291 -0
  496. package/pennyfarthing-dist/personas/themes/world-explorers.yaml +320 -0
  497. package/pennyfarthing-dist/personas/themes/wwii-leaders.yaml +307 -0
  498. package/pennyfarthing-dist/personas/themes/x-files.yaml +302 -0
  499. package/pennyfarthing-dist/scripts/add-short-names.mjs +264 -0
  500. package/pennyfarthing-dist/scripts/agent-session.sh +367 -0
  501. package/pennyfarthing-dist/scripts/check-context.sh +187 -0
  502. package/pennyfarthing-dist/scripts/check.sh +497 -0
  503. package/pennyfarthing-dist/scripts/deploy.sh +284 -0
  504. package/pennyfarthing-dist/scripts/doctor-dogfood.sh +360 -0
  505. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +61 -0
  506. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +66 -0
  507. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +35 -0
  508. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +166 -0
  509. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +50 -0
  510. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +71 -0
  511. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +54 -0
  512. package/pennyfarthing-dist/scripts/hooks/session-start.sh +98 -0
  513. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +59 -0
  514. package/pennyfarthing-dist/scripts/install-git-hooks.sh +91 -0
  515. package/pennyfarthing-dist/scripts/prime.sh +161 -0
  516. package/pennyfarthing-dist/scripts/release.sh +198 -0
  517. package/pennyfarthing-dist/scripts/repo-utils.sh +778 -0
  518. package/pennyfarthing-dist/scripts/run-ci.sh +219 -0
  519. package/pennyfarthing-dist/scripts/run.sh +65 -0
  520. package/pennyfarthing-dist/scripts/statusline.sh +264 -0
  521. package/pennyfarthing-dist/scripts/tests/check.test.sh +582 -0
  522. package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +107 -0
  523. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +597 -0
  524. package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +514 -0
  525. package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +517 -0
  526. package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +331 -0
  527. package/pennyfarthing-dist/scripts/uninstall.sh +271 -0
  528. package/pennyfarthing-dist/scripts/utils/background-tasks.sh +177 -0
  529. package/pennyfarthing-dist/scripts/utils/check-status.sh +251 -0
  530. package/pennyfarthing-dist/scripts/utils/checkpoint.sh +136 -0
  531. package/pennyfarthing-dist/scripts/utils/common.sh +157 -0
  532. package/pennyfarthing-dist/scripts/utils/create-feature-branches.sh +230 -0
  533. package/pennyfarthing-dist/scripts/utils/file-lock.sh +269 -0
  534. package/pennyfarthing-dist/scripts/utils/find-related-work.sh +231 -0
  535. package/pennyfarthing-dist/scripts/utils/find-root.sh +33 -0
  536. package/pennyfarthing-dist/scripts/utils/generate-skill-docs.sh +110 -0
  537. package/pennyfarthing-dist/scripts/utils/git-status-all.sh +127 -0
  538. package/pennyfarthing-dist/scripts/utils/ground-truth-judge.py +289 -0
  539. package/pennyfarthing-dist/scripts/utils/jira/jira-lib.mjs +443 -0
  540. package/pennyfarthing-dist/scripts/utils/jira/jira-sync-story.mjs +208 -0
  541. package/pennyfarthing-dist/scripts/utils/jira/jira-sync.mjs +198 -0
  542. package/pennyfarthing-dist/scripts/utils/jira-claim-story.sh +162 -0
  543. package/pennyfarthing-dist/scripts/utils/jira-lib.sh +463 -0
  544. package/pennyfarthing-dist/scripts/utils/jira-sync-story.sh +8 -0
  545. package/pennyfarthing-dist/scripts/utils/jira-sync.sh +8 -0
  546. package/pennyfarthing-dist/scripts/utils/log-skill-usage.sh +74 -0
  547. package/pennyfarthing-dist/scripts/utils/logging.sh +186 -0
  548. package/pennyfarthing-dist/scripts/utils/repo-scan.sh +141 -0
  549. package/pennyfarthing-dist/scripts/utils/retry.sh +76 -0
  550. package/pennyfarthing-dist/scripts/utils/run-timestamp.sh +7 -0
  551. package/pennyfarthing-dist/scripts/utils/session-cleanup.sh +319 -0
  552. package/pennyfarthing-dist/scripts/utils/skill-usage-report.sh +193 -0
  553. package/pennyfarthing-dist/scripts/utils/sprint-common.sh +286 -0
  554. package/pennyfarthing-dist/scripts/utils/sprint-metrics.sh +241 -0
  555. package/pennyfarthing-dist/scripts/utils/swebench-judge.py +400 -0
  556. package/pennyfarthing-dist/scripts/utils/sync-epic-to-jira.sh +16 -0
  557. package/pennyfarthing-dist/scripts/utils/test-setup.sh +337 -0
  558. package/pennyfarthing-dist/scripts/utils/validate-subagent-frontmatter.sh +160 -0
  559. package/pennyfarthing-dist/scripts/worktree-manager.sh +498 -0
  560. package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +236 -0
  561. package/pennyfarthing-dist/skills/changelog/SKILL.md +367 -0
  562. package/pennyfarthing-dist/skills/code-review/SKILL.md +168 -0
  563. package/pennyfarthing-dist/skills/context-engineering/SKILL.md +268 -0
  564. package/pennyfarthing-dist/skills/cyclist/SKILL.md +117 -0
  565. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +421 -0
  566. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +258 -0
  567. package/pennyfarthing-dist/skills/jira/SKILL.md +281 -0
  568. package/pennyfarthing-dist/skills/judge/SKILL.md +524 -0
  569. package/pennyfarthing-dist/skills/just/SKILL.md +160 -0
  570. package/pennyfarthing-dist/skills/mermaid/SKILL.md +240 -0
  571. package/pennyfarthing-dist/skills/otel/skill.md +222 -0
  572. package/pennyfarthing-dist/skills/permissions/skill.md +172 -0
  573. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +173 -0
  574. package/pennyfarthing-dist/skills/skill-registry.schema.json +102 -0
  575. package/pennyfarthing-dist/skills/skill-registry.yaml +335 -0
  576. package/pennyfarthing-dist/skills/sprint-context/SKILL.md +120 -0
  577. package/pennyfarthing-dist/skills/story-management/SKILL.md +208 -0
  578. package/pennyfarthing-dist/skills/testing/SKILL.md +99 -0
  579. package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +124 -0
  580. package/pennyfarthing-dist/skills/theme/skill.md +129 -0
  581. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +169 -0
  582. package/pennyfarthing-dist/skills/workflow/SKILL.md +160 -0
  583. package/pennyfarthing-dist/skills/yq/SKILL.md +264 -0
  584. package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +187 -0
  585. package/pennyfarthing-dist/templates/LEADERBOARD.template.md +59 -0
  586. package/pennyfarthing-dist/templates/agent-scopes.yaml.template +276 -0
  587. package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +61 -0
  588. package/pennyfarthing-dist/templates/persona-config.yaml.template +22 -0
  589. package/pennyfarthing-dist/templates/preferences.yaml.template +15 -0
  590. package/pennyfarthing-dist/templates/settings.local.json.template +90 -0
  591. package/pennyfarthing-dist/templates/setup-env.sh.template +18 -0
  592. package/pennyfarthing-dist/templates/shared-context.md.template +70 -0
  593. package/pennyfarthing-dist/templates/sidecar/decisions.md.template +40 -0
  594. package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +37 -0
  595. package/pennyfarthing-dist/templates/sidecar/patterns.md.template +34 -0
  596. package/pennyfarthing-dist/workflows/agent-docs.yaml +70 -0
  597. package/pennyfarthing-dist/workflows/bdd.yaml +58 -0
  598. package/pennyfarthing-dist/workflows/tdd.yaml +50 -0
  599. package/pennyfarthing-dist/workflows/trivial.yaml +40 -0
@@ -0,0 +1,702 @@
1
+ /**
2
+ * BMAD Status Sync Tests - Story 32-6
3
+ *
4
+ * Tests for bidirectional sync between Pennyfarthing and BMAD sprint status.
5
+ */
6
+ import { describe, it } from 'node:test';
7
+ import assert from 'node:assert';
8
+ import {
9
+ // Story ID conversion
10
+ bmadIdToPenny, pennyIdToBmad, isValidBmadStoryId, isValidPennyStoryId,
11
+ // Status mapping
12
+ mapBmadToPennyStatus, mapPennyToBmadStatus,
13
+ // AC1: Parse
14
+ parseBmadSprintStatus,
15
+ // AC2: Import
16
+ convertBmadStoryToPenny, importFromBmadStatus,
17
+ // AC3: Export
18
+ convertPennyStoryToBmad, exportToSprintStatus,
19
+ // AC5: Conflicts
20
+ detectConflicts, } from './status-sync.js';
21
+ // =============================================================================
22
+ // Test Fixtures
23
+ // =============================================================================
24
+ const VALID_BMAD_YAML = `
25
+ sprint:
26
+ number: 10
27
+ goal: "Complete user authentication"
28
+ start_date: 2024-01-15
29
+ end_date: 2024-01-26
30
+
31
+ stories:
32
+ - id: "1.1"
33
+ title: "Email/Password Login"
34
+ epic: "User Authentication"
35
+ status: done
36
+ assignee: "Alice Chen"
37
+ points: 5
38
+ priority: P0
39
+ started: 2024-01-15
40
+ completed: 2024-01-17
41
+
42
+ - id: "1.2"
43
+ title: "OAuth Integration"
44
+ status: in-progress
45
+ assignee: "Bob Smith"
46
+ points: 8
47
+ priority: P1
48
+ started: 2024-01-18
49
+
50
+ - id: "2.1"
51
+ title: "Edit Profile"
52
+ status: ready-for-dev
53
+ points: 3
54
+ priority: P1
55
+
56
+ metrics:
57
+ total_points: 16
58
+ completed_points: 5
59
+ in_progress_points: 8
60
+ `;
61
+ const BLOCKED_STORY_YAML = `
62
+ sprint:
63
+ number: 10
64
+ goal: "Test blocked status"
65
+ start_date: 2024-01-15
66
+ end_date: 2024-01-26
67
+
68
+ stories:
69
+ - id: "1.3"
70
+ title: "Password Reset Flow"
71
+ status: blocked
72
+ points: 3
73
+ priority: P1
74
+ blockers:
75
+ - "Waiting for email service"
76
+ - "Need API keys"
77
+
78
+ metrics:
79
+ total_points: 3
80
+ completed_points: 0
81
+ `;
82
+ const MINIMAL_BMAD_YAML = `
83
+ sprint:
84
+ number: 1
85
+ goal: "Minimal sprint"
86
+ start_date: 2024-01-01
87
+ end_date: 2024-01-14
88
+
89
+ stories:
90
+ - id: "1.1"
91
+ title: "Simple story"
92
+ status: ready-for-dev
93
+ points: 1
94
+ priority: P2
95
+
96
+ metrics:
97
+ total_points: 1
98
+ completed_points: 0
99
+ `;
100
+ // =============================================================================
101
+ // Story ID Conversion Tests
102
+ // =============================================================================
103
+ describe('Story ID Conversion', () => {
104
+ describe('bmadIdToPenny', () => {
105
+ it('converts single dot to dash', () => {
106
+ assert.strictEqual(bmadIdToPenny('1.1'), '1-1');
107
+ });
108
+ it('converts multiple dots to dashes', () => {
109
+ assert.strictEqual(bmadIdToPenny('32.6'), '32-6');
110
+ });
111
+ it('handles larger numbers', () => {
112
+ assert.strictEqual(bmadIdToPenny('100.99'), '100-99');
113
+ });
114
+ });
115
+ describe('pennyIdToBmad', () => {
116
+ it('converts single dash to dot', () => {
117
+ assert.strictEqual(pennyIdToBmad('1-1'), '1.1');
118
+ });
119
+ it('converts multiple dashes to dots', () => {
120
+ assert.strictEqual(pennyIdToBmad('32-6'), '32.6');
121
+ });
122
+ it('handles larger numbers', () => {
123
+ assert.strictEqual(pennyIdToBmad('100-99'), '100.99');
124
+ });
125
+ });
126
+ describe('isValidBmadStoryId', () => {
127
+ it('returns true for valid dot notation', () => {
128
+ assert.strictEqual(isValidBmadStoryId('1.1'), true);
129
+ assert.strictEqual(isValidBmadStoryId('32.6'), true);
130
+ assert.strictEqual(isValidBmadStoryId('100.99'), true);
131
+ });
132
+ it('returns false for dash notation', () => {
133
+ assert.strictEqual(isValidBmadStoryId('1-1'), false);
134
+ });
135
+ it('returns false for invalid formats', () => {
136
+ assert.strictEqual(isValidBmadStoryId('1'), false);
137
+ assert.strictEqual(isValidBmadStoryId('1.'), false);
138
+ assert.strictEqual(isValidBmadStoryId('.1'), false);
139
+ assert.strictEqual(isValidBmadStoryId('a.b'), false);
140
+ });
141
+ });
142
+ describe('isValidPennyStoryId', () => {
143
+ it('returns true for valid dash notation', () => {
144
+ assert.strictEqual(isValidPennyStoryId('1-1'), true);
145
+ assert.strictEqual(isValidPennyStoryId('32-6'), true);
146
+ assert.strictEqual(isValidPennyStoryId('100-99'), true);
147
+ });
148
+ it('returns false for dot notation', () => {
149
+ assert.strictEqual(isValidPennyStoryId('1.1'), false);
150
+ });
151
+ it('returns false for invalid formats', () => {
152
+ assert.strictEqual(isValidPennyStoryId('1'), false);
153
+ assert.strictEqual(isValidPennyStoryId('1-'), false);
154
+ assert.strictEqual(isValidPennyStoryId('-1'), false);
155
+ });
156
+ });
157
+ });
158
+ // =============================================================================
159
+ // AC4: Status Mapping Tests
160
+ // =============================================================================
161
+ describe('AC4: Status Mapping', () => {
162
+ describe('mapBmadToPennyStatus', () => {
163
+ it('maps ready-for-dev to backlog', () => {
164
+ assert.strictEqual(mapBmadToPennyStatus('ready-for-dev'), 'backlog');
165
+ });
166
+ it('maps in-progress to in_progress', () => {
167
+ assert.strictEqual(mapBmadToPennyStatus('in-progress'), 'in_progress');
168
+ });
169
+ it('maps review to needs_review', () => {
170
+ assert.strictEqual(mapBmadToPennyStatus('review'), 'needs_review');
171
+ });
172
+ it('maps done to done', () => {
173
+ assert.strictEqual(mapBmadToPennyStatus('done'), 'done');
174
+ });
175
+ it('maps blocked to backlog', () => {
176
+ assert.strictEqual(mapBmadToPennyStatus('blocked'), 'backlog');
177
+ });
178
+ });
179
+ describe('mapPennyToBmadStatus', () => {
180
+ it('maps backlog to ready-for-dev', () => {
181
+ assert.strictEqual(mapPennyToBmadStatus('backlog'), 'ready-for-dev');
182
+ });
183
+ it('maps in_progress to in-progress', () => {
184
+ assert.strictEqual(mapPennyToBmadStatus('in_progress'), 'in-progress');
185
+ });
186
+ it('maps needs_review to review', () => {
187
+ assert.strictEqual(mapPennyToBmadStatus('needs_review'), 'review');
188
+ });
189
+ it('maps approved to review', () => {
190
+ assert.strictEqual(mapPennyToBmadStatus('approved'), 'review');
191
+ });
192
+ it('maps done to done', () => {
193
+ assert.strictEqual(mapPennyToBmadStatus('done'), 'done');
194
+ });
195
+ });
196
+ describe('round-trip mapping', () => {
197
+ it('backlog round-trips correctly', () => {
198
+ const penny = 'backlog';
199
+ const bmad = mapPennyToBmadStatus(penny);
200
+ const back = mapBmadToPennyStatus(bmad);
201
+ assert.strictEqual(back, penny);
202
+ });
203
+ it('in_progress round-trips correctly', () => {
204
+ const penny = 'in_progress';
205
+ const bmad = mapPennyToBmadStatus(penny);
206
+ const back = mapBmadToPennyStatus(bmad);
207
+ assert.strictEqual(back, penny);
208
+ });
209
+ it('done round-trips correctly', () => {
210
+ const penny = 'done';
211
+ const bmad = mapPennyToBmadStatus(penny);
212
+ const back = mapBmadToPennyStatus(bmad);
213
+ assert.strictEqual(back, penny);
214
+ });
215
+ });
216
+ });
217
+ // =============================================================================
218
+ // AC1: Parse BMAD Sprint Status Tests
219
+ // =============================================================================
220
+ describe('AC1: parseBmadSprintStatus', () => {
221
+ it('parses valid BMAD sprint status YAML', () => {
222
+ const result = parseBmadSprintStatus(VALID_BMAD_YAML);
223
+ assert.strictEqual(result.success, true);
224
+ assert.ok(result.data);
225
+ assert.strictEqual(result.data.sprint.number, 10);
226
+ assert.strictEqual(result.data.sprint.goal, 'Complete user authentication');
227
+ assert.strictEqual(result.data.stories.length, 3);
228
+ });
229
+ it('parses story fields correctly', () => {
230
+ const result = parseBmadSprintStatus(VALID_BMAD_YAML);
231
+ assert.ok(result.data);
232
+ const story = result.data.stories[0];
233
+ assert.strictEqual(story.id, '1.1');
234
+ assert.strictEqual(story.title, 'Email/Password Login');
235
+ assert.strictEqual(story.epic, 'User Authentication');
236
+ assert.strictEqual(story.status, 'done');
237
+ assert.strictEqual(story.assignee, 'Alice Chen');
238
+ assert.strictEqual(story.points, 5);
239
+ assert.strictEqual(story.priority, 'P0');
240
+ assert.strictEqual(story.started, '2024-01-15');
241
+ assert.strictEqual(story.completed, '2024-01-17');
242
+ });
243
+ it('parses metrics correctly', () => {
244
+ const result = parseBmadSprintStatus(VALID_BMAD_YAML);
245
+ assert.ok(result.data);
246
+ assert.strictEqual(result.data.metrics.total_points, 16);
247
+ assert.strictEqual(result.data.metrics.completed_points, 5);
248
+ assert.strictEqual(result.data.metrics.in_progress_points, 8);
249
+ });
250
+ it('handles minimal valid YAML', () => {
251
+ const result = parseBmadSprintStatus(MINIMAL_BMAD_YAML);
252
+ assert.strictEqual(result.success, true);
253
+ assert.ok(result.data);
254
+ assert.strictEqual(result.data.stories.length, 1);
255
+ });
256
+ it('handles blocked stories with blockers array', () => {
257
+ const result = parseBmadSprintStatus(BLOCKED_STORY_YAML);
258
+ assert.strictEqual(result.success, true);
259
+ assert.ok(result.data);
260
+ const story = result.data.stories[0];
261
+ assert.strictEqual(story.status, 'blocked');
262
+ assert.ok(story.blockers);
263
+ assert.strictEqual(story.blockers.length, 2);
264
+ assert.strictEqual(story.blockers[0], 'Waiting for email service');
265
+ });
266
+ it('returns errors for invalid YAML', () => {
267
+ const result = parseBmadSprintStatus('not: valid: yaml: {{');
268
+ assert.strictEqual(result.success, false);
269
+ assert.ok(result.errors);
270
+ assert.ok(result.errors.some((e) => e.field === 'yaml'));
271
+ });
272
+ it('returns errors for missing sprint section', () => {
273
+ const yaml = `
274
+ stories:
275
+ - id: "1.1"
276
+ title: "Story"
277
+ status: done
278
+ points: 1
279
+ priority: P1
280
+ metrics:
281
+ total_points: 1
282
+ completed_points: 1
283
+ `;
284
+ const result = parseBmadSprintStatus(yaml);
285
+ assert.strictEqual(result.success, false);
286
+ assert.ok(result.errors);
287
+ assert.ok(result.errors.some((e) => e.field === 'sprint'));
288
+ });
289
+ it('returns errors for invalid story ID format', () => {
290
+ const yaml = `
291
+ sprint:
292
+ number: 1
293
+ goal: "Test"
294
+ start_date: 2024-01-01
295
+ end_date: 2024-01-14
296
+ stories:
297
+ - id: "invalid"
298
+ title: "Story"
299
+ status: done
300
+ points: 1
301
+ priority: P1
302
+ metrics:
303
+ total_points: 1
304
+ completed_points: 1
305
+ `;
306
+ const result = parseBmadSprintStatus(yaml);
307
+ assert.strictEqual(result.success, false);
308
+ assert.ok(result.errors);
309
+ assert.ok(result.errors.some((e) => e.message.includes('Invalid BMAD story ID')));
310
+ });
311
+ it('returns errors for invalid status', () => {
312
+ const yaml = `
313
+ sprint:
314
+ number: 1
315
+ goal: "Test"
316
+ start_date: 2024-01-01
317
+ end_date: 2024-01-14
318
+ stories:
319
+ - id: "1.1"
320
+ title: "Story"
321
+ status: invalid-status
322
+ points: 1
323
+ priority: P1
324
+ metrics:
325
+ total_points: 1
326
+ completed_points: 1
327
+ `;
328
+ const result = parseBmadSprintStatus(yaml);
329
+ assert.strictEqual(result.success, false);
330
+ assert.ok(result.errors);
331
+ assert.ok(result.errors.some((e) => e.message.includes('Invalid status')));
332
+ });
333
+ });
334
+ // =============================================================================
335
+ // AC2: Import BMAD to Pennyfarthing Tests
336
+ // =============================================================================
337
+ describe('AC2: Import BMAD to Pennyfarthing', () => {
338
+ describe('convertBmadStoryToPenny', () => {
339
+ it('converts story ID from dot to dash notation', () => {
340
+ const bmad = {
341
+ id: '32.6',
342
+ title: 'Test Story',
343
+ status: 'ready-for-dev',
344
+ points: 2,
345
+ priority: 'P1',
346
+ };
347
+ const penny = convertBmadStoryToPenny(bmad);
348
+ assert.strictEqual(penny.id, '32-6');
349
+ });
350
+ it('maps status correctly', () => {
351
+ const bmad = {
352
+ id: '1.1',
353
+ title: 'Test',
354
+ status: 'in-progress',
355
+ points: 3,
356
+ priority: 'P0',
357
+ };
358
+ const penny = convertBmadStoryToPenny(bmad);
359
+ assert.strictEqual(penny.status, 'in_progress');
360
+ });
361
+ it('preserves optional fields', () => {
362
+ const bmad = {
363
+ id: '1.1',
364
+ title: 'Test',
365
+ status: 'done',
366
+ points: 5,
367
+ priority: 'P0',
368
+ assignee: 'Alice',
369
+ started: '2024-01-15',
370
+ completed: '2024-01-17',
371
+ };
372
+ const penny = convertBmadStoryToPenny(bmad);
373
+ assert.strictEqual(penny.assigned_to, 'Alice');
374
+ assert.strictEqual(penny.started, '2024-01-15');
375
+ assert.strictEqual(penny.completed, '2024-01-17');
376
+ });
377
+ it('converts blocked status with blockers to blocked_reason', () => {
378
+ const bmad = {
379
+ id: '1.3',
380
+ title: 'Blocked Story',
381
+ status: 'blocked',
382
+ points: 3,
383
+ priority: 'P1',
384
+ blockers: ['Reason 1', 'Reason 2'],
385
+ };
386
+ const penny = convertBmadStoryToPenny(bmad);
387
+ assert.strictEqual(penny.status, 'backlog');
388
+ assert.strictEqual(penny.blocked_reason, 'Reason 1; Reason 2');
389
+ });
390
+ });
391
+ describe('importFromBmadStatus', () => {
392
+ it('updates existing stories', () => {
393
+ const bmadStatus = {
394
+ sprint: { number: 10, goal: 'Test', start_date: '2024-01-01', end_date: '2024-01-14' },
395
+ stories: [
396
+ { id: '1.1', title: 'Updated Story', status: 'done', points: 3, priority: 'P1' },
397
+ ],
398
+ metrics: { total_points: 3, completed_points: 3 },
399
+ };
400
+ const existing = [
401
+ { id: '1-1', title: 'Original Story', status: 'in_progress', points: 3, priority: 'P1' },
402
+ ];
403
+ const result = importFromBmadStatus(bmadStatus, existing);
404
+ assert.strictEqual(result.success, true);
405
+ assert.ok(result.updatedStories);
406
+ assert.ok(result.updatedStories.some((u) => u.id === '1-1' && u.field === 'status'));
407
+ });
408
+ it('adds new stories from BMAD', () => {
409
+ const bmadStatus = {
410
+ sprint: { number: 10, goal: 'Test', start_date: '2024-01-01', end_date: '2024-01-14' },
411
+ stories: [
412
+ { id: '2.1', title: 'New Story', status: 'ready-for-dev', points: 2, priority: 'P2' },
413
+ ],
414
+ metrics: { total_points: 2, completed_points: 0 },
415
+ };
416
+ const existing = [];
417
+ const result = importFromBmadStatus(bmadStatus, existing);
418
+ assert.strictEqual(result.success, true);
419
+ assert.ok(result.updatedStories);
420
+ assert.ok(result.updatedStories.some((u) => u.id === '2-1' && u.field === '_new'));
421
+ });
422
+ it('tracks all field changes', () => {
423
+ const bmadStatus = {
424
+ sprint: { number: 10, goal: 'Test', start_date: '2024-01-01', end_date: '2024-01-14' },
425
+ stories: [
426
+ {
427
+ id: '1.1',
428
+ title: 'Story',
429
+ status: 'done',
430
+ points: 3,
431
+ priority: 'P1',
432
+ assignee: 'New Person',
433
+ completed: '2024-01-20',
434
+ },
435
+ ],
436
+ metrics: { total_points: 3, completed_points: 3 },
437
+ };
438
+ const existing = [
439
+ {
440
+ id: '1-1',
441
+ title: 'Story',
442
+ status: 'in_progress',
443
+ points: 3,
444
+ priority: 'P1',
445
+ assigned_to: 'Old Person',
446
+ },
447
+ ];
448
+ const result = importFromBmadStatus(bmadStatus, existing);
449
+ assert.strictEqual(result.success, true);
450
+ assert.ok(result.updatedStories);
451
+ const statusUpdate = result.updatedStories.find((u) => u.field === 'status');
452
+ assert.ok(statusUpdate);
453
+ assert.strictEqual(statusUpdate.oldValue, 'in_progress');
454
+ assert.strictEqual(statusUpdate.newValue, 'done');
455
+ const assigneeUpdate = result.updatedStories.find((u) => u.field === 'assigned_to');
456
+ assert.ok(assigneeUpdate);
457
+ assert.strictEqual(assigneeUpdate.oldValue, 'Old Person');
458
+ assert.strictEqual(assigneeUpdate.newValue, 'New Person');
459
+ });
460
+ });
461
+ });
462
+ // =============================================================================
463
+ // AC3: Export Pennyfarthing to BMAD Tests
464
+ // =============================================================================
465
+ describe('AC3: Export Pennyfarthing to BMAD', () => {
466
+ describe('convertPennyStoryToBmad', () => {
467
+ it('converts story ID from dash to dot notation', () => {
468
+ const penny = {
469
+ id: '32-6',
470
+ title: 'Test Story',
471
+ status: 'backlog',
472
+ points: 2,
473
+ priority: 'P1',
474
+ };
475
+ const bmad = convertPennyStoryToBmad(penny);
476
+ assert.strictEqual(bmad.id, '32.6');
477
+ });
478
+ it('maps status correctly', () => {
479
+ const penny = {
480
+ id: '1-1',
481
+ title: 'Test',
482
+ status: 'in_progress',
483
+ points: 3,
484
+ priority: 'P0',
485
+ };
486
+ const bmad = convertPennyStoryToBmad(penny);
487
+ assert.strictEqual(bmad.status, 'in-progress');
488
+ });
489
+ it('maps approved to review', () => {
490
+ const penny = {
491
+ id: '1-1',
492
+ title: 'Test',
493
+ status: 'approved',
494
+ points: 3,
495
+ priority: 'P0',
496
+ };
497
+ const bmad = convertPennyStoryToBmad(penny);
498
+ assert.strictEqual(bmad.status, 'review');
499
+ });
500
+ it('converts blocked_reason to blockers array and blocked status', () => {
501
+ const penny = {
502
+ id: '1-3',
503
+ title: 'Blocked Story',
504
+ status: 'backlog',
505
+ points: 3,
506
+ priority: 'P1',
507
+ blocked_reason: 'Waiting for dependency',
508
+ };
509
+ const bmad = convertPennyStoryToBmad(penny);
510
+ assert.strictEqual(bmad.status, 'blocked');
511
+ assert.ok(bmad.blockers);
512
+ assert.strictEqual(bmad.blockers[0], 'Waiting for dependency');
513
+ });
514
+ it('preserves optional fields', () => {
515
+ const penny = {
516
+ id: '1-1',
517
+ title: 'Test',
518
+ status: 'done',
519
+ points: 5,
520
+ priority: 'P0',
521
+ assigned_to: 'Alice',
522
+ started: '2024-01-15',
523
+ completed: '2024-01-17',
524
+ };
525
+ const bmad = convertPennyStoryToBmad(penny);
526
+ assert.strictEqual(bmad.assignee, 'Alice');
527
+ assert.strictEqual(bmad.started, '2024-01-15');
528
+ assert.strictEqual(bmad.completed, '2024-01-17');
529
+ });
530
+ });
531
+ describe('exportToSprintStatus', () => {
532
+ it('exports valid YAML', () => {
533
+ const sprintInfo = {
534
+ number: 10,
535
+ goal: 'Test sprint',
536
+ start_date: '2024-01-15',
537
+ end_date: '2024-01-26',
538
+ };
539
+ const stories = [
540
+ { id: '1-1', title: 'Story 1', status: 'done', points: 5, priority: 'P0' },
541
+ { id: '1-2', title: 'Story 2', status: 'in_progress', points: 3, priority: 'P1' },
542
+ ];
543
+ const result = exportToSprintStatus(sprintInfo, stories);
544
+ assert.strictEqual(result.success, true);
545
+ assert.ok(result.yaml);
546
+ assert.ok(result.yaml.includes('number: 10'));
547
+ assert.ok(result.yaml.includes('goal: Test sprint'));
548
+ });
549
+ it('calculates metrics correctly', () => {
550
+ const sprintInfo = {
551
+ number: 10,
552
+ goal: 'Test',
553
+ start_date: '2024-01-15',
554
+ end_date: '2024-01-26',
555
+ };
556
+ const stories = [
557
+ { id: '1-1', title: 'Done', status: 'done', points: 5, priority: 'P0' },
558
+ { id: '1-2', title: 'In Progress', status: 'in_progress', points: 3, priority: 'P1' },
559
+ { id: '1-3', title: 'Backlog', status: 'backlog', points: 2, priority: 'P2' },
560
+ ];
561
+ const result = exportToSprintStatus(sprintInfo, stories);
562
+ assert.strictEqual(result.success, true);
563
+ assert.ok(result.yaml);
564
+ assert.ok(result.yaml.includes('total_points: 10'));
565
+ assert.ok(result.yaml.includes('completed_points: 5'));
566
+ assert.ok(result.yaml.includes('in_progress_points: 3'));
567
+ });
568
+ it('converts story IDs to dot notation', () => {
569
+ const sprintInfo = {
570
+ number: 10,
571
+ goal: 'Test',
572
+ start_date: '2024-01-15',
573
+ end_date: '2024-01-26',
574
+ };
575
+ const stories = [
576
+ { id: '32-6', title: 'Story', status: 'backlog', points: 2, priority: 'P1' },
577
+ ];
578
+ const result = exportToSprintStatus(sprintInfo, stories);
579
+ assert.strictEqual(result.success, true);
580
+ assert.ok(result.yaml);
581
+ assert.ok(result.yaml.includes('id: "32.6"') || result.yaml.includes("id: '32.6'") || result.yaml.includes('id: 32.6'));
582
+ });
583
+ it('returns errors for missing sprint info', () => {
584
+ const sprintInfo = {
585
+ number: 10,
586
+ goal: '',
587
+ start_date: '',
588
+ end_date: '',
589
+ };
590
+ const result = exportToSprintStatus(sprintInfo, []);
591
+ assert.strictEqual(result.success, false);
592
+ assert.ok(result.errors);
593
+ assert.ok(result.errors.length >= 2);
594
+ });
595
+ });
596
+ });
597
+ // =============================================================================
598
+ // AC5: Conflict Detection Tests
599
+ // =============================================================================
600
+ describe('AC5: Conflict Detection', () => {
601
+ it('detects no conflicts when statuses match mapping', () => {
602
+ const bmadStories = [
603
+ { id: '1.1', title: 'Story', status: 'in-progress', points: 3, priority: 'P1' },
604
+ ];
605
+ const pennyStories = [
606
+ { id: '1-1', title: 'Story', status: 'in_progress', points: 3, priority: 'P1' },
607
+ ];
608
+ const result = detectConflicts(bmadStories, pennyStories);
609
+ assert.strictEqual(result.hasConflicts, false);
610
+ assert.strictEqual(result.conflicts.length, 0);
611
+ });
612
+ it('detects status conflicts', () => {
613
+ const bmadStories = [
614
+ { id: '1.1', title: 'Story', status: 'done', points: 3, priority: 'P1' },
615
+ ];
616
+ const pennyStories = [
617
+ { id: '1-1', title: 'Story', status: 'in_progress', points: 3, priority: 'P1' },
618
+ ];
619
+ const result = detectConflicts(bmadStories, pennyStories);
620
+ assert.strictEqual(result.hasConflicts, true);
621
+ assert.strictEqual(result.conflicts.length, 1);
622
+ assert.strictEqual(result.conflicts[0].field, 'status');
623
+ assert.strictEqual(result.conflicts[0].bmadValue, 'done');
624
+ assert.strictEqual(result.conflicts[0].pennyValue, 'in_progress');
625
+ });
626
+ it('detects assignee conflicts', () => {
627
+ const bmadStories = [
628
+ { id: '1.1', title: 'Story', status: 'in-progress', points: 3, priority: 'P1', assignee: 'Alice' },
629
+ ];
630
+ const pennyStories = [
631
+ { id: '1-1', title: 'Story', status: 'in_progress', points: 3, priority: 'P1', assigned_to: 'Bob' },
632
+ ];
633
+ const result = detectConflicts(bmadStories, pennyStories);
634
+ assert.strictEqual(result.hasConflicts, true);
635
+ assert.ok(result.conflicts.some((c) => c.field === 'assignee'));
636
+ });
637
+ it('detects completion date conflicts', () => {
638
+ const bmadStories = [
639
+ { id: '1.1', title: 'Story', status: 'done', points: 3, priority: 'P1', completed: '2024-01-20' },
640
+ ];
641
+ const pennyStories = [
642
+ { id: '1-1', title: 'Story', status: 'done', points: 3, priority: 'P1', completed: '2024-01-21' },
643
+ ];
644
+ const result = detectConflicts(bmadStories, pennyStories);
645
+ assert.strictEqual(result.hasConflicts, true);
646
+ assert.ok(result.conflicts.some((c) => c.field === 'completed'));
647
+ });
648
+ it('ignores stories only in one system', () => {
649
+ const bmadStories = [
650
+ { id: '1.1', title: 'BMAD Only', status: 'ready-for-dev', points: 3, priority: 'P1' },
651
+ ];
652
+ const pennyStories = [
653
+ { id: '2-1', title: 'Penny Only', status: 'backlog', points: 2, priority: 'P2' },
654
+ ];
655
+ const result = detectConflicts(bmadStories, pennyStories);
656
+ assert.strictEqual(result.hasConflicts, false);
657
+ });
658
+ it('detects multiple conflicts across stories', () => {
659
+ const bmadStories = [
660
+ { id: '1.1', title: 'Story 1', status: 'done', points: 3, priority: 'P1' },
661
+ { id: '1.2', title: 'Story 2', status: 'review', points: 2, priority: 'P1', assignee: 'Alice' },
662
+ ];
663
+ const pennyStories = [
664
+ { id: '1-1', title: 'Story 1', status: 'in_progress', points: 3, priority: 'P1' },
665
+ { id: '1-2', title: 'Story 2', status: 'in_progress', points: 2, priority: 'P1', assigned_to: 'Bob' },
666
+ ];
667
+ const result = detectConflicts(bmadStories, pennyStories);
668
+ assert.strictEqual(result.hasConflicts, true);
669
+ assert.ok(result.conflicts.length >= 2);
670
+ });
671
+ });
672
+ // =============================================================================
673
+ // Round-Trip Tests
674
+ // =============================================================================
675
+ describe('Round-trip: Export → Parse', () => {
676
+ it('exported YAML can be parsed back', () => {
677
+ const sprintInfo = {
678
+ number: 10,
679
+ goal: 'Test sprint',
680
+ start_date: '2024-01-15',
681
+ end_date: '2024-01-26',
682
+ };
683
+ const stories = [
684
+ { id: '1-1', title: 'Story One', status: 'done', points: 5, priority: 'P0', assigned_to: 'Alice', completed: '2024-01-17' },
685
+ { id: '1-2', title: 'Story Two', status: 'in_progress', points: 3, priority: 'P1', assigned_to: 'Bob', started: '2024-01-18' },
686
+ ];
687
+ const exportResult = exportToSprintStatus(sprintInfo, stories);
688
+ assert.strictEqual(exportResult.success, true);
689
+ assert.ok(exportResult.yaml);
690
+ const parseResult = parseBmadSprintStatus(exportResult.yaml);
691
+ assert.strictEqual(parseResult.success, true);
692
+ assert.ok(parseResult.data);
693
+ // Verify data integrity
694
+ assert.strictEqual(parseResult.data.sprint.number, 10);
695
+ assert.strictEqual(parseResult.data.stories.length, 2);
696
+ assert.strictEqual(parseResult.data.stories[0].id, '1.1');
697
+ assert.strictEqual(parseResult.data.stories[0].status, 'done');
698
+ assert.strictEqual(parseResult.data.metrics.total_points, 8);
699
+ assert.strictEqual(parseResult.data.metrics.completed_points, 5);
700
+ });
701
+ });
702
+ //# sourceMappingURL=status-sync.test.js.map