@pennyfarthing/core 10.1.0 → 10.3.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 (422) hide show
  1. package/README.md +22 -24
  2. package/package.json +3 -1
  3. package/packages/core/dist/cli/commands/doctor-file-layout.test.js.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor-legacy.test.js +24 -0
  5. package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
  6. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  7. package/packages/core/dist/cli/commands/doctor.js +101 -15
  8. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  9. package/packages/core/dist/cli/commands/e2e-fresh-install.test.js +2 -2
  10. package/packages/core/dist/cli/commands/e2e-fresh-install.test.js.map +1 -1
  11. package/packages/core/dist/cli/commands/e2e-upgrade.test.js +2 -2
  12. package/packages/core/dist/cli/commands/e2e-upgrade.test.js.map +1 -1
  13. package/packages/core/dist/cli/commands/hooks-consolidation.test.js +2 -2
  14. package/packages/core/dist/cli/commands/hooks-consolidation.test.js.map +1 -1
  15. package/packages/core/dist/cli/commands/init-consolidation.test.js.map +1 -1
  16. package/packages/core/dist/cli/commands/theme.js +1 -1
  17. package/packages/core/dist/cli/commands/theme.js.map +1 -1
  18. package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -1
  19. package/packages/core/dist/cli/commands/uninstall.js +24 -13
  20. package/packages/core/dist/cli/commands/uninstall.js.map +1 -1
  21. package/packages/core/dist/cli/commands/update-consolidation.test.js +0 -10
  22. package/packages/core/dist/cli/commands/update-consolidation.test.js.map +1 -1
  23. package/packages/core/dist/cli/commands/update.js.map +1 -1
  24. package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
  25. package/packages/core/dist/cli/theme-maker.test.js +64 -115
  26. package/packages/core/dist/cli/theme-maker.test.js.map +1 -1
  27. package/packages/core/dist/cli/utils/themes.d.ts.map +1 -1
  28. package/packages/core/dist/cli/utils/themes.js +3 -2
  29. package/packages/core/dist/cli/utils/themes.js.map +1 -1
  30. package/packages/core/dist/index.d.ts +1 -1
  31. package/packages/core/dist/index.d.ts.map +1 -1
  32. package/packages/core/dist/index.js +2 -2
  33. package/packages/core/dist/index.js.map +1 -1
  34. package/packages/core/dist/plugins/plugin-discovery.d.ts +116 -0
  35. package/packages/core/dist/plugins/plugin-discovery.d.ts.map +1 -0
  36. package/packages/core/dist/plugins/plugin-discovery.js +165 -0
  37. package/packages/core/dist/plugins/plugin-discovery.js.map +1 -0
  38. package/packages/core/dist/plugins/plugin-discovery.test.d.ts +22 -0
  39. package/packages/core/dist/plugins/plugin-discovery.test.d.ts.map +1 -0
  40. package/packages/core/dist/plugins/plugin-discovery.test.js +498 -0
  41. package/packages/core/dist/plugins/plugin-discovery.test.js.map +1 -0
  42. package/packages/core/dist/scripts/add-ocean-profiles.js +1 -1
  43. package/packages/core/dist/scripts/add-ocean-profiles.js.map +1 -1
  44. package/packages/core/dist/scripts/generate-all-spiders.js +2 -0
  45. package/packages/core/dist/scripts/generate-all-spiders.js.map +1 -1
  46. package/packages/core/dist/scripts/generate-report.d.ts.map +1 -1
  47. package/packages/core/dist/scripts/generate-report.js +2 -0
  48. package/packages/core/dist/scripts/generate-report.js.map +1 -1
  49. package/packages/core/dist/scripts/generate-spider-report.js.map +1 -1
  50. package/packages/core/dist/scripts/generate-spider.d.ts.map +1 -1
  51. package/packages/core/dist/scripts/generate-spider.js +2 -0
  52. package/packages/core/dist/scripts/generate-spider.js.map +1 -1
  53. package/packages/core/dist/scripts/validate-ocean-profiles.js +1 -1
  54. package/packages/core/dist/scripts/validate-ocean-profiles.js.map +1 -1
  55. package/packages/core/dist/workflow/file-watch.d.ts +82 -0
  56. package/packages/core/dist/workflow/file-watch.d.ts.map +1 -0
  57. package/packages/core/dist/workflow/file-watch.js +198 -0
  58. package/packages/core/dist/workflow/file-watch.js.map +1 -0
  59. package/packages/core/dist/workflow/file-watch.test.d.ts +21 -0
  60. package/packages/core/dist/workflow/file-watch.test.d.ts.map +1 -0
  61. package/packages/core/dist/workflow/file-watch.test.js +469 -0
  62. package/packages/core/dist/workflow/file-watch.test.js.map +1 -0
  63. package/packages/core/dist/workflow/observation-writer.d.ts +79 -0
  64. package/packages/core/dist/workflow/observation-writer.d.ts.map +1 -0
  65. package/packages/core/dist/workflow/observation-writer.js +97 -0
  66. package/packages/core/dist/workflow/observation-writer.js.map +1 -0
  67. package/packages/core/dist/workflow/observation-writer.test.d.ts +18 -0
  68. package/packages/core/dist/workflow/observation-writer.test.d.ts.map +1 -0
  69. package/packages/core/dist/workflow/observation-writer.test.js +424 -0
  70. package/packages/core/dist/workflow/observation-writer.test.js.map +1 -0
  71. package/packages/core/dist/workflow/output-path-normalizer.d.ts +47 -0
  72. package/packages/core/dist/workflow/output-path-normalizer.d.ts.map +1 -0
  73. package/packages/core/dist/workflow/output-path-normalizer.js +79 -0
  74. package/packages/core/dist/workflow/output-path-normalizer.js.map +1 -0
  75. package/packages/core/dist/workflow/output-path-normalizer.test.d.ts +16 -0
  76. package/packages/core/dist/workflow/output-path-normalizer.test.d.ts.map +1 -0
  77. package/packages/core/dist/workflow/output-path-normalizer.test.js +157 -0
  78. package/packages/core/dist/workflow/output-path-normalizer.test.js.map +1 -0
  79. package/packages/core/dist/workflow/story-workflow-routing.test.js +4 -2
  80. package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -1
  81. package/packages/core/dist/workflow/tandem-lifecycle.d.ts +117 -0
  82. package/packages/core/dist/workflow/tandem-lifecycle.d.ts.map +1 -0
  83. package/packages/core/dist/workflow/tandem-lifecycle.js +186 -0
  84. package/packages/core/dist/workflow/tandem-lifecycle.js.map +1 -0
  85. package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts +16 -0
  86. package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts.map +1 -0
  87. package/packages/core/dist/workflow/tandem-lifecycle.test.js +531 -0
  88. package/packages/core/dist/workflow/tandem-lifecycle.test.js.map +1 -0
  89. package/packages/core/dist/workflow/tool-watch.d.ts +68 -0
  90. package/packages/core/dist/workflow/tool-watch.d.ts.map +1 -0
  91. package/packages/core/dist/workflow/tool-watch.js +166 -0
  92. package/packages/core/dist/workflow/tool-watch.js.map +1 -0
  93. package/packages/core/dist/workflow/tool-watch.test.d.ts +18 -0
  94. package/packages/core/dist/workflow/tool-watch.test.d.ts.map +1 -0
  95. package/packages/core/dist/workflow/tool-watch.test.js +717 -0
  96. package/packages/core/dist/workflow/tool-watch.test.js.map +1 -0
  97. package/packages/core/dist/workflow/variable-resolver.js +1 -1
  98. package/packages/core/dist/workflow/variable-resolver.js.map +1 -1
  99. package/packages/core/dist/workflow/workflow-migration.test.js +8 -4
  100. package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -1
  101. package/packages/core/dist/workflow/workflow-schema.d.ts +7 -0
  102. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  103. package/packages/core/dist/workflow/workflow-schema.js +44 -0
  104. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  105. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  106. package/packages/core/dist/workflow/workflow-schema.test.js +192 -0
  107. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  108. package/pennyfarthing-dist/agents/README.md +3 -1
  109. package/pennyfarthing-dist/agents/ba.md +165 -0
  110. package/pennyfarthing-dist/agents/handoff.md +18 -3
  111. package/pennyfarthing-dist/agents/sm-finish.md +1 -1
  112. package/pennyfarthing-dist/agents/sm-handoff.md +27 -4
  113. package/pennyfarthing-dist/agents/sm.md +11 -5
  114. package/pennyfarthing-dist/agents/tandem-backseat.md +119 -0
  115. package/pennyfarthing-dist/commands/ba.md +17 -0
  116. package/pennyfarthing-dist/commands/setup.md +4 -0
  117. package/pennyfarthing-dist/guides/agent-behavior.md +62 -6
  118. package/pennyfarthing-dist/guides/bikelane.md +3 -2
  119. package/pennyfarthing-dist/guides/scale-levels.md +4 -6
  120. package/pennyfarthing-dist/guides/tandem-protocol.md +158 -0
  121. package/pennyfarthing-dist/guides/workflow-schema.md +1 -1
  122. package/pennyfarthing-dist/personas/themes/a-team.yaml +30 -0
  123. package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +30 -0
  124. package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +30 -0
  125. package/pennyfarthing-dist/personas/themes/blade-runner.yaml +30 -0
  126. package/pennyfarthing-dist/personas/themes/catch-22.yaml +30 -0
  127. package/pennyfarthing-dist/personas/themes/control.yaml +30 -0
  128. package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +31 -0
  129. package/pennyfarthing-dist/personas/themes/discworld.yaml +32 -1
  130. package/pennyfarthing-dist/personas/themes/doctor-who.yaml +31 -0
  131. package/pennyfarthing-dist/personas/themes/dune.yaml +32 -0
  132. package/pennyfarthing-dist/personas/themes/fifth-element.yaml +327 -0
  133. package/pennyfarthing-dist/personas/themes/firefly.yaml +31 -0
  134. package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +30 -0
  135. package/pennyfarthing-dist/personas/themes/harry-potter.yaml +30 -0
  136. package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +30 -0
  137. package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +30 -0
  138. package/pennyfarthing-dist/personas/themes/mad-max.yaml +30 -0
  139. package/pennyfarthing-dist/personas/themes/mash.yaml +33 -0
  140. package/pennyfarthing-dist/personas/themes/princess-bride.yaml +34 -0
  141. package/pennyfarthing-dist/personas/themes/sandman.yaml +33 -0
  142. package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +34 -0
  143. package/pennyfarthing-dist/personas/themes/star-wars.yaml +33 -0
  144. package/pennyfarthing-dist/personas/themes/the-expanse.yaml +30 -0
  145. package/pennyfarthing-dist/personas/themes/the-matrix.yaml +30 -0
  146. package/pennyfarthing-dist/personas/themes/watchmen.yaml +30 -0
  147. package/pennyfarthing-dist/personas/themes/west-wing.yaml +30 -0
  148. package/pennyfarthing-dist/personas/themes/x-files.yaml +30 -0
  149. package/pennyfarthing-dist/scripts/README.md +1 -1
  150. package/pennyfarthing-dist/scripts/core/agent-session.sh +1 -1
  151. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +131 -54
  152. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +20 -10
  153. package/pennyfarthing-dist/scripts/misc/statusline.sh +50 -8
  154. package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +2 -2
  155. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +1 -0
  156. package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
  157. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +10 -189
  158. package/pennyfarthing-dist/skills/skill-registry.schema.json +8 -0
  159. package/pennyfarthing-dist/skills/skill-registry.yaml +1 -1
  160. package/pennyfarthing-dist/skills/sprint/skill.md +25 -2
  161. package/pennyfarthing-dist/skills/theme/skill.md +1 -1
  162. package/pennyfarthing-dist/skills/workflow/skill.md +24 -1
  163. package/pennyfarthing-dist/workflows/architecture/workflow.yaml +65 -0
  164. package/pennyfarthing-dist/workflows/architecture.yaml +2 -2
  165. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +70 -0
  166. package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +2 -2
  167. package/pennyfarthing-dist/workflows/implementation-readiness/workflow.yaml +2 -2
  168. package/pennyfarthing-dist/workflows/prd/workflow.yaml +2 -2
  169. package/pennyfarthing-dist/workflows/product-brief/workflow.yaml +2 -2
  170. package/pennyfarthing-dist/workflows/project-context/workflow.yaml +2 -2
  171. package/pennyfarthing-dist/workflows/quick-dev/workflow.yaml +2 -2
  172. package/pennyfarthing-dist/workflows/research/workflow.yaml +2 -2
  173. package/pennyfarthing-dist/workflows/retrospective/workflow.yaml +1 -1
  174. package/pennyfarthing-dist/workflows/sprint-planning/workflow.yaml +3 -3
  175. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +61 -0
  176. package/pennyfarthing-dist/workflows/ux-design/workflow.yaml +2 -2
  177. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  179. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  180. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  181. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  182. package/pennyfarthing_scripts/bellmode_hook.py +202 -47
  183. package/pennyfarthing_scripts/bikerack/__init__.py +36 -0
  184. package/pennyfarthing_scripts/bikerack/__main__.py +5 -0
  185. package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  188. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  189. package/pennyfarthing_scripts/bikerack/cli.py +148 -0
  190. package/pennyfarthing_scripts/bikerack/launcher.py +181 -0
  191. package/pennyfarthing_scripts/brownfield/__init__.py +6 -6
  192. package/pennyfarthing_scripts/brownfield/__main__.py +1 -0
  193. package/pennyfarthing_scripts/brownfield/cli.py +0 -1
  194. package/pennyfarthing_scripts/brownfield/discover.py +1 -2
  195. package/pennyfarthing_scripts/cli.py +16 -6
  196. package/pennyfarthing_scripts/codemarkers/__init__.py +5 -1
  197. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  201. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  202. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/codemarkers/analyze.py +177 -2
  204. package/pennyfarthing_scripts/codemarkers/cli.py +50 -0
  205. package/pennyfarthing_scripts/codemarkers/formatters.py +0 -1
  206. package/pennyfarthing_scripts/codemarkers/models.py +15 -0
  207. package/pennyfarthing_scripts/common/__init__.py +8 -9
  208. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/common/config.py +1 -1
  211. package/pennyfarthing_scripts/complexity/__init__.py +1 -1
  212. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  213. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  214. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  215. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  216. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  217. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  218. package/pennyfarthing_scripts/complexity/analyze.py +1 -1
  219. package/pennyfarthing_scripts/complexity/cli.py +5 -1
  220. package/pennyfarthing_scripts/complexity/formatters.py +1 -1
  221. package/pennyfarthing_scripts/context.py +14 -15
  222. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  223. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  225. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/deadcode/analyze.py +3 -4
  229. package/pennyfarthing_scripts/deadcode/cli.py +2 -2
  230. package/pennyfarthing_scripts/dependencies/__init__.py +2 -2
  231. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  233. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/dependencies/analyze.py +1 -1
  238. package/pennyfarthing_scripts/dependencies/cli.py +8 -4
  239. package/pennyfarthing_scripts/dependencies/formatters.py +1 -1
  240. package/pennyfarthing_scripts/git/__init__.py +5 -5
  241. package/pennyfarthing_scripts/git/create_branches.py +3 -2
  242. package/pennyfarthing_scripts/git/status_all.py +1 -1
  243. package/pennyfarthing_scripts/healthscore/__init__.py +2 -2
  244. package/pennyfarthing_scripts/healthscore/__main__.py +8 -0
  245. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/healthscore/analyze.py +452 -21
  252. package/pennyfarthing_scripts/healthscore/cli.py +5 -1
  253. package/pennyfarthing_scripts/healthscore/models.py +0 -1
  254. package/pennyfarthing_scripts/hooks.py +8 -11
  255. package/pennyfarthing_scripts/hotspots/__init__.py +6 -6
  256. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  257. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  258. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  259. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  260. package/pennyfarthing_scripts/hotspots/analyze.py +128 -14
  261. package/pennyfarthing_scripts/hotspots/cli.py +2 -2
  262. package/pennyfarthing_scripts/hotspots/models.py +0 -1
  263. package/pennyfarthing_scripts/jira/__init__.py +15 -17
  264. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  266. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  267. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  268. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  269. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/jira/bidirectional.py +2 -3
  275. package/pennyfarthing_scripts/jira/claim.py +21 -0
  276. package/pennyfarthing_scripts/jira/cli.py +2 -2
  277. package/pennyfarthing_scripts/jira/client.py +4 -4
  278. package/pennyfarthing_scripts/jira/create.py +45 -1
  279. package/pennyfarthing_scripts/jira/epic.py +3 -2
  280. package/pennyfarthing_scripts/jira/reconcile.py +0 -1
  281. package/pennyfarthing_scripts/jira/story.py +2 -0
  282. package/pennyfarthing_scripts/jira/sync.py +1 -1
  283. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  284. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  285. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/migration/skill.py +0 -1
  289. package/pennyfarthing_scripts/migration/step.py +0 -1
  290. package/pennyfarthing_scripts/migration/validate.py +8 -5
  291. package/pennyfarthing_scripts/patch_mode.py +2 -2
  292. package/pennyfarthing_scripts/preflight/__init__.py +1 -1
  293. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  294. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  295. package/pennyfarthing_scripts/preflight/finish.py +0 -1
  296. package/pennyfarthing_scripts/pretooluse_hook.py +6 -7
  297. package/pennyfarthing_scripts/prime/__init__.py +2 -0
  298. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  302. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  303. package/pennyfarthing_scripts/prime/cli.py +18 -1
  304. package/pennyfarthing_scripts/prime/loader.py +72 -3
  305. package/pennyfarthing_scripts/prime/persona.py +4 -2
  306. package/pennyfarthing_scripts/prime/tiers.py +17 -4
  307. package/pennyfarthing_scripts/schema_validation_hook.py +2 -3
  308. package/pennyfarthing_scripts/sprint/__init__.py +10 -12
  309. package/pennyfarthing_scripts/sprint/__main__.py +2 -2
  310. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  311. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  312. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  313. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  314. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  315. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  316. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  317. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  318. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  319. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  320. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  321. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  322. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  323. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  324. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  325. package/pennyfarthing_scripts/sprint/archive.py +0 -1
  326. package/pennyfarthing_scripts/sprint/archive_epic.py +1 -4
  327. package/pennyfarthing_scripts/sprint/cli.py +34 -28
  328. package/pennyfarthing_scripts/sprint/epic_add.py +8 -1
  329. package/pennyfarthing_scripts/sprint/import_epic.py +42 -18
  330. package/pennyfarthing_scripts/sprint/loader.py +6 -0
  331. package/pennyfarthing_scripts/sprint/status.py +1 -2
  332. package/pennyfarthing_scripts/sprint/story_add.py +2 -2
  333. package/pennyfarthing_scripts/sprint/story_finish.py +3 -5
  334. package/pennyfarthing_scripts/sprint/story_update.py +11 -3
  335. package/pennyfarthing_scripts/sprint/validate_cmd.py +0 -1
  336. package/pennyfarthing_scripts/sprint/validator.py +120 -6
  337. package/pennyfarthing_scripts/sprint/work.py +1 -4
  338. package/pennyfarthing_scripts/sprint/yaml_io.py +10 -2
  339. package/pennyfarthing_scripts/story/__init__.py +14 -16
  340. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  341. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  342. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  343. package/pennyfarthing_scripts/story/size.py +0 -1
  344. package/pennyfarthing_scripts/story/template.py +0 -1
  345. package/pennyfarthing_scripts/swebench.py +1 -2
  346. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  347. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  348. package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
  349. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  350. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  351. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  352. package/pennyfarthing_scripts/tests/conftest.py +1 -2
  353. package/pennyfarthing_scripts/tests/test_bikerack.py +785 -0
  354. package/pennyfarthing_scripts/tests/test_brownfield.py +10 -13
  355. package/pennyfarthing_scripts/tests/test_cli_modules.py +0 -4
  356. package/pennyfarthing_scripts/tests/test_codemarkers.py +13 -8
  357. package/pennyfarthing_scripts/tests/test_common.py +9 -4
  358. package/pennyfarthing_scripts/tests/test_epic_shard_validation.py +699 -0
  359. package/pennyfarthing_scripts/tests/test_git_utils.py +10 -13
  360. package/pennyfarthing_scripts/tests/test_healthscore.py +17 -25
  361. package/pennyfarthing_scripts/tests/test_jira_package.py +0 -3
  362. package/pennyfarthing_scripts/tests/test_package_structure.py +3 -16
  363. package/pennyfarthing_scripts/tests/test_patch_mode.py +7 -11
  364. package/pennyfarthing_scripts/tests/test_prime.py +39 -21
  365. package/pennyfarthing_scripts/tests/test_sprint_package.py +3 -8
  366. package/pennyfarthing_scripts/tests/test_sprint_validator.py +53 -5
  367. package/pennyfarthing_scripts/tests/test_story_add.py +3 -7
  368. package/pennyfarthing_scripts/tests/test_story_package.py +0 -3
  369. package/pennyfarthing_scripts/tests/test_story_update.py +5 -10
  370. package/pennyfarthing_scripts/tests/test_tiers.py +18 -17
  371. package/pennyfarthing_scripts/tests/test_token_counting.py +19 -13
  372. package/pennyfarthing_scripts/tests/test_topology_loader.py +620 -0
  373. package/pennyfarthing_scripts/tests/test_validate_cmd.py +2 -7
  374. package/pennyfarthing_scripts/tests/test_workflow_check.py +0 -2
  375. package/pennyfarthing_scripts/tests/test_yaml_io.py +0 -3
  376. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  377. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  378. package/pennyfarthing_scripts/theme/cli.py +3 -2
  379. package/pennyfarthing_scripts/validate/__init__.py +21 -0
  380. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  381. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  382. package/pennyfarthing_scripts/validate/adapters/__init__.py +0 -0
  383. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  384. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  385. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  386. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  387. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  388. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  389. package/pennyfarthing_scripts/validate/adapters/agent.py +239 -0
  390. package/pennyfarthing_scripts/validate/adapters/schema.py +30 -0
  391. package/pennyfarthing_scripts/validate/adapters/skill_command.py +291 -0
  392. package/pennyfarthing_scripts/validate/adapters/sprint.py +69 -0
  393. package/pennyfarthing_scripts/validate/adapters/workflow.py +320 -0
  394. package/pennyfarthing_scripts/validate/cli.py +141 -0
  395. package/pennyfarthing_scripts/welcome_hook.py +2 -3
  396. package/pennyfarthing_scripts/workflow.py +3 -3
  397. package/scripts/README.md +3 -15
  398. package/pennyfarthing-dist/commands/benchmark-control.md +0 -69
  399. package/pennyfarthing-dist/commands/benchmark.md +0 -485
  400. package/pennyfarthing-dist/commands/job-fair.md +0 -102
  401. package/pennyfarthing-dist/commands/solo.md +0 -447
  402. package/pennyfarthing-dist/guides/benchmarks.md +0 -62
  403. package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +0 -59
  404. package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +0 -220
  405. package/pennyfarthing-dist/scripts/test/swebench-judge.py +0 -374
  406. package/pennyfarthing-dist/scripts/test/test-cache.sh +0 -165
  407. package/pennyfarthing-dist/scripts/test/test-setup.sh +0 -337
  408. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +0 -13
  409. package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +0 -402
  410. package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +0 -97
  411. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +0 -261
  412. package/pennyfarthing-dist/skills/judge/SKILL.md +0 -644
  413. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +0 -187
  414. package/pennyfarthing-dist/workflows/dev-story/checklist.md +0 -80
  415. package/pennyfarthing-dist/workflows/dev-story/instructions.xml +0 -410
  416. package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +0 -50
  417. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +0 -201
  418. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +0 -156
  419. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +0 -140
  420. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +0 -203
  421. package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +0 -74
  422. package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +0 -27
@@ -134,6 +134,39 @@ if [ -n "$config_file" ] && [ -n "$agent_name" ]; then
134
134
  fi
135
135
  theme_display="$character_display"
136
136
 
137
+ # Tandem indicator: detect active backseat agent from observation files
138
+ # Files: .session/{storyId}-tandem-{partner}.md (created by backseat spawn, cleaned on finish)
139
+ tandem_partner=""
140
+ tandem_partner_display=""
141
+ if [ -d "$PROJECT_ROOT/.session" ]; then
142
+ tandem_file=$(find "$PROJECT_ROOT/.session" -maxdepth 1 -name "*-tandem-*.md" -print 2>/dev/null | head -1)
143
+ if [ -n "$tandem_file" ]; then
144
+ # Extract partner name from filename: {storyId}-tandem-{partner}.md
145
+ tandem_partner=$(basename "$tandem_file" | sed -n 's/.*-tandem-\([a-zA-Z_-]*\)\.md$/\1/p')
146
+ if [ -n "$tandem_partner" ] && [ -n "$theme_file" ] && [ -f "$theme_file" ]; then
147
+ # Look up partner's character name from theme
148
+ partner_full=$(yq ".agents.${tandem_partner}.character" "$theme_file" 2>/dev/null)
149
+ if [ -n "$partner_full" ] && [ "$partner_full" != "null" ]; then
150
+ partner_clean=$(echo "$partner_full" | sed 's/ *([^)]*)//g' | xargs)
151
+ partner_clean=$(echo "$partner_clean" | sed -E 's/^(Captain|Lieutenant|Dr\.|Doc|Mr\.|Mrs\.|Ms\.|Admiral|Commander|Chief|Ensign|Translator|Agent|Colonel|Major|Sergeant|Professor|Lord|Lady|Sir|The) +//i')
152
+ partner_wc=$(echo "$partner_clean" | wc -w | tr -d ' ')
153
+ if [ "$partner_wc" -eq 1 ]; then
154
+ tandem_partner_display="$partner_clean"
155
+ else
156
+ tandem_partner_display=$(echo "$partner_clean" | awk '{print $NF}')
157
+ fi
158
+ fi
159
+ # Fallback to agent abbreviation if no theme character
160
+ if [ -z "$tandem_partner_display" ]; then
161
+ tandem_partner_display=$(get_agent_abbrev "$tandem_partner")
162
+ fi
163
+ elif [ -n "$tandem_partner" ]; then
164
+ # No theme file — use abbreviation
165
+ tandem_partner_display=$(get_agent_abbrev "$tandem_partner")
166
+ fi
167
+ fi
168
+ fi
169
+
137
170
  # ANSI colors
138
171
  RESET=$'\033[0m'
139
172
  DIM=$'\033[2m'
@@ -214,20 +247,29 @@ repo_fmt=$(printf "%-14s" "$dir_name")
214
247
  branch_fmt=$(printf "%-12s" "${branch}${branch_dirty}")
215
248
  model_fmt=$(printf "%-10s" "$model")
216
249
 
217
- # Build agent display: [ROLE] Theme (role in reverse text with color)
250
+ # Build tandem suffix: "+ Partner" when backseat agent is active
251
+ tandem_suffix=""
252
+ tandem_suffix_len=0
253
+ if [ -n "$tandem_partner_display" ]; then
254
+ partner_color=$(get_agent_color "$tandem_partner")
255
+ tandem_suffix=" ${DIM}+${RESET} ${partner_color}${tandem_partner_display}${RESET}"
256
+ tandem_suffix_len=$((3 + ${#tandem_partner_display})) # " + " + name
257
+ fi
258
+
259
+ # Build agent display: [ROLE] Theme (+ Partner) (role in reverse text with color)
218
260
  if [ -n "$agent_abbrev" ]; then
219
261
  agent_color=$(get_agent_color "$agent_name")
220
262
  # Role in reverse text with color, then theme
221
263
  if [ -n "$theme_display" ]; then
222
- agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET} ${DIM}${theme_display}${RESET}"
223
- # Pad to ~20 chars visual width (abbrev ~3 + spaces ~2 + theme ~10 = ~15, pad to 20)
224
- pad_len=$((18 - ${#agent_abbrev} - ${#theme_display}))
264
+ agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET} ${DIM}${theme_display}${RESET}${tandem_suffix}"
265
+ # Pad to ~20 chars visual width (abbrev ~3 + spaces ~2 + theme ~10 + tandem = ~15+, pad to 20)
266
+ pad_len=$((18 - ${#agent_abbrev} - ${#theme_display} - tandem_suffix_len))
225
267
  [ "$pad_len" -lt 0 ] && pad_len=0
226
268
  padding=$(printf "%${pad_len}s" "")
227
269
  agent_section="${agent_section}${padding}"
228
270
  else
229
- agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET}"
230
- pad_len=$((17 - ${#agent_abbrev}))
271
+ agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET}${tandem_suffix}"
272
+ pad_len=$((17 - ${#agent_abbrev} - tandem_suffix_len))
231
273
  [ "$pad_len" -lt 0 ] && pad_len=0
232
274
  padding=$(printf "%${pad_len}s" "")
233
275
  agent_section="${agent_section}${padding}"
@@ -235,8 +277,8 @@ if [ -n "$agent_abbrev" ]; then
235
277
  else
236
278
  # No agent - just show theme if available
237
279
  if [ -n "$theme_display" ]; then
238
- agent_section="${DIM}${theme_display}${RESET}"
239
- pad_len=$((20 - ${#theme_display}))
280
+ agent_section="${DIM}${theme_display}${RESET}${tandem_suffix}"
281
+ pad_len=$((20 - ${#theme_display} - tandem_suffix_len))
240
282
  [ "$pad_len" -lt 0 ] && pad_len=0
241
283
  padding=$(printf "%${pad_len}s" "")
242
284
  agent_section="${agent_section}${padding}"
@@ -91,10 +91,10 @@ GUIDANCE_SCALE = 7.5
91
91
  # CLIP token limit - prompts are truncated beyond this
92
92
  CLIP_MAX_TOKENS = 77
93
93
 
94
- # Role order for the 10 agents
94
+ # Role order for the 11 agents
95
95
  ROLES = [
96
96
  "orchestrator", "sm", "tea", "dev", "reviewer",
97
- "architect", "pm", "tech-writer", "ux-designer", "devops"
97
+ "architect", "pm", "tech-writer", "ux-designer", "devops", "ba"
98
98
  ]
99
99
 
100
100
  # Default style suffix (visual description comes first for emphasis)
@@ -43,6 +43,7 @@ PRIMARY_AGENTS=(
43
43
  "devops.md"
44
44
  "tech-writer.md"
45
45
  "ux-designer.md"
46
+ "ba.md"
46
47
  )
47
48
 
48
49
  # Subagents (have YAML frontmatter, different schema)
@@ -6,7 +6,7 @@ Scripts for workflow mechanics, phase transitions, and quality gates.
6
6
 
7
7
  | Script | Purpose |
8
8
  |--------|---------|
9
- | `finish-story.sh` | Story completion workflow (archive, PR merge, Jira transition) |
9
+ | `finish-story.sh` | **DEPRECATED** forwards to `pf sprint story finish` |
10
10
  | `fix-session-phase.sh` | Repair session file phase state |
11
11
  | `check.sh` | Quality gates runner (lint, type check, tests) |
12
12
  | `list-workflows.sh` | List available workflows |
@@ -18,7 +18,7 @@ Scripts for workflow mechanics, phase transitions, and quality gates.
18
18
  ## Usage
19
19
 
20
20
  ```bash
21
- .pennyfarthing/scripts/workflow/finish-story.sh MSSCI-12345
21
+ pf sprint story finish MSSCI-12345
22
22
  .pennyfarthing/scripts/workflow/start-workflow.sh prd --mode create
23
23
  ```
24
24
 
@@ -1,199 +1,20 @@
1
1
  #!/bin/bash
2
- # Finish a story: archive, merge PR, transition Jira, update sprint YAML
3
- # Usage: finish-story.sh <story-id> [--dry-run]
4
- #
5
- # Example: finish-story.sh MSSCI-12052
6
- # finish-story.sh MSSCI-12052 --dry-run
2
+ # DEPRECATED: Use `pf sprint story finish` instead.
7
3
  #
8
- # Prerequisites:
9
- # - Session file exists at .session/{story-id}-session.md
10
- # - PR is approved and mergeable
11
- # - Reviewer has approved (phase: finish in session)
4
+ # This shell script had a bug where yq paths targeted .epics[].stories[]
5
+ # but the sprint YAML uses sharded epic files with .stories[] at root.
6
+ # The Python implementation (pennyfarthing_scripts.sprint.story_finish)
7
+ # correctly handles sharded YAML via read_sprint/write_sprint.
12
8
  #
13
- # This script performs:
14
- # 1. Archive session file to sprint/archive/{jira-key}-session.md
15
- # 2. Squash merge PR and delete remote branch
16
- # 3. Transition Jira to Done
17
- # 4. Update sprint YAML (status: done, completed date)
18
- # 5. Archive completed epics (if last story in epic was just finished)
19
- # 6. Clean up local branch and session file
9
+ # Usage: finish-story.sh <story-id> [--dry-run]
20
10
 
21
11
  set -euo pipefail
22
12
 
23
- STORY_ID="${1:-}"
24
- DRY_RUN=false
13
+ echo "DEPRECATED: finish-story.sh is deprecated. Forwarding to 'pf sprint story finish'." >&2
25
14
 
26
- # Parse options
15
+ ARGS=()
27
16
  for arg in "$@"; do
28
- case $arg in
29
- --dry-run)
30
- DRY_RUN=true
31
- shift
32
- ;;
33
- esac
17
+ ARGS+=("$arg")
34
18
  done
35
19
 
36
- if [[ -z "$STORY_ID" ]]; then
37
- echo "Usage: finish-story.sh <story-id> [--dry-run]"
38
- echo ""
39
- echo "Options:"
40
- echo " --dry-run Show what would be done without executing"
41
- exit 1
42
- fi
43
-
44
- # Find project root
45
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
46
-
47
- SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
48
- ARCHIVE_DIR="$PROJECT_ROOT/sprint/archive"
49
-
50
- # Ensure archive directory exists
51
- mkdir -p "$ARCHIVE_DIR"
52
-
53
- # Resolve session file: prefer Jira key, fall back to numeric story ID
54
- SESSION_FILE="$PROJECT_ROOT/.session/${STORY_ID}-session.md"
55
- if [[ ! -f "$SESSION_FILE" ]]; then
56
- # Look up Jira key from sprint YAML and try that
57
- _JIRA_LOOKUP=$(pf sprint story field "$STORY_ID" jira 2>/dev/null || echo "")
58
- if [[ -n "$_JIRA_LOOKUP" && "$_JIRA_LOOKUP" != "null" ]]; then
59
- ALT_SESSION="$PROJECT_ROOT/.session/${_JIRA_LOOKUP}-session.md"
60
- if [[ -f "$ALT_SESSION" ]]; then
61
- SESSION_FILE="$ALT_SESSION"
62
- fi
63
- fi
64
- fi
65
-
66
- # Also try the reverse: if called with Jira key, try numeric ID
67
- if [[ ! -f "$SESSION_FILE" ]]; then
68
- # List session files and look for one containing the story ID
69
- for f in "$PROJECT_ROOT/.session/"*-session.md; do
70
- [[ -f "$f" ]] || continue
71
- if grep -q "$STORY_ID" "$f" 2>/dev/null; then
72
- SESSION_FILE="$f"
73
- break
74
- fi
75
- done
76
- fi
77
-
78
- # Validate session file exists
79
- if [[ ! -f "$SESSION_FILE" ]]; then
80
- echo "Error: Session file not found for story $STORY_ID"
81
- echo "Looked for: $PROJECT_ROOT/.session/${STORY_ID}-session.md"
82
- [[ -n "${_JIRA_LOOKUP:-}" ]] && echo "Also tried: $PROJECT_ROOT/.session/${_JIRA_LOOKUP}-session.md"
83
- exit 1
84
- fi
85
-
86
- # Extract metadata from session file
87
- # Try **Jira:** field first (handle both "**Jira:**" and "- **Jira:**", markdown link format)
88
- JIRA_KEY=$(grep -E '\*\*Jira:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Jira:\*\* //' | sed 's/\[//' | sed 's/\].*//' | tr -d ' ' || echo "")
89
-
90
- # Fallback: extract MSSCI key from **ID:** field (format: "MSSCI-14459 (81-2)" or just "MSSCI-14459")
91
- if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
92
- JIRA_KEY=$(grep -E '\*\*ID:\*\*' "$SESSION_FILE" | grep -oE 'MSSCI-[0-9]+' | head -1 || echo "")
93
- fi
94
-
95
- # Fallback: if STORY_ID itself is a Jira key, use it directly
96
- if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
97
- if [[ "$STORY_ID" =~ ^MSSCI-[0-9]+$ ]]; then
98
- JIRA_KEY="$STORY_ID"
99
- fi
100
- fi
101
-
102
- # Fallback: look up Jira key from sprint YAML via pf CLI
103
- if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
104
- JIRA_KEY=$(pf sprint story field "$STORY_ID" jira 2>/dev/null || echo "")
105
- fi
106
-
107
- if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
108
- echo "Error: Could not determine Jira key for story $STORY_ID"
109
- echo "Check session file or sprint YAML for jira: field"
110
- exit 1
111
- fi
112
-
113
- # Extract branch - strip any trailing annotations like "(pushed)"
114
- BRANCH=$(grep -E '\*\*Branch:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Branch:\*\* //' | sed 's/ *(.*//' | tr -d ' ' || echo "")
115
-
116
- # Try to get PR number from session file first (format: **PR:** #422 - title)
117
- PR_NUMBER=$(grep -E '\*\*PR:\*\*' "$SESSION_FILE" | sed 's/.*#\([0-9]*\).*/\1/' || echo "")
118
-
119
- # Fallback: get PR number from GitHub if not in session file
120
- if [[ -z "$PR_NUMBER" ]] && [[ -n "$BRANCH" ]]; then
121
- PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || echo "")
122
- fi
123
-
124
- TODAY=$(date +%Y-%m-%d)
125
-
126
- echo "=== Finish Story: $STORY_ID ==="
127
- echo "Jira Key: $JIRA_KEY"
128
- echo "Branch: ${BRANCH:-none}"
129
- echo "PR: ${PR_NUMBER:-none}"
130
- echo ""
131
-
132
- if $DRY_RUN; then
133
- echo "[DRY RUN] Would perform:"
134
- echo " 1. Archive session → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
135
- if [[ -n "$PR_NUMBER" ]]; then
136
- echo " 2. Merge PR #$PR_NUMBER (squash, delete branch)"
137
- else
138
- echo " 2. No PR to merge"
139
- fi
140
- echo " 3. Transition $JIRA_KEY to Done"
141
- echo " 4. Update sprint YAML (status: done, completed: $TODAY)"
142
- echo " 5. Archive any completed epics"
143
- echo " 6. Delete local branch: $BRANCH"
144
- echo " 7. Remove session file"
145
- exit 0
146
- fi
147
-
148
- # Step 1: Archive session file
149
- echo "1. Archiving session file..."
150
- cp "$SESSION_FILE" "$ARCHIVE_DIR/${JIRA_KEY}-session.md"
151
- echo " → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
152
-
153
- # Step 2: Merge PR (if exists)
154
- if [[ -n "$PR_NUMBER" ]]; then
155
- echo "2. Merging PR #$PR_NUMBER..."
156
- gh pr merge "$PR_NUMBER" --squash --delete-branch || {
157
- echo " Warning: PR merge failed (may already be merged)"
158
- }
159
- else
160
- echo "2. No PR found for branch $BRANCH (skipping merge)"
161
- fi
162
-
163
- # Step 3: Transition Jira to Done
164
- echo "3. Transitioning Jira to Done..."
165
- jira issue move "$JIRA_KEY" "Done" 2>/dev/null || {
166
- echo " Warning: Jira transition failed (may already be Done)"
167
- }
168
-
169
- # Step 4: Update sprint YAML
170
- echo "4. Updating sprint YAML..."
171
- # Update status to done
172
- yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).status = \"done\"" "$SPRINT_FILE"
173
- # Add completed date
174
- yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).completed = \"$TODAY\"" "$SPRINT_FILE"
175
- # Remove assigned_to (no longer in progress)
176
- yq eval -i "del((.epics[].stories[] | select(.id == \"$STORY_ID\")).assigned_to)" "$SPRINT_FILE"
177
- echo " → status: done, completed: $TODAY"
178
-
179
- # Step 5: Archive completed epics
180
- echo "5. Archiving completed epics..."
181
- pf sprint epic archive 2>/dev/null && echo " → Checked for completed epics" || echo " → No epics to archive"
182
-
183
- # Step 6: Clean up git
184
- echo "6. Cleaning up git..."
185
- git checkout develop 2>/dev/null || git checkout main 2>/dev/null || true
186
- git pull origin "$(git branch --show-current)" 2>/dev/null || true
187
-
188
- if [[ -n "$BRANCH" ]]; then
189
- git branch -d "$BRANCH" 2>/dev/null || echo " Local branch already deleted"
190
- fi
191
-
192
- # Step 7: Remove session file
193
- echo "7. Removing session file..."
194
- rm "$SESSION_FILE"
195
-
196
- echo ""
197
- echo "=== Story $STORY_ID Complete ==="
198
- echo "Archived: sprint/archive/${JIRA_KEY}-session.md"
199
- echo "Jira: https://1898andco.atlassian.net/browse/$JIRA_KEY"
20
+ exec pf sprint story finish "${ARGS[@]}"
@@ -98,6 +98,14 @@
98
98
  "type": "array",
99
99
  "items": { "type": "string" },
100
100
  "description": "Tools this skill is allowed to use. If omitted, all tools are allowed. Use to restrict read-only skills from writing."
101
+ },
102
+ "deprecated": {
103
+ "type": "boolean",
104
+ "description": "Whether this skill is deprecated"
105
+ },
106
+ "redirect": {
107
+ "type": "string",
108
+ "description": "Skill name to redirect to when deprecated"
101
109
  }
102
110
  },
103
111
  "required": ["name", "description", "category", "tags"],
@@ -386,7 +386,7 @@ skills:
386
386
  anti_patterns:
387
387
  - Don't switch workflows mid-story unless requirements fundamentally changed
388
388
  related_skills: [sprint]
389
- keywords: [tdd, trivial, agent-docs, bdd, architecture, bikelane, stepped, phased]
389
+ keywords: [tdd, tdd-tandem, trivial, agent-docs, bdd, bdd-tandem, architecture, bikelane, stepped, phased]
390
390
 
391
391
  yq:
392
392
  name: yq
@@ -293,7 +293,7 @@ pf sprint story add <epic-id> "<title>" <points> [options]
293
293
  | `points` | Yes | Story points (1, 2, 3, 5, 8) |
294
294
  | `--type` | No | Story type: feature, bug, chore, refactor (default: feature) |
295
295
  | `--priority` | No | Priority: P0, P1, P2, P3 (default: P1) |
296
- | `--workflow` | No | Workflow: tdd, trivial, bdd (default: tdd) |
296
+ | `--workflow` | No | Workflow: tdd, tdd-tandem, trivial, bdd, bdd-tandem (default: tdd) |
297
297
  | `--jira` | No | Jira issue key |
298
298
  </args>
299
299
 
@@ -399,6 +399,28 @@ pf sprint story claim <story-id>
399
399
 
400
400
  ---
401
401
 
402
+ ### `/sprint story assign <story-id> <assignee>`
403
+
404
+ Assign a Jira story to a user. Shortcut for `/jira assign`.
405
+
406
+ <run>
407
+ pf jira assign <story-id> <assignee>
408
+ </run>
409
+
410
+ <args>
411
+ | Arg | Required | Description |
412
+ |-----|----------|-------------|
413
+ | `story-id` | Yes | Jira key (e.g., `MSSCI-14552`) |
414
+ | `assignee` | Yes | Email or GitHub username (e.g., `keith.avery@1898andco.io`, `slabgorb`) |
415
+ </args>
416
+
417
+ <example>
418
+ pf jira assign MSSCI-14552 keith.avery@1898andco.io
419
+ pf jira assign MSSCI-14552 slabgorb
420
+ </example>
421
+
422
+ ---
423
+
402
424
  ### `/sprint epic add <epic-id> <title> [options]`
403
425
 
404
426
  Add a new epic to the current sprint.
@@ -696,7 +718,7 @@ All gates must pass before handoff:
696
718
  | Sprint name | `"TO Sprint YYWW"` (e.g., "TO Sprint 2604") |
697
719
  | Story IDs | Jira keys `MSSCI-XXXXX` |
698
720
  | Status | `backlog`, `ready`, `in_progress`, `done` |
699
- | Workflow | `tdd`, `trivial`, `agent-docs`, `bdd` |
721
+ | Workflow | `tdd`, `tdd-tandem`, `trivial`, `agent-docs`, `bdd`, `bdd-tandem` |
700
722
  | Priority | `P0`, `P1`, `P2`, `P3` |
701
723
  | in_sprint | `true`, `false` - Jira sprint membership |
702
724
 
@@ -761,6 +783,7 @@ For Jira integration, see `/jira` skill prerequisites.
761
783
  | `/sprint story template` | `pf sprint story template` |
762
784
  | `/sprint story finish ID` | `pf sprint story finish ID` |
763
785
  | `/sprint story claim ID` | `pf sprint story claim ID` |
786
+ | `/sprint story assign ID USER` | `pf jira assign ID USER` |
764
787
  | `/sprint epic show ID` | `pf sprint epic show ID` |
765
788
  | `/sprint epic field ID FIELD` | `pf sprint epic field ID FIELD` |
766
789
  | `/sprint epic add ...` | `pf sprint epic add ...` |
@@ -181,7 +181,7 @@ Best for: Users who want to pick characters from suggestions.
181
181
  4. Preview and confirm
182
182
  5. Write theme file
183
183
 
184
- **Agent Order:** orchestrator, sm, tea, dev, reviewer, architect, pm, tech-writer, ux-designer, devops
184
+ **Agent Order:** orchestrator, sm, tea, dev, reviewer, architect, pm, tech-writer, ux-designer, devops, ba
185
185
 
186
186
  ---
187
187
 
@@ -163,6 +163,18 @@ SM → TEA → Dev → Reviewer → SM
163
163
  - Dev implements to make tests pass
164
164
  - **Triggers:** `types: [feature, enhancement]`, `points.min: 3`
165
165
 
166
+ ### TDD-Tandem (TDD with full tandem chain)
167
+
168
+ ```
169
+ setup → red (+Architect) → green (+TEA) → review (+PM) → finish
170
+ SM → TEA (+Architect) → Dev (+TEA) → Reviewer (+PM) → SM
171
+ ```
172
+
173
+ - Full tandem chain: every phase has a backseat observer
174
+ - Architect watches test design, TEA watches implementation, PM watches review
175
+ - For high-stakes features needing cross-role visibility
176
+ - **Triggers:** `tags: [tandem]`, `points.min: 3`
177
+
166
178
  ### Trivial (for 1-2 point fixes)
167
179
 
168
180
  ```
@@ -196,6 +208,17 @@ SM → UX-Designer → TEA → Dev → Reviewer → SM
196
208
  - For UI components and user-facing features
197
209
  - **Triggers:** `types: [ui, ux, behavior]`, `tags: [bdd, ux-first]`
198
210
 
211
+ ### BDD-Tandem (BDD with full tandem chain)
212
+
213
+ ```
214
+ setup → design (+Architect) → red → green (+UX-Designer) → review (+PM) → finish
215
+ SM → UX-Designer (+Architect) → TEA → Dev (+UX-Designer) → Reviewer (+PM) → SM
216
+ ```
217
+
218
+ - Full tandem chain: Architect watches design, UX-Designer watches implementation, PM watches review
219
+ - Everyone shares their cake — cross-role visibility at every phase
220
+ - **Triggers:** `tags: [bdd-tandem, tandem, ux-first]`, `points.min: 3`
221
+
199
222
  ### Architecture (stepped workflow)
200
223
 
201
224
  ```
@@ -341,5 +364,5 @@ workflow:
341
364
  For comprehensive documentation on creating stepped workflows, see:
342
365
 
343
366
  - **[guides/bikelane.md](../../guides/bikelane.md)** - Full BikeLane user guide
344
- - **[docs/adr/0013-bmad-workflow-import.md](../../docs/adr/0013-bmad-workflow-import.md)** - Technical ADR
367
+ - **ADR-0013: Stepped Workflow Support** - Technical ADR (see `docs/adr/0013-bmad-workflow-import.md` in framework repo)
345
368
  - **[pennyfarthing-dist/workflows/architecture.yaml](../../workflows/architecture.yaml)** - Example implementation
@@ -0,0 +1,65 @@
1
+ # Architecture Workflow - Migrated from BMAD format
2
+ # Collaborative architectural decision-making with progressive disclosure
3
+ #
4
+ # Flow: Initialize → [Continue?] → Context → Patterns → Components → Interfaces → Risks → Document
5
+ # Use for architectural decisions, system design, and technical planning
6
+ #
7
+ # BMAD Enhancements:
8
+ # - Continuation handler (step-01b) for resuming workflows
9
+ # - A/P/C menus: Advanced Elicitation, Party Mode, Continue
10
+ # - Web search integration for current technology versions
11
+ # - AI agent consistency focus in component and risk steps
12
+ # - Pre-documentation validation checks
13
+
14
+ workflow:
15
+ name: architecture
16
+ description: Collaborative architectural decision facilitation for AI-agent consistency. Produces a decision-focused architecture document optimized for preventing agent conflicts through step-by-step discovery with A/P/C collaboration menus.
17
+ version: "2.0.0"
18
+ type: stepped
19
+
20
+ # Step configuration
21
+ steps:
22
+ path: ./steps/
23
+ pattern: step-{nn}-*.md
24
+ # Note: step-01b-continue.md is loaded conditionally by step-01 when existing workflow detected
25
+
26
+ # Variables available in step files
27
+ variables:
28
+ project_root: .
29
+ planning_artifacts: sprint/planning/
30
+ output_file: sprint/planning/architecture.md
31
+ input_required:
32
+ - prd
33
+
34
+ # User approval gates - pause for confirmation at key decision points
35
+ # Steps with A/P/C menus naturally pause; these are the formal gates
36
+ gates:
37
+ after_steps: [2, 4, 6]
38
+ gate_marker: "<!-- GATE -->"
39
+
40
+ # Collaboration menus available in steps
41
+ collaboration:
42
+ menus:
43
+ - key: A
44
+ name: Advanced Elicitation
45
+ description: Use discovery protocols to develop deeper insights
46
+ - key: P
47
+ name: Party Mode
48
+ description: Bring multiple perspectives to analyze from different angles
49
+ - key: C
50
+ name: Continue
51
+ description: Save content and proceed to next step
52
+ - key: R
53
+ name: Revise
54
+ description: Need to gather more information or make changes
55
+
56
+ # Output template
57
+ template: ./templates/architecture-decision.md
58
+
59
+ # Agent assignment
60
+ agent: architect
61
+
62
+ # Triggers - when to suggest this workflow
63
+ triggers:
64
+ types: [architecture, design, adr, system-design]
65
+ tags: [architecture, stepped]
@@ -26,8 +26,8 @@ workflow:
26
26
 
27
27
  # Variables available in step files
28
28
  variables:
29
- output_file: planning-artifacts/architecture.md
30
- planning_artifacts: planning-artifacts
29
+ output_file: sprint/planning/architecture.md
30
+ planning_artifacts: sprint/planning/
31
31
  input_required:
32
32
  - prd
33
33
 
@@ -0,0 +1,70 @@
1
+ # BDD Tandem Workflow - BDD with Full Tandem Chain
2
+ # Extends standard BDD with tandem observers:
3
+ # - Architect backseats UX-Designer during design
4
+ # - UX-Designer backseats Dev during implementation
5
+ # - PM backseats Reviewer during review
6
+ #
7
+ # Flow: SM → UX-Designer (+Architect) → TEA → Dev (+UX-Designer) → Reviewer (+PM) → SM
8
+
9
+ workflow:
10
+ name: bdd-tandem
11
+ description: BDD with full tandem chain across design, implementation, and review
12
+ version: "1.0.0"
13
+
14
+ phases:
15
+ - name: setup
16
+ agent: sm
17
+ output: [session_file, branches, story_context]
18
+
19
+ - name: design
20
+ agent: ux-designer
21
+ input: [session_file, story_context]
22
+ output: [design_spec, user_flows, wireframes, behavior_scenarios]
23
+ gate:
24
+ type: design_review
25
+ condition: UX spec defines user flows and acceptance behaviors
26
+ tandem:
27
+ partner: architect
28
+ scope: file-watch
29
+
30
+ - name: red
31
+ agent: tea
32
+ input: [design_spec, behavior_scenarios, story_context]
33
+ output: [failing_tests]
34
+ gate:
35
+ type: tests_fail
36
+ condition: Behavior scenarios have test coverage
37
+
38
+ - name: green
39
+ agent: dev
40
+ input: [failing_tests, design_spec, story_context]
41
+ output: [implementation, passing_tests]
42
+ gate:
43
+ type: tests_pass
44
+ condition: All tests passing, UX spec implemented
45
+ tandem:
46
+ partner: ux-designer
47
+ scope: file-watch
48
+
49
+ - name: review
50
+ agent: reviewer
51
+ input: [implementation, passing_tests, design_spec]
52
+ output: [approval]
53
+ gate:
54
+ type: approval
55
+ condition: Code review approved, UX requirements met
56
+ tandem:
57
+ partner: pm
58
+ scope: file-watch
59
+
60
+ - name: finish
61
+ agent: sm
62
+ input: [approval]
63
+ output: [archived_session, story_summary]
64
+
65
+ triggers:
66
+ types: [ui, ux, behavior, component, settings]
67
+ tags: [bdd-tandem, tandem, ux-first]
68
+ points:
69
+ min: 3
70
+ default: false
@@ -16,8 +16,8 @@ workflow:
16
16
  # Variables available in step files
17
17
  variables:
18
18
  project_root: .
19
- planning_artifacts: ./artifacts
20
- output_file: artifacts/create-epics-and-stories.md
19
+ planning_artifacts: sprint/planning/
20
+ output_file: sprint/planning/create-epics-and-stories.md
21
21
 
22
22
  # Agent assignment (customize as needed)
23
23
  agent: architect
@@ -28,8 +28,8 @@ workflow:
28
28
  # Variables available in step files
29
29
  variables:
30
30
  project_root: .
31
- planning_artifacts: ./artifacts
32
- output_file: artifacts/implementation-readiness-report.md
31
+ planning_artifacts: sprint/planning/
32
+ output_file: sprint/planning/implementation-readiness-report.md
33
33
 
34
34
  # Agent assignment - PM/SM role for adversarial review
35
35
  agent: sm
@@ -22,8 +22,8 @@ workflow:
22
22
  # Variables available in step files
23
23
  variables:
24
24
  project_root: .
25
- planning_artifacts: ./artifacts
26
- output_file: artifacts/prd.md
25
+ planning_artifacts: sprint/planning/
26
+ output_file: sprint/planning/prd.md
27
27
 
28
28
  # Gates - pause for user approval at key decision points
29
29
  gates:
@@ -16,8 +16,8 @@ workflow:
16
16
  # Variables available in step files
17
17
  variables:
18
18
  project_root: .
19
- planning_artifacts: ./artifacts
20
- output_file: artifacts/product-brief.md
19
+ planning_artifacts: sprint/planning/
20
+ output_file: sprint/planning/product-brief.md
21
21
 
22
22
  # Template for product brief output
23
23
  template: ./templates/product-brief.template.md