@pennyfarthing/core 11.2.0 → 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 (403) hide show
  1. package/README.md +1 -1
  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/server.d.ts +0 -3
  41. package/packages/core/dist/server/server.d.ts.map +1 -1
  42. package/packages/core/dist/server/server.js +3 -37
  43. package/packages/core/dist/server/server.js.map +1 -1
  44. package/packages/core/dist/server/server.test.d.ts +1 -1
  45. package/packages/core/dist/server/server.test.js +12 -23
  46. package/packages/core/dist/server/server.test.js.map +1 -1
  47. package/packages/core/dist/shared/capabilities.d.ts +88 -0
  48. package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
  49. package/packages/core/dist/shared/capabilities.js +133 -0
  50. package/packages/core/dist/shared/capabilities.js.map +1 -0
  51. package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
  52. package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
  53. package/packages/core/dist/shared/capabilities.test.js +217 -0
  54. package/packages/core/dist/shared/capabilities.test.js.map +1 -0
  55. package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
  56. package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
  57. package/packages/core/dist/shared/spawn-prompt.js +82 -0
  58. package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
  59. package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
  60. package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
  61. package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
  62. package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
  63. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
  64. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
  65. package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
  66. package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
  67. package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
  68. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  69. package/packages/core/dist/workflow/workflow-schema.js +120 -0
  70. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  71. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  72. package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
  73. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  74. package/pennyfarthing-dist/agents/dev.md +6 -10
  75. package/pennyfarthing-dist/agents/reviewer.md +8 -2
  76. package/pennyfarthing-dist/agents/sm-finish.md +18 -1
  77. package/pennyfarthing-dist/commands/pf-git.md +4 -2
  78. package/pennyfarthing-dist/gates/approval.md +63 -0
  79. package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
  80. package/pennyfarthing-dist/gates/context-ok.md +56 -0
  81. package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
  82. package/pennyfarthing-dist/gates/quality-pass.md +67 -0
  83. package/pennyfarthing-dist/gates/tests-fail.md +84 -0
  84. package/pennyfarthing-dist/gates/tests-pass.md +79 -0
  85. package/pennyfarthing-dist/guides/agent-behavior.md +23 -19
  86. package/pennyfarthing-dist/guides/bell-mode.md +1 -1
  87. package/pennyfarthing-dist/guides/hooks.md +28 -28
  88. package/pennyfarthing-dist/guides/reflector.md +1 -1
  89. package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
  90. package/pennyfarthing-dist/scripts/core/check-context.sh +2 -0
  91. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +5 -87
  92. package/pennyfarthing-dist/scripts/hooks/README.md +5 -5
  93. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  94. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
  95. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
  96. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
  97. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
  98. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +27 -33
  99. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
  100. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
  101. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
  102. package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
  103. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
  104. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
  105. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +4 -93
  106. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  107. package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
  108. package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
  109. package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
  110. package/pennyfarthing_scripts/CLAUDE.md +19 -10
  111. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  112. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  113. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  114. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  115. package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
  116. package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
  117. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  118. package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
  119. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  120. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  121. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  122. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  123. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  124. package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
  125. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  126. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  127. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  128. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  129. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  130. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  131. package/pennyfarthing_scripts/bc/__pycache__/__init__.cpython-314.pyc +0 -0
  132. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  133. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  134. package/pennyfarthing_scripts/bellmode_hook.py +12 -296
  135. package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
  136. package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
  137. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  138. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  139. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  140. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  141. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  142. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  143. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  144. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  145. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  146. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  147. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  148. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  149. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  150. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  151. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
  152. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
  153. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  154. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  155. package/pennyfarthing_scripts/bikerack/audit_log_panel.py +119 -0
  156. package/pennyfarthing_scripts/bikerack/base_panel.py +27 -4
  157. package/pennyfarthing_scripts/bikerack/changed_panel.py +96 -4
  158. package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
  159. package/pennyfarthing_scripts/bikerack/debug_panel.py +1 -1
  160. package/pennyfarthing_scripts/bikerack/diffs_panel.py +30 -0
  161. package/pennyfarthing_scripts/bikerack/events.py +28 -0
  162. package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
  163. package/pennyfarthing_scripts/bikerack/sprint_panel.py +373 -142
  164. package/pennyfarthing_scripts/bikerack/story_detail_data.py +244 -0
  165. package/pennyfarthing_scripts/bikerack/story_detail_screen.py +176 -0
  166. package/pennyfarthing_scripts/bikerack/tui.py +293 -61
  167. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  168. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  169. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  170. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  171. package/pennyfarthing_scripts/cli.py +5 -0
  172. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  173. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  174. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  179. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  180. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  181. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  182. package/pennyfarthing_scripts/common/pr_config.py +38 -0
  183. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  184. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  185. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  188. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  189. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  190. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  191. package/pennyfarthing_scripts/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
  192. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  193. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  194. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  201. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  202. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  211. package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
  212. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  213. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  214. package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
  215. package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
  216. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  217. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  218. package/pennyfarthing_scripts/handoff/cli.py +33 -1
  219. package/pennyfarthing_scripts/handoff/complete_phase.py +28 -0
  220. package/pennyfarthing_scripts/handoff/marker.py +15 -15
  221. package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
  222. package/pennyfarthing_scripts/handoff/resolve_gate.py +13 -1
  223. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  225. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/hooks/__init__.py +437 -0
  230. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  233. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  238. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  239. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  240. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  241. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  242. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  243. package/pennyfarthing_scripts/hooks/bell_mode.py +215 -0
  244. package/pennyfarthing_scripts/hooks/cli.py +96 -0
  245. package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
  246. package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
  247. package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
  248. package/pennyfarthing_scripts/hooks/pre_edit_check.py +78 -0
  249. package/pennyfarthing_scripts/hooks/reflector_check.py +271 -0
  250. package/pennyfarthing_scripts/hooks/schema_validation.py +203 -0
  251. package/pennyfarthing_scripts/hooks/session_start.py +296 -0
  252. package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
  253. package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
  254. package/pennyfarthing_scripts/hooks/statusline.py +420 -0
  255. package/pennyfarthing_scripts/hooks.py +27 -432
  256. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  257. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  258. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  259. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  260. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  261. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  262. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  263. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  264. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  266. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  267. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  268. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  269. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  276. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  277. package/pennyfarthing_scripts/launch/__pycache__/__init__.cpython-314.pyc +0 -0
  278. package/pennyfarthing_scripts/launch/__pycache__/cli.cpython-314.pyc +0 -0
  279. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  280. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  283. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  284. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  285. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  289. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
  291. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  292. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  293. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  294. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  295. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  296. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  297. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/prime/workflow.py +2 -1
  302. package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
  303. package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
  304. package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
  305. package/pennyfarthing_scripts/session_start_hook.py +4 -186
  306. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  307. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  308. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  309. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  311. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  312. package/pennyfarthing_scripts/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
  313. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  314. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  315. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  316. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  317. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  318. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  319. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  320. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  321. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  322. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  323. package/pennyfarthing_scripts/sprint/story_update.py +19 -0
  324. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  325. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  326. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  327. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  328. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  329. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  332. package/pennyfarthing_scripts/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
  333. package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
  334. package/pennyfarthing_scripts/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
  335. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  336. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  337. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  338. package/pennyfarthing_scripts/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
  339. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  340. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  341. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
  342. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
  343. package/pennyfarthing_scripts/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
  344. package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
  345. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  346. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  347. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
  348. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  349. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  350. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  351. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  352. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  353. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  354. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
  355. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  356. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  357. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  358. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  359. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  360. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  361. package/pennyfarthing_scripts/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
  362. package/pennyfarthing_scripts/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
  363. package/pennyfarthing_scripts/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
  364. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  365. package/pennyfarthing_scripts/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
  366. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  367. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  368. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  369. package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
  370. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  371. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  372. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  373. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  374. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  375. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  376. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  377. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  378. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  379. package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
  380. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  381. package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
  382. package/pennyfarthing_scripts/welcome_hook.py +3 -149
  383. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  384. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  385. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  386. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  387. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  388. package/pennyfarthing_scripts/workflow/cli.py +7 -6
  389. package/pennyfarthing_scripts/workflow/team_lifecycle.py +257 -0
  390. package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
  391. package/packages/core/dist/scripts/theme-detail.test.js +0 -199
  392. package/pennyfarthing_scripts/bikerack/__pycache__/portrait.cpython-314.pyc +0 -0
  393. package/pennyfarthing_scripts/gate/__pycache__/__init__.cpython-314.pyc +0 -0
  394. package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
  395. package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
  396. package/pennyfarthing_scripts/git/__pycache__/hooks_installer.cpython-314.pyc +0 -0
  397. package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
  398. package/pennyfarthing_scripts/git/__pycache__/worktree.cpython-314.pyc +0 -0
  399. package/pennyfarthing_scripts/prime/__pycache__/heatmap.cpython-314.pyc +0 -0
  400. package/pennyfarthing_scripts/tests/__pycache__/test_108_2_remove_handoff_fallback.cpython-314-pytest-9.0.2.pyc +0 -0
  401. package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
  402. package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
  403. package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
@@ -1,94 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # Welcome Hook: Display a friendly welcome message on session start
3
- #
4
- # For CLI: Displays ASCII art of a penny-farthing bicycle
5
- # For Cyclist: Sends WebSocket message to display logo and welcome
6
- #
7
- # Called by Claude Code SessionStart hook
8
-
9
- set -euo pipefail
10
-
11
- # Read and discard stdin (required by hook protocol)
12
- cat > /dev/null
13
-
14
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
15
- PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(cd "$SCRIPT_DIR/../../.." && pwd)}"
16
-
17
- # Once-per-session guard: only show welcome on first invocation
18
- # Use session ID from environment or generate a unique one
19
- SESSION_ID="${CLAUDE_SESSION_ID:-$$}"
20
- WELCOME_LOCK="$PROJECT_ROOT/.session/.welcome-shown-$SESSION_ID"
21
-
22
- # Ensure .session directory exists
23
- mkdir -p "$PROJECT_ROOT/.session"
24
-
25
- # Check if welcome was already shown for this session
26
- if [[ -f "$WELCOME_LOCK" ]]; then
27
- exit 0
28
- fi
29
-
30
- # Mark welcome as shown for this session
31
- touch "$WELCOME_LOCK"
32
-
33
- # Check if running in Cyclist (port file exists)
34
- PORT_FILE="$PROJECT_ROOT/.wheelhub-port"
35
- IN_CYCLIST=false
36
- if [[ -f "$PORT_FILE" ]]; then
37
- CYCLIST_PORT=$(cat "$PORT_FILE" 2>/dev/null)
38
- if [[ "$CYCLIST_PORT" =~ ^[0-9]+$ ]]; then
39
- IN_CYCLIST=true
40
- fi
41
- fi
42
-
43
- # Get project name from package.json or directory name
44
- PROJECT_NAME=""
45
- if [[ -f "$PROJECT_ROOT/package.json" ]]; then
46
- PROJECT_NAME=$(jq -r '.name // empty' "$PROJECT_ROOT/package.json" 2>/dev/null || echo "")
47
- fi
48
- if [[ -z "$PROJECT_NAME" ]]; then
49
- PROJECT_NAME=$(basename "$PROJECT_ROOT")
50
- fi
51
-
52
- # Get current theme from config
53
- THEME=""
54
- if [[ -f "$PROJECT_ROOT/.pennyfarthing/config.local.yaml" ]]; then
55
- THEME=$(grep -E '^theme:' "$PROJECT_ROOT/.pennyfarthing/config.local.yaml" 2>/dev/null | sed 's/theme:[[:space:]]*//' | tr -d '"' || echo "")
56
- fi
57
-
58
- if [[ "$IN_CYCLIST" == "true" ]]; then
59
- # Send welcome message via WebSocket API for Cyclist to display
60
- # Cyclist will show the pennyfarthing logo image and welcome text
61
- curl -s -X POST "http://localhost:$CYCLIST_PORT/api/welcome" \
62
- -H "Content-Type: application/json" \
63
- -d "{\"project\": \"$PROJECT_NAME\", \"theme\": \"$THEME\"}" \
64
- >/dev/null 2>&1 || true
65
- else
66
- # CLI mode: Display ASCII art welcome
67
- cat << 'EOF'
68
-
69
- ___
70
- / \
71
- | | Welcome to
72
- | | ╔═══════════════════════════════════╗
73
- \___/ ║ ╔═╗╔═╗╔╗╔╔╗╔╦═╗╔═╗╔═╗╔═╗╦╔═╗ ║
74
- ║ ║ ╠═╝║╣ ║║║║║║ ╠╣ ╠═╣╠╦╝ ║ ╠═╣ ║
75
- ║ ║ ╩ ╚═╝╝╚╝╝╚╝╩ ╩ ╩╩╚═ ╩ ╩ ╩ ║
76
- ╔═╩═╗ ╚═══════════════════════════════════╝
77
- / \
78
- │ O │ Agent-powered development with style
79
- \ /
80
- ╚═══╝
81
-
82
- EOF
83
-
84
- # Add project-specific info
85
- if [[ -n "$PROJECT_NAME" ]]; then
86
- echo " Project: $PROJECT_NAME"
87
- fi
88
- if [[ -n "$THEME" ]]; then
89
- echo " Theme: $THEME"
90
- fi
91
- echo ""
92
- fi
93
-
94
- exit 0
2
+ # DEPRECATED: This script is a shim. Logic has moved to Python.
3
+ # Welcome is now part of session-start.
4
+ # Use: pf hooks session-start
5
+ exec pf hooks session-start
@@ -9,7 +9,7 @@ Uncategorized utilities and one-off scripts.
9
9
  | `deploy.sh` | Deployment script |
10
10
  | `doctor-dogfood.sh` | Health check for framework/orchestrator development setup |
11
11
  | `run-ci.sh` | Run CI locally |
12
- | `statusline.sh` | Status line configuration |
12
+ | `pf hooks statusline` | Status line configuration |
13
13
  | `uninstall.sh` | Uninstall Pennyfarthing from project |
14
14
  | `backlog.sh` | Backlog operations |
15
15
  | `repo-utils.sh` | Multi-repo utilities |
@@ -1,301 +1,4 @@
1
- #!/usr/bin/env zsh
2
- # Claude Code statusline - fixed-width segments
3
- # Format: [ROLE] Theme | repo | branch | model [progress] pct%
4
-
5
- input=$(cat)
6
-
7
- # Validate JSON
8
- if ! echo "$input" | jq -e . >/dev/null 2>&1; then
9
- echo "⚠ invalid input"
10
- exit 0
11
- fi
12
-
13
- # Extract fields - use cwd for display only, PROJECT_ROOT for file lookups
14
- cwd=$(echo "$input" | jq -r '.workspace.current_dir // empty' 2>/dev/null)
15
- dir_name=$(basename "$cwd" 2>/dev/null || echo "?")
16
- PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$cwd}"
17
- session_id=$(echo "$input" | jq -r '.session_id // empty' 2>/dev/null)
18
-
19
- # Model name - clean up
20
- model=$(echo "$input" | jq -r '
21
- if .model | type == "object" then .model.id // .model.name // "claude"
22
- elif .model | type == "string" then .model
23
- else "claude"
24
- end
25
- ' 2>/dev/null)
26
- [ -z "$model" ] || [ "$model" = "null" ] && model="claude"
27
- model=$(echo "$model" | sed 's/claude-//' | sed 's/-[0-9]*$//' | cut -c1-10)
28
-
29
- # Git branch
30
- branch=""
31
- branch_dirty=""
32
- if git -C "$cwd" rev-parse --git-dir > /dev/null 2>&1; then
33
- branch=$(git -C "$cwd" branch --show-current 2>/dev/null)
34
- [ -z "$branch" ] && branch=$(git -C "$cwd" rev-parse --short HEAD 2>/dev/null)
35
-
36
- # Check if dirty using diff-index (doesn't lock the index like status does)
37
- # This avoids "index.lock: File exists" errors when multiple Claude sessions
38
- # run concurrent statusline updates during git operations
39
- if ! git -C "$cwd" diff-index --quiet HEAD -- 2>/dev/null || \
40
- [ -n "$(git -C "$cwd" ls-files --others --exclude-standard 2>/dev/null | head -1)" ]; then
41
- branch_dirty="*"
42
- fi
43
- fi
44
-
45
- # Context percentage
46
- pct="--"
47
- usage=$(echo "$input" | jq '.context_window.current_usage // empty' 2>/dev/null)
48
- if [ -n "$usage" ] && [ "$usage" != "null" ]; then
49
- current=$(echo "$usage" | jq '.input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens' 2>/dev/null)
50
- size=$(echo "$input" | jq '.context_window.context_window_size // 0' 2>/dev/null)
51
- if [ -n "$current" ] && [ "$current" != "null" ] && [ -n "$size" ] && [ "$size" != "null" ] && [ "$size" -gt 0 ] 2>/dev/null; then
52
- pct=$((current * 100 / size))
53
- fi
54
- fi
55
-
56
- # Agent abbreviation map
57
- get_agent_abbrev() {
58
- case "$1" in
59
- pm) echo "PM" ;;
60
- sm) echo "SM" ;;
61
- dev) echo "DEV" ;;
62
- tea) echo "TEA" ;;
63
- reviewer) echo "REV" ;;
64
- architect) echo "ARC" ;;
65
- devops) echo "OPS" ;;
66
- ux-designer) echo "UX" ;;
67
- tech-writer) echo "DOC" ;;
68
- orchestrator) echo "ORC" ;;
69
- ba) echo "BA" ;;
70
- *) echo "???" ;;
71
- esac
72
- }
73
-
74
- # Agent and theme from session
75
- agent_name=""
76
- agent_abbrev=""
77
- theme_display=""
78
-
79
- # Try session_id match first, then fall back to most recent agent file
80
- if [ -n "$session_id" ] && [ -f "$PROJECT_ROOT/.session/agents/${session_id}" ]; then
81
- # Exact session match (ideal case)
82
- agent_name=$(cat "$PROJECT_ROOT/.session/agents/${session_id}")
83
- agent_abbrev=$(get_agent_abbrev "$agent_name")
84
- elif [ -d "$PROJECT_ROOT/.session/agents" ]; then
85
- # Fallback: use most recently modified agent file
86
- # This handles the session_id mismatch between hooks
87
- latest_file=$(ls -t "$PROJECT_ROOT/.session/agents/" 2>/dev/null | head -1)
88
- if [ -n "$latest_file" ] && [ -f "$PROJECT_ROOT/.session/agents/$latest_file" ]; then
89
- agent_name=$(cat "$PROJECT_ROOT/.session/agents/$latest_file")
90
- agent_abbrev=$(get_agent_abbrev "$agent_name")
91
- fi
92
- fi
93
-
94
- # Get character name from theme file (single source of truth)
95
- # Priority: .pennyfarthing/config.local.yaml > .pennyfarthing/persona-config.yaml
96
- config_file=""
97
- if [ -f "$PROJECT_ROOT/.pennyfarthing/config.local.yaml" ]; then
98
- config_file="$PROJECT_ROOT/.pennyfarthing/config.local.yaml"
99
- elif [ -f "$PROJECT_ROOT/.pennyfarthing/persona-config.yaml" ]; then
100
- config_file="$PROJECT_ROOT/.pennyfarthing/persona-config.yaml"
101
- fi
102
-
103
- character_display=""
104
- if [ -n "$config_file" ] && [ -n "$agent_name" ]; then
105
- # Get theme name from config
106
- theme=$(yq '.theme' "$config_file" 2>/dev/null)
107
-
108
- if [ -n "$theme" ] && [ "$theme" != "null" ]; then
109
- # Read character directly from theme file (matches agent-session.sh behavior)
110
- theme_file="$PROJECT_ROOT/.pennyfarthing/personas/themes/${theme}.yaml"
111
- if [ -f "$theme_file" ]; then
112
- full_name=$(yq ".agents.${agent_name}.character" "$theme_file" 2>/dev/null)
113
-
114
- if [ -n "$full_name" ] && [ "$full_name" != "null" ]; then
115
- # Smart character name extraction:
116
- # 1. Remove parenthetical content: "Breq (Justice of Toren)" → "Breq"
117
- # 2. Strip common titles: "Captain Kirk" → "Kirk"
118
- # 3. If single word remains, use it; otherwise take last word
119
- clean_name=$(echo "$full_name" | sed 's/ *([^)]*)//g' | xargs)
120
- clean_name=$(echo "$clean_name" | sed -E 's/^(Captain|Lieutenant|Dr\.|Doc|Mr\.|Mrs\.|Ms\.|Admiral|Commander|Chief|Ensign|Translator|Agent|Colonel|Major|Sergeant|Professor|Lord|Lady|Sir|The) +//i')
121
- word_count=$(echo "$clean_name" | wc -w | tr -d ' ')
122
- if [ "$word_count" -eq 1 ]; then
123
- character_display="$clean_name"
124
- else
125
- character_display=$(echo "$clean_name" | awk '{print $NF}')
126
- fi
127
- fi
128
- fi
129
-
130
- # Fallback to theme name if no character found
131
- if [ -z "$character_display" ]; then
132
- character_display="$(echo "${theme:0:1}" | tr '[:lower:]' '[:upper:]')${theme:1}"
133
- fi
134
- fi
135
- fi
136
- theme_display="$character_display"
137
-
138
- # Tandem indicator: detect active backseat agent from observation files
139
- # Files: .session/{storyId}-tandem-{partner}.md (created by backseat spawn, cleaned on finish)
140
- tandem_partner=""
141
- tandem_partner_display=""
142
- if [ -d "$PROJECT_ROOT/.session" ]; then
143
- tandem_file=$(find "$PROJECT_ROOT/.session" -maxdepth 1 -name "*-tandem-*.md" -print 2>/dev/null | head -1)
144
- if [ -n "$tandem_file" ]; then
145
- # Extract partner name from filename: {storyId}-tandem-{partner}.md
146
- tandem_partner=$(basename "$tandem_file" | sed -n 's/.*-tandem-\([a-zA-Z_-]*\)\.md$/\1/p')
147
- if [ -n "$tandem_partner" ] && [ -n "$theme_file" ] && [ -f "$theme_file" ]; then
148
- # Look up partner's character name from theme
149
- partner_full=$(yq ".agents.${tandem_partner}.character" "$theme_file" 2>/dev/null)
150
- if [ -n "$partner_full" ] && [ "$partner_full" != "null" ]; then
151
- partner_clean=$(echo "$partner_full" | sed 's/ *([^)]*)//g' | xargs)
152
- partner_clean=$(echo "$partner_clean" | sed -E 's/^(Captain|Lieutenant|Dr\.|Doc|Mr\.|Mrs\.|Ms\.|Admiral|Commander|Chief|Ensign|Translator|Agent|Colonel|Major|Sergeant|Professor|Lord|Lady|Sir|The) +//i')
153
- partner_wc=$(echo "$partner_clean" | wc -w | tr -d ' ')
154
- if [ "$partner_wc" -eq 1 ]; then
155
- tandem_partner_display="$partner_clean"
156
- else
157
- tandem_partner_display=$(echo "$partner_clean" | awk '{print $NF}')
158
- fi
159
- fi
160
- # Fallback to agent abbreviation if no theme character
161
- if [ -z "$tandem_partner_display" ]; then
162
- tandem_partner_display=$(get_agent_abbrev "$tandem_partner")
163
- fi
164
- elif [ -n "$tandem_partner" ]; then
165
- # No theme file — use abbreviation
166
- tandem_partner_display=$(get_agent_abbrev "$tandem_partner")
167
- fi
168
- fi
169
- fi
170
-
171
- # ANSI colors
172
- RESET=$'\033[0m'
173
- DIM=$'\033[2m'
174
- BOLD=$'\033[1m'
175
- REVERSE=$'\033[7m'
176
- FG_CYAN=$'\033[36m'
177
- FG_GREEN=$'\033[32m'
178
- FG_YELLOW=$'\033[33m'
179
- FG_RED=$'\033[31m'
180
- FG_MAGENTA=$'\033[35m'
181
- FG_BLUE=$'\033[34m'
182
- FG_WHITE=$'\033[97m'
183
- FG_GRAY=$'\033[38;5;245m'
184
- FG_ORANGE=$'\033[38;5;208m'
185
- FG_PINK=$'\033[38;5;213m'
186
- FG_TEAL=$'\033[38;5;43m'
187
- FG_PURPLE=$'\033[38;5;141m'
188
- FG_LIME=$'\033[38;5;154m'
189
-
190
- # Agent color map
191
- get_agent_color() {
192
- case "$1" in
193
- pm) echo "${FG_PURPLE}${BOLD}" ;; # Purple - strategic
194
- sm) echo "${FG_BLUE}${BOLD}" ;; # Blue - coordination
195
- dev) echo "${FG_GREEN}${BOLD}" ;; # Green - building
196
- tea) echo "${FG_TEAL}${BOLD}" ;; # Teal - testing
197
- reviewer) echo "${FG_RED}${BOLD}" ;; # Red - critical eye
198
- architect) echo "${FG_ORANGE}${BOLD}" ;; # Orange - design
199
- devops) echo "${FG_CYAN}${BOLD}" ;; # Cyan - infrastructure
200
- ux-designer) echo "${FG_PINK}${BOLD}" ;; # Pink - design
201
- tech-writer) echo "${FG_WHITE}${BOLD}" ;; # White - documentation
202
- orchestrator) echo "${FG_MAGENTA}${BOLD}" ;;# Magenta - coordination
203
- ba) echo "${FG_LIME}${BOLD}" ;; # Lime - discovery
204
- *) echo "${FG_MAGENTA}${BOLD}" ;; # Default
205
- esac
206
- }
207
-
208
- # Build progress bar (10 segments)
209
- bar_width=10
210
- if [ "$pct" != "--" ]; then
211
- filled=$((pct * bar_width / 100))
212
- [ "$filled" -gt "$bar_width" ] && filled=$bar_width
213
- [ "$filled" -lt 0 ] && filled=0
214
-
215
- # Color based on level
216
- if [ "$pct" -gt 95 ]; then
217
- bar_color="${FG_RED}${BOLD}"
218
- elif [ "$pct" -gt 85 ]; then
219
- bar_color="${FG_RED}"
220
- elif [ "$pct" -gt 70 ]; then
221
- bar_color="${FG_YELLOW}"
222
- else
223
- bar_color="${FG_GREEN}"
224
- fi
225
-
226
- # Build bar: filled portion with ▓, empty with ░
227
- bar_filled=""
228
- bar_empty=""
229
- for ((i=0; i<filled; i++)); do bar_filled+="▓"; done
230
- for ((i=filled; i<bar_width; i++)); do bar_empty+="░"; done
231
-
232
- progress_bar="${bar_color}${bar_filled}${RESET}${DIM}${bar_empty}${RESET}"
233
- pct_display="${bar_color}${pct}%${RESET}"
234
- else
235
- progress_bar="${DIM}░░░░░░░░░░${RESET}"
236
- pct_display="${FG_GRAY}--%${RESET}"
237
- fi
238
-
239
- # Branch color (yellow if dirty, green if clean)
240
- if [ -n "$branch_dirty" ]; then
241
- branch_color="${FG_YELLOW}"
242
- else
243
- branch_color="${FG_GREEN}"
244
- fi
245
-
246
- # Fixed-width formatting using printf
247
- # Agent+Theme: ~20 chars, Repo: 14 chars, Branch: 12 chars, Model: 10 chars
248
- repo_fmt=$(printf "%-14s" "$dir_name")
249
- branch_fmt=$(printf "%-12s" "${branch}${branch_dirty}")
250
- model_fmt=$(printf "%-10s" "$model")
251
-
252
- # Build tandem suffix: "+ Partner" when backseat agent is active
253
- tandem_suffix=""
254
- tandem_suffix_len=0
255
- if [ -n "$tandem_partner_display" ]; then
256
- partner_color=$(get_agent_color "$tandem_partner")
257
- tandem_suffix=" ${DIM}+${RESET} ${partner_color}${tandem_partner_display}${RESET}"
258
- tandem_suffix_len=$((3 + ${#tandem_partner_display})) # " + " + name
259
- fi
260
-
261
- # Build agent display: [ROLE] Theme (+ Partner) (role in reverse text with color)
262
- if [ -n "$agent_abbrev" ]; then
263
- agent_color=$(get_agent_color "$agent_name")
264
- # Role in reverse text with color, then theme
265
- if [ -n "$theme_display" ]; then
266
- agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET} ${DIM}${theme_display}${RESET}${tandem_suffix}"
267
- # Pad to ~20 chars visual width (abbrev ~3 + spaces ~2 + theme ~10 + tandem = ~15+, pad to 20)
268
- pad_len=$((18 - ${#agent_abbrev} - ${#theme_display} - tandem_suffix_len))
269
- [ "$pad_len" -lt 0 ] && pad_len=0
270
- padding=$(printf "%${pad_len}s" "")
271
- agent_section="${agent_section}${padding}"
272
- else
273
- agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET}${tandem_suffix}"
274
- pad_len=$((17 - ${#agent_abbrev} - tandem_suffix_len))
275
- [ "$pad_len" -lt 0 ] && pad_len=0
276
- padding=$(printf "%${pad_len}s" "")
277
- agent_section="${agent_section}${padding}"
278
- fi
279
- else
280
- # No agent - just show theme if available
281
- if [ -n "$theme_display" ]; then
282
- agent_section="${DIM}${theme_display}${RESET}${tandem_suffix}"
283
- pad_len=$((20 - ${#theme_display} - tandem_suffix_len))
284
- [ "$pad_len" -lt 0 ] && pad_len=0
285
- padding=$(printf "%${pad_len}s" "")
286
- agent_section="${agent_section}${padding}"
287
- else
288
- agent_section=$(printf "%-20s" "")
289
- fi
290
- fi
291
-
292
- # Build output: [ROLE] Theme | repo | branch | model [progress] pct%
293
- echo -n "${agent_section}"
294
- echo -n "${DIM}│${RESET} "
295
- echo -n "${FG_CYAN}${repo_fmt}${RESET}"
296
- echo -n "${DIM}│${RESET} "
297
- echo -n "${branch_color}${branch_fmt}${RESET}"
298
- echo -n "${DIM}│${RESET} "
299
- echo -n "${FG_GRAY}${model_fmt}${RESET}"
300
- echo -n "${progress_bar} "
301
- echo -n "${pct_display}"
1
+ #!/usr/bin/env bash
2
+ # DEPRECATED: This script is a shim. Logic has moved to Python.
3
+ # Use: pf hooks statusline
4
+ exec pf hooks statusline
@@ -40,7 +40,7 @@
40
40
  "hooks": [
41
41
  {
42
42
  "type": "command",
43
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/session-start.sh"
43
+ "command": "pf hooks session-start"
44
44
  }
45
45
  ]
46
46
  },
@@ -68,7 +68,16 @@
68
68
  "hooks": [
69
69
  {
70
70
  "type": "command",
71
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/question-reflector-check.sh"
71
+ "command": "pf hooks reflector-check"
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "matcher": "",
77
+ "hooks": [
78
+ {
79
+ "type": "command",
80
+ "command": "pf hooks session-stop"
72
81
  }
73
82
  ]
74
83
  }
@@ -79,7 +88,7 @@
79
88
  "hooks": [
80
89
  {
81
90
  "type": "command",
82
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/bell-mode-hook.sh"
91
+ "command": "pf hooks bell-mode"
83
92
  }
84
93
  ]
85
94
  },
@@ -88,7 +97,7 @@
88
97
  "hooks": [
89
98
  {
90
99
  "type": "command",
91
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/sprint-yaml-validation.sh"
100
+ "command": "pf hooks sprint-yaml"
92
101
  }
93
102
  ]
94
103
  }
@@ -99,7 +108,7 @@
99
108
  "hooks": [
100
109
  {
101
110
  "type": "command",
102
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/pre-edit-check.sh"
111
+ "command": "pf hooks pre-edit-check"
103
112
  }
104
113
  ]
105
114
  },
@@ -108,7 +117,7 @@
108
117
  "hooks": [
109
118
  {
110
119
  "type": "command",
111
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/schema-validation.sh"
120
+ "command": "pf hooks schema-validation"
112
121
  }
113
122
  ]
114
123
  },
@@ -117,7 +126,7 @@
117
126
  "hooks": [
118
127
  {
119
128
  "type": "command",
120
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/context-warning.sh"
129
+ "command": "pf hooks context-warning"
121
130
  }
122
131
  ]
123
132
  },
@@ -126,7 +135,7 @@
126
135
  "hooks": [
127
136
  {
128
137
  "type": "command",
129
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/context-circuit-breaker.sh"
138
+ "command": "pf hooks context-breaker"
130
139
  }
131
140
  ]
132
141
  },
@@ -134,7 +143,7 @@
134
143
  "hooks": [
135
144
  {
136
145
  "type": "command",
137
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/hooks/cyclist-pretooluse-hook.sh"
146
+ "command": "pf hooks cyclist-pretooluse"
138
147
  }
139
148
  ]
140
149
  }
@@ -142,6 +151,6 @@
142
151
  },
143
152
  "statusLine": {
144
153
  "type": "command",
145
- "command": "\"$CLAUDE_PROJECT_DIR\"/.pennyfarthing/scripts/misc/statusline.sh"
154
+ "command": "pf hooks statusline"
146
155
  }
147
156
  }
@@ -1,7 +1,7 @@
1
1
  # TDD Workflow - Test-Driven Development
2
2
  # Default workflow for feature development in Pennyfarthing
3
3
  #
4
- # Flow: SM → TEA → Dev → Reviewer → SM
4
+ # Flow: SM → TEA → Dev → TEA (verify) → Reviewer → SM
5
5
  # Scale routing: 1-2 pts use 'trivial' workflow instead
6
6
 
7
7
  workflow:
@@ -32,9 +32,18 @@ workflow:
32
32
  type: tests_pass
33
33
  condition: All tests passing, no skipped tests
34
34
 
35
+ - name: verify
36
+ agent: tea
37
+ input: [implementation, passing_tests]
38
+ output: [quality_verified]
39
+ gate:
40
+ file: gates/quality-pass
41
+ type: quality_pass
42
+ condition: Lint, typecheck, and all tests passing
43
+
35
44
  - name: review
36
45
  agent: reviewer
37
- input: [implementation, passing_tests]
46
+ input: [implementation, passing_tests, quality_verified]
38
47
  output: [approval]
39
48
  gate:
40
49
  file: gates/approval
@@ -184,16 +184,25 @@ Options: `--session-id`, `--no-persona`, `--json`, `--minimal`, `--full`, `--qui
184
184
  | `pf debug deadcode exports` | Unused TypeScript exports | `deadcode/cli.py` |
185
185
  | `pf debug healthscore analyze` | Composite health score | `healthscore/cli.py` |
186
186
 
187
- ## Hooks (non-CLI)
188
-
189
- | File | Hook Type | Purpose |
190
- |------|-----------|---------|
191
- | `hooks.py` | PostToolUse | Main hook dispatcher |
192
- | `bellmode_hook.py` | PostToolUse | Bell mode message injection |
193
- | `pretooluse_hook.py` | PreToolUse | Permission and safety gates |
194
- | `schema_validation_hook.py` | PreToolUse:Write | Schema validation on file writes |
195
- | `welcome_hook.py` | PostToolUse | Welcome message on session start |
196
- | `patch_mode.py` | PostToolUse | Patch mode interrupt handling |
187
+ ## Hooks (`pf hooks`)
188
+
189
+ All hooks are in `hooks/` subpackage, invoked via `pf hooks <name>`.
190
+
191
+ | Command | Hook Type | Purpose |
192
+ |---------|-----------|---------|
193
+ | `pf hooks session-start` | SessionStart | Session setup, checkpoint, WheelHub, welcome |
194
+ | `pf hooks session-stop` | Stop | Save checkpoint for cross-session continuity |
195
+ | `pf hooks reflector-check` | Stop | Enforce CYCLIST reflector markers |
196
+ | `pf hooks pre-edit-check` | PreToolUse | Block edits to protected files |
197
+ | `pf hooks context-warning` | PreToolUse | Warn when context usage is high |
198
+ | `pf hooks context-breaker` | PreToolUse | Block tool execution at critical context |
199
+ | `pf hooks cyclist-pretooluse` | PreToolUse | Route approval through WheelHub |
200
+ | `pf hooks schema-validation` | PreToolUse:Write | Validate session/skill/step schema |
201
+ | `pf hooks bell-mode` | PostToolUse | Bell queue + tandem injection |
202
+ | `pf hooks sprint-yaml` | PostToolUse | Validate sprint YAML (YAML 1.2) |
203
+ | `pf hooks statusline` | statusLine | Render Claude Code status bar |
204
+
205
+ Legacy shims (`bellmode_hook.py`, `pretooluse_hook.py`, etc.) re-export from `hooks/` for backward compat.
197
206
 
198
207
  ## Architecture
199
208