@pennyfarthing/core 11.1.1 → 11.2.1

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 (487) hide show
  1. package/README.md +8 -8
  2. package/package.json +2 -1
  3. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor.js +381 -66
  5. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  6. package/packages/core/dist/cli/commands/init.js +4 -4
  7. package/packages/core/dist/cli/commands/init.js.map +1 -1
  8. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  9. package/packages/core/dist/cli/commands/update.js +4 -5
  10. package/packages/core/dist/cli/commands/update.js.map +1 -1
  11. package/packages/core/dist/cli/utils/constants.d.ts +3 -8
  12. package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
  13. package/packages/core/dist/cli/utils/constants.js +3 -4
  14. package/packages/core/dist/cli/utils/constants.js.map +1 -1
  15. package/packages/core/dist/cli/utils/settings.d.ts +11 -0
  16. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  17. package/packages/core/dist/cli/utils/settings.js +65 -29
  18. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  19. package/packages/core/dist/cli/utils/symlinks.js +16 -16
  20. package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
  21. package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
  22. package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
  23. package/packages/core/dist/consultation/tandem-metrics.js +131 -0
  24. package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
  25. package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
  26. package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
  27. package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
  28. package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
  29. package/packages/core/dist/public/js/react/react.js +14 -14
  30. package/packages/core/dist/scripts/benchmark-integration.d.ts +182 -0
  31. package/packages/core/dist/scripts/benchmark-integration.d.ts.map +1 -0
  32. package/packages/core/dist/scripts/benchmark-integration.js +691 -0
  33. package/packages/core/dist/scripts/benchmark-integration.js.map +1 -0
  34. package/packages/core/dist/scripts/job-fair-aggregator.d.ts +150 -0
  35. package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +1 -0
  36. package/packages/core/dist/scripts/job-fair-aggregator.js +547 -0
  37. package/packages/core/dist/scripts/job-fair-aggregator.js.map +1 -0
  38. package/packages/core/dist/server/api/agent-load.js +1 -1
  39. package/packages/core/dist/server/api/agent-load.js.map +1 -1
  40. package/packages/core/dist/server/otlp-receiver.d.ts +16 -11
  41. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  42. package/packages/core/dist/server/otlp-receiver.js +185 -24
  43. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  44. package/packages/core/dist/server/otlp-receiver.test.d.ts +21 -0
  45. package/packages/core/dist/server/otlp-receiver.test.d.ts.map +1 -0
  46. package/packages/core/dist/server/otlp-receiver.test.js +446 -0
  47. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -0
  48. package/packages/core/dist/server/server.d.ts +0 -3
  49. package/packages/core/dist/server/server.d.ts.map +1 -1
  50. package/packages/core/dist/server/server.js +3 -37
  51. package/packages/core/dist/server/server.js.map +1 -1
  52. package/packages/core/dist/server/server.test.d.ts +1 -1
  53. package/packages/core/dist/server/server.test.js +12 -23
  54. package/packages/core/dist/server/server.test.js.map +1 -1
  55. package/packages/core/dist/shared/capabilities.d.ts +88 -0
  56. package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
  57. package/packages/core/dist/shared/capabilities.js +133 -0
  58. package/packages/core/dist/shared/capabilities.js.map +1 -0
  59. package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
  60. package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
  61. package/packages/core/dist/shared/capabilities.test.js +217 -0
  62. package/packages/core/dist/shared/capabilities.test.js.map +1 -0
  63. package/packages/core/dist/shared/portrait-resolver.d.ts +9 -0
  64. package/packages/core/dist/shared/portrait-resolver.d.ts.map +1 -1
  65. package/packages/core/dist/shared/portrait-resolver.js +27 -0
  66. package/packages/core/dist/shared/portrait-resolver.js.map +1 -1
  67. package/packages/core/dist/shared/portrait-resolver.test.js +47 -1
  68. package/packages/core/dist/shared/portrait-resolver.test.js.map +1 -1
  69. package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
  70. package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
  71. package/packages/core/dist/shared/spawn-prompt.js +82 -0
  72. package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
  73. package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
  74. package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
  75. package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
  76. package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
  77. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts +13 -0
  78. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts.map +1 -0
  79. package/packages/core/dist/shared/tandem-portrait-inventory.test.js +126 -0
  80. package/packages/core/dist/shared/tandem-portrait-inventory.test.js.map +1 -0
  81. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
  82. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
  83. package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
  84. package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
  85. package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
  86. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  87. package/packages/core/dist/workflow/workflow-schema.js +120 -0
  88. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  89. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  90. package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
  91. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  92. package/pennyfarthing-dist/agents/dev.md +7 -11
  93. package/pennyfarthing-dist/agents/reviewer.md +9 -3
  94. package/pennyfarthing-dist/agents/sm-finish.md +18 -1
  95. package/pennyfarthing-dist/agents/sm-setup.md +1 -1
  96. package/pennyfarthing-dist/agents/sm.md +2 -2
  97. package/pennyfarthing-dist/agents/tea.md +1 -1
  98. package/pennyfarthing-dist/agents/testing-runner.md +2 -1
  99. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  100. package/pennyfarthing-dist/commands/pf-git.md +4 -2
  101. package/pennyfarthing-dist/commands/pf-standalone.md +7 -2
  102. package/pennyfarthing-dist/gates/approval.md +63 -0
  103. package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
  104. package/pennyfarthing-dist/gates/context-ok.md +56 -0
  105. package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
  106. package/pennyfarthing-dist/gates/quality-pass.md +67 -0
  107. package/pennyfarthing-dist/gates/tests-fail.md +84 -0
  108. package/pennyfarthing-dist/gates/tests-pass.md +79 -0
  109. package/pennyfarthing-dist/guides/agent-behavior.md +23 -19
  110. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +1 -1
  111. package/pennyfarthing-dist/guides/bell-mode.md +1 -1
  112. package/pennyfarthing-dist/guides/bikerack.md +3 -3
  113. package/pennyfarthing-dist/guides/hooks.md +29 -29
  114. package/pennyfarthing-dist/guides/reflector.md +1 -1
  115. package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
  116. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  117. package/pennyfarthing-dist/guides/xml-tags.md +2 -2
  118. package/pennyfarthing-dist/scripts/README.md +1 -1
  119. package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
  120. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +5 -87
  121. package/pennyfarthing-dist/scripts/git/README.md +24 -14
  122. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +5 -266
  123. package/pennyfarthing-dist/scripts/git/git-status-all.sh +5 -151
  124. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +6 -144
  125. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +5 -496
  126. package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
  127. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  128. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
  129. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
  130. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
  131. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
  132. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +9 -11
  133. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +27 -33
  134. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
  135. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
  136. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
  137. package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
  138. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
  139. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
  140. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +4 -93
  141. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  142. package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
  143. package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +76 -0
  144. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +4 -221
  145. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +5 -13
  146. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +4 -123
  147. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +4 -33
  148. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +4 -156
  149. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +4 -131
  150. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +4 -249
  151. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +4 -160
  152. package/pennyfarthing-dist/skills/pf-bc/usage.md +1 -1
  153. package/pennyfarthing-dist/skills/pf-jira/examples.md +5 -2
  154. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -16
  155. package/pennyfarthing-dist/skills/pf-workflow/skill.md +9 -12
  156. package/pennyfarthing-dist/skills/pf-workflow/usage.md +33 -8
  157. package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
  158. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +18 -6
  159. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
  160. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
  161. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
  162. package/pennyfarthing-dist/workflows/review-tandem.yaml +65 -0
  163. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +16 -8
  164. package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
  165. package/pennyfarthing_scripts/CLAUDE.md +45 -14
  166. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  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.cpython-314.pyc +0 -0
  174. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  179. package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
  180. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  181. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  182. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  183. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  184. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  185. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/bc/__pycache__/__init__.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  188. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  189. package/pennyfarthing_scripts/bc/cli.py +3 -5
  190. package/pennyfarthing_scripts/bellmode_hook.py +12 -296
  191. package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
  192. package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
  193. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  194. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  201. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  202. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  211. package/pennyfarthing_scripts/bikerack/audit_log_panel.py +119 -0
  212. package/pennyfarthing_scripts/bikerack/background_panel.py +86 -5
  213. package/pennyfarthing_scripts/bikerack/base_panel.py +87 -2
  214. package/pennyfarthing_scripts/bikerack/changed_panel.py +125 -29
  215. package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
  216. package/pennyfarthing_scripts/bikerack/debug_panel.py +32 -2
  217. package/pennyfarthing_scripts/bikerack/diffs_panel.py +104 -17
  218. package/pennyfarthing_scripts/bikerack/events.py +28 -0
  219. package/pennyfarthing_scripts/bikerack/git_panel.py +103 -33
  220. package/pennyfarthing_scripts/bikerack/launcher.py +15 -15
  221. package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
  222. package/pennyfarthing_scripts/bikerack/progress_panel.py +315 -0
  223. package/pennyfarthing_scripts/bikerack/sprint_panel.py +395 -32
  224. package/pennyfarthing_scripts/bikerack/story_detail_data.py +244 -0
  225. package/pennyfarthing_scripts/bikerack/story_detail_screen.py +176 -0
  226. package/pennyfarthing_scripts/bikerack/tui.py +575 -37
  227. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  228. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/cli.py +42 -65
  233. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  238. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  239. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  240. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  241. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  242. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  243. package/pennyfarthing_scripts/common/pr_config.py +38 -0
  244. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/consultation/__init__.py +1 -0
  251. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/consultation/cli.py +149 -0
  255. package/pennyfarthing_scripts/consultation/dialogue_manager.py +417 -0
  256. package/pennyfarthing_scripts/context.py +3 -3
  257. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  258. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  259. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  260. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  261. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  262. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  263. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  264. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  266. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  267. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  268. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  269. package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/git/__init__.py +12 -1
  272. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/git/create_branches.py +3 -4
  276. package/pennyfarthing_scripts/git/hooks_installer.py +152 -0
  277. package/pennyfarthing_scripts/git/repos.py +196 -0
  278. package/pennyfarthing_scripts/git/status_all.py +27 -11
  279. package/pennyfarthing_scripts/git/worktree.py +302 -0
  280. package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/git_group/cli.py +143 -40
  283. package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
  284. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  285. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  289. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/handoff/cli.py +33 -1
  291. package/pennyfarthing_scripts/handoff/complete_phase.py +40 -0
  292. package/pennyfarthing_scripts/handoff/marker.py +15 -15
  293. package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
  294. package/pennyfarthing_scripts/handoff/resolve_gate.py +18 -15
  295. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  296. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  297. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/hooks/__init__.py +437 -0
  302. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  303. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  304. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  305. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  306. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  307. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  308. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  309. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  311. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  312. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  313. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  314. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  315. package/pennyfarthing_scripts/hooks/bell_mode.py +215 -0
  316. package/pennyfarthing_scripts/hooks/cli.py +96 -0
  317. package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
  318. package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
  319. package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
  320. package/pennyfarthing_scripts/hooks/pre_edit_check.py +78 -0
  321. package/pennyfarthing_scripts/hooks/reflector_check.py +271 -0
  322. package/pennyfarthing_scripts/hooks/schema_validation.py +203 -0
  323. package/pennyfarthing_scripts/hooks/session_start.py +296 -0
  324. package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
  325. package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
  326. package/pennyfarthing_scripts/hooks/statusline.py +420 -0
  327. package/pennyfarthing_scripts/hooks.py +27 -446
  328. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  329. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  332. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  333. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  334. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  335. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  336. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  337. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  338. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  339. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  340. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  341. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  342. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  343. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  344. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  345. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  346. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  347. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  348. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  349. package/pennyfarthing_scripts/launch/__pycache__/__init__.cpython-314.pyc +0 -0
  350. package/pennyfarthing_scripts/launch/__pycache__/cli.cpython-314.pyc +0 -0
  351. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  352. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  355. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  356. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  357. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  358. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  359. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  360. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  361. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  362. package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
  363. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  364. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  365. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  366. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  367. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  368. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  369. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  370. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  371. package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
  372. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  373. package/pennyfarthing_scripts/prime/heatmap.py +655 -0
  374. package/pennyfarthing_scripts/prime/workflow.py +2 -1
  375. package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
  376. package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
  377. package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
  378. package/pennyfarthing_scripts/session_start_hook.py +4 -186
  379. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  380. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  381. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  382. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  383. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  384. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  385. package/pennyfarthing_scripts/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
  386. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  387. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  388. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  389. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  390. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  391. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  392. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  393. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  394. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  395. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  396. package/pennyfarthing_scripts/sprint/loader.py +15 -1
  397. package/pennyfarthing_scripts/sprint/story_update.py +19 -0
  398. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  399. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  400. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  401. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  402. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  403. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  404. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  405. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  406. package/pennyfarthing_scripts/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
  407. package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
  408. package/pennyfarthing_scripts/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
  409. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  410. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  411. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  412. package/pennyfarthing_scripts/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
  413. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  414. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  415. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
  416. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
  417. package/pennyfarthing_scripts/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
  418. package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
  419. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  420. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  421. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
  422. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  423. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  424. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  425. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  426. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  427. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  428. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
  429. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  430. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  431. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  432. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  433. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  434. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  435. package/pennyfarthing_scripts/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
  436. package/pennyfarthing_scripts/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
  437. package/pennyfarthing_scripts/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
  438. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  439. package/pennyfarthing_scripts/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
  440. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  441. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  442. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  443. package/pennyfarthing_scripts/tests/test_bikerack.py +51 -51
  444. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +811 -0
  445. package/pennyfarthing_scripts/tests/test_handoff_cli.py +16 -11
  446. package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
  447. package/pennyfarthing_scripts/tests/test_workflow_check.py +2 -3
  448. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  449. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  450. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  451. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  452. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  453. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  454. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  455. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  456. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  457. package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
  458. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  459. package/pennyfarthing_scripts/validate/adapters/tandem_awareness.py +254 -0
  460. package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
  461. package/pennyfarthing_scripts/validate/cli.py +17 -5
  462. package/pennyfarthing_scripts/welcome_hook.py +3 -149
  463. package/pennyfarthing_scripts/workflow/__init__.py +40 -0
  464. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  465. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  466. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  467. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  468. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  469. package/pennyfarthing_scripts/workflow/cli.py +1100 -0
  470. package/pennyfarthing_scripts/workflow/helpers.py +241 -0
  471. package/pennyfarthing_scripts/{workflow.py → workflow/scale.py} +0 -104
  472. package/pennyfarthing_scripts/workflow/state.py +112 -0
  473. package/pennyfarthing_scripts/workflow/team_lifecycle.py +257 -0
  474. package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
  475. package/packages/core/dist/scripts/theme-detail.test.js +0 -199
  476. package/pennyfarthing-dist/skills/pf-workflow/scripts/list-workflows.sh +0 -91
  477. package/pennyfarthing-dist/skills/pf-workflow/scripts/resume-workflow.sh +0 -163
  478. package/pennyfarthing-dist/skills/pf-workflow/scripts/show-workflow.sh +0 -138
  479. package/pennyfarthing-dist/skills/pf-workflow/scripts/start-workflow.sh +0 -273
  480. package/pennyfarthing-dist/skills/pf-workflow/scripts/workflow-status.sh +0 -167
  481. package/pennyfarthing_scripts/gate/__pycache__/__init__.cpython-314.pyc +0 -0
  482. package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
  483. package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
  484. package/pennyfarthing_scripts/tests/__pycache__/test_108_2_remove_handoff_fallback.cpython-314-pytest-9.0.2.pyc +0 -0
  485. package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
  486. package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
  487. package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
@@ -0,0 +1,257 @@
1
+ """
2
+ Phase-scoped Team Lifecycle for Story 86-10.
3
+
4
+ Manages the lifecycle of native Agent Teams within workflow phases.
5
+ When a workflow phase has a `team:` config block, the lead agent creates
6
+ a team at phase start, spawns teammates, and cleans up before handoff.
7
+
8
+ Python port of packages/core/dist/workflow/team-lifecycle.js.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from datetime import datetime, timezone
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+
18
+ # =============================================================================
19
+ # In-memory registries
20
+ # =============================================================================
21
+
22
+ _active_teams: dict[str, dict[str, Any]] = {}
23
+ """Active teams keyed by story_id."""
24
+
25
+ _sidecar_locks: dict[str, dict[str, Any]] = {}
26
+ """Sidecar locks keyed by file path."""
27
+
28
+
29
+ def _reset_for_testing() -> None:
30
+ """Reset all in-memory state. For testing only."""
31
+ _active_teams.clear()
32
+ _sidecar_locks.clear()
33
+
34
+
35
+ async def create_team(
36
+ phase: dict[str, Any],
37
+ story_id: str,
38
+ adapter: Any | None = None,
39
+ ) -> dict[str, Any]:
40
+ """Create a phase-scoped team.
41
+
42
+ If phase has no team config, returns success with no handle (no-op).
43
+ If phase has team config, creates team and returns handle.
44
+ """
45
+ if not phase.get("team"):
46
+ return {"success": True}
47
+
48
+ team_name = f"{story_id}-{phase['name']}"
49
+
50
+ # Clean up existing team for same story
51
+ existing = _active_teams.get(story_id)
52
+ if existing and adapter:
53
+ try:
54
+ await adapter.delete_team(existing["teamName"])
55
+ except Exception:
56
+ pass
57
+ del _active_teams[story_id]
58
+
59
+ handle: dict[str, Any] = {
60
+ "teamName": team_name,
61
+ "storyId": story_id,
62
+ "phase": phase["name"],
63
+ "teammates": [],
64
+ "createdAt": datetime.now(timezone.utc).isoformat(),
65
+ }
66
+
67
+ if adapter:
68
+ try:
69
+ await adapter.create_team({"teamName": team_name})
70
+ except Exception as exc:
71
+ return {"success": False, "error": str(exc)}
72
+
73
+ _active_teams[story_id] = handle
74
+ return {"success": True, "data": handle}
75
+
76
+
77
+ async def spawn_teammates(
78
+ handle: dict[str, Any],
79
+ config: dict[str, Any],
80
+ story_id: str,
81
+ phase: dict[str, Any],
82
+ adapter: Any | None = None,
83
+ ) -> dict[str, Any]:
84
+ """Spawn all teammates for a team based on workflow YAML config."""
85
+ teammates: list[dict[str, Any]] = []
86
+
87
+ for member in config["teammates"]:
88
+ teammate: dict[str, Any] = {
89
+ "agent": member["agent"],
90
+ "task": member["task"],
91
+ "status": "spawned",
92
+ }
93
+ if adapter:
94
+ try:
95
+ await adapter.spawn_teammate({
96
+ "teamName": handle["teamName"],
97
+ "agent": member["agent"],
98
+ "prompt": f'pf agent start "{member["agent"]}"',
99
+ "model": config.get("model"),
100
+ })
101
+ except Exception:
102
+ teammate["status"] = "crashed"
103
+ teammates.append(teammate)
104
+
105
+ handle["teammates"] = teammates
106
+
107
+ # Update registry
108
+ if handle.get("storyId") in _active_teams:
109
+ _active_teams[handle["storyId"]] = handle
110
+
111
+ return {"success": True, "data": teammates}
112
+
113
+
114
+ async def shutdown_all_teammates(
115
+ handle: dict[str, Any],
116
+ adapter: Any | None = None,
117
+ ) -> dict[str, Any]:
118
+ """Shut down all active teammates in a team."""
119
+ shutdown_count = 0
120
+
121
+ for teammate in handle["teammates"]:
122
+ if teammate["status"] in ("shutdown", "crashed"):
123
+ continue
124
+ if adapter:
125
+ try:
126
+ await adapter.shutdown_teammate({
127
+ "teamName": handle["teamName"],
128
+ "agent": teammate["agent"],
129
+ })
130
+ except Exception:
131
+ pass # Graceful degradation — swallow adapter errors
132
+ teammate["status"] = "shutdown"
133
+ shutdown_count += 1
134
+
135
+ return {"success": True, "data": {"shutdownCount": shutdown_count}}
136
+
137
+
138
+ async def cleanup_team(
139
+ handle: dict[str, Any],
140
+ adapter: Any | None = None,
141
+ ) -> dict[str, Any]:
142
+ """Clean up a team entirely (TeamDelete). Must run before pf handoff."""
143
+ if adapter:
144
+ try:
145
+ await adapter.delete_team(handle["teamName"])
146
+ except Exception:
147
+ pass
148
+
149
+ _active_teams.pop(handle.get("storyId", ""), None)
150
+ return {"success": True, "data": {"cleaned": True}}
151
+
152
+
153
+ def check_gate_on_task_completed(
154
+ handle: dict[str, Any],
155
+ phase: dict[str, Any],
156
+ ) -> dict[str, Any]:
157
+ """Check gate condition when a TaskCompleted event fires."""
158
+ if not phase.get("gate"):
159
+ return {"passed": True, "gate": "none"}
160
+
161
+ gate_type = phase["gate"].get("type", "unknown")
162
+ has_active = any(t["status"] == "active" for t in handle["teammates"])
163
+
164
+ if has_active:
165
+ return {"passed": False, "gate": gate_type, "reason": "Teammates still active"}
166
+
167
+ return {"passed": True, "gate": gate_type}
168
+
169
+
170
+ def check_gate_on_teammate_idle(
171
+ handle: dict[str, Any],
172
+ teammate: dict[str, Any],
173
+ phase: dict[str, Any],
174
+ ) -> dict[str, Any]:
175
+ """Check gate condition when a TeammateIdle event fires."""
176
+ if not phase.get("gate"):
177
+ return {"passed": True, "gate": "none"}
178
+
179
+ gate_type = phase["gate"].get("type", "unknown")
180
+
181
+ if teammate["status"] == "crashed":
182
+ return {"passed": False, "gate": gate_type, "reason": "Teammate crashed"}
183
+
184
+ return {"passed": True, "gate": gate_type}
185
+
186
+
187
+ def generate_team_summary(handle: dict[str, Any]) -> dict[str, Any]:
188
+ """Generate a team activity summary for the session file audit trail."""
189
+ return {
190
+ "teamName": handle["teamName"],
191
+ "storyId": handle["storyId"],
192
+ "phase": handle["phase"],
193
+ "members": [
194
+ {"agent": t["agent"], "status": t["status"], "task": t["task"]}
195
+ for t in handle["teammates"]
196
+ ],
197
+ "cleanShutdown": all(t["status"] == "shutdown" for t in handle["teammates"]),
198
+ }
199
+
200
+
201
+ def acquire_sidecar_lock(
202
+ file_path: str,
203
+ story_id: str,
204
+ timeout: int = 5000,
205
+ ) -> dict[str, Any]:
206
+ """Acquire an exclusive lock for sidecar file writing."""
207
+ existing = _sidecar_locks.get(file_path)
208
+ if existing:
209
+ if existing["storyId"] == story_id:
210
+ return {"success": True, "data": existing}
211
+ return {"success": False, "error": f"Lock held by story {existing['storyId']}"}
212
+
213
+ lock: dict[str, Any] = {
214
+ "lockPath": f"{file_path}.lock",
215
+ "storyId": story_id,
216
+ "acquiredAt": datetime.now(timezone.utc).isoformat(),
217
+ }
218
+ _sidecar_locks[file_path] = lock
219
+ return {"success": True, "data": lock}
220
+
221
+
222
+ def release_sidecar_lock(lock: dict[str, Any]) -> dict[str, Any]:
223
+ """Release a sidecar file lock."""
224
+ for path, held in list(_sidecar_locks.items()):
225
+ if held["lockPath"] == lock["lockPath"]:
226
+ del _sidecar_locks[path]
227
+ break
228
+ return {"success": True}
229
+
230
+
231
+ def get_active_team(story_id: str) -> dict[str, Any] | None:
232
+ """Get the active team for a story, if any."""
233
+ return _active_teams.get(story_id)
234
+
235
+
236
+ def update_session_with_summary(
237
+ session_path: str | Path,
238
+ summary: dict[str, Any],
239
+ ) -> dict[str, Any]:
240
+ """Write team activity summary to session file for audit trail."""
241
+ path = Path(session_path)
242
+ content = path.read_text() if path.exists() else ""
243
+
244
+ lines = [
245
+ "\n## Team Activity Summary\n",
246
+ f"**Team:** {summary['teamName']}",
247
+ f"**Phase:** {summary['phase']}",
248
+ f"**Clean Shutdown:** {'Yes' if summary.get('cleanShutdown') else 'No'}\n",
249
+ "| Agent | Status | Task |",
250
+ "|-------|--------|------|",
251
+ ]
252
+ for member in summary.get("members", []):
253
+ lines.append(f"| {member['agent']} | {member['status']} | {member['task']} |")
254
+
255
+ content += "\n".join(lines) + "\n"
256
+ path.write_text(content)
257
+ return {"success": True}
@@ -1,10 +0,0 @@
1
- /**
2
- * Story 13-5: Theme Detail Page Tests
3
- *
4
- * Tests for the theme detail page with team spider chart,
5
- * agent grid with ProfileCards, and profile links.
6
- *
7
- * Run with: npm test
8
- */
9
- export {};
10
- //# sourceMappingURL=theme-detail.test.d.ts.map
@@ -1,199 +0,0 @@
1
- /**
2
- * Story 13-5: Theme Detail Page Tests
3
- *
4
- * Tests for the theme detail page with team spider chart,
5
- * agent grid with ProfileCards, and profile links.
6
- *
7
- * Run with: npm test
8
- */
9
- import { describe, it } from 'node:test';
10
- import assert from 'node:assert';
11
- import { existsSync, readFileSync } from 'fs';
12
- import { join, dirname } from 'path';
13
- import { fileURLToPath } from 'url';
14
- import { findMonorepoRoot } from '../cli/utils/files.js';
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = dirname(__filename);
17
- // Find monorepo root by walking up from current directory
18
- const projectRoot = findMonorepoRoot(__dirname);
19
- const PAGES_DIR = join(projectRoot, 'internal', 'showcase', 'src', 'pages');
20
- const COMPONENTS_DIR = join(projectRoot, 'internal', 'showcase', 'src', 'components');
21
- describe('Story 13-5: Theme Detail Page', () => {
22
- describe('AC1: Theme detail pages generated for all themes', () => {
23
- it('should have dynamic [theme].astro route', () => {
24
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
25
- assert.ok(existsSync(pagePath), 'Dynamic theme page should exist');
26
- });
27
- it('should use getStaticPaths for dynamic routing', () => {
28
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
29
- assert.ok(existsSync(pagePath), 'Page file should exist');
30
- const content = readFileSync(pagePath, 'utf-8');
31
- assert.match(content, /getStaticPaths/, 'Should use getStaticPaths');
32
- });
33
- it('should import loadThemes for generating paths', () => {
34
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
35
- assert.ok(existsSync(pagePath), 'Page file should exist');
36
- const content = readFileSync(pagePath, 'utf-8');
37
- assert.match(content, /import.*loadThemes.*from/, 'Should import loadThemes');
38
- });
39
- it('should generate paths for all themes', () => {
40
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
41
- assert.ok(existsSync(pagePath), 'Page file should exist');
42
- const content = readFileSync(pagePath, 'utf-8');
43
- // Should map themes to params
44
- assert.match(content, /themes\.map|\.map.*params/, 'Should map themes to params');
45
- });
46
- it('should display theme name in header', () => {
47
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
48
- assert.ok(existsSync(pagePath), 'Page file should exist');
49
- const content = readFileSync(pagePath, 'utf-8');
50
- assert.match(content, /metadata\.name|theme\.metadata\.name/, 'Should display theme name');
51
- });
52
- it('should display theme description', () => {
53
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
54
- assert.ok(existsSync(pagePath), 'Page file should exist');
55
- const content = readFileSync(pagePath, 'utf-8');
56
- assert.match(content, /metadata\.description|theme\.metadata\.description/, 'Should display description');
57
- });
58
- it('should display theme source', () => {
59
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
60
- assert.ok(existsSync(pagePath), 'Page file should exist');
61
- const content = readFileSync(pagePath, 'utf-8');
62
- assert.match(content, /metadata\.source|theme\.metadata\.source/, 'Should display source');
63
- });
64
- });
65
- describe('AC2: Team overlay spider displayed prominently (300px+)', () => {
66
- it('should include SpiderChart in detail page', () => {
67
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
68
- assert.ok(existsSync(pagePath), 'Page file should exist');
69
- const content = readFileSync(pagePath, 'utf-8');
70
- assert.match(content, /SpiderChart/, 'Should include SpiderChart');
71
- });
72
- it('should import SpiderChart component', () => {
73
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
74
- assert.ok(existsSync(pagePath), 'Page file should exist');
75
- const content = readFileSync(pagePath, 'utf-8');
76
- assert.match(content, /import.*SpiderChart.*from/, 'Should import SpiderChart');
77
- });
78
- it('should pass size prop of at least 300 to team spider', () => {
79
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
80
- assert.ok(existsSync(pagePath), 'Page file should exist');
81
- const content = readFileSync(pagePath, 'utf-8');
82
- // Should have size={300} or larger
83
- const sizeMatch = content.match(/SpiderChart[\s\S]*?size=\{?(\d+)/);
84
- assert.ok(sizeMatch, 'Should have size prop on SpiderChart');
85
- if (sizeMatch) {
86
- assert.ok(parseInt(sizeMatch[1]) >= 300, 'Size should be at least 300');
87
- }
88
- });
89
- it('should pass all theme agents to team spider', () => {
90
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
91
- assert.ok(existsSync(pagePath), 'Page file should exist');
92
- const content = readFileSync(pagePath, 'utf-8');
93
- // Should pass theme.agents or agents array
94
- assert.match(content, /SpiderChart[\s\S]*?agents=\{.*agents/, 'Should pass agents to SpiderChart');
95
- });
96
- });
97
- describe('AC3: All 10 agents shown with face + spider + quote', () => {
98
- it('should have ProfileCard component', () => {
99
- const componentPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
100
- assert.ok(existsSync(componentPath), 'ProfileCard component should exist');
101
- });
102
- it('should display character name in ProfileCard', () => {
103
- const cardPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
104
- assert.ok(existsSync(cardPath), 'ProfileCard file should exist');
105
- const content = readFileSync(cardPath, 'utf-8');
106
- assert.match(content, /agent\.character|character/, 'Should display character name');
107
- });
108
- it('should display quote in ProfileCard', () => {
109
- const cardPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
110
- assert.ok(existsSync(cardPath), 'ProfileCard file should exist');
111
- const content = readFileSync(cardPath, 'utf-8');
112
- assert.match(content, /agent\.quote|quote/, 'Should display quote');
113
- });
114
- it('should include SpiderChart in ProfileCard', () => {
115
- const cardPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
116
- assert.ok(existsSync(cardPath), 'ProfileCard file should exist');
117
- const content = readFileSync(cardPath, 'utf-8');
118
- assert.match(content, /SpiderChart/, 'Should include SpiderChart');
119
- });
120
- it('should show agent emoji or face placeholder', () => {
121
- const cardPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
122
- assert.ok(existsSync(cardPath), 'ProfileCard file should exist');
123
- const content = readFileSync(cardPath, 'utf-8');
124
- // Should have emoji, avatar, or face reference
125
- assert.match(content, /emoji|avatar|face|icon/i, 'Should show face or icon');
126
- });
127
- it('should have AgentGrid component for 2x5 layout', () => {
128
- const gridPath = join(COMPONENTS_DIR, 'AgentGrid.astro');
129
- assert.ok(existsSync(gridPath), 'AgentGrid component should exist');
130
- });
131
- it('should use responsive grid in AgentGrid', () => {
132
- const gridPath = join(COMPONENTS_DIR, 'AgentGrid.astro');
133
- assert.ok(existsSync(gridPath), 'AgentGrid file should exist');
134
- const content = readFileSync(gridPath, 'utf-8');
135
- // Should have grid-cols classes for responsive 2x5 layout
136
- assert.match(content, /grid-cols/, 'Should use grid-cols for layout');
137
- });
138
- it('should render ProfileCard for each agent in detail page', () => {
139
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
140
- assert.ok(existsSync(pagePath), 'Page file should exist');
141
- const content = readFileSync(pagePath, 'utf-8');
142
- // Should map agents to ProfileCard components
143
- assert.match(content, /ProfileCard/, 'Should use ProfileCard');
144
- assert.match(content, /\.map\s*\(/, 'Should map agents to components');
145
- });
146
- it('should include AgentGrid in detail page', () => {
147
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
148
- assert.ok(existsSync(pagePath), 'Page file should exist');
149
- const content = readFileSync(pagePath, 'utf-8');
150
- assert.match(content, /AgentGrid/, 'Should include AgentGrid');
151
- });
152
- });
153
- describe('AC4: Links to individual profile pages work', () => {
154
- it('should have link in ProfileCard', () => {
155
- const cardPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
156
- assert.ok(existsSync(cardPath), 'ProfileCard file should exist');
157
- const content = readFileSync(cardPath, 'utf-8');
158
- assert.match(content, /<a\s|href=/, 'Should have anchor link');
159
- });
160
- it('should link to /characters/[theme]/[role] pattern', () => {
161
- const cardPath = join(COMPONENTS_DIR, 'ProfileCard.astro');
162
- assert.ok(existsSync(cardPath), 'ProfileCard file should exist');
163
- const content = readFileSync(cardPath, 'utf-8');
164
- // Should have href pointing to /characters/{theme}/{role}
165
- assert.match(content, /href=.*characters.*\//, 'Should link to characters path');
166
- });
167
- it('should pass themeId to ProfileCard', () => {
168
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
169
- assert.ok(existsSync(pagePath), 'Page file should exist');
170
- const content = readFileSync(pagePath, 'utf-8');
171
- // ProfileCard needs themeId for building profile links
172
- assert.match(content, /ProfileCard[\s\S]*?themeId=|theme\.id/, 'Should pass themeId to ProfileCard');
173
- });
174
- });
175
- describe('Component integration', () => {
176
- it('should use Base layout in detail page', () => {
177
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
178
- assert.ok(existsSync(pagePath), 'Page file should exist');
179
- const content = readFileSync(pagePath, 'utf-8');
180
- assert.match(content, /import.*Base.*from.*layouts/, 'Should import Base layout');
181
- assert.match(content, /<Base/, 'Should use Base component');
182
- });
183
- it('should have dynamic page title with theme name', () => {
184
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
185
- assert.ok(existsSync(pagePath), 'Page file should exist');
186
- const content = readFileSync(pagePath, 'utf-8');
187
- // Title should include theme name
188
- assert.match(content, /title=.*metadata\.name|title=.*theme/, 'Should have dynamic title');
189
- });
190
- it('should have Compare this team button', () => {
191
- const pagePath = join(PAGES_DIR, 'themes', '[theme].astro');
192
- assert.ok(existsSync(pagePath), 'Page file should exist');
193
- const content = readFileSync(pagePath, 'utf-8');
194
- // Should have compare button/link
195
- assert.match(content, /[Cc]ompare|compare/i, 'Should have compare button');
196
- });
197
- });
198
- });
199
- //# sourceMappingURL=theme-detail.test.js.map
@@ -1,91 +0,0 @@
1
- #!/bin/bash
2
- # List all available workflows with type indicators
3
- # Usage: .pennyfarthing/scripts/workflow/list-workflows.sh
4
- # or: Invoked with PROJECT_ROOT already set
5
- #
6
- # MSSCI-12083: Added type, steps, and modes columns
7
-
8
- set -euo pipefail
9
-
10
- # PROJECT_ROOT should be set by find-root.sh, but find it if not
11
- if [[ -z "${PROJECT_ROOT:-}" ]]; then
12
- d="$PWD"
13
- while [[ ! -d "$d/.claude" ]] && [[ "$d" != "/" ]]; do
14
- d="$(dirname "$d")"
15
- done
16
- PROJECT_ROOT="$d"
17
- fi
18
-
19
- WORKFLOWS_DIR="$PROJECT_ROOT/.pennyfarthing/workflows"
20
-
21
- if [[ ! -d "$WORKFLOWS_DIR" ]]; then
22
- echo "Error: Workflows directory not found at $WORKFLOWS_DIR"
23
- exit 1
24
- fi
25
-
26
- if ! command -v yq &> /dev/null; then
27
- echo "Error: yq is required but not installed"
28
- echo "Install with: brew install yq"
29
- exit 1
30
- fi
31
-
32
- echo "# Available Workflows"
33
- echo ""
34
- echo "| Workflow | Type | Default | Steps/Phases | Modes | Description |"
35
- echo "|----------|------|---------|--------------|-------|-------------|"
36
-
37
- for f in "$WORKFLOWS_DIR"/*.yaml; do
38
- [[ -f "$f" ]] || continue
39
-
40
- name=$(yq eval '.workflow.name' "$f")
41
- desc=$(yq eval '.workflow.description' "$f" | head -1)
42
- is_default=$(yq eval '.workflow.triggers.default // false' "$f")
43
-
44
- # Detect workflow type (stepped vs phased)
45
- # Stepped workflows have .workflow.type == "stepped" or .workflow.steps
46
- workflow_type=$(yq eval '.workflow.type // "phased"' "$f")
47
- has_steps=$(yq eval '.workflow.steps != null' "$f")
48
-
49
- if [[ "$has_steps" == "true" ]] || [[ "$workflow_type" == "stepped" ]]; then
50
- type_col="stepped"
51
- # Count step files if steps.path is defined
52
- steps_path=$(yq eval '.workflow.steps.path // ""' "$f")
53
- steps_pattern=$(yq eval '.workflow.steps.pattern // "step-*.md"' "$f")
54
- if [[ -n "$steps_path" ]] && [[ -d "$PROJECT_ROOT/$steps_path" ]]; then
55
- step_count=$(find "$PROJECT_ROOT/$steps_path" -name "$steps_pattern" 2>/dev/null | wc -l | tr -d ' ')
56
- steps_col="${step_count} steps"
57
- else
58
- steps_col="-"
59
- fi
60
- else
61
- type_col="phased"
62
- # Count phases for phased workflows
63
- phase_count=$(yq eval '.workflow.phases | length' "$f")
64
- steps_col="${phase_count} phases"
65
- fi
66
-
67
- # Default column
68
- if [[ "$is_default" == "true" ]]; then
69
- default_col="yes"
70
- else
71
- default_col="no"
72
- fi
73
-
74
- # Modes column (for tri-modal workflows)
75
- modes=$(yq eval '.workflow.modes.available // []' "$f")
76
- if [[ "$modes" != "[]" ]] && [[ "$modes" != "null" ]]; then
77
- # Format as comma-separated list
78
- modes_col=$(yq eval '.workflow.modes.available | join(",")' "$f")
79
- else
80
- modes_col="-"
81
- fi
82
-
83
- echo "| $name | $type_col | $default_col | $steps_col | $modes_col | $desc |"
84
- done
85
-
86
- echo ""
87
- echo "**Legend:**"
88
- echo "- **phased**: Agent-driven workflow (SM → TEA → Dev → Reviewer)"
89
- echo "- **stepped**: Step-by-step guided workflow with progressive disclosure"
90
- echo ""
91
- echo "Use \`/workflow show <name>\` for workflow details."