@pennyfarthing/core 11.2.1 → 11.2.2

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 (467) hide show
  1. package/README.md +100 -40
  2. package/package.json +1 -1
  3. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor.js +121 -28
  5. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  6. package/packages/core/dist/cli/utils/settings.d.ts +0 -4
  7. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  8. package/packages/core/dist/cli/utils/settings.js +31 -26
  9. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  10. package/packages/core/dist/consultation/dialogue-manager.d.ts +1 -1
  11. package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -1
  12. package/packages/core/dist/consultation/dialogue-manager.js +1 -1
  13. package/packages/core/dist/consultation/dialogue-manager.js.map +1 -1
  14. package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -1
  15. package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -1
  16. package/packages/core/dist/public/css/react.css +1 -1
  17. package/packages/core/dist/public/js/react/react.js +9 -9
  18. package/packages/core/dist/server/api/git.d.ts.map +1 -1
  19. package/packages/core/dist/server/api/git.js +0 -1
  20. package/packages/core/dist/server/api/git.js.map +1 -1
  21. package/packages/core/dist/server/api/index.d.ts +2 -0
  22. package/packages/core/dist/server/api/index.d.ts.map +1 -1
  23. package/packages/core/dist/server/api/index.js +2 -0
  24. package/packages/core/dist/server/api/index.js.map +1 -1
  25. package/packages/core/dist/server/api/project-info.d.ts +11 -0
  26. package/packages/core/dist/server/api/project-info.d.ts.map +1 -0
  27. package/packages/core/dist/server/api/project-info.js +18 -0
  28. package/packages/core/dist/server/api/project-info.js.map +1 -0
  29. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  30. package/packages/core/dist/server/otlp-receiver.js +18 -1
  31. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  32. package/packages/core/dist/server/otlp-receiver.test.js +1 -1
  33. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -1
  34. package/packages/core/dist/server/server.d.ts.map +1 -1
  35. package/packages/core/dist/server/server.js +3 -2
  36. package/packages/core/dist/server/server.js.map +1 -1
  37. package/packages/core/dist/server/server.test.d.ts +1 -1
  38. package/packages/core/dist/server/server.test.js +8 -8
  39. package/packages/core/dist/server/settings.d.ts +1 -0
  40. package/packages/core/dist/server/settings.d.ts.map +1 -1
  41. package/packages/core/dist/server/settings.js +13 -0
  42. package/packages/core/dist/server/settings.js.map +1 -1
  43. package/packages/core/dist/workflow/team-lifecycle.d.ts +169 -0
  44. package/packages/core/dist/workflow/team-lifecycle.d.ts.map +1 -0
  45. package/packages/core/dist/workflow/team-lifecycle.js +217 -0
  46. package/packages/core/dist/workflow/team-lifecycle.js.map +1 -0
  47. package/packages/core/dist/workflow/team-lifecycle.test.d.ts +20 -0
  48. package/packages/core/dist/workflow/team-lifecycle.test.d.ts.map +1 -0
  49. package/packages/core/dist/workflow/team-lifecycle.test.js +966 -0
  50. package/packages/core/dist/workflow/team-lifecycle.test.js.map +1 -0
  51. package/packages/core/dist/workflow/workflow-team-templates.test.d.ts +17 -0
  52. package/packages/core/dist/workflow/workflow-team-templates.test.d.ts.map +1 -0
  53. package/packages/core/dist/workflow/workflow-team-templates.test.js +275 -0
  54. package/packages/core/dist/workflow/workflow-team-templates.test.js.map +1 -0
  55. package/pennyfarthing-dist/agents/dev.md +15 -2
  56. package/pennyfarthing-dist/agents/reviewer.md +17 -4
  57. package/pennyfarthing-dist/agents/sm-finish.md +1 -1
  58. package/pennyfarthing-dist/agents/sm-setup.md +7 -7
  59. package/pennyfarthing-dist/agents/sm.md +12 -12
  60. package/pennyfarthing-dist/agents/tea.md +2 -2
  61. package/pennyfarthing-dist/agents/testing-runner.md +1 -1
  62. package/pennyfarthing-dist/commands/pf-architect.md +1 -1
  63. package/pennyfarthing-dist/commands/pf-ba.md +1 -1
  64. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  65. package/pennyfarthing-dist/commands/pf-dev.md +1 -1
  66. package/pennyfarthing-dist/commands/pf-devops.md +1 -1
  67. package/pennyfarthing-dist/commands/pf-epic.md +6 -6
  68. package/pennyfarthing-dist/commands/pf-git.md +10 -10
  69. package/pennyfarthing-dist/commands/pf-health-check.md +1 -1
  70. package/pennyfarthing-dist/commands/pf-help.md +12 -12
  71. package/pennyfarthing-dist/commands/pf-orchestrator.md +1 -1
  72. package/pennyfarthing-dist/commands/pf-pm.md +1 -1
  73. package/pennyfarthing-dist/commands/pf-prime.md +8 -8
  74. package/pennyfarthing-dist/commands/pf-reviewer.md +1 -1
  75. package/pennyfarthing-dist/commands/pf-session.md +7 -7
  76. package/pennyfarthing-dist/commands/pf-sm.md +1 -1
  77. package/pennyfarthing-dist/commands/pf-sprint.md +7 -7
  78. package/pennyfarthing-dist/commands/pf-tea.md +1 -1
  79. package/pennyfarthing-dist/commands/pf-tech-writer.md +1 -1
  80. package/pennyfarthing-dist/commands/pf-theme.md +9 -9
  81. package/pennyfarthing-dist/commands/pf-ux-designer.md +1 -1
  82. package/pennyfarthing-dist/commands/pf-work.md +1 -1
  83. package/pennyfarthing-dist/guides/agent-behavior.md +70 -19
  84. package/pennyfarthing-dist/guides/agent-coordination.md +10 -10
  85. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +6 -6
  86. package/pennyfarthing-dist/guides/agent-template-tactical.md +1 -1
  87. package/pennyfarthing-dist/guides/bell-mode.md +1 -1
  88. package/pennyfarthing-dist/guides/bikerack.md +10 -10
  89. package/pennyfarthing-dist/guides/brownfield-tools.md +24 -24
  90. package/pennyfarthing-dist/guides/command-tag-taxonomy.md +1 -1
  91. package/pennyfarthing-dist/guides/gate-schema.md +2 -2
  92. package/pennyfarthing-dist/guides/gates.md +3 -3
  93. package/pennyfarthing-dist/guides/handoff-cli.md +8 -8
  94. package/pennyfarthing-dist/guides/hooks.md +27 -27
  95. package/pennyfarthing-dist/guides/prime.md +2 -2
  96. package/pennyfarthing-dist/guides/reflector.md +1 -1
  97. package/pennyfarthing-dist/guides/skill-schema.md +6 -6
  98. package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
  99. package/pennyfarthing-dist/guides/workflow-schema.md +1 -1
  100. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  101. package/pennyfarthing-dist/guides/xml-tags.md +8 -8
  102. package/pennyfarthing-dist/scripts/README.md +4 -4
  103. package/pennyfarthing-dist/scripts/core/agent-session.sh +2 -5
  104. package/pennyfarthing-dist/scripts/core/check-context.sh +1 -1
  105. package/pennyfarthing-dist/scripts/core/pf.sh +5 -0
  106. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +2 -5
  107. package/pennyfarthing-dist/scripts/core/prime.sh +2 -25
  108. package/pennyfarthing-dist/scripts/git/README.md +14 -14
  109. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +2 -3
  110. package/pennyfarthing-dist/scripts/git/git-status-all.sh +2 -3
  111. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +2 -3
  112. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +2 -4
  113. package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
  114. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +3 -3
  115. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +3 -3
  116. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +3 -3
  117. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -3
  118. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +5 -4
  119. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +2 -1
  120. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +3 -3
  121. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -3
  122. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +3 -3
  123. package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -3
  124. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +3 -3
  125. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +3 -3
  126. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +3 -4
  127. package/pennyfarthing-dist/scripts/lib/env.sh +34 -0
  128. package/pennyfarthing-dist/scripts/lib/run-pf.sh +39 -0
  129. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  130. package/pennyfarthing-dist/scripts/misc/statusline.sh +3 -3
  131. package/pennyfarthing-dist/scripts/sprint/README.md +21 -21
  132. package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
  133. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +2 -16
  134. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +3 -3
  135. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +3 -3
  136. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +3 -3
  137. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +3 -3
  138. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +3 -3
  139. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +3 -3
  140. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +3 -3
  141. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +3 -3
  142. package/pennyfarthing-dist/skills/pf-bc/examples.md +23 -23
  143. package/pennyfarthing-dist/skills/pf-bc/skill.md +17 -17
  144. package/pennyfarthing-dist/skills/pf-bc/usage.md +8 -8
  145. package/pennyfarthing-dist/skills/pf-jira/SKILL.md +15 -15
  146. package/pennyfarthing-dist/skills/pf-jira/examples.md +48 -48
  147. package/pennyfarthing-dist/skills/pf-jira/usage.md +15 -15
  148. package/pennyfarthing-dist/skills/pf-sprint/examples.md +80 -80
  149. package/pennyfarthing-dist/skills/pf-sprint/skill.md +35 -35
  150. package/pennyfarthing-dist/skills/pf-sprint/usage.md +30 -30
  151. package/pennyfarthing-dist/skills/pf-theme/examples.md +15 -15
  152. package/pennyfarthing-dist/skills/pf-theme/skill.md +6 -6
  153. package/pennyfarthing-dist/skills/pf-theme/usage.md +5 -5
  154. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -27
  155. package/pennyfarthing-dist/skills/pf-workflow/skill.md +11 -11
  156. package/pennyfarthing-dist/skills/pf-workflow/usage.md +11 -11
  157. package/pennyfarthing-dist/skills/skill-registry.yaml +19 -19
  158. package/pennyfarthing-dist/templates/settings.local.json.template +11 -11
  159. package/pennyfarthing-dist/workflows/bdd-team.yaml +89 -0
  160. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +1 -1
  161. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
  162. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
  163. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
  164. package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +47 -0
  165. package/pennyfarthing-dist/workflows/tdd-team.yaml +80 -0
  166. package/pennyfarthing_scripts/__init__.py +1 -1
  167. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  168. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  169. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  170. package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
  171. package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
  172. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  173. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  174. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/__pycache__/patch_mode.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__/session_start_hook.cpython-314.pyc +0 -0
  182. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  183. package/pennyfarthing_scripts/bc/__pycache__/__init__.cpython-314.pyc +0 -0
  184. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  185. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/bc/__pycache__/split.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/bc/cli.py +2 -2
  188. package/pennyfarthing_scripts/bellmode_hook.py +2 -5
  189. package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
  190. package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
  191. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  192. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  193. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  194. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  201. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  202. package/pennyfarthing_scripts/bikerack/__pycache__/portrait.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/bikerack/audit_log_panel.py +48 -6
  211. package/pennyfarthing_scripts/bikerack/launcher.py +6 -6
  212. package/pennyfarthing_scripts/bikerack/progress_panel.py +0 -1
  213. package/pennyfarthing_scripts/bikerack/sprint_panel.py +1 -1
  214. package/pennyfarthing_scripts/bikerack/story_detail_data.py +4 -1
  215. package/pennyfarthing_scripts/bikerack/story_detail_screen.py +2 -1
  216. package/pennyfarthing_scripts/bikerack/tui.py +12 -2
  217. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  218. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  219. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  220. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  221. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  222. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  223. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  225. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/common/config.py +29 -2
  233. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  238. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  239. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  240. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  241. package/pennyfarthing_scripts/consultation/cli.py +3 -3
  242. package/pennyfarthing_scripts/context.py +3 -3
  243. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  244. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  255. package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
  256. package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
  257. package/pennyfarthing_scripts/gate/__pycache__/__init__.cpython-314.pyc +0 -0
  258. package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
  259. package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
  260. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  261. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  262. package/pennyfarthing_scripts/git/__pycache__/hooks_installer.cpython-314.pyc +0 -0
  263. package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
  264. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/git/__pycache__/worktree.cpython-314.pyc +0 -0
  266. package/pennyfarthing_scripts/git/hooks_installer.py +2 -3
  267. package/pennyfarthing_scripts/git/status_all.py +1 -1
  268. package/pennyfarthing_scripts/git/worktree.py +2 -2
  269. package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
  276. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  277. package/pennyfarthing_scripts/handoff/__pycache__/phase_check.cpython-314.pyc +0 -0
  278. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  279. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  280. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  283. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  284. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  285. package/pennyfarthing_scripts/hooks/__init__.py +8 -3
  286. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  289. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  291. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  292. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  293. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  294. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  295. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  296. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  297. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/hooks/bell_mode.py +0 -1
  300. package/pennyfarthing_scripts/hooks/pre_edit_check.py +0 -1
  301. package/pennyfarthing_scripts/hooks/reflector_check.py +1 -2
  302. package/pennyfarthing_scripts/hooks/schema_validation.py +0 -1
  303. package/pennyfarthing_scripts/hooks/session_start.py +6 -8
  304. package/pennyfarthing_scripts/hooks/statusline.py +10 -1
  305. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  306. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  307. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  308. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  309. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  311. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  312. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  313. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  314. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  315. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  316. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  317. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  318. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  319. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  320. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  321. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  322. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  323. package/pennyfarthing_scripts/launch/__pycache__/__init__.cpython-314.pyc +0 -0
  324. package/pennyfarthing_scripts/launch/__pycache__/cli.cpython-314.pyc +0 -0
  325. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  326. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  327. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  328. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  329. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  332. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  333. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  334. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  335. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  336. package/pennyfarthing_scripts/prime/__pycache__/heatmap.cpython-314.pyc +0 -0
  337. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  338. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  339. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  340. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  341. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  342. package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
  343. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  344. package/pennyfarthing_scripts/prime/heatmap.py +3 -15
  345. package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
  346. package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
  347. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  348. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  349. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  350. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  351. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  352. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  355. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  356. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  357. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  358. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  359. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  360. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  361. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  362. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  363. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  364. package/pennyfarthing_scripts/sprint/cli.py +121 -0
  365. package/pennyfarthing_scripts/sprint/loader.py +154 -3
  366. package/pennyfarthing_scripts/sprint/story_update.py +7 -0
  367. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  368. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  369. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  370. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  371. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  372. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  373. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  374. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  375. package/pennyfarthing_scripts/tests/__pycache__/test_108_2_remove_handoff_fallback.cpython-314-pytest-9.0.2.pyc +0 -0
  376. package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
  377. package/pennyfarthing_scripts/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
  378. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  379. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  380. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  381. package/pennyfarthing_scripts/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
  382. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  383. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  384. package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
  385. package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
  386. package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
  387. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  388. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  389. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
  390. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  391. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  392. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  393. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  394. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  395. package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
  396. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  397. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
  398. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  399. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  400. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  401. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  402. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  403. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  404. package/pennyfarthing_scripts/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
  405. package/pennyfarthing_scripts/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
  406. package/pennyfarthing_scripts/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
  407. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  408. package/pennyfarthing_scripts/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
  409. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  410. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_list_team.cpython-314-pytest-9.0.2.pyc +0 -0
  411. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  412. package/pennyfarthing_scripts/tests/test_bikerack.py +26 -26
  413. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +0 -1
  414. package/pennyfarthing_scripts/tests/test_workflow_list_team.py +147 -0
  415. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  416. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  417. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  418. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  419. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  420. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  421. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  422. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  423. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  424. package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
  425. package/pennyfarthing_scripts/validate/adapters/__pycache__/team_mode.cpython-314.pyc +0 -0
  426. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  427. package/pennyfarthing_scripts/validate/adapters/team_mode.py +323 -0
  428. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  429. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  430. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  431. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  432. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  433. package/pennyfarthing_scripts/workflow/__pycache__/team_lifecycle.cpython-314.pyc +0 -0
  434. package/pennyfarthing_scripts/workflow/cli.py +15 -14
  435. package/pennyfarthing_scripts/workflow/state.py +0 -1
  436. package/pennyfarthing_scripts/workflow/team_lifecycle.py +3 -4
  437. package/packages/core/dist/cli/cyclist-migration.test.d.ts +0 -16
  438. package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +0 -1
  439. package/packages/core/dist/cli/cyclist-migration.test.js +0 -229
  440. package/packages/core/dist/cli/cyclist-migration.test.js.map +0 -1
  441. package/packages/core/dist/scripts/benchmark-integration.d.ts +0 -182
  442. package/packages/core/dist/scripts/benchmark-integration.d.ts.map +0 -1
  443. package/packages/core/dist/scripts/benchmark-integration.js +0 -691
  444. package/packages/core/dist/scripts/benchmark-integration.js.map +0 -1
  445. package/packages/core/dist/scripts/job-fair-aggregator.d.ts +0 -150
  446. package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +0 -1
  447. package/packages/core/dist/scripts/job-fair-aggregator.js +0 -547
  448. package/packages/core/dist/scripts/job-fair-aggregator.js.map +0 -1
  449. package/packages/core/dist/scripts/theme-detail.test.d.ts.map +0 -1
  450. package/packages/core/dist/scripts/theme-detail.test.js.map +0 -1
  451. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  452. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  453. package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
  454. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  455. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  456. package/pennyfarthing_scripts/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
  457. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  458. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  459. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  460. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  461. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  462. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  463. package/pennyfarthing_scripts/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
  464. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
  465. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
  466. package/pennyfarthing_scripts/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
  467. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
@@ -0,0 +1,147 @@
1
+ """Tests for Story 86-15 AC4: workflow list shows team-enabled workflows with indicator.
2
+
3
+ Story: 86-15 — Team-enabled workflow templates
4
+ Epic: 86 — Agent Collaboration: Tandem to Teams
5
+
6
+ Acceptance Criteria:
7
+ - [AC4] /workflow list shows team-enabled workflows with indicator
8
+
9
+ The `pf workflow list` command should visually distinguish team-enabled
10
+ workflows from regular and tandem workflows. When a workflow has `team:`
11
+ blocks on any phase, the output must include an indicator.
12
+
13
+ These tests verify the CLI output format. Tests should fail until
14
+ both the workflow templates (tdd-team.yaml, bdd-team.yaml) and the
15
+ workflow list team indicator are implemented.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from pathlib import Path
21
+ from unittest.mock import patch
22
+
23
+ import pytest
24
+ import yaml
25
+ from click.testing import CliRunner
26
+
27
+ from pennyfarthing_scripts.cli import cli
28
+
29
+
30
+ class TestWorkflowListTeamIndicator:
31
+ """Tests for team indicator in workflow list output (AC4)."""
32
+
33
+ @pytest.fixture
34
+ def runner(self) -> CliRunner:
35
+ return CliRunner()
36
+
37
+ def test_workflow_list_shows_team_workflows(self, runner: CliRunner) -> None:
38
+ """AC4: workflow list should include tdd-team and bdd-team."""
39
+ result = runner.invoke(cli, ["workflow", "list"])
40
+ assert result.exit_code == 0
41
+ assert "tdd-team" in result.output, "tdd-team workflow should appear in list"
42
+ assert "bdd-team" in result.output, "bdd-team workflow should appear in list"
43
+
44
+ def test_workflow_list_has_team_indicator_for_tdd_team(
45
+ self, runner: CliRunner
46
+ ) -> None:
47
+ """AC4: tdd-team should have a team indicator in workflow list."""
48
+ result = runner.invoke(cli, ["workflow", "list"])
49
+ assert result.exit_code == 0
50
+
51
+ # Find the tdd-team row in the markdown table
52
+ tdd_team_line = None
53
+ for line in result.output.splitlines():
54
+ if "tdd-team" in line and "|" in line:
55
+ tdd_team_line = line
56
+ break
57
+
58
+ assert tdd_team_line is not None, "tdd-team should appear as a table row"
59
+
60
+ # The row should have a team indicator — could be a column value,
61
+ # emoji, or tag that distinguishes it from non-team workflows
62
+ line_lower = tdd_team_line.lower()
63
+ assert (
64
+ "team" in line_lower
65
+ ), "tdd-team row should contain a 'team' indicator"
66
+
67
+ def test_workflow_list_has_team_indicator_for_bdd_team(
68
+ self, runner: CliRunner
69
+ ) -> None:
70
+ """AC4: bdd-team should have a team indicator in workflow list."""
71
+ result = runner.invoke(cli, ["workflow", "list"])
72
+ assert result.exit_code == 0
73
+
74
+ bdd_team_line = None
75
+ for line in result.output.splitlines():
76
+ if "bdd-team" in line and "|" in line:
77
+ bdd_team_line = line
78
+ break
79
+
80
+ assert bdd_team_line is not None, "bdd-team should appear as a table row"
81
+
82
+ line_lower = bdd_team_line.lower()
83
+ assert (
84
+ "team" in line_lower
85
+ ), "bdd-team row should contain a 'team' indicator"
86
+
87
+ def test_non_team_workflows_lack_team_indicator(
88
+ self, runner: CliRunner
89
+ ) -> None:
90
+ """AC4: Regular workflows should NOT have team indicator."""
91
+ result = runner.invoke(cli, ["workflow", "list"])
92
+ assert result.exit_code == 0
93
+
94
+ for line in result.output.splitlines():
95
+ if "|" not in line:
96
+ continue
97
+ # Skip header, separator, and team workflows
98
+ if "tdd-team" in line or "bdd-team" in line:
99
+ continue
100
+ if "Workflow" in line or "---" in line:
101
+ continue
102
+
103
+ # Check columns (split by |)
104
+ cols = [c.strip() for c in line.split("|")]
105
+ name_col = cols[1] if len(cols) > 1 else ""
106
+
107
+ # tdd-tandem and bdd-tandem are tandem, not team
108
+ if "tandem" in name_col:
109
+ continue
110
+
111
+ # Plain workflows like tdd, trivial, bdd should not show team
112
+ # in their mode/indicator columns (but "team" might appear
113
+ # in description text, which is fine — we check indicator columns)
114
+ # The name itself (e.g., "tdd") doesn't contain "team", confirming
115
+ # no false positives in the name column
116
+
117
+
118
+ class TestWorkflowListTeamColumnOrTag:
119
+ """Verify the team indicator mechanism in workflow list."""
120
+
121
+ @pytest.fixture
122
+ def runner(self) -> CliRunner:
123
+ return CliRunner()
124
+
125
+ def test_workflow_list_distinguishes_team_from_tandem(
126
+ self, runner: CliRunner
127
+ ) -> None:
128
+ """Team workflows should be distinguishable from tandem workflows."""
129
+ result = runner.invoke(cli, ["workflow", "list"])
130
+ assert result.exit_code == 0
131
+
132
+ tdd_team_line = None
133
+ tdd_tandem_line = None
134
+ for line in result.output.splitlines():
135
+ if "tdd-team" in line and "|" in line:
136
+ tdd_team_line = line
137
+ elif "tdd-tandem" in line and "|" in line:
138
+ tdd_tandem_line = line
139
+
140
+ assert tdd_team_line is not None, "tdd-team should be in the list"
141
+ assert tdd_tandem_line is not None, "tdd-tandem should be in the list"
142
+
143
+ # They should have different indicators — team vs tandem
144
+ # At minimum, the descriptions should be distinct
145
+ assert tdd_team_line != tdd_tandem_line, (
146
+ "tdd-team and tdd-tandem should have different rows"
147
+ )
@@ -0,0 +1,323 @@
1
+ """Team-mode protocol validator adapter.
2
+
3
+ Validates that agent definitions include proper team-mode sections
4
+ for Claude Code native Agent Teams integration.
5
+
6
+ Story: MSSCI-15109 (86-14)
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import re
12
+ from pathlib import Path
13
+
14
+ from pennyfarthing_scripts.validate import ValidateReport
15
+
16
+ # Regex to extract <team-mode> section content
17
+ _TEAM_MODE_RE = re.compile(r"<team-mode>(.*?)</team-mode>", re.DOTALL)
18
+
19
+ # Required topics in the behavior guide's <team-mode> section
20
+ _BEHAVIOR_GUIDE_TOPICS = {
21
+ "team_creation": ["TeamCreate", "team creation", "create team"],
22
+ "spawning": ["spawn", "Task tool", "teammate"],
23
+ "sendmessage": ["SendMessage"],
24
+ "cleanup": ["cleanup", "TeamDelete", "shut down", "shutdown"],
25
+ }
26
+
27
+ # Required lead agent topics
28
+ _LEAD_TOPICS = {
29
+ "phase_entry": ["phase entry", "phase start", "on phase"],
30
+ "spawn_per_yaml": ["spawn", "teammates", "workflow YAML", "YAML"],
31
+ "shutdown_before_exit": ["shut down", "shutdown", "before exit", "before handoff"],
32
+ }
33
+
34
+ # Required teammate awareness topics
35
+ _TEAMMATE_TOPICS = {
36
+ "identity": ["teammate", "not lead", "not the lead"],
37
+ "sendmessage": ["SendMessage"],
38
+ "idle": ["idle", "go idle"],
39
+ "shutdown_response": ["shutdown", "shutdown_response", "shutdown request"],
40
+ }
41
+
42
+
43
+ def extract_team_mode_section(content: str) -> str | None:
44
+ """Extract content between <team-mode> tags."""
45
+ m = _TEAM_MODE_RE.search(content)
46
+ return m.group(1) if m else None
47
+
48
+
49
+ def validate_behavior_guide_team_mode(
50
+ path: Path,
51
+ ) -> tuple[list[str], list[str]]:
52
+ """Validate the behavior guide has a <team-mode> section with required topics.
53
+
54
+ Returns:
55
+ (errors, warnings) — two lists of message strings.
56
+ """
57
+ errors: list[str] = []
58
+ warnings: list[str] = []
59
+ content = path.read_text()
60
+ section = extract_team_mode_section(content)
61
+
62
+ if section is None:
63
+ errors.append("Missing <team-mode> section in behavior guide")
64
+ return errors, warnings
65
+
66
+ stripped = section.strip()
67
+ if not stripped:
68
+ errors.append("Empty <team-mode> section — no content")
69
+ return errors, warnings
70
+
71
+ # Check required topics
72
+ for topic_name, keywords in _BEHAVIOR_GUIDE_TOPICS.items():
73
+ if not any(kw.lower() in section.lower() for kw in keywords):
74
+ errors.append(
75
+ f"<team-mode> section missing required topic: {topic_name} "
76
+ f"(expected one of: {', '.join(keywords)})"
77
+ )
78
+
79
+ return errors, warnings
80
+
81
+
82
+ def validate_lead_agent_team_mode(
83
+ path: Path,
84
+ ) -> tuple[list[str], list[str]]:
85
+ """Validate lead agent has team-mode behavior section.
86
+
87
+ Returns:
88
+ (errors, warnings) — two lists of message strings.
89
+ """
90
+ errors: list[str] = []
91
+ warnings: list[str] = []
92
+ content = path.read_text()
93
+ section = extract_team_mode_section(content)
94
+
95
+ if section is None:
96
+ errors.append(f"Missing <team-mode> section in lead agent {path.name}")
97
+ return errors, warnings
98
+
99
+ stripped = section.strip()
100
+ if not stripped:
101
+ errors.append(f"Empty <team-mode> section in lead agent {path.name}")
102
+ return errors, warnings
103
+
104
+ section_lower = section.lower()
105
+
106
+ # Must reference lead role
107
+ if "lead" not in section_lower:
108
+ errors.append("Lead agent <team-mode> section must reference 'lead' role")
109
+
110
+ # Check lead-specific topics
111
+ for topic_name, keywords in _LEAD_TOPICS.items():
112
+ if not any(kw.lower() in section_lower for kw in keywords):
113
+ warnings.append(
114
+ f"Lead agent <team-mode> missing topic: {topic_name} "
115
+ f"(expected one of: {', '.join(keywords)})"
116
+ )
117
+
118
+ return errors, warnings
119
+
120
+
121
+ def validate_teammate_awareness(
122
+ content: str,
123
+ ) -> tuple[list[str], list[str]]:
124
+ """Validate teammate behavior content in team-mode section.
125
+
126
+ Returns:
127
+ (errors, warnings) — two lists of message strings.
128
+ """
129
+ errors: list[str] = []
130
+ warnings: list[str] = []
131
+ section = extract_team_mode_section(content)
132
+
133
+ if section is None:
134
+ errors.append("Missing <team-mode> section for teammate awareness")
135
+ return errors, warnings
136
+
137
+ section_lower = section.lower()
138
+
139
+ # Check teammate-specific topics
140
+ for topic_name, keywords in _TEAMMATE_TOPICS.items():
141
+ if not any(kw.lower() in section_lower for kw in keywords):
142
+ errors.append(
143
+ f"Teammate awareness missing topic: {topic_name} "
144
+ f"(expected one of: {', '.join(keywords)})"
145
+ )
146
+
147
+ return errors, warnings
148
+
149
+
150
+ def validate_exit_protocol_team_branch(
151
+ content: str,
152
+ ) -> tuple[list[str], list[str]]:
153
+ """Validate exit protocol has team-mode cleanup branch.
154
+
155
+ Returns:
156
+ (errors, warnings) — two lists of message strings.
157
+ """
158
+ errors: list[str] = []
159
+ warnings: list[str] = []
160
+
161
+ # Look for team cleanup in exit protocol section
162
+ # The exit protocol is in <agent-exit-protocol> tags
163
+ exit_re = re.compile(
164
+ r"<agent-exit-protocol>(.*?)</agent-exit-protocol>", re.DOTALL
165
+ )
166
+ exit_match = exit_re.search(content)
167
+
168
+ if exit_match is None:
169
+ errors.append("Missing <agent-exit-protocol> section")
170
+ return errors, warnings
171
+
172
+ exit_content = exit_match.group(1).lower()
173
+
174
+ # Must reference team cleanup
175
+ team_cleanup_terms = ["team", "teamdelete", "cleanup team", "shut down teammate"]
176
+ if not any(term in exit_content for term in team_cleanup_terms):
177
+ errors.append(
178
+ "Exit protocol missing team-mode branch "
179
+ "(must reference team cleanup before handoff)"
180
+ )
181
+
182
+ return errors, warnings
183
+
184
+
185
+ def validate_communication_protocols(
186
+ content: str,
187
+ ) -> tuple[list[str], list[str]]:
188
+ """Validate that reflector markers and SendMessage are properly documented.
189
+
190
+ Reflector markers for inter-phase handoff (unchanged).
191
+ SendMessage for intra-phase teammate communication (new).
192
+
193
+ Returns:
194
+ (errors, warnings) — two lists of message strings.
195
+ """
196
+ errors: list[str] = []
197
+ warnings: list[str] = []
198
+
199
+ # Reflector section must still exist
200
+ if "<critical>" not in content or "CYCLIST" not in content:
201
+ errors.append("Reflector/CYCLIST marker section missing — must remain for inter-phase handoff")
202
+
203
+ # Team-mode section must reference SendMessage for intra-phase
204
+ section = extract_team_mode_section(content)
205
+ if section is not None:
206
+ if "SendMessage" not in section:
207
+ errors.append(
208
+ "<team-mode> must reference SendMessage for intra-phase communication"
209
+ )
210
+ # Should distinguish inter-phase (markers) from intra-phase (SendMessage)
211
+ if "inter-phase" not in section.lower() and "intra-phase" not in section.lower():
212
+ warnings.append(
213
+ "<team-mode> should distinguish inter-phase (markers) "
214
+ "from intra-phase (SendMessage) communication"
215
+ )
216
+
217
+ return errors, warnings
218
+
219
+
220
+ def classify_team_mode_agents(
221
+ agents_dir: Path,
222
+ ) -> tuple[list[Path], list[Path]]:
223
+ """Classify agent files into lead agents and all agents with team-mode.
224
+
225
+ Lead agents are those whose <team-mode> section mentions 'lead'.
226
+
227
+ Returns:
228
+ (lead_agents, all_team_mode_agents)
229
+ """
230
+ leads: list[Path] = []
231
+ all_tm: list[Path] = []
232
+
233
+ for f in sorted(agents_dir.glob("*.md")):
234
+ if f.name == "README.md":
235
+ continue
236
+
237
+ content = f.read_text()
238
+ section = extract_team_mode_section(content)
239
+ if section is None:
240
+ continue
241
+
242
+ all_tm.append(f)
243
+ if "lead" in section.lower():
244
+ leads.append(f)
245
+
246
+ return leads, all_tm
247
+
248
+
249
+ def run(
250
+ root: Path, *, fix: bool = False, strict: bool = False
251
+ ) -> ValidateReport:
252
+ """Validate agent team-mode protocol sections."""
253
+ report = ValidateReport(validator="team-mode")
254
+
255
+ # Validate behavior guide
256
+ guides_dir = root / "pennyfarthing-dist" / "guides"
257
+ behavior_guide = guides_dir / "agent-behavior.md"
258
+ if behavior_guide.is_file():
259
+ file_errors, file_warnings = validate_behavior_guide_team_mode(behavior_guide)
260
+ for e in file_errors:
261
+ report.errors += 1
262
+ report.details.append(f"[ERROR] agent-behavior.md: {e}")
263
+ for w in file_warnings:
264
+ if strict:
265
+ report.errors += 1
266
+ report.details.append(f"[ERROR] agent-behavior.md: {w}")
267
+ else:
268
+ report.warnings += 1
269
+ report.details.append(f"[WARN] agent-behavior.md: {w}")
270
+ if not file_errors:
271
+ report.passed += 1
272
+
273
+ # Validate exit protocol team branch
274
+ guide_content = behavior_guide.read_text()
275
+ exit_errors, exit_warnings = validate_exit_protocol_team_branch(guide_content)
276
+ for e in exit_errors:
277
+ report.errors += 1
278
+ report.details.append(f"[ERROR] agent-behavior.md exit: {e}")
279
+ for w in exit_warnings:
280
+ if strict:
281
+ report.errors += 1
282
+ report.details.append(f"[ERROR] agent-behavior.md exit: {w}")
283
+ else:
284
+ report.warnings += 1
285
+ report.details.append(f"[WARN] agent-behavior.md exit: {w}")
286
+
287
+ # Validate communication protocol distinction
288
+ comm_errors, comm_warnings = validate_communication_protocols(guide_content)
289
+ for e in comm_errors:
290
+ report.errors += 1
291
+ report.details.append(f"[ERROR] agent-behavior.md comm: {e}")
292
+ for w in comm_warnings:
293
+ if strict:
294
+ report.errors += 1
295
+ report.details.append(f"[ERROR] agent-behavior.md comm: {w}")
296
+ else:
297
+ report.warnings += 1
298
+ report.details.append(f"[WARN] agent-behavior.md comm: {w}")
299
+ else:
300
+ report.errors += 1
301
+ report.details.append("[ERROR] agent-behavior.md guide not found")
302
+
303
+ # Validate lead agents
304
+ agents_dir = root / "pennyfarthing-dist" / "agents"
305
+ if agents_dir.is_dir():
306
+ for agent_name in ("dev", "reviewer"):
307
+ agent_path = agents_dir / f"{agent_name}.md"
308
+ if agent_path.is_file():
309
+ lead_errors, lead_warnings = validate_lead_agent_team_mode(agent_path)
310
+ for e in lead_errors:
311
+ report.errors += 1
312
+ report.details.append(f"[ERROR] {agent_name}.md: {e}")
313
+ for w in lead_warnings:
314
+ if strict:
315
+ report.errors += 1
316
+ report.details.append(f"[ERROR] {agent_name}.md: {w}")
317
+ else:
318
+ report.warnings += 1
319
+ report.details.append(f"[WARN] {agent_name}.md: {w}")
320
+ if not lead_errors:
321
+ report.passed += 1
322
+
323
+ return report
@@ -16,6 +16,8 @@ Usage:
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
+ from datetime import UTC
20
+
19
21
  import click
20
22
 
21
23
 
@@ -141,7 +143,6 @@ def workflow_list_cmd():
141
143
 
142
144
  Shows a markdown table with type, phases/steps, modes, and descriptions.
143
145
  """
144
- import yaml as yaml_mod
145
146
 
146
147
  from pennyfarthing_scripts.workflow.helpers import (
147
148
  count_steps,
@@ -353,7 +354,7 @@ def workflow_start_cmd(name: str, mode: str | None):
353
354
  Arguments:
354
355
  NAME - Workflow name (e.g., architecture, release)
355
356
  """
356
- from datetime import datetime, timezone
357
+ from datetime import datetime
357
358
 
358
359
  from pennyfarthing_scripts.common.config import get_project_root
359
360
  from pennyfarthing_scripts.workflow.helpers import (
@@ -444,7 +445,7 @@ def workflow_start_cmd(name: str, mode: str | None):
444
445
  return
445
446
 
446
447
  # Create session file
447
- now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
448
+ now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
448
449
  wf_agent = wf.get("agent", "pm")
449
450
  wf_desc = wf.get("description", "-")
450
451
 
@@ -516,7 +517,7 @@ def workflow_resume_cmd(name: str | None):
516
517
  Arguments:
517
518
  NAME - Workflow name (auto-detects from active session if omitted)
518
519
  """
519
- from datetime import datetime, timezone
520
+ from datetime import datetime
520
521
 
521
522
  from pennyfarthing_scripts.common.config import get_project_root
522
523
  from pennyfarthing_scripts.workflow.helpers import (
@@ -601,7 +602,7 @@ def workflow_resume_cmd(name: str | None):
601
602
  raise SystemExit(1)
602
603
 
603
604
  # Update last updated timestamp
604
- now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
605
+ now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
605
606
  import re
606
607
 
607
608
  updated_content = re.sub(
@@ -788,7 +789,7 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
788
789
  TARGET_PHASE - Target phase to set (e.g., review, approved, finish)
789
790
  """
790
791
  import re
791
- from datetime import datetime, timezone
792
+ from datetime import datetime
792
793
 
793
794
  from pennyfarthing_scripts.common.config import get_project_root
794
795
  from pennyfarthing_scripts.workflow.helpers import (
@@ -849,17 +850,17 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
849
850
  # Find indices
850
851
  try:
851
852
  current_idx = phases.index(current_phase)
852
- except ValueError:
853
+ except ValueError as err:
853
854
  click.echo(f"Error: Current phase '{current_phase}' not found in {workflow_name} workflow", err=True)
854
855
  click.echo(f"Valid phases: {', '.join(phases)}", err=True)
855
- raise SystemExit(1)
856
+ raise SystemExit(1) from err
856
857
 
857
858
  try:
858
859
  target_idx = phases.index(target_phase)
859
- except ValueError:
860
+ except ValueError as err:
860
861
  click.echo(f"Error: Target phase '{target_phase}' not found in {workflow_name} workflow", err=True)
861
862
  click.echo(f"Valid phases: {', '.join(phases)}", err=True)
862
- raise SystemExit(1)
863
+ raise SystemExit(1) from err
863
864
 
864
865
  if target_idx <= current_idx:
865
866
  click.echo(f"Error: Target phase '{target_phase}' is not ahead of current phase '{current_phase}'", err=True)
@@ -867,7 +868,7 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
867
868
  raise SystemExit(1)
868
869
 
869
870
  # Calculate transitions
870
- now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
871
+ now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
871
872
  click.echo("")
872
873
  click.echo("Transitions needed:")
873
874
 
@@ -909,7 +910,7 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
909
910
 
910
911
  # Build handoff history additions
911
912
  handoff_lines = []
912
- for from_phase, to_phase, from_agent, to_agent, gate in transitions:
913
+ for _from_phase, _to_phase, from_agent, to_agent, gate in transitions:
913
914
  handoff_lines.append(f"| {from_agent} | {to_agent} | {gate} | PASSED | {now} |")
914
915
 
915
916
  # Insert handoff rows after the last PASSED/FAILED row
@@ -951,7 +952,7 @@ def workflow_complete_step_cmd(name: str | None, step_override: int | None):
951
952
  NAME - Workflow name (auto-detects from session if omitted)
952
953
  """
953
954
  import re
954
- from datetime import datetime, timezone
955
+ from datetime import datetime
955
956
 
956
957
  from pennyfarthing_scripts.common.config import get_project_root
957
958
  from pennyfarthing_scripts.workflow.helpers import (
@@ -1036,7 +1037,7 @@ def workflow_complete_step_cmd(name: str | None, step_override: int | None):
1036
1037
  new_status = "completed" if completed_count >= step_count else "in_progress"
1037
1038
 
1038
1039
  # Update session file
1039
- now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
1040
+ now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
1040
1041
 
1041
1042
  content = re.sub(
1042
1043
  r"^- \*\*Current Step:\*\*.*$",
@@ -7,7 +7,6 @@ state detection from .session/ files.
7
7
 
8
8
  from typing import Any
9
9
 
10
-
11
10
  # Phase ownership mapping for TDD workflow
12
11
  # Canonical YAML names: setup, red, green, review, finish
13
12
  TDD_PHASE_OWNERS: dict[str, str] = {
@@ -10,11 +10,10 @@ Python port of packages/core/dist/workflow/team-lifecycle.js.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
- from datetime import datetime, timezone
13
+ from datetime import UTC, datetime
14
14
  from pathlib import Path
15
15
  from typing import Any
16
16
 
17
-
18
17
  # =============================================================================
19
18
  # In-memory registries
20
19
  # =============================================================================
@@ -61,7 +60,7 @@ async def create_team(
61
60
  "storyId": story_id,
62
61
  "phase": phase["name"],
63
62
  "teammates": [],
64
- "createdAt": datetime.now(timezone.utc).isoformat(),
63
+ "createdAt": datetime.now(UTC).isoformat(),
65
64
  }
66
65
 
67
66
  if adapter:
@@ -213,7 +212,7 @@ def acquire_sidecar_lock(
213
212
  lock: dict[str, Any] = {
214
213
  "lockPath": f"{file_path}.lock",
215
214
  "storyId": story_id,
216
- "acquiredAt": datetime.now(timezone.utc).isoformat(),
215
+ "acquiredAt": datetime.now(UTC).isoformat(),
217
216
  }
218
217
  _sidecar_locks[file_path] = lock
219
218
  return {"success": True, "data": lock}