@pennyfarthing/core 11.1.1 → 11.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/README.md +8 -8
  2. package/package.json +2 -1
  3. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor.js +381 -66
  5. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  6. package/packages/core/dist/cli/commands/init.js +4 -4
  7. package/packages/core/dist/cli/commands/init.js.map +1 -1
  8. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  9. package/packages/core/dist/cli/commands/update.js +4 -5
  10. package/packages/core/dist/cli/commands/update.js.map +1 -1
  11. package/packages/core/dist/cli/utils/constants.d.ts +3 -8
  12. package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
  13. package/packages/core/dist/cli/utils/constants.js +3 -4
  14. package/packages/core/dist/cli/utils/constants.js.map +1 -1
  15. package/packages/core/dist/cli/utils/settings.d.ts +11 -0
  16. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  17. package/packages/core/dist/cli/utils/settings.js +65 -29
  18. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  19. package/packages/core/dist/cli/utils/symlinks.js +16 -16
  20. package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
  21. package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
  22. package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
  23. package/packages/core/dist/consultation/tandem-metrics.js +131 -0
  24. package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
  25. package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
  26. package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
  27. package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
  28. package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
  29. package/packages/core/dist/public/js/react/react.js +14 -14
  30. package/packages/core/dist/scripts/benchmark-integration.d.ts +182 -0
  31. package/packages/core/dist/scripts/benchmark-integration.d.ts.map +1 -0
  32. package/packages/core/dist/scripts/benchmark-integration.js +691 -0
  33. package/packages/core/dist/scripts/benchmark-integration.js.map +1 -0
  34. package/packages/core/dist/scripts/job-fair-aggregator.d.ts +150 -0
  35. package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +1 -0
  36. package/packages/core/dist/scripts/job-fair-aggregator.js +547 -0
  37. package/packages/core/dist/scripts/job-fair-aggregator.js.map +1 -0
  38. package/packages/core/dist/server/api/agent-load.js +1 -1
  39. package/packages/core/dist/server/api/agent-load.js.map +1 -1
  40. package/packages/core/dist/server/otlp-receiver.d.ts +16 -11
  41. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  42. package/packages/core/dist/server/otlp-receiver.js +185 -24
  43. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  44. package/packages/core/dist/server/otlp-receiver.test.d.ts +21 -0
  45. package/packages/core/dist/server/otlp-receiver.test.d.ts.map +1 -0
  46. package/packages/core/dist/server/otlp-receiver.test.js +446 -0
  47. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -0
  48. package/packages/core/dist/server/server.d.ts +0 -3
  49. package/packages/core/dist/server/server.d.ts.map +1 -1
  50. package/packages/core/dist/server/server.js +3 -37
  51. package/packages/core/dist/server/server.js.map +1 -1
  52. package/packages/core/dist/server/server.test.d.ts +1 -1
  53. package/packages/core/dist/server/server.test.js +12 -23
  54. package/packages/core/dist/server/server.test.js.map +1 -1
  55. package/packages/core/dist/shared/capabilities.d.ts +88 -0
  56. package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
  57. package/packages/core/dist/shared/capabilities.js +133 -0
  58. package/packages/core/dist/shared/capabilities.js.map +1 -0
  59. package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
  60. package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
  61. package/packages/core/dist/shared/capabilities.test.js +217 -0
  62. package/packages/core/dist/shared/capabilities.test.js.map +1 -0
  63. package/packages/core/dist/shared/portrait-resolver.d.ts +9 -0
  64. package/packages/core/dist/shared/portrait-resolver.d.ts.map +1 -1
  65. package/packages/core/dist/shared/portrait-resolver.js +27 -0
  66. package/packages/core/dist/shared/portrait-resolver.js.map +1 -1
  67. package/packages/core/dist/shared/portrait-resolver.test.js +47 -1
  68. package/packages/core/dist/shared/portrait-resolver.test.js.map +1 -1
  69. package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
  70. package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
  71. package/packages/core/dist/shared/spawn-prompt.js +82 -0
  72. package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
  73. package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
  74. package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
  75. package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
  76. package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
  77. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts +13 -0
  78. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts.map +1 -0
  79. package/packages/core/dist/shared/tandem-portrait-inventory.test.js +126 -0
  80. package/packages/core/dist/shared/tandem-portrait-inventory.test.js.map +1 -0
  81. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
  82. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
  83. package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
  84. package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
  85. package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
  86. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  87. package/packages/core/dist/workflow/workflow-schema.js +120 -0
  88. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  89. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  90. package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
  91. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  92. package/pennyfarthing-dist/agents/dev.md +7 -11
  93. package/pennyfarthing-dist/agents/reviewer.md +9 -3
  94. package/pennyfarthing-dist/agents/sm-finish.md +18 -1
  95. package/pennyfarthing-dist/agents/sm-setup.md +1 -1
  96. package/pennyfarthing-dist/agents/sm.md +2 -2
  97. package/pennyfarthing-dist/agents/tea.md +1 -1
  98. package/pennyfarthing-dist/agents/testing-runner.md +2 -1
  99. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  100. package/pennyfarthing-dist/commands/pf-git.md +4 -2
  101. package/pennyfarthing-dist/commands/pf-standalone.md +7 -2
  102. package/pennyfarthing-dist/gates/approval.md +63 -0
  103. package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
  104. package/pennyfarthing-dist/gates/context-ok.md +56 -0
  105. package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
  106. package/pennyfarthing-dist/gates/quality-pass.md +67 -0
  107. package/pennyfarthing-dist/gates/tests-fail.md +84 -0
  108. package/pennyfarthing-dist/gates/tests-pass.md +79 -0
  109. package/pennyfarthing-dist/guides/agent-behavior.md +23 -19
  110. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +1 -1
  111. package/pennyfarthing-dist/guides/bell-mode.md +1 -1
  112. package/pennyfarthing-dist/guides/bikerack.md +3 -3
  113. package/pennyfarthing-dist/guides/hooks.md +29 -29
  114. package/pennyfarthing-dist/guides/reflector.md +1 -1
  115. package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
  116. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  117. package/pennyfarthing-dist/guides/xml-tags.md +2 -2
  118. package/pennyfarthing-dist/scripts/README.md +1 -1
  119. package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
  120. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +5 -87
  121. package/pennyfarthing-dist/scripts/git/README.md +24 -14
  122. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +5 -266
  123. package/pennyfarthing-dist/scripts/git/git-status-all.sh +5 -151
  124. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +6 -144
  125. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +5 -496
  126. package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
  127. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  128. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
  129. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
  130. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
  131. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
  132. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +9 -11
  133. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +27 -33
  134. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
  135. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
  136. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
  137. package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
  138. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
  139. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
  140. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +4 -93
  141. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  142. package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
  143. package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +76 -0
  144. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +4 -221
  145. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +5 -13
  146. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +4 -123
  147. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +4 -33
  148. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +4 -156
  149. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +4 -131
  150. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +4 -249
  151. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +4 -160
  152. package/pennyfarthing-dist/skills/pf-bc/usage.md +1 -1
  153. package/pennyfarthing-dist/skills/pf-jira/examples.md +5 -2
  154. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -16
  155. package/pennyfarthing-dist/skills/pf-workflow/skill.md +9 -12
  156. package/pennyfarthing-dist/skills/pf-workflow/usage.md +33 -8
  157. package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
  158. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +18 -6
  159. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
  160. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
  161. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
  162. package/pennyfarthing-dist/workflows/review-tandem.yaml +65 -0
  163. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +16 -8
  164. package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
  165. package/pennyfarthing_scripts/CLAUDE.md +45 -14
  166. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  167. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  168. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  169. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  170. package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
  171. package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
  172. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  173. package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
  174. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  179. package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
  180. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  181. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  182. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  183. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  184. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  185. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/bc/__pycache__/__init__.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  188. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  189. package/pennyfarthing_scripts/bc/cli.py +3 -5
  190. package/pennyfarthing_scripts/bellmode_hook.py +12 -296
  191. package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
  192. package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
  193. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  194. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  201. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  202. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  211. package/pennyfarthing_scripts/bikerack/audit_log_panel.py +119 -0
  212. package/pennyfarthing_scripts/bikerack/background_panel.py +86 -5
  213. package/pennyfarthing_scripts/bikerack/base_panel.py +87 -2
  214. package/pennyfarthing_scripts/bikerack/changed_panel.py +125 -29
  215. package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
  216. package/pennyfarthing_scripts/bikerack/debug_panel.py +32 -2
  217. package/pennyfarthing_scripts/bikerack/diffs_panel.py +104 -17
  218. package/pennyfarthing_scripts/bikerack/events.py +28 -0
  219. package/pennyfarthing_scripts/bikerack/git_panel.py +103 -33
  220. package/pennyfarthing_scripts/bikerack/launcher.py +15 -15
  221. package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
  222. package/pennyfarthing_scripts/bikerack/progress_panel.py +315 -0
  223. package/pennyfarthing_scripts/bikerack/sprint_panel.py +395 -32
  224. package/pennyfarthing_scripts/bikerack/story_detail_data.py +244 -0
  225. package/pennyfarthing_scripts/bikerack/story_detail_screen.py +176 -0
  226. package/pennyfarthing_scripts/bikerack/tui.py +575 -37
  227. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  228. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/cli.py +42 -65
  233. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  238. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  239. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  240. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  241. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  242. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  243. package/pennyfarthing_scripts/common/pr_config.py +38 -0
  244. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/consultation/__init__.py +1 -0
  251. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/consultation/cli.py +149 -0
  255. package/pennyfarthing_scripts/consultation/dialogue_manager.py +417 -0
  256. package/pennyfarthing_scripts/context.py +3 -3
  257. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  258. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  259. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  260. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  261. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  262. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  263. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  264. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  266. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  267. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  268. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  269. package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/git/__init__.py +12 -1
  272. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/git/create_branches.py +3 -4
  276. package/pennyfarthing_scripts/git/hooks_installer.py +152 -0
  277. package/pennyfarthing_scripts/git/repos.py +196 -0
  278. package/pennyfarthing_scripts/git/status_all.py +27 -11
  279. package/pennyfarthing_scripts/git/worktree.py +302 -0
  280. package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/git_group/cli.py +143 -40
  283. package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
  284. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  285. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  289. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/handoff/cli.py +33 -1
  291. package/pennyfarthing_scripts/handoff/complete_phase.py +40 -0
  292. package/pennyfarthing_scripts/handoff/marker.py +15 -15
  293. package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
  294. package/pennyfarthing_scripts/handoff/resolve_gate.py +18 -15
  295. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  296. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  297. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/hooks/__init__.py +437 -0
  302. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  303. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  304. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  305. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  306. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  307. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  308. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  309. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  311. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  312. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  313. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  314. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  315. package/pennyfarthing_scripts/hooks/bell_mode.py +215 -0
  316. package/pennyfarthing_scripts/hooks/cli.py +96 -0
  317. package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
  318. package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
  319. package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
  320. package/pennyfarthing_scripts/hooks/pre_edit_check.py +78 -0
  321. package/pennyfarthing_scripts/hooks/reflector_check.py +271 -0
  322. package/pennyfarthing_scripts/hooks/schema_validation.py +203 -0
  323. package/pennyfarthing_scripts/hooks/session_start.py +296 -0
  324. package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
  325. package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
  326. package/pennyfarthing_scripts/hooks/statusline.py +420 -0
  327. package/pennyfarthing_scripts/hooks.py +27 -446
  328. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  329. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  332. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  333. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  334. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  335. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  336. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  337. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  338. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  339. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  340. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  341. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  342. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  343. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  344. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  345. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  346. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  347. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  348. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  349. package/pennyfarthing_scripts/launch/__pycache__/__init__.cpython-314.pyc +0 -0
  350. package/pennyfarthing_scripts/launch/__pycache__/cli.cpython-314.pyc +0 -0
  351. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  352. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  355. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  356. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  357. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  358. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  359. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  360. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  361. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  362. package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
  363. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  364. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  365. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  366. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  367. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  368. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  369. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  370. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  371. package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
  372. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  373. package/pennyfarthing_scripts/prime/heatmap.py +655 -0
  374. package/pennyfarthing_scripts/prime/workflow.py +2 -1
  375. package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
  376. package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
  377. package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
  378. package/pennyfarthing_scripts/session_start_hook.py +4 -186
  379. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  380. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  381. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  382. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  383. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  384. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  385. package/pennyfarthing_scripts/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
  386. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  387. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  388. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  389. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  390. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  391. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  392. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  393. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  394. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  395. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  396. package/pennyfarthing_scripts/sprint/loader.py +15 -1
  397. package/pennyfarthing_scripts/sprint/story_update.py +19 -0
  398. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  399. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  400. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  401. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  402. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  403. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  404. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  405. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  406. package/pennyfarthing_scripts/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
  407. package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
  408. package/pennyfarthing_scripts/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
  409. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  410. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  411. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  412. package/pennyfarthing_scripts/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
  413. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  414. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  415. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
  416. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
  417. package/pennyfarthing_scripts/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
  418. package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
  419. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  420. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  421. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
  422. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  423. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  424. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  425. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  426. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  427. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  428. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
  429. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  430. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  431. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  432. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  433. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  434. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  435. package/pennyfarthing_scripts/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
  436. package/pennyfarthing_scripts/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
  437. package/pennyfarthing_scripts/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
  438. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  439. package/pennyfarthing_scripts/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
  440. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  441. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  442. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  443. package/pennyfarthing_scripts/tests/test_bikerack.py +51 -51
  444. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +811 -0
  445. package/pennyfarthing_scripts/tests/test_handoff_cli.py +16 -11
  446. package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
  447. package/pennyfarthing_scripts/tests/test_workflow_check.py +2 -3
  448. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  449. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  450. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  451. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  452. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  453. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  454. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  455. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  456. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  457. package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
  458. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  459. package/pennyfarthing_scripts/validate/adapters/tandem_awareness.py +254 -0
  460. package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
  461. package/pennyfarthing_scripts/validate/cli.py +17 -5
  462. package/pennyfarthing_scripts/welcome_hook.py +3 -149
  463. package/pennyfarthing_scripts/workflow/__init__.py +40 -0
  464. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  465. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  466. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  467. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  468. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  469. package/pennyfarthing_scripts/workflow/cli.py +1100 -0
  470. package/pennyfarthing_scripts/workflow/helpers.py +241 -0
  471. package/pennyfarthing_scripts/{workflow.py → workflow/scale.py} +0 -104
  472. package/pennyfarthing_scripts/workflow/state.py +112 -0
  473. package/pennyfarthing_scripts/workflow/team_lifecycle.py +257 -0
  474. package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
  475. package/packages/core/dist/scripts/theme-detail.test.js +0 -199
  476. package/pennyfarthing-dist/skills/pf-workflow/scripts/list-workflows.sh +0 -91
  477. package/pennyfarthing-dist/skills/pf-workflow/scripts/resume-workflow.sh +0 -163
  478. package/pennyfarthing-dist/skills/pf-workflow/scripts/show-workflow.sh +0 -138
  479. package/pennyfarthing-dist/skills/pf-workflow/scripts/start-workflow.sh +0 -273
  480. package/pennyfarthing-dist/skills/pf-workflow/scripts/workflow-status.sh +0 -167
  481. package/pennyfarthing_scripts/gate/__pycache__/__init__.cpython-314.pyc +0 -0
  482. package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
  483. package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
  484. package/pennyfarthing_scripts/tests/__pycache__/test_108_2_remove_handoff_fallback.cpython-314-pytest-9.0.2.pyc +0 -0
  485. package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
  486. package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
  487. package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
@@ -1,33 +1,4 @@
1
1
  #!/usr/bin/env bash
2
- #
3
- # Session Start Hook - Shell wrapper for Python implementation
4
- #
5
- # Initializes environment for Claude Code session:
6
- # - Session directory setup and logging
7
- # - Checkpoint validation (cross-session drift)
8
- # - WheelHub auto-start
9
- # - OTEL auto-configuration
10
- #
11
- # Input (stdin): JSON with session_id, source, cwd, etc.
12
- # Output: Writes to CLAUDE_ENV_FILE
13
-
14
- set -euo pipefail
15
-
16
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
17
- source "$SCRIPT_DIR/../lib/find-root.sh"
18
-
19
- # Set PYTHONPATH for pennyfarthing_scripts
20
- PENNYFARTHING_SCRIPTS=""
21
- if [[ -d "$PROJECT_ROOT/pennyfarthing" ]]; then
22
- # Dogfooding: framework inlined in orchestrator
23
- PENNYFARTHING_SCRIPTS="$PROJECT_ROOT/pennyfarthing"
24
- elif [[ -d "$PROJECT_ROOT/node_modules/@pennyfarthing/core" ]]; then
25
- # Normal install
26
- PENNYFARTHING_SCRIPTS="$PROJECT_ROOT/node_modules/@pennyfarthing/core"
27
- fi
28
-
29
- if [[ -n "$PENNYFARTHING_SCRIPTS" ]]; then
30
- export PYTHONPATH="$PENNYFARTHING_SCRIPTS:${PYTHONPATH:-}"
31
- fi
32
-
33
- python3 -m pennyfarthing_scripts.session_start_hook
2
+ # DEPRECATED: This script is a shim. Logic has moved to Python.
3
+ # Use: pf hooks session-start
4
+ exec pf hooks session-start
@@ -1,65 +1,4 @@
1
- #!/usr/bin/env zsh
2
- # Session stop hook: Save checkpoint for cross-session continuity
3
- # Called by Claude Code when a session ends
4
- #
5
- # Writes session state to checkpoint:
6
- # - Active agent (from .session/agents/)
7
- # - Current story (from .session/*-session.md)
8
- # - Workflow phase (from session file)
9
- # - Git SHA (current HEAD)
10
- # - Session ID
11
- #
12
- # Next session can validate this against current git state.
13
-
14
- set -euo pipefail
15
-
16
- # Load shared functions
17
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
18
-
19
- # Determine project root (directory containing .claude)
20
- PROJECT_ROOT="$SCRIPT_DIR"
21
- while [[ ! -d "$PROJECT_ROOT/.pennyfarthing" ]] && [[ "$PROJECT_ROOT" != "/" ]]; do
22
- PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
23
- done
24
-
25
- source "$SCRIPT_DIR/../lib/checkpoint.sh"
26
-
27
- # Read input from stdin (contains session_id, source, etc.)
28
- input=$(cat)
29
- session_id=$(echo "$input" | jq -r '.session_id // "unknown"')
30
-
31
- # Get current agent for this session
32
- agent=""
33
- agent_file="$PROJECT_ROOT/.session/agents/$session_id"
34
- if [[ -f "$agent_file" ]]; then
35
- agent=$(cat "$agent_file")
36
- fi
37
-
38
- # Find active story from session files
39
- story=""
40
- phase=""
41
- session_file=$(find "$PROJECT_ROOT/.session" -maxdepth 1 -name "*-session.md" -type f 2>/dev/null | head -1)
42
- if [[ -n "$session_file" && -f "$session_file" ]]; then
43
- # Extract story ID from filename (e.g., 8-3-session.md -> 8-3)
44
- story=$(basename "$session_file" | sed 's/-session\.md$//')
45
-
46
- # Extract phase from session file (look for "Phase:" line)
47
- phase=$(grep -i "^- Phase:" "$session_file" 2>/dev/null | head -1 | sed 's/.*Phase:[[:space:]]*//' | cut -d' ' -f1 || echo "")
48
- fi
49
-
50
- # Get current git SHA
51
- git_sha=""
52
- if command -v git &>/dev/null && git rev-parse --git-dir &>/dev/null; then
53
- git_sha=$(git rev-parse --short HEAD 2>/dev/null || echo "")
54
- fi
55
-
56
- # Build checkpoint data (semicolon-separated key=value pairs)
57
- checkpoint_data="agent=${agent};story=${story};phase=${phase};sha=${git_sha};session=${session_id}"
58
-
59
- # Save checkpoint
60
- checkpoint_save "session_state" "$checkpoint_data"
61
-
62
- # Log session end
63
- echo "$(date -Iseconds) | Session end: $session_id (agent=$agent, story=$story)" >> "$PROJECT_ROOT/.session/session-log.txt"
64
-
65
- exit 0
1
+ #!/usr/bin/env bash
2
+ # DEPRECATED: This script is a shim. Logic has moved to Python.
3
+ # Use: pf hooks session-stop
4
+ exec pf hooks session-stop
@@ -1,78 +1,4 @@
1
- #!/bin/bash
2
- #
3
- # Sprint YAML Validation Hook (PostToolUse)
4
- #
5
- # Validates sprint YAML files after Edit/Write operations to ensure
6
- # compatibility with the yaml npm package used by Cyclist's SprintPanel.
7
- #
8
- # The yaml npm package follows YAML 1.2 strictly and rejects:
9
- # - Single-quoted strings with blank lines
10
- # - Invalid multiline string formats
11
- #
12
- # When validation fails, returns additionalContext with an error message
13
- # prompting the agent to fix the YAML format.
14
- #
15
- # Input: JSON via stdin with tool_name, tool_input
16
- # Output: JSON with additionalContext on validation failure
17
- #
18
- # See also: pf sprint validate
19
-
20
- set -euo pipefail
21
-
22
- # Read hook input from stdin
23
- INPUT=$(cat)
24
-
25
- # Extract tool name and file path from input
26
- TOOL_NAME=$(echo "$INPUT" | grep -o '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"tool_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || echo "")
27
- FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || echo "")
28
-
29
- # Only process Edit and Write operations on sprint YAML files
30
- if [[ "$TOOL_NAME" != "Edit" && "$TOOL_NAME" != "Write" ]]; then
31
- exit 0
32
- fi
33
-
34
- # Check if it's a sprint YAML file
35
- if [[ ! "$FILE_PATH" =~ sprint/.*\.(yaml|yml)$ ]]; then
36
- exit 0
37
- fi
38
-
39
- # Check if the file exists
40
- if [[ ! -f "$FILE_PATH" ]]; then
41
- exit 0
42
- fi
43
-
44
- # Validate using Node.js yaml package (same parser Cyclist uses)
45
- VALIDATION_ERROR=$(node --input-type=module -e "
46
- import { parse } from 'yaml';
47
- import { readFileSync } from 'fs';
48
-
49
- try {
50
- const content = readFileSync('$FILE_PATH', 'utf-8');
51
- parse(content);
52
- process.exit(0);
53
- } catch (e) {
54
- console.error(e.message);
55
- process.exit(1);
56
- }
57
- " 2>&1) && VALID=true || VALID=false
58
-
59
- if [[ "$VALID" == "true" ]]; then
60
- # Valid YAML - exit silently
61
- exit 0
62
- fi
63
-
64
- # Validation failed - return error context to agent
65
- # Escape special characters for JSON
66
- ESCAPED_ERROR=$(echo "$VALIDATION_ERROR" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | tr '\n' ' ')
67
- ESCAPED_PATH=$(echo "$FILE_PATH" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
68
-
69
- cat << EOF
70
- {
71
- "hookSpecificOutput": {
72
- "hookEventName": "PostToolUse",
73
- "additionalContext": "⚠️ SPRINT YAML VALIDATION FAILED\n\nFile: $ESCAPED_PATH\nError: $ESCAPED_ERROR\n\nThe sprint YAML file has invalid syntax that will break the Cyclist SprintPanel.\n\nCommon fix: Single-quoted strings cannot contain blank lines in YAML 1.2.\nUse literal block scalars (|) for multiline strings instead.\n\nTo auto-fix, run: yq eval -o=json '$ESCAPED_PATH' > /tmp/sprint.json && yq eval -P /tmp/sprint.json > '$ESCAPED_PATH'"
74
- }
75
- }
76
- EOF
77
-
78
- exit 0
1
+ #!/usr/bin/env bash
2
+ # DEPRECATED: This script is a shim. Logic has moved to Python.
3
+ # Use: pf hooks sprint-yaml
4
+ exec pf hooks sprint-yaml
@@ -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/.cyclist-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
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env zsh
2
+ #
3
+ # generate-tandem-portraits.sh — Generate per-theme tandem cyclist branding images
4
+ #
5
+ # Processes cyclist_tandem.png source into medium (200x200) and large (300x300)
6
+ # versions for each theme's portrait directory.
7
+ #
8
+ # Usage: ./generate-tandem-portraits.sh [--source PATH] [--portraits-dir PATH]
9
+
10
+ set -euo pipefail
11
+
12
+ SCRIPT_DIR="${0:A:h}"
13
+ # Source image lives alongside portraits in pennyfarthing-dist
14
+ DIST_DIR="${SCRIPT_DIR}/../.."
15
+ SOURCE_IMAGE="${DIST_DIR}/personas/portraits/cyclist-tandem-source.png"
16
+ PORTRAITS_DIR=""
17
+
18
+ # Parse arguments
19
+ while [[ $# -gt 0 ]]; do
20
+ case "$1" in
21
+ --source) SOURCE_IMAGE="$2"; shift 2 ;;
22
+ --portraits-dir) PORTRAITS_DIR="$2"; shift 2 ;;
23
+ *) echo "Unknown option: $1"; exit 1 ;;
24
+ esac
25
+ done
26
+
27
+ # Auto-detect portraits directory if not provided
28
+ if [[ -z "$PORTRAITS_DIR" ]]; then
29
+ PORTRAITS_DIR="${DIST_DIR}/personas/portraits"
30
+ fi
31
+
32
+ # Resolve to absolute path
33
+ PORTRAITS_DIR="${PORTRAITS_DIR:A}"
34
+
35
+ if [[ ! -f "$SOURCE_IMAGE" ]]; then
36
+ echo "Error: Source image not found: $SOURCE_IMAGE"
37
+ exit 1
38
+ fi
39
+
40
+ if [[ ! -d "$PORTRAITS_DIR" ]]; then
41
+ echo "Error: Portraits directory not found: $PORTRAITS_DIR"
42
+ exit 1
43
+ fi
44
+
45
+ # Verify ImageMagick is available
46
+ if ! command -v magick &>/dev/null; then
47
+ echo "Error: ImageMagick (magick) not found in PATH"
48
+ exit 1
49
+ fi
50
+
51
+ echo "Source: $SOURCE_IMAGE"
52
+ echo "Portraits: $PORTRAITS_DIR"
53
+ echo ""
54
+
55
+ generated=0
56
+ skipped=0
57
+
58
+ for theme_dir in "$PORTRAITS_DIR"/*/; do
59
+ theme_name="$(basename "$theme_dir")"
60
+
61
+ for size_name size_px in medium 200 large 300; do
62
+ size_dir="${theme_dir}${size_name}"
63
+ output="${size_dir}/cyclist-tandem.png"
64
+
65
+ # Create size directory if it doesn't exist
66
+ mkdir -p "$size_dir"
67
+
68
+ # Generate resized tandem portrait
69
+ magick "$SOURCE_IMAGE" -resize "${size_px}x${size_px}" -strip "$output"
70
+ generated=$((generated + 1))
71
+ done
72
+ done
73
+
74
+ echo ""
75
+ echo "Generated: $generated tandem portraits"
76
+ echo "Done."