@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,393 @@
1
+ import { readFileSync, readdirSync, existsSync, writeFileSync, mkdirSync } from 'fs';
2
+ import { join, dirname, basename } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { homedir } from 'os';
5
+ import YAML from 'yaml';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ /**
9
+ * Get the path to the themes directory
10
+ */
11
+ export function getThemesDir() {
12
+ // In installed package: dist/cli/utils/themes.ts -> need to go to pennyfarthing-dist
13
+ // Try relative to package root first
14
+ const packageRoot = join(__dirname, '../../..');
15
+ const distThemes = join(packageRoot, 'pennyfarthing-dist/personas/themes');
16
+ if (existsSync(distThemes)) {
17
+ return distThemes;
18
+ }
19
+ // Fallback: try from project's .claude/pennyfarthing symlink
20
+ const projectRoot = process.cwd();
21
+ const claudeThemes = join(projectRoot, '.claude/pennyfarthing/personas/themes');
22
+ if (existsSync(claudeThemes)) {
23
+ return claudeThemes;
24
+ }
25
+ throw new Error('Could not find themes directory');
26
+ }
27
+ /**
28
+ * Get the project-level custom themes directory
29
+ */
30
+ export function getProjectCustomThemesDir(projectRoot) {
31
+ return join(projectRoot, '.claude/pennyfarthing/themes');
32
+ }
33
+ /**
34
+ * Get the user-level custom themes directory
35
+ */
36
+ export function getUserCustomThemesDir() {
37
+ return join(homedir(), '.claude/pennyfarthing/themes');
38
+ }
39
+ /**
40
+ * Get the path to the .pennyfarthing local config (preferred for dogfooding)
41
+ */
42
+ export function getPennyfarthingConfigPath(projectRoot) {
43
+ return join(projectRoot, '.pennyfarthing/config.local.yaml');
44
+ }
45
+ /**
46
+ * Get the current theme from config files
47
+ * Priority: .pennyfarthing/config.local.yaml > .claude/persona-config.local.yaml > .claude/persona-config.yaml
48
+ */
49
+ export function getCurrentTheme(projectRoot) {
50
+ const root = projectRoot || process.cwd();
51
+ // Priority 1: .pennyfarthing/config.local.yaml (dogfooding/agent-writable)
52
+ const pennyfarthingConfigPath = getPennyfarthingConfigPath(root);
53
+ if (existsSync(pennyfarthingConfigPath)) {
54
+ try {
55
+ const content = readFileSync(pennyfarthingConfigPath, 'utf8');
56
+ const config = YAML.parse(content);
57
+ if (config?.theme) {
58
+ return config.theme;
59
+ }
60
+ }
61
+ catch {
62
+ // Fall through to next option
63
+ }
64
+ }
65
+ // Priority 2: .claude/persona-config.local.yaml (legacy local)
66
+ const localConfigPath = join(root, '.claude/persona-config.local.yaml');
67
+ if (existsSync(localConfigPath)) {
68
+ try {
69
+ const content = readFileSync(localConfigPath, 'utf8');
70
+ const config = YAML.parse(content);
71
+ if (config?.theme) {
72
+ return config.theme;
73
+ }
74
+ }
75
+ catch {
76
+ // Fall through to shared config
77
+ }
78
+ }
79
+ // Priority 3: .claude/persona-config.yaml (project default)
80
+ const sharedConfigPath = join(root, '.claude/persona-config.yaml');
81
+ if (existsSync(sharedConfigPath)) {
82
+ try {
83
+ const content = readFileSync(sharedConfigPath, 'utf8');
84
+ const config = YAML.parse(content);
85
+ return config?.theme || null;
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+ /**
94
+ * Parse a theme YAML file and extract theme info
95
+ */
96
+ export function parseThemeFile(filePath, isCustom = false) {
97
+ try {
98
+ const content = readFileSync(filePath, 'utf8');
99
+ const data = YAML.parse(content);
100
+ if (!data?.theme?.name) {
101
+ return null;
102
+ }
103
+ const id = basename(filePath, '.yaml');
104
+ return {
105
+ id,
106
+ name: data.theme.name,
107
+ description: data.theme.description || '',
108
+ isCustom,
109
+ agents: data.agents || {}
110
+ };
111
+ }
112
+ catch {
113
+ return null;
114
+ }
115
+ }
116
+ /**
117
+ * Load themes from a directory
118
+ */
119
+ function loadThemesFromDir(dir, isCustom) {
120
+ const themes = [];
121
+ if (!existsSync(dir)) {
122
+ return themes;
123
+ }
124
+ const files = readdirSync(dir).filter(f => f.endsWith('.yaml'));
125
+ for (const file of files) {
126
+ const theme = parseThemeFile(join(dir, file), isCustom);
127
+ if (theme) {
128
+ themes.push(theme);
129
+ }
130
+ }
131
+ return themes;
132
+ }
133
+ /**
134
+ * Get all available themes (built-in + custom)
135
+ */
136
+ export function getThemes(projectRoot) {
137
+ const themes = [];
138
+ const seenIds = new Set();
139
+ // 1. Load built-in themes
140
+ try {
141
+ const builtInDir = getThemesDir();
142
+ for (const theme of loadThemesFromDir(builtInDir, false)) {
143
+ if (!seenIds.has(theme.id)) {
144
+ themes.push(theme);
145
+ seenIds.add(theme.id);
146
+ }
147
+ }
148
+ }
149
+ catch {
150
+ // Built-in themes not found - continue with custom themes
151
+ }
152
+ // 2. Load project-level custom themes
153
+ const root = projectRoot || process.cwd();
154
+ const projectDir = getProjectCustomThemesDir(root);
155
+ for (const theme of loadThemesFromDir(projectDir, true)) {
156
+ if (!seenIds.has(theme.id)) {
157
+ themes.push(theme);
158
+ seenIds.add(theme.id);
159
+ }
160
+ }
161
+ // 3. Load user-level custom themes
162
+ const userDir = getUserCustomThemesDir();
163
+ for (const theme of loadThemesFromDir(userDir, true)) {
164
+ if (!seenIds.has(theme.id)) {
165
+ themes.push(theme);
166
+ seenIds.add(theme.id);
167
+ }
168
+ }
169
+ // Sort alphabetically by name
170
+ return themes.sort((a, b) => a.name.localeCompare(b.name));
171
+ }
172
+ /**
173
+ * Get sample agent characters for display
174
+ */
175
+ export function getAgentSamples(theme) {
176
+ const samples = [];
177
+ if (theme.agents.sm?.character) {
178
+ samples.push(`SM: ${theme.agents.sm.character}`);
179
+ }
180
+ if (theme.agents.tea?.character) {
181
+ samples.push(`TEA: ${theme.agents.tea.character}`);
182
+ }
183
+ if (theme.agents.dev?.character) {
184
+ samples.push(`Dev: ${theme.agents.dev.character}`);
185
+ }
186
+ return samples.join(' | ');
187
+ }
188
+ /**
189
+ * Set the active theme
190
+ * By default writes to .pennyfarthing/config.local.yaml (agent-writable, dogfooding-friendly)
191
+ * Use { legacy: true } to write to .claude/persona-config.local.yaml
192
+ * Use { global: true } to write to .claude/persona-config.yaml (project default)
193
+ * Returns the ThemeInfo if successful, throws if theme not found
194
+ */
195
+ export function setTheme(themeName, projectRoot, options = {}) {
196
+ const themes = getThemes(projectRoot);
197
+ const theme = themes.find(t => t.id === themeName);
198
+ if (!theme) {
199
+ const available = themes.map(t => t.id).join(', ');
200
+ throw new Error(`Theme '${themeName}' not found. Available themes: ${available}`);
201
+ }
202
+ let configPath;
203
+ let header;
204
+ if (options.global) {
205
+ // Project default - shared with team
206
+ configPath = join(projectRoot, '.claude/persona-config.yaml');
207
+ header = '# Pennyfarthing Persona Configuration (Project Default)\n\n';
208
+ }
209
+ else if (options.legacy) {
210
+ // Legacy local config location
211
+ configPath = join(projectRoot, '.claude/persona-config.local.yaml');
212
+ header = '# Pennyfarthing Persona Configuration (Local User Preference)\n# This file is gitignored - your personal theme choice\n\n';
213
+ }
214
+ else {
215
+ // Default: .pennyfarthing/ directory (agent-writable, dogfooding-friendly)
216
+ configPath = getPennyfarthingConfigPath(projectRoot);
217
+ header = '# Pennyfarthing Local Configuration\n# This file is gitignored - your personal preferences\n# Agents can write to this file during dogfooding\n\n';
218
+ }
219
+ // Ensure parent directory exists
220
+ const configDir = dirname(configPath);
221
+ if (!existsSync(configDir)) {
222
+ mkdirSync(configDir, { recursive: true });
223
+ }
224
+ // Read existing config or create new one
225
+ let config = {};
226
+ if (existsSync(configPath)) {
227
+ try {
228
+ const content = readFileSync(configPath, 'utf8');
229
+ config = YAML.parse(content) || {};
230
+ }
231
+ catch {
232
+ // If parse fails, start fresh
233
+ config = {};
234
+ }
235
+ }
236
+ // Update theme
237
+ config.theme = themeName;
238
+ // Write back with comment header
239
+ const yamlContent = YAML.stringify(config);
240
+ writeFileSync(configPath, header + yamlContent, 'utf8');
241
+ return theme;
242
+ }
243
+ /**
244
+ * Validate a theme name
245
+ */
246
+ export function validateThemeName(name) {
247
+ if (!name) {
248
+ return { valid: false, error: 'Theme name is required' };
249
+ }
250
+ if (name !== name.toLowerCase()) {
251
+ return { valid: false, error: 'Theme name must be lowercase' };
252
+ }
253
+ if (/\s/.test(name)) {
254
+ return { valid: false, error: 'Theme name cannot contain spaces (use hyphens instead)' };
255
+ }
256
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
257
+ return { valid: false, error: 'Theme name must start with a letter and contain only lowercase letters, numbers, and hyphens' };
258
+ }
259
+ return { valid: true };
260
+ }
261
+ /**
262
+ * Get the path to a theme file (built-in or custom)
263
+ */
264
+ export function getThemeFilePath(themeId) {
265
+ // Check built-in themes first
266
+ try {
267
+ const builtInPath = join(getThemesDir(), `${themeId}.yaml`);
268
+ if (existsSync(builtInPath)) {
269
+ return builtInPath;
270
+ }
271
+ }
272
+ catch {
273
+ // Built-in dir not found
274
+ }
275
+ // Check project-level
276
+ const projectPath = join(getProjectCustomThemesDir(process.cwd()), `${themeId}.yaml`);
277
+ if (existsSync(projectPath)) {
278
+ return projectPath;
279
+ }
280
+ // Check user-level
281
+ const userPath = join(getUserCustomThemesDir(), `${themeId}.yaml`);
282
+ if (existsSync(userPath)) {
283
+ return userPath;
284
+ }
285
+ return null;
286
+ }
287
+ /**
288
+ * Create a new custom theme
289
+ * Returns the path to the created theme file
290
+ */
291
+ export function createTheme(themeName, projectRoot, options = {}) {
292
+ const { baseTheme = 'minimalist', userLevel = false } = options;
293
+ // Validate theme name
294
+ const validation = validateThemeName(themeName);
295
+ if (!validation.valid) {
296
+ throw new Error(validation.error);
297
+ }
298
+ // Check if theme already exists
299
+ const existingThemes = getThemes(projectRoot);
300
+ if (existingThemes.some(t => t.id === themeName)) {
301
+ throw new Error(`Theme '${themeName}' already exists`);
302
+ }
303
+ // Find base theme file
304
+ const baseThemePath = getThemeFilePath(baseTheme);
305
+ if (!baseThemePath) {
306
+ const available = existingThemes.map(t => t.id).join(', ');
307
+ throw new Error(`Base theme '${baseTheme}' not found. Available themes: ${available}`);
308
+ }
309
+ // Determine target directory
310
+ const targetDir = userLevel
311
+ ? getUserCustomThemesDir()
312
+ : getProjectCustomThemesDir(projectRoot);
313
+ // Create directory if needed
314
+ if (!existsSync(targetDir)) {
315
+ mkdirSync(targetDir, { recursive: true });
316
+ }
317
+ // Read base theme content
318
+ const baseContent = readFileSync(baseThemePath, 'utf8');
319
+ const baseData = YAML.parse(baseContent);
320
+ // Update theme metadata
321
+ baseData.theme.name = themeName.charAt(0).toUpperCase() + themeName.slice(1).replace(/-/g, ' ');
322
+ baseData.theme.description = `Custom theme based on ${baseTheme}`;
323
+ // Write new theme file
324
+ const targetPath = join(targetDir, `${themeName}.yaml`);
325
+ const header = `# Custom Theme: ${themeName}\n# Based on: ${baseTheme}\n# Edit this file to customize your agent personas\n\n`;
326
+ const yamlContent = YAML.stringify(baseData);
327
+ writeFileSync(targetPath, header + yamlContent, 'utf8');
328
+ return targetPath;
329
+ }
330
+ /**
331
+ * All 10 required agent types for a complete theme
332
+ */
333
+ const REQUIRED_AGENTS = [
334
+ 'orchestrator',
335
+ 'sm',
336
+ 'tea',
337
+ 'dev',
338
+ 'reviewer',
339
+ 'architect',
340
+ 'pm',
341
+ 'tech-writer',
342
+ 'ux-designer',
343
+ 'devops'
344
+ ];
345
+ /**
346
+ * Validate a theme object has all required fields and agents
347
+ * Used to validate AI-generated themes before writing to file
348
+ */
349
+ export function validateThemeSchema(themeData) {
350
+ const errors = [];
351
+ // Check if themeData is an object
352
+ if (!themeData || typeof themeData !== 'object') {
353
+ return { valid: false, errors: ['Theme data must be an object'] };
354
+ }
355
+ const data = themeData;
356
+ // Check theme section
357
+ if (!data.theme || typeof data.theme !== 'object') {
358
+ errors.push('Missing theme section');
359
+ }
360
+ else {
361
+ const theme = data.theme;
362
+ if (!theme.name) {
363
+ errors.push('Missing theme.name');
364
+ }
365
+ }
366
+ // Check agents section
367
+ if (!data.agents || typeof data.agents !== 'object') {
368
+ errors.push('Missing agents section');
369
+ return { valid: false, errors };
370
+ }
371
+ const agents = data.agents;
372
+ // Check all required agents are present with required fields
373
+ for (const agentType of REQUIRED_AGENTS) {
374
+ const agent = agents[agentType];
375
+ if (!agent || typeof agent !== 'object') {
376
+ errors.push(`Missing required agent: ${agentType}`);
377
+ continue;
378
+ }
379
+ const agentData = agent;
380
+ // Check required fields for each agent
381
+ if (!agentData.character) {
382
+ errors.push(`Agent ${agentType} missing required field: character`);
383
+ }
384
+ if (!agentData.style) {
385
+ errors.push(`Agent ${agentType} missing required field: style`);
386
+ }
387
+ }
388
+ if (errors.length > 0) {
389
+ return { valid: false, errors };
390
+ }
391
+ return { valid: true };
392
+ }
393
+ //# sourceMappingURL=themes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.js","sourceRoot":"","sources":["../../../src/cli/utils/themes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Tests for BL-1: Store theme preference in local settings
3
+ *
4
+ * These tests verify:
5
+ * - getCurrentTheme() checks local config first, falls back to shared
6
+ * - setTheme() writes to local config by default
7
+ * - setTheme() with global option writes to shared config
8
+ *
9
+ * Run with: npm test
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=themes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.test.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/themes.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Tests for BL-1: Store theme preference in local settings
3
+ *
4
+ * These tests verify:
5
+ * - getCurrentTheme() checks local config first, falls back to shared
6
+ * - setTheme() writes to local config by default
7
+ * - setTheme() with global option writes to shared config
8
+ *
9
+ * Run with: npm test
10
+ */
11
+ import { describe, it, beforeEach, afterEach } from 'node:test';
12
+ import assert from 'node:assert';
13
+ import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync } from 'fs';
14
+ import { join } from 'path';
15
+ import { tmpdir } from 'os';
16
+ import { stringify as yamlStringify, parse as yamlParse } from 'yaml';
17
+ // Import functions to test
18
+ import { getCurrentTheme, setTheme } from './themes.js';
19
+ describe('Theme Local Settings (BL-1)', () => {
20
+ let testDir;
21
+ let claudeDir;
22
+ let themesDir;
23
+ // Minimal valid theme for testing
24
+ const testTheme = {
25
+ theme: { name: 'Test Theme', description: 'Test theme for unit tests' },
26
+ agents: {
27
+ orchestrator: { character: 'Test Orchestrator', style: 'test' },
28
+ sm: { character: 'Test SM', style: 'test' },
29
+ tea: { character: 'Test TEA', style: 'test' },
30
+ dev: { character: 'Test Dev', style: 'test' },
31
+ reviewer: { character: 'Test Reviewer', style: 'test' },
32
+ architect: { character: 'Test Architect', style: 'test' },
33
+ pm: { character: 'Test PM', style: 'test' },
34
+ 'tech-writer': { character: 'Test Writer', style: 'test' },
35
+ 'ux-designer': { character: 'Test UX', style: 'test' },
36
+ devops: { character: 'Test DevOps', style: 'test' }
37
+ }
38
+ };
39
+ beforeEach(() => {
40
+ // Create a temporary project directory for each test
41
+ testDir = join(tmpdir(), `pennyfarthing-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
42
+ claudeDir = join(testDir, '.claude');
43
+ themesDir = join(claudeDir, 'pennyfarthing/themes');
44
+ mkdirSync(themesDir, { recursive: true });
45
+ // Create a test theme so setTheme can find it
46
+ writeFileSync(join(themesDir, 'test-theme.yaml'), yamlStringify(testTheme));
47
+ });
48
+ afterEach(() => {
49
+ // Clean up test directory
50
+ if (existsSync(testDir)) {
51
+ rmSync(testDir, { recursive: true, force: true });
52
+ }
53
+ });
54
+ describe('getCurrentTheme() local precedence', () => {
55
+ it('should return local theme when both local and shared exist', () => {
56
+ // Setup: local config with "star-trek", shared config with "discworld"
57
+ const localConfig = { theme: 'star-trek' };
58
+ const sharedConfig = { theme: 'discworld' };
59
+ writeFileSync(join(claudeDir, 'persona-config.local.yaml'), yamlStringify(localConfig));
60
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
61
+ // Act
62
+ const result = getCurrentTheme(testDir);
63
+ // Assert: should prefer local over shared
64
+ assert.strictEqual(result, 'star-trek', 'Should return local theme when both exist');
65
+ });
66
+ it('should fall back to shared theme when local does not exist', () => {
67
+ // Setup: only shared config
68
+ const sharedConfig = { theme: 'discworld' };
69
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
70
+ // Act
71
+ const result = getCurrentTheme(testDir);
72
+ // Assert: should use shared config
73
+ assert.strictEqual(result, 'discworld', 'Should fall back to shared theme');
74
+ });
75
+ it('should return null when neither local nor shared exist', () => {
76
+ // Setup: no config files (just empty .claude dir)
77
+ // Act
78
+ const result = getCurrentTheme(testDir);
79
+ // Assert
80
+ assert.strictEqual(result, null, 'Should return null when no config exists');
81
+ });
82
+ it('should prefer local even when local theme is different', () => {
83
+ // Setup: local explicitly set to minimalist, shared is elaborate theme
84
+ const localConfig = { theme: 'minimalist' };
85
+ const sharedConfig = { theme: 'shakespeare' };
86
+ writeFileSync(join(claudeDir, 'persona-config.local.yaml'), yamlStringify(localConfig));
87
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
88
+ // Act
89
+ const result = getCurrentTheme(testDir);
90
+ // Assert
91
+ assert.strictEqual(result, 'minimalist', 'Should always prefer local config');
92
+ });
93
+ });
94
+ describe('setTheme() writes to local config', () => {
95
+ it('should write to local config file by default', () => {
96
+ // Setup: create shared config with a different theme
97
+ const sharedConfig = { theme: 'other-theme' };
98
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
99
+ // Act: set theme using our test theme
100
+ setTheme('test-theme', testDir);
101
+ // Assert: local config should exist with the new theme
102
+ const localPath = join(claudeDir, 'persona-config.local.yaml');
103
+ assert.ok(existsSync(localPath), 'setTheme should write to persona-config.local.yaml');
104
+ const localContent = yamlParse(readFileSync(localPath, 'utf-8'));
105
+ assert.strictEqual(localContent.theme, 'test-theme', 'Local config should have the theme');
106
+ });
107
+ it('should not modify shared config when setting theme locally', () => {
108
+ // Setup: shared config with original theme
109
+ const originalSharedConfig = { theme: 'original-theme' };
110
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(originalSharedConfig));
111
+ // Act: set theme locally
112
+ setTheme('test-theme', testDir);
113
+ // Assert: shared config should be unchanged
114
+ const sharedContent = yamlParse(readFileSync(join(claudeDir, 'persona-config.yaml'), 'utf-8'));
115
+ assert.strictEqual(sharedContent.theme, 'original-theme', 'Shared config should remain unchanged when setting local theme');
116
+ });
117
+ it('should write to shared config when global option is true', () => {
118
+ // Setup: shared config with original theme
119
+ const sharedConfig = { theme: 'original-theme' };
120
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
121
+ // Act: set theme with global option
122
+ setTheme('test-theme', testDir, { global: true });
123
+ // Assert: shared config should be updated
124
+ const sharedContent = yamlParse(readFileSync(join(claudeDir, 'persona-config.yaml'), 'utf-8'));
125
+ assert.strictEqual(sharedContent.theme, 'test-theme', 'Global option should update shared config');
126
+ });
127
+ });
128
+ describe('Theme precedence integration', () => {
129
+ it('should allow multiple users to have different themes', () => {
130
+ // This test simulates the scenario where:
131
+ // - Shared config has team default "discworld"
132
+ // - User A sets local to "star-trek"
133
+ // - getCurrentTheme should return "star-trek" for User A
134
+ // Setup: shared team default
135
+ writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify({ theme: 'discworld' }));
136
+ // User A sets their local preference
137
+ writeFileSync(join(claudeDir, 'persona-config.local.yaml'), yamlStringify({ theme: 'star-trek' }));
138
+ // Assert: User A sees their local theme
139
+ const result = getCurrentTheme(testDir);
140
+ assert.strictEqual(result, 'star-trek', 'User should see their local theme preference');
141
+ });
142
+ });
143
+ });
144
+ //# sourceMappingURL=themes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.test.js","sourceRoot":"","sources":["../../../src/cli/utils/themes.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAChF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAEtE,2BAA2B;AAC3B,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExD,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,IAAI,OAAe,CAAC;IACpB,IAAI,SAAiB,CAAC;IACtB,IAAI,SAAiB,CAAC;IAEtB,kCAAkC;IAClC,MAAM,SAAS,GAAG;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,2BAA2B,EAAE;QACvE,MAAM,EAAE;YACN,YAAY,EAAE,EAAE,SAAS,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE;YAC/D,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE;YAC3C,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;YAC7C,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;YAC7C,QAAQ,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE;YACvD,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE;YACzD,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE;YAC3C,aAAa,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE;YAC1D,aAAa,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE;YACtD,MAAM,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE;SACpD;KACF,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACd,qDAAqD;QACrD,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,sBAAsB,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpG,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACrC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;QACpD,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1C,8CAA8C;QAC9C,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,0BAA0B;QAC1B,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,uEAAuE;YACvE,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YAC3C,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YAE5C,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,EAC5C,aAAa,CAAC,WAAW,CAAC,CAC3B,CAAC;YACF,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,YAAY,CAAC,CAC5B,CAAC;YAEF,MAAM;YACN,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAExC,0CAA0C;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,2CAA2C,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,4BAA4B;YAC5B,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YAE5C,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,YAAY,CAAC,CAC5B,CAAC;YAEF,MAAM;YACN,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAExC,mCAAmC;YACnC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,kCAAkC,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,kDAAkD;YAElD,MAAM;YACN,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAExC,SAAS;YACT,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,0CAA0C,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,uEAAuE;YACvE,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;YAC5C,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAE9C,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,EAC5C,aAAa,CAAC,WAAW,CAAC,CAC3B,CAAC;YACF,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,YAAY,CAAC,CAC5B,CAAC;YAEF,MAAM;YACN,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAExC,SAAS;YACT,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,mCAAmC,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACjD,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,qDAAqD;YACrD,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAC9C,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,YAAY,CAAC,CAC5B,CAAC;YAEF,sCAAsC;YACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YAEhC,uDAAuD;YACvD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC;YAE/D,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,oDAAoD,CAAC,CAAC;YACvF,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;YACjE,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,oCAAoC,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,2CAA2C;YAC3C,MAAM,oBAAoB,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YACzD,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,oBAAoB,CAAC,CACpC,CAAC;YAEF,yBAAyB;YACzB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YAEhC,4CAA4C;YAC5C,MAAM,aAAa,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/F,MAAM,CAAC,WAAW,CAChB,aAAa,CAAC,KAAK,EACnB,gBAAgB,EAChB,gEAAgE,CACjE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YAClE,2CAA2C;YAC3C,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YACjD,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,YAAY,CAAC,CAC5B,CAAC;YAEF,oCAAoC;YACpC,QAAQ,CAAC,YAAY,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAElD,0CAA0C;YAC1C,MAAM,aAAa,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/F,MAAM,CAAC,WAAW,CAChB,aAAa,CAAC,KAAK,EACnB,YAAY,EACZ,2CAA2C,CAC5C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,0CAA0C;YAC1C,+CAA+C;YAC/C,qCAAqC;YACrC,yDAAyD;YAEzD,6BAA6B;YAC7B,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CACtC,CAAC;YAEF,qCAAqC;YACrC,aAAa,CACX,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,EAC5C,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CACtC,CAAC;YAEF,wCAAwC;YACxC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,8CAA8C,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Get the package version from VERSION file or package.json
3
+ */
4
+ export declare function getPackageVersion(): string;
5
+ /**
6
+ * Get the distributable package directory path
7
+ * This contains all files that get installed to target projects
8
+ */
9
+ export declare function getAssetsPath(): string;
10
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/version.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAoC1C;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAgBtC"}
@@ -0,0 +1,63 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = dirname(__filename);
6
+ /**
7
+ * Get the package version from VERSION file or package.json
8
+ */
9
+ export function getPackageVersion() {
10
+ // Try VERSION file first (relative to compiled output location)
11
+ const versionPaths = [
12
+ join(__dirname, '../../../VERSION'), // From dist/cli/utils/
13
+ join(__dirname, '../../VERSION'), // Fallback
14
+ join(process.cwd(), 'VERSION') // If running from package root
15
+ ];
16
+ for (const versionPath of versionPaths) {
17
+ if (existsSync(versionPath)) {
18
+ try {
19
+ return readFileSync(versionPath, 'utf8').trim();
20
+ }
21
+ catch {
22
+ continue;
23
+ }
24
+ }
25
+ }
26
+ // Fallback to package.json
27
+ const packagePaths = [
28
+ join(__dirname, '../../../package.json'),
29
+ join(__dirname, '../../package.json')
30
+ ];
31
+ for (const packagePath of packagePaths) {
32
+ if (existsSync(packagePath)) {
33
+ try {
34
+ const pkg = JSON.parse(readFileSync(packagePath, 'utf8'));
35
+ return pkg.version;
36
+ }
37
+ catch {
38
+ continue;
39
+ }
40
+ }
41
+ }
42
+ return '0.0.0';
43
+ }
44
+ /**
45
+ * Get the distributable package directory path
46
+ * This contains all files that get installed to target projects
47
+ */
48
+ export function getAssetsPath() {
49
+ const searchPaths = [
50
+ join(__dirname, '../../../../../pennyfarthing-dist'), // From packages/core/dist/cli/utils/ to package root
51
+ join(__dirname, '../../../../pennyfarthing-dist'),
52
+ join(__dirname, '../../../pennyfarthing-dist'),
53
+ join(__dirname, '../../pennyfarthing-dist'),
54
+ join(process.cwd(), 'pennyfarthing-dist')
55
+ ];
56
+ for (const searchPath of searchPaths) {
57
+ if (existsSync(searchPath)) {
58
+ return searchPath;
59
+ }
60
+ }
61
+ throw new Error('Package directory not found (looked for pennyfarthing-dist/)');
62
+ }
63
+ //# sourceMappingURL=version.js.map