@pennyfarthing/core 11.2.0 → 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 (367) hide show
  1. package/README.md +100 -40
  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 +474 -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 +7 -0
  16. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  17. package/packages/core/dist/cli/utils/settings.js +70 -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/dialogue-manager.d.ts +1 -1
  22. package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -1
  23. package/packages/core/dist/consultation/dialogue-manager.js +1 -1
  24. package/packages/core/dist/consultation/dialogue-manager.js.map +1 -1
  25. package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -1
  26. package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
  27. package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
  28. package/packages/core/dist/consultation/tandem-metrics.js +131 -0
  29. package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
  30. package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
  31. package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
  32. package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
  33. package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
  34. package/packages/core/dist/public/css/react.css +1 -1
  35. package/packages/core/dist/public/js/react/react.js +14 -14
  36. package/packages/core/dist/server/api/agent-load.js +1 -1
  37. package/packages/core/dist/server/api/agent-load.js.map +1 -1
  38. package/packages/core/dist/server/api/git.d.ts.map +1 -1
  39. package/packages/core/dist/server/api/git.js +0 -1
  40. package/packages/core/dist/server/api/git.js.map +1 -1
  41. package/packages/core/dist/server/api/index.d.ts +2 -0
  42. package/packages/core/dist/server/api/index.d.ts.map +1 -1
  43. package/packages/core/dist/server/api/index.js +2 -0
  44. package/packages/core/dist/server/api/index.js.map +1 -1
  45. package/packages/core/dist/server/api/project-info.d.ts +11 -0
  46. package/packages/core/dist/server/api/project-info.d.ts.map +1 -0
  47. package/packages/core/dist/server/api/project-info.js +18 -0
  48. package/packages/core/dist/server/api/project-info.js.map +1 -0
  49. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  50. package/packages/core/dist/server/otlp-receiver.js +18 -1
  51. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  52. package/packages/core/dist/server/otlp-receiver.test.js +1 -1
  53. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -1
  54. package/packages/core/dist/server/server.d.ts +0 -3
  55. package/packages/core/dist/server/server.d.ts.map +1 -1
  56. package/packages/core/dist/server/server.js +5 -38
  57. package/packages/core/dist/server/server.js.map +1 -1
  58. package/packages/core/dist/server/server.test.d.ts +1 -1
  59. package/packages/core/dist/server/server.test.js +12 -23
  60. package/packages/core/dist/server/server.test.js.map +1 -1
  61. package/packages/core/dist/server/settings.d.ts +1 -0
  62. package/packages/core/dist/server/settings.d.ts.map +1 -1
  63. package/packages/core/dist/server/settings.js +13 -0
  64. package/packages/core/dist/server/settings.js.map +1 -1
  65. package/packages/core/dist/shared/capabilities.d.ts +88 -0
  66. package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
  67. package/packages/core/dist/shared/capabilities.js +133 -0
  68. package/packages/core/dist/shared/capabilities.js.map +1 -0
  69. package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
  70. package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
  71. package/packages/core/dist/shared/capabilities.test.js +217 -0
  72. package/packages/core/dist/shared/capabilities.test.js.map +1 -0
  73. package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
  74. package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
  75. package/packages/core/dist/shared/spawn-prompt.js +82 -0
  76. package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
  77. package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
  78. package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
  79. package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
  80. package/packages/core/dist/shared/spawn-prompt.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/team-lifecycle.d.ts +169 -0
  86. package/packages/core/dist/workflow/team-lifecycle.d.ts.map +1 -0
  87. package/packages/core/dist/workflow/team-lifecycle.js +217 -0
  88. package/packages/core/dist/workflow/team-lifecycle.js.map +1 -0
  89. package/packages/core/dist/workflow/team-lifecycle.test.d.ts +20 -0
  90. package/packages/core/dist/workflow/team-lifecycle.test.d.ts.map +1 -0
  91. package/packages/core/dist/workflow/team-lifecycle.test.js +966 -0
  92. package/packages/core/dist/workflow/team-lifecycle.test.js.map +1 -0
  93. package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
  94. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  95. package/packages/core/dist/workflow/workflow-schema.js +120 -0
  96. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  97. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  98. package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
  99. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  100. package/packages/core/dist/workflow/workflow-team-templates.test.d.ts +17 -0
  101. package/packages/core/dist/workflow/workflow-team-templates.test.d.ts.map +1 -0
  102. package/packages/core/dist/workflow/workflow-team-templates.test.js +275 -0
  103. package/packages/core/dist/workflow/workflow-team-templates.test.js.map +1 -0
  104. package/pennyfarthing-dist/agents/dev.md +21 -12
  105. package/pennyfarthing-dist/agents/reviewer.md +23 -4
  106. package/pennyfarthing-dist/agents/sm-finish.md +19 -2
  107. package/pennyfarthing-dist/agents/sm-setup.md +7 -7
  108. package/pennyfarthing-dist/agents/sm.md +12 -12
  109. package/pennyfarthing-dist/agents/tea.md +2 -2
  110. package/pennyfarthing-dist/agents/testing-runner.md +1 -1
  111. package/pennyfarthing-dist/commands/pf-architect.md +1 -1
  112. package/pennyfarthing-dist/commands/pf-ba.md +1 -1
  113. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  114. package/pennyfarthing-dist/commands/pf-dev.md +1 -1
  115. package/pennyfarthing-dist/commands/pf-devops.md +1 -1
  116. package/pennyfarthing-dist/commands/pf-epic.md +6 -6
  117. package/pennyfarthing-dist/commands/pf-git.md +12 -10
  118. package/pennyfarthing-dist/commands/pf-health-check.md +1 -1
  119. package/pennyfarthing-dist/commands/pf-help.md +12 -12
  120. package/pennyfarthing-dist/commands/pf-orchestrator.md +1 -1
  121. package/pennyfarthing-dist/commands/pf-pm.md +1 -1
  122. package/pennyfarthing-dist/commands/pf-prime.md +8 -8
  123. package/pennyfarthing-dist/commands/pf-reviewer.md +1 -1
  124. package/pennyfarthing-dist/commands/pf-session.md +7 -7
  125. package/pennyfarthing-dist/commands/pf-sm.md +1 -1
  126. package/pennyfarthing-dist/commands/pf-sprint.md +7 -7
  127. package/pennyfarthing-dist/commands/pf-tea.md +1 -1
  128. package/pennyfarthing-dist/commands/pf-tech-writer.md +1 -1
  129. package/pennyfarthing-dist/commands/pf-theme.md +9 -9
  130. package/pennyfarthing-dist/commands/pf-ux-designer.md +1 -1
  131. package/pennyfarthing-dist/commands/pf-work.md +1 -1
  132. package/pennyfarthing-dist/gates/approval.md +63 -0
  133. package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
  134. package/pennyfarthing-dist/gates/context-ok.md +56 -0
  135. package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
  136. package/pennyfarthing-dist/gates/quality-pass.md +67 -0
  137. package/pennyfarthing-dist/gates/tests-fail.md +84 -0
  138. package/pennyfarthing-dist/gates/tests-pass.md +79 -0
  139. package/pennyfarthing-dist/guides/agent-behavior.md +84 -29
  140. package/pennyfarthing-dist/guides/agent-coordination.md +10 -10
  141. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +6 -6
  142. package/pennyfarthing-dist/guides/agent-template-tactical.md +1 -1
  143. package/pennyfarthing-dist/guides/bell-mode.md +1 -1
  144. package/pennyfarthing-dist/guides/bikerack.md +10 -10
  145. package/pennyfarthing-dist/guides/brownfield-tools.md +24 -24
  146. package/pennyfarthing-dist/guides/command-tag-taxonomy.md +1 -1
  147. package/pennyfarthing-dist/guides/gate-schema.md +2 -2
  148. package/pennyfarthing-dist/guides/gates.md +3 -3
  149. package/pennyfarthing-dist/guides/handoff-cli.md +8 -8
  150. package/pennyfarthing-dist/guides/hooks.md +29 -29
  151. package/pennyfarthing-dist/guides/prime.md +2 -2
  152. package/pennyfarthing-dist/guides/reflector.md +1 -1
  153. package/pennyfarthing-dist/guides/skill-schema.md +6 -6
  154. package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
  155. package/pennyfarthing-dist/guides/workflow-schema.md +1 -1
  156. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  157. package/pennyfarthing-dist/guides/xml-tags.md +8 -8
  158. package/pennyfarthing-dist/scripts/README.md +4 -4
  159. package/pennyfarthing-dist/scripts/core/agent-session.sh +2 -5
  160. package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
  161. package/pennyfarthing-dist/scripts/core/pf.sh +5 -0
  162. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +4 -89
  163. package/pennyfarthing-dist/scripts/core/prime.sh +2 -25
  164. package/pennyfarthing-dist/scripts/git/README.md +14 -14
  165. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +2 -3
  166. package/pennyfarthing-dist/scripts/git/git-status-all.sh +2 -3
  167. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +2 -3
  168. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +2 -4
  169. package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
  170. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
  171. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
  172. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
  173. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
  174. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +5 -4
  175. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +29 -34
  176. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
  177. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
  178. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
  179. package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
  180. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
  181. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
  182. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +3 -93
  183. package/pennyfarthing-dist/scripts/lib/env.sh +34 -0
  184. package/pennyfarthing-dist/scripts/lib/run-pf.sh +39 -0
  185. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  186. package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
  187. package/pennyfarthing-dist/scripts/sprint/README.md +21 -21
  188. package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
  189. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +2 -16
  190. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +3 -3
  191. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +3 -3
  192. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +3 -3
  193. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +3 -3
  194. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +3 -3
  195. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +3 -3
  196. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +3 -3
  197. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +3 -3
  198. package/pennyfarthing-dist/skills/pf-bc/examples.md +23 -23
  199. package/pennyfarthing-dist/skills/pf-bc/skill.md +17 -17
  200. package/pennyfarthing-dist/skills/pf-bc/usage.md +8 -8
  201. package/pennyfarthing-dist/skills/pf-jira/SKILL.md +15 -15
  202. package/pennyfarthing-dist/skills/pf-jira/examples.md +48 -48
  203. package/pennyfarthing-dist/skills/pf-jira/usage.md +15 -15
  204. package/pennyfarthing-dist/skills/pf-sprint/examples.md +80 -80
  205. package/pennyfarthing-dist/skills/pf-sprint/skill.md +35 -35
  206. package/pennyfarthing-dist/skills/pf-sprint/usage.md +30 -30
  207. package/pennyfarthing-dist/skills/pf-theme/examples.md +15 -15
  208. package/pennyfarthing-dist/skills/pf-theme/skill.md +6 -6
  209. package/pennyfarthing-dist/skills/pf-theme/usage.md +5 -5
  210. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -27
  211. package/pennyfarthing-dist/skills/pf-workflow/skill.md +11 -11
  212. package/pennyfarthing-dist/skills/pf-workflow/usage.md +11 -11
  213. package/pennyfarthing-dist/skills/skill-registry.yaml +19 -19
  214. package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
  215. package/pennyfarthing-dist/workflows/bdd-team.yaml +89 -0
  216. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +1 -1
  217. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
  218. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
  219. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
  220. package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +47 -0
  221. package/pennyfarthing-dist/workflows/tdd-team.yaml +80 -0
  222. package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
  223. package/pennyfarthing_scripts/CLAUDE.md +19 -10
  224. package/pennyfarthing_scripts/__init__.py +1 -1
  225. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  233. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/bc/__pycache__/split.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/bc/cli.py +2 -2
  237. package/pennyfarthing_scripts/bellmode_hook.py +9 -296
  238. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  239. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  240. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  241. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  242. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  243. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  244. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  255. package/pennyfarthing_scripts/bikerack/audit_log_panel.py +161 -0
  256. package/pennyfarthing_scripts/bikerack/base_panel.py +27 -4
  257. package/pennyfarthing_scripts/bikerack/changed_panel.py +96 -4
  258. package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
  259. package/pennyfarthing_scripts/bikerack/debug_panel.py +1 -1
  260. package/pennyfarthing_scripts/bikerack/diffs_panel.py +30 -0
  261. package/pennyfarthing_scripts/bikerack/events.py +28 -0
  262. package/pennyfarthing_scripts/bikerack/launcher.py +6 -6
  263. package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
  264. package/pennyfarthing_scripts/bikerack/progress_panel.py +0 -1
  265. package/pennyfarthing_scripts/bikerack/sprint_panel.py +373 -142
  266. package/pennyfarthing_scripts/bikerack/story_detail_data.py +247 -0
  267. package/pennyfarthing_scripts/bikerack/story_detail_screen.py +177 -0
  268. package/pennyfarthing_scripts/bikerack/tui.py +304 -62
  269. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  270. package/pennyfarthing_scripts/cli.py +5 -0
  271. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/common/config.py +29 -2
  273. package/pennyfarthing_scripts/common/pr_config.py +38 -0
  274. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  276. package/pennyfarthing_scripts/consultation/cli.py +3 -3
  277. package/pennyfarthing_scripts/context.py +3 -3
  278. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  279. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  280. package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/git/hooks_installer.py +2 -3
  283. package/pennyfarthing_scripts/git/status_all.py +1 -1
  284. package/pennyfarthing_scripts/git/worktree.py +2 -2
  285. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  289. package/pennyfarthing_scripts/handoff/__pycache__/phase_check.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  291. package/pennyfarthing_scripts/handoff/cli.py +33 -1
  292. package/pennyfarthing_scripts/handoff/complete_phase.py +28 -0
  293. package/pennyfarthing_scripts/handoff/marker.py +15 -15
  294. package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
  295. package/pennyfarthing_scripts/handoff/resolve_gate.py +13 -1
  296. package/pennyfarthing_scripts/hooks/__init__.py +442 -0
  297. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  302. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  303. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  304. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  305. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  306. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  307. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  308. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  309. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/hooks/bell_mode.py +214 -0
  311. package/pennyfarthing_scripts/hooks/cli.py +96 -0
  312. package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
  313. package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
  314. package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
  315. package/pennyfarthing_scripts/hooks/pre_edit_check.py +77 -0
  316. package/pennyfarthing_scripts/hooks/reflector_check.py +270 -0
  317. package/pennyfarthing_scripts/hooks/schema_validation.py +202 -0
  318. package/pennyfarthing_scripts/hooks/session_start.py +294 -0
  319. package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
  320. package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
  321. package/pennyfarthing_scripts/hooks/statusline.py +429 -0
  322. package/pennyfarthing_scripts/hooks.py +27 -432
  323. package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
  324. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  325. package/pennyfarthing_scripts/prime/heatmap.py +3 -15
  326. package/pennyfarthing_scripts/prime/workflow.py +2 -1
  327. package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
  328. package/pennyfarthing_scripts/session_start_hook.py +4 -186
  329. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  332. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  333. package/pennyfarthing_scripts/sprint/cli.py +121 -0
  334. package/pennyfarthing_scripts/sprint/loader.py +154 -3
  335. package/pennyfarthing_scripts/sprint/story_update.py +26 -0
  336. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  337. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  338. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_list_team.cpython-314-pytest-9.0.2.pyc +0 -0
  339. package/pennyfarthing_scripts/tests/test_bikerack.py +26 -26
  340. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +0 -1
  341. package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
  342. package/pennyfarthing_scripts/tests/test_workflow_list_team.py +147 -0
  343. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  344. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  345. package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
  346. package/pennyfarthing_scripts/validate/adapters/__pycache__/team_mode.cpython-314.pyc +0 -0
  347. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  348. package/pennyfarthing_scripts/validate/adapters/team_mode.py +323 -0
  349. package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
  350. package/pennyfarthing_scripts/welcome_hook.py +3 -149
  351. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  352. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  355. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  356. package/pennyfarthing_scripts/workflow/__pycache__/team_lifecycle.cpython-314.pyc +0 -0
  357. package/pennyfarthing_scripts/workflow/cli.py +22 -20
  358. package/pennyfarthing_scripts/workflow/state.py +0 -1
  359. package/pennyfarthing_scripts/workflow/team_lifecycle.py +256 -0
  360. package/packages/core/dist/cli/cyclist-migration.test.d.ts +0 -16
  361. package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +0 -1
  362. package/packages/core/dist/cli/cyclist-migration.test.js +0 -229
  363. package/packages/core/dist/cli/cyclist-migration.test.js.map +0 -1
  364. package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
  365. package/packages/core/dist/scripts/theme-detail.test.d.ts.map +0 -1
  366. package/packages/core/dist/scripts/theme-detail.test.js +0 -199
  367. package/packages/core/dist/scripts/theme-detail.test.js.map +0 -1
@@ -6,7 +6,7 @@ the bash wrapper dialogue-manager.sh interface.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- from datetime import datetime, timezone
9
+ from datetime import UTC, datetime
10
10
  from pathlib import Path
11
11
 
12
12
  import click
@@ -44,7 +44,7 @@ def init(story_id: str, workflow: str, leader: str, partner: str) -> None:
44
44
  workflow=workflow,
45
45
  leader=leader,
46
46
  partner=partner,
47
- started_at=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
47
+ started_at=datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"),
48
48
  )
49
49
 
50
50
  content = create_dialogue_content(header)
@@ -80,7 +80,7 @@ def append(story_id: str, question: str, recommendation: str, confidence: str) -
80
80
 
81
81
  exchange = DialogueExchange(
82
82
  number=next_num,
83
- timestamp=datetime.now(timezone.utc).strftime("%H:%M"),
83
+ timestamp=datetime.now(UTC).strftime("%H:%M"),
84
84
  leader="",
85
85
  partner="",
86
86
  question=question,
@@ -269,7 +269,7 @@ def detect_cyclist(project_dir: str | None = None) -> bool:
269
269
 
270
270
  Checks:
271
271
  1. CYCLIST env var set to '1' (Electron mode - definitive)
272
- 2. .wheelhub-port file exists AND port is responding (Web mode)
272
+ 2. .bikerack-port file exists AND port is responding (Web mode)
273
273
  """
274
274
  # Env var is definitive - set by Cyclist when it spawns Claude
275
275
  if os.environ.get("CYCLIST") == "1":
@@ -284,8 +284,8 @@ def detect_cyclist(project_dir: str | None = None) -> bool:
284
284
  )
285
285
 
286
286
  port_files = [
287
- Path(project_dir) / "packages" / "cyclist" / ".wheelhub-port",
288
- Path(os.getcwd()) / ".wheelhub-port",
287
+ Path(project_dir) / "packages" / "cyclist" / ".bikerack-port",
288
+ Path(os.getcwd()) / ".bikerack-port",
289
289
  ]
290
290
 
291
291
  for port_file in port_files:
@@ -10,7 +10,6 @@ Usage via CLI:
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
- import re
14
13
  from pathlib import Path
15
14
 
16
15
  from pennyfarthing_scripts.common.config import get_project_root
@@ -70,8 +69,8 @@ def install_git_hooks(project_root: Path | None = None) -> int:
70
69
  return 1
71
70
 
72
71
  print("Installing git hooks with .d/ dispatcher pattern...")
73
- print(f" Source: pennyfarthing-dist/scripts/hooks/")
74
- print(f" Dest: .git/hooks/")
72
+ print(" Source: pennyfarthing-dist/scripts/hooks/")
73
+ print(" Dest: .git/hooks/")
75
74
  print()
76
75
 
77
76
  for source_file, dest_name in HOOKS:
@@ -291,7 +291,7 @@ async def main(brief: bool = False) -> int:
291
291
  Returns:
292
292
  0 if all repos clean, 1 if any have changes/unpushed
293
293
  """
294
- from pennyfarthing_scripts.git.repos import load_repos_config, get_repo_paths
294
+ from pennyfarthing_scripts.git.repos import get_repo_paths, load_repos_config
295
295
 
296
296
  repos_with_upstream: list[tuple[str, Path, str]] = []
297
297
  repo_paths = get_repo_paths()
@@ -199,7 +199,7 @@ def remove_worktree(name: str) -> int:
199
199
  shutil.rmtree(wt_path)
200
200
 
201
201
  # Prune worktree references
202
- for repo_name, cfg in repos.items():
202
+ for _repo_name, cfg in repos.items():
203
203
  full_path = (project_root / cfg.path).resolve()
204
204
  if full_path.exists():
205
205
  _git(["worktree", "prune"], full_path)
@@ -277,7 +277,7 @@ def show_worktree_status() -> int:
277
277
  if repo_wt.exists():
278
278
  branch, _ = _git(["branch", "--show-current"], repo_wt)
279
279
  status_out, _ = _git(["status", "--short"], repo_wt)
280
- count = len([l for l in status_out.split("\n") if l.strip()]) if status_out else 0
280
+ count = len([line for line in status_out.split("\n") if line.strip()]) if status_out else 0
281
281
  print(f" {repo_name} ({cfg.repo_type}): {branch} ({count} uncommitted)")
282
282
 
283
283
  # Check for session files referencing this worktree
@@ -4,8 +4,9 @@ Usage:
4
4
  pf handoff resolve-gate STORY_ID WORKFLOW PHASE
5
5
  pf handoff complete-phase STORY_ID WORKFLOW FROM_PHASE TO_PHASE GATE_TYPE
6
6
  pf handoff marker NEXT_AGENT [--error MESSAGE]
7
+ pf handoff phase-check AGENT
7
8
 
8
- Stories: 105-1, 105-4 (Script-First Handoff)
9
+ Stories: 105-1, 105-4 (Script-First Handoff), 110-8 (CLI Relay Handoff Fix)
9
10
  """
10
11
 
11
12
  from __future__ import annotations
@@ -22,6 +23,7 @@ def handoff():
22
23
  resolve-gate - Resolve gate for current phase
23
24
  complete-phase - Complete phase transition atomically
24
25
  marker - Generate AGENT_COMMAND handoff marker
26
+ phase-check - Check if agent owns current phase
25
27
  """
26
28
  pass
27
29
 
@@ -118,3 +120,33 @@ def marker_cmd(next_agent: str | None, error_msg: str | None):
118
120
  )
119
121
 
120
122
  click.echo(generate_marker(next_agent, error=error_msg))
123
+
124
+
125
+ @handoff.command("phase-check")
126
+ @click.argument("agent")
127
+ def phase_check_cmd(agent: str):
128
+ """Check if the requested agent owns the current workflow phase.
129
+
130
+ Returns a YAML block with action ("start" or "redirect"), the correct
131
+ agent, story ID, phase, and a human-readable message.
132
+
133
+ If the agent does not own the phase, generates a handoff marker for
134
+ the correct agent.
135
+
136
+ \b
137
+ Arguments:
138
+ AGENT - Agent to check (e.g., dev, tea, reviewer, sm)
139
+ """
140
+ from pennyfarthing_scripts.handoff.phase_check import phase_check_start
141
+
142
+ result = phase_check_start(agent)
143
+
144
+ import yaml
145
+
146
+ click.echo(yaml.dump({"PHASE_CHECK": result}, default_flow_style=False).rstrip())
147
+
148
+ if result["action"] == "redirect":
149
+ click.echo("")
150
+ from pennyfarthing_scripts.handoff.marker import generate_marker
151
+
152
+ click.echo(generate_marker(result["agent"]))
@@ -70,6 +70,19 @@ def complete_phase(
70
70
  from_agent = _get_phase_agent(project_root, workflow, from_phase)
71
71
  to_agent = _get_phase_agent(project_root, workflow, to_phase)
72
72
 
73
+ # Update tandem line: remove existing, add if to_phase has tandem config
74
+ content = re.sub(r"\*\*Tandem:\*\*[^\n]*\n", "", content)
75
+ tandem = _get_phase_tandem(project_root, workflow, to_phase)
76
+ if tandem:
77
+ partner = tandem["partner"]
78
+ scope = tandem["scope"]
79
+ tandem_line = f"**Tandem:** {partner} ({scope})\n"
80
+ content = re.sub(
81
+ r"(\*\*Workflow:\*\*[^\n]*\n)",
82
+ rf"\1{tandem_line}",
83
+ content,
84
+ )
85
+
73
86
  # Update all **Phase:** lines to new phase
74
87
  content = re.sub(r"(\*\*Phase:\*\*) \S+", rf"\1 {to_phase}", content)
75
88
 
@@ -145,6 +158,21 @@ def _calc_duration(started_str: str, ended_str: str) -> str:
145
158
  return f"{hours}h {rem_minutes}m" if rem_minutes else f"{hours}h"
146
159
 
147
160
 
161
+ def _get_phase_tandem(project_root: Path, workflow: str, phase: str) -> dict | None:
162
+ """Return tandem config for a phase, or None if no tandem block."""
163
+ for name in [f"{workflow}.yaml", f"{workflow}/workflow.yaml"]:
164
+ path = project_root / ".pennyfarthing" / "workflows" / name
165
+ if path.exists():
166
+ try:
167
+ data = yaml.safe_load(path.read_text())
168
+ for p in data["workflow"]["phases"]:
169
+ if p["name"] == phase:
170
+ return p.get("tandem")
171
+ except Exception:
172
+ pass
173
+ return None
174
+
175
+
148
176
  def _get_phase_agent(project_root: Path, workflow: str, phase: str) -> str:
149
177
  for name in [f"{workflow}.yaml", f"{workflow}/workflow.yaml"]:
150
178
  path = project_root / ".pennyfarthing" / "workflows" / name
@@ -72,25 +72,25 @@ def generate_marker(
72
72
  fallback=f"Run `{cmd}` to continue",
73
73
  )
74
74
 
75
- # Non-Cyclist relay: invoke the next agent directly
76
- import subprocess
77
- try:
78
- result = subprocess.run(
79
- ["pf", "agent", "start", next_agent],
80
- capture_output=True,
81
- text=True,
82
- timeout=30,
75
+ # Non-Cyclist relay: return structured action for the agent to act on.
76
+ # The calling agent reads the `action` field and executes accordingly.
77
+ if ctx.use_tirepump:
78
+ return _block(
79
+ action="tirepump_handoff",
80
+ next_agent=next_agent,
81
+ fallback=f"Context is high ({pct}%). Run /clear then {cmd}",
82
+ context_percent=pct,
83
+ relay_mode=True,
83
84
  )
84
- agent_output = result.stdout.strip()
85
- except Exception as e:
86
- agent_output = f"Failed to invoke agent: {e}"
87
85
 
88
86
  return _block(
89
- fallback=f"Run `{cmd}` to continue{context_warning}",
90
- relay_mode=True,
87
+ action="inline_handoff",
88
+ next_agent=next_agent,
89
+ activation_command=f"pf agent start {next_agent} --tier handoff --quiet",
90
+ fallback=f"Run `{cmd}` to continue",
91
91
  context_percent=pct,
92
- invoke=cmd,
93
- ) + f"\n\n{agent_output}"
92
+ relay_mode=True,
93
+ )
94
94
 
95
95
 
96
96
  def _block(**fields: object) -> str:
@@ -0,0 +1,96 @@
1
+ """Phase check for agent activation.
2
+
3
+ Determines whether the requested agent owns the current workflow phase.
4
+ If not, returns a redirect to the correct agent. Replaces phase-check-start.sh.
5
+
6
+ Story: 110-8 (CLI Relay Handoff Fix)
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from pathlib import Path
12
+
13
+ from pennyfarthing_scripts.common.config import get_project_root
14
+ from pennyfarthing_scripts.prime.workflow import (
15
+ check_redirect,
16
+ detect_workflow_state,
17
+ find_active_session,
18
+ parse_session_header,
19
+ )
20
+
21
+
22
+ def phase_check_start(
23
+ agent_name: str,
24
+ project_root: Path | None = None,
25
+ ) -> dict:
26
+ """Check if requested agent owns current phase.
27
+
28
+ Args:
29
+ agent_name: Agent to check (e.g., "dev", "tea", "reviewer").
30
+ project_root: Project root path (auto-detected if not provided).
31
+
32
+ Returns:
33
+ Dict with:
34
+ action: "start" (proceed) or "redirect" (wrong agent)
35
+ agent: The agent that should run
36
+ story_id: Current story ID (if session exists)
37
+ phase: Current phase (if session exists)
38
+ phase_owner: Agent that owns the phase
39
+ message: Human-readable explanation
40
+ """
41
+ root = project_root or get_project_root()
42
+
43
+ # Find active session
44
+ session_file = find_active_session(root)
45
+ if not session_file:
46
+ return {
47
+ "action": "start",
48
+ "agent": agent_name,
49
+ "story_id": None,
50
+ "phase": None,
51
+ "phase_owner": None,
52
+ "message": f"No active session — starting {agent_name}",
53
+ }
54
+
55
+ # Parse session header
56
+ header = parse_session_header(session_file)
57
+ story_id = header.get("story_id")
58
+ workflow = header.get("workflow", "tdd")
59
+ phase = header.get("phase")
60
+
61
+ if not phase:
62
+ return {
63
+ "action": "start",
64
+ "agent": agent_name,
65
+ "story_id": story_id,
66
+ "phase": None,
67
+ "phase_owner": None,
68
+ "message": f"No phase detected — starting {agent_name}",
69
+ }
70
+
71
+ # Use detect_workflow_state + check_redirect for consistent logic
72
+ workflow_status = detect_workflow_state(root)
73
+ redirect = check_redirect(workflow_status, agent_name)
74
+
75
+ if redirect:
76
+ target_agent, reason = redirect
77
+ return {
78
+ "action": "redirect",
79
+ "agent": target_agent,
80
+ "story_id": story_id,
81
+ "phase": phase,
82
+ "phase_owner": target_agent,
83
+ "message": (
84
+ f"Story {story_id} is in '{phase}' phase "
85
+ f"(workflow: {workflow}) — owned by {target_agent}"
86
+ ),
87
+ }
88
+
89
+ return {
90
+ "action": "start",
91
+ "agent": agent_name,
92
+ "story_id": story_id,
93
+ "phase": phase,
94
+ "phase_owner": agent_name,
95
+ "message": f"Agent {agent_name} owns phase '{phase}' — proceeding",
96
+ }
@@ -67,7 +67,19 @@ def resolve_gate(
67
67
 
68
68
  gate = current_phase.get("gate")
69
69
 
70
- if current_idx + 1 < len(phases):
70
+ # Support explicit next: directive for non-linear phase routing
71
+ explicit_next = current_phase.get("next")
72
+ if explicit_next:
73
+ nxt = next((p for p in phases if p["name"] == explicit_next), None)
74
+ if nxt:
75
+ next_phase = nxt["name"]
76
+ next_agent = nxt["agent"]
77
+ else:
78
+ return _result(
79
+ status="error",
80
+ error=f"Phase '{explicit_next}' referenced by next: not found in workflow '{workflow}'",
81
+ )
82
+ elif current_idx + 1 < len(phases):
71
83
  nxt = phases[current_idx + 1]
72
84
  next_phase = nxt["name"]
73
85
  next_agent = nxt["agent"]