@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,367 @@
1
+ #!/usr/bin/env zsh
2
+ # Agent session management script
3
+ # Usage: agent-session.sh <action> [agent-name] [session-id]
4
+ # start "agent-name" "session-id" - Register agent session and output persona
5
+ # stop "session-id" - Remove session for given ID
6
+ # stop-all - Remove all agent sessions
7
+ # status - Output for Claude Code statusLine (reads JSON from stdin)
8
+ #
9
+ # Session files stored in .session/agents/<session-id> for multi-session support
10
+
11
+ # Find project root
12
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
13
+ source "$SCRIPT_DIR/utils/find-root.sh"
14
+
15
+ # Agents directory for multi-session support
16
+ AGENTS_DIR="$PROJECT_ROOT/.session/agents"
17
+
18
+ # Check if character_voice preference is enabled
19
+ # Returns 0 (true) if enabled or not set, 1 (false) if explicitly disabled
20
+ is_character_voice_enabled() {
21
+ local prefs_file=""
22
+
23
+ # Check for local prefs first, then default
24
+ if [ -f "$PROJECT_ROOT/.claude/pennyfarthing/preferences.local.yaml" ]; then
25
+ prefs_file="$PROJECT_ROOT/.claude/pennyfarthing/preferences.local.yaml"
26
+ elif [ -f "$PROJECT_ROOT/.claude/pennyfarthing/preferences.yaml" ]; then
27
+ prefs_file="$PROJECT_ROOT/.claude/pennyfarthing/preferences.yaml"
28
+ else
29
+ # No preferences file = default to enabled
30
+ return 0
31
+ fi
32
+
33
+ # Read character_voice setting (default to true if not set)
34
+ local voice=$(yq '.character_voice' "$prefs_file" 2>/dev/null)
35
+ # If null/empty, default to enabled
36
+ if [ -z "$voice" ] || [ "$voice" = "null" ]; then
37
+ return 0
38
+ fi
39
+ # If explicitly false, return disabled
40
+ if [ "$voice" = "false" ]; then
41
+ return 1
42
+ fi
43
+ return 0
44
+ }
45
+
46
+ # Get agent file path for a session
47
+ get_agent_file() {
48
+ local session_id="$1"
49
+ echo "$AGENTS_DIR/$session_id"
50
+ }
51
+
52
+ # Check if theme version matches current Pennyfarthing version
53
+ # Only warns on major/minor mismatch, not patch
54
+ # Arguments: theme_file, theme_name
55
+ check_theme_version() {
56
+ local theme_file="$1"
57
+ local theme_name="$2"
58
+
59
+ # Only check custom themes (in .claude/pennyfarthing/themes/)
60
+ if [[ ! "$theme_file" == *".claude/pennyfarthing/themes/"* ]]; then
61
+ return 0
62
+ fi
63
+
64
+ # Get theme's pennyfarthing_version
65
+ local theme_version=$(yq '.theme.pennyfarthing_version // ""' "$theme_file" 2>/dev/null)
66
+ if [ -z "$theme_version" ] || [ "$theme_version" = "null" ] || [ "$theme_version" = "" ]; then
67
+ # No version in theme - skip warning (legacy custom theme)
68
+ return 0
69
+ fi
70
+
71
+ # Get current version from VERSION file
72
+ local version_file="$PROJECT_ROOT/VERSION"
73
+ if [ ! -f "$version_file" ]; then
74
+ # No VERSION file - skip warning
75
+ return 0
76
+ fi
77
+ local current_version=$(cat "$version_file" 2>/dev/null | tr -d '[:space:]')
78
+ if [ -z "$current_version" ]; then
79
+ return 0
80
+ fi
81
+
82
+ # Extract major.minor from both versions
83
+ local theme_major_minor=$(echo "$theme_version" | cut -d. -f1,2)
84
+ local current_major_minor=$(echo "$current_version" | cut -d. -f1,2)
85
+
86
+ # Compare major.minor only
87
+ if [ "$theme_major_minor" != "$current_major_minor" ]; then
88
+ echo "" >&2
89
+ echo "Warning: Theme '${theme_name}' was created with Pennyfarthing ${theme_version}" >&2
90
+ echo " Current version: ${current_version} - agent roles may have changed." >&2
91
+ echo " Run '/theme-maker --update ${theme_name}' to review." >&2
92
+ echo "" >&2
93
+ fi
94
+
95
+ return 0
96
+ }
97
+
98
+ # Function to output persona for an agent
99
+ output_persona() {
100
+ local agent_name="$1"
101
+ local config_file=""
102
+ local theme=""
103
+ local theme_file=""
104
+
105
+ # Check for config files in priority order:
106
+ # 1. .pennyfarthing/config.local.yaml (agent-writable, dogfooding-friendly)
107
+ # 2. .claude/persona-config.local.yaml (legacy local)
108
+ # 3. .claude/persona-config.yaml (project default)
109
+ if [ -f "$PROJECT_ROOT/.pennyfarthing/config.local.yaml" ]; then
110
+ config_file="$PROJECT_ROOT/.pennyfarthing/config.local.yaml"
111
+ elif [ -f "$PROJECT_ROOT/.claude/persona-config.local.yaml" ]; then
112
+ config_file="$PROJECT_ROOT/.claude/persona-config.local.yaml"
113
+ elif [ -f "$PROJECT_ROOT/.claude/persona-config.yaml" ]; then
114
+ config_file="$PROJECT_ROOT/.claude/persona-config.yaml"
115
+ else
116
+ echo "<!-- No persona config found -->" >&2
117
+ return 1
118
+ fi
119
+
120
+ # Get theme from config
121
+ theme=$(yq '.theme' "$config_file" 2>/dev/null)
122
+ if [ -z "$theme" ] || [ "$theme" = "null" ]; then
123
+ echo "<!-- No theme configured -->" >&2
124
+ return 1
125
+ fi
126
+
127
+ # Find theme file (check custom themes first, then built-in locations)
128
+ # Custom themes: .claude/pennyfarthing/themes/
129
+ # Built-in: .pennyfarthing/personas/themes/ and personas/themes/
130
+ if [ -f "$PROJECT_ROOT/.claude/pennyfarthing/themes/${theme}.yaml" ]; then
131
+ theme_file="$PROJECT_ROOT/.claude/pennyfarthing/themes/${theme}.yaml"
132
+ elif [ -f "$PROJECT_ROOT/.pennyfarthing/personas/themes/${theme}.yaml" ]; then
133
+ theme_file="$PROJECT_ROOT/.pennyfarthing/personas/themes/${theme}.yaml"
134
+ elif [ -f "$PROJECT_ROOT/personas/themes/${theme}.yaml" ]; then
135
+ theme_file="$PROJECT_ROOT/personas/themes/${theme}.yaml"
136
+ else
137
+ echo "<!-- Theme file not found: ${theme}.yaml -->" >&2
138
+ return 1
139
+ fi
140
+
141
+ # Check theme version compatibility (warns on major/minor mismatch)
142
+ check_theme_version "$theme_file" "$theme"
143
+
144
+ # Extract agent persona
145
+ local persona=$(yq ".agents.${agent_name}" "$theme_file" 2>/dev/null)
146
+ if [ -z "$persona" ] || [ "$persona" = "null" ]; then
147
+ echo "<!-- No persona found for agent: ${agent_name} -->" >&2
148
+ return 1
149
+ fi
150
+
151
+ # Output persona in a format Claude can use
152
+ echo ""
153
+ echo "<persona agent=\"${agent_name}\" theme=\"${theme}\">"
154
+ echo "Character: $(yq ".agents.${agent_name}.character" "$theme_file")"
155
+ echo "Style: $(yq ".agents.${agent_name}.style" "$theme_file")"
156
+ echo "Role: $(yq ".agents.${agent_name}.role" "$theme_file")"
157
+
158
+ # Optional fields
159
+ local trait=$(yq ".agents.${agent_name}.trait // \"\"" "$theme_file")
160
+ [ -n "$trait" ] && [ "$trait" != "null" ] && [ "$trait" != "" ] && echo "Trait: $trait"
161
+
162
+ local quirk=$(yq ".agents.${agent_name}.quirk // \"\"" "$theme_file")
163
+ [ -n "$quirk" ] && [ "$quirk" != "null" ] && [ "$quirk" != "" ] && echo "Quirk: $quirk"
164
+
165
+ local motto=$(yq ".agents.${agent_name}.motto // \"\"" "$theme_file")
166
+ [ -n "$motto" ] && [ "$motto" != "null" ] && [ "$motto" != "" ] && echo "Motto: $motto"
167
+
168
+ local quote=$(yq ".agents.${agent_name}.quote // \"\"" "$theme_file")
169
+ [ -n "$quote" ] && [ "$quote" != "null" ] && [ "$quote" != "" ] && echo "Quote: $quote"
170
+
171
+ # Helper info
172
+ local helper_name=$(yq ".agents.${agent_name}.helper.name // \"\"" "$theme_file")
173
+ local helper_style=$(yq ".agents.${agent_name}.helper.style // \"\"" "$theme_file")
174
+ if [ -n "$helper_name" ] && [ "$helper_name" != "null" ] && [ "$helper_name" != "" ]; then
175
+ echo "Helper: ${helper_name} - ${helper_style}"
176
+ fi
177
+
178
+ echo "</persona>"
179
+
180
+ # Output portrait path if available (for Claude to read with Read tool)
181
+ local portrait_path=$(node "$PROJECT_ROOT/scripts/resolve-portrait.mjs" "$theme" "$agent_name" 2>/dev/null)
182
+ if [ -n "$portrait_path" ] && [ -f "$portrait_path" ]; then
183
+ echo ""
184
+ echo "<portrait>$portrait_path</portrait>"
185
+ fi
186
+
187
+ # Output user title if defined
188
+ local user_title=$(yq ".theme.user_title // \"\"" "$theme_file" 2>/dev/null)
189
+ if [ -n "$user_title" ] && [ "$user_title" != "null" ] && [ "$user_title" != "" ]; then
190
+ echo ""
191
+ echo "<user-title>Address the user as: ${user_title}</user-title>"
192
+ fi
193
+
194
+ # Output crew manifest so agents know other characters
195
+ echo ""
196
+ echo "<crew theme=\"${theme}\">"
197
+ echo "When handing off to other agents, address them by character name:"
198
+ for role in sm tea dev reviewer architect pm tech-writer ux-designer devops orchestrator; do
199
+ local char=$(yq ".agents.${role}.character // \"\"" "$theme_file" 2>/dev/null)
200
+ if [ -n "$char" ] && [ "$char" != "null" ] && [ "$char" != "" ]; then
201
+ printf " %-12s %s\n" "${role}:" "$char"
202
+ fi
203
+ done
204
+ echo "</crew>"
205
+ }
206
+
207
+ case "$1" in
208
+ start)
209
+ if [ -z "$2" ]; then
210
+ echo "Usage: agent-session.sh start \"agent-name\" [session-id]" >&2
211
+ exit 1
212
+ fi
213
+ # Use provided session ID, fall back to SESSION_ID env var, then generate one
214
+ session_id="${3:-$SESSION_ID}"
215
+ if [ -z "$session_id" ]; then
216
+ # Generate a session ID if not provided (for fresh sessions)
217
+ session_id=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || date +%s)
218
+ fi
219
+ mkdir -p "$AGENTS_DIR"
220
+
221
+ # Clean up old session files (older than 7 days) to prevent accumulation
222
+ find "$AGENTS_DIR" -type f -mtime +7 -delete 2>/dev/null || true
223
+
224
+ AGENT_FILE=$(get_agent_file "$session_id")
225
+ echo "$2" > "$AGENT_FILE"
226
+ echo "Session: $session_id -> $2"
227
+
228
+ # Output persona on start (unless character_voice is disabled)
229
+ if is_character_voice_enabled; then
230
+ output_persona "$2"
231
+ fi
232
+
233
+ # Auto-prime context after persona (reduces cold-start overhead)
234
+ # Pass agent name so prime can load agent-specific sidecar
235
+ if [[ -f "$PROJECT_ROOT/.pennyfarthing/scripts/prime.sh" ]]; then
236
+ "$PROJECT_ROOT/.pennyfarthing/scripts/prime.sh" --quiet --agent "$2"
237
+ fi
238
+ ;;
239
+ stop)
240
+ # Use provided session ID, fall back to SESSION_ID env var
241
+ session_id="${2:-$SESSION_ID}"
242
+ if [ -z "$session_id" ]; then
243
+ echo "Usage: agent-session.sh stop [session-id]" >&2
244
+ exit 1
245
+ fi
246
+
247
+ # Get current agent for this session
248
+ AGENT_FILE=$(get_agent_file "$session_id")
249
+ CURRENT_AGENT=""
250
+ if [ -f "$AGENT_FILE" ]; then
251
+ CURRENT_AGENT=$(cat "$AGENT_FILE")
252
+ fi
253
+
254
+ # Validate handoff was spawned (Story 31-16: Enforce handoff subagent spawning)
255
+ # Only check for agents that require handoff (tea, dev, reviewer)
256
+ if [[ "$CURRENT_AGENT" =~ ^(tea|dev|reviewer)$ ]]; then
257
+ # Find active session file
258
+ SESSION_DIR="$PROJECT_ROOT/.session"
259
+ ACTIVE_SESSION=$(find "$SESSION_DIR" -maxdepth 1 -name "*-session.md" -type f ! -name "context-*" 2>/dev/null | head -1)
260
+
261
+ if [ -n "$ACTIVE_SESSION" ] && [ -f "$ACTIVE_SESSION" ]; then
262
+ # Map agent to expected assessment section
263
+ case "$CURRENT_AGENT" in
264
+ tea) EXPECTED_SECTION="TEA Assessment" ;;
265
+ dev) EXPECTED_SECTION="Dev Assessment" ;;
266
+ reviewer) EXPECTED_SECTION="Reviewer Assessment" ;;
267
+ esac
268
+
269
+ # Check if assessment exists
270
+ HAS_ASSESSMENT=$(grep -q "## $EXPECTED_SECTION" "$ACTIVE_SESSION" 2>/dev/null && echo "yes" || echo "no")
271
+
272
+ # Check if handoff was recorded in Handoff History table
273
+ # Table format: | From | To | Phase | Gate | Timestamp |
274
+ # Agent must appear in "From" column (first data column) to indicate they completed handoff
275
+ HAS_HANDOFF="no"
276
+
277
+ # Check for agent in "From" column (starts with "| agent |")
278
+ # Case-insensitive match for the agent name at start of row
279
+ if grep -Ei "^\| *$CURRENT_AGENT *\|" "$ACTIVE_SESSION" 2>/dev/null; then
280
+ HAS_HANDOFF="yes"
281
+ fi
282
+
283
+ # Also check for CYCLIST:HANDOFF marker (generic-handoff output)
284
+ if [ "$HAS_HANDOFF" = "no" ] && grep -q "CYCLIST:HANDOFF" "$ACTIVE_SESSION" 2>/dev/null; then
285
+ HAS_HANDOFF="yes"
286
+ fi
287
+
288
+ # Warn if assessment exists but handoff is missing
289
+ if [ "$HAS_ASSESSMENT" = "yes" ] && [ "$HAS_HANDOFF" = "no" ]; then
290
+ echo "" >&2
291
+ echo "WARNING: Handoff subagent was not spawned!" >&2
292
+ echo "" >&2
293
+ echo " Agent: $CURRENT_AGENT" >&2
294
+ echo " Assessment: Found ($EXPECTED_SECTION)" >&2
295
+ echo " Handoff: NOT FOUND" >&2
296
+ echo "" >&2
297
+ echo " You MUST spawn generic-handoff before stopping:" >&2
298
+ echo "" >&2
299
+ echo " Task tool:" >&2
300
+ echo " subagent_type: \"generic-handoff\"" >&2
301
+ echo " prompt: |" >&2
302
+ echo " STORY_ID: {story-id}" >&2
303
+ echo " WORKFLOW: {workflow}" >&2
304
+ echo " CURRENT_PHASE: {phase}" >&2
305
+ echo " ..." >&2
306
+ echo "" >&2
307
+ echo " Session: $(basename "$ACTIVE_SESSION")" >&2
308
+ echo "" >&2
309
+ # Exit non-zero to signal incomplete handoff
310
+ exit 1
311
+ fi
312
+ fi
313
+ fi
314
+
315
+ # Clear the agent file for this session
316
+ rm -f "$AGENT_FILE" 2>/dev/null
317
+ echo "Agent session closed: $session_id"
318
+ ;;
319
+ stop-all)
320
+ rm -rf "$AGENTS_DIR" 2>/dev/null
321
+ echo "All agent sessions closed."
322
+ ;;
323
+ status)
324
+ # Read JSON from stdin (Claude Code statusLine passes context)
325
+ input=$(cat)
326
+
327
+ # Get session ID from input
328
+ session_id=""
329
+ if command -v jq &>/dev/null && [ -n "$input" ]; then
330
+ session_id=$(echo "$input" | jq -r '.session_id // empty' 2>/dev/null)
331
+ fi
332
+
333
+ # Get agent name for this session
334
+ if [ -n "$session_id" ]; then
335
+ AGENT_FILE=$(get_agent_file "$session_id")
336
+ if [ -f "$AGENT_FILE" ]; then
337
+ AGENT=$(cat "$AGENT_FILE")
338
+ else
339
+ AGENT=""
340
+ fi
341
+ else
342
+ AGENT=""
343
+ fi
344
+
345
+ # Output just the agent name (statusline.sh handles the rest)
346
+ echo "$AGENT"
347
+ ;;
348
+ list)
349
+ # List all active agent sessions
350
+ if [ -d "$AGENTS_DIR" ]; then
351
+ for f in "$AGENTS_DIR"/*; do
352
+ [ -f "$f" ] && echo "$(basename "$f"): $(cat "$f")"
353
+ done
354
+ else
355
+ echo "No active sessions"
356
+ fi
357
+ ;;
358
+ *)
359
+ echo "Usage: agent-session.sh <start|stop|stop-all|status|list> [args]" >&2
360
+ echo " start \"agent\" \"session-id\" - Register agent for session" >&2
361
+ echo " stop \"session-id\" - Remove agent for session" >&2
362
+ echo " stop-all - Remove all agent sessions" >&2
363
+ echo " status - Get agent for session (reads JSON stdin)" >&2
364
+ echo " list - List all active sessions" >&2
365
+ exit 1
366
+ ;;
367
+ esac
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env zsh
2
+ # check-context.sh - Check current Claude Code context usage
3
+ # Returns: percentage and recommendation for handoff
4
+ #
5
+ # Usage:
6
+ # ./check-context.sh # Output env vars (most recent transcript)
7
+ # ./check-context.sh --human # Human-readable output
8
+ # ./check-context.sh --session <id> # Check specific session transcript
9
+ # SESSION_ID=<id> ./check-context.sh # Alternative: session via env var
10
+ # eval $(./check-context.sh) # Load vars into shell
11
+
12
+ # Parse command line arguments
13
+ HUMAN_MODE=false
14
+ while [[ $# -gt 0 ]]; do
15
+ case "$1" in
16
+ --human)
17
+ HUMAN_MODE=true
18
+ shift
19
+ ;;
20
+ --session)
21
+ SESSION_ID="$2"
22
+ shift 2
23
+ ;;
24
+ *)
25
+ shift
26
+ ;;
27
+ esac
28
+ done
29
+
30
+ # Derive Claude project path from current directory
31
+ # Claude Code stores transcripts at ~/.claude/projects/<path-with-dashes>
32
+ # The path format is: -Users-name-Projects-project (leading dash, all slashes become dashes)
33
+ PROJECT_DIR="${PROJECT_ROOT:-$(pwd)}"
34
+ CLAUDE_PROJECT_PATH="$HOME/.claude/projects/$(echo "$PROJECT_DIR" | tr '/' '-')"
35
+
36
+ # Default thresholds (can be overridden by settings.local.json)
37
+ DEFAULT_IMMINENT_THRESHOLD=65
38
+ DEFAULT_WARNING_THRESHOLD=60
39
+ DEFAULT_CRITICAL_THRESHOLD=85
40
+ DEFAULT_MAX_TOKENS=200000
41
+
42
+ # Load thresholds from .pennyfarthing/config.local.yaml (preferred) or settings.local.json (fallback)
43
+ PENNYFARTHING_CONFIG="${CLAUDE_PROJECT_DIR:-$PROJECT_DIR}/.pennyfarthing/config.local.yaml"
44
+ SETTINGS_FILE="${CLAUDE_PROJECT_DIR:-$PROJECT_DIR}/.claude/settings.local.json"
45
+ CONFIG=$(python3 -c "
46
+ import json
47
+ import sys
48
+
49
+ imminent_threshold = $DEFAULT_IMMINENT_THRESHOLD
50
+ warning_threshold = $DEFAULT_WARNING_THRESHOLD
51
+ critical_threshold = $DEFAULT_CRITICAL_THRESHOLD
52
+ max_tokens = $DEFAULT_MAX_TOKENS
53
+
54
+ # First try .pennyfarthing/config.local.yaml (preferred location)
55
+ try:
56
+ import yaml
57
+ with open('$PENNYFARTHING_CONFIG', 'r') as f:
58
+ config = yaml.safe_load(f)
59
+ if config and 'context_budget' in config:
60
+ cb = config['context_budget']
61
+ imminent_threshold = cb.get('imminent_threshold', imminent_threshold)
62
+ warning_threshold = cb.get('warning_threshold', warning_threshold)
63
+ critical_threshold = cb.get('critical_threshold', critical_threshold)
64
+ max_tokens = cb.get('max_tokens', max_tokens)
65
+ except:
66
+ # Fallback to settings.local.json (legacy location)
67
+ try:
68
+ with open('$SETTINGS_FILE', 'r') as f:
69
+ settings = json.load(f)
70
+ if 'context_budget' in settings:
71
+ cb = settings['context_budget']
72
+ imminent_threshold = cb.get('imminent_threshold', imminent_threshold)
73
+ warning_threshold = cb.get('warning_threshold', warning_threshold)
74
+ critical_threshold = cb.get('critical_threshold', critical_threshold)
75
+ max_tokens = cb.get('max_tokens', max_tokens)
76
+ except:
77
+ pass
78
+
79
+ print(f'IMMINENT_THRESHOLD={imminent_threshold}')
80
+ print(f'WARNING_THRESHOLD={warning_threshold}')
81
+ print(f'CRITICAL_THRESHOLD={critical_threshold}')
82
+ print(f'MAX_TOKENS={max_tokens}')
83
+ " 2>/dev/null)
84
+
85
+ # Apply config or use defaults
86
+ eval "$CONFIG" 2>/dev/null || {
87
+ IMMINENT_THRESHOLD=$DEFAULT_IMMINENT_THRESHOLD
88
+ WARNING_THRESHOLD=$DEFAULT_WARNING_THRESHOLD
89
+ CRITICAL_THRESHOLD=$DEFAULT_CRITICAL_THRESHOLD
90
+ MAX_TOKENS=$DEFAULT_MAX_TOKENS
91
+ }
92
+
93
+ # Find transcript - either specific session or most recent
94
+ if [ -n "$SESSION_ID" ]; then
95
+ # Session-specific: look for transcript with matching session ID
96
+ TRANSCRIPT="$CLAUDE_PROJECT_PATH/${SESSION_ID}.jsonl"
97
+ if [ ! -f "$TRANSCRIPT" ]; then
98
+ if [ "$HUMAN_MODE" = "true" ]; then
99
+ echo "⚠️ Context: unknown (session transcript not found: $SESSION_ID)"
100
+ else
101
+ echo "CONTEXT_ERROR=session_not_found"
102
+ echo "CONTEXT_SESSION=$SESSION_ID"
103
+ fi
104
+ exit 1
105
+ fi
106
+ else
107
+ # Default: find most recent transcript (current session)
108
+ TRANSCRIPT=$(ls -t "$CLAUDE_PROJECT_PATH"/*.jsonl 2>/dev/null | grep -v "agent-" | head -1)
109
+ if [ -z "$TRANSCRIPT" ]; then
110
+ if [ "$HUMAN_MODE" = "true" ]; then
111
+ echo "⚠️ Context: unknown (no transcript found)"
112
+ else
113
+ echo "CONTEXT_ERROR=no_transcript"
114
+ fi
115
+ exit 1
116
+ fi
117
+ fi
118
+
119
+ # Parse last message for usage data
120
+ RESULT=$(python3 -c "
121
+ import sys
122
+ import json
123
+
124
+ warning_threshold = $WARNING_THRESHOLD
125
+ max_tokens = $MAX_TOKENS
126
+
127
+ with open('$TRANSCRIPT', 'r') as f:
128
+ lines = f.readlines()
129
+
130
+ # Find last line with usage data
131
+ for line in reversed(lines):
132
+ try:
133
+ data = json.loads(line.strip())
134
+ if 'message' in data and 'usage' in data['message']:
135
+ usage = data['message']['usage']
136
+ input_t = usage.get('input_tokens', 0)
137
+ cache_read = usage.get('cache_read_input_tokens', 0)
138
+ cache_create = usage.get('cache_creation_input_tokens', 0)
139
+
140
+ total = cache_read + cache_create + input_t
141
+ pct = (total / max_tokens) * 100
142
+
143
+ print(f'CONTEXT_TOKENS={total}')
144
+ print(f'CONTEXT_PERCENT={pct:.0f}')
145
+ # Use configurable warning threshold
146
+ if pct > warning_threshold:
147
+ print('CONTEXT_STATUS=HIGH')
148
+ print('HANDOFF_MODE=auto')
149
+ else:
150
+ print('CONTEXT_STATUS=OK')
151
+ print('HANDOFF_MODE=ask')
152
+ break
153
+ except:
154
+ continue
155
+ " 2>/dev/null)
156
+
157
+ if [ "$HUMAN_MODE" = "true" ]; then
158
+ eval "$RESULT"
159
+ if [ "$CONTEXT_STATUS" = "HIGH" ]; then
160
+ echo "⚠️ Context: ${CONTEXT_PERCENT}% (${CONTEXT_TOKENS} tokens) - AUTO-HANDOFF"
161
+ else
162
+ echo "✅ Context: ${CONTEXT_PERCENT}% (${CONTEXT_TOKENS} tokens) - OK to continue"
163
+ fi
164
+
165
+ # Output warning messages at configurable thresholds
166
+ if [ -n "$CONTEXT_PERCENT" ]; then
167
+ if [ "$CONTEXT_PERCENT" -ge "$CRITICAL_THRESHOLD" ] 2>/dev/null; then
168
+ echo "CONTEXT_WARNING: Critical (${CONTEXT_PERCENT}%) - checkpoint and handoff recommended"
169
+ elif [ "$CONTEXT_PERCENT" -ge "$WARNING_THRESHOLD" ] 2>/dev/null; then
170
+ echo "CONTEXT_WARNING: High (${CONTEXT_PERCENT}%) - consider handoff soon"
171
+ fi
172
+ fi
173
+ else
174
+ echo "$RESULT"
175
+
176
+ # Also output warnings in non-human mode for scripting
177
+ eval "$RESULT" 2>/dev/null || true
178
+ if [ -n "$CONTEXT_PERCENT" ]; then
179
+ if [ "$CONTEXT_PERCENT" -ge "$CRITICAL_THRESHOLD" ] 2>/dev/null; then
180
+ echo "CONTEXT_WARNING=Critical"
181
+ echo "CONTEXT_RECOMMENDATION=checkpoint and handoff recommended"
182
+ elif [ "$CONTEXT_PERCENT" -ge "$WARNING_THRESHOLD" ] 2>/dev/null; then
183
+ echo "CONTEXT_WARNING=High"
184
+ echo "CONTEXT_RECOMMENDATION=consider handoff soon"
185
+ fi
186
+ fi
187
+ fi